Archived
0

Add a few development commands. World generation works

This commit is contained in:
Dico200
2018-07-22 20:51:46 +02:00
parent 8a0a77b8ba
commit 9e31ea7e51
6 changed files with 168 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ package io.dico.parcels2
import io.dico.parcels2.math.Vec2i import io.dico.parcels2.math.Vec2i
import io.dico.parcels2.math.floor import io.dico.parcels2.math.floor
import kotlinx.coroutines.experimental.launch import io.dico.parcels2.util.doAwait
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.World import org.bukkit.World
@@ -10,10 +10,11 @@ import org.bukkit.WorldCreator
import org.bukkit.block.Block import org.bukkit.block.Block
import org.bukkit.entity.Entity import org.bukkit.entity.Entity
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.plugin.Plugin
import java.util.* import java.util.*
import kotlin.coroutines.experimental.buildSequence import kotlin.coroutines.experimental.buildSequence
class Worlds { class Worlds(private val plugin: Plugin) {
val worlds: Map<String, ParcelWorld> get() = _worlds val worlds: Map<String, ParcelWorld> get() = _worlds
private val _worlds: MutableMap<String, ParcelWorld> = HashMap() private val _worlds: MutableMap<String, ParcelWorld> = HashMap()
@@ -48,9 +49,26 @@ class Worlds {
_worlds.put(worldName, world) _worlds.put(worldName, world)
if (Bukkit.getWorld(worldName) == null) { if (Bukkit.getWorld(worldName) == null) {
val bworld = WorldCreator(worldName).generator(world.generator).createWorld() plugin.doAwait {
val spawn = world.generator.getFixedSpawnLocation(bworld, null) cond = {
bworld.setSpawnLocation(spawn.x.floor(), spawn.y.floor(), spawn.z.floor()) try {
// server.getDefaultGameMode() throws an error before any worlds are initialized.
// createWorld() below calls that method.
// Plugin needs to load on STARTUP for generators to be registered correctly.
// Means we need to await the initial worlds getting loaded.
plugin.server.defaultGameMode; true
} catch (ex: Throwable) {
false
}
}
onSuccess = {
val bworld = WorldCreator(worldName).generator(world.generator).createWorld()
val spawn = world.generator.getFixedSpawnLocation(bworld, null)
bworld.setSpawnLocation(spawn.x.floor(), spawn.y.floor(), spawn.z.floor())
}
}
} }
} }
@@ -72,8 +90,8 @@ interface ParcelProvider {
} }
class ParcelWorld(val name: String, class ParcelWorld(val name: String,
val options: WorldOptions, val options: WorldOptions,
val generator: ParcelGenerator) : ParcelProvider by generator { val generator: ParcelGenerator) : ParcelProvider by generator {
val world: World by lazy { val world: World by lazy {
val tmp = Bukkit.getWorld(name) val tmp = Bukkit.getWorld(name)
if (tmp == null) { if (tmp == null) {

View File

@@ -1,5 +1,8 @@
package io.dico.parcels2 package io.dico.parcels2
import io.dico.dicore.command.CommandBuilder
import io.dico.dicore.command.EOverridePolicy
import io.dico.dicore.command.ICommandDispatcher
import io.dico.parcels2.storage.Storage import io.dico.parcels2.storage.Storage
import io.dico.parcels2.storage.yamlObjectMapper import io.dico.parcels2.storage.yamlObjectMapper
import io.dico.parcels2.util.tryCreate import io.dico.parcels2.util.tryCreate
@@ -7,7 +10,6 @@ import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.File
import java.util.logging.Level
val logger = LoggerFactory.getLogger("ParcelsPlugin") val logger = LoggerFactory.getLogger("ParcelsPlugin")
@@ -18,28 +20,28 @@ class ParcelsPlugin : JavaPlugin() {
lateinit var options: Options lateinit var options: Options
lateinit var worlds: Worlds lateinit var worlds: Worlds
lateinit var storage: Storage lateinit var storage: Storage
private var cmdDispatcher: ICommandDispatcher? = null
override fun onEnable() { override fun onEnable() {
if (!init()) { if (!init()) {
Bukkit.getPluginManager().disablePlugin(this) Bukkit.getPluginManager().disablePlugin(this)
return
} }
registerCommands()
}
override fun onDisable() {
cmdDispatcher?.unregisterFromCommandMap()
} }
private fun init(): Boolean { private fun init(): Boolean {
optionsFile = File(dataFolder, "options.yml") optionsFile = File(dataFolder, "options.yml")
options = Options() options = Options()
worlds = Worlds() worlds = Worlds(this)
try { try {
if (optionsFile.exists()) { if (!loadOptions()) return false
yamlObjectMapper.readerForUpdating(options).readValue<Options>(optionsFile)
} else if (optionsFile.tryCreate()) {
options.addWorld("plotworld", WorldOptions())
yamlObjectMapper.writeValue(optionsFile, options)
} else {
plogger.error("Failed to save options file ${optionsFile.canonicalPath}")
return false
}
try { try {
storage = options.storage.newStorageInstance() storage = options.storage.newStorageInstance()
@@ -57,4 +59,29 @@ class ParcelsPlugin : JavaPlugin() {
return true return true
} }
fun loadOptions(): Boolean {
if (optionsFile.exists()) {
yamlObjectMapper.readerForUpdating(options).readValue<Options>(optionsFile)
} else if (optionsFile.tryCreate()) {
options.addWorld("plotworld", WorldOptions())
yamlObjectMapper.writeValue(optionsFile, options)
} else {
plogger.error("Failed to save options file ${optionsFile.canonicalPath}")
return false
}
return true
}
private fun registerCommands() {
//@formatting:off
cmdDispatcher = CommandBuilder()
.group("parcel", "plot", "plots", "p")
.registerCommands(PlotCommands(this))
.parent()
.getDispatcher()
//@formatting:on
cmdDispatcher!!.registerToCommandMap("parcels:", EOverridePolicy.FALLBACK_ONLY)
}
} }

View File

@@ -0,0 +1,25 @@
package io.dico.parcels2
import io.dico.dicore.command.CommandException
import io.dico.dicore.command.annotation.Cmd
import org.bukkit.Bukkit
import org.bukkit.entity.Player
class PlotCommands(val plugin: ParcelsPlugin) {
@Cmd("reloadoptions")
fun reloadOptions() {
plugin.loadOptions()
}
@Cmd("tpworld")
fun tpWorld(sender: Player, worldName: String): String {
if (worldName == "list") {
return Bukkit.getWorlds().joinToString("\n- ", "- ", "")
}
val world = Bukkit.getWorld(worldName) ?: throw CommandException("World $worldName is not loaded")
sender.teleport(world.spawnLocation)
return "Teleported you to $worldName spawn"
}
}

View File

@@ -8,8 +8,10 @@ import kotlinx.coroutines.experimental.channels.ProducerScope
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.ReferenceOption import org.jetbrains.exposed.sql.ReferenceOption
import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.* import java.util.*
import javax.sql.DataSource import javax.sql.DataSource
import org.jetbrains.exposed.sql.SchemaUtils.create
object ParcelsTable : Table() { object ParcelsTable : Table() {
val id = integer("id").autoIncrement().primaryKey() val id = integer("id").autoIncrement().primaryKey()
@@ -39,6 +41,9 @@ class ExposedBacking(val dataSource: DataSource) : Backing {
override suspend fun init() { override suspend fun init() {
database = Database.connect(dataSource) database = Database.connect(dataSource)
transaction(database) {
create(ParcelsTable, ParcelsAddedTable)
}
} }
override suspend fun shutdown() { override suspend fun shutdown() {

View File

@@ -0,0 +1,74 @@
package io.dico.parcels2.util
import org.bukkit.plugin.Plugin
import org.bukkit.scheduler.BukkitTask
inline fun Plugin.doAwait(checkNow: Boolean = true, configure: AwaitTask.() -> Unit) {
with(AwaitTask()) {
configure()
start(checkNow = checkNow)
}
}
private typealias Action<T> = () -> T
class AwaitTask : Runnable {
//@formatter:off
var cond: Action<Boolean>? = null ; set(value) { checkNotRunning(); field = value }
var onSuccess: Action<Unit>? = null ; set(value) { checkNotRunning(); field = value }
var onFailure: Action<Unit>? = null ; set(value) { checkNotRunning(); field = value }
var delay: Int = -1 ; set(value) { checkNotRunning(); field = value }
var interval: Int = 20 ; set(value) { checkNotRunning(); field = value }
var maxChecks: Int = 0 ; set(value) { checkNotRunning(); field = value }
var task: BukkitTask? = null ; private set
var elapsedChecks = 0 ; private set
var cancelled = false ; private set
//@formatter:on
fun Plugin.start(checkNow: Boolean = true) {
if (cancelled) throw IllegalStateException()
requireNotNull(cond)
requireNotNull(onSuccess)
if (checkNow && check()) {
cancel()
onSuccess!!.invoke()
return
}
task = server.scheduler.runTaskTimer(this, this@AwaitTask, delay.toLong(), interval.toLong())
}
override fun run() {
if (task?.isCancelled != false) return
if (check()) {
cancel()
onSuccess!!.invoke()
}
elapsedChecks++
if (maxChecks in 1 until elapsedChecks) {
cancel()
onFailure?.invoke()
}
}
private fun check(): Boolean {
elapsedChecks++
return cond!!.invoke()
}
fun cancel() {
task?.cancel()
cancelled = true
}
private fun checkNotRunning() {
if (cancelled || task != null) throw IllegalStateException()
}
}

View File

@@ -1,7 +1,7 @@
<configuration> <configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<pattern>%d{HH:mm:ss.SSS} %magenta(%-8.-8(%thread)) %highlight(%-5level) %boldCyan(%32.-32logger{32}) - %msg%n</pattern> <pattern>%d{HH:mm:ss.SSS} %magenta(%-8.-8(%thread)) %highlight(%-5level) %boldCyan(%32.-32logger{32}) - %msg</pattern>
</encoder> </encoder>
</appender> </appender>