From d967dfd06d3c3744b9f1ff8731fb9f67a1568689 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 12 Apr 2020 10:42:14 +0200 Subject: [PATCH 01/20] Change sqlite-jdbc to be a compileOnly dependency --- build.gradle | 2 +- .../net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt diff --git a/build.gradle b/build.gradle index 66a32f9..31057c0 100644 --- a/build.gradle +++ b/build.gradle @@ -55,7 +55,7 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compileOnly "com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT" compileOnly "org.dynmap:dynmap-api:2.0" - compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0' + compileOnly group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0' compile "io.papermc:paperlib:1.0.2" compile "org.bstats:bstats-bukkit:1.5" } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt new file mode 100644 index 0000000..51c0992 --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt @@ -0,0 +1,4 @@ +package net.trivernis.chunkmaster.lib.dynmap + +class DynmapApiWrapper { +} \ No newline at end of file From 53aec18a06aa6c9a1c699286588fbdbe781eebbf Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 12 Apr 2020 14:16:42 +0200 Subject: [PATCH 02/20] Change group for Chunkmaster dynmap markers - Change the group to "Chunkmaster" to be able to disable all of those markers. - Add a marker that displays the last chunk that has been generated and refreshes every 30 seconds. --- .../net/trivernis/chunkmaster/Chunkmaster.kt | 1 - .../lib/dynmap/DynmapApiWrapper.kt | 28 ++++++- .../lib/dynmap/ExtendedMarkerSet.kt | 63 +++++++++++++++ .../chunkmaster/lib/dynmap/FillStyle.kt | 3 + .../chunkmaster/lib/dynmap/LineStyle.kt | 3 + .../chunkmaster/lib/dynmap/MarkerStyle.kt | 5 ++ .../lib/generation/GenerationManager.kt | 1 + .../lib/generation/GenerationTask.kt | 76 +++++++++++-------- .../lib/generation/GenerationTaskPaper.kt | 5 +- .../lib/generation/GenerationTaskSpigot.kt | 5 +- 10 files changed, 153 insertions(+), 37 deletions(-) create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/FillStyle.kt create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/LineStyle.kt create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/MarkerStyle.kt diff --git a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt index f1d6db4..285b8d9 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/Chunkmaster.kt @@ -9,7 +9,6 @@ import org.bstats.bukkit.Metrics import org.bukkit.plugin.java.JavaPlugin import org.bukkit.scheduler.BukkitTask import org.dynmap.DynmapAPI -import org.dynmap.DynmapCommonAPI import java.lang.Exception class Chunkmaster: JavaPlugin() { diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt index 51c0992..209cef8 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/DynmapApiWrapper.kt @@ -1,4 +1,30 @@ package net.trivernis.chunkmaster.lib.dynmap -class DynmapApiWrapper { +import org.dynmap.DynmapAPI + +class DynmapApiWrapper(private val dynmapAPI: DynmapAPI) { + + /** + * Returns a marker set by name + */ + fun getMarkerSet(name: String): ExtendedMarkerSet? { + val set = dynmapAPI.markerAPI?.getMarkerSet(name) + return if (set != null) { + ExtendedMarkerSet(set) + } else { + null + } + } + + fun getCreateMarkerSet(id: String, name: String): ExtendedMarkerSet? { + var set = dynmapAPI.markerAPI?.getMarkerSet(id) + if (set == null) { + set = dynmapAPI.markerAPI?.createMarkerSet(id, name, null, true) + } + return if (set != null) { + ExtendedMarkerSet(set) + } else { + null + } + } } \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt new file mode 100644 index 0000000..757faa8 --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt @@ -0,0 +1,63 @@ +package net.trivernis.chunkmaster.lib.dynmap + +import org.bukkit.Location +import org.dynmap.markers.AreaMarker +import org.dynmap.markers.Marker +import org.dynmap.markers.MarkerSet + +class ExtendedMarkerSet(private val markerSet: MarkerSet) { + /** + * Creates or updates an area marker depending on if it exists + * @param id - the unique id of the area marker + * @param label - the label that is displayed when clicking on the marker + * @param l1 - the top left corner + * @param l2 - the bottom right corner + */ + fun creUpdateAreMarker(id: String, label: String, l1: Location, l2: Location, style: MarkerStyle?): AreaMarker { + var marker = markerSet.findAreaMarker(id) + + if (marker != null) { + marker.setCornerLocations( + doubleArrayOf(l1.x, l2.x), + doubleArrayOf(l1.z, l2.z) + ) + } else { + marker = markerSet.createAreaMarker( + id, + label, + false, + l1.world.name, + doubleArrayOf(l1.x, l2.x), + doubleArrayOf(l1.z, l2.z), + true + ) + } + if (style != null) { + marker.boostFlag = style.boostFlag + if (style.lineStyle != null) { + marker.setLineStyle(style.lineStyle.weight, style.lineStyle.opacity, style.lineStyle.color) + } + if (style.fillStyle != null) { + marker.setFillStyle(style.fillStyle.opacity, style.fillStyle.color) + } + } + return marker + } + + /** + * Returns the area marker for an id + * @param id - the id of the marker + */ + fun findAreaMarker(id: String): AreaMarker? { + return markerSet.findAreaMarker(id) + } + + /** + * Deletes an area marker + * @param id - the id of the marker + */ + fun deleteAreaMarker(id: String) { + val marker = this.findAreaMarker(id) + marker?.deleteMarker() + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/FillStyle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/FillStyle.kt new file mode 100644 index 0000000..5f82a8f --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/FillStyle.kt @@ -0,0 +1,3 @@ +package net.trivernis.chunkmaster.lib.dynmap + +data class FillStyle(val opacity: Double, val color: Int) \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/LineStyle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/LineStyle.kt new file mode 100644 index 0000000..4bc467d --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/LineStyle.kt @@ -0,0 +1,3 @@ +package net.trivernis.chunkmaster.lib.dynmap + +data class LineStyle(val weight: Int, val opacity: Double, val color: Int) \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/MarkerStyle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/MarkerStyle.kt new file mode 100644 index 0000000..4260002 --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/MarkerStyle.kt @@ -0,0 +1,5 @@ +package net.trivernis.chunkmaster.lib.dynmap + +import org.dynmap.markers.MarkerIcon + +data class MarkerStyle(val icon: MarkerIcon?, val lineStyle: LineStyle?, val fillStyle: FillStyle?, val boostFlag: Boolean = 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 f822620..541d951 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -308,6 +308,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server genTask.lastChunk.x, genTask.lastChunk.z)) saveProgressToDatabase(genTask.lastChunkCoords, task.id) + genTask.updateLastChunkMarker() } catch (error: Exception) { chunkmaster.logger.warning(chunkmaster.langManager.getLocalized("TASK_SAVE_FAILED", error.toString())) } 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 8436a92..8207e31 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -2,8 +2,8 @@ package net.trivernis.chunkmaster.lib.generation import net.trivernis.chunkmaster.Chunkmaster import net.trivernis.chunkmaster.lib.Spiral +import net.trivernis.chunkmaster.lib.dynmap.* import org.bukkit.Chunk -import org.bukkit.Location import org.bukkit.World import kotlin.math.* @@ -27,13 +27,22 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold") protected val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks") protected val chunksPerStep = plugin.config.getInt("generation.chunks-per-step") - protected val dynmapIntegration = plugin.config.getBoolean("dynmap") - protected val dynmap = plugin.dynmapApi - protected var endReachedCallback: ((GenerationTask) -> Unit)? = null - private set - private val markerId = "chunkmaster_genarea" - private val markerName = "Chunkmaster Generation Area" + private var endReachedCallback: ((GenerationTask) -> Unit)? = null + + private val dynmapIntegration = plugin.config.getBoolean("dynmap") + private val dynmap = plugin.dynmapApi + private val markerSet: ExtendedMarkerSet? = if (dynmap != null) { + DynmapApiWrapper(dynmap).getCreateMarkerSet("chunkmaster", "Chunkmaster") + } else { + null + } + private val markerAreaStyle = MarkerStyle(null, LineStyle(2, 1.0, 0x0022FF), FillStyle(.0, 0)) + private val markerAreaId = "chunkmaster_genarea" + private val markerAreaName = "Chunkmaster Generation Area" + private val markerLastStyle = MarkerStyle(null, LineStyle(2, 1.0, 0x0077FF), FillStyle(.0, 0)) + private val markerLastId = "chunkmaster_lastchunk" + private val markerLastName = "Chunkmaster Last Chunk" private val ignoreWorldborder = plugin.config.getBoolean("generation.ignore-worldborder") abstract override fun run() @@ -83,38 +92,42 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun /** * Updates the dynmap marker for the generation radius */ - protected fun updateDynmapMarker(clear: Boolean = false) { - val markerSet = dynmap?.markerAPI?.getMarkerSet("markers") - var marker = markerSet?.findAreaMarker(markerId) + protected fun updateGenerationAreaMarker(clear: Boolean = false) { if (clear) { - marker?.deleteMarker() + markerSet?.deleteAreaMarker(markerAreaId) } else if (dynmapIntegration && stopAfter > 0) { val (topLeft, bottomRight) = this.getAreaCorners() - if (marker != null) { - marker.setCornerLocations( - doubleArrayOf((topLeft.x * 16).toDouble(), (bottomRight.x * 16).toDouble()), - doubleArrayOf((topLeft.z * 16).toDouble(), (bottomRight.z * 16).toDouble()) - ) - } else { - marker = markerSet?.createAreaMarker( - markerId, - markerName, - false, - world.name, - doubleArrayOf((topLeft.x * 16).toDouble(), (bottomRight.x * 16).toDouble()), - doubleArrayOf((topLeft.z * 16).toDouble(), (bottomRight.z * 16).toDouble()), - true - ) - } - marker?.setFillStyle(.0, 0) - marker?.setLineStyle(2, 1.0, 0x0000FF) + markerSet?.creUpdateAreMarker( + markerAreaId, + markerAreaName, + topLeft.getCenterLocation(world), + bottomRight.getCenterLocation(world), + markerAreaStyle + ) + } + } + + /** + * Updates the dynmap marker for the generation radius + */ + fun updateLastChunkMarker(clear: Boolean = false) { + if (clear) { + markerSet?.deleteAreaMarker(markerLastId) + } else if (dynmapIntegration) { + markerSet?.creUpdateAreMarker( + markerLastId, + markerLastName, + this.lastChunk.getBlock(0, 0, 0).location, + this.lastChunk.getBlock(15, 0, 15).location, + markerLastStyle + ) } } /** * Returns an approximation of cornders of the generation area */ - protected fun getAreaCorners(): Pair { + private fun getAreaCorners(): Pair { val width = sqrt(stopAfter.toFloat()) return Pair( ChunkCoordinates(centerChunk.x - floor(width/2).toInt(), centerChunk.z - floor(width/2).toInt()), @@ -128,7 +141,8 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun protected fun setEndReached() { endReached = true endReachedCallback?.invoke(this) - updateDynmapMarker(true) + updateGenerationAreaMarker(true) + updateLastChunkMarker(true) if (dynmapIntegration) { val (topLeft, bottomRight) = this.getAreaCorners() dynmap?.triggerRenderOfVolume(topLeft.getCenterLocation(world), bottomRight.getCenterLocation(world)) 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 a8e20bc..3f19cb1 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -20,7 +20,7 @@ class GenerationTaskPaper( override var endReached: Boolean = false init { - updateDynmapMarker() + updateGenerationAreaMarker() } /** @@ -70,7 +70,8 @@ class GenerationTaskPaper( * This unloads all chunks that were generated but not unloaded yet. */ override fun cancel() { - updateDynmapMarker(true) + updateGenerationAreaMarker(true) + updateLastChunkMarker(true) unloadAllChunks() } 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 bf5a36f..c82d3bb 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -16,7 +16,7 @@ class GenerationTaskSpigot( override var endReached: Boolean = false init { - updateDynmapMarker() + updateGenerationAreaMarker() } /** @@ -67,6 +67,7 @@ class GenerationTaskSpigot( } } } - updateDynmapMarker(true) + updateGenerationAreaMarker(true) + updateLastChunkMarker(true) } } \ No newline at end of file From 2eeff350f8255a428051164fcddd44d7afe2c4f2 Mon Sep 17 00:00:00 2001 From: trivernis Date: Mon, 13 Apr 2020 14:50:59 +0200 Subject: [PATCH 03/20] Add circular shape class --- build.gradle | 2 +- .../lib/generation/GenerationManager.kt | 7 +- .../lib/generation/GenerationTask.kt | 11 ++- .../lib/generation/GenerationTaskPaper.kt | 8 +- .../lib/generation/GenerationTaskSpigot.kt | 8 +- .../chunkmaster/lib/shapes/Circle.kt | 86 +++++++++++++++++++ .../trivernis/chunkmaster/lib/shapes/Shape.kt | 11 +++ .../chunkmaster/lib/{ => shapes}/Spiral.kt | 8 +- src/main/resources/plugin.yml | 2 +- 9 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt create mode 100644 src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt rename src/main/kotlin/net/trivernis/chunkmaster/lib/{ => shapes}/Spiral.kt (88%) diff --git a/build.gradle b/build.gradle index 31057c0..2887247 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ idea { } group "net.trivernis" -version "0.15-beta" +version "0.16-beta" sourceCompatibility = 1.8 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 541d951..b9f16d6 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -2,6 +2,8 @@ package net.trivernis.chunkmaster.lib.generation import io.papermc.lib.PaperLib import net.trivernis.chunkmaster.Chunkmaster +import net.trivernis.chunkmaster.lib.shapes.Circle +import net.trivernis.chunkmaster.lib.shapes.Spiral import org.bukkit.Chunk import org.bukkit.Server import org.bukkit.World @@ -339,10 +341,11 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server start: ChunkCoordinates, stopAfter: Int ): GenerationTask { + val shape = Spiral(Pair(center.x, center.z), Pair(center.x, center.z)) return if (PaperLib.isPaper()) { - GenerationTaskPaper(chunkmaster, world, center, start, stopAfter) + GenerationTaskPaper(chunkmaster, world, center, start, stopAfter, shape) } else { - GenerationTaskSpigot(chunkmaster, world, center, start, stopAfter) + GenerationTaskSpigot(chunkmaster, world, center, start, stopAfter, shape) } } } \ 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 8207e31..e631fe1 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -1,8 +1,9 @@ package net.trivernis.chunkmaster.lib.generation import net.trivernis.chunkmaster.Chunkmaster -import net.trivernis.chunkmaster.lib.Spiral +import net.trivernis.chunkmaster.lib.shapes.Spiral import net.trivernis.chunkmaster.lib.dynmap.* +import net.trivernis.chunkmaster.lib.shapes.Shape import org.bukkit.Chunk import org.bukkit.World import kotlin.math.* @@ -10,7 +11,7 @@ import kotlin.math.* /** * Interface for generation tasks. */ -abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: ChunkCoordinates, startChunk: ChunkCoordinates) : +abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: ChunkCoordinates, startChunk: ChunkCoordinates, protected val shape: Shape) : Runnable { abstract val stopAfter: Int @@ -18,8 +19,6 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun abstract val count: Int abstract var endReached: Boolean - protected val spiral: Spiral = - Spiral(Pair(centerChunk.x, centerChunk.z), Pair(startChunk.x, startChunk.z)) protected val loadedChunks: HashSet = HashSet() var lastChunkCoords = ChunkCoordinates(startChunk.x, startChunk.z) protected set @@ -40,7 +39,7 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun private val markerAreaStyle = MarkerStyle(null, LineStyle(2, 1.0, 0x0022FF), FillStyle(.0, 0)) private val markerAreaId = "chunkmaster_genarea" private val markerAreaName = "Chunkmaster Generation Area" - private val markerLastStyle = MarkerStyle(null, LineStyle(2, 1.0, 0x0077FF), FillStyle(.0, 0)) + private val markerLastStyle = MarkerStyle(null, LineStyle(2, 1.0, 0x0077FF), FillStyle(.5, 0x0077FF)) private val markerLastId = "chunkmaster_lastchunk" private val markerLastName = "Chunkmaster Last Chunk" private val ignoreWorldborder = plugin.config.getBoolean("generation.ignore-worldborder") @@ -50,7 +49,7 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun val nextChunkCoordinates: ChunkCoordinates get() { - val nextChunkCoords = spiral.next() + val nextChunkCoords = shape.next() return ChunkCoordinates(nextChunkCoords.first, nextChunkCoords.second) } 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 3f19cb1..bde3821 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -1,6 +1,7 @@ package net.trivernis.chunkmaster.lib.generation import net.trivernis.chunkmaster.Chunkmaster +import net.trivernis.chunkmaster.lib.shapes.Shape import org.bukkit.Chunk import org.bukkit.World import java.util.concurrent.CompletableFuture @@ -8,8 +9,9 @@ import java.util.concurrent.CompletableFuture class GenerationTaskPaper( private val plugin: Chunkmaster, override val world: World, centerChunk: ChunkCoordinates, private val startChunk: ChunkCoordinates, - override val stopAfter: Int = -1 -) : GenerationTask(plugin, centerChunk, startChunk) { + override val stopAfter: Int = -1, + shape: Shape +) : GenerationTask(plugin, centerChunk, startChunk, shape) { private val maxPendingChunks = plugin.config.getInt("generation.max-pending-chunks") @@ -59,7 +61,7 @@ class GenerationTaskPaper( } } lastChunkCoords = chunk - count = spiral.count // set the count to the more accurate spiral count + count = shape.count // set the count to the more accurate spiral count } } checkChunksLoaded() 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 c82d3bb..c0c9561 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -1,14 +1,16 @@ package net.trivernis.chunkmaster.lib.generation import net.trivernis.chunkmaster.Chunkmaster +import net.trivernis.chunkmaster.lib.shapes.Shape import org.bukkit.World import java.lang.Exception class GenerationTaskSpigot( private val plugin: Chunkmaster, override val world: World, centerChunk: ChunkCoordinates, private val startChunk: ChunkCoordinates, - override val stopAfter: Int = -1 -) : GenerationTask(plugin, centerChunk, startChunk) { + override val stopAfter: Int = -1, + shape: Shape +) : GenerationTask(plugin, centerChunk, startChunk, shape) { override var count = 0 @@ -48,7 +50,7 @@ class GenerationTaskSpigot( loadedChunks.add(chunkInstance) } lastChunkCoords = chunk - count = spiral.count // set the count to the more accurate spiral count + count = shape.count // set the count to the more accurate spiral count } } } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt new file mode 100644 index 0000000..6560866 --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt @@ -0,0 +1,86 @@ +package net.trivernis.chunkmaster.lib.shapes + +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashSet +import kotlin.system.exitProcess + +class Circle(center: Pair, start: Pair): Shape(center, start) { + var r = 0 + private set + private var coords = Stack>() + + override fun next(): Pair { + if (count == 0 && currentPos != center) { + val tmpCircle = Circle(center, center) + while (tmpCircle.next() != currentPos); + this.count = tmpCircle.count + this.r = tmpCircle.r + } + if (count == 0) { + count++ + return center + } + if (coords.isEmpty()) { + r++ + val tmpCoords = HashSet>() + tmpCoords.addAll(getCircleCoordinates((r*2)-1).map { Pair(it.first / 2, it.second / 2) }) + tmpCoords.addAll(getCircleCoordinates(r)) + coords.addAll(tmpCoords) + } + count++ + val coord = coords.pop() + currentPos = Pair(coord.first + center.first, coord.second + center.second) + return currentPos + } + + /** + * Returns the int coordinates for a circle + * @param r - the radius + */ + private fun getCircleCoordinates(r: Int): HashSet> { + val coords = ArrayList>() + val segCoords = getSegment(r) + coords.addAll(segCoords) + for (step in 0..7) { + for (pos in segCoords) { + coords.add(when (step) { + 0 -> pos + 1 -> Pair(pos.second, pos.first) + 2 -> Pair(pos.first, -pos.second) + 3 -> Pair(-pos.second, pos.first) + 4 -> Pair(-pos.first, -pos.second) + 5 -> Pair(-pos.second, -pos.first) + 6 -> Pair(-pos.first, pos.second) + 7 -> Pair(pos.second, -pos.first) + else -> pos + }) + } + } + + val set = HashSet>() + set.addAll(coords) + return set + } + + /** + * Returns the int coordinates for a circles segment + * @param r - the radius + */ + private fun getSegment(r: Int): ArrayList> { + var d = -r + var x = r + var y = 0 + val coords = ArrayList>() + while (y <= x) { + coords.add(Pair(x, y)) + d += 2 * y + 1 + y += 1 + if (d > 0) { + x -= 1 + d -= 2 * x + } + } + return coords + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt new file mode 100644 index 0000000..0c5c365 --- /dev/null +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt @@ -0,0 +1,11 @@ +package net.trivernis.chunkmaster.lib.shapes + +abstract class Shape(protected val center: Pair, start: Pair) { + protected var currentPos = start + var count = 0 + + /** + * Returns the next value + */ + abstract fun next(): Pair +} \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/Spiral.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt similarity index 88% rename from src/main/kotlin/net/trivernis/chunkmaster/lib/Spiral.kt rename to src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt index 15b063f..8a70f5b 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/Spiral.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt @@ -1,16 +1,14 @@ -package net.trivernis.chunkmaster.lib +package net.trivernis.chunkmaster.lib.shapes import kotlin.math.abs -class Spiral(private val center: Pair, start: Pair) { - private var currentPos = start +class Spiral(center: Pair, start: Pair): Shape(center, start) { private var direction = 0 - var count = 0 /** * Returns the next value in the spiral */ - fun next(): Pair { + override fun next(): Pair { if (count == 0 && currentPos != center) { // simulate the spiral to get the correct direction // TODO: Improve performance of this workaround (replace it with acutal stuff) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 8bf099a..196281a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ main: net.trivernis.chunkmaster.Chunkmaster name: Chunkmaster -version: '0.15-beta' +version: '0.16-beta' description: Chunk commands plugin. author: Trivernis website: trivernis.net From 572369192a8a23f427d5390733b5f694cdcf2100 Mon Sep 17 00:00:00 2001 From: trivernis Date: Mon, 13 Apr 2020 19:31:58 +0200 Subject: [PATCH 04/20] Add circlular generation tasks --- .../chunkmaster/commands/CmdGenerate.kt | 111 ++++++++---------- .../trivernis/chunkmaster/commands/CmdList.kt | 6 +- .../chunkmaster/lib/SqliteManager.kt | 3 +- .../lib/dynmap/ExtendedMarkerSet.kt | 32 +++++ .../lib/generation/GenerationManager.kt | 54 +++++---- .../lib/generation/GenerationTask.kt | 49 ++++---- .../lib/generation/GenerationTaskPaper.kt | 20 ++-- .../lib/generation/GenerationTaskSpigot.kt | 21 ++-- .../lib/generation/RunningTaskEntry.kt | 23 ++-- .../chunkmaster/lib/shapes/Circle.kt | 72 +++++++++--- .../trivernis/chunkmaster/lib/shapes/Shape.kt | 28 ++++- .../chunkmaster/lib/shapes/Spiral.kt | 32 ++++- .../resources/i18n/DEFAULT.i18n.properties | 5 +- src/main/resources/i18n/de.i18n.properties | 5 +- src/main/resources/i18n/en.i18n.properties | 5 +- src/main/resources/plugin.yml | 2 +- 16 files changed, 297 insertions(+), 171 deletions(-) diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt index deaa7c3..baef0b9 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdGenerate.kt @@ -5,7 +5,6 @@ import net.trivernis.chunkmaster.lib.Subcommand import org.bukkit.command.Command import org.bukkit.command.CommandSender import org.bukkit.entity.Player -import kotlin.math.pow class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { override val name = "generate" @@ -24,16 +23,17 @@ class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { .map {it.name}.toMutableList() } else if (args.size == 2) { if (args[0].toIntOrNull() != null) { - return units.filter {it.indexOf(args[1]) == 0}.toMutableList() + return shapes.filter {it.indexOf(args[1]) == 0}.toMutableList() } } else if (args.size > 2) { if (args[1].toIntOrNull() != null) { - return units.filter {it.indexOf(args[2]) == 0}.toMutableList() + return shapes.filter {it.indexOf(args[2]) == 0}.toMutableList() } } return emptyList().toMutableList() } - val units = listOf("blockradius", "radius", "diameter") + + val shapes = listOf("circle", "square") /** @@ -41,80 +41,73 @@ class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand { */ override fun execute(sender: CommandSender, args: List): Boolean { var worldName = "" - var stopAfter = -1 + var blockRadius = -1 + var shape = "square" + if (sender is Player) { - if (args.isNotEmpty()) { - if (args[0].toIntOrNull() != null) { - stopAfter = args[0].toInt() - worldName = sender.world.name - } else { - worldName = args[0] - } - if (args.size > 1) { - if (args[1].toIntOrNull() != null) { - stopAfter = args[1].toInt() - } else if (args[1] in units && args[0].toIntOrNull() != null) { - stopAfter = getStopAfter(stopAfter, args[1]) - } else { - worldName = args[1] - } - } - if (args.size > 2 && args[2] in units && args[1].toIntOrNull() != null) { - stopAfter = getStopAfter(stopAfter, args[2]) - } + worldName = sender.world.name + } + if (args.isEmpty()) { + if (sender is Player) { + return createTask(sender, worldName, blockRadius, shape) } else { - worldName = sender.world.name + sender.sendMessage(chunkmaster.langManager.getLocalized("WORLD_NAME_REQUIRED")) + return false } - } else { - if (args.isNotEmpty()) { - worldName = args[0] - if (args.size > 1) { - if (args[1].toIntOrNull() != null) { - stopAfter = args[1].toInt() - } - } - if (args.size > 2 && args[2] in units) { - stopAfter = getStopAfter(stopAfter, args[2]) - } - } else { + } + if (args[0].toIntOrNull() != null) { + if (sender !is Player) { sender.sendMessage(chunkmaster.langManager.getLocalized("WORLD_NAME_REQUIRED")) return false } + blockRadius = args[0].toInt() + } else { + worldName = args[0] } - return createTask(sender, worldName, stopAfter) - } - /** - * Returns stopAfter for a given unit - */ - private fun getStopAfter(number: Int, unit: String): Int { - if (unit in units) { - return when (unit) { - "radius" -> { - ((number * 2)+1).toDouble().pow(2.0).toInt() - } - "diameter" -> { - number.toDouble().pow(2.0).toInt() - } - "blockradius" -> { - ((number.toDouble()+1)/8).pow(2.0).toInt() - } - else -> number + if (args.size == 1) { + return createTask(sender, worldName, blockRadius, shape) + } + + when { + args[1].toIntOrNull() != null -> blockRadius = args[1].toInt() + args[1] in shapes -> shape = args[1] + else -> { + sender.sendMessage(chunkmaster.langManager.getLocalized("INVALID_ARGUMENT", 2, args[1])) + return false } } - return number + if (args.size == 2) { + return createTask(sender, worldName, blockRadius, shape) + } + if (args[2] in shapes) { + shape = args[2] + } else { + sender.sendMessage(chunkmaster.langManager.getLocalized("INVALID_ARGUMENT", 3, args[2])) + return false + } + + return createTask(sender, worldName, blockRadius, shape) } /** * Creates the task with the given arguments. */ - private fun createTask(sender: CommandSender, worldName: String, stopAfter: Int): Boolean { + private fun createTask(sender: CommandSender, worldName: String, blockRadius: Int, shape: String): Boolean { val world = chunkmaster.server.getWorld(worldName) val allTasks = chunkmaster.generationManager.allTasks return if (world != null && (allTasks.find { it.generationTask.world == world }) == null) { - chunkmaster.generationManager.addTask(world, stopAfter) + chunkmaster.generationManager.addTask(world, if (blockRadius > 0) blockRadius/16 else -1 , shape) sender.sendMessage(chunkmaster.langManager - .getLocalized("TASK_CREATION_SUCCESS", worldName, if (stopAfter > 0) "$stopAfter chunks" else "WorldBorder")) + .getLocalized("TASK_CREATION_SUCCESS", + worldName, + if (blockRadius > 0) { + chunkmaster.langManager.getLocalized("TASK_UNIT_RADIUS", blockRadius) + } else{ + chunkmaster.langManager.getLocalized("TASK_UNIT_WORLDBORDER") + }, + shape + )) true } else if (world == null){ sender.sendMessage(chunkmaster.langManager.getLocalized("WORLD_NOT_FOUND", worldName)); diff --git a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdList.kt b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdList.kt index 86f98c3..98472cb 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdList.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/commands/CmdList.kt @@ -1,7 +1,5 @@ package net.trivernis.chunkmaster.commands -import net.md_5.bungee.api.ChatColor -import net.md_5.bungee.api.chat.ComponentBuilder import net.trivernis.chunkmaster.Chunkmaster import net.trivernis.chunkmaster.lib.Subcommand import net.trivernis.chunkmaster.lib.generation.TaskEntry @@ -50,8 +48,8 @@ class CmdList(private val chunkmaster: Chunkmaster): Subcommand { */ private fun getGenerationEntry(task: TaskEntry): String { val genTask = task.generationTask - val percentage = if (genTask.stopAfter > 0) - " (%.1f".format((genTask.count.toDouble()/genTask.stopAfter.toDouble())*100) + "%)." + val percentage = if (genTask.radius > 0) + " (%.1f".format(genTask.shape.progress()*100) + "%)." else "" return "\n" + chunkmaster.langManager.getLocalized("TASKS_ENTRY", diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/SqliteManager.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/SqliteManager.kt index 00dcd5b..47419f5 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/SqliteManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/SqliteManager.kt @@ -20,7 +20,8 @@ class SqliteManager(private val chunkmaster: Chunkmaster) { 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("radius", "integer DEFAULT -1"), + Pair("shape", "text NOT NULL DEFAULT 'square'") ) ), Pair( diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt index 757faa8..c5dab40 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/dynmap/ExtendedMarkerSet.kt @@ -4,6 +4,7 @@ import org.bukkit.Location import org.dynmap.markers.AreaMarker import org.dynmap.markers.Marker import org.dynmap.markers.MarkerSet +import org.dynmap.markers.PolyLineMarker class ExtendedMarkerSet(private val markerSet: MarkerSet) { /** @@ -44,6 +45,25 @@ class ExtendedMarkerSet(private val markerSet: MarkerSet) { return marker } + + fun creUpdatePolyLineMarker(id: String, label: String, edges: List, style: MarkerStyle?): PolyLineMarker? { + var marker = markerSet.findPolyLineMarker(id) + val xList = edges.map { it.x } + val yList = edges.map { it.y } + val zList = edges.map { it.z } + if (marker != null) { + marker.setCornerLocations(xList.toDoubleArray(), yList.toDoubleArray(), zList.toDoubleArray()) + } else { + marker = markerSet.createPolyLineMarker(id, label, false, edges.first().world.name, xList.toDoubleArray(), yList.toDoubleArray(), zList.toDoubleArray(), true) + } + if (style != null) { + if (style.lineStyle != null) { + marker.setLineStyle(style.lineStyle.weight, style.lineStyle.opacity, style.lineStyle.color) + } + } + return marker + } + /** * Returns the area marker for an id * @param id - the id of the marker @@ -52,6 +72,13 @@ class ExtendedMarkerSet(private val markerSet: MarkerSet) { return markerSet.findAreaMarker(id) } + /** + * Returns the polylinemarker for an id + */ + fun findPolyLineMarker(id: String): PolyLineMarker? { + return markerSet.findPolyLineMarker(id) + } + /** * Deletes an area marker * @param id - the id of the marker @@ -60,4 +87,9 @@ class ExtendedMarkerSet(private val markerSet: MarkerSet) { val marker = this.findAreaMarker(id) marker?.deleteMarker() } + + fun deletePolyLineMarker(id: String) { + val marker = this.findPolyLineMarker(id) + marker?.deleteMarker() + } } \ 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 b9f16d6..af94091 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -4,7 +4,6 @@ import io.papermc.lib.PaperLib import net.trivernis.chunkmaster.Chunkmaster import net.trivernis.chunkmaster.lib.shapes.Circle import net.trivernis.chunkmaster.lib.shapes.Spiral -import org.bukkit.Chunk import org.bukkit.Server import org.bukkit.World @@ -35,7 +34,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server /** * Adds a generation task */ - fun addTask(world: World, stopAfter: Int = -1): Int { + fun addTask(world: World, radius: Int = -1, shape: String = "square"): Int { val foundTask = allTasks.find { it.generationTask.world == world } if (foundTask == null) { val centerChunk = if (worldCenters[world.name] == null) { @@ -44,12 +43,12 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val center = worldCenters[world.name]!! ChunkCoordinates(center.first, center.second) } - val generationTask = createGenerationTask(world, centerChunk, centerChunk, stopAfter) + val generationTask = createGenerationTask(world, centerChunk, centerChunk, radius, shape) chunkmaster.sqliteManager.executeStatement( """ - INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, stop_after) - values (?, ?, ?, ?, ?, ?) + INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, radius, shape) + values (?, ?, ?, ?, ?, ?, ?) """, HashMap( mapOf( @@ -58,7 +57,8 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server 3 to centerChunk.x, 4 to centerChunk.z, 5 to world.name, - 6 to stopAfter + 6 to radius, + 7 to shape ) ), null @@ -101,14 +101,15 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server center: ChunkCoordinates, last: ChunkCoordinates, id: Int, - stopAfter: Int = -1, - delay: Long = 200L + radius: Int = -1, + delay: Long = 200L, + shape: String = "square" ) { if (!paused) { chunkmaster.logger.info(chunkmaster.langManager.getLocalized("RESUME_FOR_WORLD", world.name)) - val generationTask = createGenerationTask(world, center, last, stopAfter) + val generationTask = createGenerationTask(world, center, last, radius, shape) val task = server.scheduler.runTaskTimer( - chunkmaster, generationTask, delay, // 10 sec delay + chunkmaster, generationTask, delay, chunkmaster.config.getLong("generation.period") ) tasks.add(RunningTaskEntry(id, task, generationTask)) @@ -163,7 +164,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server if (!server.onlinePlayers.isEmpty()) { this.pauseAll() } - }, 600) + }, 20) } /** @@ -199,9 +200,10 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server val world = server.getWorld(res.getString("world")) val center = ChunkCoordinates(res.getInt("center_x"), res.getInt("center_z")) val last = ChunkCoordinates(res.getInt("last_x"), res.getInt("last_z")) - val stopAfter = res.getInt("stop_after") + val radius = res.getInt("radius") + val shape = res.getString("shape") if (this.tasks.find { it.id == id } == null) { - resumeTask(world!!, center, last, id, stopAfter, 200L + count) + resumeTask(world!!, center, last, id, radius, 200L + count, shape) } } catch (error: NullPointerException) { chunkmaster.logger.severe(chunkmaster.langManager.getLocalized("TASK_LOAD_FAILED", res.getInt("id"))) @@ -286,12 +288,10 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server for (task in tasks) { try { val genTask = task.generationTask - val speed = task.generationSpeed!! - val percentage = if (genTask.stopAfter > 0) "(${"%.2f".format( - (genTask.count.toDouble() / genTask.stopAfter.toDouble()) * 100 - )}%)" else "" - val eta = if (genTask.stopAfter > 0 && speed > 0) { - val etaSeconds = (genTask.stopAfter - genTask.count).toDouble()/speed + val (speed, chunkSpeed) = task.generationSpeed + val percentage = if (genTask.radius > 0) "(${"%.2f".format(genTask.shape.progress() * 100)}%)" else "" + val eta = if (genTask.radius > 0 && speed!! > 0) { + val etaSeconds = (genTask.shape.progress())/speed val hours: Int = (etaSeconds/3600).toInt() val minutes: Int = ((etaSeconds % 3600) / 60).toInt() val seconds: Int = (etaSeconds % 60).toInt() @@ -306,7 +306,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server genTask.count, percentage, eta, - speed, + chunkSpeed!!, genTask.lastChunk.x, genTask.lastChunk.z)) saveProgressToDatabase(genTask.lastChunkCoords, task.id) @@ -339,13 +339,19 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server world: World, center: ChunkCoordinates, start: ChunkCoordinates, - stopAfter: Int + radius: Int, + shapeName: String ): GenerationTask { - val shape = Spiral(Pair(center.x, center.z), Pair(center.x, center.z)) + val shape = when (shapeName) { + "circle" -> Circle(Pair(center.x, center.z), Pair(center.x, center.z), radius) + "square" -> Spiral(Pair(center.x, center.z), Pair(center.x, center.z), radius) + else -> Spiral(Pair(center.x, center.z), Pair(center.x, center.z), radius) + } + return if (PaperLib.isPaper()) { - GenerationTaskPaper(chunkmaster, world, center, start, stopAfter, shape) + GenerationTaskPaper(chunkmaster, world, start, radius, shape) } else { - GenerationTaskSpigot(chunkmaster, world, center, start, stopAfter, shape) + GenerationTaskSpigot(chunkmaster, world, center, start, radius, shape) } } } \ 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 e631fe1..50b6447 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -1,22 +1,24 @@ package net.trivernis.chunkmaster.lib.generation import net.trivernis.chunkmaster.Chunkmaster -import net.trivernis.chunkmaster.lib.shapes.Spiral import net.trivernis.chunkmaster.lib.dynmap.* import net.trivernis.chunkmaster.lib.shapes.Shape import org.bukkit.Chunk import org.bukkit.World -import kotlin.math.* /** * Interface for generation tasks. */ -abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: ChunkCoordinates, startChunk: ChunkCoordinates, protected val shape: Shape) : +abstract class GenerationTask( + plugin: Chunkmaster, + startChunk: ChunkCoordinates, + val shape: Shape +) : Runnable { - abstract val stopAfter: Int + abstract val radius: Int abstract val world: World - abstract val count: Int + abstract var count: Int abstract var endReached: Boolean protected val loadedChunks: HashSet = HashSet() @@ -69,7 +71,7 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun */ protected fun borderReached(): Boolean { return (!world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) && !ignoreWorldborder) - || (stopAfter in 1..count) + || shape.endReached() } /** @@ -93,14 +95,12 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun */ protected fun updateGenerationAreaMarker(clear: Boolean = false) { if (clear) { - markerSet?.deleteAreaMarker(markerAreaId) - } else if (dynmapIntegration && stopAfter > 0) { - val (topLeft, bottomRight) = this.getAreaCorners() - markerSet?.creUpdateAreMarker( + markerSet?.deletePolyLineMarker(markerAreaId) + } else if (dynmapIntegration && radius > 0) { + markerSet?.creUpdatePolyLineMarker( markerAreaId, markerAreaName, - topLeft.getCenterLocation(world), - bottomRight.getCenterLocation(world), + this.shape.getShapeEdgeLocations().map { ChunkCoordinates(it.first, it.second).getCenterLocation(this.world) }, markerAreaStyle ) } @@ -123,29 +123,26 @@ abstract class GenerationTask(plugin: Chunkmaster, private val centerChunk: Chun } } - /** - * Returns an approximation of cornders of the generation area - */ - private fun getAreaCorners(): Pair { - val width = sqrt(stopAfter.toFloat()) - return Pair( - ChunkCoordinates(centerChunk.x - floor(width/2).toInt(), centerChunk.z - floor(width/2).toInt()), - ChunkCoordinates(centerChunk.x + ceil(width/2).toInt(), centerChunk.z + ceil(width/2).toInt()) - ) - } - /** * Handles the invocation of the end reached callback and additional logic */ protected fun setEndReached() { endReached = true + count = shape.count endReachedCallback?.invoke(this) updateGenerationAreaMarker(true) updateLastChunkMarker(true) - if (dynmapIntegration) { - val (topLeft, bottomRight) = this.getAreaCorners() - dynmap?.triggerRenderOfVolume(topLeft.getCenterLocation(world), bottomRight.getCenterLocation(world)) + } + + /** + * Performs a check if the border has been reached + */ + protected fun borderReachedCheck(): Boolean { + val done = borderReached() + if (done) { + setEndReached() } + return done } /** 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 bde3821..73915c6 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -7,18 +7,18 @@ import org.bukkit.World import java.util.concurrent.CompletableFuture class GenerationTaskPaper( - private val plugin: Chunkmaster, override val world: World, - centerChunk: ChunkCoordinates, private val startChunk: ChunkCoordinates, - override val stopAfter: Int = -1, + private val plugin: Chunkmaster, + override val world: World, + startChunk: ChunkCoordinates, + override val radius: Int = -1, shape: Shape -) : GenerationTask(plugin, centerChunk, startChunk, shape) { +) : GenerationTask(plugin, startChunk, shape) { private val maxPendingChunks = plugin.config.getInt("generation.max-pending-chunks") private val pendingChunks = HashSet>() override var count = 0 - private set override var endReached: Boolean = false init { @@ -35,10 +35,7 @@ class GenerationTaskPaper( if (loadedChunks.size > maxLoadedChunks) { unloadLoadedChunks() } else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait. - if (borderReached()) { - setEndReached() - return - } + if (borderReachedCheck()) return var chunk = nextChunkCoordinates for (i in 1 until chunkSkips) { @@ -50,13 +47,14 @@ class GenerationTaskPaper( } if (!world.isChunkGenerated(chunk.x, chunk.z)) { - for (i in 0 until minOf(chunksPerStep, (stopAfter - count) - 1)) { + for (i in 0 until chunksPerStep) { + if (borderReachedCheck()) break if (!world.isChunkGenerated(chunk.x, chunk.z)) { pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true)) } chunk = nextChunkCoordinates } - if (!world.isChunkGenerated(chunk.x, chunk.z)) { + if (!borderReachedCheck() && !world.isChunkGenerated(chunk.x, chunk.z)) { pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true)) } } 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 c0c9561..bf60f9a 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -8,13 +8,12 @@ import java.lang.Exception class GenerationTaskSpigot( private val plugin: Chunkmaster, override val world: World, centerChunk: ChunkCoordinates, private val startChunk: ChunkCoordinates, - override val stopAfter: Int = -1, + override val radius: Int = -1, shape: Shape -) : GenerationTask(plugin, centerChunk, startChunk, shape) { +) : GenerationTask(plugin, startChunk, shape) { override var count = 0 - private set override var endReached: Boolean = false init { @@ -31,23 +30,23 @@ class GenerationTaskSpigot( if (loadedChunks.size > maxLoadedChunks) { unloadLoadedChunks() } else { - if (borderReached()) { - setEndReached() - return - } + if (borderReachedCheck()) return var chunk = nextChunkCoordinates if (!world.isChunkGenerated(chunk.x, chunk.z)) { - for (i in 0 until minOf(chunksPerStep, stopAfter - count)) { + for (i in 0 until minOf(chunksPerStep, radius - shape.currentRadius())) { + if (borderReachedCheck()) break val chunkInstance = world.getChunkAt(chunk.x, chunk.z) chunkInstance.load(true) loadedChunks.add(chunkInstance) chunk = nextChunkCoordinates } - val chunkInstance = world.getChunkAt(chunk.x, chunk.z) - chunkInstance.load(true) - loadedChunks.add(chunkInstance) + if (!borderReachedCheck()) { + val chunkInstance = world.getChunkAt(chunk.x, chunk.z) + chunkInstance.load(true) + loadedChunks.add(chunkInstance) + } } lastChunkCoords = chunk count = shape.count // set the count to the more accurate spiral count diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/RunningTaskEntry.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/RunningTaskEntry.kt index a5f35c0..d28d8bb 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/RunningTaskEntry.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/RunningTaskEntry.kt @@ -8,25 +8,34 @@ class RunningTaskEntry( override val generationTask: GenerationTask ) : TaskEntry { - private var lastProgress: Pair? = null + private var lastProgress: Pair? = null + private var lastChunkCount: Pair? = null /** * Returns the generation Speed */ - val generationSpeed: Double? + val generationSpeed: Pair get() { var generationSpeed: Double? = null + var chunkGenerationSpeed: Double? = null if (lastProgress != null) { - val chunkDiff = generationTask.count - lastProgress!!.second + val progressDiff = generationTask.shape.progress() - lastProgress!!.second val timeDiff = (System.currentTimeMillis() - lastProgress!!.first).toDouble()/1000 - generationSpeed = chunkDiff.toDouble()/timeDiff + generationSpeed = progressDiff/timeDiff } - lastProgress = Pair(System.currentTimeMillis(), generationTask.count) - return generationSpeed + if (lastChunkCount != null) { + val chunkDiff = generationTask.count - lastChunkCount!!.second + val timeDiff = (System.currentTimeMillis() - lastChunkCount!!.first).toDouble()/1000 + chunkGenerationSpeed = chunkDiff/timeDiff + } + lastProgress = Pair(System.currentTimeMillis(), generationTask.shape.progress()) + lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count) + return Pair(generationSpeed, chunkGenerationSpeed) } init { - lastProgress = Pair(System.currentTimeMillis(), generationTask.count) + lastProgress = Pair(System.currentTimeMillis(), generationTask.shape.progress()) + lastChunkCount = Pair(System.currentTimeMillis(), generationTask.count) } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt index 6560866..90bc9de 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt @@ -1,18 +1,42 @@ package net.trivernis.chunkmaster.lib.shapes +import net.trivernis.chunkmaster.lib.dynmap.ExtendedMarkerSet +import net.trivernis.chunkmaster.lib.dynmap.MarkerStyle import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashSet +import kotlin.math.PI +import kotlin.math.pow +import kotlin.math.sqrt import kotlin.system.exitProcess -class Circle(center: Pair, start: Pair): Shape(center, start) { - var r = 0 - private set +class Circle(center: Pair, start: Pair, radius: Int): Shape(center, start, radius) { + private var r = 0 private var coords = Stack>() + private var previousCoords = HashSet>() + + override fun endReached(): Boolean { + if ((radius + 1) in 1..r) return true + return radius > 0 && coords.isEmpty() && r >= radius + } + + override fun progress(): Double { + return (PI * r.toFloat().pow(2))/(PI* radius.toFloat().pow(2)) + } + + override fun currentRadius(): Int { + return r + } + + override fun getShapeEdgeLocations(): List> { + val locations = this.getCircleCoordinates(this.radius) + locations.add(locations.first()) + return locations.map{ Pair(it.first + center.first, it.second + center.second) } + } override fun next(): Pair { if (count == 0 && currentPos != center) { - val tmpCircle = Circle(center, center) + val tmpCircle = Circle(center, center, radius) while (tmpCircle.next() != currentPos); this.count = tmpCircle.count this.r = tmpCircle.r @@ -26,7 +50,10 @@ class Circle(center: Pair, start: Pair): Shape(center, start val tmpCoords = HashSet>() tmpCoords.addAll(getCircleCoordinates((r*2)-1).map { Pair(it.first / 2, it.second / 2) }) tmpCoords.addAll(getCircleCoordinates(r)) + tmpCoords.removeAll(previousCoords) + previousCoords.clear() coords.addAll(tmpCoords) + previousCoords.addAll(tmpCoords) } count++ val coord = coords.pop() @@ -36,31 +63,38 @@ class Circle(center: Pair, start: Pair): Shape(center, start /** * Returns the int coordinates for a circle + * Some coordinates might already be present in the list * @param r - the radius */ - private fun getCircleCoordinates(r: Int): HashSet> { + private fun getCircleCoordinates(r: Int): ArrayList> { val coords = ArrayList>() val segCoords = getSegment(r) - coords.addAll(segCoords) - for (step in 0..7) { + coords.addAll(segCoords.reversed()) + for (step in 1..7) { + val tmpSeg = ArrayList>() for (pos in segCoords) { - coords.add(when (step) { - 0 -> pos - 1 -> Pair(pos.second, pos.first) - 2 -> Pair(pos.first, -pos.second) - 3 -> Pair(-pos.second, pos.first) + val coord = when (step) { + 1 -> Pair(pos.first, -pos.second) + 2 ->Pair(pos.second, -pos.first) + 3 -> Pair(-pos.second, -pos.first) 4 -> Pair(-pos.first, -pos.second) - 5 -> Pair(-pos.second, -pos.first) - 6 -> Pair(-pos.first, pos.second) - 7 -> Pair(pos.second, -pos.first) + 5 -> Pair(-pos.first, pos.second) + 6 -> Pair(-pos.second, pos.first) + 7 -> Pair(pos.second, pos.first) else -> pos - }) + } + if (coord !in coords) { + tmpSeg.add(coord) + } + } + if (step % 2 == 0) { + coords.addAll(tmpSeg.reversed()) + } else { + coords.addAll(tmpSeg) } } - val set = HashSet>() - set.addAll(coords) - return set + return coords } /** diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt index 0c5c365..22d3902 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Shape.kt @@ -1,11 +1,37 @@ package net.trivernis.chunkmaster.lib.shapes -abstract class Shape(protected val center: Pair, start: Pair) { +import net.trivernis.chunkmaster.lib.dynmap.ExtendedMarkerSet +import net.trivernis.chunkmaster.lib.dynmap.MarkerStyle +import javax.xml.stream.Location + +abstract class Shape(protected val center: Pair, start: Pair, radius: Int) { protected var currentPos = start + protected var radius = radius + private set var count = 0 /** * Returns the next value */ abstract fun next(): Pair + + /** + * If the shape can provide a next value + */ + abstract fun endReached(): Boolean + + /** + * Returns the progress of the shape + */ + abstract fun progress(): Double + + /** + * Returns the current radius + */ + abstract fun currentRadius(): Int + + /** + * returns a poly marker for the shape + */ + abstract fun getShapeEdgeLocations(): List> } \ No newline at end of file diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt index 8a70f5b..47afefb 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt @@ -1,18 +1,34 @@ package net.trivernis.chunkmaster.lib.shapes +import kotlin.math.PI import kotlin.math.abs +import kotlin.math.pow +import kotlin.math.sqrt -class Spiral(center: Pair, start: Pair): Shape(center, start) { +class Spiral(center: Pair, start: Pair, radius: Int): Shape(center, start, radius) { private var direction = 0 + override fun endReached(): Boolean { + val distances = getDistances(center, currentPos) + return radius > 0 && (distances.first > radius || distances.second > radius) + } + + override fun progress(): Double { + return (currentRadius()*2).toDouble().pow(2) / (radius * 2).toDouble().pow(2) + } + + override fun currentRadius(): Int { + val distances = getDistances(center, currentPos) + return distances.first.coerceAtLeast(distances.second) + } + /** * Returns the next value in the spiral */ override fun next(): Pair { if (count == 0 && currentPos != center) { - // simulate the spiral to get the correct direction - // TODO: Improve performance of this workaround (replace it with acutal stuff) - val simSpiral = Spiral(center, center) + // simulate the spiral to get the correct direction and count + val simSpiral = Spiral(center, center, radius) while (simSpiral.next() != currentPos); direction = simSpiral.direction count = simSpiral.count @@ -53,6 +69,14 @@ class Spiral(center: Pair, start: Pair): Shape(center, start return currentPos } + override fun getShapeEdgeLocations(): List> { + val a = Pair(this.radius + center.first, this.radius + center.second) + val b = Pair(this.radius + center.first, -this.radius + center.second) + val c = Pair(-this.radius + center.first, -this.radius + center.second) + val d = Pair(-this.radius + center.first, this.radius + center.second) + return listOf(a, b, c, d, a) + } + /** * Returns the distances between 2 coordinates */ diff --git a/src/main/resources/i18n/DEFAULT.i18n.properties b/src/main/resources/i18n/DEFAULT.i18n.properties index fac0f79..3b9bb3c 100644 --- a/src/main/resources/i18n/DEFAULT.i18n.properties +++ b/src/main/resources/i18n/DEFAULT.i18n.properties @@ -11,8 +11,11 @@ TASK_SAVE_FAILED = §cException when saving tasks: %s WORLD_NAME_REQUIRED = §cYou need to provide a world name! WORLD_NOT_FOUND = §cWorld §2%s §cnot found! TASK_ALREADY_EXISTS = §cA task for '%s' already exists! -TASK_CREATION_SUCCESS = §9Generation Task for world §2%s §9 until §2%s §9successfully created! +TASK_CREATION_SUCCESS = §9Generation Task for world §2%s§9 §2%s§9 and shape %s successfully created! +TASK_UNIT_WORLDBORDER = until world border +TASK_UNIT_RADIUS = with a radius of %s TASK_ID_REQUIRED = §cYou need to provide a task id! +INVALID_ARGUMENT = §cInvalid argument at %s: %s! PAUSED_TASKS_HEADER = Currently Paused Generation Tasks TASKS_ENTRY = - §9#%d§r - §2%s§r - §2%d chunks %s§r diff --git a/src/main/resources/i18n/de.i18n.properties b/src/main/resources/i18n/de.i18n.properties index 1307e88..e30787d 100644 --- a/src/main/resources/i18n/de.i18n.properties +++ b/src/main/resources/i18n/de.i18n.properties @@ -11,8 +11,11 @@ TASK_SAVE_FAILED = §cFehler beim Speichern der Aufgaben: %s WORLD_NAME_REQUIRED = §cDu musst einen Weltennamen angeben! WORLD_NOT_FOUND = §c Die Welt §2%s §cwurde nicht gefunden! TASK_ALREADY_EXISTS = §cEs existiert bereits eine Aufgabe für §2%s§c! -TASK_CREATION_SUCCESS = §9Generierungs-Aufgabe §2%s §9 bis §2%s §9wurde erfolgreich erstellt! +TASK_CREATION_SUCCESS = §9Generierungs-Aufgabe §2%s§9 §2%s§9 in der Form %s wurde erfolgreich erstellt! +TASK_UNIT_WORLDBORDER = bis zur World-Border +TASK_UNIT_RADIUS = mit einem Radius von %s TASK_ID_REQUIRED = §cDu musst eine Aufgaben-Id angeben! +INVALID_ARGUMENT = §cFalscher Parameter an Stelle %s: %s! PAUSED_TASKS_HEADER = §lPausierte Generierungsaufgaben§r diff --git a/src/main/resources/i18n/en.i18n.properties b/src/main/resources/i18n/en.i18n.properties index fac0f79..3b9bb3c 100644 --- a/src/main/resources/i18n/en.i18n.properties +++ b/src/main/resources/i18n/en.i18n.properties @@ -11,8 +11,11 @@ TASK_SAVE_FAILED = §cException when saving tasks: %s WORLD_NAME_REQUIRED = §cYou need to provide a world name! WORLD_NOT_FOUND = §cWorld §2%s §cnot found! TASK_ALREADY_EXISTS = §cA task for '%s' already exists! -TASK_CREATION_SUCCESS = §9Generation Task for world §2%s §9 until §2%s §9successfully created! +TASK_CREATION_SUCCESS = §9Generation Task for world §2%s§9 §2%s§9 and shape %s successfully created! +TASK_UNIT_WORLDBORDER = until world border +TASK_UNIT_RADIUS = with a radius of %s TASK_ID_REQUIRED = §cYou need to provide a task id! +INVALID_ARGUMENT = §cInvalid argument at %s: %s! PAUSED_TASKS_HEADER = Currently Paused Generation Tasks TASKS_ENTRY = - §9#%d§r - §2%s§r - §2%d chunks %s§r diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 196281a..15dbfb0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -13,7 +13,7 @@ commands: description: Main command permission: chunkmaster.chunkmaster usage: | - / generate [, ] - generates chunks starting from the spawn until the chunk-count is reached + / 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 From 0347730580e0dd67bafa38d6c13c9785cd375257 Mon Sep 17 00:00:00 2001 From: trivernis Date: Mon, 13 Apr 2020 21:31:26 +0200 Subject: [PATCH 05/20] Improve performance of periodical chunk progress saving task --- .../trivernis/chunkmaster/lib/generation/GenerationManager.kt | 4 ++-- .../trivernis/chunkmaster/lib/generation/GenerationTask.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 af94091..cb82eb4 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -307,8 +307,8 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server percentage, eta, chunkSpeed!!, - genTask.lastChunk.x, - genTask.lastChunk.z)) + genTask.lastChunkCoords.x, + genTask.lastChunkCoords.z)) saveProgressToDatabase(genTask.lastChunkCoords, task.id) genTask.updateLastChunkMarker() } catch (error: Exception) { 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 50b6447..9178372 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -116,8 +116,8 @@ abstract class GenerationTask( markerSet?.creUpdateAreMarker( markerLastId, markerLastName, - this.lastChunk.getBlock(0, 0, 0).location, - this.lastChunk.getBlock(15, 0, 15).location, + this.lastChunkCoords.getCenterLocation(world).chunk.getBlock(0, 0, 0).location, + this.lastChunkCoords.getCenterLocation(world).chunk.getBlock(15, 0, 15).location, markerLastStyle ) } From 2b121b67fd608b5524bd3beb368a0559d1ede098 Mon Sep 17 00:00:00 2001 From: trivernis Date: Mon, 13 Apr 2020 21:43:14 +0200 Subject: [PATCH 06/20] Fix generation stopping one chunk too early --- .../chunkmaster/lib/generation/GenerationTaskPaper.kt | 4 ++-- .../lib/generation/GenerationTaskSpigot.kt | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) 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 73915c6..41549c5 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -48,13 +48,13 @@ class GenerationTaskPaper( if (!world.isChunkGenerated(chunk.x, chunk.z)) { for (i in 0 until chunksPerStep) { - if (borderReachedCheck()) break + if (borderReached()) break if (!world.isChunkGenerated(chunk.x, chunk.z)) { pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true)) } chunk = nextChunkCoordinates } - if (!borderReachedCheck() && !world.isChunkGenerated(chunk.x, chunk.z)) { + if (!world.isChunkGenerated(chunk.x, chunk.z)) { pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true)) } } 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 bf60f9a..836edc5 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -36,17 +36,16 @@ class GenerationTaskSpigot( if (!world.isChunkGenerated(chunk.x, chunk.z)) { for (i in 0 until minOf(chunksPerStep, radius - shape.currentRadius())) { - if (borderReachedCheck()) break + if (borderReached()) break val chunkInstance = world.getChunkAt(chunk.x, chunk.z) chunkInstance.load(true) loadedChunks.add(chunkInstance) chunk = nextChunkCoordinates } - if (!borderReachedCheck()) { - val chunkInstance = world.getChunkAt(chunk.x, chunk.z) - chunkInstance.load(true) - loadedChunks.add(chunkInstance) - } + val chunkInstance = world.getChunkAt(chunk.x, chunk.z) + chunkInstance.load(true) + loadedChunks.add(chunkInstance) + } lastChunkCoords = chunk count = shape.count // set the count to the more accurate spiral count From be130adc6fed907c4c9b2bddc552edf15d76c38b Mon Sep 17 00:00:00 2001 From: trivernis Date: Tue, 14 Apr 2020 22:34:31 +0200 Subject: [PATCH 07/20] Improve spigot chunk generation Add skipping of already generated chunks. An issue remaining is that some chunks are still not generated and the shape doesn't always match. --- .../lib/generation/GenerationManager.kt | 2 +- .../lib/generation/GenerationTask.kt | 14 ++--------- .../lib/generation/GenerationTaskPaper.kt | 12 ++++----- .../lib/generation/GenerationTaskSpigot.kt | 25 ++++++++++++------- 4 files changed, 25 insertions(+), 28 deletions(-) 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 cb82eb4..509d910 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationManager.kt @@ -351,7 +351,7 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server return if (PaperLib.isPaper()) { GenerationTaskPaper(chunkmaster, world, start, radius, shape) } else { - GenerationTaskSpigot(chunkmaster, world, center, start, radius, shape) + GenerationTaskSpigot(chunkmaster, world, start, radius, shape) } } } \ 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 9178372..539a8da 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt @@ -55,17 +55,6 @@ abstract class GenerationTask( return ChunkCoordinates(nextChunkCoords.first, nextChunkCoords.second) } - val lastChunk: Chunk - get() { - return world.getChunkAt(lastChunkCoords.x, lastChunkCoords.z) - } - - 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. */ @@ -126,7 +115,7 @@ abstract class GenerationTask( /** * Handles the invocation of the end reached callback and additional logic */ - protected fun setEndReached() { + private fun setEndReached() { endReached = true count = shape.count endReachedCallback?.invoke(this) @@ -140,6 +129,7 @@ abstract class GenerationTask( protected fun borderReachedCheck(): Boolean { val done = borderReached() if (done) { + unloadLoadedChunks() setEndReached() } return done 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 41549c5..a349c07 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -26,19 +26,19 @@ class GenerationTaskPaper( } /** - * Runs the generation task. Every Iteration the next chunk will be generated if - * it hasn't been generated already. - * After 10 chunks have been generated, they will all be unloaded and saved. + * Runs the generation task. Every Iteration the next chunks will be generated if + * they haven't been generated already + * After a configured number of chunks chunks have been generated, they will all be unloaded and saved. */ override fun run() { - if (plugin.mspt < msptThreshold) { // pause when tps < 2 + if (plugin.mspt < msptThreshold) { if (loadedChunks.size > maxLoadedChunks) { unloadLoadedChunks() - } else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait. + } else if (pendingChunks.size < maxPendingChunks) { if (borderReachedCheck()) return var chunk = nextChunkCoordinates - for (i in 1 until chunkSkips) { + for (i in 0 until chunkSkips) { if (world.isChunkGenerated(chunk.x, chunk.z)) { chunk = nextChunkCoordinates } else { 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 836edc5..8e3b64a 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -6,8 +6,9 @@ import org.bukkit.World import java.lang.Exception class GenerationTaskSpigot( - private val plugin: Chunkmaster, override val world: World, - centerChunk: ChunkCoordinates, private val startChunk: ChunkCoordinates, + private val plugin: Chunkmaster, + override val world: World, + startChunk: ChunkCoordinates, override val radius: Int = -1, shape: Shape ) : GenerationTask(plugin, startChunk, shape) { @@ -21,21 +22,28 @@ class GenerationTaskSpigot( } /** - * Runs the generation task. Every Iteration the next chunk will be generated if - * it hasn't been generated already. - * After 10 chunks have been generated, they will all be unloaded and saved. + * Runs the generation task. Every Iteration the next chunks will be generated if + * they haven't been generated already + * After a configured number of chunks chunks have been generated, they will all be unloaded and saved. */ override fun run() { - if (plugin.mspt < msptThreshold) { // pause when tps < 2 + if (plugin.mspt < msptThreshold) { if (loadedChunks.size > maxLoadedChunks) { unloadLoadedChunks() } else { if (borderReachedCheck()) return var chunk = nextChunkCoordinates + for (i in 0 until chunkSkips) { + if (world.isChunkGenerated(chunk.x, chunk.z)) { + chunk = nextChunkCoordinates + } else { + break + } + } if (!world.isChunkGenerated(chunk.x, chunk.z)) { - for (i in 0 until minOf(chunksPerStep, radius - shape.currentRadius())) { + for (i in 0 until chunksPerStep) { if (borderReached()) break val chunkInstance = world.getChunkAt(chunk.x, chunk.z) chunkInstance.load(true) @@ -45,10 +53,9 @@ class GenerationTaskSpigot( val chunkInstance = world.getChunkAt(chunk.x, chunk.z) chunkInstance.load(true) loadedChunks.add(chunkInstance) - } lastChunkCoords = chunk - count = shape.count // set the count to the more accurate spiral count + count = shape.count } } } From c0909770212011f1b5957d5cb9cd18b47d3043c4 Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 16 Apr 2020 20:56:53 +0200 Subject: [PATCH 08/20] Revert optimizations on spigot Revert the optimizations which check if the chunk is already generated because the function doesn't report the right value. https://hub.spigotmc.org/jira/browse/SPIGOT-5541?attachmentOrder=desc --- .../lib/generation/GenerationTaskPaper.kt | 2 +- .../lib/generation/GenerationTaskSpigot.kt | 23 ++++++------------- .../chunkmaster/lib/shapes/Circle.kt | 3 +++ 3 files changed, 11 insertions(+), 17 deletions(-) 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 a349c07..5e8d92f 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskPaper.kt @@ -59,7 +59,7 @@ class GenerationTaskPaper( } } lastChunkCoords = chunk - count = shape.count // set the count to the more accurate spiral count + count = shape.count } } checkChunksLoaded() 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 8e3b64a..5dfbd10 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTaskSpigot.kt @@ -34,26 +34,17 @@ class GenerationTaskSpigot( if (borderReachedCheck()) return var chunk = nextChunkCoordinates - for (i in 0 until chunkSkips) { - if (world.isChunkGenerated(chunk.x, chunk.z)) { - chunk = nextChunkCoordinates - } else { - break - } - } - - if (!world.isChunkGenerated(chunk.x, chunk.z)) { - for (i in 0 until chunksPerStep) { - if (borderReached()) break - val chunkInstance = world.getChunkAt(chunk.x, chunk.z) - chunkInstance.load(true) - loadedChunks.add(chunkInstance) - chunk = nextChunkCoordinates - } + for (i in 0 until chunksPerStep) { + if (borderReached()) break val chunkInstance = world.getChunkAt(chunk.x, chunk.z) chunkInstance.load(true) loadedChunks.add(chunkInstance) + chunk = nextChunkCoordinates } + val chunkInstance = world.getChunkAt(chunk.x, chunk.z) + chunkInstance.load(true) + loadedChunks.add(chunkInstance) + lastChunkCoords = chunk count = shape.count } diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt index 90bc9de..19aa335 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt @@ -35,6 +35,9 @@ class Circle(center: Pair, start: Pair, radius: Int): Shape( } override fun next(): Pair { + if (endReached()) { + return currentPos + } if (count == 0 && currentPos != center) { val tmpCircle = Circle(center, center, radius) while (tmpCircle.next() != currentPos); From 03eaf52dc3a5d49d247818cb435ef4559a9449f0 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 10:43:12 +0200 Subject: [PATCH 09/20] Add more comments --- .../kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt | 7 +++++++ .../kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt index 19aa335..be03db5 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Circle.kt @@ -28,12 +28,19 @@ class Circle(center: Pair, start: Pair, radius: Int): Shape( return r } + /** + * Returns the edge locations of the shape to be used + * with dynmap markers + */ override fun getShapeEdgeLocations(): List> { val locations = this.getCircleCoordinates(this.radius) locations.add(locations.first()) return locations.map{ Pair(it.first + center.first, it.second + center.second) } } + /** + * Returns the next coordinate of the circle until the end is reached + */ override fun next(): Pair { if (endReached()) { return currentPos diff --git a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt index 47afefb..75ee564 100644 --- a/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt +++ b/src/main/kotlin/net/trivernis/chunkmaster/lib/shapes/Spiral.kt @@ -69,6 +69,9 @@ class Spiral(center: Pair, start: Pair, radius: Int): Shape( return currentPos } + /** + * Returns the edges to be used with dynmap markers + */ override fun getShapeEdgeLocations(): List> { val a = Pair(this.radius + center.first, this.radius + center.second) val b = Pair(this.radius + center.first, -this.radius + center.second) From b06018ec0d44c79cb1337cf11164c529e7a45d92 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:16:43 +0200 Subject: [PATCH 10/20] Add abstruse ci config --- .abstruse.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .abstruse.yml diff --git a/.abstruse.yml b/.abstruse.yml new file mode 100644 index 0000000..d986460 --- /dev/null +++ b/.abstruse.yml @@ -0,0 +1,13 @@ +image: openjdk:8-jdk + +matrix: + - env: SCRIPT=shadowJar + +before_install: + - apt update + +install: + - apt install -y gradle + +script: + - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi \ No newline at end of file From 72618e3e50506716ae53e6102a073d7b77d8fecb Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:17:46 +0200 Subject: [PATCH 11/20] Change version of image for ci --- .abstruse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.abstruse.yml b/.abstruse.yml index d986460..7a28d58 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -1,4 +1,4 @@ -image: openjdk:8-jdk +image: openjdk:8 matrix: - env: SCRIPT=shadowJar From bd570874270c694b08341052f3ee5ef825ce0836 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:18:26 +0200 Subject: [PATCH 12/20] Remove openjdk version tag --- .abstruse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.abstruse.yml b/.abstruse.yml index 7a28d58..c4395fd 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -1,4 +1,4 @@ -image: openjdk:8 +image: openjdk matrix: - env: SCRIPT=shadowJar From dc802f9e0080d0dbbff4401667f15ed786ba0695 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:20:21 +0200 Subject: [PATCH 13/20] Change to default docker and add jdk to install --- .abstruse.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.abstruse.yml b/.abstruse.yml index c4395fd..ab131a7 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -1,4 +1,4 @@ -image: openjdk +image: abstruse matrix: - env: SCRIPT=shadowJar @@ -7,6 +7,7 @@ before_install: - apt update install: + - apt install -y openjdk-8-jdk - apt install -y gradle script: From d52bc304f49aa7889f4564b6c4e0bc5f2cedd1a7 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:29:21 +0200 Subject: [PATCH 14/20] Rever to openjdk image I've read it wrong lol --- .abstruse.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.abstruse.yml b/.abstruse.yml index ab131a7..c4395fd 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -1,4 +1,4 @@ -image: abstruse +image: openjdk matrix: - env: SCRIPT=shadowJar @@ -7,7 +7,6 @@ before_install: - apt update install: - - apt install -y openjdk-8-jdk - apt install -y gradle script: From b587f491cf20d45a77d0c5f14abf063d506a9eb6 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:30:15 +0200 Subject: [PATCH 15/20] Remove gradle install instructions from buildfile --- .abstruse.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.abstruse.yml b/.abstruse.yml index c4395fd..eba9e50 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -3,11 +3,5 @@ image: openjdk matrix: - env: SCRIPT=shadowJar -before_install: - - apt update - -install: - - apt install -y gradle - script: - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi \ No newline at end of file From 3cfa38e03dabeaccbe1877371df56ef53a8602c1 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:45:56 +0200 Subject: [PATCH 16/20] Add .gradle to cache to speed up building --- .abstruse.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.abstruse.yml b/.abstruse.yml index eba9e50..1aece27 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -4,4 +4,7 @@ matrix: - env: SCRIPT=shadowJar script: - - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi \ No newline at end of file + - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi + +cache: + - .gradle \ No newline at end of file From 3367af9adc08c10b60765d662d8522457d530235 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:50:21 +0200 Subject: [PATCH 17/20] Create .gradle dir before installation Create .gradle directory to avoid errors when unpacking cached files (I hope this helps). --- .abstruse.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.abstruse.yml b/.abstruse.yml index 1aece27..cc96e22 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -3,6 +3,9 @@ image: openjdk matrix: - env: SCRIPT=shadowJar +before_install: + - mkdir .gradle + script: - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi From ac3c068f5d2b6cd80806d7cba093ea8feca20c1a Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:55:27 +0200 Subject: [PATCH 18/20] Add dependency resolving to install task --- .abstruse.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.abstruse.yml b/.abstruse.yml index cc96e22..c2d3f3b 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -6,6 +6,9 @@ matrix: before_install: - mkdir .gradle +install: + - gradle dependencies + script: - if [[ "SCRIPT" ]]; then gradle $SCRIPT; fi From a377392fd250d3a6e4f219286b958f63ae4a23ed Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 11:56:11 +0200 Subject: [PATCH 19/20] Remove creation of .gradle directory due to errors --- .abstruse.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.abstruse.yml b/.abstruse.yml index c2d3f3b..657aa34 100644 --- a/.abstruse.yml +++ b/.abstruse.yml @@ -3,9 +3,6 @@ image: openjdk matrix: - env: SCRIPT=shadowJar -before_install: - - mkdir .gradle - install: - gradle dependencies From a6d5462433f3f656ff2096a891cdc29e71e7113c Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 19 Apr 2020 12:06:22 +0200 Subject: [PATCH 20/20] Add abstruse badge to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a281f65..12a682e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# chunkmaster +# chunkmaster ![](https://abstruse.trivernis.net/badge/1) This plugin can be used to pre-generate the region of a world around the spawn chunk(s). The generation automatically pauses when a player joins the server (assuming the server was empty before)