Clean up code for polymorphic options serialization, fix logger configuration
This commit is contained in:
@@ -72,7 +72,8 @@ dependencies {
|
|||||||
compile("org.jetbrains.exposed:exposed:0.10.3") { isTransitive = false }
|
compile("org.jetbrains.exposed:exposed:0.10.3") { isTransitive = false }
|
||||||
compile("joda-time:joda-time:2.10")
|
compile("joda-time:joda-time:2.10")
|
||||||
compile("com.zaxxer:HikariCP:3.2.0")
|
compile("com.zaxxer:HikariCP:3.2.0")
|
||||||
compile("ch.qos.logback:logback-classic:1.2.3")
|
compile("ch.qos.logback:logback-classic:1.2.3") { isTransitive = false }
|
||||||
|
compile("ch.qos.logback:logback-core:1.2.3") { isTransitive = false }
|
||||||
|
|
||||||
val jacksonVersion = "2.9.6"
|
val jacksonVersion = "2.9.6"
|
||||||
compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
|
compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion")
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
package io.dico.parcels2
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
|
||||||
import io.dico.parcels2.blockvisitor.TickWorktimeOptions
|
|
||||||
import io.dico.parcels2.defaultimpl.DefaultGeneratorOptions
|
|
||||||
import io.dico.parcels2.storage.Storage
|
|
||||||
import io.dico.parcels2.storage.StorageFactory
|
|
||||||
import io.dico.parcels2.storage.yamlObjectMapper
|
|
||||||
import org.bukkit.GameMode
|
|
||||||
import org.bukkit.Material
|
|
||||||
import java.io.Reader
|
|
||||||
import java.io.Writer
|
|
||||||
import java.util.EnumSet
|
|
||||||
|
|
||||||
class Options {
|
|
||||||
var worlds: Map<String, WorldOptionsHolder> = hashMapOf()
|
|
||||||
private set
|
|
||||||
var storage: StorageOptions = StorageOptions("postgresql", DataConnectionOptions())
|
|
||||||
var tickWorktime: TickWorktimeOptions = TickWorktimeOptions(20, 1)
|
|
||||||
|
|
||||||
fun addWorld(name: String,
|
|
||||||
generatorOptions: GeneratorOptions? = null,
|
|
||||||
worldOptions: WorldOptions? = null) {
|
|
||||||
val optionsHolder = WorldOptionsHolder(
|
|
||||||
generatorOptions ?: DefaultGeneratorOptions(),
|
|
||||||
worldOptions ?: WorldOptions()
|
|
||||||
)
|
|
||||||
|
|
||||||
(worlds as MutableMap).put(name, optionsHolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun writeTo(writer: Writer) = yamlObjectMapper.writeValue(writer, this)
|
|
||||||
|
|
||||||
fun mergeFrom(reader: Reader) = yamlObjectMapper.readerForUpdating(this).readValue<Options>(reader)
|
|
||||||
|
|
||||||
override fun toString(): String = yamlObjectMapper.writeValueAsString(this)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorldOptionsHolder(var generator: GeneratorOptions = DefaultGeneratorOptions(),
|
|
||||||
var runtime: WorldOptions = WorldOptions())
|
|
||||||
|
|
||||||
data class WorldOptions(var gameMode: GameMode? = GameMode.CREATIVE,
|
|
||||||
var dayTime: Boolean = true,
|
|
||||||
var noWeather: Boolean = true,
|
|
||||||
var preventWeatherBlockChanges: Boolean = true,
|
|
||||||
var preventBlockSpread: Boolean = true, // TODO
|
|
||||||
var dropEntityItems: Boolean = true,
|
|
||||||
var doTileDrops: Boolean = false,
|
|
||||||
var disableExplosions: Boolean = true,
|
|
||||||
var blockPortalCreation: Boolean = true,
|
|
||||||
var blockMobSpawning: Boolean = true,
|
|
||||||
var blockedItems: Set<Material> = EnumSet.of(Material.FLINT_AND_STEEL, Material.SNOWBALL),
|
|
||||||
var axisLimit: Int = 10) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class GeneratorOptions {
|
|
||||||
|
|
||||||
abstract fun generatorFactory(): GeneratorFactory
|
|
||||||
|
|
||||||
fun newGenerator(worldName: String) = generatorFactory().newParcelGenerator(worldName, this)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class StorageOptions(val dialect: String,
|
|
||||||
val options: Any) {
|
|
||||||
|
|
||||||
@get:JsonIgnore
|
|
||||||
val factory = StorageFactory.getFactory(dialect)
|
|
||||||
?: throw IllegalArgumentException("Invalid storage dialect: $dialect")
|
|
||||||
|
|
||||||
fun newStorageInstance(): Storage = factory.newStorageInstance(dialect, options)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data class DataConnectionOptions(val address: String = "localhost",
|
|
||||||
val database: String = "parcels",
|
|
||||||
val username: String = "root",
|
|
||||||
val password: String = "",
|
|
||||||
val poolSize: Int = 4) {
|
|
||||||
|
|
||||||
fun splitAddressAndPort(defaultPort: Int = 3306): Pair<String, Int>? {
|
|
||||||
val idx = address.indexOf(":").takeUnless { it == -1 } ?: return Pair(address, defaultPort)
|
|
||||||
|
|
||||||
val addressName = address.substring(0, idx).takeUnless { it.isBlank() } ?: return null.also {
|
|
||||||
logger.error("(Invalidly) blank address in data storage options")
|
|
||||||
}
|
|
||||||
|
|
||||||
val port = address.substring(idx + 1).toIntOrNull() ?: return null.also {
|
|
||||||
logger.error("Invalid port number in data storage options: $it, using $defaultPort as default")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Pair(addressName, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data class DataFileOptions(val location: String = "/flatfile-storage/")
|
|
||||||
|
|
||||||
class MigrationOptions() {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import io.dico.parcels2.blockvisitor.RegionTraversal
|
|||||||
import io.dico.parcels2.blockvisitor.Worker
|
import io.dico.parcels2.blockvisitor.Worker
|
||||||
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
||||||
import io.dico.parcels2.defaultimpl.DefaultParcelGenerator
|
import io.dico.parcels2.defaultimpl.DefaultParcelGenerator
|
||||||
|
import io.dico.parcels2.options.GeneratorOptions
|
||||||
import io.dico.parcels2.util.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import org.bukkit.Chunk
|
import org.bukkit.Chunk
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
@@ -17,26 +18,6 @@ import java.util.HashMap
|
|||||||
import java.util.Random
|
import java.util.Random
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
object GeneratorFactories {
|
|
||||||
private val map: MutableMap<String, GeneratorFactory> = HashMap()
|
|
||||||
|
|
||||||
fun registerFactory(generator: GeneratorFactory): Boolean = map.putIfAbsent(generator.name, generator) == null
|
|
||||||
|
|
||||||
fun getFactory(name: String): GeneratorFactory? = map.get(name)
|
|
||||||
|
|
||||||
init {
|
|
||||||
registerFactory(DefaultParcelGenerator.Factory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GeneratorFactory {
|
|
||||||
val name: String
|
|
||||||
|
|
||||||
val optionsClass: KClass<out GeneratorOptions>
|
|
||||||
|
|
||||||
fun newParcelGenerator(worldName: String, options: GeneratorOptions): ParcelGenerator
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ParcelGenerator : ChunkGenerator() {
|
abstract class ParcelGenerator : ChunkGenerator() {
|
||||||
abstract val world: World
|
abstract val world: World
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.dico.parcels2
|
package io.dico.parcels2
|
||||||
|
|
||||||
|
import io.dico.parcels2.options.RuntimeWorldOptions
|
||||||
import io.dico.parcels2.storage.Storage
|
import io.dico.parcels2.storage.Storage
|
||||||
import io.dico.parcels2.util.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import io.dico.parcels2.util.floor
|
import io.dico.parcels2.util.floor
|
||||||
@@ -76,7 +77,7 @@ interface ParcelWorld : ParcelLocator, ParcelContainer, ParcelBlockManager {
|
|||||||
val id: ParcelWorldId
|
val id: ParcelWorldId
|
||||||
val name: String
|
val name: String
|
||||||
val uid: UUID?
|
val uid: UUID?
|
||||||
val options: WorldOptions
|
val options: RuntimeWorldOptions
|
||||||
val generator: ParcelGenerator
|
val generator: ParcelGenerator
|
||||||
val storage: Storage
|
val storage: Storage
|
||||||
val container: ParcelContainer
|
val container: ParcelContainer
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import io.dico.parcels2.defaultimpl.GlobalAddedDataManagerImpl
|
|||||||
import io.dico.parcels2.defaultimpl.ParcelProviderImpl
|
import io.dico.parcels2.defaultimpl.ParcelProviderImpl
|
||||||
import io.dico.parcels2.listener.ParcelEntityTracker
|
import io.dico.parcels2.listener.ParcelEntityTracker
|
||||||
import io.dico.parcels2.listener.ParcelListeners
|
import io.dico.parcels2.listener.ParcelListeners
|
||||||
|
import io.dico.parcels2.options.Options
|
||||||
|
import io.dico.parcels2.options.optionsMapper
|
||||||
import io.dico.parcels2.storage.Storage
|
import io.dico.parcels2.storage.Storage
|
||||||
import io.dico.parcels2.storage.yamlObjectMapper
|
|
||||||
import io.dico.parcels2.util.FunctionHelper
|
import io.dico.parcels2.util.FunctionHelper
|
||||||
import io.dico.parcels2.util.tryCreate
|
import io.dico.parcels2.util.tryCreate
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
@@ -60,7 +61,7 @@ class ParcelsPlugin : JavaPlugin() {
|
|||||||
if (!loadOptions()) return false
|
if (!loadOptions()) return false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
storage = options.storage.newStorageInstance()
|
storage = options.storage.newInstance()
|
||||||
storage.init()
|
storage.init()
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
plogger.error("Failed to connect to database", ex)
|
plogger.error("Failed to connect to database", ex)
|
||||||
@@ -83,11 +84,11 @@ class ParcelsPlugin : JavaPlugin() {
|
|||||||
|
|
||||||
fun loadOptions(): Boolean {
|
fun loadOptions(): Boolean {
|
||||||
when {
|
when {
|
||||||
optionsFile.exists() -> yamlObjectMapper.readerForUpdating(options).readValue<Options>(optionsFile)
|
optionsFile.exists() -> optionsMapper.readerForUpdating(options).readValue<Options>(optionsFile)
|
||||||
optionsFile.tryCreate() -> {
|
optionsFile.tryCreate() -> {
|
||||||
options.addWorld("parcels")
|
options.addWorld("parcels")
|
||||||
try {
|
try {
|
||||||
yamlObjectMapper.writeValue(optionsFile, options)
|
optionsMapper.writeValue(optionsFile, options)
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
optionsFile.delete()
|
optionsFile.delete()
|
||||||
throw ex
|
throw ex
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import io.dico.parcels2.*
|
|||||||
import io.dico.parcels2.blockvisitor.RegionTraversal
|
import io.dico.parcels2.blockvisitor.RegionTraversal
|
||||||
import io.dico.parcels2.blockvisitor.Worker
|
import io.dico.parcels2.blockvisitor.Worker
|
||||||
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
||||||
|
import io.dico.parcels2.options.DefaultGeneratorOptions
|
||||||
import io.dico.parcels2.util.*
|
import io.dico.parcels2.util.*
|
||||||
import org.bukkit.*
|
import org.bukkit.*
|
||||||
import org.bukkit.block.Biome
|
import org.bukkit.block.Biome
|
||||||
@@ -17,21 +18,6 @@ import java.util.Random
|
|||||||
|
|
||||||
private val airType = Bukkit.createBlockData(Material.AIR)
|
private val airType = Bukkit.createBlockData(Material.AIR)
|
||||||
|
|
||||||
data class DefaultGeneratorOptions(var defaultBiome: Biome = Biome.JUNGLE,
|
|
||||||
var wallType: BlockData = Bukkit.createBlockData(Material.STONE_SLAB),
|
|
||||||
var floorType: BlockData = Bukkit.createBlockData(Material.QUARTZ_BLOCK),
|
|
||||||
var fillType: BlockData = Bukkit.createBlockData(Material.QUARTZ_BLOCK),
|
|
||||||
var pathMainType: BlockData = Bukkit.createBlockData(Material.SANDSTONE),
|
|
||||||
var pathAltType: BlockData = Bukkit.createBlockData(Material.REDSTONE_BLOCK),
|
|
||||||
var parcelSize: Int = 101,
|
|
||||||
var pathSize: Int = 9,
|
|
||||||
var floorHeight: Int = 64,
|
|
||||||
var offsetX: Int = 0,
|
|
||||||
var offsetZ: Int = 0) : GeneratorOptions() {
|
|
||||||
|
|
||||||
override fun generatorFactory(): GeneratorFactory = DefaultParcelGenerator.Factory
|
|
||||||
}
|
|
||||||
|
|
||||||
class DefaultParcelGenerator(val name: String, private val o: DefaultGeneratorOptions) : ParcelGenerator() {
|
class DefaultParcelGenerator(val name: String, private val o: DefaultGeneratorOptions) : ParcelGenerator() {
|
||||||
private var _world: World? = null
|
private var _world: World? = null
|
||||||
override val world: World
|
override val world: World
|
||||||
@@ -44,15 +30,6 @@ class DefaultParcelGenerator(val name: String, private val o: DefaultGeneratorOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var maxHeight = 0
|
private var maxHeight = 0
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val sectionSize = o.parcelSize + o.pathSize
|
val sectionSize = o.parcelSize + o.pathSize
|
||||||
val pathOffset = (if (o.pathSize % 2 == 0) o.pathSize + 2 else o.pathSize + 1) / 2
|
val pathOffset = (if (o.pathSize % 2 == 0) o.pathSize + 2 else o.pathSize + 1) / 2
|
||||||
val makePathMain = o.pathSize > 2
|
val makePathMain = o.pathSize > 2
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider {
|
|||||||
override fun getWorldGenerator(worldName: String): ParcelGenerator? {
|
override fun getWorldGenerator(worldName: String): ParcelGenerator? {
|
||||||
return _worlds[worldName]?.generator
|
return _worlds[worldName]?.generator
|
||||||
?: _generators[worldName]
|
?: _generators[worldName]
|
||||||
?: options.worlds[worldName]?.generator?.newGenerator(worldName)?.also { _generators[worldName] = it }
|
?: options.worlds[worldName]?.generator?.newInstance(worldName)?.also { _generators[worldName] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadWorlds() {
|
override fun loadWorlds() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package io.dico.parcels2.defaultimpl
|
|||||||
|
|
||||||
import io.dico.parcels2.*
|
import io.dico.parcels2.*
|
||||||
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
import io.dico.parcels2.blockvisitor.WorktimeLimiter
|
||||||
|
import io.dico.parcels2.options.RuntimeWorldOptions
|
||||||
import io.dico.parcels2.storage.Storage
|
import io.dico.parcels2.storage.Storage
|
||||||
import org.bukkit.World
|
import org.bukkit.World
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -11,7 +12,7 @@ import java.util.UUID
|
|||||||
class ParcelWorldImpl private
|
class ParcelWorldImpl private
|
||||||
constructor(override val world: World,
|
constructor(override val world: World,
|
||||||
override val generator: ParcelGenerator,
|
override val generator: ParcelGenerator,
|
||||||
override var options: WorldOptions,
|
override var options: RuntimeWorldOptions,
|
||||||
override val storage: Storage,
|
override val storage: Storage,
|
||||||
override val globalAddedData: GlobalAddedDataManager,
|
override val globalAddedData: GlobalAddedDataManager,
|
||||||
containerFactory: ParcelContainerFactory,
|
containerFactory: ParcelContainerFactory,
|
||||||
@@ -62,7 +63,7 @@ constructor(override val world: World,
|
|||||||
// Use this to be able to delegate blockManager and assign it to a property too, at least.
|
// Use this to be able to delegate blockManager and assign it to a property too, at least.
|
||||||
operator fun invoke(world: World,
|
operator fun invoke(world: World,
|
||||||
generator: ParcelGenerator,
|
generator: ParcelGenerator,
|
||||||
options: WorldOptions,
|
options: RuntimeWorldOptions,
|
||||||
storage: Storage,
|
storage: Storage,
|
||||||
globalAddedData: GlobalAddedDataManager,
|
globalAddedData: GlobalAddedDataManager,
|
||||||
containerFactory: ParcelContainerFactory,
|
containerFactory: ParcelContainerFactory,
|
||||||
|
|||||||
36
src/main/kotlin/io/dico/parcels2/options/GeneratorOptions.kt
Normal file
36
src/main/kotlin/io/dico/parcels2/options/GeneratorOptions.kt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import io.dico.parcels2.ParcelGenerator
|
||||||
|
import io.dico.parcels2.defaultimpl.DefaultParcelGenerator
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.block.Biome
|
||||||
|
import org.bukkit.block.data.BlockData
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
object GeneratorOptionsFactories : PolymorphicOptionsFactories<ParcelGenerator>("name", GeneratorOptions::class, DefaultGeneratorOptionsFactory())
|
||||||
|
|
||||||
|
class GeneratorOptions(name: String, options: Any) : PolymorphicOptions<ParcelGenerator>(name, options, GeneratorOptionsFactories) {
|
||||||
|
fun newInstance(worldName: String) = factory.newInstance(key, options, worldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DefaultGeneratorOptionsFactory : PolymorphicOptionsFactory<ParcelGenerator> {
|
||||||
|
override val supportedKeys: List<String> = listOf("default")
|
||||||
|
override val optionsClass: KClass<out Any> get() = DefaultGeneratorOptions::class
|
||||||
|
|
||||||
|
override fun newInstance(key: String, options: Any, vararg extra: Any?): ParcelGenerator {
|
||||||
|
return DefaultParcelGenerator(extra.first() as String, options as DefaultGeneratorOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultGeneratorOptions(val defaultBiome: Biome = Biome.JUNGLE,
|
||||||
|
val wallType: BlockData = Bukkit.createBlockData(Material.STONE_SLAB),
|
||||||
|
val floorType: BlockData = Bukkit.createBlockData(Material.QUARTZ_BLOCK),
|
||||||
|
val fillType: BlockData = Bukkit.createBlockData(Material.QUARTZ_BLOCK),
|
||||||
|
val pathMainType: BlockData = Bukkit.createBlockData(Material.SANDSTONE),
|
||||||
|
val pathAltType: BlockData = Bukkit.createBlockData(Material.REDSTONE_BLOCK),
|
||||||
|
val parcelSize: Int = 101,
|
||||||
|
val pathSize: Int = 9,
|
||||||
|
val floorHeight: Int = 64,
|
||||||
|
val offsetX: Int = 0,
|
||||||
|
val offsetZ: Int = 0)
|
||||||
17
src/main/kotlin/io/dico/parcels2/options/MigrationOptions.kt
Normal file
17
src/main/kotlin/io/dico/parcels2/options/MigrationOptions.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import io.dico.parcels2.storage.migration.Migration
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
object MigrationOptionsFactories : PolymorphicOptionsFactories<Migration>("kind", MigrationOptions::class, PlotmeMigrationFactory())
|
||||||
|
|
||||||
|
class MigrationOptions(kind: String, options: Any) : SimplePolymorphicOptions<Migration>(kind, options, MigrationOptionsFactories)
|
||||||
|
|
||||||
|
private class PlotmeMigrationFactory : PolymorphicOptionsFactory<Migration> {
|
||||||
|
override val supportedKeys = listOf("plotme-0.17")
|
||||||
|
override val optionsClass: KClass<out Any> get() = TODO()
|
||||||
|
|
||||||
|
override fun newInstance(key: String, options: Any, vararg extra: Any?): Migration {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/main/kotlin/io/dico/parcels2/options/Options.kt
Normal file
51
src/main/kotlin/io/dico/parcels2/options/Options.kt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import io.dico.parcels2.blockvisitor.TickWorktimeOptions
|
||||||
|
import org.bukkit.GameMode
|
||||||
|
import org.bukkit.Material
|
||||||
|
import java.io.Reader
|
||||||
|
import java.io.Writer
|
||||||
|
import java.util.EnumSet
|
||||||
|
|
||||||
|
class Options {
|
||||||
|
var worlds: Map<String, WorldOptions> = hashMapOf()
|
||||||
|
private set
|
||||||
|
var storage: StorageOptions = StorageOptions("postgresql", DataConnectionOptions())
|
||||||
|
var tickWorktime: TickWorktimeOptions = TickWorktimeOptions(20, 1)
|
||||||
|
|
||||||
|
fun addWorld(name: String,
|
||||||
|
generatorOptions: GeneratorOptions? = null,
|
||||||
|
worldOptions: RuntimeWorldOptions? = null) {
|
||||||
|
val optionsHolder = WorldOptions(
|
||||||
|
generatorOptions ?: GeneratorOptions("default", DefaultGeneratorOptions()),
|
||||||
|
worldOptions ?: RuntimeWorldOptions()
|
||||||
|
)
|
||||||
|
|
||||||
|
(worlds as MutableMap).put(name, optionsHolder)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeTo(writer: Writer) = optionsMapper.writeValue(writer, this)
|
||||||
|
|
||||||
|
fun mergeFrom(reader: Reader) = optionsMapper.readerForUpdating(this).readValue<Options>(reader)
|
||||||
|
|
||||||
|
override fun toString(): String = optionsMapper.writeValueAsString(this)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorldOptions(val generator: GeneratorOptions,
|
||||||
|
var runtime: RuntimeWorldOptions = RuntimeWorldOptions())
|
||||||
|
|
||||||
|
class RuntimeWorldOptions(var gameMode: GameMode? = GameMode.CREATIVE,
|
||||||
|
var dayTime: Boolean = true,
|
||||||
|
var noWeather: Boolean = true,
|
||||||
|
var preventWeatherBlockChanges: Boolean = true,
|
||||||
|
var preventBlockSpread: Boolean = true, // TODO
|
||||||
|
var dropEntityItems: Boolean = true,
|
||||||
|
var doTileDrops: Boolean = false,
|
||||||
|
var disableExplosions: Boolean = true,
|
||||||
|
var blockPortalCreation: Boolean = true,
|
||||||
|
var blockMobSpawning: Boolean = true,
|
||||||
|
var blockedItems: Set<Material> = EnumSet.of(Material.FLINT_AND_STEEL, Material.SNOWBALL),
|
||||||
|
var axisLimit: Int = 10)
|
||||||
|
|
||||||
|
class DataFileOptions(val location: String = "/flatfile-storage/")
|
||||||
66
src/main/kotlin/io/dico/parcels2/options/OptionsMapper.kt
Normal file
66
src/main/kotlin/io/dico/parcels2/options/OptionsMapper.kt
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.databind.PropertyNamingStrategy
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||||
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
|
||||||
|
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.block.data.BlockData
|
||||||
|
|
||||||
|
val optionsMapper = ObjectMapper(YAMLFactory()).apply {
|
||||||
|
propertyNamingStrategy = PropertyNamingStrategy.KEBAB_CASE
|
||||||
|
|
||||||
|
val kotlinModule = KotlinModule()
|
||||||
|
|
||||||
|
with(kotlinModule) {
|
||||||
|
/*
|
||||||
|
setSerializerModifier(object : BeanSerializerModifier() {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun modifySerializer(config: SerializationConfig?, beanDesc: BeanDescription, serializer: JsonSerializer<*>): JsonSerializer<*> {
|
||||||
|
|
||||||
|
val newSerializer = if (GeneratorOptions::class.isSuperclassOf(beanDesc.beanClass.kotlin)) {
|
||||||
|
GeneratorOptionsSerializer(serializer as JsonSerializer<GeneratorOptions>)
|
||||||
|
} else {
|
||||||
|
serializer
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.modifySerializer(config, beanDesc, newSerializer)
|
||||||
|
}
|
||||||
|
})*/
|
||||||
|
|
||||||
|
addSerializer(BlockDataSerializer())
|
||||||
|
addDeserializer(BlockData::class.java, BlockDataDeserializer())
|
||||||
|
|
||||||
|
GeneratorOptionsFactories.registerSerialization(this)
|
||||||
|
StorageOptionsFactories.registerSerialization(this)
|
||||||
|
MigrationOptionsFactories.registerSerialization(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
registerModule(kotlinModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlockDataSerializer : StdSerializer<BlockData>(BlockData::class.java) {
|
||||||
|
|
||||||
|
override fun serialize(value: BlockData, gen: JsonGenerator, provider: SerializerProvider) {
|
||||||
|
gen.writeString(value.asString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlockDataDeserializer : StdDeserializer<BlockData>(BlockData::class.java) {
|
||||||
|
|
||||||
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): BlockData? {
|
||||||
|
try {
|
||||||
|
return Bukkit.createBlockData(p.valueAsString)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
throw RuntimeException("Exception occurred at ${p.currentLocation}", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||||
|
import io.dico.parcels2.logger
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
abstract class PolymorphicOptions<T : Any>(val key: String,
|
||||||
|
val options: Any,
|
||||||
|
factories: PolymorphicOptionsFactories<T>) {
|
||||||
|
val factory = factories.getFactory(key)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SimplePolymorphicOptions<T : Any>(key: String, options: Any, factories: PolymorphicOptionsFactories<T>)
|
||||||
|
: PolymorphicOptions<T>(key, options, factories) {
|
||||||
|
fun newInstance(): T = factory.newInstance(key, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PolymorphicOptionsFactory<T : Any> {
|
||||||
|
val supportedKeys: List<String>
|
||||||
|
val optionsClass: KClass<out Any>
|
||||||
|
fun newInstance(key: String, options: Any, vararg extra: Any?): T
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
abstract class PolymorphicOptionsFactories<T : Any>(val serializeKeyAs: String,
|
||||||
|
rootClass: KClass<out PolymorphicOptions<T>>,
|
||||||
|
vararg defaultFactories: PolymorphicOptionsFactory<T>) {
|
||||||
|
val rootClass = rootClass as KClass<PolymorphicOptions<T>>
|
||||||
|
private val map: MutableMap<String, PolymorphicOptionsFactory<T>> = linkedMapOf()
|
||||||
|
val availableKeys: Collection<String> get() = map.keys
|
||||||
|
|
||||||
|
fun registerFactory(factory: PolymorphicOptionsFactory<T>) = factory.supportedKeys.forEach { map.putIfAbsent(it.toLowerCase(), factory) }
|
||||||
|
|
||||||
|
fun getFactory(key: String): PolymorphicOptionsFactory<T>? = map[key.toLowerCase()]
|
||||||
|
|
||||||
|
fun registerSerialization(module: SimpleModule) {
|
||||||
|
module.addSerializer(PolymorphicOptionsSerializer(this))
|
||||||
|
module.addDeserializer(rootClass.java, PolymorphicOptionsDeserializer(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
defaultFactories.forEach { registerFactory(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class PolymorphicOptionsDeserializer<T : Any>(val factories: PolymorphicOptionsFactories<T>) : JsonDeserializer<PolymorphicOptions<T>>() {
|
||||||
|
|
||||||
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): PolymorphicOptions<T> {
|
||||||
|
val node = p.readValueAsTree<JsonNode>()
|
||||||
|
val key = node.get(factories.serializeKeyAs).asText()
|
||||||
|
val factory = getFactory(key)
|
||||||
|
val optionsNode = node.get("options")
|
||||||
|
val options = p.codec.treeToValue(optionsNode, factory.optionsClass.java)
|
||||||
|
return factories.rootClass.constructors.first().call(key, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFactory(key: String): PolymorphicOptionsFactory<T> {
|
||||||
|
factories.getFactory(key)?.let { return it }
|
||||||
|
|
||||||
|
logger.warn("Unknown ${factories.rootClass.simpleName} ${factories.serializeKeyAs}: $key. " +
|
||||||
|
"\nAvailable options: ${factories.availableKeys}")
|
||||||
|
|
||||||
|
val default = factories.getFactory(factories.availableKeys.first())
|
||||||
|
?: throw IllegalStateException("No default ${factories.rootClass.simpleName} factory registered.")
|
||||||
|
return default
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PolymorphicOptionsSerializer<T : Any>(val factories: PolymorphicOptionsFactories<T>) : StdSerializer<PolymorphicOptions<T>>(factories.rootClass.java) {
|
||||||
|
|
||||||
|
override fun serialize(value: PolymorphicOptions<T>, gen: JsonGenerator, sp: SerializerProvider?) {
|
||||||
|
with(gen) {
|
||||||
|
writeStartObject()
|
||||||
|
writeStringField(factories.serializeKeyAs, value.key)
|
||||||
|
writeFieldName("options")
|
||||||
|
writeObject(value.options)
|
||||||
|
writeEndObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/main/kotlin/io/dico/parcels2/options/StorageOptions.kt
Normal file
45
src/main/kotlin/io/dico/parcels2/options/StorageOptions.kt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package io.dico.parcels2.options
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
|
import io.dico.parcels2.logger
|
||||||
|
import io.dico.parcels2.storage.Storage
|
||||||
|
import io.dico.parcels2.storage.StorageWithCoroutineBacking
|
||||||
|
import io.dico.parcels2.storage.exposed.ExposedBacking
|
||||||
|
import io.dico.parcels2.storage.getHikariConfig
|
||||||
|
|
||||||
|
object StorageOptionsFactories : PolymorphicOptionsFactories<Storage>("dialect", StorageOptions::class, ConnectionStorageFactory())
|
||||||
|
|
||||||
|
class StorageOptions(dialect: String, options: Any) : SimplePolymorphicOptions<Storage>(dialect, options, StorageOptionsFactories)
|
||||||
|
|
||||||
|
private class ConnectionStorageFactory : PolymorphicOptionsFactory<Storage> {
|
||||||
|
override val optionsClass = DataConnectionOptions::class
|
||||||
|
override val supportedKeys: List<String> = listOf("postgresql", "mariadb")
|
||||||
|
|
||||||
|
override fun newInstance(key: String, options: Any, vararg extra: Any?): Storage {
|
||||||
|
val hikariConfig = getHikariConfig(key, options as DataConnectionOptions)
|
||||||
|
val dataSourceFactory = suspend { HikariDataSource(hikariConfig) }
|
||||||
|
return StorageWithCoroutineBacking(ExposedBacking(dataSourceFactory))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class DataConnectionOptions(val address: String = "localhost",
|
||||||
|
val database: String = "parcels",
|
||||||
|
val username: String = "root",
|
||||||
|
val password: String = "",
|
||||||
|
val poolSize: Int = 4) {
|
||||||
|
|
||||||
|
fun splitAddressAndPort(defaultPort: Int = 3306): Pair<String, Int>? {
|
||||||
|
val idx = address.indexOf(":").takeUnless { it == -1 } ?: return Pair(address, defaultPort)
|
||||||
|
|
||||||
|
val addressName = address.substring(0, idx).takeUnless { it.isBlank() } ?: return null.also {
|
||||||
|
logger.error("(Invalidly) blank address in data storage options")
|
||||||
|
}
|
||||||
|
|
||||||
|
val port = address.substring(idx + 1).toIntOrNull() ?: return null.also {
|
||||||
|
logger.error("Invalid port number in data storage options: $it, using $defaultPort as default")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair(addressName, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.dico.parcels2.storage
|
package io.dico.parcels2.storage
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import io.dico.parcels2.DataConnectionOptions
|
import io.dico.parcels2.options.DataConnectionOptions
|
||||||
|
|
||||||
fun getHikariConfig(dialectName: String,
|
fun getHikariConfig(dialectName: String,
|
||||||
dco: DataConnectionOptions): HikariConfig = HikariConfig().apply {
|
dco: DataConnectionOptions): HikariConfig = HikariConfig().apply {
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
package io.dico.parcels2.storage
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
|
||||||
import com.fasterxml.jackson.databind.*
|
|
||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
|
||||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier
|
|
||||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
|
||||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
|
|
||||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
|
||||||
import io.dico.parcels2.GeneratorFactories
|
|
||||||
import io.dico.parcels2.GeneratorOptions
|
|
||||||
import io.dico.parcels2.StorageOptions
|
|
||||||
import org.bukkit.Bukkit
|
|
||||||
import org.bukkit.block.data.BlockData
|
|
||||||
import kotlin.reflect.full.isSuperclassOf
|
|
||||||
|
|
||||||
val yamlObjectMapper = ObjectMapper(YAMLFactory()).apply {
|
|
||||||
propertyNamingStrategy = PropertyNamingStrategy.KEBAB_CASE
|
|
||||||
|
|
||||||
val kotlinModule = KotlinModule()
|
|
||||||
|
|
||||||
with(kotlinModule) {
|
|
||||||
setSerializerModifier(object : BeanSerializerModifier() {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun modifySerializer(config: SerializationConfig?, beanDesc: BeanDescription, serializer: JsonSerializer<*>): JsonSerializer<*> {
|
|
||||||
|
|
||||||
val newSerializer = if (GeneratorOptions::class.isSuperclassOf(beanDesc.beanClass.kotlin)) {
|
|
||||||
GeneratorOptionsSerializer(serializer as JsonSerializer<GeneratorOptions>)
|
|
||||||
} else {
|
|
||||||
serializer
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.modifySerializer(config, beanDesc, newSerializer)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
addSerializer(BlockDataSerializer())
|
|
||||||
addDeserializer(BlockData::class.java, BlockDataDeserializer())
|
|
||||||
|
|
||||||
addSerializer(StorageOptionsSerializer())
|
|
||||||
addDeserializer(StorageOptions::class.java, StorageOptionsDeserializer())
|
|
||||||
|
|
||||||
addDeserializer(GeneratorOptions::class.java, GeneratorOptionsDeserializer())
|
|
||||||
}
|
|
||||||
|
|
||||||
registerModule(kotlinModule)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BlockDataSerializer : StdSerializer<BlockData>(BlockData::class.java) {
|
|
||||||
|
|
||||||
override fun serialize(value: BlockData, gen: JsonGenerator, provider: SerializerProvider) {
|
|
||||||
gen.writeString(value.asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BlockDataDeserializer : StdDeserializer<BlockData>(BlockData::class.java) {
|
|
||||||
|
|
||||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): BlockData? {
|
|
||||||
try {
|
|
||||||
return Bukkit.createBlockData(p.valueAsString)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
throw RuntimeException("Exception occurred at ${p.currentLocation}", ex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class StorageOptionsDeserializer : JsonDeserializer<StorageOptions>() {
|
|
||||||
|
|
||||||
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): StorageOptions {
|
|
||||||
val node = p!!.readValueAsTree<JsonNode>()
|
|
||||||
val dialect = node.get("dialect").asText()
|
|
||||||
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, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class StorageOptionsSerializer : StdSerializer<StorageOptions>(StorageOptions::class.java) {
|
|
||||||
|
|
||||||
override fun serialize(value: StorageOptions?, gen: JsonGenerator?, serializers: SerializerProvider?) {
|
|
||||||
with(gen!!) {
|
|
||||||
writeStartObject()
|
|
||||||
writeStringField("dialect", value!!.dialect)
|
|
||||||
writeFieldName("options")
|
|
||||||
writeObject(value.options)
|
|
||||||
writeEndObject()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class GeneratorOptionsDeserializer : JsonDeserializer<GeneratorOptions>() {
|
|
||||||
|
|
||||||
override fun deserialize(parser: JsonParser?, ctx: DeserializationContext?): GeneratorOptions? {
|
|
||||||
val node = parser!!.readValueAsTree<JsonNode>()
|
|
||||||
val name = node.get("name").asText()
|
|
||||||
val optionsNode = node.get("options")
|
|
||||||
val factory = GeneratorFactories.getFactory(name) ?: throw IllegalStateException("Unknown generator: $name")
|
|
||||||
|
|
||||||
return parser.codec.treeToValue(optionsNode, factory.optionsClass.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class GeneratorOptionsSerializer(private val defaultSerializer: JsonSerializer<GeneratorOptions>) : JsonSerializer<GeneratorOptions>() {
|
|
||||||
|
|
||||||
override fun serialize(input: GeneratorOptions?, generator: JsonGenerator?, provider: SerializerProvider?) {
|
|
||||||
with(generator!!) {
|
|
||||||
writeStartObject()
|
|
||||||
writeStringField("name", input!!.generatorFactory().name)
|
|
||||||
writeFieldName("options")
|
|
||||||
defaultSerializer.serialize(input, generator, provider)
|
|
||||||
writeEndObject()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package io.dico.parcels2.storage
|
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
|
||||||
import io.dico.parcels2.DataConnectionOptions
|
|
||||||
import io.dico.parcels2.storage.exposed.ExposedBacking
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
interface StorageFactory {
|
|
||||||
companion object StorageFactories {
|
|
||||||
private val map: MutableMap<String, StorageFactory> = HashMap()
|
|
||||||
|
|
||||||
fun registerFactory(dialect: String, generator: StorageFactory): Boolean = map.putIfAbsent(dialect.toLowerCase(), generator) == null
|
|
||||||
|
|
||||||
fun getFactory(dialect: String): StorageFactory? = map[dialect.toLowerCase()]
|
|
||||||
|
|
||||||
init {
|
|
||||||
// have to write the code like this in kotlin.
|
|
||||||
// This code is absolutely disgusting
|
|
||||||
ConnectionStorageFactory().register(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val optionsClass: KClass<out Any>
|
|
||||||
|
|
||||||
fun newStorageInstance(dialect: String, options: Any): Storage
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConnectionStorageFactory : StorageFactory {
|
|
||||||
override val optionsClass = DataConnectionOptions::class
|
|
||||||
private val types: List<String> = listOf("postgresql", "mariadb")
|
|
||||||
|
|
||||||
fun register(companion: StorageFactory.StorageFactories) {
|
|
||||||
types.forEach { companion.registerFactory(it, this) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newStorageInstance(dialect: String, options: Any): Storage {
|
|
||||||
val hikariConfig = getHikariConfig(dialect, options as DataConnectionOptions)
|
|
||||||
val dataSourceFactory = suspend { HikariDataSource(hikariConfig) }
|
|
||||||
return StorageWithCoroutineBacking(ExposedBacking(dataSourceFactory))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package io.dico.parcels2.storage.migration
|
|
||||||
|
|
||||||
interface MigrationFactory {
|
|
||||||
fun getMigration()
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
<configuration debug="true">
|
<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</pattern>
|
<!-- old pattern <pattern>%d{HH:mm:ss.SSS} %magenta(%-8.-8(%thread)) %highlight(%-5level) %boldCyan(%8.-32logger{32}) - %msg</pattern>-->
|
||||||
|
<pattern>%magenta(%-8.-8(%thread)) %highlight(%-5level) %boldCyan(%6.-32logger{32}) - %msg</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<root level="info">
|
<root level="debug">
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
</configuration>
|
</configuration>
|
||||||
Reference in New Issue
Block a user