profiles: blocks profile, key combination for showing chunk borders

This commit is contained in:
Bixilon 2021-12-03 20:22:31 +01:00
parent b37f554fee
commit 7fedff7d67
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
25 changed files with 260 additions and 82 deletions

View File

@ -1,25 +0,0 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.config.game
import com.squareup.moshi.Json
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.RGBColor
data class BlockOutline(
@Json(name = "collision_boxes") val collisionBoxes: Boolean = false,
@Json(name = "disable_z_buffer") val disableZBuffer: Boolean = false,
@Json(name = "outline_color") val outlineColor: RGBColor = ChatColors.RED,
@Json(name = "collision_color") val collisionColor: RGBColor = ChatColors.BLUE,
)

View File

@ -1,20 +0,0 @@
/*
* Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.config.game
import com.squareup.moshi.Json
data class CameraGameConfig(
@Json(name = "view_distance") var viewDistance: Int = 10,
)

View File

@ -16,15 +16,12 @@ package de.bixilon.minosoft.config.config.game
import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig
import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig
import de.bixilon.minosoft.config.config.game.hud.HUDGameConfig
import de.bixilon.minosoft.config.config.game.world.WorldConfig
data class GameConfig(
var graphics: GraphicsGameConfig = GraphicsGameConfig(),
var other: OtherGameConfig = OtherGameConfig(),
var hud: HUDGameConfig = HUDGameConfig(),
var controls: ControlsGameConfig = ControlsGameConfig(),
var camera: CameraGameConfig = CameraGameConfig(),
var world: WorldConfig = WorldConfig(),
var light: LightConfig = LightConfig(),
var skin: SkinConfig = SkinConfig(),
)

View File

@ -18,6 +18,5 @@ import com.squareup.moshi.Json
data class OtherGameConfig(
@Json(name = "anti_moire_pattern") var antiMoirePattern: Boolean = true,
@Json(name = "flower_random_offset") var flowerRandomOffset: Boolean = true,
@Json(name = "block_outline") var blockOutline: BlockOutline = BlockOutline(),
@Json(name = "experimental_fps") var experimentalFPS: Boolean = false,
)

View File

@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.type.MapType
import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.config.profile.profiles.account.AccountProfileManager
import de.bixilon.minosoft.config.profile.profiles.audio.AudioProfileManager
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfileManager
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfileManager
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
import de.bixilon.minosoft.config.profile.profiles.particle.ParticleProfileManager
@ -32,6 +33,7 @@ object GlobalProfileManager {
ResourcesProfileManager,
AccountProfileManager,
RenderingProfileManager,
BlockProfileManager,
)
private val SELECTED_PROFILES_TYPE: MapType = Jackson.MAPPER.typeFactory.constructMapType(HashMap::class.java, ResourceLocation::class.java, String::class.java)
val CLASS_MAPPING: Map<Class<out Profile>, ProfileManager<*>>

View File

@ -2,6 +2,8 @@ package de.bixilon.minosoft.config.profile
import de.bixilon.minosoft.config.profile.profiles.audio.AudioProfile
import de.bixilon.minosoft.config.profile.profiles.audio.AudioProfileManager
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfile
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfileManager
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfile
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfileManager
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfile
@ -20,4 +22,5 @@ data class ProfileCollection(
val entity: EntityProfile = EntityProfileManager.selected,
val resources: ResourcesProfile = ResourcesProfileManager.selected,
val rendering: RenderingProfile = RenderingProfileManager.selected,
val block: BlockProfile = BlockProfileManager.selected,
)

View File

@ -11,8 +11,12 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.config.game.world
package de.bixilon.minosoft.config.profile
data class ChunkBorderConfig(
var enabled: Boolean = false,
)
class ProfileLoadException(
val path: String,
val exception: Throwable? = null,
) : Exception(exception) {
override val message: String
get() = "Could not load profile ($path): ${exception?.message}"
}

View File

@ -32,8 +32,7 @@ interface ProfileManager<T : Profile> {
val profiles: HashBiMap<String, T>
var selected: T
@Deprecated("Should not be accessed")
var currentLoadingPath: String?
@Deprecated("Should not be accessed") var currentLoadingPath: String?
val baseDirectory: File
get() = File(RunConfiguration.HOME_DIRECTORY + "config/" + namespace.namespace + "/")
@ -159,7 +158,12 @@ interface ProfileManager<T : Profile> {
saveFile = true
}
val profile = load(profileName, json)
val profile: T
try {
profile = load(profileName, json)
} catch (exception: Throwable) {
throw ProfileLoadException(path, exception)
}
if (saveFile) {
profile.saved = false
save(profile)

View File

@ -0,0 +1,40 @@
package de.bixilon.minosoft.config.profile.profiles.block
import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfileManager.delegate
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfileManager.latestVersion
import de.bixilon.minosoft.config.profile.profiles.block.outline.OutlineC
/**
* Profile for block rendering
*/
class BlockProfile(
description: String? = null,
) : Profile {
override var initializing: Boolean = true
private set
override var saved: Boolean = true
override val version: Int = latestVersion
override val description by delegate(description ?: "")
/**
* The block view distance in chunks.
* The own chunk get loaded at 0 view distance. Every value above 1 shows 1 extra ring of chunks
* Total chunks is calculated as (viewDistance * 2 + 1)^2
* Must not be negative or exceed 128
*
* Other profiles (like entities, ...) also have view distance, but this value is the only one that gets sent to the server.
* The server may limit the other view distances according to this value
*/
var viewDistance by delegate(10) { check(it in 0..128) { "Invalid view distance $it" } }
val outline = OutlineC()
override fun toString(): String {
return BlockProfileManager.getName(this)
}
init {
initializing = false
}
}

