From 8a0a77b8ba4a2e160558809b592e4bc393e7c997 Mon Sep 17 00:00:00 2001 From: Dico200 Date: Sun, 22 Jul 2018 16:44:32 +0200 Subject: Successfully connecting to h2 database --- build.gradle.kts | 20 +++++--- src/main/kotlin/io/dico/parcels2/Options.kt | 4 +- src/main/kotlin/io/dico/parcels2/ParcelWorld.kt | 56 +++++++++++----------- src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt | 47 +++++++++++++++++- src/main/kotlin/io/dico/parcels2/WorldGenerator.kt | 10 ++-- src/main/kotlin/io/dico/parcels2/storage/Hikari.kt | 5 ++ .../kotlin/io/dico/parcels2/storage/Jackson.kt | 7 +-- .../io/dico/parcels2/storage/StorageFactory.kt | 9 ++-- .../kotlin/io/dico/parcels2/util/MiscExtensions.kt | 15 ++++++ src/main/resources/plugin.yml | 3 +- 10 files changed, 122 insertions(+), 54 deletions(-) create mode 100644 src/main/kotlin/io/dico/parcels2/util/MiscExtensions.kt diff --git a/build.gradle.kts b/build.gradle.kts index 3c9baf6..8b65cd9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,10 +1,5 @@ -import com.github.jengelman.gradle.plugins.shadow.relocation.RelocateClassContext -import com.github.jengelman.gradle.plugins.shadow.relocation.RelocatePathContext -import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext import org.jetbrains.kotlin.gradle.dsl.Coroutines -import shadow.org.apache.tools.zip.ZipOutputStream plugins { kotlin("jvm") version "1.2.51" @@ -33,14 +28,16 @@ dependencies { compile("org.jetbrains.exposed:exposed:0.10.3") compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4") compile("com.zaxxer:HikariCP:3.2.0") + compile(files("../h2/bin/h2-client-1.4.197.jar")) val jacksonVersion = "2.9.6" compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion") compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") - compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion") compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") + //compile("org.yaml:snakeyaml:1.21") + compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion") - compile("org.slf4j:slf4j-api:1.7.25") + shadow("org.slf4j:slf4j-api:1.7.25") compile("ch.qos.logback:logback-classic:1.2.3") testCompile("junit:junit:4.12") @@ -73,4 +70,13 @@ tasks { relocate("kotlin", "kotlin") } + + val relocateSnakeyamlJar by creating(ShadowJar::class) { + destinationDir = file("$rootDir/debug/plugins") + baseName = "parcels2-shaded" + relocate("org.yaml", "shadow.org.yaml") + + from(*project.configurations.compile.map(::zipTree).toTypedArray()) + with(jar) + } } \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/Options.kt b/src/main/kotlin/io/dico/parcels2/Options.kt index 4324df3..5dcb318 100644 --- a/src/main/kotlin/io/dico/parcels2/Options.kt +++ b/src/main/kotlin/io/dico/parcels2/Options.kt @@ -22,8 +22,6 @@ class Options { fun addWorld(name: String, options: WorldOptions) = (worlds as MutableMap).put(name, options) - fun addDefaultWorld() = addWorld("plotworld", WorldOptions()) - fun writeTo(writer: Writer) = yamlObjectMapper.writeValue(writer, this) fun mergeFrom(reader: Reader) = yamlObjectMapper.readerForUpdating(this).readValue(reader) @@ -50,7 +48,7 @@ abstract class GeneratorOptions { abstract fun generatorFactory(): GeneratorFactory - fun getGenerator(worldName: String) = generatorFactory().newParcelGenerator(worldName, this) + fun getGenerator(worlds: Worlds, worldName: String) = generatorFactory().newParcelGenerator(worlds, worldName, this) } diff --git a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt index 97e3942..8acf7c8 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt @@ -13,47 +13,49 @@ import org.bukkit.entity.Player import java.util.* import kotlin.coroutines.experimental.buildSequence -val worlds: Map get() = _worlds -private val _worlds: MutableMap = HashMap() +class Worlds { + val worlds: Map get() = _worlds + private val _worlds: MutableMap = HashMap() -fun getWorld(name: String): ParcelWorld? = _worlds.get(name) + fun getWorld(name: String): ParcelWorld? = _worlds.get(name) -fun getWorld(world: World): ParcelWorld? = getWorld(world.name) + fun getWorld(world: World): ParcelWorld? = getWorld(world.name) -fun getParcelAt(block: Block): Parcel? = getParcelAt(block.world, block.x, block.z) + fun getParcelAt(block: Block): Parcel? = getParcelAt(block.world, block.x, block.z) -fun getParcelAt(player: Player): Parcel? = getParcelAt(player.location) + fun getParcelAt(player: Player): Parcel? = getParcelAt(player.location) -fun getParcelAt(location: Location): Parcel? = getParcelAt(location.world, location.x.floor(), location.z.floor()) + fun getParcelAt(location: Location): Parcel? = getParcelAt(location.world, location.x.floor(), location.z.floor()) -fun getParcelAt(world: World, x: Int, z: Int): Parcel? = getParcelAt(world.name, x, z) + fun getParcelAt(world: World, x: Int, z: Int): Parcel? = getParcelAt(world.name, x, z) -fun getParcelAt(world: String, x: Int, z: Int): Parcel? { - with (getWorld(world) ?: return null) { - return generator.parcelAt(x, z) + fun getParcelAt(world: String, x: Int, z: Int): Parcel? { + with(getWorld(world) ?: return null) { + return generator.parcelAt(x, z) + } } -} -fun loadWorlds(options: Options) { - for ((worldName, worldOptions) in options.worlds.entries) { - val world: ParcelWorld - try { - world = ParcelWorld(worldName, worldOptions, worldOptions.generator.getGenerator(worldName)) - } catch (ex: Exception) { - ex.printStackTrace() - continue - } + fun loadWorlds(options: Options) { + for ((worldName, worldOptions) in options.worlds.entries) { + val world: ParcelWorld + try { + world = ParcelWorld(worldName, worldOptions, worldOptions.generator.getGenerator(this, worldName)) + } catch (ex: Exception) { + ex.printStackTrace() + continue + } - _worlds.put(worldName, world) + _worlds.put(worldName, world) + + if (Bukkit.getWorld(worldName) == null) { + 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()) + } - if (Bukkit.getWorld(worldName) == null) { - 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()) } } - } interface ParcelProvider { diff --git a/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt b/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt index 5ffce7c..43ee65b 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt @@ -1,15 +1,60 @@ package io.dico.parcels2 +import io.dico.parcels2.storage.Storage +import io.dico.parcels2.storage.yamlObjectMapper +import io.dico.parcels2.util.tryCreate +import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin import org.slf4j.LoggerFactory +import java.io.File +import java.util.logging.Level val logger = LoggerFactory.getLogger("ParcelsPlugin") +private inline val plogger get() = logger + class ParcelsPlugin : JavaPlugin() { + lateinit var optionsFile: File + lateinit var options: Options + lateinit var worlds: Worlds + lateinit var storage: Storage override fun onEnable() { - super.onEnable() + if (!init()) { + Bukkit.getPluginManager().disablePlugin(this) + } + } + + private fun init(): Boolean { + optionsFile = File(dataFolder, "options.yml") + options = Options() + worlds = Worlds() + + try { + if (optionsFile.exists()) { + yamlObjectMapper.readerForUpdating(options).readValue(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 { + storage = options.storage.newStorageInstance() + } catch (ex: Exception) { + plogger.error("Failed to connect to database", ex) + return false + } + + worlds.loadWorlds(options) + } catch (ex: Exception) { + plogger.error("Error loading options", ex) + return false + } + return true } } \ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt b/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt index 8f6a3aa..1123955 100644 --- a/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt +++ b/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt @@ -71,19 +71,19 @@ interface GeneratorFactory { val optionsClass: KClass - fun newParcelGenerator(worldName: String, options: GeneratorOptions): ParcelGenerator + fun newParcelGenerator(worlds: Worlds, worldName: String, options: GeneratorOptions): ParcelGenerator } -class DefaultParcelGenerator(name: String, private val o: DefaultGeneratorOptions) : ParcelGenerator() { - override val world: ParcelWorld by lazy { TODO() } +class DefaultParcelGenerator(val worlds: Worlds, val name: String, private val o: DefaultGeneratorOptions) : ParcelGenerator() { + override val world: ParcelWorld by lazy { worlds.getWorld(name)!! } override val factory = Factory companion object Factory : GeneratorFactory { override val name get() = "default" override val optionsClass get() = DefaultGeneratorOptions::class - override fun newParcelGenerator(worldName: String, options: GeneratorOptions): ParcelGenerator { - return DefaultParcelGenerator(worldName, options as DefaultGeneratorOptions) + override fun newParcelGenerator(worlds: Worlds, worldName: String, options: GeneratorOptions): ParcelGenerator { + return DefaultParcelGenerator(worlds, worldName, options as DefaultGeneratorOptions) } } diff --git a/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt b/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt index 7e4fb7f..108ad92 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/Hikari.kt @@ -27,6 +27,11 @@ fun getHikariDataSource(dialectName: String, // copied from github.com/lucko/LuckPerms if (dialectName.toLowerCase() == "mariadb") { addDataSourceProperty("properties", "useUnicode=true;characterEncoding=utf8") + } else if (dialectName.toLowerCase() == "h2") { + dataSourceProperties.remove("serverName") + dataSourceProperties.remove("port") + dataSourceProperties.remove("databaseName") + addDataSourceProperty("url", "jdbc:h2:tcp://$address/~/${dco.database}") } else { // doesn't exist on the MariaDB driver addDataSourceProperty("cachePrepStmts", "true") diff --git a/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt b/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt index 685ccb5..b5bdbeb 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/Jackson.kt @@ -34,10 +34,8 @@ val yamlObjectMapper = ObjectMapper(YAMLFactory()).apply { addSerializer(BlockDataSerializer()) addDeserializer(BlockData::class.java, BlockDataDeserializer()) - /* addSerializer(StorageOptionsSerializer()) addDeserializer(StorageOptions::class.java, StorageOptionsDeserializer()) - */ addDeserializer(GeneratorOptions::class.java, GeneratorOptionsDeserializer()) } @@ -65,7 +63,6 @@ private class BlockDataDeserializer : StdDeserializer(BlockData::clas } -/* class StorageOptionsDeserializer : JsonDeserializer() { override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): StorageOptions { @@ -74,7 +71,7 @@ class StorageOptionsDeserializer : JsonDeserializer() { val optionsNode = node.get("options") val factory = StorageFactory.getFactory(dialect) ?: throw IllegalStateException("Unknown storage dialect: $dialect") val options = p.codec.treeToValue(optionsNode, factory.optionsClass.java) - return StorageOptions(dialect, factory, options) + return StorageOptions(dialect, options) } } @@ -92,8 +89,6 @@ class StorageOptionsSerializer : StdSerializer(StorageOptions::c } } -*/ - class GeneratorOptionsDeserializer : JsonDeserializer() { diff --git a/src/main/kotlin/io/dico/parcels2/storage/StorageFactory.kt b/src/main/kotlin/io/dico/parcels2/storage/StorageFactory.kt index 7429351..c1e158a 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/StorageFactory.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/StorageFactory.kt @@ -1,6 +1,7 @@ package io.dico.parcels2.storage import io.dico.parcels2.DataConnectionOptions +import net.minecraft.server.v1_13_R1.WorldType.types import kotlin.reflect.KClass interface StorageFactory { @@ -27,10 +28,10 @@ interface StorageFactory { class ConnectionStorageFactory : StorageFactory { override val optionsClass = DataConnectionOptions::class - private val types: Map = with(HashMap()) { - put("mysql", "com.mysql.jdbc.jdbc2.optional.MysqlDataSource") - this - } + private val types: Map = mutableMapOf( + "mysql" to "com.mysql.jdbc.jdbc2.optional.MysqlDataSource", + "h2" to "org.h2.jdbcx.JdbcDataSource" + ) fun register(companion: StorageFactory.StorageFactories) { types.keys.forEach { diff --git a/src/main/kotlin/io/dico/parcels2/util/MiscExtensions.kt b/src/main/kotlin/io/dico/parcels2/util/MiscExtensions.kt new file mode 100644 index 0000000..f70014d --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/MiscExtensions.kt @@ -0,0 +1,15 @@ +package io.dico.parcels2.util + +import io.dico.parcels2.logger +import org.slf4j.Logger +import java.io.File +import java.io.PrintWriter + +fun File.tryCreate(): Boolean { + val parent = parentFile + if (parent == null || !(parent.exists() || parent.mkdirs()) || !createNewFile()) { + logger.warn("Failed to create file ${canonicalPath}") + return false + } + return true +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3d8cd01..19c68da 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,4 +2,5 @@ name: Parcels author: Dico main: io.dico.parcels2.ParcelsPlugin version: 0.1 -api-version: 1.13 \ No newline at end of file +api-version: 1.13 +load: STARTUP \ No newline at end of file -- cgit v1.2.3