You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spigot-chunkmaster/src/main/kotlin/net/trivernis/chunkmaster/lib/generation/GenerationTask.kt

144 lines
4.8 KiB
Kotlin

package net.trivernis.chunkmaster.lib.generation
import net.trivernis.chunkmaster.Chunkmaster
import net.trivernis.chunkmaster.lib.dynmap.*
import net.trivernis.chunkmaster.lib.shapes.Shape
import org.bukkit.World
import kotlin.math.ceil
/**
* Interface for generation tasks.
*/
abstract class GenerationTask(
plugin: Chunkmaster,
val world: World,
protected val unloader: ChunkUnloader,
val startChunk: ChunkCoordinates,
val shape: Shape,
val missingChunks: HashSet<ChunkCoordinates>,
var state: TaskState
) :
Runnable {
abstract val radius: Int
abstract var count: Int
abstract var endReached: Boolean
var isRunning: Boolean = false
var lastChunkCoords = ChunkCoordinates(startChunk.x, startChunk.z)
protected set
protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold")
protected var cancelRun: Boolean = false
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_${world.name}"
private val markerAreaName = "Chunkmaster Generation Area (${ceil(shape.total()).toInt()} chunks)"
private val ignoreWorldborder = plugin.config.getBoolean("generation.ignore-worldborder")
abstract fun generate()
abstract fun validate()
abstract fun generateMissing()
abstract fun cancel()
override fun run() {
isRunning = true
try {
when (state) {
TaskState.GENERATING -> {
this.generate()
if (!cancelRun) {
this.state = TaskState.VALIDATING
this.validate()
}
if (!cancelRun) {
this.state = TaskState.CORRECTING
this.generateMissing()
}
}
TaskState.VALIDATING -> {
this.validate()
if (!cancelRun) {
this.state = TaskState.CORRECTING
this.generateMissing()
}
}
TaskState.CORRECTING -> {
this.generateMissing()
}
else -> {
}
}
if (!cancelRun && this.borderReached()) {
this.setEndReached()
}
} catch (e: InterruptedException) {
}
isRunning = false
}
val nextChunkCoordinates: ChunkCoordinates
get() {
val nextChunkCoords = shape.next()
return ChunkCoordinates(nextChunkCoords.first, nextChunkCoords.second)
}
/**
* Checks if the World border or the maximum chunk setting for the task is reached.
*/
protected fun borderReached(): Boolean {
return (!world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) && !ignoreWorldborder)
|| shape.endReached()
}
/**
* Updates the dynmap marker for the generation radius
*/
protected fun updateGenerationAreaMarker(clear: Boolean = false) {
if (clear) {
markerSet?.deletePolyLineMarker(markerAreaId)
} else if (dynmapIntegration && radius > 0) {
markerSet?.creUpdatePolyLineMarker(
markerAreaId,
markerAreaName,
this.shape.getShapeEdgeLocations()
.map { ChunkCoordinates(it.first, it.second).getCenterLocation(this.world) },
markerAreaStyle
)
}
}
protected fun triggerDynmapRender(chunkCoordinates: ChunkCoordinates) {
if (dynmapIntegration) {
dynmap?.triggerRenderOfVolume(
world.getBlockAt(chunkCoordinates.x * 16, 0, chunkCoordinates.z * 16).location,
world.getBlockAt((chunkCoordinates.x * 16) + 16, 255, (chunkCoordinates.z * 16) + 16).location
)
}
}
/**
* Handles the invocation of the end reached callback and additional logic
*/
private fun setEndReached() {
endReached = true
count = shape.count
updateGenerationAreaMarker(true)
endReachedCallback?.invoke(this)
}
/**
* Registers end reached callback
*/
fun onEndReached(cb: (GenerationTask) -> Unit) {
endReachedCallback = cb
}
}