View File

@ -0,0 +1,36 @@
package de.bixilon.minosoft.config.profile.profiles.block
import com.google.common.collect.HashBiMap
import de.bixilon.minosoft.config.profile.GlobalProfileManager
import de.bixilon.minosoft.config.profile.ProfileManager
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.KUtil.unsafeCast
import java.util.concurrent.locks.ReentrantLock
object BlockProfileManager : ProfileManager<BlockProfile> {
override val namespace = "minosoft:block".toResourceLocation()
override val latestVersion = 1
override val saveLock = ReentrantLock()
override val profileClass = BlockProfile::class.java
override var currentLoadingPath: String? = null
override val profiles: HashBiMap<String, BlockProfile> = HashBiMap.create()
override var selected: BlockProfile = null.unsafeCast()
set(value) {
field = value
GlobalProfileManager.selectProfile(this, value)
GlobalEventMaster.fireEvent(BlockProfileSelectEvent(value))
}
override fun createDefaultProfile(name: String): BlockProfile {
currentLoadingPath = name
val profile = BlockProfile("Default block profile")
currentLoadingPath = null
profiles[name] = profile
return profile
}
}

View File

@ -0,0 +1,7 @@
package de.bixilon.minosoft.config.profile.profiles.block
import de.bixilon.minosoft.modding.event.events.Event
class BlockProfileSelectEvent(
val profile: BlockProfile,
) : Event

View File

@ -0,0 +1,48 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.profile.profiles.block.outline
import de.bixilon.minosoft.config.profile.profiles.block.BlockProfileManager.delegate
import de.bixilon.minosoft.data.text.ChatColors
class OutlineC {
/**
* Highlights the current selected block
*/
var enabled by delegate(true)
/**
* Shows the collision box of the selected block
*/
var showCollisionBoxes by delegate(false)
/**
* Disables the z-buffer of the block outline
* Makes the whole outline visible and ignores the walls
*/
var showThroughWalls by delegate(false)
/**
* The color of the block that is currently selected
* Defaults to light red
*/
var outlineColor by delegate(ChatColors.RED)
/**
* The color of the block collision box that is currently selected
* Defaults to light blue
*/
var collisionColor by delegate(ChatColors.RED)
}

