diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt index 3c3bc4241..a2a9531be 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.datagen.items +import com.google.common.collect.Streams import net.minecraft.resources.ResourceLocation import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.datagen.DataGen @@ -52,18 +53,22 @@ fun addItemModels(provider: MatteryItemModelProvider) { provider.generated(MItems.PILL_HEAL) provider.generated(MItems.NUTRIENT_PASTE) - for (item in MItems.EXOSUIT_INVENTORY_UPGRADES_CRAFTABLE) { - provider.generated(item, ResourceLocation(DataGen.MOD_ID, "item/exosuit_inventory_upgrade")) + for (item in MItems.ExosuitUpgrades.INVENTORY_UPGRADES) { + provider.generated(item, modLocation("item/exosuit_inventory_upgrade")) } - for (item in MItems.EXOSUIT_INVENTORY_UPGRADES_UNCRAFTABLE) { - provider.KOT(item) + for (item in listOf( + MItems.ExosuitUpgrades.INVENTORY_UPGRADE_HUGE, + MItems.ExosuitUpgrades.INVENTORY_UPGRADE_BIG, + MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, + MItems.ExosuitUpgrades.INVENTORY_UPGRADE_WITHER, + MItems.ExosuitUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, + )) { + provider.generated(item, modLocation("item/exosuit_inventory_upgrade")) } - provider.generated(MItems.EXOSUIT_INVENTORY_UPGRADE_CREATIVE) - provider.generated(MItems.EXOSUIT_CRAFTING_UPGRADE) - provider.KOT(MItems.EXOSUIT_INVENTORY_UPGRADE_BIG) - provider.KOT(MItems.EXOSUIT_INVENTORY_UPGRADE_HUGE) + provider.generated(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_CREATIVE) + provider.generated(MItems.ExosuitUpgrades.CRAFTING_UPGRADE) provider.component(MItems.TRITANIUM_INGOT) provider.resource(MItems.TRITANIUM_ORE_CLUMP) @@ -112,16 +117,6 @@ fun addItemModels(provider: MatteryItemModelProvider) { provider.block(MItems.STORAGE_IMPORTER) provider.block(MItems.STORAGE_EXPORTER) - provider.generated(MItems.EXOSUIT_CRAFTING_UPGRADE) - provider.generated(MItems.EXOSUIT_INVENTORY_UPGRADE_CREATIVE) - - provider.generatedStrict(MItems.EXOSUIT_INVENTORY_UPGRADE_BIG, "exosuit_inventory_upgrade") - provider.generatedStrict(MItems.EXOSUIT_INVENTORY_UPGRADE_HUGE, "exosuit_inventory_upgrade") - - for (item in MItems.EXOSUIT_INVENTORY_UPGRADES) { - provider.generatedStrict(item, "exosuit_inventory_upgrade") - } - for ((color, item) in MItems.CARGO_CRATE_MINECARTS) { provider.generated(item) } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 98474103b..6fd84cfc4 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -415,8 +415,17 @@ private fun blocks(provider: MatteryLanguageProvider) { private fun items(provider: MatteryLanguageProvider) { with(provider.english) { add(MItems.EXOSUIT_PROBE, "Exosuit Probe") - add(MItems.EXOSUIT_INVENTORY_UPGRADE_CREATIVE, "Creative Exosuit Inventory Upgrade") - add(MItems.EXOSUIT_CRAFTING_UPGRADE, "Exosuit Crafting Upgrade") + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exosuit Inventory Upgrade") + add(MItems.ExosuitUpgrades.CRAFTING_UPGRADE, "Exosuit Crafting Upgrade") + + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_WITHER, "Superdense Packing Upgrade") + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Utilizes similar principle that exhibit Nether Stars") + + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "Ender Link Pocket Dimension Upgrade") + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "description", "Allows to store items in portative pocket dimension") + + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "Indescribable Exosuit Inventory Upgrade") + add(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "description", "They normally generate in dungeons with appropriate NBT tag attached") add(MItems.NUTRIENT_PASTE, "Nutrient paste") 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 aa0114199..45a9c5d40 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,17 +1,23 @@ 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 +import net.minecraft.world.level.storage.loot.BuiltInLootTables import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.predicates.LootItemKilledByPlayerCondition import net.minecraftforge.common.loot.LootTableIdCondition import ru.dbotthepony.mc.otm.data.ChanceWithPlaytimeCondition import ru.dbotthepony.mc.otm.data.HasExosuitCondition +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.LootTableBasicAppender import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender +import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender +import ru.dbotthepony.mc.otm.item.ProceduralExoSuitSlotUpgradeItem import ru.dbotthepony.mc.otm.registry.MItems fun LootTableIdCondition(location: String): LootItemCondition { @@ -24,53 +30,97 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition { fun addLootModifiers(it: LootModifiers) { it.add("dungeon_pill", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/simple_dungeon")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), ItemStack(MItems.PILL_ANDROID, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 2) to 0.5, ItemStack(MItems.PILL_HEAL, 1) to 0.75, )) + it.add("dungeon_exosuit", RandomizableItemLootAppender( + arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), + listOf( + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.2), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.05, rarity = Rarity.UNCOMMON) + ) + )) + it.add("mineshaft_pill", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), ItemStack(MItems.PILL_ANDROID, 1) to 0.075, ItemStack(MItems.PILL_HEAL, 2) to 0.1, ItemStack(MItems.PILL_HEAL, 1) to 0.4, )) + it.add("mineshaft_exosuit", RandomizableItemLootAppender( + arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), + listOf( + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.1), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.01, rarity = Rarity.UNCOMMON) + ) + )) + it.add("mineshaft_nutrient_paste", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), + 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( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), ItemStack(MItems.PILL_ANDROID, 1) to 0.05, ItemStack(MItems.PILL_HEAL, 1) to 0.3, )) + it.add("desert_pyramid_exosuit", RandomizableItemLootAppender( + arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), + listOf( + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.UNCOMMON), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.25, rarity = Rarity.COMMON), + ) + )) + it.add("jungle_temple_pill", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/jungle_temple")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)), ItemStack(MItems.PILL_ANDROID, 1) to 0.5 )) + it.add("jungle_temple_exosuit", RandomizableItemLootAppender( + arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)), + listOf( + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.UNCOMMON), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.35, rarity = Rarity.RARE) + ) + )) + it.add("end_city_modifications", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_HUMANE, 1) to 0.3, ItemStack(MItems.PILL_OBLIVION, 1) to 0.5, ItemStack(MItems.ZPM_BATTERY, 1) to 0.005, )) + it.add("end_city_exosuit", RandomizableItemLootAppender( + arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), + listOf( + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.4, rarity = Rarity.UNCOMMON), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.2, rarity = Rarity.RARE), + RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.EPIC), + ) + )) + it.add("shipwreck_supply_pill", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)), ItemStack(MItems.PILL_HUMANE, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 1) to 0.6, + ItemStack(MItems.PILL_HEAL, 1) to 0.6, + ItemStack(MItems.PILL_HEAL, 1) to 0.6, + ItemStack(MItems.PILL_HEAL, 1) to 0.6, )) it.add("shipwreck_supply_nutrient_paste", LootTableSeparatedAppender( - arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()), + arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)), ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.85, ItemStack(MItems.NUTRIENT_PASTE, 24) to 0.35, ItemStack(MItems.NUTRIENT_PASTE, 38) to 0.1, diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt index c789378ef..f1eaa94a6 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt @@ -77,7 +77,7 @@ fun addLootTables(lootTables: LootTables) { lootTables.provider(LootContextParamSets.ADVANCEMENT_ENTITY) { it.accept(modLocation("research_all_android"), singleLootPool { - it.add(LootItem.lootTableItem(MItems.EXOSUIT_INVENTORY_UPGRADE_HUGE)) + it.add(LootItem.lootTableItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_HUGE)) }) it.accept(modLocation("tritanium_block3"), singleLootPool { diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt index b995243df..39ce751e8 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt @@ -280,7 +280,7 @@ fun addCraftingTableRecipes(consumer: Consumer) { .build(consumer) // апгрейд на сетку крафта - MatteryRecipe(MItems.EXOSUIT_CRAFTING_UPGRADE) + MatteryRecipe(MItems.ExosuitUpgrades.CRAFTING_UPGRADE) .row(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT) .row(MItemTags.CRAFTING_TABLES, MItems.QUANTUM_TRANSCEIVER, MItemTags.CRAFTING_TABLES) .row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt index 4595a85e5..2a93691b8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/CompoundTagExt.kt @@ -10,6 +10,7 @@ import net.minecraft.nbt.IntTag import net.minecraft.nbt.ListTag import net.minecraft.nbt.LongArrayTag import net.minecraft.nbt.LongTag +import net.minecraft.nbt.NbtUtils import net.minecraft.nbt.ShortTag import net.minecraft.nbt.StringTag import net.minecraft.nbt.Tag @@ -101,15 +102,32 @@ fun CompoundTag.getList(key: String): ListTag { return this[key] as? ListTag ?: ListTag() } +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getByteList(key: String): MutableList = getList(key, Tag.TAG_BYTE.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getShortList(key: String): MutableList = getList(key, Tag.TAG_SHORT.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getIntList(key: String): MutableList = getList(key, Tag.TAG_INT.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getLongList(key: String): MutableList = getList(key, Tag.TAG_LONG.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getFloatList(key: String): MutableList = getList(key, Tag.TAG_FLOAT.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getDoubleList(key: String): MutableList = getList(key, Tag.TAG_DOUBLE.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getByteArrayList(key: String): MutableList = getList(key, Tag.TAG_BYTE_ARRAY.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getStringList(key: String): MutableList = getList(key, Tag.TAG_STRING.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getListList(key: String): MutableList = getList(key, Tag.TAG_LIST.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getCompoundList(key: String): MutableList = getList(key, Tag.TAG_COMPOUND.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getIntArrayList(key: String): MutableList = getList(key, Tag.TAG_INT_ARRAY.toInt()) as MutableList +@Suppress("unchecked_cast") // type is checked inside getList fun CompoundTag.getLongArrayList(key: String): MutableList = getList(key, Tag.TAG_LONG_ARRAY.toInt()) as MutableList + +fun CompoundTag.getUUIDSafe(key: String): UUID? { + val value = this[key] as? IntArrayTag ?: return null + return NbtUtils.loadUUID(value) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt index 512d2482f..f19157160 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -29,6 +29,7 @@ import net.minecraftforge.registries.ForgeRegistry import net.minecraftforge.registries.IForgeRegistry import java.math.BigInteger import java.util.Spliterators +import java.util.UUID import java.util.stream.Stream import java.util.stream.StreamSupport import kotlin.reflect.KProperty @@ -396,3 +397,11 @@ fun Entity.genericPositions(): Collection { boundingBox.center ) } + +fun ResourceLocation.toUUID(): UUID { + return toString().toUUID() +} + +fun String.toUUID(): UUID { + return UUID.nameUUIDFromBytes(toByteArray(Charsets.UTF_8)) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/EnumCodec.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/EnumCodec.kt new file mode 100644 index 000000000..e760a5a69 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/EnumCodec.kt @@ -0,0 +1,30 @@ +package ru.dbotthepony.mc.otm.data + +import com.google.common.collect.ImmutableMap +import com.mojang.datafixers.util.Pair +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.DynamicOps +import kotlin.reflect.KClass + +class EnumCodec>(val type: Class) : Codec { + private val values: Map by lazy { + val builder = ImmutableMap.Builder() + for (value in type.enumConstants) builder.put(value.name, value) + builder.build() + } + + override fun encode(input: E, ops: DynamicOps, prefix: T): DataResult { + require(prefix == ops.empty()) { "Non-empty prefix: $prefix" } + return DataResult.success(ops.createString(input.name)) + } + + override fun decode(ops: DynamicOps, input: T): DataResult> { + return ops.getStringValue(input).flatMap { + DataResult.success(values[it] ?: return@flatMap DataResult.error("No such enum $it (valid ones are: ${values.keys.joinToString(", ")})")) + }.map { Pair.of(it, ops.empty()) } + } +} + +fun > Class.codec() = EnumCodec(this) +fun > KClass.codec() = EnumCodec(this.java) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/RandomizableItemLootAppender.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/RandomizableItemLootAppender.kt new file mode 100644 index 000000000..7b09b384b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/RandomizableItemLootAppender.kt @@ -0,0 +1,195 @@ +package ru.dbotthepony.mc.otm.data + +import com.google.common.collect.ImmutableList +import com.mojang.datafixers.util.Pair +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.DynamicOps +import com.mojang.serialization.codecs.RecordCodecBuilder +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import net.minecraft.util.RandomSource +import net.minecraft.util.valueproviders.ConstantInt +import net.minecraft.util.valueproviders.IntProvider +import net.minecraft.util.valueproviders.UniformInt +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Rarity +import net.minecraft.world.level.ItemLike +import net.minecraft.world.level.storage.loot.LootContext +import net.minecraft.world.level.storage.loot.parameters.LootContextParams +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition +import net.minecraftforge.common.loot.LootModifier +import net.minecraftforge.registries.ForgeRegistries + +interface IRandomizableItem : ItemLike { + fun randomize(itemStack: ItemStack, random: RandomSource, ply: Player?, rarity: Rarity = Rarity.COMMON) +} + +class RandomizableItemLootAppender( + conditions: Array, + entries: Collection +) : LootModifier(conditions) { + data class Entry( + val item: IRandomizableItem, + val chance: Double, + val count: IntProvider = ConstantInt.of(1), + val rarity: Rarity = Rarity.COMMON, + val distinct: Boolean = true, + ) { + constructor( + item: IRandomizableItem, + chance: Double, + count: Int, + rarity: Rarity = Rarity.COMMON, + distinct: Boolean = true, + ) : this(item, chance, ConstantInt.of(count), rarity, distinct) + + private constructor( + item: Item, + chance: Double, + count: IntProvider, + rarity: Rarity = Rarity.COMMON, + distinct: Boolean = true, + ) : this(item as? IRandomizableItem ?: throw ClassCastException("$item is not a subtype of IRandomizableItem"), chance, count, rarity, distinct) + + init { + require(count.minValue >= 0) { "Invalid min value ${count.minValue}" } + require(count.maxValue >= 0) { "Invalid max value ${count.maxValue}" } + require(count.maxValue >= count.minValue) { "Invalid bounds, they must be ${count.maxValue} >= ${count.minValue}!" } + } + + companion object { + val CODEC: Codec by lazy { + RecordCodecBuilder.create { + it.group( + ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter { it.item.asItem() }, + Codec.DOUBLE.fieldOf("chance").forGetter(Entry::chance), + IntProvider.CODEC.fieldOf("count").forGetter(Entry::count), + Rarity::class.codec().fieldOf("rarity").forGetter(Entry::rarity), + Codec.BOOL.fieldOf("distinct").forGetter(Entry::distinct), + ).apply(it, ::Entry) + } + } + } + } + + val entries: List = ImmutableList.copyOf(entries) + + override fun codec(): Codec { + return Companion + } + + override fun doApply( + generatedLoot: ObjectArrayList, + context: LootContext + ): ObjectArrayList { + 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 + } + } + + for ((item, chance, count, rarity, distinct) in entries) { + if (random.nextDouble() <= chance) { + if (distinct) { + val items = ArrayList() + + for (i in 0 until count.sample(random)) { + val stack = ItemStack(item.asItem(), 1) + item.randomize(stack, random, player, rarity) + + for (existing in items) { + if (ItemStack.isSameItemSameTags(existing, stack)) { + existing.count += stack.count + stack.count = 0 + break + } + } + + if (stack.count > 0) { + items.add(stack) + } + } + + for (stack in items) { + while (stack.count > stack.maxStackSize && stack.maxStackSize > 0) { + val split = stack.split(stack.maxStackSize) + generatedLoot.add(split) + } + + generatedLoot.add(stack) + } + } else { + val stack = ItemStack(item.asItem(), count.sample(random)) + item.randomize(stack, random, player, rarity) + + while (stack.count > stack.maxStackSize && stack.maxStackSize > 0) { + val split = stack.split(stack.maxStackSize) + generatedLoot.add(split) + } + + generatedLoot.add(stack) + } + } + } + + return generatedLoot + } + + companion object : Codec { + override fun encode( + input: RandomizableItemLootAppender, + ops: DynamicOps, + prefix: T + ): DataResult { + require(prefix == ops.empty()) { "Non-empty prefix: $prefix" } + + return LOOT_CONDITIONS_CODEC.encode(input.conditions, ops, prefix).flatMap map@{ + val encodedEntries = input.entries.map { Entry.CODEC.encode(it, ops, prefix) } + val firstError = encodedEntries.firstOrNull { !it.result().isPresent } + + if (firstError != null) { + return@map firstError + } + + return@map DataResult.success(ops.createMap(linkedMapOf( + ops.createString("conditions") to it, + ops.createString("entries") to ops.createList(encodedEntries.stream().map { it.result().get() }) + ))) + } + } + + override fun decode( + ops: DynamicOps, + input: T + ): DataResult> { + return ops.getMap(input).flatMap { map -> + LOOT_CONDITIONS_CODEC.decode(ops, map["conditions"]).flatMap { + val conditions = it.first + + ops.getStream(map["entries"]).flatMap { + val collected = it.map { Entry.CODEC.decode(ops, it) }.toList() + + for ((i, element) in collected.withIndex()) { + if (element.result().isEmpty) { + return@flatMap DataResult.error("Invalid entry at $i: ${element.error().get().message()}") + } + } + + return@flatMap DataResult.success(Pair.of(RandomizableItemLootAppender(conditions, collected.map { it.result().get().first }), ops.empty())) + } + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/AbstractExoSuitSlotUpgradeItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/AbstractExoSuitSlotUpgradeItem.kt new file mode 100644 index 000000000..ee69ffbcb --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/AbstractExoSuitSlotUpgradeItem.kt @@ -0,0 +1,120 @@ +package ru.dbotthepony.mc.otm.item + +import net.minecraft.ChatFormatting +import net.minecraft.network.chat.Component +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.InteractionHand +import net.minecraft.world.InteractionResultHolder +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Rarity +import net.minecraft.world.item.TooltipFlag +import net.minecraft.world.item.UseAnim +import net.minecraft.world.level.Level +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.ServerConfig +import ru.dbotthepony.mc.otm.capability.matteryPlayer +import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.registryName +import ru.dbotthepony.mc.otm.core.toUUID +import ru.dbotthepony.mc.otm.runIfClient +import java.util.UUID + +abstract class AbstractExoSuitSlotUpgradeItem(properties: Properties = defaultProperties()) : Item(properties) { + abstract fun hasDescription(itemStack: ItemStack): Boolean + abstract fun slotCount(itemStack: ItemStack): Int + abstract fun uuid(itemStack: ItemStack): UUID? + + override fun canBeHurtBy(p_41387_: DamageSource): Boolean { + return super.canBeHurtBy(p_41387_) && !p_41387_.isExplosion && !p_41387_.isFire + } + + override fun getUseDuration(p_41454_: ItemStack): Int { + return 30 + } + + override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, tooltip: MutableList, p_41424_: TooltipFlag) { + super.appendHoverText(p_41421_, p_41422_, tooltip, p_41424_) + + val alreadyHasExosuit = runIfClient(true) { + minecraft.player?.matteryPlayer?.hasExoSuit == true + } + + if (!alreadyHasExosuit) { + tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.no_exosuit").withStyle(ChatFormatting.GRAY)) + + if (runIfClient(false) { minecraft.player?.isCreative != true }) { + return + } + } + + val uuid = uuid(p_41421_) + + val alreadyHas = (uuid != null && !ServerConfig.INFINITE_EXOSUIT_UPGRADES) && runIfClient(false) { + minecraft.player?.matteryPlayer?.exoSuitSlotCountModifiers?.contains(uuid) == true + } + + if (alreadyHas) { + tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.already_activated").withStyle(ChatFormatting.DARK_RED)) + } + + tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.slots_upgrade", slotCount(p_41421_)).withStyle(ChatFormatting.DARK_GREEN)) + + if (hasDescription(p_41421_)) { + tooltip.add(TranslatableComponent("$descriptionId.description").withStyle(ChatFormatting.DARK_GRAY)) + } + } + + override fun use(p_41432_: Level, player: Player, hand: InteractionHand): InteractionResultHolder { + val matteryPlayer = player.matteryPlayer ?: return super.use(p_41432_, player, hand) + + val uuid = uuid(player.getItemInHand(hand)) + + if (matteryPlayer.hasExoSuit && ((uuid == null || ServerConfig.INFINITE_EXOSUIT_UPGRADES) || uuid !in matteryPlayer.exoSuitSlotCountModifiers)) { + player.startUsingItem(hand) + return InteractionResultHolder.consume(player.getItemInHand(hand)) + } + + return super.use(p_41432_, player, hand) + } + + override fun finishUsingItem(itemStack: ItemStack, level: Level, player: LivingEntity): ItemStack { + if (player !is Player) return super.finishUsingItem(itemStack, level, player) + val matteryPlayer = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player) + val uuid = uuid(itemStack) + val slotCount = slotCount(itemStack) + + if (slotCount <= 0 || !matteryPlayer.hasExoSuit || (!ServerConfig.INFINITE_EXOSUIT_UPGRADES && uuid != null && uuid in matteryPlayer.exoSuitSlotCountModifiers)) { + return super.finishUsingItem(itemStack, level, player) + } + + if (!player.abilities.instabuild) + itemStack.shrink(1) + + if (player is ServerPlayer) { + if (uuid != null) { + if (ServerConfig.INFINITE_EXOSUIT_UPGRADES && uuid in matteryPlayer.exoSuitSlotCountModifiers) { + matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount + } else { + matteryPlayer.exoSuitSlotCountModifiers[uuid] = slotCount + } + } else { + matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount + } + + player.displayClientMessage(TranslatableComponent("otm.exosuit_upgrades.slots_upgraded", slotCount).withStyle(ChatFormatting.DARK_GREEN), false) + } + + return itemStack + } + + override fun getUseAnimation(p_41452_: ItemStack): UseAnim = UseAnim.BOW + + companion object { + fun defaultProperties(rarity: Rarity = Rarity.UNCOMMON) = Properties().stacksTo(8).rarity(Rarity.UNCOMMON).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).fireResistant() + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ExoSuitSlotUpgradeItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ExoSuitSlotUpgradeItem.kt index 1717342e6..a2d262bda 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ExoSuitSlotUpgradeItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ExoSuitSlotUpgradeItem.kt @@ -5,6 +5,7 @@ import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerPlayer import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionResultHolder +import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player import net.minecraft.world.item.Item @@ -18,84 +19,55 @@ import ru.dbotthepony.mc.otm.ServerConfig import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.registryName +import ru.dbotthepony.mc.otm.core.toUUID import ru.dbotthepony.mc.otm.runIfClient import java.util.UUID -class ExoSuitSlotUpgradeItem( - val id: UUID?, - val slotCount: Int, - properties: Properties = Properties().stacksTo(8).rarity(Rarity.UNCOMMON).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB) -) : Item(properties) { - val isCreative: Boolean get() = id == null +class ExoSuitSlotUpgradeItem : AbstractExoSuitSlotUpgradeItem { + val hasDescription: Boolean + val slotCount: Int + val isCreative: Boolean - override fun getUseDuration(p_41454_: ItemStack): Int { - return 30 + private val uuidProvider: () -> UUID? + + override fun uuid(itemStack: ItemStack): UUID? { + return uuidProvider.invoke() } - override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, tooltip: MutableList, p_41424_: TooltipFlag) { - super.appendHoverText(p_41421_, p_41422_, tooltip, p_41424_) - - val alreadyHasExosuit = runIfClient(true) { - minecraft.player?.matteryPlayer?.hasExoSuit == true - } - - if (!alreadyHasExosuit) { - tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.no_exosuit").withStyle(ChatFormatting.GRAY)) - - if (runIfClient(false) { minecraft.player?.isCreative != true }) { - return - } - } - - val alreadyHas = (id != null && !ServerConfig.INFINITE_EXOSUIT_UPGRADES) && runIfClient(false) { - minecraft.player?.matteryPlayer?.exoSuitSlotCountModifiers?.contains(id) == true - } - - if (alreadyHas) { - tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.already_activated").withStyle(ChatFormatting.DARK_RED)) - } - - tooltip.add(TranslatableComponent("otm.gui.exosuit_upgrades.slots_upgrade", slotCount).withStyle(ChatFormatting.DARK_GREEN)) + override fun hasDescription(itemStack: ItemStack): Boolean { + return hasDescription } - override fun use(p_41432_: Level, player: Player, hand: InteractionHand): InteractionResultHolder { - val matteryPlayer = player.matteryPlayer ?: return super.use(p_41432_, player, hand) - - if (matteryPlayer.hasExoSuit && ((id == null || ServerConfig.INFINITE_EXOSUIT_UPGRADES) || id !in matteryPlayer.exoSuitSlotCountModifiers)) { - player.startUsingItem(hand) - return InteractionResultHolder.consume(player.getItemInHand(hand)) - } - - return super.use(p_41432_, player, hand) + override fun slotCount(itemStack: ItemStack): Int { + return slotCount } - override fun finishUsingItem(itemStack: ItemStack, level: Level, player: LivingEntity): ItemStack { - if (player !is Player) return super.finishUsingItem(itemStack, level, player) - val matteryPlayer = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player) - - if (!matteryPlayer.hasExoSuit || (!ServerConfig.INFINITE_EXOSUIT_UPGRADES && id != null && id in matteryPlayer.exoSuitSlotCountModifiers)) { - return super.finishUsingItem(itemStack, level, player) - } - - if (!player.abilities.instabuild) - itemStack.shrink(1) - - if (player is ServerPlayer) { - if (id != null) { - if (ServerConfig.INFINITE_EXOSUIT_UPGRADES && id in matteryPlayer.exoSuitSlotCountModifiers) { - matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount - } else { - matteryPlayer.exoSuitSlotCountModifiers[id] = slotCount - } - } else { - matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount - } - - player.displayClientMessage(TranslatableComponent("otm.exosuit_upgrades.slots_upgraded", slotCount).withStyle(ChatFormatting.DARK_GREEN), false) - } - - return itemStack + constructor(slotCount: Int, properties: Properties = defaultProperties(), hasDescription: Boolean = false) : super(properties) { + isCreative = false + this.slotCount = slotCount + this.uuidProvider = lazy { registryName!!.toUUID() }::value + this.hasDescription = hasDescription } - override fun getUseAnimation(p_41452_: ItemStack): UseAnim = UseAnim.BOW + constructor(uuid: UUID?, slotCount: Int, properties: Properties = defaultProperties(), hasDescription: Boolean = false) : super(properties) { + isCreative = uuid == null + this.slotCount = slotCount + this.uuidProvider = { UUID(0L, 0L) } + this.hasDescription = hasDescription + } + + constructor(slotCount: Int, rarity: Rarity, hasDescription: Boolean = false) : super(defaultProperties(rarity)) { + isCreative = false + this.slotCount = slotCount + this.uuidProvider = lazy { registryName!!.toUUID() }::value + this.hasDescription = hasDescription + } + + constructor(uuid: UUID?, slotCount: Int, rarity: Rarity, hasDescription: Boolean = false) : super(defaultProperties(rarity)) { + isCreative = uuid == null + this.slotCount = slotCount + this.uuidProvider = { UUID(0L, 0L) } + this.hasDescription = hasDescription + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralExoSuitSlotUpgradeItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralExoSuitSlotUpgradeItem.kt new file mode 100644 index 000000000..ac562f433 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralExoSuitSlotUpgradeItem.kt @@ -0,0 +1,82 @@ +package ru.dbotthepony.mc.otm.item + +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.world.item.ItemStack +import net.minecraft.world.item.Rarity +import net.minecraft.world.item.TooltipFlag +import net.minecraft.world.level.Level +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.core.tagNotNull +import ru.dbotthepony.mc.otm.data.IRandomizableItem +import java.util.* + +@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // .tab(null) is a legal statement because tab field itself is nullable +class ProceduralExoSuitSlotUpgradeItem : AbstractExoSuitSlotUpgradeItem(defaultProperties().tab(null)), 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 + } + } + + override fun hasDescription(itemStack: ItemStack): Boolean { + return false + } + + override fun slotCount(itemStack: ItemStack): Int { + return itemStack.tag?.getInt(SLOT_COUNT_KEY) ?: 0 + } + + override fun uuid(itemStack: ItemStack): UUID? { + return null + } + + override fun appendHoverText( + p_41421_: ItemStack, + p_41422_: Level?, + tooltip: MutableList, + p_41424_: TooltipFlag + ) { + super.appendHoverText(p_41421_, p_41422_, tooltip, p_41424_) + + if (p_41421_.tag?.get(SLOT_COUNT_KEY) == null) { + tooltip.add(TranslatableComponent("$descriptionId.description").withStyle(ChatFormatting.GRAY)) + } + } + + 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/LootModifiers.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt index 7307b42d8..67e65c02c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/LootModifiers.kt @@ -7,6 +7,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.data.LootTableAppender import ru.dbotthepony.mc.otm.data.LootTableBasicAppender import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender +import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender object LootModifiers { private val registry = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, OverdriveThatMatters.MOD_ID) @@ -15,6 +16,7 @@ object LootModifiers { registry.register("loot_appender") { LootTableAppender.CODEC } registry.register("loot_appender_separated") { LootTableSeparatedAppender.CODEC } registry.register("loot_appender_basic") { LootTableBasicAppender.CODEC } + registry.register("randomizable_item_loot_appender") { RandomizableItemLootAppender.Companion } } internal fun register(bus: IEventBus) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt index 5a2f20b8c..c5624947c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.registry +import com.google.common.collect.Streams import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component import net.minecraft.tags.BlockTags @@ -17,9 +18,11 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.ServerConfig import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.toUUID import ru.dbotthepony.mc.otm.item.* import ru.dbotthepony.mc.otm.item.weapon.PlasmaRifleItem import java.util.* +import java.util.stream.Stream import kotlin.collections.ArrayList object MItems { @@ -297,42 +300,28 @@ object MItems { val CARGO_CRATE_MINECARTS = registry.allColored(MNames.MINECART_CARGO_CRATE) { color, _ -> MinecartCargoCrateItem(color) } val EXOSUIT_PROBE: Item by registry.register(MNames.EXOSUIT_PROBE, ::ExoSuitProbeItem) - val EXOSUIT_INVENTORY_UPGRADE_CREATIVE: Item by registry.register("exosuit_inventory_upgrade_creative") { ExoSuitSlotUpgradeItem(null, 9, Item.Properties().stacksTo(8).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) } - val EXOSUIT_CRAFTING_UPGRADE: Item by registry.register("exosuit_crafting_upgrade", ::ExoSuitCraftingUpgradeItem) - val EXOSUIT_INVENTORY_UPGRADES: List - val EXOSUIT_INVENTORY_UPGRADES_CRAFTABLE: List - val EXOSUIT_INVENTORY_UPGRADES_UNCRAFTABLE: List + object ExosuitUpgrades { + val INVENTORY_UPGRADE_CREATIVE: Item by registry.register("exosuit_inventory_upgrade_creative") { ExoSuitSlotUpgradeItem(null, 27, Rarity.EPIC) } + val CRAFTING_UPGRADE: Item by registry.register("exosuit_crafting_upgrade", ::ExoSuitCraftingUpgradeItem) - init { - val upgrades = ArrayList<() -> Item>() - val upgradesCraftable = ArrayList<() -> Item>() - val upgradesUncraftable = ArrayList<() -> Item>() - - val baseSignificant = 7344348239534784L - var baseInsignificant = 848473865769484L - - for (i in 1 .. 4) { - val obj = registry.register("exosuit_inventory_upgrade_$i") { ExoSuitSlotUpgradeItem(UUID(baseSignificant, baseInsignificant++), 9) } - upgrades.add(obj::get) - upgradesCraftable.add(obj::get) + val INVENTORY_UPGRADES = LazyList(8) { + registry.register("exosuit_inventory_upgrade_$it") { ExoSuitSlotUpgradeItem(18, Rarity.COMMON) }::get } - for (i in 1 .. 16) { - val obj = registry.register("exosuit_inventory_upgrade_uncraftable_$i") { ExoSuitSlotUpgradeItem(UUID(baseSignificant, baseInsignificant++), 9 + (i / 5) * 9) } - upgrades.add(obj::get) - upgradesUncraftable.add(obj::get) - } + val INVENTORY_UPGRADE_PROCEDURAL: Item by registry.register("exosuit_inventory_upgrade_procedural") { ProceduralExoSuitSlotUpgradeItem() } - EXOSUIT_INVENTORY_UPGRADES = LazyList(upgrades) - EXOSUIT_INVENTORY_UPGRADES_CRAFTABLE = LazyList(upgradesCraftable) - EXOSUIT_INVENTORY_UPGRADES_UNCRAFTABLE = LazyList(upgradesUncraftable) + val INVENTORY_UPGRADE_BIG: Item by registry.register("exosuit_inventory_upgrade_big") { ExoSuitSlotUpgradeItem(60, Rarity.RARE) } + val INVENTORY_UPGRADE_HUGE: Item by registry.register("exosuit_inventory_upgrade_huge") { ExoSuitSlotUpgradeItem(135, Rarity.RARE) } + + val INVENTORY_UPGRADE_WITHER: Item by registry.register("exosuit_inventory_upgrade_wither") { ExoSuitSlotUpgradeItem(90, Rarity.RARE, hasDescription = true) } + val INVENTORY_UPGRADE_ENDER_DRAGON: Item by registry.register("exosuit_inventory_upgrade_ender_dragon") { ExoSuitSlotUpgradeItem(180, Rarity.EPIC, hasDescription = true) } } - val EXOSUIT_INVENTORY_UPGRADE_BIG: Item by registry.register("exosuit_inventory_upgrade_big") { ExoSuitSlotUpgradeItem(UUID.fromString("121a17a5-533c-9ac0-ff02-03aea75ed20c"), 45, Item.Properties().stacksTo(8).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) } - val EXOSUIT_INVENTORY_UPGRADE_HUGE: Item by registry.register("exosuit_inventory_upgrade_huge") { ExoSuitSlotUpgradeItem(UUID.fromString("121a17a5-533c-9ac0-ff02-03aea75ed20d"), 90, Item.Properties().stacksTo(8).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) } - init { + // call static initializer + ExosuitUpgrades + MRegistry.CARGO_CRATES.registerItems(registry) MRegistry.TRITANIUM_BLOCK.registerItems(registry) MRegistry.TRITANIUM_STAIRS.registerItems(registry)