From 5d0f1584276bde975ebc6178dfbdc313fb268982 Mon Sep 17 00:00:00 2001 From: Trivernis Date: Wed, 18 Sep 2019 16:17:05 +0200 Subject: [PATCH] Changes to task cancelation and fix - fixed generate command error on multiple tasks for one world - changed check of task completion from polling to interrupt (via callback function) --- .../chunkmaster/commands/CmdCancel.kt | 4 +- .../chunkmaster/commands/CmdGenerate.kt | 8 +- .../lib/generation/GenerationManager.kt | 76 +++++++++++-------- .../lib/generation/GenerationTask.kt | 10 +++ .../lib/generation/GenerationTaskPaper.kt | 1 + .../lib/generation/GenerationTaskSpigot.kt | 1 + 6 files changed, 65 insertions(+), 35 deletions(-) diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdCancel.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdCancel.kt index f0e16b0..052ee60 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdCancel.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdCancel.kt @@ -21,9 +21,7 @@ class CmdCancel(private val chunkmaster: Chunkmaster): Subcommand { args: List ): MutableList { val genManager = chunkmaster.generationManager - val allTasks = HashSet() - allTasks.addAll(genManager.pausedTasks) - allTasks.addAll(genManager.tasks) + val allTasks = genManager.allTasks return allTasks.filter {it.id.toString().indexOf(args[0]) == 0} .map { it.id.toString() }.toMutableList() } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt index 8a7f588..b9a5431 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt @@ -59,17 +59,21 @@ class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { } } val world = chunkmaster.server.getWorld(worldName) - return if (world != null) { + val allTasks = chunkmaster.generationManager.allTasks + return if (world != null && (allTasks.find { it.generationTask.world == world }) == null) { chunkmaster.generationManager.addTask(world, stopAfter) sender.spigot().sendMessage(*ComponentBuilder("Generation task for world ").color(ChatColor.BLUE) .append(worldName).color(ChatColor.GREEN).append(" until ").color(ChatColor.BLUE) .append(if (stopAfter > 0) "$stopAfter chunks" else "WorldBorder").color(ChatColor.GREEN) .append(" successfully created").color(ChatColor.BLUE).create()) true - } else { + } else if (world == null){ sender.spigot().sendMessage(*ComponentBuilder("World ").color(ChatColor.RED) .append(worldName).color(ChatColor.GREEN).append(" not found!").color(ChatColor.RED).create()) false + } else { + sender.spigot().sendMessage(*ComponentBuilder("Task already exists!").color(ChatColor.RED).create()) + return false } } } \ No newline at end of file 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 d225022..a7d01d4 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -12,6 +12,13 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val tasks: HashSet = HashSet() val pausedTasks: HashSet = HashSet() + val allTasks: HashSet + get() { + val all = HashSet() + all.addAll(pausedTasks) + all.addAll(tasks) + return all + } var paused = false private set @@ -19,41 +26,51 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server * Adds a generation task */ fun addTask(world: World, stopAfter: Int = -1): Int { - val centerChunk = world.getChunkAt(world.spawnLocation) - val generationTask = createGenerationTask(world, centerChunk, centerChunk, stopAfter) + val foundTask = allTasks.find { it.generationTask.world == world } + if (foundTask == null) { + 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) - insertStatement.setInt(4, centerChunk.z) - insertStatement.setString(5, world.name) - insertStatement.setInt(6, stopAfter) - insertStatement.execute() - - val getIdStatement = chunkmaster.sqliteConnection.prepareStatement(""" + insertStatement.setInt(1, centerChunk.x) + insertStatement.setInt(2, centerChunk.z) + insertStatement.setInt(3, centerChunk.x) + insertStatement.setInt(4, centerChunk.z) + insertStatement.setString(5, world.name) + insertStatement.setInt(6, stopAfter) + insertStatement.execute() + + val getIdStatement = chunkmaster.sqliteConnection.prepareStatement(""" SELECT id FROM generation_tasks ORDER BY id DESC LIMIT 1 """.trimIndent()) - getIdStatement.execute() - val result = getIdStatement.resultSet - result.next() - val id: Int = result.getInt("id") + getIdStatement.execute() + val result = getIdStatement.resultSet + result.next() + val id: Int = result.getInt("id") - insertStatement.close() - getIdStatement.close() + insertStatement.close() + getIdStatement.close() - if (!paused) { - val task = server.scheduler.runTaskTimer(chunkmaster, generationTask, 10, - chunkmaster.config.getLong("generation.period")) - tasks.add(RunningTaskEntry(id, task, generationTask)) + generationTask.onEndReached { + server.consoleSender.sendMessage("Task #${id} finished after ${generationTask.count} chunks.") + removeTask(id) + } + + if (!paused) { + val task = server.scheduler.runTaskTimer(chunkmaster, generationTask, 10, + chunkmaster.config.getLong("generation.period")) + tasks.add(RunningTaskEntry(id, task, generationTask)) + } else { + pausedTasks.add(PausedTaskEntry(id, generationTask)) + } + + return id } else { - pausedTasks.add(PausedTaskEntry(id, generationTask)) + return foundTask.id } - - return id } /** @@ -66,6 +83,10 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val task = server.scheduler.runTaskTimer(chunkmaster, generationTask, 10, chunkmaster.config.getLong("generation.period")) tasks.add(RunningTaskEntry(id, task, generationTask)) + generationTask.onEndReached { + server.consoleSender.sendMessage("Task #${id} finished after ${generationTask.count} chunks.") + removeTask(id) + } } } @@ -201,11 +222,6 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server updateStatement.setInt(3, task.id) updateStatement.execute() updateStatement.close() - - if (genTask.endReached) { // remove the task if it is finished after the progress has been saved - server.consoleSender.sendMessage("Task #${task.id} finished after ${genTask.count} chunks.") - removeTask(task.id) - } } catch (error: Exception) { server.consoleSender.sendMessage("Exception when saving task progress ${error.message}") } 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 e8c1233..91f8575 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -23,6 +23,9 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: Chunk, startChun protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold") protected val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks") + protected var endReachedCallback: (() -> Unit)? = null + private set + abstract override fun run() abstract fun cancel() @@ -48,4 +51,11 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: Chunk, startChun protected fun borderReached(): Boolean { return !world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) || (stopAfter in 1..count) } + + /** + * Registers end reached callback + */ + fun onEndReached(cb: () -> Unit) { + endReachedCallback = cb + } } \ 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 3b30d98..2a49321 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -38,6 +38,7 @@ class GenerationTaskPaper( } else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait. if (borderReached()) { endReached = true + endReachedCallback?.invoke() 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 f54f666..ea71d4d 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -33,6 +33,7 @@ class GenerationTaskSpigot( } else { if (borderReached()) { endReached = true + endReachedCallback?.invoke() return }