View File

@ -5,6 +5,7 @@ import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfileMan
import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfileManager.latestVersion
import de.bixilon.minosoft.config.profile.profiles.rendering.advanced.AdvancedC
import de.bixilon.minosoft.config.profile.profiles.rendering.camera.CameraC
import de.bixilon.minosoft.config.profile.profiles.rendering.chunkborder.ChunkBorderC
import de.bixilon.minosoft.config.profile.profiles.rendering.movement.MovementC
/**
@ -22,6 +23,7 @@ class RenderingProfile(
val camera = CameraC()
val advanced = AdvancedC()
val movement = MovementC()
val chunkBorder = ChunkBorderC()
override fun toString(): String {

View File

@ -11,10 +11,11 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.config.config.game.world
package de.bixilon.minosoft.config.profile.profiles.rendering.chunkborder
import com.squareup.moshi.Json
import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfileManager.delegate
data class WorldConfig(
@Json(name = "chunk_borders") var chunkBorders: ChunkBorderConfig = ChunkBorderConfig(),
)
class ChunkBorderC {
var enabled by delegate(false)
}

View File

@ -72,6 +72,7 @@ class World(
var raining = false
var rainGradient = 0.0f
var thunderGradient = 0.0f
var viewDistance = connection.profiles.block.viewDistance // ToDo: Calculate view distance by chunks sent from the server Limited by clientViewDistance in profile
private val random = Random
var audioPlayer: AbstractAudioPlayer? = null

View File

@ -13,7 +13,6 @@
package de.bixilon.minosoft.gui.rendering
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
@ -138,9 +137,7 @@ class RenderWindow(
registerRenderer(ParticleRenderer)
}
registerRenderer(EntityHitboxRenderer)
if (Minosoft.config.config.game.world.chunkBorders.enabled) {
registerRenderer(ChunkBorderRenderer)
}
registerRenderer(ChunkBorderRenderer)
registerRenderer(HUDRenderer)
}

View File

@ -60,7 +60,7 @@ class Camera(
) {
private val profile = connection.profiles.rendering.camera
var fogColor = Previous(ChatColors.GREEN)
var fogStart = Minosoft.config.config.game.camera.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDo
var fogStart = connection.world.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDo
private var mouseSensitivity = Minosoft.config.config.game.controls.moseSensitivity
private var lastMousePosition: Vec2d = Vec2d(0.0, 0.0)
@ -136,7 +136,7 @@ class Camera(
fogStart = if (connection.player.submergedFluid?.resourceLocation == DefaultFluids.WATER) {
10.0f
} else {
Minosoft.config.config.game.camera.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDO
connection.world.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDO
}
}

View File

@ -13,7 +13,6 @@
package de.bixilon.minosoft.gui.rendering.particle
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.profile.change.listener.SimpleChangeListener.Companion.listen
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.*
@ -152,7 +151,7 @@ class ParticleRenderer(
try {
val time = KUtil.time
for (particle in particles) {
if (particle.position.length() - cameraLength >= Minosoft.config.config.game.camera.viewDistance * ProtocolDefinition.SECTION_WIDTH_X) {
if (particle.position.length() - cameraLength >= connection.world.viewDistance * ProtocolDefinition.SECTION_WIDTH_X) {
particle.dead = true
toRemove += particle
} else if (particle.dead) {
@ -194,7 +193,7 @@ class ParticleRenderer(
}
val cameraLength = connection.player.position.length()
if (particle.position.length() - cameraLength >= Minosoft.config.config.game.camera.viewDistance * ProtocolDefinition.SECTION_WIDTH_X) {
if (particle.position.length() - cameraLength >= connection.world.viewDistance * ProtocolDefinition.SECTION_WIDTH_X) {
particle.dead = true
return
}

View File

@ -558,7 +558,7 @@ class WorldRenderer(
}
private fun isChunkVisible(chunkPosition: Vec2i): Boolean {
return chunkPosition.isInRenderDistance(cameraChunkPosition)
return chunkPosition.isInRenderDistance(connection.world.viewDistance, cameraChunkPosition)
}
private fun isSectionVisible(chunkPosition: Vec2i, sectionHeight: Int, minPosition: Vec3i, maxPosition: Vec3i, checkChunk: Boolean): Boolean {

View File

@ -13,6 +13,9 @@
package de.bixilon.minosoft.gui.rendering.world.chunk
import de.bixilon.minosoft.config.key.KeyAction
import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.gui.rendering.RenderConstants
@ -24,6 +27,8 @@ import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable
import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.format
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
@ -31,12 +36,32 @@ class ChunkBorderRenderer(
val connection: PlayConnection,
override val renderWindow: RenderWindow,
) : Renderer, OpaqueDrawable {
private val profile = connection.profiles.rendering
override val renderSystem: RenderSystem = renderWindow.renderSystem
private var lastChunkPosition: Vec2i? = null
private var lastMesh: LineMesh? = null
override val skipOpaque: Boolean
get() = !profile.chunkBorder.enabled
override fun init() {
renderWindow.inputHandler.registerKeyCallback(CHUNK_BORDER_TOGGLE_KEY_COMBINATION,
KeyBinding(
mutableMapOf(
KeyAction.MODIFIER to mutableSetOf(KeyCodes.KEY_F3),
KeyAction.STICKY to mutableSetOf(KeyCodes.KEY_G),
),
), defaultPressed = profile.chunkBorder.enabled) {
profile.chunkBorder.enabled = it
renderWindow.sendDebugMessage("Chunk borders: ${it.format()}")
}
}
override fun prepareDraw() {
if (!profile.chunkBorder.enabled) {
lastMesh?.unload()
return
}
val chunkPosition = renderWindow.connection.player.positionInfo.chunkPosition
if (chunkPosition == lastChunkPosition && lastMesh != null) {
return
@ -124,6 +149,8 @@ class ChunkBorderRenderer(
companion object : RendererBuilder<ChunkBorderRenderer> {
override val RESOURCE_LOCATION = ResourceLocation("minosoft:chunk_borders")
private val CHUNK_BORDER_TOGGLE_KEY_COMBINATION = "minosoft:toggle_chunk_borders".toResourceLocation()
override fun build(connection: PlayConnection, renderWindow: RenderWindow): ChunkBorderRenderer {
return ChunkBorderRenderer(connection, renderWindow)

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.gui.rendering.world.outline
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.profile.change.listener.SimpleChangeListener.Companion.listen
import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.blocks.BlockState
@ -36,6 +36,7 @@ class BlockOutlineRenderer(
val connection: PlayConnection,
override val renderWindow: RenderWindow,
) : Renderer, OtherDrawable {
private val profile = connection.profiles.block.outline
override val renderSystem: RenderSystem = renderWindow.renderSystem
private var currentOutlinePosition: Vec3i? = null
private var currentOutlineBlockState: BlockState? = null
@ -44,6 +45,20 @@ class BlockOutlineRenderer(
override val skipOther: Boolean
get() = currentMesh == null
/**
* Unloads the current mesh and creates a new one
* Uses when the profile changed
*/
private var reload = false
override fun init() {
val profile = connection.profiles.block
this.profile::enabled.listen(this, profile = profile) { reload = true }
this.profile::showCollisionBoxes.listen(this, profile = profile) { reload = true }
this.profile::outlineColor.listen(this, profile = profile) { reload = true }
this.profile::collisionColor.listen(this, profile = profile) { reload = true }
}
override fun drawOther() {
val currentMesh = currentMesh ?: return
@ -52,7 +67,7 @@ class BlockOutlineRenderer(
override fun setupOther() {
renderWindow.renderSystem.reset(faceCulling = false)
if (Minosoft.config.config.game.other.blockOutline.disableZBuffer) {
if (profile.showThroughWalls) {
renderWindow.renderSystem.depth = DepthFunctions.ALWAYS
}
renderWindow.shaderManager.genericColorShader.use()
@ -88,7 +103,11 @@ class BlockOutlineRenderer(
}
}
if (raycastHit.blockPosition == currentOutlinePosition && raycastHit.blockState == currentOutlineBlockState) {
if (raycastHit.blockPosition == currentOutlinePosition && raycastHit.blockState == currentOutlineBlockState && !reload) {
return
}
if (!profile.enabled) {
return
}
@ -97,11 +116,11 @@ class BlockOutlineRenderer(
val blockOffset = raycastHit.blockPosition.toVec3d + raycastHit.blockPosition.getWorldOffset(raycastHit.blockState.block)
currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.outlineColor)
currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.outlineColor)
if (Minosoft.config.config.game.other.blockOutline.collisionBoxes) {
currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.collisionColor, 0.005f)
if (profile.showCollisionBoxes) {
currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, profile.collisionColor, 0.005f)
}
currentMesh.load()
@ -110,6 +129,7 @@ class BlockOutlineRenderer(
this.currentOutlinePosition = raycastHit.blockPosition
this.currentOutlineBlockState = raycastHit.blockState
this.currentMesh = currentMesh
this.reload = false
}

View File

@ -169,7 +169,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
connection.world.cacheBiomeAccessor = NoiseBiomeAccessor(connection.world)
}
connection.sendPacket(ClientSettingsC2SP(viewDistance = Minosoft.config.config.game.camera.viewDistance))
connection.sendPacket(ClientSettingsC2SP(viewDistance = connection.profiles.block.viewDistance)) // ToDo: This should not be here
val brandName = DefaultRegistries.DEFAULT_PLUGIN_CHANNELS_REGISTRY.forVersion(connection.version)[DefaultPluginChannels.BRAND]!!.resourceLocation
val buffer = PlayOutByteBuffer(connection)

View File

@ -13,7 +13,6 @@
package de.bixilon.minosoft.util.chunk
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.registries.biomes.Biome
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
@ -294,10 +293,9 @@ object ChunkUtil {
}
}
fun Vec2i.isInRenderDistance(cameraPosition: Vec2i): Boolean {
val viewDistance = Minosoft.config.config.game.camera.viewDistance
fun Vec2i.isInRenderDistance(viewDistance: Int, cameraPosition: Vec2i): Boolean {
val delta = (this - cameraPosition).abs
return delta.x < viewDistance || delta.y < viewDistance
return delta.x <= viewDistance || delta.y <= viewDistance
}
}

