diff --git a/README.md b/README.md index 9f59125..a85f519 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,24 @@ All features can be accessed with the command `/chunkmaster` or the aliases `/ch ```yaml generation: + # The maximum amount of chunks that are loaded before unloading and saving them. + # Higher values mean higher generation speed but greater memory usage. + # The value should be a positive integer. + max-loaded-chunks: 10 + + # Paper Only + # The maximum amount of requested chunks with the asynchronous paper chunk + # loading method. Higher values mean faster generation but more memory usage + # (and probably bigger performance impact). + # The value should be a positive integer. + max-pending-chunks: 10 + # The period (in ticks) in which a generation step is run. # Higher values mean less performance impact but slower generation. # The value should be a positive integer. period: 2 + # Paper Only # The number of already generated chunks that will be skipped for each step. # Notice that these still have a performance impact because the server needs to check # if the chunk is generated. @@ -47,4 +60,10 @@ generation: # process is minimal. # The value should be a boolean pause-on-join: true -``` \ No newline at end of file +``` + +## Spigot and Paper + +The plugin works on spigot and paper servers but is significantly faster on paper servers +(because it profits from asynchronous chunk loading an the better implementation of the +isChunkGenerated method). \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt index c26c4e0..117bb10 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt @@ -56,9 +56,11 @@ class Chunkmaster: JavaPlugin() { private fun configure() { dataFolder.mkdir() config.addDefault("generation.period", 2L) - config.addDefault("generation.chunks-skips-per-step", 4) + config.addDefault("generation.chunks-skips-per-step", 10) config.addDefault("generation.mspt-pause-threshold", 500L) config.addDefault("generation.pause-on-join", true) + config.addDefault("generation.max-pending-chunks", 10) + config.addDefault("generation.max-loaded-chunks", 10) config.options().copyDefaults(true) saveConfig() } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/ChunkCoordinates.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/ChunkCoordinates.kt index 6c4627f..e9a7fc4 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/ChunkCoordinates.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/ChunkCoordinates.kt @@ -1,4 +1,10 @@ package net.trivernis.chunkmaster.lib.generation -data class ChunkCoordinates(val x: Int, val z: Int) { +import org.bukkit.Location +import org.bukkit.World + +class ChunkCoordinates(val x: Int, val z: Int) { + fun getCenterLocation(world: World): Location { + return Location(world, ((x*16) + 8).toDouble(), 1.0, ((x*16) + 8).toDouble()) + } } \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt index 697abd9..e8c1233 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -13,14 +13,15 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: Chunk, startChun abstract val stopAfter: Int abstract val world: World abstract val count: Int - abstract val lastChunk: Chunk abstract val endReached: Boolean protected val spiral: Spiral = Spiral(Pair(centerChunk.x, centerChunk.z), Pair(startChunk.x, startChunk.z)) protected val loadedChunks: HashSet = HashSet() + protected var lastChunkCoords = ChunkCoordinates(startChunk.x, startChunk.z) protected val chunkSkips = plugin.config.getInt("generation.chunks-skips-per-step") protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold") + protected val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks") abstract override fun run() abstract fun cancel() @@ -30,13 +31,21 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: Chunk, startChun val nextChunkCoords = spiral.next() return ChunkCoordinates(nextChunkCoords.first, nextChunkCoords.second) } + var lastChunk: Chunk = startChunk + get() { + return world.getChunkAt(lastChunkCoords.x, lastChunkCoords.z) + } + private set val nextChunk: Chunk get() { val next = nextChunkCoordinates return world.getChunkAt(next.x, next.z) } + /** + * Checks if the World border or the maximum chunk setting for the task is reached. + */ protected fun borderReached(): Boolean { - return !world.worldBorder.isInside(lastChunk.getBlock(8, 0, 8).location) || (stopAfter in 1..count) + return !world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) || (stopAfter in 1..count) } } \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt index 67b419c..756d085 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -12,20 +12,15 @@ class GenerationTaskPaper( override val stopAfter: Int = -1 ) : GenerationTask(plugin, centerChunk, startChunk) { + private val maxPendingChunks = plugin.config.getInt("generation.max-pending-chunks") + private val pendingChunks = HashSet>() override var count = 0 private set - override var lastChunk: Chunk = startChunk - get() { - return world.getChunkAt(lastChunkCoords.x, lastChunkCoords.z) - } - private set override var endReached: Boolean = false private set - private var lastChunkCoords = ChunkCoordinates(startChunk.x, startChunk.z) - /** * Runs the generation task. Every Iteration the next chunk will be generated if * it hasn't been generated already. @@ -33,13 +28,14 @@ class GenerationTaskPaper( */ override fun run() { if (plugin.mspt < msptThreshold) { // pause when tps < 2 - if (loadedChunks.size > 10) { + if (loadedChunks.size > maxLoadedChunks) { for (chunk in loadedChunks) { if (chunk.isLoaded) { chunk.unload(true) } } - } else if (pendingChunks.size < 10) { // if more than 10 chunks are pending, wait. + loadedChunks.clear() + } else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait. if (borderReached()) { endReached = true return diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt index 0032a51..f54f666 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -13,8 +13,6 @@ class GenerationTaskSpigot( override var count = 0 private set - override var lastChunk: Chunk = startChunk - private set override var endReached: Boolean = false private set @@ -25,33 +23,27 @@ class GenerationTaskSpigot( */ override fun run() { if (plugin.mspt < msptThreshold) { // pause when tps < 2 - if (loadedChunks.size > 10) { + if (loadedChunks.size > maxLoadedChunks) { for (chunk in loadedChunks) { if (chunk.isLoaded) { chunk.unload(true) } } + loadedChunks.clear() } else { if (borderReached()) { endReached = true return } - var chunk = nextChunk - - for (i in 1 until chunkSkips) { - if (world.isChunkGenerated(chunk.x, chunk.z)) { - chunk = nextChunk - } else { - break - } - } + val chunk = nextChunkCoordinates if (!world.isChunkGenerated(chunk.x, chunk.z)) { - chunk.load(true) - loadedChunks.add(chunk) + val chunkInstance = world.getChunkAt(chunk.x, chunk.z) + chunkInstance.load(true) + loadedChunks.add(chunkInstance) } - lastChunk = chunk + lastChunkCoords = chunk count = spiral.count // set the count to the more accurate spiral count } }