diff --git a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt index 2864be4..444b06b 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt @@ -60,7 +60,7 @@ class Chunkmaster: JavaPlugin() { private fun configure() { dataFolder.mkdir() config.addDefault("generation.period", 2L) - config.addDefault("generation.chunks-per-step", 4) + config.addDefault("generation.chunks-per-step", 2) config.addDefault("generation.chunk-skips-per-step", 100) config.addDefault("generation.mspt-pause-threshold", 500L) config.addDefault("generation.pause-on-join", true) diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt index b9a5431..75c4ec9 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt @@ -37,6 +37,7 @@ class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { if (args.isNotEmpty()) { if (args[0].toIntOrNull() != null) { stopAfter = args[0].toInt() + worldName = sender.world.name } else { worldName = args[0] } @@ -58,6 +59,13 @@ class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { return false } } + return createTask(sender, worldName, stopAfter) + } + + /** + * Creates the task with the given arguments. + */ + private fun createTask(sender: CommandSender, worldName: String, stopAfter: Int): Boolean { val world = chunkmaster.server.getWorld(worldName) val allTasks = chunkmaster.generationManager.allTasks return if (world != null && (allTasks.find { it.generationTask.world == world }) == null) { diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdTpChunk.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdTpChunk.kt new file mode 100644 index 0000000..89253bd --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdTpChunk.kt @@ -0,0 +1,52 @@ +package net.trivernis.chunkmaster.commands + +import io.papermc.lib.PaperLib +import net.md_5.bungee.api.ChatColor +import net.md_5.bungee.api.chat.ComponentBuilder +import net.trivernis.chunkmaster.lib.Subcommand +import org.bukkit.Material +import org.bukkit.command.Command +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class CmdTpChunk: Subcommand { + override val name = "tpchunk" + + override fun onTabComplete( + sender: CommandSender, + command: Command, + alias: String, + args: List + ): MutableList { + return emptyList().toMutableList() + } + + /** + * Teleports the player to a save location in the chunk + */ + override fun execute(sender: CommandSender, args: List): Boolean { + if (sender is Player) { + if (args.size == 2 && args[0].toIntOrNull() != null && args[1].toIntOrNull() != null) { + val location = sender.world.getChunkAt(args[0].toInt(), args[1].toInt()).getBlock(8, 60, 8).location + + while (location.block.blockData.material != Material.AIR) { + location.y++ + } + if (PaperLib.isPaper()) { + PaperLib.teleportAsync(sender, location) + } else { + sender.teleport(location) + } + sender.spigot().sendMessage(*ComponentBuilder("You have been teleportet to chunk") + .color(ChatColor.YELLOW).append("${args[0]}, ${args[1]}").color(ChatColor.BLUE).create()) + return true + } else { + return false + } + } else { + sender.spigot().sendMessage(*ComponentBuilder("This command can only be executed by a player!") + .color(ChatColor.RED).create()) + return false + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CommandChunkmaster.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CommandChunkmaster.kt index 69b4de5..50bd98e 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CommandChunkmaster.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CommandChunkmaster.kt @@ -83,5 +83,8 @@ class CommandChunkmaster(private val chunkmaster: Chunkmaster, private val serve val cmdReload = CmdReload(chunkmaster) commands[cmdReload.name] = cmdReload + + val cmdTpChunk = CmdTpChunk() + commands[cmdTpChunk.name] = cmdTpChunk } } \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/SqlUpdateManager.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/SqlUpdateManager.kt index 5da91d6..ad18e03 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/SqlUpdateManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/SqlUpdateManager.kt @@ -15,8 +15,7 @@ class SqlUpdateManager(private val connnection: Connection, private val chunkmas Pair("last_x", "integer NOT NULL DEFAULT 0"), Pair("last_z", "integer NOT NULL DEFAULT 0"), Pair("world", "text UNIQUE NOT NULL DEFAULT 'world'"), - Pair("stop_after", "integer DEFAULT -1"), - Pair("autostart", "integer DEFAULT 1") + Pair("stop_after", "integer DEFAULT -1") ) ) ) diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt index 7498692..e820b2f 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -31,10 +31,12 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val centerChunk = world.getChunkAt(world.spawnLocation) val generationTask = createGenerationTask(world, centerChunk, centerChunk, stopAfter) - val insertStatement = chunkmaster.sqliteConnection.prepareStatement(""" + val insertStatement = chunkmaster.sqliteConnection.prepareStatement( + """ INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, stop_after) values (?, ?, ?, ?, ?, ?) - """) + """ + ) insertStatement.setInt(1, centerChunk.x) insertStatement.setInt(2, centerChunk.z) insertStatement.setInt(3, centerChunk.x) @@ -43,9 +45,11 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server insertStatement.setInt(6, stopAfter) insertStatement.execute() - val getIdStatement = chunkmaster.sqliteConnection.prepareStatement(""" + val getIdStatement = chunkmaster.sqliteConnection.prepareStatement( + """ SELECT id FROM generation_tasks ORDER BY id DESC LIMIT 1 - """.trimIndent()) + """.trimIndent() + ) getIdStatement.execute() val result = getIdStatement.resultSet result.next() @@ -60,8 +64,10 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server } if (!paused) { - val task = server.scheduler.runTaskTimer(chunkmaster, generationTask, 10, - chunkmaster.config.getLong("generation.period")) + val task = server.scheduler.runTaskTimer( + chunkmaster, generationTask, 200, // 10 sec delay + chunkmaster.config.getLong("generation.period") + ) tasks.add(RunningTaskEntry(id, task, generationTask)) } else { pausedTasks.add(PausedTaskEntry(id, generationTask)) @@ -80,8 +86,10 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server if (!paused) { chunkmaster.logger.info("Resuming chunk generation task for world \"${world.name}\"") val generationTask = createGenerationTask(world, center, last, stopAfter) - val task = server.scheduler.runTaskTimer(chunkmaster, generationTask, 10, - chunkmaster.config.getLong("generation.period")) + val task = server.scheduler.runTaskTimer( + chunkmaster, generationTask, 200, // 10 sec delay + chunkmaster.config.getLong("generation.period") + ) tasks.add(RunningTaskEntry(id, task, generationTask)) generationTask.onEndReached { server.consoleSender.sendMessage("Task #${id} finished after ${generationTask.count} chunks.") @@ -95,15 +103,17 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server */ fun removeTask(id: Int): Boolean { val taskEntry: TaskEntry? = if (this.paused) { - this.pausedTasks.find {it.id == id} + this.pausedTasks.find { it.id == id } } else { - this.tasks.find {it.id == id} + this.tasks.find { it.id == id } } if (taskEntry != null) { taskEntry.cancel() - val deleteTask = chunkmaster.sqliteConnection.prepareStatement(""" + val deleteTask = chunkmaster.sqliteConnection.prepareStatement( + """ DELETE FROM generation_tasks WHERE id = ?; - """.trimIndent()) + """.trimIndent() + ) deleteTask.setInt(1, taskEntry.id) deleteTask.execute() deleteTask.close() @@ -162,15 +172,13 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val res = savedTasksStatement.resultSet while (res.next()) { try { - if (res.getBoolean("autostart")) { - val id = res.getInt("id") - val world = server.getWorld(res.getString("world")) - val center = world!!.getChunkAt(res.getInt("center_x"), res.getInt("center_z")) - val last = world.getChunkAt(res.getInt("last_x"), res.getInt("last_z")) - val stopAfter = res.getInt("stop_after") - if (this.tasks.find {it.id == id} == null) { - resumeTask(world, center, last, id, stopAfter) - } + val id = res.getInt("id") + val world = server.getWorld(res.getString("world")) + val center = world!!.getChunkAt(res.getInt("center_x"), res.getInt("center_z")) + val last = world.getChunkAt(res.getInt("last_x"), res.getInt("last_z")) + val stopAfter = res.getInt("stop_after") + if (this.tasks.find { it.id == id } == null) { + resumeTask(world, center, last, id, stopAfter) } } catch (error: NullPointerException) { server.consoleSender.sendMessage("Failed to load Task ${res.getInt("id")}.") @@ -209,15 +217,19 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server for (task in tasks) { try { val genTask = task.generationTask - server.consoleSender.sendMessage("""Task #${task.id} running for "${genTask.world.name}". + server.consoleSender.sendMessage( + """Task #${task.id} running for "${genTask.world.name}". |Progress ${task.generationTask.count} chunks - |${if (task.generationTask.stopAfter > 0)"(${(task.generationTask.count.toDouble()/ - task.generationTask.stopAfter.toDouble())*100}%)" else ""}. - |Last Chunk: ${genTask.lastChunk.x}, ${genTask.lastChunk.z}""".trimMargin("|").replace('\n', ' ')) - val updateStatement = chunkmaster.sqliteConnection.prepareStatement(""" + |${if (task.generationTask.stopAfter > 0) "(${(task.generationTask.count.toDouble() / + task.generationTask.stopAfter.toDouble()) * 100}%)" else ""}. + |Last Chunk: ${genTask.lastChunk.x}, ${genTask.lastChunk.z}""".trimMargin("|").replace('\n', ' ') + ) + val updateStatement = chunkmaster.sqliteConnection.prepareStatement( + """ UPDATE generation_tasks SET last_x = ?, last_z = ? WHERE id = ? - """.trimIndent()) + """.trimIndent() + ) updateStatement.setInt(1, genTask.lastChunk.x) updateStatement.setInt(2, genTask.lastChunk.z) updateStatement.setInt(3, task.id) @@ -236,7 +248,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server private fun createGenerationTask(world: World, center: Chunk, start: Chunk, stopAfter: Int): GenerationTask { return if (PaperLib.isPaper()) { GenerationTaskPaper(chunkmaster, world, center, start, stopAfter) - } else { + } else { GenerationTaskSpigot(chunkmaster, world, center, start, stopAfter) } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 5feec3a..7ee3e97 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -9,7 +9,14 @@ commands: chunkmaster: description: Main command permission: chunkmaster.chunkmaster - usage: /chunkmaster + usage: | + / generate [, ] - generates chunks starting from the spawn until the chunk-count is reached + / cancel - cancels the generation task with the task-id + / list - lists all running and paused generation tasks + / pause - pauses all generation tasks + / resume - resumes all generation tasks + / reload - reloads the configuration and restarts all tasks + / tpchunk - teleports you to the chunk with the given chunk coordinates aliases: - chm - chunkm @@ -33,6 +40,9 @@ permissions: chunkmaster.reload: description: Allows the reload subcommand. default: op + chunkmaster.tpchunk: + description: Allows the tpchunk subcommand. + default: op chunkmaster.chunkmaster: description: Allows Chunkmaster commands. default: op