Minigame map/arena library to hold & store data.
minecraft minecraft-lib minecraft-library
3

Configure Feed

Select the types of activity you want to include in your feed.

Update TOML & Json parsers to work with the new WorldData changes!

Lukiiy (Jul 15, 2026, 2:01 AM -0300) 156fb3ab ae3663d6

+110 -64
+56 -36
src/main/kotlin/me/lukiiy/mapling/provided/JsonWorldDataStore.kt
··· 15 15 import java.io.File 16 16 import kotlin.collections.component1 17 17 import kotlin.collections.component2 18 - import kotlin.collections.iterator 19 18 import kotlin.collections.map 20 19 21 20 class JsonWorldDataStore : WorldDataStore { 22 21 override fun load(file: File): WorldData { 23 22 if (!file.exists()) return WorldData() 24 23 25 - return deserialize(Json.parseToJsonElement(file.readText()).jsonObject) 24 + val root = Json.parseToJsonElement(file.readText()).jsonObject 25 + val data = WorldData() 26 + 27 + // parsings & gathering! 28 + (root["values"] as? JsonObject)?.forEach { (k, v) -> data.set(k, decode(v)) } 29 + (root["positions"] as? JsonObject)?.forEach { (k, v) -> data.setPosition(k, Position.deserialize((v as JsonPrimitive).content)) } 30 + 31 + (root["areas"] as? JsonObject)?.forEach { (k, v) -> 32 + val value = v as JsonObject 33 + 34 + data.setArea(k, Position.deserialize((value["from"] as JsonPrimitive).content), Position.deserialize((value["to"] as JsonPrimitive).content)) 35 + } 36 + 37 + (root["groups"] as? JsonObject)?.forEach { (k, v) -> 38 + val list = data.group(k) 39 + 40 + (v as JsonArray).forEach { list.add(Position.deserialize((it as JsonPrimitive).content)) } 41 + } 42 + 43 + return data 26 44 } 27 45 28 46 override fun save(file: File, data: WorldData) { 29 47 if (data.isEmpty()) return 30 48 31 49 file.parentFile?.mkdirs() 32 - file.writeText(Json.encodeToString(JsonObject.serializer(), serialize(data))) 33 - } 34 50 35 - private fun serialize(data: WorldData): JsonObject { 36 - fun encode(value: Any): JsonElement = when (value) { 37 - is Position -> JsonPrimitive(value.serialize()) 38 - is Boolean -> JsonPrimitive(value) 39 - is Long -> JsonPrimitive(value) 40 - is Int -> JsonPrimitive(value) 41 - is Double -> JsonPrimitive(value) 42 - is String -> JsonPrimitive(value) 43 - is List<*> -> JsonArray(value.map { encode(requireNotNull(it)) }) 44 - else -> error("Unsupported value.") 45 - } 51 + val root = buildMap<String, JsonElement> { 52 + data.values().takeIf { it.isNotEmpty() }?.let { 53 + put("values", JsonObject(it.mapValues { (_, v) -> encode(v) })) 54 + } 46 55 47 - return JsonObject(buildMap { 48 - for ((key, value) in data.values()) put(key, encode(value)) 49 - for ((key, section) in data.sections()) put(key, serialize(section)) 50 - }) 51 - } 56 + data.positionValues().takeIf { it.isNotEmpty() }?.let { 57 + put("positions", JsonObject(it.mapValues { (_, p) -> JsonPrimitive(p.serialize()) })) 58 + } 52 59 53 - private fun deserialize(obj: JsonObject): WorldData { 54 - fun decode(element: JsonElement): Any = when (element) { 55 - is JsonPrimitive -> when { 56 - element.content.startsWith("pos:") -> Position.deserialize(element.content) 57 - !element.isString -> element.booleanOrNull ?: element.longOrNull ?: element.doubleOrNull ?: element.content 58 - else -> element.content 60 + data.areaValues().takeIf { it.isNotEmpty() }?.let { areas -> 61 + put("areas", JsonObject(areas.mapValues { (_, a) -> 62 + JsonObject(mapOf("from" to JsonPrimitive(a.first.serialize()), "to" to JsonPrimitive(a.second.serialize()))) 63 + })) 59 64 } 60 65 61 - is JsonArray -> element.map(::decode) 62 - else -> error(WorldDataStore.INCOMPATIBLE) 66 + data.groups().filterValues { it.isNotEmpty() }.takeIf { it.isNotEmpty() }?.let { groups -> 67 + put("groups", JsonObject(groups.mapValues { (_, list) -> 68 + JsonArray(list.map { JsonPrimitive(it.serialize()) }) 69 + })) 70 + } 63 71 } 64 72 65 - fun read(obj: JsonObject, target: WorldData) { 66 - for ((key, element) in obj) { 67 - when (element) { 68 - is JsonObject -> read(element, target.section(key)) 69 - else -> target.set(key, decode(element)) 70 - } 71 - } 73 + file.writeText(Json.encodeToString(JsonObject.serializer(), JsonObject(root))) 74 + } 75 + 76 + private fun encode(value: Any): JsonElement = when (value) { 77 + is Boolean -> JsonPrimitive(value) 78 + is Long -> JsonPrimitive(value) 79 + is Double -> JsonPrimitive(value) 80 + is String -> JsonPrimitive(value) 81 + is List<*> -> JsonArray(value.map { encode(requireNotNull(it)) }) 82 + else -> error(WorldDataStore.INCOMPATIBLE) 83 + } 84 + 85 + private fun decode(element: JsonElement): Any = when (element) { 86 + is JsonPrimitive -> when { 87 + !element.isString -> element.booleanOrNull ?: element.longOrNull ?: element.doubleOrNull ?: element.content 88 + 89 + else -> element.content 72 90 } 73 91 74 - return WorldData().also { read(obj, it) } 92 + is JsonArray -> element.map(::decode) 93 + 94 + else -> error(WorldDataStore.INCOMPATIBLE) 75 95 } 76 96 }
+54 -28
src/main/kotlin/me/lukiiy/mapling/provided/TomlWorldDataStore.kt
··· 13 13 import me.lukiiy.mapling.WorldData 14 14 import me.lukiiy.mapling.WorldDataStore 15 15 import java.io.File 16 + import kotlin.collections.component1 17 + import kotlin.collections.component2 18 + import kotlin.collections.map 16 19 17 20 class TomlWorldDataStore : WorldDataStore { 18 21 override fun load(file: File): WorldData { 19 22 if (!file.exists()) return WorldData() 20 23 21 - return deserialize(Toml.parseToTomlTable(file.readText())) 24 + val root = Toml.parseToTomlTable(file.readText()) 25 + val data = WorldData() 26 + 27 + // parsings & gathering! 28 + (root["values"] as? TomlTable)?.forEach { (k, v) -> data.set(k, decode(v)) } 29 + (root["positions"] as? TomlTable)?.forEach { (k, v) -> data.setPosition(k, Position.deserialize((v as TomlLiteral).content)) } 30 + 31 + (root["areas"] as? TomlTable)?.forEach { (k, v) -> 32 + val value = v as TomlTable 33 + 34 + data.setArea(k, Position.deserialize((value["from"] as TomlLiteral).content), Position.deserialize((value["to"] as TomlLiteral).content)) 35 + } 36 + 37 + (root["groups"] as? TomlTable)?.forEach { (k, v) -> 38 + val list = data.group(k) 39 + 40 + (v as TomlArray).forEach { list.add(Position.deserialize((it as TomlLiteral).content)) } 41 + } 42 + 43 + return data 22 44 } 23 45 24 46 override fun save(file: File, data: WorldData) { 25 47 if (data.isEmpty()) return 26 48 27 49 file.parentFile?.mkdirs() 28 - file.writeText(Toml.encodeToString(serialize(data))) 29 - } 30 50 31 - private fun serialize(data: WorldData): TomlTable { 32 - fun encode(value: Any): Any = when (value) { 33 - is Position -> value.serialize() 34 - is List<*> -> value.map { 35 - encode(requireNotNull(it)) 51 + val root = buildMap<String, TomlElement> { 52 + data.values().takeIf { it.isNotEmpty() }?.let { 53 + put("values", TomlTable(it.mapValues { (_, v) -> encode(v) })) 36 54 } 37 55 38 - else -> value 56 + data.positionValues().takeIf { it.isNotEmpty() }?.let { 57 + put("positions", TomlTable(it.mapValues { (_, p) -> TomlLiteral(p.serialize()) })) 58 + } 59 + 60 + data.areaValues().takeIf { it.isNotEmpty() }?.let { areas -> 61 + put("areas", TomlTable(areas.mapValues { (_, a) -> 62 + TomlTable(mapOf("from" to TomlLiteral(a.first.serialize()), "to" to TomlLiteral(a.second.serialize()))) 63 + })) 64 + } 65 + 66 + data.groups().filterValues { it.isNotEmpty() }.takeIf { it.isNotEmpty() }?.let { groups -> 67 + put("groups", TomlTable(groups.mapValues { (_, list) -> 68 + TomlArray(list.map { TomlLiteral(it.serialize()) }) 69 + })) 70 + } 39 71 } 40 72 41 - return TomlTable(buildMap { 42 - for ((key, value) in data.values()) put(key, encode(value)) 43 - for ((key, section) in data.sections()) put(key, serialize(section)) 44 - }) 73 + file.writeText(Toml.encodeToString(TomlTable(root))) 45 74 } 46 75 47 - private fun deserialize(table: TomlTable): WorldData { 48 - fun decode(element: TomlElement): Any = when (element) { 49 - is TomlLiteral -> element.toBooleanOrNull() ?: element.toLongOrNull() ?: element.toDoubleOrNull() ?: element.content.takeIf { it.startsWith("pos:") }?.let(Position::deserialize) ?: element.content 50 - is TomlArray -> element.map(::decode) 76 + private fun encode(value: Any): TomlElement = when (value) { 77 + is Boolean -> TomlLiteral(value) 78 + is Long -> TomlLiteral(value) 79 + is Double -> TomlLiteral(value) 80 + is String -> TomlLiteral(value) 81 + is List<*> -> TomlArray(value.map { encode(requireNotNull(it)) }) 82 + else -> error(WorldDataStore.INCOMPATIBLE) 83 + } 51 84 52 - else -> error(WorldDataStore.INCOMPATIBLE) 53 - } 85 + private fun decode(element: TomlElement): Any = when (element) { 86 + is TomlLiteral -> element.toBooleanOrNull() ?: element.toLongOrNull() ?: element.toDoubleOrNull() ?: element.content 54 87 55 - fun read(table: TomlTable, target: WorldData) { 56 - for ((key, element) in table) { 57 - when (element) { 58 - is TomlTable -> read(element, target.section(key)) 59 - else -> target.set(key, decode(element)) 60 - } 61 - } 62 - } 88 + is TomlArray -> element.map(::decode) 63 89 64 - return WorldData().also { read(table, it) } 90 + else -> error(WorldDataStore.INCOMPATIBLE) 65 91 } 66 92 }