View File

@ -10,6 +10,7 @@ object Jackson {
val MAPPER = ObjectMapper()
.registerModule(KotlinModule())
.registerModule(ResourceLocationSerializer)
.registerModule(RGBColorSerializer)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

View File

@ -0,0 +1,37 @@
package de.bixilon.minosoft.util.json.jackson
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import de.bixilon.minosoft.data.text.ChatCode.Companion.toColor
import de.bixilon.minosoft.data.text.RGBColor
object RGBColorSerializer : SimpleModule() {
init {
addDeserializer(RGBColor::class.java, Deserializer)
addSerializer(RGBColor::class.java, Serializer)
}
object Deserializer : StdDeserializer<RGBColor>(RGBColor::class.java) {
override fun deserialize(parser: JsonParser, context: DeserializationContext?): RGBColor {
return when (parser.currentToken) {
JsonToken.VALUE_NUMBER_INT -> RGBColor(parser.valueAsInt)
JsonToken.VALUE_STRING -> parser.valueAsString.toColor()!!
else -> TODO("Can not parse color!")
}
}
}
object Serializer : StdSerializer<RGBColor>(RGBColor::class.java) {
override fun serialize(value: RGBColor?, generator: JsonGenerator, provider: SerializerProvider?) {
generator.writeString(value?.toString())
}
}
}