diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt index 16795d267..d96d09c95 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.data.IRandomizableItem import ru.dbotthepony.mc.otm.data.ItemInInventoryCondition import ru.dbotthepony.mc.otm.data.KilledByRealPlayer import ru.dbotthepony.mc.otm.data.BasicLootAppender -import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender +import ru.dbotthepony.mc.otm.data.PlainLootAppender import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender import ru.dbotthepony.mc.otm.registry.MItems @@ -26,7 +26,7 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition { } fun addLootModifiers(it: LootModifiers) { - it.add("dungeon_pill", LootTableSeparatedAppender( + it.add("dungeon_pill", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), ItemStack(MItems.PILL_ANDROID, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 2) to 0.5, @@ -41,7 +41,7 @@ fun addLootModifiers(it: LootModifiers) { ) )) - it.add("mineshaft_pill", LootTableSeparatedAppender( + it.add("mineshaft_pill", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), ItemStack(MItems.PILL_ANDROID, 1) to 0.075, ItemStack(MItems.PILL_HEAL, 2) to 0.1, @@ -56,14 +56,14 @@ fun addLootModifiers(it: LootModifiers) { ) )) - it.add("mineshaft_nutrient_paste", LootTableSeparatedAppender( + it.add("mineshaft_nutrient_paste", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), ItemStack(MItems.NUTRIENT_PASTE, 6) to 0.5, ItemStack(MItems.NUTRIENT_PASTE, 8) to 0.35, ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.15, )) - it.add("desert_pyramid_pill", LootTableSeparatedAppender( + it.add("desert_pyramid_pill", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), ItemStack(MItems.PILL_ANDROID, 1) to 0.05, ItemStack(MItems.PILL_HEAL, 1) to 0.3, @@ -77,7 +77,7 @@ fun addLootModifiers(it: LootModifiers) { ) )) - it.add("jungle_temple_pill", LootTableSeparatedAppender( + it.add("jungle_temple_pill", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)), ItemStack(MItems.PILL_ANDROID, 1) to 0.5 )) @@ -90,7 +90,7 @@ fun addLootModifiers(it: LootModifiers) { ) )) - it.add("end_city_modifications", LootTableSeparatedAppender( + it.add("end_city_modifications", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_HUMANE, 1) to 0.3, @@ -107,7 +107,7 @@ fun addLootModifiers(it: LootModifiers) { ) )) - it.add("shipwreck_supply_pill", LootTableSeparatedAppender( + it.add("shipwreck_supply_pill", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)), ItemStack(MItems.PILL_HUMANE, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 1) to 0.6, @@ -116,7 +116,7 @@ fun addLootModifiers(it: LootModifiers) { ItemStack(MItems.PILL_HEAL, 1) to 0.6, )) - it.add("shipwreck_supply_nutrient_paste", LootTableSeparatedAppender( + it.add("shipwreck_supply_nutrient_paste", PlainLootAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)), ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.85, ItemStack(MItems.NUTRIENT_PASTE, 24) to 0.35, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/ItemStackCodec.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/ItemStackCodec.kt index e8d169708..a2a42a34d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/ItemStackCodec.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/ItemStackCodec.kt @@ -26,18 +26,18 @@ import ru.dbotthepony.mc.otm.core.set import java.lang.reflect.Type object ItemStackCodec : Codec, TypeAdapter(), JsonSerializer, JsonDeserializer { - override fun encode(input: ItemStack, ops: DynamicOps, prefix: T): DataResult { + override fun encode(input: ItemStack, ops: DynamicOps, prefix: T): DataResult { require(prefix == ops.empty()) { "Non-empty prefix: $prefix" } - return ForgeRegistries.ITEMS.codec.encode(input.item, ops, ops.empty()).map { - ops.createMap(mapOf( + return ForgeRegistries.ITEMS.codec.encode(input.item, ops, ops.empty()).flatMap { + DataResult.success(ops.createMap(linkedMapOf( ops.createString("id") to it, ops.createString("count") to ops.createInt(input.count) - )) + ))) } } - override fun decode(ops: DynamicOps, input: T): DataResult> { + override fun decode(ops: DynamicOps, input: T): DataResult> { return ops.getMap(input).flatMap { val item = it["id"]?.let { ForgeRegistries.ITEMS.codec.decode(ops, it) }?.result()?.orElse(null)?.first val count = it["count"]?.let(ops::getNumberValue)?.result()?.orElse(null)?.toInt() ?: return@flatMap DataResult.error("Invalid item count") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootPoolAppender.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootPoolAppender.kt index 2f086ec75..cf1b69275 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootPoolAppender.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/LootPoolAppender.kt @@ -8,7 +8,6 @@ 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 import net.minecraft.world.level.storage.loot.Deserializers import net.minecraft.world.level.storage.loot.LootContext @@ -16,34 +15,15 @@ import net.minecraft.world.level.storage.loot.LootPool import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraftforge.common.loot.IGlobalLootModifier import net.minecraftforge.common.loot.LootModifier -import net.minecraftforge.registries.ForgeRegistries -import ru.dbotthepony.mc.otm.core.registryName +import java.util.Arrays +import java.util.stream.Stream -// 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) -} +class LootPoolAppender(conditions: Array, pools: Stream) : LootModifier(conditions) { + private val pools = pools.collect(ImmutableList.toImmutableList()) -private val LootPoolCodec: Codec> by lazy { - val serializer = Deserializers.createLootTableSerializer().create() + constructor(conditions: Array, pools: Collection) : this(conditions, pools.stream()) + constructor(conditions: Array, vararg pools: LootPool) : this(conditions, Arrays.stream(pools)) - 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 LootPoolAppender(conditions: Array, private vararg val pools: LootPool) : LootModifier(conditions) { override fun doApply(generatedLoot: ObjectArrayList, context: LootContext): ObjectArrayList { pools.forEach { it.addRandomItems(generatedLoot::add, context) } return generatedLoot @@ -54,93 +34,37 @@ class LootPoolAppender(conditions: Array, private vararg } companion object { - val CODEC: Codec by lazy { - RecordCodecBuilder.create { - codecStart(it).and( - LootPoolCodec.fieldOf("pools").forGetter { appender -> appender.pools as Array } - ).apply(it, ::LootPoolAppender) - } - } - } -} - -class LootTableSeparatedAppender(conditions: Array, entries: List>) : LootModifier(conditions) { - constructor(conditions: Array, vararg entries: Pair) : this(conditions, entries.toList()) - - private val entries = ImmutableList.copyOf(entries) - - override fun doApply(generatedLoot: ObjectArrayList, context: LootContext): ObjectArrayList { - for ((item, chance) in entries) { - if (context.random.nextDouble() <= chance) { - generatedLoot.add(item.copy()) - } + // same bro + 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) } - return generatedLoot - } + private val lootPoolCodec: Codec> - override fun codec(): Codec { - return CODEC - } + init { + val serializer = Deserializers.createLootTableSerializer().create() - companion object { - val ItemPairListCodec: Codec>> by lazy { - Codec.PASSTHROUGH.flatXmap({ + lootPoolCodec = Codec.list(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.success(serializer.fromJson(getJson(it as Dynamic), LootPool::class.java)) + } catch(err: JsonSyntaxException) { 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.success(Dynamic(JsonOps.INSTANCE, serializer.toJsonTree(it))) + } catch(err: JsonSyntaxException) { DataResult.error(err.message) } - }) + })) } - val CODEC: Codec by lazy { + val CODEC: Codec = RecordCodecBuilder.create { codecStart(it).and( - ItemPairListCodec.fieldOf("entries").forGetter { appender -> appender.entries } - ).apply(it, ::LootTableSeparatedAppender) + lootPoolCodec.fieldOf("pools").forGetter(LootPoolAppender::pools) + ).apply(it, ::LootPoolAppender) } - } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/PlainLootAppender.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/PlainLootAppender.kt new file mode 100644 index 000000000..614933aef --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/PlainLootAppender.kt @@ -0,0 +1,52 @@ +package ru.dbotthepony.mc.otm.data + +import com.google.common.collect.ImmutableList +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.storage.loot.LootContext +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition +import net.minecraftforge.common.loot.IGlobalLootModifier +import net.minecraftforge.common.loot.LootModifier +import java.util.* +import java.util.stream.Stream + +class PlainLootAppender(conditions: Array, entries: Stream>) : LootModifier(conditions) { + constructor(conditions: Array, vararg entries: Pair) : this(conditions, Arrays.stream(entries)) + constructor(conditions: Array, entries: Collection>) : this(conditions, entries.stream()) + + private val entries = entries.map { it.first.copy() to it.second }.collect(ImmutableList.toImmutableList()) + + override fun doApply(generatedLoot: ObjectArrayList, context: LootContext): ObjectArrayList { + for ((item, chance) in entries) { + if (context.random.nextDouble() <= chance) { + generatedLoot.add(item.copy()) + } + } + + return generatedLoot + } + + override fun codec(): Codec { + return CODEC + } + + companion object { + private val paircodec: Codec> = RecordCodecBuilder.create { + it.group( + ItemStackCodec.fieldOf("item").forGetter { it.first }, + Codec.DOUBLE.fieldOf("chance").forGetter { it.second } + ).apply(it, ::Pair) + } + + private val pairlistcodec = Codec.list(paircodec) + + val CODEC: Codec = + RecordCodecBuilder.create { + codecStart(it).and( + pairlistcodec.fieldOf("entries").forGetter(PlainLootAppender::entries) + ).apply(it, ::PlainLootAppender) + } + } +} 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 30b4b347d..d9051b0b2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt @@ -6,7 +6,7 @@ import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.data.LootPoolAppender import ru.dbotthepony.mc.otm.data.BasicLootAppender -import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender +import ru.dbotthepony.mc.otm.data.PlainLootAppender import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender object LootModifiers { @@ -14,7 +14,7 @@ object LootModifiers { init { registry.register("loot_appender") { LootPoolAppender.CODEC } - registry.register("loot_appender_separated") { LootTableSeparatedAppender.CODEC } + registry.register("loot_appender_separated") { PlainLootAppender.CODEC } registry.register("loot_appender_basic") { BasicLootAppender.CODEC } registry.register("randomizable_item_loot_appender") { RandomizableItemLootAppender.Companion } }