diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt index b62d7f57e..ecacac754 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.datagen.loot import net.minecraft.advancements.critereon.StatePropertiesPredicate import net.minecraft.util.StringRepresentable -import net.minecraft.world.item.Rarity import net.minecraft.world.level.ItemLike import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.properties.Property @@ -17,7 +16,6 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.providers.number.ConstantValue import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator import ru.dbotthepony.mc.otm.data.condition.ChanceCondition -import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction inline fun LootTable.Builder.lootPool(configurator: LootPool.Builder.() -> Unit): LootTable.Builder = withPool(LootPool.lootPool().also(configurator)) inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootTable.Builder { @@ -29,18 +27,6 @@ inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSi inline fun lootPool(configurator: LootPool.Builder.() -> Unit): LootPool = LootPool.lootPool().also(configurator).build() inline fun singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootPool = lootPool { item(item, configurator) } -fun singleRandomizedItem(item: ItemLike, rarity: Rarity = Rarity.COMMON, chance: Double? = null): LootPool { - return lootPool { - item(item) { - apply(RandomizerFunction.valueOf(rarity)) - - if (chance != null) { - chanceCondition(chance) - } - } - } -} - inline fun LootPool.Builder.item(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit) { add(LootItem.lootTableItem(item).also(configurator)) } 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 6b3002281..cd236189d 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 @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.datagen.loot import net.minecraft.resources.ResourceLocation +import net.minecraft.util.valueproviders.UniformInt import net.minecraft.world.entity.EntityType import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Rarity @@ -14,8 +15,8 @@ import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender -import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem +import ru.dbotthepony.mc.otm.item.exopack.ProceduralExoPackSlotUpgradeItem import ru.dbotthepony.mc.otm.registry.MItems @Suppress("FunctionName") @@ -29,24 +30,32 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition { } fun addLootModifiers(it: LootModifiers) { - it.add("dungeon_exosuit", LootPoolAppender( + it.add("dungeon_exopack", LootPoolAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { chanceCondition(0.2) - apply(RandomizerFunction.COMMON) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(6, 9))) }, singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { chanceCondition(0.05) - apply(RandomizerFunction.UNCOMMON) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18))) }, )) it.add("mineshaft_additions", LootPoolAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1, rarity = Rarity.UNCOMMON), + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.1) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(4, 8))) + }, + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.1) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(4, 10))) + }, singleItem(MItems.PROCEDURAL_BATTERY) { chanceCondition(0.15) @@ -61,21 +70,49 @@ fun addLootModifiers(it: LootModifiers) { it.add("desert_pyramid_exosuit", LootPoolAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.25, rarity = Rarity.COMMON) + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.1) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(12, 18))) + }, + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.25) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(4, 9))) + }, )) it.add("jungle_temple_exosuit", LootPoolAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.35, rarity = Rarity.RARE) + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.15) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18))) + }, + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.35) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(16, 28), UniformInt.of(2, 6))) + }, )) it.add("end_city_exosuit", LootPoolAppender( arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.4, rarity = Rarity.UNCOMMON), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.2, rarity = Rarity.RARE), - singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.EPIC), + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.4) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18))) + }, + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.2) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(14, 27), UniformInt.of(2, 6))) + }, + + singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { + chanceCondition(0.1) + apply(ProceduralExoPackSlotUpgradeItem.Randomizer(UniformInt.of(27, 56), UniformInt.of(2, 6))) + }, )) it.add("dungeon_pill", PlainLootAppender( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/Ext.kt index bd3f096c1..6cf8c6434 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/Ext.kt @@ -1,8 +1,10 @@ package ru.dbotthepony.mc.otm.data import com.mojang.serialization.DataResult +import net.minecraft.world.entity.player.Player import net.minecraft.world.level.storage.loot.LootContext import net.minecraft.world.level.storage.loot.parameters.LootContextParam +import net.minecraft.world.level.storage.loot.parameters.LootContextParams operator fun LootContext.get(param: LootContextParam): T? { return getParamOrNull(param) @@ -11,3 +13,14 @@ operator fun LootContext.get(param: LootContextParam): T? { fun DataResult.getOrNull(): T? { return get().left().orElse(null) } + +fun LootContext.findPlayer(): Player? { + return getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY).let { + if (it != null) + it as? Player + else + getParamOrNull(LootContextParams.KILLER_ENTITY).let { + if (it != null) it as? Player else getParamOrNull(LootContextParams.THIS_ENTITY) as? Player + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/IRandomizableItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/IRandomizableItem.kt deleted file mode 100644 index b649659ac..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/IRandomizableItem.kt +++ /dev/null @@ -1,11 +0,0 @@ -package ru.dbotthepony.mc.otm.data.loot - -import net.minecraft.util.RandomSource -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemStack -import net.minecraft.world.item.Rarity -import net.minecraft.world.level.ItemLike - -interface IRandomizableItem { - fun randomize(itemStack: ItemStack, random: RandomSource, ply: Player?, rarity: Rarity = Rarity.COMMON) -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/RandomizerFunction.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/RandomizerFunction.kt deleted file mode 100644 index 822fdee36..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/data/loot/RandomizerFunction.kt +++ /dev/null @@ -1,82 +0,0 @@ -package ru.dbotthepony.mc.otm.data.loot - -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonObject -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSyntaxException -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemStack -import net.minecraft.world.item.Rarity -import net.minecraft.world.level.storage.loot.LootContext -import net.minecraft.world.level.storage.loot.Serializer -import net.minecraft.world.level.storage.loot.functions.LootItemFunction -import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType -import net.minecraft.world.level.storage.loot.parameters.LootContextParams -import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.core.set -import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes - -enum class RandomizerFunction(val rarity: Rarity) : LootItemFunction, LootItemFunction.Builder { - COMMON(Rarity.COMMON), - UNCOMMON(Rarity.UNCOMMON), - RARE(Rarity.RARE), - EPIC(Rarity.EPIC); - - override fun apply(itemStack: ItemStack, context: LootContext): ItemStack { - val randomizer = itemStack.item as? IRandomizableItem - - if (randomizer == null) { - LOGGER.error("${itemStack.item} does not implement ${IRandomizableItem::class.qualifiedName}! Can not randomize $itemStack!") - return itemStack - } - - val random = context.random - - val player = - context.getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY).let { - if (it != null) - it as? Player - else - context.getParamOrNull(LootContextParams.KILLER_ENTITY).let { - if (it != null) - it as? Player - else - context.getParamOrNull(LootContextParams.THIS_ENTITY) as? Player - } - } - - randomizer.randomize(itemStack, random, player, rarity) - return itemStack - } - - override fun getType(): LootItemFunctionType { - return MItemFunctionTypes.RANDOMIZER - } - - override fun build(): LootItemFunction { - return this - } - - companion object : Serializer { - fun valueOf(rarity: Rarity): RandomizerFunction { - return when(rarity) { - Rarity.COMMON -> COMMON - Rarity.UNCOMMON -> UNCOMMON - Rarity.RARE -> RARE - Rarity.EPIC -> EPIC - } - } - - override fun serialize(p_79325_: JsonObject, p_79326_: RandomizerFunction, p_79327_: JsonSerializationContext) { - p_79325_["rarity"] = JsonPrimitive(p_79326_.rarity.name) - } - - override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): RandomizerFunction { - return valueOf(Rarity.valueOf(p_79323_["rarity"]?.asString ?: throw JsonSyntaxException("Invalid rarity json element"))) - } - - private val LOGGER = LogManager.getLogger() - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ProceduralExoPackSlotUpgradeItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ProceduralExoPackSlotUpgradeItem.kt index c4b7d8915..940e4d8b1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ProceduralExoPackSlotUpgradeItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ProceduralExoPackSlotUpgradeItem.kt @@ -1,27 +1,48 @@ package ru.dbotthepony.mc.otm.item.exopack +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component -import net.minecraft.util.RandomSource -import net.minecraft.world.entity.player.Player +import net.minecraft.util.valueproviders.ConstantInt +import net.minecraft.util.valueproviders.IntProvider import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Rarity import net.minecraft.world.item.TooltipFlag import net.minecraft.world.level.Level +import net.minecraft.world.level.storage.loot.LootContext +import net.minecraft.world.level.storage.loot.functions.LootItemFunction +import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.tagNotNull -import ru.dbotthepony.mc.otm.data.loot.IRandomizableItem +import ru.dbotthepony.mc.otm.data.Codec2Serializer +import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes import java.util.* -class ProceduralExoPackSlotUpgradeItem : AbstractExoPackSlotUpgradeItem(defaultProperties()), IRandomizableItem { - override fun getRarity(itemStack: ItemStack): Rarity { - return when (slotCount(itemStack)) { - in 0 .. 9 -> Rarity.COMMON - in 10 .. 18 -> Rarity.UNCOMMON - in 19 .. 27 -> Rarity.RARE - in 28 .. 36 -> Rarity.EPIC - else -> Rarity.EPIC +class ProceduralExoPackSlotUpgradeItem : AbstractExoPackSlotUpgradeItem(defaultProperties()) { + class Randomizer(val slots: IntProvider, val luckBias: IntProvider = ConstantInt.ZERO) : LootItemFunction, LootItemFunction.Builder { + override fun apply(t: ItemStack, u: LootContext): ItemStack { + t.tagNotNull[SLOT_COUNT_KEY] = slots.sample(u.random) + (luckBias.sample(u.random) * u.luck / 1024f).coerceAtLeast(0f).toInt() + return t + } + + override fun getType(): LootItemFunctionType { + return MItemFunctionTypes.PROCEDURAL_EXOPACK_UPGRADE + } + + override fun build(): LootItemFunction { + return this + } + + companion object { + val SERIALIZER = Codec2Serializer( + RecordCodecBuilder.create { + it.group( + IntProvider.CODEC.fieldOf("slots").forGetter(Randomizer::slots), + IntProvider.CODEC.optionalFieldOf("luck_bias", ConstantInt.ZERO).forGetter(Randomizer::luckBias), + ).apply(it, ::Randomizer) + } + ) } } @@ -50,30 +71,6 @@ class ProceduralExoPackSlotUpgradeItem : AbstractExoPackSlotUpgradeItem(defaultP } } - override fun randomize(itemStack: ItemStack, random: RandomSource, ply: Player?, rarity: Rarity) { - var amount = random.nextIntBetweenInclusive(6, 9) - val luck = (ply?.luck ?: 0f) * 0.3f - val finalLuck = (0.5f - (luck / 512f).coerceAtLeast(-0.3f).coerceAtMost(0.3f)) - - if (random.nextFloat() >= finalLuck && rarity.ordinal >= Rarity.UNCOMMON.ordinal) { - amount += random.nextIntBetweenInclusive(4, 9) - - if (random.nextFloat() >= finalLuck && rarity.ordinal >= Rarity.RARE.ordinal) { - amount += random.nextIntBetweenInclusive(6, 9) - - if (random.nextFloat() >= finalLuck && rarity.ordinal >= Rarity.EPIC.ordinal) { - amount += random.nextIntBetweenInclusive(8, 12) - - if (random.nextFloat() >= finalLuck) { - amount += random.nextIntBetweenInclusive(14, 18) - } - } - } - } - - itemStack.tagNotNull[SLOT_COUNT_KEY] = amount - } - companion object { const val SLOT_COUNT_KEY = "slotCount" const val UUID_KEY = "uuid" diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt index d30b97e29..f8005cdad 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt @@ -6,15 +6,15 @@ import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction -import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem +import ru.dbotthepony.mc.otm.item.exopack.ProceduralExoPackSlotUpgradeItem object MItemFunctionTypes { private val registry = DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, OverdriveThatMatters.MOD_ID) - val RANDOMIZER: LootItemFunctionType by registry.register("randomizer") { LootItemFunctionType(RandomizerFunction.Companion) } val COPY_TILE_NBT: LootItemFunctionType by registry.register("copy_tile_nbt") { LootItemFunctionType(CopyTileNbtFunction.Companion) } val PROCEDURAL_BATTERY: LootItemFunctionType by registry.register(MNames.PROCEDURAL_BATTERY) { LootItemFunctionType(ProceduralBatteryItem.Randomizer.SERIALIZER) } + val PROCEDURAL_EXOPACK_UPGRADE: LootItemFunctionType by registry.register("exopack_upgrade") { LootItemFunctionType(ProceduralExoPackSlotUpgradeItem.Randomizer.SERIALIZER) } internal fun register(bus: IEventBus) { registry.register(bus)