From fc736528ddc27c17055486fe00cc1df7fa175e91 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 19 Aug 2022 12:32:01 +0700 Subject: [PATCH] Move loot modifiers to 'convenient' and 'powerful' codecs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UndefinedBHVR — 22.08.2021 "Unconventional" is an understatement, there's some things there that are just.. "This is the worst way possible to do this, why would you do this Mojang?" --- .../mc/otm/data/LootTableAppender.kt | 186 +++++++++--------- .../mc/otm/registry/LootModifiers.kt | 4 +- 2 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootTableAppender.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootTableAppender.kt index 329a8a277..15b005625 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootTableAppender.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootTableAppender.kt @@ -1,12 +1,12 @@ package ru.dbotthepony.mc.otm.data import com.google.common.collect.ImmutableList -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import com.google.gson.JsonParseException +import com.google.gson.* import com.mojang.serialization.Codec import com.mojang.serialization.DataResult -import com.mojang.serialization.DynamicOps +import com.mojang.serialization.Dynamic +import com.mojang.serialization.JsonOps +import com.mojang.serialization.codecs.RecordCodecBuilder import it.unimi.dsi.fastutil.objects.ObjectArrayList import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.ItemStack @@ -19,6 +19,29 @@ import net.minecraftforge.common.loot.LootModifier import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.registryName +// 1.19 do be like overengineering already overengineered stuff beyond any recognition +private fun getJson(it: Dynamic): JsonElement { + val value = it.value ?: throw NullPointerException("value was null") + return value as? JsonElement ?: it.ops.convertTo(JsonOps.INSTANCE, it) +} + +private val LootPoolCodec: Codec> by lazy { + val serializer = Deserializers.createLootTableSerializer().create() + + Codec.PASSTHROUGH.flatXmap({ + try { + DataResult.success(serializer.fromJson(getJson(it as Dynamic), Array::class.java)) + } catch(err: JsonSyntaxException) { + DataResult.error(err.message) + } + }, { + try { + DataResult.success(Dynamic(JsonOps.INSTANCE, serializer.toJsonTree(it))) + } catch(err: JsonSyntaxException) { + DataResult.error(err.message) + } + }) +} class LootTableAppender(conditions: Array, private vararg val pools: LootPool) : LootModifier(conditions) { override fun doApply(generatedLoot: ObjectArrayList, context: LootContext): ObjectArrayList { @@ -27,51 +50,25 @@ class LootTableAppender(conditions: Array, private vararg } override fun codec(): Codec { - return Companion + return CODEC } - companion object : Codec { - override fun encode(input: LootTableAppender?, ops: DynamicOps?, prefix: T): DataResult { - return DataResult.error("NYI") - } - - override fun decode( - ops: DynamicOps?, - input: T - ): DataResult> { - return DataResult.error("NYI") - } - - private val lootPoolGson = Deserializers.createLootTableSerializer().create() - - /*override fun read( - location: ResourceLocation, - `object`: JsonObject, - ailootcondition: Array - ): LootTableAppender { - val pools = lootPoolGson.fromJson(`object`["pools"], Array::class.java) ?: throw JsonParseException("Invalid 'pools' entry") - pools.forEach { - @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") - it!! + companion object { + val CODEC: Codec by lazy { + RecordCodecBuilder.create { + codecStart(it).and( + LootPoolCodec.fieldOf("pools").forGetter { appender -> appender.pools as Array } + ).apply(it, ::LootTableAppender) } - return LootTableAppender(ailootcondition, *pools) } - - override fun write(instance: LootTableAppender): JsonObject { - val build = makeConditions(instance.conditions) - build.add("pools", lootPoolGson.toJsonTree(instance.pools)) - return build - }*/ } } -class LootTableBasicAppender(conditions: Array, items: List>) : LootModifier(conditions) { - private val items = ImmutableList.copyOf(items) - - constructor(conditions: Array, vararg items: Pair) : this(conditions, items.toList()) +class LootTableBasicAppender(conditions: Array, entries: List>) : LootModifier(conditions) { + private val entries = ImmutableList.copyOf(entries) override fun doApply(generatedLoot: ObjectArrayList, context: LootContext): ObjectArrayList { - for ((item, chance) in items) { + for ((item, chance) in entries) { if (context.random.nextDouble() <= chance) { generatedLoot.add(item.copy()) } @@ -81,64 +78,67 @@ class LootTableBasicAppender(conditions: Array, items: Li } override fun codec(): Codec { - return Companion + return CODEC } - companion object : Codec { - override fun encode(input: LootTableBasicAppender?, ops: DynamicOps?, prefix: T): DataResult { - return DataResult.error("NYI") + companion object { + val ItemPairListCodec: Codec>> by lazy { + Codec.PASSTHROUGH.flatXmap({ + try { + val entries = ArrayList>() + + for (entry in getJson(it as Dynamic).asJsonArray) { + entry as JsonObject + val item = entry["item"]?.asJsonObject ?: throw JsonParseException("Missing 'item'") + val name = item["name"]?.asString ?: throw JsonParseException("Missing 'item.name'") + val count = item["count"]?.asInt ?: throw JsonParseException("Missing 'item.count'") + val chance = entry["chance"]?.asDouble ?: throw JsonParseException("Missing 'chance'") + + val itemObj = ForgeRegistries.ITEMS.getValue(ResourceLocation(name)) + ?: throw JsonParseException("Unknown item $name") + val stack = ItemStack(itemObj, count) + + entries.add(stack to chance) + } + + DataResult.success(entries) + } catch (err: JsonSyntaxException) { + DataResult.error(err.message) + } catch (err: JsonParseException) { + DataResult.error(err.message) + } + }, { + try { + val listing = JsonArray() + + for ((item, chance) in it) { + val entry = JsonObject() + + entry.add("item", JsonObject().also { + it.addProperty("name", item.item.registryName!!.toString()) + it.addProperty("count", item.count) + }) + + entry.addProperty("chance", chance) + + listing.add(entry) + } + + DataResult.success(Dynamic(JsonOps.INSTANCE, listing)) + } catch (err: JsonSyntaxException) { + DataResult.error(err.message) + } catch (err: JsonParseException) { + DataResult.error(err.message) + } + }) } - override fun decode( - ops: DynamicOps?, - input: T - ): DataResult> { - return DataResult.error("NYI") - } - - /*override fun read( - location: ResourceLocation, - obj: JsonObject, - ailootcondition: Array - ): LootTableBasicAppender { - val entries = ArrayList>() - - for (entry in obj["entries"].asJsonArray) { - entry as JsonObject - val item = entry["item"]?.asJsonObject ?: throw JsonParseException("Missing 'item'") - val name = item["name"]?.asString ?: throw JsonParseException("Missing 'item.name'") - val count = item["count"]?.asInt ?: throw JsonParseException("Missing 'item.count'") - val chance = entry["chance"]?.asDouble ?: throw JsonParseException("Missing 'chance'") - - val itemObj = ForgeRegistries.ITEMS.getValue(ResourceLocation(name)) ?: throw JsonParseException("Unknown item $name") - val stack = ItemStack(itemObj, count) - - entries.add(stack to chance) + val CODEC: Codec by lazy { + RecordCodecBuilder.create { + codecStart(it).and( + ItemPairListCodec.fieldOf("entries").forGetter { appender -> appender.entries } + ).apply(it, ::LootTableBasicAppender) } - - return LootTableBasicAppender(ailootcondition, ImmutableList.copyOf(entries)) } - - override fun write(instance: LootTableBasicAppender): JsonObject { - val obj = makeConditions(instance.conditions) - val listing = JsonArray() - - for ((item, chance) in instance.items) { - val entry = JsonObject() - - entry.add("item", JsonObject().also { - it.addProperty("name", item.item.registryName!!.toString()) - it.addProperty("count", item.count) - }) - - entry.addProperty("chance", chance) - - listing.add(entry) - } - - obj.add("entries", listing) - - return obj - }*/ } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt index 9da28f24c..d646f916f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt @@ -11,8 +11,8 @@ import ru.dbotthepony.mc.otm.data.LootTableBasicAppender object LootModifiers { private val registry = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, OverdriveThatMatters.MOD_ID) - val LOOT_TABLE_APPENDER: Codec by registry.register("loot_table_appender") { LootTableAppender.Companion } - val LOOT_TABLE_BASIC_APPENDER: Codec by registry.register("loot_table_basic_appender") { LootTableBasicAppender.Companion } + val LOOT_TABLE_APPENDER: Codec by registry.register("loot_appender") { LootTableAppender.CODEC } + val LOOT_TABLE_BASIC_APPENDER: Codec by registry.register("loot_appender_basic") { LootTableBasicAppender.CODEC } internal fun register() { registry.register(FMLJavaModLoadingContext.get().modEventBus)