Merge pull request #15 from Trivernis/develop

Fixes and changes to the sql structure
pull/23/head v0.13-beta
Trivernis 5 years ago committed by GitHub
commit f1ad4473de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,6 @@
# chunkmaster [![CircleCI](https://circleci.com/gh/Trivernis/spigot-chunkmaster.svg?style=svg)](https://circleci.com/gh/Trivernis/spigot-chunkmaster) # chunkmaster
This plugin can be used to pre-generate the region of a world around the spawn chunk. 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) The generation automatically pauses when a player joins the server (assuming the server was empty before)
and resumes when the server is empty again. The generation also auto-resumes after a server and resumes when the server is empty again. The generation also auto-resumes after a server
restart. The plugin tracks the ticks per second and pauses the generation when the tps restart. The plugin tracks the ticks per second and pauses the generation when the tps
@ -23,6 +23,11 @@ All features can be accessed with the command `/chunkmaster` or the aliases `/ch
```yaml ```yaml
generation: generation:
# If set to true the plugin ignores the vanilla world border and doesn't stop
# the chunk generation when reaching it.
# The value should be a boolean <true/false>
ignore-worldborder: false
# The maximum amount of chunks that are loaded before unloading and saving them. # The maximum amount of chunks that are loaded before unloading and saving them.
# Higher values mean higher generation speed but greater memory usage. # Higher values mean higher generation speed but greater memory usage.
# The value should be a positive integer. # The value should be a positive integer.

@ -22,7 +22,7 @@ idea {
} }
group "net.trivernis" group "net.trivernis"
version "0.12-beta" version "0.13-beta"
sourceCompatibility = 1.8 sourceCompatibility = 1.8
@ -48,7 +48,8 @@ dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
testCompile group: 'junit', name: 'junit', version: '4.12' testCompile group: 'junit', name: 'junit', version: '4.12'
compileOnly "org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT" //compileOnly "org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT"
compileOnly "com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT"
compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0' compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0'
compile "io.papermc:paperlib:1.0.2" compile "io.papermc:paperlib:1.0.2"
compile "org.bstats:bstats-bukkit:1.5" compile "org.bstats:bstats-bukkit:1.5"

@ -3,20 +3,17 @@ package net.trivernis.chunkmaster
import io.papermc.lib.PaperLib import io.papermc.lib.PaperLib
import net.trivernis.chunkmaster.commands.* import net.trivernis.chunkmaster.commands.*
import net.trivernis.chunkmaster.lib.generation.GenerationManager import net.trivernis.chunkmaster.lib.generation.GenerationManager
import net.trivernis.chunkmaster.lib.SqlUpdateManager import net.trivernis.chunkmaster.lib.SqliteManager
import org.bstats.bukkit.Metrics import org.bstats.bukkit.Metrics
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scheduler.BukkitTask import org.bukkit.scheduler.BukkitTask
import java.lang.Exception import java.lang.Exception
import java.sql.Connection
import java.sql.DriverManager
class Chunkmaster: JavaPlugin() { class Chunkmaster: JavaPlugin() {
lateinit var sqliteConnection: Connection lateinit var sqliteManager: SqliteManager
var dbname: String? = null
lateinit var generationManager: GenerationManager lateinit var generationManager: GenerationManager
private lateinit var tpsTask: BukkitTask private lateinit var tpsTask: BukkitTask
var mspt = 50L // keep track of the milliseconds per tick var mspt = 20 // keep track of the milliseconds per tick
private set private set
/** /**
@ -37,13 +34,19 @@ class Chunkmaster: JavaPlugin() {
server.pluginManager.registerEvents(ChunkmasterEvents(this, server), this) server.pluginManager.registerEvents(ChunkmasterEvents(this, server), this)
if (PaperLib.isPaper() && PaperLib.getMinecraftPatchVersion() >= 225) {
tpsTask = server.scheduler.runTaskTimer(this, Runnable {
mspt = 1000/server.currentTick // use papers exposed tick rather than calculating it
}, 1, 300)
} else {
tpsTask = server.scheduler.runTaskTimer(this, Runnable { tpsTask = server.scheduler.runTaskTimer(this, Runnable {
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
server.scheduler.runTaskLater(this, Runnable { server.scheduler.runTaskLater(this, Runnable {
mspt = System.currentTimeMillis() - start mspt = (System.currentTimeMillis() - start).toInt()
}, 1) }, 1)
}, 1, 300) }, 1, 300)
} }
}
/** /**
* Stop all tasks and close database connection on disable * Stop all tasks and close database connection on disable
@ -51,7 +54,6 @@ class Chunkmaster: JavaPlugin() {
override fun onDisable() { override fun onDisable() {
logger.info("Stopping all generation tasks...") logger.info("Stopping all generation tasks...")
generationManager.stopAll() generationManager.stopAll()
sqliteConnection.close()
} }
/** /**
@ -66,6 +68,8 @@ class Chunkmaster: JavaPlugin() {
config.addDefault("generation.pause-on-join", true) config.addDefault("generation.pause-on-join", true)
config.addDefault("generation.max-pending-chunks", 10) config.addDefault("generation.max-pending-chunks", 10)
config.addDefault("generation.max-loaded-chunks", 10) config.addDefault("generation.max-loaded-chunks", 10)
config.addDefault("generation.ignore-worldborder", false)
config.addDefault("database.filename", "chunkmaster.db")
config.options().copyDefaults(true) config.options().copyDefaults(true)
saveConfig() saveConfig()
} }
@ -76,13 +80,8 @@ class Chunkmaster: JavaPlugin() {
private fun initDatabase() { private fun initDatabase() {
logger.info("Initializing Database...") logger.info("Initializing Database...")
try { try {
Class.forName("org.sqlite.JDBC") this.sqliteManager = SqliteManager( this)
sqliteConnection = DriverManager.getConnection("jdbc:sqlite:${dataFolder.absolutePath}/chunkmaster.db") sqliteManager.init()
logger.info("Database connection established.")
val updateManager = SqlUpdateManager(sqliteConnection, this)
updateManager.checkUpdate()
updateManager.performUpdate()
logger.info("Database fully initialized.") logger.info("Database fully initialized.")
} catch(e: Exception) { } catch(e: Exception) {
logger.warning("Failed to init database: ${e.message}") logger.warning("Failed to init database: ${e.message}")

@ -52,17 +52,4 @@ class ChunkmasterEvents(private val chunkmaster: Chunkmaster, private val server
} }
} }
} }
/**
* Unload all chunks before a save.
*/
@EventHandler
fun onWorldSave(event: WorldSaveEvent) {
val task = chunkmaster.generationManager.tasks.find { it.generationTask.world == event.world }
if (task != null) {
if (task.generationTask is GenerationTaskPaper) {
task.generationTask.unloadAllChunks()
}
}
}
} }

@ -1,79 +0,0 @@
package net.trivernis.chunkmaster.lib
import net.trivernis.chunkmaster.Chunkmaster
import java.lang.Exception
import java.sql.Connection
class SqlUpdateManager(private val connnection: Connection, private val chunkmaster: Chunkmaster) {
private val tables = listOf(
Pair(
"generation_tasks",
listOf(
Pair("id", "integer PRIMARY KEY AUTOINCREMENT"),
Pair("center_x", "integer NOT NULL DEFAULT 0"),
Pair("center_z", "integer NOT NULL DEFAULT 0"),
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")
)
)
)
private val needUpdate = HashSet<Pair<String, Pair<String, String>>>()
private val needCreation = HashSet<String>()
/**
* Checks which tables need an update or creation.
*/
fun checkUpdate() {
val meta = connnection.metaData
for (table in tables) {
val resTables = meta.getTables(null, null, table.first, null)
if (resTables.next()) { // table exists
for (column in table.second) {
val resColumn = meta.getColumns(null, null, table.first, column.first)
if (!resColumn.next()) {
needUpdate.add(Pair(table.first, column))
}
}
} else {
needCreation.add(table.first)
}
}
}
/**
* Creates or updates tables that needed an update.
*/
fun performUpdate() {
for (table in needCreation) {
try {
var tableDef = "CREATE TABLE IF NOT EXISTS $table ("
for (column in tables.find{it.first == table}!!.second) {
tableDef += "${column.first} ${column.second},"
}
tableDef = tableDef.substringBeforeLast(",") + ");"
chunkmaster.logger.info("Creating table $table with definition $tableDef")
val stmt = connnection.prepareStatement(tableDef)
stmt.execute()
stmt.close()
} catch (err: Exception) {
chunkmaster.logger.severe("Error creating table $table.")
}
}
for (table in needUpdate) {
val updateSql = "ALTER TABLE ${table.first} ADD COLUMN ${table.second.first} ${table.second.second}"
try {
val stmt = connnection.prepareStatement(updateSql)
stmt.execute()
stmt.close()
chunkmaster.logger.info("Updated table ${table.first} with sql $updateSql")
} catch (e: Exception) {
chunkmaster.logger.severe("Failed to update table ${table.first} with sql $updateSql")
}
}
}
}

@ -0,0 +1,137 @@
package net.trivernis.chunkmaster.lib
import net.trivernis.chunkmaster.Chunkmaster
import org.apache.commons.lang.exception.ExceptionUtils
import org.sqlite.SQLiteConnection
import java.lang.Exception
import java.sql.Connection
import java.sql.DriverManager
import java.sql.PreparedStatement
import java.sql.ResultSet
class SqliteManager(private val chunkmaster: Chunkmaster) {
private val tables = listOf(
Pair(
"generation_tasks",
listOf(
Pair("id", "integer PRIMARY KEY AUTOINCREMENT"),
Pair("center_x", "integer NOT NULL DEFAULT 0"),
Pair("center_z", "integer NOT NULL DEFAULT 0"),
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")
)
)
)
private val needUpdate = HashSet<Pair<String, Pair<String, String>>>()
private val needCreation = HashSet<String>()
/**
* Returns the connection to the database
*/
fun getConnection(): Connection? {
try {
Class.forName("org.sqlite.JDBC")
return DriverManager.getConnection("jdbc:sqlite:${chunkmaster.dataFolder.absolutePath}/" +
"${chunkmaster.config.getString("database.filename")}")
} catch (e: Exception) {
chunkmaster.logger.severe("Could not get database connection.")
chunkmaster.logger.severe(e.message)
}
return null
}
/**
* Checks for and performs an update
*/
fun init() {
this.checkUpdate()
this.performUpdate()
}
/**
* Checks which tables need an update or creation.
*/
private fun checkUpdate() {
val meta = getConnection()!!.metaData
for (table in tables) {
val resTables = meta.getTables(null, null, table.first, null)
if (resTables.next()) { // table exists
for (column in table.second) {
val resColumn = meta.getColumns(null, null, table.first, column.first)
if (!resColumn.next()) {
needUpdate.add(Pair(table.first, column))
}
resColumn.close()
}
} else {
needCreation.add(table.first)
}
resTables.close()
}
}
/**
* Executes a sql statement on the database.
*/
fun executeStatement(sql: String, values: HashMap<Int, Any>, callback: ((ResultSet) -> Unit)?) {
val connection = getConnection()
if (connection != null) {
try {
val statement = connection.prepareStatement(sql)
for (parameterValue in values) {
statement.setObject(parameterValue.key, parameterValue.value)
}
statement.execute()
val res = statement.resultSet
if (callback != null) {
callback(res)
}
statement.close()
} catch (e: Exception) {
chunkmaster.logger.severe("An error occured on sql $sql. ${e.message}")
chunkmaster.logger.info(ExceptionUtils.getStackTrace(e))
} finally {
connection.close()
}
} else {
chunkmaster.logger.severe("Could not execute sql $sql. No database connection established.")
}
}
/**
* Creates or updates tables that needed an update.
*/
private fun performUpdate() {
for (table in needCreation) {
try {
var tableDef = "CREATE TABLE IF NOT EXISTS $table ("
for (column in tables.find{it.first == table}!!.second) {
tableDef += "${column.first} ${column.second},"
}
tableDef = tableDef.substringBeforeLast(",") + ");"
chunkmaster.logger.info("Creating table $table with definition $tableDef")
executeStatement(tableDef, HashMap(), null)
} catch (e: Exception) {
chunkmaster.logger.severe("Error creating table $table.")
chunkmaster.logger.severe(e.message)
chunkmaster.logger.info(ExceptionUtils.getStackTrace(e))
}
}
for (table in needUpdate) {
val updateSql = "ALTER TABLE ${table.first} ADD COLUMN ${table.second.first} ${table.second.second}"
try {
executeStatement(updateSql, HashMap(), null)
chunkmaster.logger.info("Updated table ${table.first} with sql $updateSql")
} catch (e: Exception) {
chunkmaster.logger.severe("Failed to update table ${table.first} with sql $updateSql")
chunkmaster.logger.severe(e.message)
chunkmaster.logger.info(ExceptionUtils.getStackTrace(e))
}
}
}
}

@ -2,11 +2,8 @@ package net.trivernis.chunkmaster.lib.generation
import io.papermc.lib.PaperLib import io.papermc.lib.PaperLib
import net.trivernis.chunkmaster.Chunkmaster import net.trivernis.chunkmaster.Chunkmaster
import org.bukkit.Chunk
import org.bukkit.Server import org.bukkit.Server
import org.bukkit.World import org.bukkit.World
import java.lang.Exception
import java.lang.NullPointerException
class GenerationManager(private val chunkmaster: Chunkmaster, private val server: Server) { class GenerationManager(private val chunkmaster: Chunkmaster, private val server: Server) {
@ -31,35 +28,37 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server
val centerChunk = ChunkCoordinates(world.spawnLocation.chunk.x, world.spawnLocation.chunk.z) val centerChunk = ChunkCoordinates(world.spawnLocation.chunk.x, world.spawnLocation.chunk.z)
val generationTask = createGenerationTask(world, centerChunk, centerChunk, stopAfter) val generationTask = createGenerationTask(world, centerChunk, centerChunk, stopAfter)
val insertStatement = chunkmaster.sqliteConnection.prepareStatement( chunkmaster.sqliteManager.executeStatement(
""" """
INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, stop_after) INSERT INTO generation_tasks (center_x, center_z, last_x, last_z, world, stop_after)
values (?, ?, ?, ?, ?, ?) values (?, ?, ?, ?, ?, ?)
""" """,
HashMap(
mapOf(
1 to centerChunk.x,
2 to centerChunk.z,
3 to centerChunk.x,
4 to centerChunk.z,
5 to world.name,
6 to stopAfter
)
),
null
) )
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( var id = 0
chunkmaster.sqliteManager.executeStatement(
""" """
SELECT id FROM generation_tasks ORDER BY id DESC LIMIT 1 SELECT id FROM generation_tasks ORDER BY id DESC LIMIT 1
""".trimIndent() """.trimIndent(),
) HashMap()
getIdStatement.execute() ) {
val result = getIdStatement.resultSet it.next()
result.next() id = it.getInt("id")
val id: Int = result.getInt("id") }
insertStatement.close()
getIdStatement.close()
generationTask.onEndReached { generationTask.onEndReached {
chunkmaster.logger.info("Task #${id} finished after ${generationTask.count} chunks.") chunkmaster.logger.info("Task #${id} finished after ${it.count} chunks.")
removeTask(id) removeTask(id)
} }
@ -115,14 +114,13 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server
} }
if (taskEntry != null) { if (taskEntry != null) {
taskEntry.cancel() taskEntry.cancel()
val deleteTask = chunkmaster.sqliteConnection.prepareStatement( chunkmaster.sqliteManager.executeStatement(
""" """
DELETE FROM generation_tasks WHERE id = ?; DELETE FROM generation_tasks WHERE id = ?;
""".trimIndent() """.trimIndent(),
HashMap(mapOf(1 to taskEntry.id)),
null
) )
deleteTask.setInt(1, taskEntry.id)
deleteTask.execute()
deleteTask.close()
if (taskEntry is RunningTaskEntry) { if (taskEntry is RunningTaskEntry) {
if (taskEntry.task.isCancelled) { if (taskEntry.task.isCancelled) {
@ -173,9 +171,8 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server
* Starts all generation tasks. * Starts all generation tasks.
*/ */
fun startAll() { fun startAll() {
val savedTasksStatement = chunkmaster.sqliteConnection.prepareStatement("SELECT * FROM generation_tasks") chunkmaster.sqliteManager.executeStatement("SELECT * FROM generation_tasks", HashMap()) {
savedTasksStatement.execute() val res = it
val res = savedTasksStatement.resultSet
while (res.next()) { while (res.next()) {
try { try {
val id = res.getInt("id") val id = res.getInt("id")
@ -190,7 +187,8 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server
chunkmaster.logger.severe("Failed to load Task ${res.getInt("id")}.") chunkmaster.logger.severe("Failed to load Task ${res.getInt("id")}.")
} }
} }
savedTasksStatement.close() }
if (tasks.isNotEmpty()) { if (tasks.isNotEmpty()) {
chunkmaster.logger.info("${tasks.size} saved tasks loaded.") chunkmaster.logger.info("${tasks.size} saved tasks loaded.")
} }
@ -226,22 +224,21 @@ class GenerationManager(private val chunkmaster: Chunkmaster, private val server
chunkmaster.logger.info( chunkmaster.logger.info(
"""Task #${task.id} running for "${genTask.world.name}". """Task #${task.id} running for "${genTask.world.name}".
|Progress ${task.generationTask.count} chunks |Progress ${task.generationTask.count} chunks
|${if (task.generationTask.stopAfter > 0) "(${"%.2f".format((task.generationTask.count.toDouble() / |${if (task.generationTask.stopAfter > 0) "(${"%.2f".format(
task.generationTask.stopAfter.toDouble()) * 100)}%)" else ""}. (task.generationTask.count.toDouble() /
task.generationTask.stopAfter.toDouble()) * 100
)}%)" else ""}.
| Speed: ${"%.1f".format(task.generationSpeed)} chunks/sec, | Speed: ${"%.1f".format(task.generationSpeed)} chunks/sec,
|Last Chunk: ${genTask.lastChunk.x}, ${genTask.lastChunk.z}""".trimMargin("|").replace('\n', ' ') |Last Chunk: ${genTask.lastChunk.x}, ${genTask.lastChunk.z}""".trimMargin("|").replace('\n', ' ')
) )
val updateStatement = chunkmaster.sqliteConnection.prepareStatement( chunkmaster.sqliteManager.executeStatement(
""" """
UPDATE generation_tasks SET last_x = ?, last_z = ? UPDATE generation_tasks SET last_x = ?, last_z = ?
WHERE id = ? WHERE id = ?
""".trimIndent() """.trimIndent(),
HashMap(mapOf(1 to genTask.lastChunk.x, 2 to genTask.lastChunk.z, 3 to task.id)),
null
) )
updateStatement.setInt(1, genTask.lastChunk.x)
updateStatement.setInt(2, genTask.lastChunk.z)
updateStatement.setInt(3, task.id)
updateStatement.execute()
updateStatement.close()
} catch (error: Exception) { } catch (error: Exception) {
chunkmaster.logger.warning("Exception when saving task progress ${error.message}") chunkmaster.logger.warning("Exception when saving task progress ${error.message}")
} }

@ -24,8 +24,9 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: ChunkCoordinates
protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold") protected val msptThreshold = plugin.config.getLong("generation.mspt-pause-threshold")
protected val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks") protected val maxLoadedChunks = plugin.config.getInt("generation.max-loaded-chunks")
protected val chunksPerStep = plugin.config.getInt("generation.chunks-per-step") protected val chunksPerStep = plugin.config.getInt("generation.chunks-per-step")
protected val ignoreWorldborder = plugin.config.getBoolean("generation.ignore-worldborder")
protected var endReachedCallback: (() -> Unit)? = null protected var endReachedCallback: ((GenerationTask) -> Unit)? = null
private set private set
abstract override fun run() abstract override fun run()
@ -52,13 +53,14 @@ abstract class GenerationTask(plugin: Chunkmaster, centerChunk: ChunkCoordinates
* Checks if the World border or the maximum chunk setting for the task is reached. * Checks if the World border or the maximum chunk setting for the task is reached.
*/ */
protected fun borderReached(): Boolean { protected fun borderReached(): Boolean {
return !world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) || (stopAfter in 1..count) return (!world.worldBorder.isInside(lastChunkCoords.getCenterLocation(world)) && !ignoreWorldborder)
|| (stopAfter in 1..count)
} }
/** /**
* Registers end reached callback * Registers end reached callback
*/ */
fun onEndReached(cb: () -> Unit) { fun onEndReached(cb: (GenerationTask) -> Unit) {
endReachedCallback = cb endReachedCallback = cb
} }
} }

@ -4,7 +4,6 @@ import net.trivernis.chunkmaster.Chunkmaster
import org.bukkit.Chunk import org.bukkit.Chunk
import org.bukkit.World import org.bukkit.World
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import io.papermc.lib.PaperLib
class GenerationTaskPaper( class GenerationTaskPaper(
private val plugin: Chunkmaster, override val world: World, private val plugin: Chunkmaster, override val world: World,
@ -38,28 +37,28 @@ class GenerationTaskPaper(
} else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait. } else if (pendingChunks.size < maxPendingChunks) { // if more than 10 chunks are pending, wait.
if (borderReached()) { if (borderReached()) {
endReached = true endReached = true
endReachedCallback?.invoke() endReachedCallback?.invoke(this)
return return
} }
var chunk = nextChunkCoordinates var chunk = nextChunkCoordinates
for (i in 1 until chunkSkips) { for (i in 1 until chunkSkips) {
if (PaperLib.isChunkGenerated(world, chunk.x, chunk.z)) { if (world.isChunkGenerated(chunk.x, chunk.z)) {
chunk = nextChunkCoordinates chunk = nextChunkCoordinates
} else { } else {
break break
} }
} }
if (!PaperLib.isChunkGenerated(world, chunk.x, chunk.z)) { if (!world.isChunkGenerated(chunk.x, chunk.z)) {
for (i in 0 until minOf(chunksPerStep, (stopAfter - count) - 1)) { for (i in 0 until minOf(chunksPerStep, (stopAfter - count) - 1)) {
if (!PaperLib.isChunkGenerated(world, chunk.x, chunk.z)) { if (!world.isChunkGenerated(chunk.x, chunk.z)) {
pendingChunks.add(PaperLib.getChunkAtAsync(world, chunk.x, chunk.z, true)) pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true))
} }
chunk = nextChunkCoordinates chunk = nextChunkCoordinates
} }
if (!PaperLib.isChunkGenerated(world, chunk.x, chunk.z)) { if (!world.isChunkGenerated(chunk.x, chunk.z)) {
pendingChunks.add(PaperLib.getChunkAtAsync(world, chunk.x, chunk.z, true)) pendingChunks.add(world.getChunkAtAsync(chunk.x, chunk.z, true))
} }
} }
lastChunkCoords = chunk lastChunkCoords = chunk

@ -1,7 +1,6 @@
package net.trivernis.chunkmaster.lib.generation package net.trivernis.chunkmaster.lib.generation
import net.trivernis.chunkmaster.Chunkmaster import net.trivernis.chunkmaster.Chunkmaster
import org.bukkit.Chunk
import org.bukkit.World import org.bukkit.World
class GenerationTaskSpigot( class GenerationTaskSpigot(
@ -33,7 +32,7 @@ class GenerationTaskSpigot(
} else { } else {
if (borderReached()) { if (borderReached()) {
endReached = true endReached = true
endReachedCallback?.invoke() endReachedCallback?.invoke(this)
return return
} }

@ -1,6 +1,6 @@
main: net.trivernis.chunkmaster.Chunkmaster main: net.trivernis.chunkmaster.Chunkmaster
name: Chunkmaster name: Chunkmaster
version: '0.12-beta' version: '0.13-beta'
description: Chunk commands plugin. description: Chunk commands plugin.
author: Trivernis author: Trivernis
website: trivernis.net website: trivernis.net

Loading…
Cancel
Save