From a76092f67477abf70082204c1109bcc48b94e5ef Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Tue, 7 May 2024 22:13:15 +0200 Subject: [PATCH 01/26] Add structure detection to Loonium Loonium figures out which structures(s) it was placed in and uses a corresponding list of loot tables with the id `botania:loonium//`. If the flower is placed in overlapping pieces of multiple structures with configured loot tables, it randomly chooses one of the tables whenever it spawns a mob. The Loonium drop capability is now attached to all mob entities, in preparation of customizable mob pools. Default equipment slot drops are turned off. TODO: Define loot tables for relevant vanilla structures. TODO: Define structure configuration data (JSON, likely separate registry) for the spawnable mob pool and whether the flower must be placed within a structure piece or anywhere within the structure's overall bounding box, maybe even the amount of mana per spawned mob. TODO: Move default configuration to a default structure configuration entry. --- .../CCAInternalEntityComponents.java | 7 +- .../ForgeInternalEntityCapabilities.java | 9 +- .../flower/functional/LooniumBlockEntity.java | 215 ++++++++++++------ .../botania/loot_tables/loonium/default.json | 15 ++ 4 files changed, 165 insertions(+), 81 deletions(-) create mode 100644 Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json diff --git a/Fabric/src/main/java/vazkii/botania/fabric/internal_caps/CCAInternalEntityComponents.java b/Fabric/src/main/java/vazkii/botania/fabric/internal_caps/CCAInternalEntityComponents.java index 4125d95cae..a13dcaf190 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/internal_caps/CCAInternalEntityComponents.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/internal_caps/CCAInternalEntityComponents.java @@ -15,12 +15,12 @@ import dev.onyxstudios.cca.api.v3.entity.EntityComponentInitializer; import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy; +import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.monster.*; import net.minecraft.world.entity.vehicle.AbstractMinecart; -import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import vazkii.botania.common.internal_caps.*; import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; @@ -36,10 +36,7 @@ public class CCAInternalEntityComponents implements EntityComponentInitializer { @Override public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) { - for (Class clz : LooniumBlockEntity.VALID_MOBS) { - registry.registerFor(clz, LOONIUM_DROP, e -> new CCALooniumComponent()); - } - + registry.registerFor(Mob.class, LOONIUM_DROP, e -> new CCALooniumComponent()); registry.registerFor(PrimedTnt.class, TNT_ETHICAL, CCAEthicalComponent::new); registry.registerFor(Slime.class, NARSLIMMUS, e -> new CCANarslimmusComponent()); registry.registerFor(ItemEntity.class, INTERNAL_ITEM, e -> new CCAItemFlagsComponent()); diff --git a/Forge/src/main/java/vazkii/botania/forge/internal_caps/ForgeInternalEntityCapabilities.java b/Forge/src/main/java/vazkii/botania/forge/internal_caps/ForgeInternalEntityCapabilities.java index a5abd8fc52..22fa44c72a 100644 --- a/Forge/src/main/java/vazkii/botania/forge/internal_caps/ForgeInternalEntityCapabilities.java +++ b/Forge/src/main/java/vazkii/botania/forge/internal_caps/ForgeInternalEntityCapabilities.java @@ -1,6 +1,7 @@ package vazkii.botania.forge.internal_caps; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.monster.Creeper; @@ -12,7 +13,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import vazkii.botania.common.internal_caps.*; import vazkii.botania.common.lib.LibMisc; import vazkii.botania.forge.CapabilityUtil; @@ -60,11 +60,8 @@ public static void attachCapabilities(AttachCapabilitiesEvent evt) { if (entity instanceof Player) { evt.addCapability(prefix("kept_items"), CapabilityUtil.makeSavedProvider(KEPT_ITEMS, new KeptItemsComponent())); } - for (Class clz : LooniumBlockEntity.VALID_MOBS) { - if (clz.isInstance(entity)) { - evt.addCapability(prefix("loonium_drop"), CapabilityUtil.makeSavedProvider(LOONIUM_DROP, new LooniumComponent())); - break; - } + if (entity instanceof Mob) { + evt.addCapability(prefix("loonium_drop"), CapabilityUtil.makeSavedProvider(LOONIUM_DROP, new LooniumComponent())); } if (entity instanceof Slime) { evt.addCapability(prefix("narslimmus"), CapabilityUtil.makeSavedProvider(NARSLIMMUS, new NarslimmusComponent())); diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index d279e93e40..091c4dc375 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -8,16 +8,18 @@ */ package vazkii.botania.common.block.flower.functional; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; + import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.Difficulty; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.monster.CaveSpider; @@ -25,19 +27,22 @@ import net.minecraft.world.entity.monster.Drowned; import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Husk; -import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.monster.Skeleton; import net.minecraft.world.entity.monster.Spider; import net.minecraft.world.entity.monster.Stray; import net.minecraft.world.entity.monster.Zombie; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.storage.loot.LootParams; +import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; + +import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.block_entity.FunctionalFlowerBlockEntity; import vazkii.botania.api.block_entity.RadiusDescriptor; import vazkii.botania.common.block.BotaniaFlowerBlocks; @@ -46,21 +51,17 @@ import java.util.*; import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final int COST = 35000; private static final int RANGE = 5; private static final String TAG_LOOT_TABLE = "lootTable"; - public static final Set> VALID_MOBS = Set.of( - Creeper.class, - EnderMan.class, - Skeleton.class, - Stray.class, - Spider.class, - Zombie.class - ); + public static final ResourceLocation[] DEFAULT_LOOT_TABLES = { prefix("loonium/default") }; - private ResourceLocation lootTable = new ResourceLocation("minecraft", "chests/simple_dungeon"); + private ResourceLocation[] lootTables = DEFAULT_LOOT_TABLES; public LooniumBlockEntity(BlockPos pos, BlockState state) { super(BotaniaFlowerBlocks.LOONIUM, pos, state); @@ -70,23 +71,22 @@ public LooniumBlockEntity(BlockPos pos, BlockState state) { public void tickFlower() { super.tickFlower(); - Level world = getLevel(); - if (!world.isClientSide && redstoneSignal == 0 && ticksExisted % 100 == 0 + if (!(getLevel() instanceof ServerLevel world)) { + return; + } + + if (ticksExisted == 1 && lootTables == DEFAULT_LOOT_TABLES) { + autodetectStructureLootTables(world); + } + + if (redstoneSignal == 0 && ticksExisted % 100 == 0 && getMana() >= COST && world.getDifficulty() != Difficulty.PEACEFUL) { var rand = world.random; - ItemStack stack; - do { - LootParams ctx = new LootParams.Builder((ServerLevel) world).create(LootContextParamSets.EMPTY); - List stacks = ((ServerLevel) world).getServer().getLootData() - .getLootTable(lootTable).getRandomItems(ctx); - if (stacks.isEmpty()) { - return; - } else { - Collections.shuffle(stacks); - stack = stacks.get(0); - } - } while (stack.isEmpty() || stack.is(BotaniaTags.Items.LOONIUM_BLACKLIST)); + ItemStack stack = pickRandomLoot(world, rand); + if (stack.isEmpty()) { + return; + } int bound = RANGE * 2 + 1; int xp = getEffectivePos().getX() - RANGE + rand.nextInt(bound); @@ -106,59 +106,31 @@ && getMana() >= COST && world.getDifficulty() != Difficulty.PEACEFUL) { double y = pos.getY() + Math.random(); double z = pos.getZ() + Math.random(); - Monster entity = null; - if (world.random.nextInt(50) == 0) { - entity = new EnderMan(EntityType.ENDERMAN, world); - } else if (world.random.nextInt(10) == 0) { - entity = new Creeper(EntityType.CREEPER, world); - if (world.random.nextInt(200) == 0) { - CompoundTag charged = new CompoundTag(); - charged.putBoolean("powered", true); - entity.readAdditionalSaveData(charged); - } - } else { - switch (world.random.nextInt(3)) { - case 0: - if (world.random.nextInt(10) == 0) { - entity = new Husk(EntityType.HUSK, world); - } else if (world.random.nextInt(5) == 0) { - entity = new Drowned(EntityType.DROWNED, world); - } else { - entity = new Zombie(world); - } - break; - case 1: - if (world.random.nextInt(10) == 0) { - entity = new Stray(EntityType.STRAY, world); - } else { - entity = new Skeleton(EntityType.SKELETON, world); - } - break; - case 2: - if (world.random.nextInt(10) == 0) { - entity = new CaveSpider(EntityType.CAVE_SPIDER, world); - } else { - entity = new Spider(EntityType.SPIDER, world); - } - break; - } + // TODO: Mob types and weights should be defined per structure + Mob entity = spawnMob(world); + if (entity == null) { + return; } entity.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); entity.setDeltaMovement(Vec3.ZERO); + // TODO: mob attribute modifications should be defined along with mob configuration entity.getAttribute(Attributes.MAX_HEALTH).addPermanentModifier(new AttributeModifier("Loonium Modififer Health", 2, AttributeModifier.Operation.MULTIPLY_BASE)); entity.setHealth(entity.getMaxHealth()); entity.getAttribute(Attributes.ATTACK_DAMAGE).addPermanentModifier(new AttributeModifier("Loonium Modififer Damage", 1.5, AttributeModifier.Operation.MULTIPLY_BASE)); + // TODO: mob potion effects should be defined in the mob configuration entity.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, - entity instanceof Creeper ? 100 : Integer.MAX_VALUE, 0)); + entity instanceof Creeper ? 100 : MobEffectInstance.INFINITE_DURATION, 0)); entity.addEffect(new MobEffectInstance(MobEffects.REGENERATION, - entity instanceof Creeper ? 100 : Integer.MAX_VALUE, 0)); + entity instanceof Creeper ? 100 : MobEffectInstance.INFINITE_DURATION, 0)); XplatAbstractions.INSTANCE.looniumComponent(entity).setDrop(stack); - entity.finalizeSpawn((ServerLevelAccessor) world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); + entity.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); + // prevent armor/weapon drops on player kill, also no nautilus shells from drowned: + Arrays.stream(EquipmentSlot.values()).forEach(slot -> entity.setDropChance(slot, 0)); world.addFreshEntity(entity); entity.spawnAnim(); @@ -167,6 +139,104 @@ && getMana() >= COST && world.getDifficulty() != Difficulty.PEACEFUL) { } } + private static @Nullable Mob spawnMob(ServerLevel world) { + Mob entity = null; + if (world.random.nextInt(50) == 0) { + entity = new EnderMan(EntityType.ENDERMAN, world); + } else if (world.random.nextInt(10) == 0) { + entity = new Creeper(EntityType.CREEPER, world); + if (world.random.nextInt(200) == 0) { + CompoundTag charged = new CompoundTag(); + charged.putBoolean("powered", true); + entity.readAdditionalSaveData(charged); + } + } else { + switch (world.random.nextInt(3)) { + case 0: + if (world.random.nextInt(10) == 0) { + entity = new Husk(EntityType.HUSK, world); + } else if (world.random.nextInt(5) == 0) { + entity = new Drowned(EntityType.DROWNED, world); + } else { + entity = new Zombie(world); + } + break; + case 1: + if (world.random.nextInt(10) == 0) { + entity = new Stray(EntityType.STRAY, world); + } else { + entity = new Skeleton(EntityType.SKELETON, world); + } + break; + case 2: + if (world.random.nextInt(10) == 0) { + entity = new CaveSpider(EntityType.CAVE_SPIDER, world); + } else { + // Note: could spawn as spider jockey, and we have no control over the skeleton + entity = new Spider(EntityType.SPIDER, world); + } + break; + } + } + return entity; + } + + private ItemStack pickRandomLoot(ServerLevel world, RandomSource rand) { + var lootTableId = lootTables[lootTables.length > 1 ? new Random().nextInt(lootTables.length) : 0]; + LootParams params = new LootParams.Builder(world).create(LootContextParamSets.EMPTY); + List stacks = world.getServer().getLootData().getLootTable(lootTableId).getRandomItems(params, rand.nextLong()); + stacks.removeIf(s -> s.isEmpty() || s.is(BotaniaTags.Items.LOONIUM_BLACKLIST)); + if (stacks.isEmpty()) { + return ItemStack.EMPTY; + } else { + Collections.shuffle(stacks); + return stacks.get(0); + } + } + + private void autodetectStructureLootTables(ServerLevel world) { + // structure ID -> whether the position is inside a structure piece (false = only overall bounding box) + var detectedStructures = new Object2BooleanOpenHashMap(); + StructureManager structureManager = world.structureManager(); + BlockPos pos = getBlockPos(); + var structures = structureManager.getAllStructuresAt(pos); + for (var entry : structures.entrySet()) { + Structure structure = entry.getKey(); + var start = structureManager.getStructureAt(pos, structure); + if (start.isValid()) { + ResourceLocation structureId = world.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(structure); + boolean insidePiece = structureManager.structureHasPieceAt(pos, start); + BotaniaAPI.LOGGER.info("Found structure {}, inside piece: {}", structureId, insidePiece); + detectedStructures.put(structureId, insidePiece); + } + } + + if (detectedStructures.isEmpty()) { + // not within any structures, keep default loot table + return; + } + + var lootTableCandidates = new ArrayList(detectedStructures.size()); + for (var entry : detectedStructures.object2BooleanEntrySet()) { + // TODO: grab structure configuration data from registry (assume must be inside a piece for now) + if (!entry.getBooleanValue()) { + continue; + } + var structureId = entry.getKey(); + var candidateId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); + LootTable lootTable = world.getServer().getLootData().getLootTable(candidateId); + if (lootTable != LootTable.EMPTY) { + lootTableCandidates.add(candidateId); + } + } + + if (!lootTableCandidates.isEmpty()) { + BotaniaAPI.LOGGER.info("Using loot tables: {}", lootTableCandidates); + lootTables = lootTableCandidates.toArray(ResourceLocation[]::new); + setChanged(); + } + } + @Override public int getColor() { return 0x274A00; @@ -191,14 +261,19 @@ public RadiusDescriptor getRadius() { public void readFromPacketNBT(CompoundTag cmp) { super.readFromPacketNBT(cmp); if (cmp.contains(TAG_LOOT_TABLE)) { - lootTable = new ResourceLocation(cmp.getString(TAG_LOOT_TABLE)); + var lootTableString = cmp.getString(TAG_LOOT_TABLE); + lootTables = Arrays.stream(cmp.getString(lootTableString).split(",")) + .map(ResourceLocation::new).toArray(ResourceLocation[]::new); } } @Override public void writeToPacketNBT(CompoundTag cmp) { super.writeToPacketNBT(cmp); - cmp.putString(TAG_LOOT_TABLE, lootTable.toString()); + if (lootTables.length >= 1) { + cmp.putString(TAG_LOOT_TABLE, + Arrays.stream(lootTables).map(ResourceLocation::toString).collect(Collectors.joining(","))); + } } public static void dropLooniumItems(LivingEntity living, Consumer consumer) { diff --git a/Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json b/Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json new file mode 100644 index 0000000000..4059ba0161 --- /dev/null +++ b/Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json @@ -0,0 +1,15 @@ +{ + "__comment": "Default loot table for Loonium outside any recognized structures", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/simple_dungeon" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file From 5875ed08e5fa55fc314bba3ba39c2b550ce5166d Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Wed, 8 May 2024 16:32:18 +0200 Subject: [PATCH 02/26] Datagen for Loonium loot tables --- .../fabric/data/FabricDatagenInitializer.java | 1 + .../3547e994b553d8eb42288bd4c3b48108cc98bacb | 33 +++ .../botania/loot_tables/loonium/default.json | 2 +- .../loonium/minecraft/ancient_city.json | 20 ++ .../loonium/minecraft/bastion_remnant.json | 28 ++ .../loonium/minecraft/buried_treasure.json | 15 ++ .../loonium/minecraft/desert_pyramid.json | 25 ++ .../loonium/minecraft/end_city.json | 20 ++ .../loonium/minecraft/fortress.json | 15 ++ .../loonium/minecraft/igloo/bottom.json | 26 ++ .../loonium/minecraft/jungle_pyramid.json | 20 ++ .../loonium/minecraft/mansion.json | 20 ++ .../loonium/minecraft/mineshaft.json | 15 ++ .../loonium/minecraft/mineshaft_mesa.json | 15 ++ .../loonium/minecraft/monument.json | 20 ++ .../loonium/minecraft/ocean_ruin_cold.json | 24 ++ .../loonium/minecraft/ocean_ruin_warm.json | 24 ++ .../loonium/minecraft/pillager_outpost.json | 15 ++ .../loonium/minecraft/ruined_portal.json | 15 ++ .../minecraft/ruined_portal_desert.json | 15 ++ .../minecraft/ruined_portal_jungle.json | 15 ++ .../minecraft/ruined_portal_mountain.json | 15 ++ .../minecraft/ruined_portal_nether.json | 15 ++ .../minecraft/ruined_portal_ocean.json | 15 ++ .../minecraft/ruined_portal_swamp.json | 15 ++ .../loonium/minecraft/shipwreck.json | 23 ++ .../loonium/minecraft/shipwreck_beached.json | 23 ++ .../loonium/minecraft/stronghold.json | 26 ++ .../loonium/minecraft/trail_ruins.json | 20 ++ .../loonium/minecraft/village_desert.json | 28 ++ .../loonium/minecraft/village_plains.json | 32 +++ .../loonium/minecraft/village_savanna.json | 36 +++ .../loonium/minecraft/village_snowy.json | 36 +++ .../loonium/minecraft/village_taiga.json | 36 +++ .../data/LooniumStructureLootProvider.java | 255 ++++++++++++++++++ 35 files changed, 957 insertions(+), 1 deletion(-) create mode 100644 Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb rename Xplat/src/{main => generated}/resources/data/botania/loot_tables/loonium/default.json (72%) create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json create mode 100644 Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java diff --git a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java index cf2fc0618a..4a15dd7dbb 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java @@ -41,6 +41,7 @@ private static void configureFabricDatagen(FabricDataGenerator.Pack pack) { private static void configureXplatDatagen(FabricDataGenerator.Pack pack) { pack.addProvider((PackOutput output) -> new BlockLootProvider(output)); + pack.addProvider((PackOutput output) -> new LooniumStructureLootProvider(output)); BlockTagProvider blockTagProvider = pack.addProvider(BlockTagProvider::new); pack.addProvider((output, registriesFuture) -> new ItemTagProvider(output, registriesFuture, blockTagProvider.contentsGetter())); pack.addProvider(EntityTagProvider::new); diff --git a/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb new file mode 100644 index 0000000000..f56f436ff4 --- /dev/null +++ b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb @@ -0,0 +1,33 @@ +// 1.20.1 Botania/Structure-specific loot tables for the Loonium +5be4598cca72d5bd04b72bbf2666d0f6a4c44003 data/botania/loot_tables/loonium/default.json +297e8b8aacbb714abc359e79d5b1273e6f797ade data/botania/loot_tables/loonium/minecraft/ancient_city.json +7c8bb4899c23eeed58b87acd4a7dc00653226826 data/botania/loot_tables/loonium/minecraft/bastion_remnant.json +d8c563b37355107a32f53b2b0b8a11222539e5c3 data/botania/loot_tables/loonium/minecraft/buried_treasure.json +e2a97abf2efe395fca879d21917567fcbe8a6ff0 data/botania/loot_tables/loonium/minecraft/desert_pyramid.json +fabda08b455e74a94f12a0a1543dfe5ef2686f0c data/botania/loot_tables/loonium/minecraft/end_city.json +7939255660c8610912a3d00ff224b57d8616835c data/botania/loot_tables/loonium/minecraft/fortress.json +baab33aa1088d316650bed8a12b9d1fa4e9fc389 data/botania/loot_tables/loonium/minecraft/igloo/bottom.json +c1d2f8f273db83026aebc7cfd578bc650773d01a data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json +82f290c4cbf99aa9eb692b6c23139c4e5628f8a7 data/botania/loot_tables/loonium/minecraft/mansion.json +54e34df119ba6c0728d94f31cde4f1dc0685e8d2 data/botania/loot_tables/loonium/minecraft/mineshaft.json +54e34df119ba6c0728d94f31cde4f1dc0685e8d2 data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json +d28977fa653e6eb049773aa0ba914724eca221f1 data/botania/loot_tables/loonium/minecraft/monument.json +3b419a644edd29e14966145f36c9484c2202a331 data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json +f888b3d04badcbac1cd52a4172432181fca36acc data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json +06b2bfc5653672e05df60928d50f6cfcf0330880 data/botania/loot_tables/loonium/minecraft/pillager_outpost.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json +1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json +498f158aeabee73fba36d9bf1b7fb7a1502f043b data/botania/loot_tables/loonium/minecraft/shipwreck.json +498f158aeabee73fba36d9bf1b7fb7a1502f043b data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json +e0a51ac44577a31cc29e6e172ad5f01020692465 data/botania/loot_tables/loonium/minecraft/stronghold.json +7106bdd381e8a057ced36ffb84eca1440a65d76b data/botania/loot_tables/loonium/minecraft/trail_ruins.json +7912f11b8be34c13d3bbdb2c02d4be55d9e56faa data/botania/loot_tables/loonium/minecraft/village_desert.json +dc70ff38d425cf26759b4dd3d5d192f49b2e959e data/botania/loot_tables/loonium/minecraft/village_plains.json +3498c7fe05d5ac6c87fdbe334a191335663b67d4 data/botania/loot_tables/loonium/minecraft/village_savanna.json +6017c02c6fd863247ee6998272e989996d9b3a19 data/botania/loot_tables/loonium/minecraft/village_snowy.json +d4f3fd38e9d76107686b2dec68a0f936e3e3bb17 data/botania/loot_tables/loonium/minecraft/village_taiga.json diff --git a/Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json similarity index 72% rename from Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json rename to Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json index 4059ba0161..c1ae3bbd2c 100644 --- a/Xplat/src/main/resources/data/botania/loot_tables/loonium/default.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json @@ -1,5 +1,5 @@ { - "__comment": "Default loot table for Loonium outside any recognized structures", + "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json new file mode 100644 index 0000000000..f34e52fe59 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ancient_city", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ancient_city_ice_box" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json new file mode 100644 index 0000000000..8536ca05e0 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/bastion_bridge" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/bastion_hoglin_stable" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/bastion_treasure" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/bastion_other", + "weight": 7 + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json new file mode 100644 index 0000000000..527461d296 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/buried_treasure" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json new file mode 100644 index 0000000000..44bc36fe47 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/desert_pyramid", + "weight": 37 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/desert_pyramid", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/desert_well" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json new file mode 100644 index 0000000000..c62044c805 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/end_city_treasure", + "weight": 49 + }, + { + "type": "minecraft:item", + "name": "minecraft:elytra" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json new file mode 100644 index 0000000000..9d98b82db7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/nether_bridge" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json new file mode 100644 index 0000000000..ddded7c5cc --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/igloo_chest", + "weight": 9 + }, + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_potion", + "id": "minecraft:weakness" + } + ], + "name": "minecraft:splash_potion" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json new file mode 100644 index 0000000000..e3b18a93b9 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/jungle_temple", + "weight": 9 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/jungle_temple_dispenser" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json new file mode 100644 index 0000000000..005165c2e1 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/woodland_mansion", + "weight": 99 + }, + { + "type": "minecraft:item", + "name": "minecraft:totem_of_undying" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json new file mode 100644 index 0000000000..4a8c506db3 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/abandoned_mineshaft" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json new file mode 100644 index 0000000000..4a8c506db3 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/abandoned_mineshaft" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json new file mode 100644 index 0000000000..6cd9c99cc0 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:elder_guardian", + "weight": 5 + }, + { + "type": "minecraft:item", + "name": "minecraft:wet_sponge" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json new file mode 100644 index 0000000000..6843afb5c2 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/underwater_ruin_big" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/underwater_ruin_small", + "weight": 8 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/ocean_ruin_cold" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json new file mode 100644 index 0000000000..6aa4474f42 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/underwater_ruin_big" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/underwater_ruin_small", + "weight": 8 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/ocean_ruin_warm" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json new file mode 100644 index 0000000000..a5b033be2a --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/pillager_outpost" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json new file mode 100644 index 0000000000..5004a7e76e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/ruined_portal" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json new file mode 100644 index 0000000000..61a3eccdab --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_map" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_supply" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_treasure" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json new file mode 100644 index 0000000000..61a3eccdab --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_map" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_supply" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/shipwreck_treasure" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json new file mode 100644 index 0000000000..e3d7f1631f --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/stronghold_corridor", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/stronghold_crossing", + "weight": 6 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/stronghold_library", + "weight": 3 + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json new file mode 100644 index 0000000000..899c0ad6b7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/trail_ruins_common", + "weight": 9 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:archaeology/trail_ruins_rare" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json new file mode 100644 index 0000000000..855b141c83 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_desert_house", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_weaponsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_toolsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_temple" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json new file mode 100644 index 0000000000..63c71c150e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json @@ -0,0 +1,32 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_plains_house", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_weaponsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_cartographer" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_fisher" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_tannery" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json new file mode 100644 index 0000000000..035946eb2e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_savanna_house", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_weaponsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_cartographer" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_mason" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_butcher" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_tannery" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json new file mode 100644 index 0000000000..8cd71f4463 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_snowy_house", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_weaponsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_armorer" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_cartographer" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_shepherd" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_tannery" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json new file mode 100644 index 0000000000..e50131284c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:empty", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_taiga_house", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_weaponsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_toolsmith" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_cartographer" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_fletcher" + }, + { + "type": "minecraft:loot_table", + "name": "minecraft:chests/village/village_tannery" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java new file mode 100644 index 0000000000..a81d07b5e7 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -0,0 +1,255 @@ +package vazkii.botania.data; + +import com.google.gson.JsonElement; + +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.level.levelgen.structure.BuiltinStructures; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.Deserializers; +import net.minecraft.world.level.storage.loot.LootPool; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.entries.LootTableReference; +import net.minecraft.world.level.storage.loot.functions.SetPotionFunction; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; + +public class LooniumStructureLootProvider implements DataProvider { + // loot collections based on which village type hoses can actually have chests + private static final EnumSet PLAINS_VILLAGE_LOOT = EnumSet + .of(VillageLoot.CARTOGRAPHER, VillageLoot.FISHER, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); + private static final EnumSet DESERT_VILLAGE_LOOT = EnumSet + .of(VillageLoot.TEMPLE, VillageLoot.TOOLSMITH, VillageLoot.WEAPONSMITH); + private static final EnumSet SAVANNA_VILLAGE_LOOT = EnumSet + .of(VillageLoot.BUTCHER, VillageLoot.CARTOGRAPHER, VillageLoot.MASON, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); + private static final EnumSet SNOWY_VILLAGE_LOOT = EnumSet + .of(VillageLoot.ARMORER, VillageLoot.CARTOGRAPHER, VillageLoot.SHEPHERD, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); + private static final EnumSet TAIGA_VILLAGE_LOOT = EnumSet + .of(VillageLoot.CARTOGRAPHER, VillageLoot.FLETCHER, VillageLoot.TANNERY, VillageLoot.TOOLSMITH, VillageLoot.WEAPONSMITH); + + private final PackOutput.PathProvider pathProvider; + + public LooniumStructureLootProvider(PackOutput packOutput) { + this.pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "loot_tables/loonium"); + } + + private ResourceLocation getLootId(ResourceKey structureKey) { + return getLootId(structureKey.location()); + } + + private ResourceLocation getLootId(ResourceLocation structureId) { + return prefix("%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); + } + + @NotNull + @Override + public CompletableFuture run(@NotNull CachedOutput cache) { + Map tables = new HashMap<>(); + + // Note: As far as world generating is concerned, dungeons are "features" (i.e. like trees or geodes), + // not "structures" (like everything else the Loonium might care about). + tables.put(prefix("default"), buildDelegateLootTable(BuiltInLootTables.SIMPLE_DUNGEON)); + + /* + Note: Be careful about adding individual items instead of loot table references. + The Loonium will randomly either generate a virtual chest full of loot from any referenced table, or put just + one of the defined item entries into the "chest". Either way it only picks a single stack from that "chest". + Individual item entries need to be weighted accordingly to not have them picked too often. + Also, archaeology loot tables need to be handled carefully, due to their limited loot pool options. + */ + + tables.put(getLootId(BuiltinStructures.ANCIENT_CITY), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY).setWeight(4)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY_ICE_BOX).setWeight(1)) + ) + ); + tables.put(getLootId(BuiltinStructures.BASTION_REMNANT), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_BRIDGE).setWeight(1)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_HOGLIN_STABLE).setWeight(1)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_TREASURE).setWeight(1)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_OTHER).setWeight(7)) + ) + ); + tables.put(getLootId(BuiltinStructures.BURIED_TREASURE), buildDelegateLootTable(BuiltInLootTables.BURIED_TREASURE)); + tables.put(getLootId(BuiltinStructures.DESERT_PYRAMID), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_PYRAMID).setWeight(37)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY).setWeight(2)) + // desert wells are features, so not detectable by the Loonium + .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_WELL_ARCHAEOLOGY)) + ) + ); + tables.put(getLootId(BuiltinStructures.END_CITY), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.END_CITY_TREASURE).setWeight(49)) + .add(LootItem.lootTableItem(Items.ELYTRA)) + ) + ); + tables.put(getLootId(BuiltinStructures.FORTRESS), buildDelegateLootTable(BuiltInLootTables.NETHER_BRIDGE)); + tables.put(getLootId(new ResourceLocation("igloo/bottom")), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.IGLOO_CHEST).setWeight(9)) + .add(LootItem.lootTableItem(Items.SPLASH_POTION).apply(SetPotionFunction.setPotion(Potions.WEAKNESS))) + ) + ); + tables.put(getLootId(BuiltinStructures.JUNGLE_TEMPLE), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.JUNGLE_TEMPLE).setWeight(9)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.JUNGLE_TEMPLE_DISPENSER)) + ) + ); + tables.put(getLootId(BuiltinStructures.MINESHAFT), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); + tables.put(getLootId(BuiltinStructures.MINESHAFT_MESA), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); + tables.put(getLootId(BuiltinStructures.OCEAN_MONUMENT), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(EntityType.getKey(EntityType.ELDER_GUARDIAN)).setWeight(5)) + // sponge is a player-kill drop and won't be rolled for the elder guardian table by the Loonium + .add(LootItem.lootTableItem(Items.WET_SPONGE)) + + ) + ); + tables.put(getLootId(BuiltinStructures.OCEAN_RUIN_COLD), + buildOceanRuinLootTable(BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY) + ); + tables.put(getLootId(BuiltinStructures.OCEAN_RUIN_WARM), + buildOceanRuinLootTable(BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY) + ); + tables.put(getLootId(BuiltinStructures.PILLAGER_OUTPOST), buildDelegateLootTable(BuiltInLootTables.PILLAGER_OUTPOST)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_DESERT), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_JUNGLE), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_MOUNTAIN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_NETHER), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_OCEAN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_STANDARD), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_SWAMP), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getLootId(BuiltinStructures.SHIPWRECK), buildShipwreckLootTable()); + tables.put(getLootId(BuiltinStructures.SHIPWRECK_BEACHED), buildShipwreckLootTable()); + tables.put(getLootId(BuiltinStructures.STRONGHOLD), + // Strongholds generate up to 4 corridor chests, up to 6 crossings, and up to 2 libraries with 1 or 2 chests + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.STRONGHOLD_CORRIDOR).setWeight(4)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.STRONGHOLD_CROSSING).setWeight(6)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.STRONGHOLD_LIBRARY).setWeight(3)) + ) + ); + // skipping swamp hut, because it doesn't contain unique loot (could merge witch/cat tables, I guess) + tables.put(getLootId(BuiltinStructures.TRAIL_RUINS), + // Trail ruins have 2 common suspicious gravel for the tower top and each road section, + // and 6 common plus 3 rare suspicious gravel per building and for the tower bottom. + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_COMMON).setWeight(9)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_RARE)) + ) + ); + tables.put(getLootId(BuiltinStructures.VILLAGE_PLAINS), + buildVillageLootTable(BuiltInLootTables.VILLAGE_PLAINS_HOUSE, PLAINS_VILLAGE_LOOT) + ); + tables.put(getLootId(BuiltinStructures.VILLAGE_DESERT), + buildVillageLootTable(BuiltInLootTables.VILLAGE_DESERT_HOUSE, DESERT_VILLAGE_LOOT) + ); + tables.put(getLootId(BuiltinStructures.VILLAGE_SAVANNA), + buildVillageLootTable(BuiltInLootTables.VILLAGE_SAVANNA_HOUSE, SAVANNA_VILLAGE_LOOT) + ); + tables.put(getLootId(BuiltinStructures.VILLAGE_SNOWY), + buildVillageLootTable(BuiltInLootTables.VILLAGE_SNOWY_HOUSE, SNOWY_VILLAGE_LOOT) + ); + tables.put(getLootId(BuiltinStructures.VILLAGE_TAIGA), + buildVillageLootTable(BuiltInLootTables.VILLAGE_TAIGA_HOUSE, TAIGA_VILLAGE_LOOT) + ); + tables.put(getLootId(BuiltinStructures.WOODLAND_MANSION), + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.WOODLAND_MANSION).setWeight(99)) + .add(LootItem.lootTableItem(Items.TOTEM_OF_UNDYING).setWeight(1)) + ) + ); + + var output = new ArrayList>(tables.size()); + for (var e : tables.entrySet()) { + Path path = pathProvider.json(e.getKey()); + LootTable.Builder builder = e.getValue(); + LootTable lootTable = builder.setParamSet(LootContextParamSets.EMPTY).build(); + JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + private static LootTable.Builder buildVillageLootTable(ResourceLocation house, Set villageLootSet) { + LootPool.Builder lootPool = LootPool.lootPool().add(LootTableReference.lootTableReference(house).setWeight(3)); + for (var loot : villageLootSet) { + lootPool.add(LootTableReference.lootTableReference(loot.lootTable)); + } + return LootTable.lootTable().withPool(lootPool); + } + + @NotNull + private static LootTable.Builder buildShipwreckLootTable() { + return LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BuiltInLootTables.SHIPWRECK_MAP)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.SHIPWRECK_SUPPLY)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.SHIPWRECK_TREASURE)) + ); + } + + @NotNull + private static LootTable.Builder buildDelegateLootTable(ResourceLocation reference) { + return LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(reference)) + ); + } + + @NotNull + private static LootTable.Builder buildOceanRuinLootTable(ResourceLocation archaeology) { + // Note: since the Loonium does not supply a location, treasure maps will roll as empty maps + return LootTable.lootTable().withPool(LootPool.lootPool() + // 30% of ocean ruin sites generate with a big ruin instead of a small one, + // but 90% of those big ruin sites additionally generate 4-8 small ruins around the big one. + .add(LootTableReference.lootTableReference(BuiltInLootTables.UNDERWATER_RUIN_BIG)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.UNDERWATER_RUIN_SMALL).setWeight(8)) + .add(LootTableReference.lootTableReference(archaeology)) + ); + } + + @NotNull + @Override + public String getName() { + return "Structure-specific loot tables for the Loonium"; + } + + private enum VillageLoot { + WEAPONSMITH(BuiltInLootTables.VILLAGE_WEAPONSMITH), + TOOLSMITH(BuiltInLootTables.VILLAGE_TOOLSMITH), + ARMORER(BuiltInLootTables.VILLAGE_ARMORER), + CARTOGRAPHER(BuiltInLootTables.VILLAGE_CARTOGRAPHER), + MASON(BuiltInLootTables.VILLAGE_MASON), + SHEPHERD(BuiltInLootTables.VILLAGE_SHEPHERD), + BUTCHER(BuiltInLootTables.VILLAGE_BUTCHER), + FLETCHER(BuiltInLootTables.VILLAGE_FLETCHER), + FISHER(BuiltInLootTables.VILLAGE_FISHER), + TANNERY(BuiltInLootTables.VILLAGE_TANNERY), + TEMPLE(BuiltInLootTables.VILLAGE_TEMPLE); + + public final ResourceLocation lootTable; + + VillageLoot(ResourceLocation lootTable) { + this.lootTable = lootTable; + } + } +} From 2139bad1a5e046d4dca6d7aab9b249d0660dba9c Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Wed, 8 May 2024 19:58:31 +0200 Subject: [PATCH 03/26] Remove igloo bottom from loot structures (can't be detected reliably) --- .../3547e994b553d8eb42288bd4c3b48108cc98bacb | 1 - .../loonium/minecraft/igloo/bottom.json | 26 ------------------- .../data/LooniumStructureLootProvider.java | 7 +---- 3 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json diff --git a/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb index f56f436ff4..cce20f1afd 100644 --- a/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb +++ b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb @@ -6,7 +6,6 @@ d8c563b37355107a32f53b2b0b8a11222539e5c3 data/botania/loot_tables/loonium/minecr e2a97abf2efe395fca879d21917567fcbe8a6ff0 data/botania/loot_tables/loonium/minecraft/desert_pyramid.json fabda08b455e74a94f12a0a1543dfe5ef2686f0c data/botania/loot_tables/loonium/minecraft/end_city.json 7939255660c8610912a3d00ff224b57d8616835c data/botania/loot_tables/loonium/minecraft/fortress.json -baab33aa1088d316650bed8a12b9d1fa4e9fc389 data/botania/loot_tables/loonium/minecraft/igloo/bottom.json c1d2f8f273db83026aebc7cfd578bc650773d01a data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json 82f290c4cbf99aa9eb692b6c23139c4e5628f8a7 data/botania/loot_tables/loonium/minecraft/mansion.json 54e34df119ba6c0728d94f31cde4f1dc0685e8d2 data/botania/loot_tables/loonium/minecraft/mineshaft.json diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json deleted file mode 100644 index ddded7c5cc..0000000000 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/igloo/bottom.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "minecraft:empty", - "pools": [ - { - "bonus_rolls": 0.0, - "entries": [ - { - "type": "minecraft:loot_table", - "name": "minecraft:chests/igloo_chest", - "weight": 9 - }, - { - "type": "minecraft:item", - "functions": [ - { - "function": "minecraft:set_potion", - "id": "minecraft:weakness" - } - ], - "name": "minecraft:splash_potion" - } - ], - "rolls": 1.0 - } - ] -} \ No newline at end of file diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index a81d07b5e7..89d1866ed4 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -103,12 +103,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ) ); tables.put(getLootId(BuiltinStructures.FORTRESS), buildDelegateLootTable(BuiltInLootTables.NETHER_BRIDGE)); - tables.put(getLootId(new ResourceLocation("igloo/bottom")), - LootTable.lootTable().withPool(LootPool.lootPool() - .add(LootTableReference.lootTableReference(BuiltInLootTables.IGLOO_CHEST).setWeight(9)) - .add(LootItem.lootTableItem(Items.SPLASH_POTION).apply(SetPotionFunction.setPotion(Potions.WEAKNESS))) - ) - ); + // skipping igloo, because the laboratory piece, which is the only part that has loot, can't be detected reliably tables.put(getLootId(BuiltinStructures.JUNGLE_TEMPLE), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.JUNGLE_TEMPLE).setWeight(9)) From 7b960fe1d8252c90466a7158b8724a4618be7980 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Wed, 8 May 2024 20:35:13 +0200 Subject: [PATCH 04/26] Adjust loot table definitions - tweak ancient table selection city weights - fix reference to elder guardian drops loot table - remove type specification on Loonium loot tables, as it caused validation warnings --- .../3547e994b553d8eb42288bd4c3b48108cc98bacb | 62 +++++++++---------- .../botania/loot_tables/loonium/default.json | 1 - .../loonium/minecraft/ancient_city.json | 3 +- .../loonium/minecraft/bastion_remnant.json | 1 - .../loonium/minecraft/buried_treasure.json | 1 - .../loonium/minecraft/desert_pyramid.json | 1 - .../loonium/minecraft/end_city.json | 1 - .../loonium/minecraft/fortress.json | 1 - .../loonium/minecraft/jungle_pyramid.json | 1 - .../loonium/minecraft/mansion.json | 1 - .../loonium/minecraft/mineshaft.json | 1 - .../loonium/minecraft/mineshaft_mesa.json | 1 - .../loonium/minecraft/monument.json | 3 +- .../loonium/minecraft/ocean_ruin_cold.json | 1 - .../loonium/minecraft/ocean_ruin_warm.json | 1 - .../loonium/minecraft/pillager_outpost.json | 1 - .../loonium/minecraft/ruined_portal.json | 1 - .../minecraft/ruined_portal_desert.json | 1 - .../minecraft/ruined_portal_jungle.json | 1 - .../minecraft/ruined_portal_mountain.json | 1 - .../minecraft/ruined_portal_nether.json | 1 - .../minecraft/ruined_portal_ocean.json | 1 - .../minecraft/ruined_portal_swamp.json | 1 - .../loonium/minecraft/shipwreck.json | 1 - .../loonium/minecraft/shipwreck_beached.json | 1 - .../loonium/minecraft/stronghold.json | 1 - .../loonium/minecraft/trail_ruins.json | 1 - .../loonium/minecraft/village_desert.json | 1 - .../loonium/minecraft/village_plains.json | 1 - .../loonium/minecraft/village_savanna.json | 1 - .../loonium/minecraft/village_snowy.json | 1 - .../loonium/minecraft/village_taiga.json | 1 - .../data/LooniumStructureLootProvider.java | 6 +- 33 files changed, 36 insertions(+), 67 deletions(-) diff --git a/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb index cce20f1afd..daa7bdabff 100644 --- a/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb +++ b/Xplat/src/generated/resources/.cache/3547e994b553d8eb42288bd4c3b48108cc98bacb @@ -1,32 +1,32 @@ // 1.20.1 Botania/Structure-specific loot tables for the Loonium -5be4598cca72d5bd04b72bbf2666d0f6a4c44003 data/botania/loot_tables/loonium/default.json -297e8b8aacbb714abc359e79d5b1273e6f797ade data/botania/loot_tables/loonium/minecraft/ancient_city.json -7c8bb4899c23eeed58b87acd4a7dc00653226826 data/botania/loot_tables/loonium/minecraft/bastion_remnant.json -d8c563b37355107a32f53b2b0b8a11222539e5c3 data/botania/loot_tables/loonium/minecraft/buried_treasure.json -e2a97abf2efe395fca879d21917567fcbe8a6ff0 data/botania/loot_tables/loonium/minecraft/desert_pyramid.json -fabda08b455e74a94f12a0a1543dfe5ef2686f0c data/botania/loot_tables/loonium/minecraft/end_city.json -7939255660c8610912a3d00ff224b57d8616835c data/botania/loot_tables/loonium/minecraft/fortress.json -c1d2f8f273db83026aebc7cfd578bc650773d01a data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json -82f290c4cbf99aa9eb692b6c23139c4e5628f8a7 data/botania/loot_tables/loonium/minecraft/mansion.json -54e34df119ba6c0728d94f31cde4f1dc0685e8d2 data/botania/loot_tables/loonium/minecraft/mineshaft.json -54e34df119ba6c0728d94f31cde4f1dc0685e8d2 data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json -d28977fa653e6eb049773aa0ba914724eca221f1 data/botania/loot_tables/loonium/minecraft/monument.json -3b419a644edd29e14966145f36c9484c2202a331 data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json -f888b3d04badcbac1cd52a4172432181fca36acc data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json -06b2bfc5653672e05df60928d50f6cfcf0330880 data/botania/loot_tables/loonium/minecraft/pillager_outpost.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json -1b427c16e2f630c9fe877f41f74fb856b60453db data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json -498f158aeabee73fba36d9bf1b7fb7a1502f043b data/botania/loot_tables/loonium/minecraft/shipwreck.json -498f158aeabee73fba36d9bf1b7fb7a1502f043b data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json -e0a51ac44577a31cc29e6e172ad5f01020692465 data/botania/loot_tables/loonium/minecraft/stronghold.json -7106bdd381e8a057ced36ffb84eca1440a65d76b data/botania/loot_tables/loonium/minecraft/trail_ruins.json -7912f11b8be34c13d3bbdb2c02d4be55d9e56faa data/botania/loot_tables/loonium/minecraft/village_desert.json -dc70ff38d425cf26759b4dd3d5d192f49b2e959e data/botania/loot_tables/loonium/minecraft/village_plains.json -3498c7fe05d5ac6c87fdbe334a191335663b67d4 data/botania/loot_tables/loonium/minecraft/village_savanna.json -6017c02c6fd863247ee6998272e989996d9b3a19 data/botania/loot_tables/loonium/minecraft/village_snowy.json -d4f3fd38e9d76107686b2dec68a0f936e3e3bb17 data/botania/loot_tables/loonium/minecraft/village_taiga.json +6c6809bce2449842eda497516397ecbe8e248df4 data/botania/loot_tables/loonium/default.json +267952295cf69e668286ae1bbeec2334c4edffe3 data/botania/loot_tables/loonium/minecraft/ancient_city.json +8fecd7949aa156ce411d58218d1b97c755535e6a data/botania/loot_tables/loonium/minecraft/bastion_remnant.json +1e75a9528dfcf3a5c0df85b75c3d369c267f77d5 data/botania/loot_tables/loonium/minecraft/buried_treasure.json +1cbf48dcdaf2af8351fb859d075ed2471dbd5f52 data/botania/loot_tables/loonium/minecraft/desert_pyramid.json +2d95f29b0eeeb7517c82df00bc21aff1b3597fe0 data/botania/loot_tables/loonium/minecraft/end_city.json +348f2833a2b7725e62c03900b8d8511b1fbfcb1b data/botania/loot_tables/loonium/minecraft/fortress.json +9c8d5d72012c2c8ee595515607c5abca0644c334 data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json +5e2abaf4e3a107350d603e4628a1252bce12d03b data/botania/loot_tables/loonium/minecraft/mansion.json +4d8a8b2550a0990a532ed9f70345fa5e83b07de6 data/botania/loot_tables/loonium/minecraft/mineshaft.json +4d8a8b2550a0990a532ed9f70345fa5e83b07de6 data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json +f073cbe252275ea680254649fd76562bc90dcec6 data/botania/loot_tables/loonium/minecraft/monument.json +65539ebf73f516910d4bee33fe3d5b5e039c6ae8 data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json +179e67b66efd46d1bde90a87faf31f204c183fb6 data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json +dcc92e196579e50af5ba2210f7666565f15c6685 data/botania/loot_tables/loonium/minecraft/pillager_outpost.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json +329743f53ff7d033ece348dcfbed39486a37fd7b data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json +eedca76b1bd188582858397700fa2b2b97be8ae9 data/botania/loot_tables/loonium/minecraft/shipwreck.json +eedca76b1bd188582858397700fa2b2b97be8ae9 data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json +6f288919e482acaa3393c5414daec2ff32028e95 data/botania/loot_tables/loonium/minecraft/stronghold.json +7bee83bc1b0b65175d183f14616dc92762a2d21e data/botania/loot_tables/loonium/minecraft/trail_ruins.json +5929a698590cc3b760e4623216fc3f31fe83817c data/botania/loot_tables/loonium/minecraft/village_desert.json +5e3467c6ab990167715bd080daad32679c0ee875 data/botania/loot_tables/loonium/minecraft/village_plains.json +d53e1eb39b960c2a5a2a1358a2b97b6064579947 data/botania/loot_tables/loonium/minecraft/village_savanna.json +4bf269c31e2c2a8612593134bfb1ab88566ca032 data/botania/loot_tables/loonium/minecraft/village_snowy.json +ce9e974c10c29f8fd7c684b7bd54d833bb657217 data/botania/loot_tables/loonium/minecraft/village_taiga.json diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json index c1ae3bbd2c..c988592205 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/default.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json index f34e52fe59..e77e010e43 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ancient_city.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, @@ -7,7 +6,7 @@ { "type": "minecraft:loot_table", "name": "minecraft:chests/ancient_city", - "weight": 4 + "weight": 9 }, { "type": "minecraft:loot_table", diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json index 8536ca05e0..04fcfd8e75 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/bastion_remnant.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json index 527461d296..e75af77ba4 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/buried_treasure.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json index 44bc36fe47..688a4b1e7c 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/desert_pyramid.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json index c62044c805..0479514e35 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/end_city.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json index 9d98b82db7..bb7ace7980 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/fortress.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json index e3b18a93b9..7ea7c7351b 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/jungle_pyramid.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json index 005165c2e1..f86fc80e83 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mansion.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json index 4a8c506db3..3481e7498d 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json index 4a8c506db3..3481e7498d 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/mineshaft_mesa.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json index 6cd9c99cc0..bfa5db3c2c 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/monument.json @@ -1,12 +1,11 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, "entries": [ { "type": "minecraft:loot_table", - "name": "minecraft:elder_guardian", + "name": "minecraft:entities/elder_guardian", "weight": 5 }, { diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json index 6843afb5c2..68d20a5cf4 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_cold.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json index 6aa4474f42..ac1ec6eff3 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ocean_ruin_warm.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json index a5b033be2a..bfe102562a 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/pillager_outpost.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_desert.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_jungle.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_mountain.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_nether.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_ocean.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json index 5004a7e76e..eb2f3cf020 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/ruined_portal_swamp.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json index 61a3eccdab..6d61c4adda 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json index 61a3eccdab..6d61c4adda 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/shipwreck_beached.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json index e3d7f1631f..5b103e1575 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/stronghold.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json index 899c0ad6b7..d0f1c11895 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/trail_ruins.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json index 855b141c83..d940537892 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_desert.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json index 63c71c150e..ecb2ea84b3 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_plains.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json index 035946eb2e..245c6929ed 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_savanna.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json index 8cd71f4463..01abbd4ca2 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_snowy.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json index e50131284c..4ff55cf07c 100644 --- a/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json +++ b/Xplat/src/generated/resources/data/botania/loot_tables/loonium/minecraft/village_taiga.json @@ -1,5 +1,4 @@ { - "type": "minecraft:empty", "pools": [ { "bonus_rolls": 0.0, diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index 89d1866ed4..686035d788 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -75,7 +75,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { tables.put(getLootId(BuiltinStructures.ANCIENT_CITY), LootTable.lootTable().withPool(LootPool.lootPool() - .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY).setWeight(4)) + .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY).setWeight(9)) .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY_ICE_BOX).setWeight(1)) ) ); @@ -114,7 +114,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { tables.put(getLootId(BuiltinStructures.MINESHAFT_MESA), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); tables.put(getLootId(BuiltinStructures.OCEAN_MONUMENT), LootTable.lootTable().withPool(LootPool.lootPool() - .add(LootTableReference.lootTableReference(EntityType.getKey(EntityType.ELDER_GUARDIAN)).setWeight(5)) + .add(LootTableReference.lootTableReference(EntityType.ELDER_GUARDIAN.getDefaultLootTable()).setWeight(5)) // sponge is a player-kill drop and won't be rolled for the elder guardian table by the Loonium .add(LootItem.lootTableItem(Items.WET_SPONGE)) @@ -179,7 +179,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { for (var e : tables.entrySet()) { Path path = pathProvider.json(e.getKey()); LootTable.Builder builder = e.getValue(); - LootTable lootTable = builder.setParamSet(LootContextParamSets.EMPTY).build(); + LootTable lootTable = builder.setParamSet(LootContextParamSets.ALL_PARAMS).build(); JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); output.add(DataProvider.saveStable(cache, jsonTree, path)); } From 5bc6a217a77ab8e72920d08280fa41b9a72d4cae Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Wed, 8 May 2024 20:35:48 +0200 Subject: [PATCH 05/26] Update lexicon description of Loonium --- Xplat/src/main/resources/assets/botania/lang/en_us.json | 3 ++- .../lexicon/en_us/entries/functional_flowers/loonium.json | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index 1021948e4f..b34b085b1c 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -2373,7 +2373,8 @@ "botania.entry.loonium": "Loonium", "botania.tagline.loonium": "Conjures dungeon loot", - "botania.page.loonium0": "Any adventurer knows that $(thing)Dungeons$(0) can hold valuable goodies. The $(item)Loonium$(0) will, when fed quite a bit of $(thing)Mana$(0), summon these items for said adventurers to collect.$(p)There's a catch, though: each item is held by a monster protecting it. These monsters are extra-strong, but will drop their precious $(thing)dungeon loot$(0) when killed.", + "botania.page.loonium0": "Any adventurer knows that the great structures of the world can hold valuable goodies. The $(item)Loonium$(0) will, when fed quite a bit of $(thing)Mana$(0), summon these items for said adventurers to collect.$(p)There's a catch, though: each item is held by a monster protecting it. These monsters are extra-strong, but will drop valuable loot when killed.", + "botania.page.looniumStructures": "Ordinarily the Loonium will summon treasure of the sort you would find in a $(thing)Dungeon$(0). However, the Loonium is sensitive to the large structures you can find in the world; if planted in one such structure, it'll instead summon treasure appropriate for its surroundings.", "botania.page.loonium1": "$(o)I CAN HAZ PHAT LOOTZ$()?", "botania.entry.daffomill": "Daffomill", diff --git a/Xplat/src/main/resources/assets/botania/patchouli_books/lexicon/en_us/entries/functional_flowers/loonium.json b/Xplat/src/main/resources/assets/botania/patchouli_books/lexicon/en_us/entries/functional_flowers/loonium.json index e0f03ded8f..f53adf3565 100644 --- a/Xplat/src/main/resources/assets/botania/patchouli_books/lexicon/en_us/entries/functional_flowers/loonium.json +++ b/Xplat/src/main/resources/assets/botania/patchouli_books/lexicon/en_us/entries/functional_flowers/loonium.json @@ -9,6 +9,10 @@ "type": "text", "text": "botania.page.loonium0" }, + { + "type": "text", + "text": "botania.page.looniumStructures" + }, { "type": "botania:petal_apothecary", "text": "botania.page.loonium1", @@ -16,6 +20,6 @@ } ], "extra_recipe_mappings": { - "botania:floating_loonium": 1 + "botania:floating_loonium": 2 } } From c9196e9afeee6eb7303909a9322066cb995fac18 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Thu, 9 May 2024 06:28:34 +0200 Subject: [PATCH 06/26] Expand wand HUD to indicate Loonium structure detection --- .../common/block/BotaniaFlowerBlocks.java | 3 +- .../flower/functional/LooniumBlockEntity.java | 44 ++++++++++++++++--- .../data/LooniumStructureLootProvider.java | 2 - .../resources/assets/botania/lang/en_us.json | 3 ++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/BotaniaFlowerBlocks.java b/Xplat/src/main/java/vazkii/botania/common/block/BotaniaFlowerBlocks.java index da2f89d4ba..be9043414a 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/BotaniaFlowerBlocks.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/BotaniaFlowerBlocks.java @@ -733,11 +733,12 @@ public static void registerWandHudCaps(BotaniaBlockEntities.BECapConsumer new HopperhockBlockEntity.WandHud((HopperhockBlockEntity) be), HOPPERHOCK, HOPPERHOCK_CHIBI); consumer.accept(be -> new PollidisiacBlockEntity.WandHud((PollidisiacBlockEntity) be), POLLIDISIAC); consumer.accept(be -> new RannuncarpusBlockEntity.WandHud((RannuncarpusBlockEntity) be), RANNUNCARPUS, RANNUNCARPUS_CHIBI); + consumer.accept(be -> new LooniumBlockEntity.WandHud((LooniumBlockEntity) be), LOONIUM); consumer.accept(be -> new BindableSpecialFlowerBlockEntity.BindableFlowerWandHud<>((FunctionalFlowerBlockEntity) be), BELLETHORNE, BELLETHORNE_CHIBI, DREADTHORN, HEISEI_DREAM, TIGERSEYE, JADED_AMARANTHUS, ORECHID, FALLEN_KANADE, EXOFLAME, AGRICARNATION, AGRICARNATION_CHIBI, TANGLEBERRIE, TANGLEBERRIE_CHIBI, JIYUULIA, JIYUULIA_CHIBI, HYACIDUS, - CLAYCONIA, CLAYCONIA_CHIBI, LOONIUM, DAFFOMILL, VINCULOTUS, SPECTRANTHEMUM, MEDUMONE, + CLAYCONIA, CLAYCONIA_CHIBI, DAFFOMILL, VINCULOTUS, SPECTRANTHEMUM, MEDUMONE, MARIMORPHOSIS, MARIMORPHOSIS_CHIBI, BUBBELL, BUBBELL_CHIBI, SOLEGNOLIA, SOLEGNOLIA_CHIBI, ORECHID_IGNEM, LABELLIA); } diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 091c4dc375..f868f4cf25 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -8,8 +8,11 @@ */ package vazkii.botania.common.block.flower.functional; -import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectBooleanPair; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.resources.language.I18n; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; @@ -196,7 +199,7 @@ private ItemStack pickRandomLoot(ServerLevel world, RandomSource rand) { private void autodetectStructureLootTables(ServerLevel world) { // structure ID -> whether the position is inside a structure piece (false = only overall bounding box) - var detectedStructures = new Object2BooleanOpenHashMap(); + var detectedStructures = new ArrayList>(); StructureManager structureManager = world.structureManager(); BlockPos pos = getBlockPos(); var structures = structureManager.getAllStructuresAt(pos); @@ -207,7 +210,7 @@ private void autodetectStructureLootTables(ServerLevel world) { ResourceLocation structureId = world.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(structure); boolean insidePiece = structureManager.structureHasPieceAt(pos, start); BotaniaAPI.LOGGER.info("Found structure {}, inside piece: {}", structureId, insidePiece); - detectedStructures.put(structureId, insidePiece); + detectedStructures.add(ObjectBooleanPair.of(structureId, insidePiece)); } } @@ -217,12 +220,12 @@ private void autodetectStructureLootTables(ServerLevel world) { } var lootTableCandidates = new ArrayList(detectedStructures.size()); - for (var entry : detectedStructures.object2BooleanEntrySet()) { + for (var entry : detectedStructures) { // TODO: grab structure configuration data from registry (assume must be inside a piece for now) - if (!entry.getBooleanValue()) { + if (!entry.valueBoolean()) { continue; } - var structureId = entry.getKey(); + var structureId = entry.key(); var candidateId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); LootTable lootTable = world.getServer().getLootData().getLootTable(candidateId); if (lootTable != LootTable.EMPTY) { @@ -234,6 +237,7 @@ private void autodetectStructureLootTables(ServerLevel world) { BotaniaAPI.LOGGER.info("Using loot tables: {}", lootTableCandidates); lootTables = lootTableCandidates.toArray(ResourceLocation[]::new); setChanged(); + sync(); } } @@ -262,7 +266,7 @@ public void readFromPacketNBT(CompoundTag cmp) { super.readFromPacketNBT(cmp); if (cmp.contains(TAG_LOOT_TABLE)) { var lootTableString = cmp.getString(TAG_LOOT_TABLE); - lootTables = Arrays.stream(cmp.getString(lootTableString).split(",")) + lootTables = Arrays.stream(lootTableString.split(",")) .map(ResourceLocation::new).toArray(ResourceLocation[]::new); } } @@ -282,4 +286,30 @@ public static void dropLooniumItems(LivingEntity living, Consumer con consumer.accept(comp.getDrop()); } } + + public static class WandHud extends BindableFlowerWandHud { + public WandHud(LooniumBlockEntity flower) { + super(flower); + } + + @Override + public void renderHUD(GuiGraphics gui, Minecraft mc) { + String attuneType; + if (Arrays.equals(flower.lootTables, DEFAULT_LOOT_TABLES)) { + attuneType = "generic_drops"; + } else if (flower.lootTables.length == 1) { + attuneType = "structure_drops"; + } else { + attuneType = "multiple_structure_drops"; + } + String attuned = I18n.get("botaniamisc.loonium." + attuneType).formatted(flower.lootTables.length); + int filterWidth = mc.font.width(attuned); + int filterTextStart = (mc.getWindow().getGuiScaledWidth() - filterWidth) / 2; + int halfMinWidth = (filterWidth + 4) / 2; + int centerY = mc.getWindow().getGuiScaledHeight() / 2; + + super.renderHUD(gui, mc, halfMinWidth, halfMinWidth, 40); + gui.drawString(mc.font, attuned, filterTextStart, centerY + 30, flower.getColor()); + } + } } diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index 686035d788..41288f1ae9 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -9,7 +9,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Items; -import net.minecraft.world.item.alchemy.Potions; import net.minecraft.world.level.levelgen.structure.BuiltinStructures; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.storage.loot.BuiltInLootTables; @@ -18,7 +17,6 @@ import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.entries.LootTableReference; -import net.minecraft.world.level.storage.loot.functions.SetPotionFunction; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import org.jetbrains.annotations.NotNull; diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index b34b085b1c..0808cbe7e5 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -132,6 +132,9 @@ "botaniamisc.rannuncarpus.state_sensitive": "Match Exact State", "botaniamisc.rannuncarpus.state_insensitive": "Match Block Only", "botaniamisc.lokiRingLimitReached": "Selection limit reached", + "botaniamisc.loonium.generic_drops": "Not attuned", + "botaniamisc.loonium.structure_drops": "Attuned to structure", + "botaniamisc.loonium.multiple_structure_drops": "Attuned to %d structures", "botaniamisc.pollidisiac.feed_adults": "Feeding adult animals", "botaniamisc.pollidisiac.feed_babies": "Feeding baby animals", "botaniamisc.pollidisiac.feed_all": "Feeding all animals", From c1ca07965dca804b84db47843a4fcd033ad79312 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Thu, 9 May 2024 20:23:35 +0200 Subject: [PATCH 07/26] Datagen for structure-specific Loonium configurations --- .../fabric/data/FabricDatagenInitializer.java | 1 + .../a864b94d006aba05700c96ad7a5769c8571473bc | 10 + .../data/botania/config/loonium/default.json | 91 +++++++ .../loonium/minecraft/ocean_ruin_cold.json | 4 + .../loonium/minecraft/ocean_ruin_warm.json | 4 + .../loonium/minecraft/pillager_outpost.json | 4 + .../loonium/minecraft/village_desert.json | 4 + .../loonium/minecraft/village_plains.json | 4 + .../loonium/minecraft/village_savanna.json | 4 + .../loonium/minecraft/village_snowy.json | 4 + .../loonium/minecraft/village_taiga.json | 4 + .../LooniumStructureConfiguration.java | 227 ++++++++++++++++++ ...LooniumStructureConfigurationProvider.java | 119 +++++++++ .../data/LooniumStructureLootProvider.java | 66 ++--- 14 files changed, 513 insertions(+), 33 deletions(-) create mode 100644 Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/default.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json create mode 100644 Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java create mode 100644 Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java diff --git a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java index 4a15dd7dbb..f6b061d51c 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java @@ -42,6 +42,7 @@ private static void configureFabricDatagen(FabricDataGenerator.Pack pack) { private static void configureXplatDatagen(FabricDataGenerator.Pack pack) { pack.addProvider((PackOutput output) -> new BlockLootProvider(output)); pack.addProvider((PackOutput output) -> new LooniumStructureLootProvider(output)); + pack.addProvider((PackOutput output) -> new LooniumStructureConfigurationProvider(output)); BlockTagProvider blockTagProvider = pack.addProvider(BlockTagProvider::new); pack.addProvider((output, registriesFuture) -> new ItemTagProvider(output, registriesFuture, blockTagProvider.contentsGetter())); pack.addProvider(EntityTagProvider::new); diff --git a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc new file mode 100644 index 0000000000..eb617e08cd --- /dev/null +++ b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc @@ -0,0 +1,10 @@ +// 1.20.1 Botania/Loonium structure configuration +79c6634f96360b3aa542841a94f84429f35c5bac data/botania/config/loonium/default.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_cold.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_warm.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/pillager_outpost.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_desert.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_plains.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_savanna.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_snowy.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_taiga.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/default.json b/Xplat/src/generated/resources/data/botania/config/loonium/default.json new file mode 100644 index 0000000000..cad9c7b5fc --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/default.json @@ -0,0 +1,91 @@ +{ + "attributeModifiers": [ + { + "amount": 2.0, + "attribute": "minecraft:generic.max_health", + "name": "Loonium Modififer Health", + "operation": "multiply_base" + }, + { + "amount": 1.5, + "attribute": "minecraft:generic.attack_damage", + "name": "Loonium Modififer Damage", + "operation": "multiply_base" + } + ], + "boundingBoxType": "piece", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "manaCost": 35000, + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "weight": 59 + }, + { + "type": "minecraft:drowned", + "weight": 106 + }, + { + "type": "minecraft:zombie", + "weight": 423 + }, + { + "type": "minecraft:stray", + "weight": 59 + }, + { + "type": "minecraft:skeleton", + "weight": 529 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java new file mode 100644 index 0000000000..22c7330687 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -0,0 +1,227 @@ +package vazkii.botania.api.configdata; + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.random.Weight; +import net.minecraft.util.random.WeightedEntry; +import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; + +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +public class LooniumStructureConfiguration { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + ExtraCodecs.POSITIVE_INT.fieldOf("manaCost").forGetter(o -> o.manaCost), + StructureSpawnOverride.BoundingBoxType.CODEC.fieldOf("boundingBoxType").forGetter(o -> o.boundingBoxType), + WeightedRandomList.codec(MobSpawnData.CODEC).fieldOf("spawnedMobs").forGetter(o -> o.spawnedMobs), + Codec.list(MobAttributeModifier.CODEC).fieldOf("attributeModifiers").forGetter(o -> o.attributeModifiers), + Codec.list(MobEffectToApply.CODEC).fieldOf("effectsToApply").forGetter(o -> o.effectsToApply) + ).apply(instance, LooniumStructureConfiguration::new) + ); + public static final Codec OPTIONAL_CODEC = RecordCodecBuilder.create( + instance -> instance.group( + ResourceLocation.CODEC.fieldOf("parent").forGetter(o -> o.parent), + ExtraCodecs.POSITIVE_INT.optionalFieldOf("manaCost").forGetter(o -> Optional.ofNullable(o.manaCost)), + StructureSpawnOverride.BoundingBoxType.CODEC.optionalFieldOf("boundingBoxType") + .forGetter(o -> Optional.ofNullable(o.boundingBoxType)), + WeightedRandomList.codec(MobSpawnData.CODEC).optionalFieldOf("spawnedMobs") + .forGetter(o -> Optional.ofNullable(o.spawnedMobs)), + Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") + .forGetter(o -> Optional.ofNullable(o.attributeModifiers)), + Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") + .forGetter(o -> Optional.ofNullable(o.effectsToApply)) + ).apply(instance, LooniumStructureConfiguration::new) + ); + + public final Integer manaCost; + public final StructureSpawnOverride.BoundingBoxType boundingBoxType; + public final WeightedRandomList spawnedMobs; + public final List attributeModifiers; + public final List effectsToApply; + public final ResourceLocation parent; + + public LooniumStructureConfiguration(Integer manaCost, StructureSpawnOverride.BoundingBoxType boundingBoxType, + WeightedRandomList spawnedMobs, List attributeModifiers, + List effectsToApply) { + this(null, manaCost, boundingBoxType, spawnedMobs, attributeModifiers, effectsToApply); + } + + public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer manaCost, + @Nullable StructureSpawnOverride.BoundingBoxType boundingBoxType, @Nullable WeightedRandomList spawnedMobs, + @Nullable List attributeModifiers, @Nullable List effectsToApply) { + this.manaCost = manaCost; + this.spawnedMobs = spawnedMobs; + this.boundingBoxType = boundingBoxType; + this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; + this.effectsToApply = effectsToApply != null ? ImmutableList.copyOf(effectsToApply) : null; + this.parent = parent; + } + + private LooniumStructureConfiguration(ResourceLocation parent, Optional manaCost, + Optional boundingBoxType, + Optional> spawnedMobs, + Optional> attributeModifiers, + Optional> effectsToApply) { + this(manaCost.orElse(null), boundingBoxType.orElse(null), spawnedMobs.orElse(null), + attributeModifiers.orElse(null), effectsToApply.orElse(null)); + } + + public LooniumStructureConfiguration(ResourceLocation parent, + StructureSpawnOverride.BoundingBoxType boundingBoxType) { + this(parent, null, boundingBoxType, null, null, null); + } + + public static class MobSpawnData extends WeightedEntry.IntrusiveBase { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("type").forGetter(o -> o.type), + Weight.CODEC.fieldOf("weight").forGetter(IntrusiveBase::getWeight), + CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(o -> Optional.ofNullable(o.nbt)), + Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") + .forGetter(o -> Optional.ofNullable(o.effectsToApply)), + Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") + .forGetter(o -> Optional.ofNullable(o.attributeModifiers)) + ).apply(instance, MobSpawnData::new) + ); + + public final EntityType type; + public final CompoundTag nbt; + public final List effectsToApply; + public final List attributeModifiers; + + public MobSpawnData(EntityType type, int weight) { + this(type, weight, null); + } + + public MobSpawnData(EntityType type, int weight, @Nullable List effectsToApply) { + this(type, weight, effectsToApply, null, null); + } + + public MobSpawnData(EntityType type, int weight, @Nullable List effectsToApply, + @Nullable List attributeModifiers, @Nullable CompoundTag nbt) { + this(type, Weight.of(weight), effectsToApply, attributeModifiers, nbt); + } + + public MobSpawnData(EntityType type, Weight weight, @Nullable List effectsToApply, + @Nullable List attributeModifiers, @Nullable CompoundTag nbt) { + super(weight); + this.type = type; + this.nbt = nbt != null ? nbt.copy() : null; + this.effectsToApply = effectsToApply != null ? ImmutableList.copyOf(effectsToApply) : null; + this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; + } + + private MobSpawnData(EntityType type, Weight weight, Optional nbt, + Optional> effectsToApply, Optional> attributeModifiers) { + this(type, weight, effectsToApply.orElse(null), attributeModifiers.orElse(null), nbt.orElse(null)); + } + } + + public static class MobAttributeModifier { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Codec.STRING.fieldOf("name").forGetter(o -> o.name), + BuiltInRegistries.ATTRIBUTE.byNameCodec().fieldOf("attribute").forGetter(o -> o.attribute), + Codec.DOUBLE.fieldOf("amount").forGetter(o -> o.amount), + Codec.STRING.xmap(MobAttributeModifier::operationFromString, MobAttributeModifier::operationToString) + .fieldOf("operation").forGetter(o -> o.operation) + ).apply(instance, MobAttributeModifier::new) + ); + + private final String name; + public final Attribute attribute; + private final double amount; + private final AttributeModifier.Operation operation; + + public MobAttributeModifier(String name, Attribute attribute, double amount, AttributeModifier.Operation operation) { + this.name = name; + this.attribute = attribute; + this.amount = amount; + this.operation = operation; + } + + public AttributeModifier createAttributeModifier() { + return new AttributeModifier(name, amount, operation); + } + + private static String operationToString(AttributeModifier.Operation operation) { + return switch (operation) { + case ADDITION -> "addition"; + case MULTIPLY_BASE -> "multiply_base"; + case MULTIPLY_TOTAL -> "multiply_total"; + default -> throw new IllegalArgumentException("Unknown operation " + operation); + }; + } + + private static AttributeModifier.Operation operationFromString(String operation) { + return switch (operation) { + case "addition" -> AttributeModifier.Operation.ADDITION; + case "multiply_base" -> AttributeModifier.Operation.MULTIPLY_BASE; + case "multiply_total" -> AttributeModifier.Operation.MULTIPLY_TOTAL; + default -> throw new JsonSyntaxException("Unknown attribute modifier operation " + operation); + }; + } + } + + public static class MobEffectToApply { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + BuiltInRegistries.MOB_EFFECT.byNameCodec().fieldOf("effect").forGetter(o -> o.effect), + ExtraCodecs.validate(Codec.INT, + duration -> duration > 0 + ? DataResult.success(duration) + : DataResult.error(() -> "Invalid effect duration")) + .optionalFieldOf("duration").forGetter(MobEffectToApply::getOptionalDuration), + Codec.intRange(0, 255) + .optionalFieldOf("amplifier").forGetter(MobEffectToApply::getOptionalAmplifier) + ).apply(instance, MobEffectToApply::new) + ); + + public final MobEffect effect; + public final int duration; + public final int amplifier; + + public MobEffectToApply(MobEffect effect) { + this(effect, MobEffectInstance.INFINITE_DURATION); + } + + public MobEffectToApply(MobEffect effect, int duration) { + this(effect, duration, 0); + } + + public MobEffectToApply(MobEffect effect, int duration, int amplifier) { + this.effect = effect; + this.duration = duration; + this.amplifier = amplifier; + } + + private MobEffectToApply(MobEffect effect, Optional optionalDuration, Optional optionalAmplifier) { + this(effect, optionalDuration.orElse(MobEffectInstance.INFINITE_DURATION), optionalAmplifier.orElse(0)); + } + + private Optional getOptionalDuration() { + return duration != MobEffectInstance.INFINITE_DURATION ? Optional.of(duration) : Optional.empty(); + } + + private Optional getOptionalAmplifier() { + return amplifier > 0 ? Optional.of(amplifier) : Optional.empty(); + } + } +} diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java new file mode 100644 index 0000000000..f6247e6d4c --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -0,0 +1,119 @@ +package vazkii.botania.data; + +import com.mojang.serialization.JsonOps; + +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.random.WeightedRandomList; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.level.levelgen.structure.BuiltinStructures; +import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; + +import org.jetbrains.annotations.NotNull; + +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.configdata.LooniumStructureConfiguration; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; +import static vazkii.botania.data.LooniumStructureLootProvider.getStructureId; + +public class LooniumStructureConfigurationProvider implements DataProvider { + + private final PackOutput.PathProvider pathProvider; + + public LooniumStructureConfigurationProvider(PackOutput packOutput) { + pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "config/loonium"); + } + + @NotNull + @Override + public CompletableFuture run(@NotNull CachedOutput cache) { + Map configs = new HashMap<>(); + + List effectsToApplyToCreepers = List.of( + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE, 100), + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION, 100) + ); + CompoundTag chargedCreeperNbt = new CompoundTag(); + chargedCreeperNbt.putBoolean("powered", true); + + ResourceLocation defaultConfigId = prefix("default"); + configs.put(defaultConfigId, new LooniumStructureConfiguration( + 35000, StructureSpawnOverride.BoundingBoxType.PIECE, + WeightedRandomList.create( + // weights roughly based on original Loonium mob selection logic + new LooniumStructureConfiguration.MobSpawnData(EntityType.ENDERMAN, 40), + new LooniumStructureConfiguration.MobSpawnData(EntityType.CREEPER, 195, + effectsToApplyToCreepers), + new LooniumStructureConfiguration.MobSpawnData(EntityType.CREEPER, 1, + effectsToApplyToCreepers, null, chargedCreeperNbt), + new LooniumStructureConfiguration.MobSpawnData(EntityType.HUSK, 59), + new LooniumStructureConfiguration.MobSpawnData(EntityType.DROWNED, 106), + new LooniumStructureConfiguration.MobSpawnData(EntityType.ZOMBIE, 423), + new LooniumStructureConfiguration.MobSpawnData(EntityType.STRAY, 59), + new LooniumStructureConfiguration.MobSpawnData(EntityType.SKELETON, 529), + new LooniumStructureConfiguration.MobSpawnData(EntityType.CAVE_SPIDER, 59), + new LooniumStructureConfiguration.MobSpawnData(EntityType.SPIDER, 529) + ), + List.of( + new LooniumStructureConfiguration.MobAttributeModifier("Loonium Modififer Health", + Attributes.MAX_HEALTH, 2, AttributeModifier.Operation.MULTIPLY_BASE), + new LooniumStructureConfiguration.MobAttributeModifier("Loonium Modififer Damage", + Attributes.ATTACK_DAMAGE, 1.5, AttributeModifier.Operation.MULTIPLY_BASE) + ), + List.of( + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE), + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION) + ) + )); + + configs.put(getStructureId(BuiltinStructures.OCEAN_RUIN_COLD), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.OCEAN_RUIN_WARM), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.PILLAGER_OUTPOST), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.VILLAGE_DESERT), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.VILLAGE_PLAINS), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.VILLAGE_SAVANNA), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.VILLAGE_SNOWY), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + configs.put(getStructureId(BuiltinStructures.VILLAGE_TAIGA), + new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + + var output = new ArrayList>(configs.size()); + for (var e : configs.entrySet()) { + Path path = pathProvider.json(e.getKey()); + var config = e.getValue(); + var jsonTree = (config.parent != null + ? LooniumStructureConfiguration.OPTIONAL_CODEC + : LooniumStructureConfiguration.CODEC) + .encodeStart(JsonOps.INSTANCE, config) + .getOrThrow(false, BotaniaAPI.LOGGER::error); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + @NotNull + @Override + public String getName() { + return "Loonium structure configuration"; + } +} diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index 41288f1ae9..357917c15b 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -46,11 +46,11 @@ public LooniumStructureLootProvider(PackOutput packOutput) { this.pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "loot_tables/loonium"); } - private ResourceLocation getLootId(ResourceKey structureKey) { - return getLootId(structureKey.location()); + public static ResourceLocation getStructureId(ResourceKey structureKey) { + return getStructureId(structureKey.location()); } - private ResourceLocation getLootId(ResourceLocation structureId) { + public static ResourceLocation getStructureId(ResourceLocation structureId) { return prefix("%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); } @@ -71,13 +71,13 @@ public CompletableFuture run(@NotNull CachedOutput cache) { Also, archaeology loot tables need to be handled carefully, due to their limited loot pool options. */ - tables.put(getLootId(BuiltinStructures.ANCIENT_CITY), + tables.put(getStructureId(BuiltinStructures.ANCIENT_CITY), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY).setWeight(9)) .add(LootTableReference.lootTableReference(BuiltInLootTables.ANCIENT_CITY_ICE_BOX).setWeight(1)) ) ); - tables.put(getLootId(BuiltinStructures.BASTION_REMNANT), + tables.put(getStructureId(BuiltinStructures.BASTION_REMNANT), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_BRIDGE).setWeight(1)) .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_HOGLIN_STABLE).setWeight(1)) @@ -85,8 +85,8 @@ public CompletableFuture run(@NotNull CachedOutput cache) { .add(LootTableReference.lootTableReference(BuiltInLootTables.BASTION_OTHER).setWeight(7)) ) ); - tables.put(getLootId(BuiltinStructures.BURIED_TREASURE), buildDelegateLootTable(BuiltInLootTables.BURIED_TREASURE)); - tables.put(getLootId(BuiltinStructures.DESERT_PYRAMID), + tables.put(getStructureId(BuiltinStructures.BURIED_TREASURE), buildDelegateLootTable(BuiltInLootTables.BURIED_TREASURE)); + tables.put(getStructureId(BuiltinStructures.DESERT_PYRAMID), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_PYRAMID).setWeight(37)) .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY).setWeight(2)) @@ -94,23 +94,23 @@ public CompletableFuture run(@NotNull CachedOutput cache) { .add(LootTableReference.lootTableReference(BuiltInLootTables.DESERT_WELL_ARCHAEOLOGY)) ) ); - tables.put(getLootId(BuiltinStructures.END_CITY), + tables.put(getStructureId(BuiltinStructures.END_CITY), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.END_CITY_TREASURE).setWeight(49)) .add(LootItem.lootTableItem(Items.ELYTRA)) ) ); - tables.put(getLootId(BuiltinStructures.FORTRESS), buildDelegateLootTable(BuiltInLootTables.NETHER_BRIDGE)); + tables.put(getStructureId(BuiltinStructures.FORTRESS), buildDelegateLootTable(BuiltInLootTables.NETHER_BRIDGE)); // skipping igloo, because the laboratory piece, which is the only part that has loot, can't be detected reliably - tables.put(getLootId(BuiltinStructures.JUNGLE_TEMPLE), + tables.put(getStructureId(BuiltinStructures.JUNGLE_TEMPLE), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.JUNGLE_TEMPLE).setWeight(9)) .add(LootTableReference.lootTableReference(BuiltInLootTables.JUNGLE_TEMPLE_DISPENSER)) ) ); - tables.put(getLootId(BuiltinStructures.MINESHAFT), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); - tables.put(getLootId(BuiltinStructures.MINESHAFT_MESA), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); - tables.put(getLootId(BuiltinStructures.OCEAN_MONUMENT), + tables.put(getStructureId(BuiltinStructures.MINESHAFT), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); + tables.put(getStructureId(BuiltinStructures.MINESHAFT_MESA), buildDelegateLootTable(BuiltInLootTables.ABANDONED_MINESHAFT)); + tables.put(getStructureId(BuiltinStructures.OCEAN_MONUMENT), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(EntityType.ELDER_GUARDIAN.getDefaultLootTable()).setWeight(5)) // sponge is a player-kill drop and won't be rolled for the elder guardian table by the Loonium @@ -118,23 +118,23 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ) ); - tables.put(getLootId(BuiltinStructures.OCEAN_RUIN_COLD), + tables.put(getStructureId(BuiltinStructures.OCEAN_RUIN_COLD), buildOceanRuinLootTable(BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY) ); - tables.put(getLootId(BuiltinStructures.OCEAN_RUIN_WARM), + tables.put(getStructureId(BuiltinStructures.OCEAN_RUIN_WARM), buildOceanRuinLootTable(BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY) ); - tables.put(getLootId(BuiltinStructures.PILLAGER_OUTPOST), buildDelegateLootTable(BuiltInLootTables.PILLAGER_OUTPOST)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_DESERT), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_JUNGLE), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_MOUNTAIN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_NETHER), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_OCEAN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_STANDARD), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.RUINED_PORTAL_SWAMP), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); - tables.put(getLootId(BuiltinStructures.SHIPWRECK), buildShipwreckLootTable()); - tables.put(getLootId(BuiltinStructures.SHIPWRECK_BEACHED), buildShipwreckLootTable()); - tables.put(getLootId(BuiltinStructures.STRONGHOLD), + tables.put(getStructureId(BuiltinStructures.PILLAGER_OUTPOST), buildDelegateLootTable(BuiltInLootTables.PILLAGER_OUTPOST)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_DESERT), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_JUNGLE), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_MOUNTAIN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_NETHER), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_OCEAN), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_STANDARD), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.RUINED_PORTAL_SWAMP), buildDelegateLootTable(BuiltInLootTables.RUINED_PORTAL)); + tables.put(getStructureId(BuiltinStructures.SHIPWRECK), buildShipwreckLootTable()); + tables.put(getStructureId(BuiltinStructures.SHIPWRECK_BEACHED), buildShipwreckLootTable()); + tables.put(getStructureId(BuiltinStructures.STRONGHOLD), // Strongholds generate up to 4 corridor chests, up to 6 crossings, and up to 2 libraries with 1 or 2 chests LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.STRONGHOLD_CORRIDOR).setWeight(4)) @@ -143,7 +143,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ) ); // skipping swamp hut, because it doesn't contain unique loot (could merge witch/cat tables, I guess) - tables.put(getLootId(BuiltinStructures.TRAIL_RUINS), + tables.put(getStructureId(BuiltinStructures.TRAIL_RUINS), // Trail ruins have 2 common suspicious gravel for the tower top and each road section, // and 6 common plus 3 rare suspicious gravel per building and for the tower bottom. LootTable.lootTable().withPool(LootPool.lootPool() @@ -151,22 +151,22 @@ public CompletableFuture run(@NotNull CachedOutput cache) { .add(LootTableReference.lootTableReference(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_RARE)) ) ); - tables.put(getLootId(BuiltinStructures.VILLAGE_PLAINS), + tables.put(getStructureId(BuiltinStructures.VILLAGE_PLAINS), buildVillageLootTable(BuiltInLootTables.VILLAGE_PLAINS_HOUSE, PLAINS_VILLAGE_LOOT) ); - tables.put(getLootId(BuiltinStructures.VILLAGE_DESERT), + tables.put(getStructureId(BuiltinStructures.VILLAGE_DESERT), buildVillageLootTable(BuiltInLootTables.VILLAGE_DESERT_HOUSE, DESERT_VILLAGE_LOOT) ); - tables.put(getLootId(BuiltinStructures.VILLAGE_SAVANNA), + tables.put(getStructureId(BuiltinStructures.VILLAGE_SAVANNA), buildVillageLootTable(BuiltInLootTables.VILLAGE_SAVANNA_HOUSE, SAVANNA_VILLAGE_LOOT) ); - tables.put(getLootId(BuiltinStructures.VILLAGE_SNOWY), + tables.put(getStructureId(BuiltinStructures.VILLAGE_SNOWY), buildVillageLootTable(BuiltInLootTables.VILLAGE_SNOWY_HOUSE, SNOWY_VILLAGE_LOOT) ); - tables.put(getLootId(BuiltinStructures.VILLAGE_TAIGA), + tables.put(getStructureId(BuiltinStructures.VILLAGE_TAIGA), buildVillageLootTable(BuiltInLootTables.VILLAGE_TAIGA_HOUSE, TAIGA_VILLAGE_LOOT) ); - tables.put(getLootId(BuiltinStructures.WOODLAND_MANSION), + tables.put(getStructureId(BuiltinStructures.WOODLAND_MANSION), LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.WOODLAND_MANSION).setWeight(99)) .add(LootItem.lootTableItem(Items.TOTEM_OF_UNDYING).setWeight(1)) From 3caf4fad458353377ada8e919b8e7b0e754d4bfa Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Fri, 10 May 2024 20:33:43 +0200 Subject: [PATCH 08/26] Datagen for and loading of structure-specific Loonium configurations (includes a generic reloadable config data manager, which currently only covers Loonium configurations) --- .../fabric/FabricCommonInitializer.java | 2 + .../botania/forge/ForgeCommonInitializer.java | 2 + .../java/vazkii/botania/api/BotaniaAPI.java | 9 ++ .../LooniumStructureConfiguration.java | 78 ++++++++---- .../common/config/ConfigDataManager.java | 118 ++++++++++++++++++ .../botania/common/impl/BotaniaAPIImpl.java | 13 ++ ...LooniumStructureConfigurationProvider.java | 10 +- 7 files changed, 199 insertions(+), 33 deletions(-) create mode 100644 Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java diff --git a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java index 8373f286bb..dd003159ec 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java @@ -81,6 +81,7 @@ import vazkii.botania.common.brew.BotaniaBrews; import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.command.SkyblockCommand; +import vazkii.botania.common.config.ConfigDataManager; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.entity.BotaniaEntities; import vazkii.botania.common.entity.GaiaGuardianEntity; @@ -138,6 +139,7 @@ public void onInitialize() { PatchouliAPI.get().registerMultiblock(prefix("gaia_ritual"), GaiaGuardianEntity.ARENA_MULTIBLOCK.get()); OrechidManager.registerListener(); + ConfigDataManager.registerListener(); CraftyCrateBlockEntity.registerListener(); CorporeaNodeDetectors.register(new FabricTransferCorporeaNodeDetector()); diff --git a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java index 283e0ea270..1cc2368877 100644 --- a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java +++ b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java @@ -94,6 +94,7 @@ import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.brew.effect.SoulCrossMobEffect; import vazkii.botania.common.command.SkyblockCommand; +import vazkii.botania.common.config.ConfigDataManager; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.entity.BotaniaEntities; import vazkii.botania.common.entity.GaiaGuardianEntity; @@ -166,6 +167,7 @@ public void commonSetup(FMLCommonSetupEvent evt) { PatchouliAPI.get().registerMultiblock(prefix("gaia_ritual"), GaiaGuardianEntity.ARENA_MULTIBLOCK.get()); OrechidManager.registerListener(); + ConfigDataManager.registerListener(); CraftyCrateBlockEntity.registerListener(); CorporeaNodeDetectors.register(new ForgeCapCorporeaNodeDetector()); if (ModList.get().isLoaded("inventorysorter")) { diff --git a/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java b/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java index 6700c5467c..1add27eefb 100644 --- a/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java +++ b/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java @@ -33,6 +33,7 @@ import vazkii.botania.api.corporea.CorporeaNodeDetector; import vazkii.botania.api.internal.DummyManaNetwork; import vazkii.botania.api.internal.ManaNetwork; +import vazkii.botania.common.config.ConfigDataManager; import java.util.Collections; import java.util.Map; @@ -216,4 +217,12 @@ default void sparkleFX(Level world, double x, double y, double z, float r, float default void registerCorporeaNodeDetector(CorporeaNodeDetector detector) { } + + default ConfigDataManager getConfigData() { + return null; + } + + default void setConfigData(ConfigDataManager configDataManager) { + + } } diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 22c7330687..3bf6026249 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -20,35 +20,42 @@ import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import vazkii.botania.api.BotaniaAPI; + import java.util.List; import java.util.Optional; +import java.util.function.Function; public class LooniumStructureConfiguration { - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance.group( - ExtraCodecs.POSITIVE_INT.fieldOf("manaCost").forGetter(o -> o.manaCost), - StructureSpawnOverride.BoundingBoxType.CODEC.fieldOf("boundingBoxType").forGetter(o -> o.boundingBoxType), - WeightedRandomList.codec(MobSpawnData.CODEC).fieldOf("spawnedMobs").forGetter(o -> o.spawnedMobs), - Codec.list(MobAttributeModifier.CODEC).fieldOf("attributeModifiers").forGetter(o -> o.attributeModifiers), - Codec.list(MobEffectToApply.CODEC).fieldOf("effectsToApply").forGetter(o -> o.effectsToApply) - ).apply(instance, LooniumStructureConfiguration::new) - ); - public static final Codec OPTIONAL_CODEC = RecordCodecBuilder.create( - instance -> instance.group( - ResourceLocation.CODEC.fieldOf("parent").forGetter(o -> o.parent), - ExtraCodecs.POSITIVE_INT.optionalFieldOf("manaCost").forGetter(o -> Optional.ofNullable(o.manaCost)), - StructureSpawnOverride.BoundingBoxType.CODEC.optionalFieldOf("boundingBoxType") - .forGetter(o -> Optional.ofNullable(o.boundingBoxType)), - WeightedRandomList.codec(MobSpawnData.CODEC).optionalFieldOf("spawnedMobs") - .forGetter(o -> Optional.ofNullable(o.spawnedMobs)), - Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") - .forGetter(o -> Optional.ofNullable(o.attributeModifiers)), - Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") - .forGetter(o -> Optional.ofNullable(o.effectsToApply)) - ).apply(instance, LooniumStructureConfiguration::new) - ); + public static final Codec CODEC = ExtraCodecs.validate( + RecordCodecBuilder.create( + instance -> instance.group( + ResourceLocation.CODEC.optionalFieldOf("parent") + .forGetter(lsc -> Optional.ofNullable(lsc.parent)), + ExtraCodecs.POSITIVE_INT.optionalFieldOf("manaCost") + .forGetter(lsc -> Optional.ofNullable(lsc.manaCost)), + StructureSpawnOverride.BoundingBoxType.CODEC.optionalFieldOf("boundingBoxType") + .forGetter(lsc -> Optional.ofNullable(lsc.boundingBoxType)), + WeightedRandomList.codec(MobSpawnData.CODEC).optionalFieldOf("spawnedMobs") + .forGetter(lsc -> Optional.ofNullable(lsc.spawnedMobs)), + Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") + .forGetter(lsc -> Optional.ofNullable(lsc.attributeModifiers)), + Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") + .forGetter(lsc -> Optional.ofNullable(lsc.effectsToApply)) + ).apply(instance, LooniumStructureConfiguration::new) + ), lsc -> { + if (lsc.parent == null && (lsc.manaCost == null || lsc.boundingBoxType == null || lsc.spawnedMobs == null)) { + return DataResult.error(() -> "Mana cost, bounding box type, and spawned mobs must be specified if there is no parent configuration"); + } + if (lsc.spawnedMobs != null && lsc.spawnedMobs.isEmpty()) { + return DataResult.error(() -> "Spawned mobs cannot be empty"); + } + return DataResult.success(lsc); + }); + public static final ResourceLocation DEFAULT_CONFIG_ID = new ResourceLocation(BotaniaAPI.MODID, "default"); public final Integer manaCost; public final StructureSpawnOverride.BoundingBoxType boundingBoxType; @@ -74,13 +81,13 @@ public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer this.parent = parent; } - private LooniumStructureConfiguration(ResourceLocation parent, Optional manaCost, + private LooniumStructureConfiguration(Optional parent, Optional manaCost, Optional boundingBoxType, Optional> spawnedMobs, Optional> attributeModifiers, Optional> effectsToApply) { - this(manaCost.orElse(null), boundingBoxType.orElse(null), spawnedMobs.orElse(null), - attributeModifiers.orElse(null), effectsToApply.orElse(null)); + this(parent.orElse(null), manaCost.orElse(null), boundingBoxType.orElse(null), + spawnedMobs.orElse(null), attributeModifiers.orElse(null), effectsToApply.orElse(null)); } public LooniumStructureConfiguration(ResourceLocation parent, @@ -88,6 +95,20 @@ public LooniumStructureConfiguration(ResourceLocation parent, this(parent, null, boundingBoxType, null, null, null); } + public LooniumStructureConfiguration getEffectiveConfig( + Function parentSupplier) { + if (parent == null) { + return this; + } + var parentConfig = parentSupplier.apply(parent).getEffectiveConfig(parentSupplier); + + return new LooniumStructureConfiguration(manaCost != null ? manaCost : parentConfig.manaCost, + boundingBoxType != null ? boundingBoxType : parentConfig.boundingBoxType, + spawnedMobs != null ? spawnedMobs : parentConfig.spawnedMobs, + attributeModifiers != null ? attributeModifiers : parentConfig.attributeModifiers, + effectsToApply != null ? effectsToApply : parentConfig.effectsToApply); + } + public static class MobSpawnData extends WeightedEntry.IntrusiveBase { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( @@ -216,6 +237,11 @@ private MobEffectToApply(MobEffect effect, Optional optionalDuration, O this(effect, optionalDuration.orElse(MobEffectInstance.INFINITE_DURATION), optionalAmplifier.orElse(0)); } + @NotNull + public MobEffectInstance createMobEffectInstance() { + return new MobEffectInstance(effect, duration, amplifier); + } + private Optional getOptionalDuration() { return duration != MobEffectInstance.INFINITE_DURATION ? Optional.of(duration) : Optional.empty(); } diff --git a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java new file mode 100644 index 0000000000..a0d7d88658 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java @@ -0,0 +1,118 @@ +package vazkii.botania.common.config; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.resources.PreparableReloadListener; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; + +import org.jetbrains.annotations.NotNull; + +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.configdata.LooniumStructureConfiguration; +import vazkii.botania.xplat.XplatAbstractions; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; + +public class ConfigDataManager implements PreparableReloadListener { + public static void registerListener() { + XplatAbstractions.INSTANCE.registerReloadListener(PackType.SERVER_DATA, prefix("configdata"), new ConfigDataManager()); + } + + private final Map looniumConfigs = new HashMap<>(); + + public LooniumStructureConfiguration getEffectiveLooniumStructureConfiguration(ResourceLocation id) { + LooniumStructureConfiguration configuration = this.looniumConfigs.get(id); + return configuration != null ? configuration.getEffectiveConfig(looniumConfigs::get) : null; + } + + private static void validateLooniumConfig(Map map) { + Set errorEntries = new HashSet<>(); + Set visitedEntries = new LinkedHashSet<>(); + do { + errorEntries.clear(); + for (var entry : map.entrySet()) { + ResourceLocation id = entry.getKey(); + ResourceLocation parent = entry.getValue().parent; + if (id.equals(parent)) { + BotaniaAPI.LOGGER.warn("Ignoring Loonium structure configuration, because it specified itself as parent: {}", id); + errorEntries.add(id); + } else { + visitedEntries.clear(); + if (!findTopmostParent(map, id, parent, visitedEntries)) { + BotaniaAPI.LOGGER.warn("Ignoring Loonium structure configuration(s) without top-most parent: {}", visitedEntries); + errorEntries.addAll(visitedEntries); + break; + } + } + } + errorEntries.forEach(map::remove); + } while (!errorEntries.isEmpty() && !map.isEmpty()); + + if (!map.containsKey(LooniumStructureConfiguration.DEFAULT_CONFIG_ID)) { + BotaniaAPI.LOGGER.error("Default Loonium configuration not found!"); + } + } + + private static boolean findTopmostParent(Map map, + ResourceLocation id, ResourceLocation parent, Set visitedEntries) { + if (!visitedEntries.add(id)) { + BotaniaAPI.LOGGER.warn("Cyclic dependency between Loonium structure configurations detected: {}", visitedEntries); + return false; + } + if (parent == null) { + return true; + } + var parentConfig = map.get(parent); + return parentConfig != null && findTopmostParent(map, parent, parentConfig.parent, visitedEntries); + } + + private void applyLooniumConfig(Map looniumConfigs) { + this.looniumConfigs.putAll(looniumConfigs); + } + + @NotNull + @Override + public CompletableFuture reload(@NotNull PreparationBarrier barrier, @NotNull ResourceManager manager, + @NotNull ProfilerFiller prepProfiler, @NotNull ProfilerFiller reloadProfiler, + @NotNull Executor backgroundExecutor, @NotNull Executor gameExecutor) { + var looniumTask = scheduleConfigParse(barrier, manager, backgroundExecutor, gameExecutor, ConfigDataType.LOONUIM); + + return CompletableFuture.allOf(looniumTask).thenRun(() -> BotaniaAPI.instance().setConfigData(this)); + } + + private CompletableFuture scheduleConfigParse(PreparationBarrier barrier, ResourceManager manager, + Executor backgroundExecutor, Executor gameExecutor, ConfigDataType type) { + return CompletableFuture.supplyAsync(() -> { + Map resourceMap = new HashMap<>(); + SimpleJsonResourceReloadListener.scanDirectory(manager, "config/" + type.directory, new Gson(), resourceMap); + Map configs = new HashMap<>(resourceMap.size()); + resourceMap.forEach((id, jsonElement) -> type.codec.parse(JsonOps.INSTANCE, jsonElement).result().ifPresent(c -> configs.put(id, c))); + type.validateFunction.accept(configs); + return configs; + }, backgroundExecutor) + .thenCompose(barrier::wait) + .thenAcceptAsync(c -> type.applyFunction.accept(this, c), gameExecutor); + } + + private record ConfigDataType (Codec codec, String directory, + Consumer> validateFunction, + BiConsumer> applyFunction) { + private static final ConfigDataType LOONUIM = + new ConfigDataType<>(LooniumStructureConfiguration.CODEC, "loonium", + ConfigDataManager::validateLooniumConfig, ConfigDataManager::applyLooniumConfig); + + } +} diff --git a/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java b/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java index 93002e5c98..25ae9cdf12 100644 --- a/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java +++ b/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java @@ -32,6 +32,7 @@ import vazkii.botania.api.internal.ManaNetwork; import vazkii.botania.client.fx.SparkleParticleData; import vazkii.botania.common.block.flower.functional.SolegnoliaBlockEntity; +import vazkii.botania.common.config.ConfigDataManager; import vazkii.botania.common.handler.BotaniaSounds; import vazkii.botania.common.handler.EquipmentHandler; import vazkii.botania.common.handler.ManaNetworkHandler; @@ -202,6 +203,8 @@ public Ingredient getRepairIngredient() { } } + private ConfigDataManager configDataManager = new ConfigDataManager(); + @Override public int apiVersion() { return 2; @@ -291,4 +294,14 @@ public void registerPaintableBlock(ResourceLocation block, Function run(@NotNull CachedOutput cache) { CompoundTag chargedCreeperNbt = new CompoundTag(); chargedCreeperNbt.putBoolean("powered", true); - ResourceLocation defaultConfigId = prefix("default"); + ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; configs.put(defaultConfigId, new LooniumStructureConfiguration( 35000, StructureSpawnOverride.BoundingBoxType.PIECE, WeightedRandomList.create( @@ -101,11 +100,8 @@ public CompletableFuture run(@NotNull CachedOutput cache) { for (var e : configs.entrySet()) { Path path = pathProvider.json(e.getKey()); var config = e.getValue(); - var jsonTree = (config.parent != null - ? LooniumStructureConfiguration.OPTIONAL_CODEC - : LooniumStructureConfiguration.CODEC) - .encodeStart(JsonOps.INSTANCE, config) - .getOrThrow(false, BotaniaAPI.LOGGER::error); + var jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) + .getOrThrow(false, BotaniaAPI.LOGGER::error); output.add(DataProvider.saveStable(cache, jsonTree, path)); } return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); From b7400d6478cc83fe75f4e75b664b444f0744e0f1 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Fri, 10 May 2024 21:17:07 +0200 Subject: [PATCH 09/26] Loonium uses structure configs and loot --- .../flower/functional/LooniumBlockEntity.java | 410 +++++++++++------- .../common/config/ConfigDataManager.java | 3 + .../internal_caps/LooniumComponent.java | 24 +- .../resources/assets/botania/lang/en_us.json | 6 +- 4 files changed, 288 insertions(+), 155 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index f868f4cf25..8849d1472f 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -8,7 +8,10 @@ */ package vazkii.botania.common.block.flower.functional; -import it.unimi.dsi.fastutil.objects.ObjectBooleanPair; +import com.google.common.base.Suppliers; + +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.*; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -18,43 +21,38 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; +import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.Difficulty; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.monster.CaveSpider; -import net.minecraft.world.entity.monster.Creeper; -import net.minecraft.world.entity.monster.Drowned; -import net.minecraft.world.entity.monster.EnderMan; -import net.minecraft.world.entity.monster.Husk; -import net.minecraft.world.entity.monster.Skeleton; -import net.minecraft.world.entity.monster.Spider; -import net.minecraft.world.entity.monster.Stray; -import net.minecraft.world.entity.monster.Zombie; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; +import net.minecraft.world.level.storage.loot.LootDataManager; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.block_entity.FunctionalFlowerBlockEntity; import vazkii.botania.api.block_entity.RadiusDescriptor; +import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.common.block.BotaniaFlowerBlocks; +import vazkii.botania.common.config.ConfigDataManager; +import vazkii.botania.common.internal_caps.LooniumComponent; import vazkii.botania.common.lib.BotaniaTags; import vazkii.botania.xplat.XplatAbstractions; import java.util.*; import java.util.function.Consumer; -import java.util.stream.Collectors; +import java.util.function.Supplier; import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; @@ -62,9 +60,25 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final int COST = 35000; private static final int RANGE = 5; private static final String TAG_LOOT_TABLE = "lootTable"; - public static final ResourceLocation[] DEFAULT_LOOT_TABLES = { prefix("loonium/default") }; - - private ResourceLocation[] lootTables = DEFAULT_LOOT_TABLES; + private static final String TAG_DETECTED_STRUCTURE = "detectedStructure"; + private static final String TAG_CONFIG_OVERRIDE = "configOverride"; + public static final ResourceLocation DEFAULT_LOOT_TABLE = prefix("loonium/default"); + private static final Supplier FALLBACK_CONFIG = + Suppliers.memoize(() -> new LooniumStructureConfiguration(COST, + StructureSpawnOverride.BoundingBoxType.PIECE, + WeightedRandomList.create(new LooniumStructureConfiguration.MobSpawnData(EntityType.ZOMBIE, 1)), + List.of(), List.of( + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION), + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE), + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.DAMAGE_RESISTANCE), + new LooniumStructureConfiguration.MobEffectToApply(MobEffects.DAMAGE_BOOST)))); + + @Nullable + private ResourceLocation lootTableOverride; + @Nullable + private Object2BooleanMap detectedStructures; + @Nullable + private ResourceLocation configOverride; public LooniumBlockEntity(BlockPos pos, BlockState state) { super(BotaniaFlowerBlocks.LOONIUM, pos, state); @@ -78,116 +92,119 @@ public void tickFlower() { return; } - if (ticksExisted == 1 && lootTables == DEFAULT_LOOT_TABLES) { - autodetectStructureLootTables(world); + if (detectedStructures == null) { + detectStructure(world); } - if (redstoneSignal == 0 && ticksExisted % 100 == 0 - && getMana() >= COST && world.getDifficulty() != Difficulty.PEACEFUL) { - var rand = world.random; + if (redstoneSignal != 0 || ticksExisted % 100 != 0 || world.getDifficulty() == Difficulty.PEACEFUL) { + return; + } - ItemStack stack = pickRandomLoot(world, rand); - if (stack.isEmpty()) { - return; - } + var configData = BotaniaAPI.instance().getConfigData(); + var structureConfigs = determineStructureConfigs(configData, detectedStructures); + var lootTables = determineLootTables(world, detectedStructures.keySet()); - int bound = RANGE * 2 + 1; - int xp = getEffectivePos().getX() - RANGE + rand.nextInt(bound); - int yp = getEffectivePos().getY(); - int zp = getEffectivePos().getZ() - RANGE + rand.nextInt(bound); + if (lootTables.isEmpty()) { + return; + } - BlockPos pos = new BlockPos(xp, yp - 1, zp); - do { - pos = pos.above(); - if (pos.getY() >= world.getMaxBuildHeight()) { - return; - } - } while (world.getBlockState(pos).isSuffocating(world, pos)); - pos = pos.above(); + var randomPick = lootTables.get(world.random.nextInt(lootTables.size())); + var pickedConfig = structureConfigs.getOrDefault(randomPick.key(), + structureConfigs.get(LooniumStructureConfiguration.DEFAULT_CONFIG_ID)); + var pickedLootTable = randomPick.value(); - double x = pos.getX() + Math.random(); - double y = pos.getY() + Math.random(); - double z = pos.getZ() + Math.random(); + if (getMana() < pickedConfig.manaCost) { + return; + } + + var pickedMobType = pickedConfig.spawnedMobs.getRandom(world.random).orElse(null); + if (pickedMobType == null) { + return; + } - // TODO: Mob types and weights should be defined per structure - Mob entity = spawnMob(world); - if (entity == null) { + ItemStack stack = pickRandomLootItem(world, pickedLootTable); + if (stack.isEmpty()) { + return; + } + + int bound = RANGE * 2 + 1; + int xp = getEffectivePos().getX() - RANGE + world.random.nextInt(bound); + int yp = getEffectivePos().getY(); + int zp = getEffectivePos().getZ() - RANGE + world.random.nextInt(bound); + + BlockPos pos = new BlockPos(xp, yp - 1, zp); + do { + pos = pos.above(); + if (pos.getY() >= world.getMaxBuildHeight()) { return; } + } while (world.getBlockState(pos).isSuffocating(world, pos)); + pos = pos.above(); - entity.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); - entity.setDeltaMovement(Vec3.ZERO); + double x = pos.getX() + Math.random(); + double y = pos.getY() + Math.random(); + double z = pos.getZ() + Math.random(); - // TODO: mob attribute modifications should be defined along with mob configuration - entity.getAttribute(Attributes.MAX_HEALTH).addPermanentModifier(new AttributeModifier("Loonium Modififer Health", 2, AttributeModifier.Operation.MULTIPLY_BASE)); - entity.setHealth(entity.getMaxHealth()); - entity.getAttribute(Attributes.ATTACK_DAMAGE).addPermanentModifier(new AttributeModifier("Loonium Modififer Damage", 1.5, AttributeModifier.Operation.MULTIPLY_BASE)); + Entity entity = pickedMobType.type.create(world); + if (!(entity instanceof Mob mob)) { + return; + } - // TODO: mob potion effects should be defined in the mob configuration - entity.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, - entity instanceof Creeper ? 100 : MobEffectInstance.INFINITE_DURATION, 0)); - entity.addEffect(new MobEffectInstance(MobEffects.REGENERATION, - entity instanceof Creeper ? 100 : MobEffectInstance.INFINITE_DURATION, 0)); + if (pickedMobType.nbt != null) { + mob.readAdditionalSaveData(pickedMobType.nbt); + } - XplatAbstractions.INSTANCE.looniumComponent(entity).setDrop(stack); + mob.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); + mob.setDeltaMovement(Vec3.ZERO); + + var attributeModifiers = pickedMobType.attributeModifiers != null + ? pickedMobType.attributeModifiers + : pickedConfig.attributeModifiers; + for (var attributeModifier : attributeModifiers) { + var attribute = mob.getAttribute(attributeModifier.attribute); + if (attribute != null) { + attribute.addPermanentModifier(attributeModifier.createAttributeModifier()); + if (attribute.getAttribute() == Attributes.MAX_HEALTH) { + mob.setHealth(mob.getMaxHealth()); + } + } + } - entity.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); - // prevent armor/weapon drops on player kill, also no nautilus shells from drowned: - Arrays.stream(EquipmentSlot.values()).forEach(slot -> entity.setDropChance(slot, 0)); - world.addFreshEntity(entity); - entity.spawnAnim(); + var effectsToApply = pickedMobType.effectsToApply != null + ? pickedMobType.effectsToApply + : pickedConfig.effectsToApply; + for (var effectToApply : effectsToApply) { + mob.addEffect(effectToApply.createMobEffectInstance()); + } - addMana(-COST); - sync(); + LooniumComponent looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(mob); + if (looniumComponent != null) { + looniumComponent.setDrop(stack); } - } - private static @Nullable Mob spawnMob(ServerLevel world) { - Mob entity = null; - if (world.random.nextInt(50) == 0) { - entity = new EnderMan(EntityType.ENDERMAN, world); - } else if (world.random.nextInt(10) == 0) { - entity = new Creeper(EntityType.CREEPER, world); - if (world.random.nextInt(200) == 0) { - CompoundTag charged = new CompoundTag(); - charged.putBoolean("powered", true); - entity.readAdditionalSaveData(charged); - } - } else { - switch (world.random.nextInt(3)) { - case 0: - if (world.random.nextInt(10) == 0) { - entity = new Husk(EntityType.HUSK, world); - } else if (world.random.nextInt(5) == 0) { - entity = new Drowned(EntityType.DROWNED, world); - } else { - entity = new Zombie(world); - } - break; - case 1: - if (world.random.nextInt(10) == 0) { - entity = new Stray(EntityType.STRAY, world); - } else { - entity = new Skeleton(EntityType.SKELETON, world); - } - break; - case 2: - if (world.random.nextInt(10) == 0) { - entity = new CaveSpider(EntityType.CAVE_SPIDER, world); - } else { - // Note: could spawn as spider jockey, and we have no control over the skeleton - entity = new Spider(EntityType.SPIDER, world); - } - break; + mob.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); + // in case the mob spawned with a vehicle or passenger(s), ensure those don't drop unexpected loot + mob.getRootVehicle().getPassengersAndSelf().forEach(e -> { + if (e != mob && e instanceof Mob otherMob) { + // prevent armor/weapon drops on player kill, also no nautilus shells from drowned: + Arrays.stream(EquipmentSlot.values()).forEach(slot -> otherMob.setDropChance(slot, 0)); + LooniumComponent otherLooniumComponent = XplatAbstractions.INSTANCE.looniumComponent(otherMob); + if (otherLooniumComponent != null) { + otherLooniumComponent.setDropNothing(true); + } } - } - return entity; + }); + + world.addFreshEntity(mob); + mob.spawnAnim(); + + addMana(-COST); + sync(); } - private ItemStack pickRandomLoot(ServerLevel world, RandomSource rand) { - var lootTableId = lootTables[lootTables.length > 1 ? new Random().nextInt(lootTables.length) : 0]; + private static ItemStack pickRandomLootItem(ServerLevel world, LootTable pickedLootTable) { LootParams params = new LootParams.Builder(world).create(LootContextParamSets.EMPTY); - List stacks = world.getServer().getLootData().getLootTable(lootTableId).getRandomItems(params, rand.nextLong()); + List stacks = pickedLootTable.getRandomItems(params, world.random.nextLong()); stacks.removeIf(s -> s.isEmpty() || s.is(BotaniaTags.Items.LOONIUM_BLACKLIST)); if (stacks.isEmpty()) { return ItemStack.EMPTY; @@ -197,9 +214,75 @@ private ItemStack pickRandomLoot(ServerLevel world, RandomSource rand) { } } - private void autodetectStructureLootTables(ServerLevel world) { - // structure ID -> whether the position is inside a structure piece (false = only overall bounding box) - var detectedStructures = new ArrayList>(); + @NotNull + private List> determineLootTables(ServerLevel world, + Set structureIds) { + var lootTables = new ArrayList>(); + LootDataManager lootData = world.getServer().getLootData(); + if (lootTableOverride != null) { + LootTable lootTable = lootData.getLootTable(lootTableOverride); + if (lootTable != LootTable.EMPTY) { + lootTables.add(Pair.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, lootTable)); + } + } else { + for (var structureId : structureIds) { + var lootTableId = structureId.equals(LooniumStructureConfiguration.DEFAULT_CONFIG_ID) + ? DEFAULT_LOOT_TABLE + : prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); + LootTable lootTable = lootData.getLootTable(lootTableId); + if (lootTable != LootTable.EMPTY) { + lootTables.add(Pair.of(structureId, lootTable)); + } + } + } + if (lootTables.isEmpty()) { + LootTable lootTable = lootData.getLootTable(DEFAULT_LOOT_TABLE); + if (lootTable != LootTable.EMPTY) { + lootTables.add(Pair.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, lootTable)); + } + } + return lootTables; + } + + /** + * Build a map of structure IDs to resolved Loonium configurations, i.e. no need to traverse any parents. + * + * @param configData Configuration data to read from. + * @param structures Detected structures to work with. + * @return The map, which is guaranteed to not be empty. + */ + @NotNull + private Map determineStructureConfigs( + @NotNull ConfigDataManager configData, @NotNull Object2BooleanMap structures) { + if (configOverride != null) { + LooniumStructureConfiguration overrideConfig = + configData.getEffectiveLooniumStructureConfiguration(configOverride); + return Map.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, + overrideConfig != null ? overrideConfig : getDefaultConfig(configData)); + } + + var structureConfigs = new HashMap(); + for (var structureEntry : structures.object2BooleanEntrySet()) { + var structureConfig = configData.getEffectiveLooniumStructureConfiguration(structureEntry.getKey()); + if (structureConfig != null && (structureEntry.getBooleanValue() + || structureConfig.boundingBoxType == StructureSpawnOverride.BoundingBoxType.STRUCTURE)) { + structureConfigs.put(structureEntry.getKey(), structureConfig); + } + } + + structureConfigs.put(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, getDefaultConfig(configData)); + return structureConfigs; + } + + private static LooniumStructureConfiguration getDefaultConfig(ConfigDataManager configData) { + var defaultConfig = configData.getEffectiveLooniumStructureConfiguration( + LooniumStructureConfiguration.DEFAULT_CONFIG_ID); + return defaultConfig != null ? defaultConfig : FALLBACK_CONFIG.get(); + } + + private void detectStructure(ServerLevel world) { + // structure ID and whether the position is inside a structure piece (false = only overall bounding box) + var structureMap = new Object2BooleanRBTreeMap(); StructureManager structureManager = world.structureManager(); BlockPos pos = getBlockPos(); var structures = structureManager.getAllStructuresAt(pos); @@ -207,38 +290,26 @@ private void autodetectStructureLootTables(ServerLevel world) { Structure structure = entry.getKey(); var start = structureManager.getStructureAt(pos, structure); if (start.isValid()) { - ResourceLocation structureId = world.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(structure); + ResourceLocation structureId = + world.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(structure); boolean insidePiece = structureManager.structureHasPieceAt(pos, start); - BotaniaAPI.LOGGER.info("Found structure {}, inside piece: {}", structureId, insidePiece); - detectedStructures.add(ObjectBooleanPair.of(structureId, insidePiece)); + if (insidePiece || !structureMap.getBoolean(structureId)) { + structureMap.put(structureId, insidePiece); + } } } - if (detectedStructures.isEmpty()) { - // not within any structures, keep default loot table - return; - } - - var lootTableCandidates = new ArrayList(detectedStructures.size()); - for (var entry : detectedStructures) { - // TODO: grab structure configuration data from registry (assume must be inside a piece for now) - if (!entry.valueBoolean()) { - continue; - } - var structureId = entry.key(); - var candidateId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); - LootTable lootTable = world.getServer().getLootData().getLootTable(candidateId); - if (lootTable != LootTable.EMPTY) { - lootTableCandidates.add(candidateId); - } + if (structureMap.isEmpty()) { + detectedStructures = Object2BooleanMaps.emptyMap(); + } else if (structureMap.size() == 1) { + var key = structureMap.firstKey(); + detectedStructures = Object2BooleanMaps.singleton(key, structureMap.getBoolean(key)); + } else { + detectedStructures = new Object2BooleanArrayMap<>(structureMap); } - if (!lootTableCandidates.isEmpty()) { - BotaniaAPI.LOGGER.info("Using loot tables: {}", lootTableCandidates); - lootTables = lootTableCandidates.toArray(ResourceLocation[]::new); - setChanged(); - sync(); - } + setChanged(); + sync(); } @Override @@ -265,18 +336,57 @@ public RadiusDescriptor getRadius() { public void readFromPacketNBT(CompoundTag cmp) { super.readFromPacketNBT(cmp); if (cmp.contains(TAG_LOOT_TABLE)) { - var lootTableString = cmp.getString(TAG_LOOT_TABLE); - lootTables = Arrays.stream(lootTableString.split(",")) - .map(ResourceLocation::new).toArray(ResourceLocation[]::new); + lootTableOverride = new ResourceLocation(cmp.getString(TAG_LOOT_TABLE)); + } + if (cmp.contains(TAG_CONFIG_OVERRIDE)) { + configOverride = new ResourceLocation(cmp.getString(TAG_CONFIG_OVERRIDE)); + } + if (cmp.contains(TAG_DETECTED_STRUCTURE)) { + var rawString = cmp.getString(TAG_DETECTED_STRUCTURE); + if (rawString.isEmpty()) { + detectedStructures = Object2BooleanMaps.emptyMap(); + } else { + var structureList = Arrays.stream(rawString.split(",")).map(part -> { + if (part.contains("|")) { + var components = part.split("\\|", 2); + return ObjectBooleanPair.of(new ResourceLocation(components[0]), Boolean.parseBoolean(components[1])); + } else { + return ObjectBooleanPair.of(new ResourceLocation(part), false); + } + }).toList(); + if (structureList.size() == 1) { + detectedStructures = Object2BooleanMaps.singleton(structureList.get(0).key(), structureList.get(0).valueBoolean()); + } else { + // list should never contain more than a few entries, so array is fine and retains entry order + var map = new Object2BooleanArrayMap(structureList.size()); + structureList.forEach(entry -> map.put(entry.key(), entry.valueBoolean())); + detectedStructures = map; + } + } } } @Override public void writeToPacketNBT(CompoundTag cmp) { super.writeToPacketNBT(cmp); - if (lootTables.length >= 1) { - cmp.putString(TAG_LOOT_TABLE, - Arrays.stream(lootTables).map(ResourceLocation::toString).collect(Collectors.joining(","))); + if (lootTableOverride != null) { + cmp.putString(TAG_LOOT_TABLE, lootTableOverride.toString()); + } + if (configOverride != null) { + cmp.putString(TAG_CONFIG_OVERRIDE, configOverride.toString()); + } + if (detectedStructures != null) { + var stringBuilder = new StringBuilder(); + boolean first = true; + for (var entry : detectedStructures.object2BooleanEntrySet()) { + if (first) { + first = false; + } else { + stringBuilder.append(','); + } + stringBuilder.append(entry.getKey()).append('|').append(entry.getBooleanValue()); + } + cmp.putString(TAG_DETECTED_STRUCTURE, stringBuilder.toString()); } } @@ -294,22 +404,22 @@ public WandHud(LooniumBlockEntity flower) { @Override public void renderHUD(GuiGraphics gui, Minecraft mc) { - String attuneType; - if (Arrays.equals(flower.lootTables, DEFAULT_LOOT_TABLES)) { - attuneType = "generic_drops"; - } else if (flower.lootTables.length == 1) { - attuneType = "structure_drops"; + String lootType; + if (flower.lootTableOverride != null) { + lootType = "custom_loot"; + } else if (flower.detectedStructures == null || flower.detectedStructures.isEmpty()) { + lootType = "generic_loot"; } else { - attuneType = "multiple_structure_drops"; + lootType = "structure_loot"; } - String attuned = I18n.get("botaniamisc.loonium." + attuneType).formatted(flower.lootTables.length); - int filterWidth = mc.font.width(attuned); + String lootTypeMessage = I18n.get("botaniamisc.loonium." + lootType); + int filterWidth = mc.font.width(lootTypeMessage); int filterTextStart = (mc.getWindow().getGuiScaledWidth() - filterWidth) / 2; int halfMinWidth = (filterWidth + 4) / 2; int centerY = mc.getWindow().getGuiScaledHeight() / 2; super.renderHUD(gui, mc, halfMinWidth, halfMinWidth, 40); - gui.drawString(mc.font, attuned, filterTextStart, centerY + 30, flower.getColor()); + gui.drawString(mc.font, lootTypeMessage, filterTextStart, centerY + 30, flower.getColor()); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java index a0d7d88658..4f5132a0bb 100644 --- a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java +++ b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java @@ -13,6 +13,7 @@ import net.minecraft.util.profiling.ProfilerFiller; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.configdata.LooniumStructureConfiguration; @@ -33,6 +34,7 @@ public static void registerListener() { private final Map looniumConfigs = new HashMap<>(); + @Nullable public LooniumStructureConfiguration getEffectiveLooniumStructureConfiguration(ResourceLocation id) { LooniumStructureConfiguration configuration = this.looniumConfigs.get(id); return configuration != null ? configuration.getEffectiveConfig(looniumConfigs::get) : null; @@ -80,6 +82,7 @@ private static boolean findTopmostParent(Map looniumConfigs) { + BotaniaAPI.LOGGER.info("Loaded {} Loonium configurations", looniumConfigs.size()); this.looniumConfigs.putAll(looniumConfigs); } diff --git a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java index a81feef1ac..8b6b03d065 100644 --- a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java +++ b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java @@ -13,7 +13,9 @@ public class LooniumComponent extends SerializableComponent { protected static final String TAG_TODROP = "toDrop"; + protected static final String TAG_DROP_NOTHING = "dropNothing"; private ItemStack toDrop = ItemStack.EMPTY; + private boolean dropNothing; public ItemStack getDrop() { return toDrop; @@ -23,17 +25,29 @@ public void setDrop(ItemStack stack) { this.toDrop = stack; } + public boolean isDropNothing() { + return dropNothing; + } + + public void setDropNothing(boolean dropNothing) { + if (dropNothing) { + setDrop(ItemStack.EMPTY); + } + this.dropNothing = dropNothing; + } + @Override public boolean equals(Object obj) { if (this == obj) { return true; } - return obj instanceof LooniumComponent component && ItemStack.matches(component.toDrop, toDrop); + return obj instanceof LooniumComponent component && ItemStack.matches(component.toDrop, toDrop) + && component.dropNothing == dropNothing; } @Override public int hashCode() { - return toDrop.hashCode(); + return toDrop.hashCode() ^ Boolean.hashCode(dropNothing); } @Override @@ -43,6 +57,9 @@ public void readFromNbt(CompoundTag tag) { } else { setDrop(ItemStack.EMPTY); } + if (tag.contains(TAG_DROP_NOTHING)) { + setDropNothing(tag.getBoolean(TAG_DROP_NOTHING)); + } } @Override @@ -50,5 +67,8 @@ public void writeToNbt(CompoundTag tag) { if (!getDrop().isEmpty()) { tag.put(TAG_TODROP, getDrop().save(new CompoundTag())); } + if (isDropNothing()) { + tag.putBoolean(TAG_DROP_NOTHING, true); + } } } diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index 0808cbe7e5..38e0b28571 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -132,9 +132,9 @@ "botaniamisc.rannuncarpus.state_sensitive": "Match Exact State", "botaniamisc.rannuncarpus.state_insensitive": "Match Block Only", "botaniamisc.lokiRingLimitReached": "Selection limit reached", - "botaniamisc.loonium.generic_drops": "Not attuned", - "botaniamisc.loonium.structure_drops": "Attuned to structure", - "botaniamisc.loonium.multiple_structure_drops": "Attuned to %d structures", + "botaniamisc.loonium.generic_loot": "Generic loot", + "botaniamisc.loonium.structure_loot": "Structure loot", + "botaniamisc.loonium.custom_loot": "Customized loot", "botaniamisc.pollidisiac.feed_adults": "Feeding adult animals", "botaniamisc.pollidisiac.feed_babies": "Feeding baby animals", "botaniamisc.pollidisiac.feed_all": "Feeding all animals", From c34a0b3629e79bf5ed3fa04065a73564d8314bd6 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sun, 12 May 2024 12:26:31 +0200 Subject: [PATCH 10/26] Remove unintended non-Loonium drops from additional mobs (covers e.g. the skeleton from a spider jockey or the bonus chicken for some baby zombies) --- .../botania/fabric/mixin/LivingEntityFabricMixin.java | 4 +++- .../java/vazkii/botania/forge/ForgeCommonInitializer.java | 8 +++++--- .../block/flower/functional/LooniumBlockEntity.java | 7 ++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Fabric/src/main/java/vazkii/botania/fabric/mixin/LivingEntityFabricMixin.java b/Fabric/src/main/java/vazkii/botania/fabric/mixin/LivingEntityFabricMixin.java index 77fc8277e9..3834d002e7 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/mixin/LivingEntityFabricMixin.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/mixin/LivingEntityFabricMixin.java @@ -55,7 +55,9 @@ private void dropEnd(DamageSource source, CallbackInfo ci) { private void dropLoonium(DamageSource source, boolean causedByPlayer, CallbackInfo ci) { var self = (LivingEntity) (Object) this; LooniumBlockEntity.dropLooniumItems(self, stack -> { - self.spawnAtLocation(stack); + if (!stack.isEmpty()) { + self.spawnAtLocation(stack); + } ci.cancel(); }); } diff --git a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java index 1cc2368877..4a9369669b 100644 --- a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java +++ b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java @@ -395,9 +395,11 @@ private void registerEvents() { }); LooniumBlockEntity.dropLooniumItems(living, stack -> { e.getDrops().clear(); - var ent = new ItemEntity(living.level(), living.getX(), living.getY(), living.getZ(), stack); - ent.setDefaultPickUpDelay(); - e.getDrops().add(ent); + if (!stack.isEmpty()) { + var ent = new ItemEntity(living.level(), living.getX(), living.getY(), living.getZ(), stack); + ent.setDefaultPickUpDelay(); + e.getDrops().add(ent); + } }); }); bus.addListener((LivingDeathEvent e) -> { diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 8849d1472f..3f4969b251 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -392,9 +392,10 @@ public void writeToPacketNBT(CompoundTag cmp) { public static void dropLooniumItems(LivingEntity living, Consumer consumer) { var comp = XplatAbstractions.INSTANCE.looniumComponent(living); - if (comp != null && !comp.getDrop().isEmpty()) { - consumer.accept(comp.getDrop()); - } + if (comp != null) + if (!comp.getDrop().isEmpty() || comp.isDropNothing()) { + consumer.accept(comp.getDrop()); + } } public static class WandHud extends BindableFlowerWandHud { From 58cb3707c36928fd1147cad118d08d2ce47c1020 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sun, 12 May 2024 13:47:05 +0200 Subject: [PATCH 11/26] Limit number of spawned mobs around Loonium --- .../a864b94d006aba05700c96ad7a5769c8571473bc | 2 +- .../data/botania/config/loonium/default.json | 1 + .../LooniumStructureConfiguration.java | 16 +++++--- .../flower/functional/LooniumBlockEntity.java | 39 ++++++++++++++++--- ...LooniumStructureConfigurationProvider.java | 4 +- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc index eb617e08cd..4ffed6e614 100644 --- a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc +++ b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc @@ -1,5 +1,5 @@ // 1.20.1 Botania/Loonium structure configuration -79c6634f96360b3aa542841a94f84429f35c5bac data/botania/config/loonium/default.json +f27da6c6a0976510c1a8c2dc652b4d13eda750b3 data/botania/config/loonium/default.json 8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_cold.json 8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_warm.json 8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/pillager_outpost.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/default.json b/Xplat/src/generated/resources/data/botania/config/loonium/default.json index cad9c7b5fc..ca82aa1736 100644 --- a/Xplat/src/generated/resources/data/botania/config/loonium/default.json +++ b/Xplat/src/generated/resources/data/botania/config/loonium/default.json @@ -23,6 +23,7 @@ } ], "manaCost": 35000, + "maxNearbyMobs": 10, "spawnedMobs": [ { "type": "minecraft:enderman", diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 3bf6026249..3f09e5efdf 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -37,6 +37,8 @@ public class LooniumStructureConfiguration { .forGetter(lsc -> Optional.ofNullable(lsc.parent)), ExtraCodecs.POSITIVE_INT.optionalFieldOf("manaCost") .forGetter(lsc -> Optional.ofNullable(lsc.manaCost)), + ExtraCodecs.POSITIVE_INT.optionalFieldOf("maxNearbyMobs") + .forGetter(lsc -> Optional.ofNullable(lsc.maxNearbyMobs)), StructureSpawnOverride.BoundingBoxType.CODEC.optionalFieldOf("boundingBoxType") .forGetter(lsc -> Optional.ofNullable(lsc.boundingBoxType)), WeightedRandomList.codec(MobSpawnData.CODEC).optionalFieldOf("spawnedMobs") @@ -58,22 +60,24 @@ public class LooniumStructureConfiguration { public static final ResourceLocation DEFAULT_CONFIG_ID = new ResourceLocation(BotaniaAPI.MODID, "default"); public final Integer manaCost; + public final Integer maxNearbyMobs; public final StructureSpawnOverride.BoundingBoxType boundingBoxType; public final WeightedRandomList spawnedMobs; public final List attributeModifiers; public final List effectsToApply; public final ResourceLocation parent; - public LooniumStructureConfiguration(Integer manaCost, StructureSpawnOverride.BoundingBoxType boundingBoxType, + public LooniumStructureConfiguration(Integer manaCost, Integer maxNearbyMobs, StructureSpawnOverride.BoundingBoxType boundingBoxType, WeightedRandomList spawnedMobs, List attributeModifiers, List effectsToApply) { - this(null, manaCost, boundingBoxType, spawnedMobs, attributeModifiers, effectsToApply); + this(null, manaCost, maxNearbyMobs, boundingBoxType, spawnedMobs, attributeModifiers, effectsToApply); } - public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer manaCost, + public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer manaCost, @Nullable Integer maxNearbyMobs, @Nullable StructureSpawnOverride.BoundingBoxType boundingBoxType, @Nullable WeightedRandomList spawnedMobs, @Nullable List attributeModifiers, @Nullable List effectsToApply) { this.manaCost = manaCost; + this.maxNearbyMobs = maxNearbyMobs; this.spawnedMobs = spawnedMobs; this.boundingBoxType = boundingBoxType; this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; @@ -82,17 +86,18 @@ public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer } private LooniumStructureConfiguration(Optional parent, Optional manaCost, + Optional maxNearbyMobs, Optional boundingBoxType, Optional> spawnedMobs, Optional> attributeModifiers, Optional> effectsToApply) { - this(parent.orElse(null), manaCost.orElse(null), boundingBoxType.orElse(null), + this(parent.orElse(null), manaCost.orElse(null), maxNearbyMobs.orElse(null), boundingBoxType.orElse(null), spawnedMobs.orElse(null), attributeModifiers.orElse(null), effectsToApply.orElse(null)); } public LooniumStructureConfiguration(ResourceLocation parent, StructureSpawnOverride.BoundingBoxType boundingBoxType) { - this(parent, null, boundingBoxType, null, null, null); + this(parent, null, null, boundingBoxType, null, null, null); } public LooniumStructureConfiguration getEffectiveConfig( @@ -103,6 +108,7 @@ public LooniumStructureConfiguration getEffectiveConfig( var parentConfig = parentSupplier.apply(parent).getEffectiveConfig(parentSupplier); return new LooniumStructureConfiguration(manaCost != null ? manaCost : parentConfig.manaCost, + maxNearbyMobs != null ? maxNearbyMobs : parentConfig.maxNearbyMobs, boundingBoxType != null ? boundingBoxType : parentConfig.boundingBoxType, spawnedMobs != null ? spawnedMobs : parentConfig.spawnedMobs, attributeModifiers != null ? attributeModifiers : parentConfig.attributeModifiers, diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 3f4969b251..13bcd36101 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -35,6 +35,7 @@ import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; @@ -53,18 +54,21 @@ import java.util.*; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.stream.Collectors; import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { - private static final int COST = 35000; + public static final int DEFAULT_COST = 35000; + public static final int DEFAULT_MAX_NEARBY_MOBS = 10; private static final int RANGE = 5; + private static final int CHECK_RANGE = 9; private static final String TAG_LOOT_TABLE = "lootTable"; private static final String TAG_DETECTED_STRUCTURE = "detectedStructure"; private static final String TAG_CONFIG_OVERRIDE = "configOverride"; public static final ResourceLocation DEFAULT_LOOT_TABLE = prefix("loonium/default"); private static final Supplier FALLBACK_CONFIG = - Suppliers.memoize(() -> new LooniumStructureConfiguration(COST, + Suppliers.memoize(() -> new LooniumStructureConfiguration(DEFAULT_COST, DEFAULT_MAX_NEARBY_MOBS, StructureSpawnOverride.BoundingBoxType.PIECE, WeightedRandomList.create(new LooniumStructureConfiguration.MobSpawnData(EntityType.ZOMBIE, 1)), List.of(), List.of( @@ -93,10 +97,14 @@ public void tickFlower() { } if (detectedStructures == null) { + // Detection intentionally uses the flower position, not the effective position, + // since the latter could change while this detection is only executed once. detectStructure(world); } - if (redstoneSignal != 0 || ticksExisted % 100 != 0 || world.getDifficulty() == Difficulty.PEACEFUL) { + if (redstoneSignal != 0 || ticksExisted % 100 != 0 || world.getDifficulty() == Difficulty.PEACEFUL + // so mobs won't spawn in unloaded or border chunks + || !world.isPositionEntityTicking(getEffectivePos())) { return; } @@ -117,6 +125,11 @@ public void tickFlower() { return; } + int numberOfMobsAround = countNearbyMobs(world, pickedConfig); + if (numberOfMobsAround >= pickedConfig.maxNearbyMobs) { + return; + } + var pickedMobType = pickedConfig.spawnedMobs.getRandom(world.random).orElse(null); if (pickedMobType == null) { return; @@ -127,6 +140,11 @@ public void tickFlower() { return; } + spawnMob(world, pickedMobType, pickedConfig, stack); + } + + private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnData pickedMobType, + LooniumStructureConfiguration pickedConfig, ItemStack stack) { int bound = RANGE * 2 + 1; int xp = getEffectivePos().getX() - RANGE + world.random.nextInt(bound); int yp = getEffectivePos().getY(); @@ -198,10 +216,16 @@ public void tickFlower() { world.addFreshEntity(mob); mob.spawnAnim(); - addMana(-COST); + addMana(-DEFAULT_COST); sync(); } + private int countNearbyMobs(ServerLevel world, LooniumStructureConfiguration pickedConfig) { + var setOfMobTypes = pickedConfig.spawnedMobs.unwrap().stream().map(msd -> msd.type).collect(Collectors.toSet()); + return world.getEntitiesOfClass(Mob.class, new AABB(getEffectivePos()).inflate(CHECK_RANGE), + m -> setOfMobTypes.contains(m.getType())).size(); + } + private static ItemStack pickRandomLootItem(ServerLevel world, LootTable pickedLootTable) { LootParams params = new LootParams.Builder(world).create(LootContextParamSets.EMPTY); List stacks = pickedLootTable.getRandomItems(params, world.random.nextLong()); @@ -319,7 +343,7 @@ public int getColor() { @Override public int getMaxMana() { - return COST; + return DEFAULT_COST; } @Override @@ -332,6 +356,11 @@ public RadiusDescriptor getRadius() { return RadiusDescriptor.Rectangle.square(getEffectivePos(), RANGE); } + @Override + public RadiusDescriptor getSecondaryRadius() { + return RadiusDescriptor.Rectangle.square(getEffectivePos(), CHECK_RANGE); + } + @Override public void readFromPacketNBT(CompoundTag cmp) { super.readFromPacketNBT(cmp); diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index 13c277c545..275ff47e8d 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -19,6 +19,7 @@ import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.configdata.LooniumStructureConfiguration; +import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import java.nio.file.Path; import java.util.ArrayList; @@ -51,7 +52,8 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; configs.put(defaultConfigId, new LooniumStructureConfiguration( - 35000, StructureSpawnOverride.BoundingBoxType.PIECE, + LooniumBlockEntity.DEFAULT_COST, LooniumBlockEntity.DEFAULT_MAX_NEARBY_MOBS, + StructureSpawnOverride.BoundingBoxType.PIECE, WeightedRandomList.create( // weights roughly based on original Loonium mob selection logic new LooniumStructureConfiguration.MobSpawnData(EntityType.ENDERMAN, 40), From c6b68fc39e3aea5bc695d830dce76517b7fae123 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sun, 12 May 2024 15:15:59 +0200 Subject: [PATCH 12/26] Loonium-spawned mobs have no instant despawn range --- .../flower/functional/LooniumBlockEntity.java | 1 + .../internal_caps/LooniumComponent.java | 22 +++++++++- .../java/vazkii/botania/mixin/MobMixin.java | 40 +++++++++++++++++++ .../main/resources/botania_xplat.mixins.json | 1 + 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 Xplat/src/main/java/vazkii/botania/mixin/MobMixin.java diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 13bcd36101..8bf2e273fa 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -198,6 +198,7 @@ private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnD LooniumComponent looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(mob); if (looniumComponent != null) { looniumComponent.setDrop(stack); + looniumComponent.setSlowDespawn(true); } mob.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); diff --git a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java index 8b6b03d065..9792468309 100644 --- a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java +++ b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java @@ -11,11 +11,15 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; +import java.util.Objects; + public class LooniumComponent extends SerializableComponent { protected static final String TAG_TODROP = "toDrop"; protected static final String TAG_DROP_NOTHING = "dropNothing"; + protected static final String TAG_SLOW_DESPAWN = "slowDespawn"; private ItemStack toDrop = ItemStack.EMPTY; private boolean dropNothing; + private boolean slowDespawn; public ItemStack getDrop() { return toDrop; @@ -36,18 +40,26 @@ public void setDropNothing(boolean dropNothing) { this.dropNothing = dropNothing; } + public boolean isSlowDespawn() { + return slowDespawn; + } + + public void setSlowDespawn(boolean slowDespawn) { + this.slowDespawn = slowDespawn; + } + @Override public boolean equals(Object obj) { if (this == obj) { return true; } return obj instanceof LooniumComponent component && ItemStack.matches(component.toDrop, toDrop) - && component.dropNothing == dropNothing; + && component.dropNothing == dropNothing && component.slowDespawn == slowDespawn; } @Override public int hashCode() { - return toDrop.hashCode() ^ Boolean.hashCode(dropNothing); + return Objects.hash(toDrop.hashCode(), dropNothing, slowDespawn); } @Override @@ -60,6 +72,9 @@ public void readFromNbt(CompoundTag tag) { if (tag.contains(TAG_DROP_NOTHING)) { setDropNothing(tag.getBoolean(TAG_DROP_NOTHING)); } + if (tag.contains(TAG_SLOW_DESPAWN)) { + setSlowDespawn(tag.getBoolean(TAG_SLOW_DESPAWN)); + } } @Override @@ -70,5 +85,8 @@ public void writeToNbt(CompoundTag tag) { if (isDropNothing()) { tag.putBoolean(TAG_DROP_NOTHING, true); } + if (isSlowDespawn()) { + tag.putBoolean(TAG_SLOW_DESPAWN, true); + } } } diff --git a/Xplat/src/main/java/vazkii/botania/mixin/MobMixin.java b/Xplat/src/main/java/vazkii/botania/mixin/MobMixin.java new file mode 100644 index 0000000000..4d55f5a1fd --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/mixin/MobMixin.java @@ -0,0 +1,40 @@ +package vazkii.botania.mixin; + +import net.minecraft.world.entity.Mob; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; + +import vazkii.botania.xplat.XplatAbstractions; + +@Mixin(Mob.class) +public class MobMixin { + /** + * Prevent instant despawning when outside the nearest player's despawn sphere by pretending the mob is closer to + * that player than it actually is. + * + * @param distToNearestPlayerSquared Squared distance to the nearest player. + * @return If mob should not despawn instantly (e.g. because it was spawned by a Loonium or by a monster spawner + * with an active Life Imbuer) but is farther away than its despawn distance, return a distance just under + * the (squared) despawn distance, otherwise return the original value. + */ + @ModifyVariable( + method = "checkDespawn", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/MobCategory;getDespawnDistance()I", ordinal = 0), + slice = @Slice( + from = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;distanceToSqr(Lnet/minecraft/world/entity/Entity;)D"), + to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;removeWhenFarAway(D)Z") + ) + ) + private double reduceDistToNearestPlayer(double distToNearestPlayerSquared) { + Mob thisMob = (Mob) (Object) this; + var looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(thisMob); + if (looniumComponent != null && looniumComponent.isSlowDespawn()) { + double justUnderDespawnDistance = thisMob.getType().getCategory().getDespawnDistance() - 1; + return Math.min(justUnderDespawnDistance * justUnderDespawnDistance, distToNearestPlayerSquared); + } + return distToNearestPlayerSquared; + } +} diff --git a/Xplat/src/main/resources/botania_xplat.mixins.json b/Xplat/src/main/resources/botania_xplat.mixins.json index db8a3f57e2..85b1a7b2fa 100644 --- a/Xplat/src/main/resources/botania_xplat.mixins.json +++ b/Xplat/src/main/resources/botania_xplat.mixins.json @@ -37,6 +37,7 @@ "LoomMenuPatternSlotMixin", "LootTableMixin", "MobAccessor", + "MobMixin", "MushroomCowAccessor", "NaturalSpawnerMixin", "NearestAttackableTargetGoalAccessor", From a1eee67607a1d6119dc1060c90922afe4c0121c0 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Mon, 13 May 2024 18:41:27 +0200 Subject: [PATCH 13/26] Fix structure configuration lookup --- .../a864b94d006aba05700c96ad7a5769c8571473bc | 16 +++---- .../config/loonium}/ocean_ruin_cold.json | 0 .../config/loonium}/ocean_ruin_warm.json | 0 .../config/loonium}/pillager_outpost.json | 0 .../config/loonium}/village_desert.json | 0 .../config/loonium}/village_plains.json | 0 .../config/loonium}/village_savanna.json | 0 .../config/loonium}/village_snowy.json | 0 .../config/loonium}/village_taiga.json | 0 .../LooniumStructureConfiguration.java | 42 +++++++++++++++++++ .../flower/functional/LooniumBlockEntity.java | 28 +++++++++---- ...LooniumStructureConfigurationProvider.java | 18 ++++---- 12 files changed, 77 insertions(+), 27 deletions(-) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/ocean_ruin_cold.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/ocean_ruin_warm.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/pillager_outpost.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/village_desert.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/village_plains.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/village_savanna.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/village_snowy.json (100%) rename Xplat/src/generated/resources/data/{botania/config/loonium/minecraft => minecraft/config/loonium}/village_taiga.json (100%) diff --git a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc index 4ffed6e614..6d20481ae5 100644 --- a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc +++ b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc @@ -1,10 +1,10 @@ // 1.20.1 Botania/Loonium structure configuration f27da6c6a0976510c1a8c2dc652b4d13eda750b3 data/botania/config/loonium/default.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_cold.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/ocean_ruin_warm.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/pillager_outpost.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_desert.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_plains.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_savanna.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_snowy.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/minecraft/village_taiga.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/ocean_ruin_cold.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/ocean_ruin_warm.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/pillager_outpost.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_desert.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_plains.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_savanna.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_snowy.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_taiga.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_cold.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/ocean_ruin_warm.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/pillager_outpost.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_desert.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_plains.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_savanna.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_snowy.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/minecraft/village_taiga.json rename to Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 3f09e5efdf..9bd0b7442c 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -115,6 +115,19 @@ public LooniumStructureConfiguration getEffectiveConfig( effectsToApply != null ? effectsToApply : parentConfig.effectsToApply); } + @Override + public String toString() { + return "LooniumStructureConfiguration{" + + "manaCost=" + manaCost + + ", maxNearbyMobs=" + maxNearbyMobs + + ", boundingBoxType=" + boundingBoxType + + ", spawnedMobs=" + (spawnedMobs != null ? spawnedMobs.unwrap() : null) + + ", attributeModifiers=" + attributeModifiers + + ", effectsToApply=" + effectsToApply + + ", parent=" + parent + + '}'; + } + public static class MobSpawnData extends WeightedEntry.IntrusiveBase { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( @@ -159,6 +172,16 @@ private MobSpawnData(EntityType type, Weight weight, Optional nb Optional> effectsToApply, Optional> attributeModifiers) { this(type, weight, effectsToApply.orElse(null), attributeModifiers.orElse(null), nbt.orElse(null)); } + + @Override + public String toString() { + return "MobSpawnData{" + + "type=" + type + + ", nbt=" + nbt + + ", effectsToApply=" + effectsToApply + + ", attributeModifiers=" + attributeModifiers + + '}'; + } } public static class MobAttributeModifier { @@ -205,6 +228,16 @@ private static AttributeModifier.Operation operationFromString(String operation) default -> throw new JsonSyntaxException("Unknown attribute modifier operation " + operation); }; } + + @Override + public String toString() { + return "MobAttributeModifier{" + + "name='" + name + '\'' + + ", attribute=" + attribute + + ", amount=" + amount + + ", operation=" + operation + + '}'; + } } public static class MobEffectToApply { @@ -255,5 +288,14 @@ private Optional getOptionalDuration() { private Optional getOptionalAmplifier() { return amplifier > 0 ? Optional.of(amplifier) : Optional.empty(); } + + @Override + public String toString() { + return "MobEffectToApply{" + + "effect=" + effect + + ", duration=" + duration + + ", amplifier=" + amplifier + + '}'; + } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 8bf2e273fa..aaa6e88c50 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -110,7 +110,7 @@ public void tickFlower() { var configData = BotaniaAPI.instance().getConfigData(); var structureConfigs = determineStructureConfigs(configData, detectedStructures); - var lootTables = determineLootTables(world, detectedStructures.keySet()); + var lootTables = determineLootTables(world, structureConfigs.keySet()); if (lootTables.isEmpty()) { return; @@ -244,6 +244,7 @@ private List> determineLootTables(ServerLevel Set structureIds) { var lootTables = new ArrayList>(); LootDataManager lootData = world.getServer().getLootData(); + Supplier defaultLootTableSupplier = Suppliers.memoize(() -> lootData.getLootTable(DEFAULT_LOOT_TABLE)); if (lootTableOverride != null) { LootTable lootTable = lootData.getLootTable(lootTableOverride); if (lootTable != LootTable.EMPTY) { @@ -251,19 +252,25 @@ private List> determineLootTables(ServerLevel } } else { for (var structureId : structureIds) { - var lootTableId = structureId.equals(LooniumStructureConfiguration.DEFAULT_CONFIG_ID) - ? DEFAULT_LOOT_TABLE - : prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); + if (structureId.equals(LooniumStructureConfiguration.DEFAULT_CONFIG_ID)) { + continue; + } + var lootTableId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); LootTable lootTable = lootData.getLootTable(lootTableId); if (lootTable != LootTable.EMPTY) { lootTables.add(Pair.of(structureId, lootTable)); + } else { + LootTable defaultLootTable = defaultLootTableSupplier.get(); + if (defaultLootTable != LootTable.EMPTY) { + lootTables.add(Pair.of(structureId, defaultLootTable)); + } } } } if (lootTables.isEmpty()) { - LootTable lootTable = lootData.getLootTable(DEFAULT_LOOT_TABLE); - if (lootTable != LootTable.EMPTY) { - lootTables.add(Pair.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, lootTable)); + LootTable defaultLootTable = defaultLootTableSupplier.get(); + if (defaultLootTable != LootTable.EMPTY) { + lootTables.add(Pair.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, defaultLootTable)); } } return lootTables; @@ -286,16 +293,19 @@ private Map determineStructureC overrideConfig != null ? overrideConfig : getDefaultConfig(configData)); } + var defaultConfig = getDefaultConfig(configData); var structureConfigs = new HashMap(); for (var structureEntry : structures.object2BooleanEntrySet()) { - var structureConfig = configData.getEffectiveLooniumStructureConfiguration(structureEntry.getKey()); + LooniumStructureConfiguration structureSpecificConfig = + configData.getEffectiveLooniumStructureConfiguration(structureEntry.getKey()); + var structureConfig = structureSpecificConfig != null ? structureSpecificConfig : defaultConfig; if (structureConfig != null && (structureEntry.getBooleanValue() || structureConfig.boundingBoxType == StructureSpawnOverride.BoundingBoxType.STRUCTURE)) { structureConfigs.put(structureEntry.getKey(), structureConfig); } } - structureConfigs.put(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, getDefaultConfig(configData)); + structureConfigs.put(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, defaultConfig); return structureConfigs; } diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index 275ff47e8d..8c4e8590a3 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -28,8 +28,6 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; -import static vazkii.botania.data.LooniumStructureLootProvider.getStructureId; - public class LooniumStructureConfigurationProvider implements DataProvider { private final PackOutput.PathProvider pathProvider; @@ -81,21 +79,21 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ) )); - configs.put(getStructureId(BuiltinStructures.OCEAN_RUIN_COLD), + configs.put(BuiltinStructures.OCEAN_RUIN_COLD.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.OCEAN_RUIN_WARM), + configs.put(BuiltinStructures.OCEAN_RUIN_WARM.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.PILLAGER_OUTPOST), + configs.put(BuiltinStructures.PILLAGER_OUTPOST.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.VILLAGE_DESERT), + configs.put(BuiltinStructures.VILLAGE_DESERT.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.VILLAGE_PLAINS), + configs.put(BuiltinStructures.VILLAGE_PLAINS.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.VILLAGE_SAVANNA), + configs.put(BuiltinStructures.VILLAGE_SAVANNA.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.VILLAGE_SNOWY), + configs.put(BuiltinStructures.VILLAGE_SNOWY.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); - configs.put(getStructureId(BuiltinStructures.VILLAGE_TAIGA), + configs.put(BuiltinStructures.VILLAGE_TAIGA.location(), new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); var output = new ArrayList>(configs.size()); From af99b6435d82aaa02a111ae5309c26dcdb2820cb Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Fri, 17 May 2024 21:37:03 +0200 Subject: [PATCH 14/26] Apply bonuses to additionally spawned Loonium mobs (such as skeletons from a spider jockey or chickens from a zombie jockey, provided they are in the spawned mobs list) --- .../flower/functional/LooniumBlockEntity.java | 91 +++++++++++++------ 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index aaa6e88c50..0b8a728409 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -29,6 +29,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; import net.minecraft.world.level.storage.loot.LootDataManager; @@ -135,16 +136,17 @@ public void tickFlower() { return; } - ItemStack stack = pickRandomLootItem(world, pickedLootTable); - if (stack.isEmpty()) { - return; - } - - spawnMob(world, pickedMobType, pickedConfig, stack); + spawnMob(world, pickedMobType, pickedConfig, pickedLootTable); } private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnData pickedMobType, - LooniumStructureConfiguration pickedConfig, ItemStack stack) { + LooniumStructureConfiguration pickedConfig, LootTable pickedLootTable) { + + ItemStack lootStack = pickRandomLootItem(world, pickedLootTable); + if (lootStack.isEmpty()) { + return; + } + int bound = RANGE * 2 + 1; int xp = getEffectivePos().getX() - RANGE + world.random.nextInt(bound); int yp = getEffectivePos().getY(); @@ -175,52 +177,81 @@ private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnD mob.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); mob.setDeltaMovement(Vec3.ZERO); - var attributeModifiers = pickedMobType.attributeModifiers != null - ? pickedMobType.attributeModifiers - : pickedConfig.attributeModifiers; - for (var attributeModifier : attributeModifiers) { - var attribute = mob.getAttribute(attributeModifier.attribute); - if (attribute != null) { - attribute.addPermanentModifier(attributeModifier.createAttributeModifier()); - if (attribute.getAttribute() == Attributes.MAX_HEALTH) { - mob.setHealth(mob.getMaxHealth()); - } - } - } - - var effectsToApply = pickedMobType.effectsToApply != null - ? pickedMobType.effectsToApply - : pickedConfig.effectsToApply; - for (var effectToApply : effectsToApply) { - mob.addEffect(effectToApply.createMobEffectInstance()); - } + applyAttributesAndEffects(pickedMobType, pickedConfig, mob); LooniumComponent looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(mob); if (looniumComponent != null) { - looniumComponent.setDrop(stack); + looniumComponent.setDrop(lootStack); looniumComponent.setSlowDespawn(true); } mob.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); // in case the mob spawned with a vehicle or passenger(s), ensure those don't drop unexpected loot mob.getRootVehicle().getPassengersAndSelf().forEach(e -> { - if (e != mob && e instanceof Mob otherMob) { + if (e instanceof Mob otherMob) { // prevent armor/weapon drops on player kill, also no nautilus shells from drowned: Arrays.stream(EquipmentSlot.values()).forEach(slot -> otherMob.setDropChance(slot, 0)); + if (e == mob) { + return; + } + + var mobType = pickedConfig.spawnedMobs.unwrap().stream() + .filter(mobSpawnData -> mobSpawnData.type.tryCast(otherMob) != null).findFirst(); + + ItemStack bonusLoot; + if (mobType.isPresent()) { + applyAttributesAndEffects(mobType.get(), pickedConfig, mob); + bonusLoot = pickRandomLootItem(world, pickedLootTable); + } else { + bonusLoot = ItemStack.EMPTY; + } + LooniumComponent otherLooniumComponent = XplatAbstractions.INSTANCE.looniumComponent(otherMob); if (otherLooniumComponent != null) { - otherLooniumComponent.setDropNothing(true); + otherLooniumComponent.setSlowDespawn(true); + if (bonusLoot.isEmpty()) { + otherLooniumComponent.setDropNothing(true); + } else { + otherLooniumComponent.setDrop(bonusLoot); + } } } }); - world.addFreshEntity(mob); + if (!world.tryAddFreshEntityWithPassengers(mob)) { + return; + } + mob.spawnAnim(); + world.gameEvent(mob, GameEvent.ENTITY_PLACE, mob.position()); addMana(-DEFAULT_COST); sync(); } + private static void applyAttributesAndEffects(LooniumStructureConfiguration.MobSpawnData mobSpawnData, + LooniumStructureConfiguration pickedConfig, Mob mob) { + var attributeModifiers = mobSpawnData.attributeModifiers != null + ? mobSpawnData.attributeModifiers + : pickedConfig.attributeModifiers; + for (var attributeModifier : attributeModifiers) { + var attribute = mob.getAttribute(attributeModifier.attribute); + if (attribute != null) { + attribute.addPermanentModifier(attributeModifier.createAttributeModifier()); + if (attribute.getAttribute() == Attributes.MAX_HEALTH) { + mob.setHealth(mob.getMaxHealth()); + } + } + } + + var effectsToApply = mobSpawnData.effectsToApply != null + ? mobSpawnData.effectsToApply + : pickedConfig.effectsToApply; + for (var effectToApply : effectsToApply) { + mob.addEffect(effectToApply.createMobEffectInstance()); + } + } + private int countNearbyMobs(ServerLevel world, LooniumStructureConfiguration pickedConfig) { var setOfMobTypes = pickedConfig.spawnedMobs.unwrap().stream().map(msd -> msd.type).collect(Collectors.toSet()); return world.getEntitiesOfClass(Mob.class, new AABB(getEffectivePos()).inflate(CHECK_RANGE), From df7ff329cce3f0a76399ccba0ba040c0c1ffcfeb Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sat, 18 May 2024 19:27:04 +0200 Subject: [PATCH 15/26] General Loonium structure config cleanup - move inner config classes to own files - add builders where appropriate - simplify optional field definitions in codecs where possible, and remove constructors with Optional arguments --- .../LooniumMobAttributeModifier.java | 67 +++++ .../configdata/LooniumMobEffectToApply.java | 108 ++++++++ .../api/configdata/LooniumMobSpawnData.java | 104 +++++++ .../LooniumStructureConfiguration.java | 259 +++++------------- .../flower/functional/LooniumBlockEntity.java | 28 +- ...LooniumStructureConfigurationProvider.java | 99 ++++--- 6 files changed, 423 insertions(+), 242 deletions(-) create mode 100644 Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobAttributeModifier.java create mode 100644 Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java create mode 100644 Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobAttributeModifier.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobAttributeModifier.java new file mode 100644 index 0000000000..51102f9d8c --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobAttributeModifier.java @@ -0,0 +1,67 @@ +package vazkii.botania.api.configdata; + +import com.google.gson.JsonSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; + +public class LooniumMobAttributeModifier { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Codec.STRING.fieldOf("name").forGetter(mam -> mam.name), + BuiltInRegistries.ATTRIBUTE.byNameCodec().fieldOf("attribute").forGetter(mam -> mam.attribute), + Codec.DOUBLE.fieldOf("amount").forGetter(mam -> mam.amount), + Codec.STRING.xmap(LooniumMobAttributeModifier::operationFromString, + LooniumMobAttributeModifier::operationToString) + .fieldOf("operation").forGetter(mam -> mam.operation) + ).apply(instance, LooniumMobAttributeModifier::new) + ); + + private final String name; + public final Attribute attribute; + private final double amount; + private final AttributeModifier.Operation operation; + + public LooniumMobAttributeModifier(String name, Attribute attribute, double amount, + AttributeModifier.Operation operation) { + this.name = name; + this.attribute = attribute; + this.amount = amount; + this.operation = operation; + } + + public AttributeModifier createAttributeModifier() { + return new AttributeModifier(name, amount, operation); + } + + private static String operationToString(AttributeModifier.Operation operation) { + return switch (operation) { + case ADDITION -> "addition"; + case MULTIPLY_BASE -> "multiply_base"; + case MULTIPLY_TOTAL -> "multiply_total"; + default -> throw new IllegalArgumentException("Unknown operation " + operation); + }; + } + + private static AttributeModifier.Operation operationFromString(String operation) { + return switch (operation) { + case "addition" -> AttributeModifier.Operation.ADDITION; + case "multiply_base" -> AttributeModifier.Operation.MULTIPLY_BASE; + case "multiply_total" -> AttributeModifier.Operation.MULTIPLY_TOTAL; + default -> throw new JsonSyntaxException("Unknown attribute modifier operation " + operation); + }; + } + + @Override + public String toString() { + return "MobAttributeModifier{" + + "name='" + name + '\'' + + ", attribute=" + attribute + + ", amount=" + amount + + ", operation=" + operation + + '}'; + } +} diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java new file mode 100644 index 0000000000..a9fb492b79 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java @@ -0,0 +1,108 @@ +package vazkii.botania.api.configdata; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class LooniumMobEffectToApply { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + BuiltInRegistries.MOB_EFFECT.byNameCodec().fieldOf("effect").forGetter(me -> me.effect), + ExtraCodecs.validate(Codec.INT, + duration -> duration > 0 + ? DataResult.success(duration) + : DataResult.error(() -> "Invalid effect duration")) + .optionalFieldOf("duration", MobEffectInstance.INFINITE_DURATION) + .forGetter(me -> me.duration), + Codec.intRange(0, 255).optionalFieldOf("amplifier", 0) + .forGetter(me -> me.amplifier) + ).apply(instance, LooniumMobEffectToApply::new) + ); + + private final MobEffect effect; + private final int duration; + private final int amplifier; + + private LooniumMobEffectToApply(MobEffect effect, int duration, int amplifier) { + this.effect = effect; + this.duration = duration; + this.amplifier = amplifier; + } + + public static Builder effect(MobEffect effect) { + return new Builder(effect); + } + + @NotNull + public MobEffectInstance createMobEffectInstance() { + return new MobEffectInstance(effect, duration, amplifier); + } + + @Override + public String toString() { + return "MobEffectToApply{" + + "effect=" + effect + + ", duration=" + duration + + ", amplifier=" + amplifier + + '}'; + } + + public MobEffect getEffect() { + return effect; + } + + public int getDuration() { + return duration; + } + + public int getAmplifier() { + return amplifier; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + return obj instanceof LooniumMobEffectToApply that && Objects.equals(this.effect, that.effect) + && this.duration == that.duration && this.amplifier == that.amplifier; + } + + @Override + public int hashCode() { + return Objects.hash(effect, duration, amplifier); + } + + public static class Builder { + private final MobEffect effect; + private int duration = MobEffectInstance.INFINITE_DURATION; + private int amplifier = 0; + + private Builder(MobEffect effect) { + this.effect = effect; + } + + public Builder duration(int duration) { + this.duration = duration; + return this; + } + + public Builder amplifier(int amplifier) { + this.amplifier = amplifier; + return this; + } + + public LooniumMobEffectToApply build() { + return new LooniumMobEffectToApply(effect, duration, amplifier); + } + } +} diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java new file mode 100644 index 0000000000..90cba08f3a --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java @@ -0,0 +1,104 @@ +package vazkii.botania.api.configdata; + +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.random.Weight; +import net.minecraft.util.random.WeightedEntry; +import net.minecraft.world.entity.EntityType; + +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +public class LooniumMobSpawnData extends WeightedEntry.IntrusiveBase { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("type").forGetter(o -> o.type), + Weight.CODEC.fieldOf("weight").forGetter(IntrusiveBase::getWeight), + CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(msd -> Optional.ofNullable(msd.nbt)), + Codec.list(LooniumMobEffectToApply.CODEC) + .optionalFieldOf("effectsToApply") + .forGetter(msd -> Optional.ofNullable(msd.effectsToApply)), + Codec.list(LooniumMobAttributeModifier.CODEC) + .optionalFieldOf("attributeModifiers") + .forGetter(msd -> Optional.ofNullable(msd.attributeModifiers)) + ).apply(instance, LooniumMobSpawnData::create) + ); + + public final EntityType type; + public final CompoundTag nbt; + public final List effectsToApply; + public final List attributeModifiers; + + private LooniumMobSpawnData(EntityType type, Weight weight, @Nullable CompoundTag nbt, + @Nullable List effectsToApply, + @Nullable List attributeModifiers) { + super(weight); + this.type = type; + this.nbt = nbt != null ? nbt.copy() : null; + this.effectsToApply = effectsToApply != null ? ImmutableList.copyOf(effectsToApply) : null; + this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; + } + + public static Builder entityWeight(EntityType type, int weight) { + return new Builder(type, weight); + } + + @Override + public String toString() { + return "MobSpawnData{" + + "type=" + type + + ", nbt=" + nbt + + ", effectsToApply=" + effectsToApply + + ", attributeModifiers=" + attributeModifiers + + '}'; + } + + // Codecs don't support setting null as intentional default value for optional fields, so we do this. + // (blame com.mojang.datafixers.util.Either::getLeft using Optional::of instead Optional.ofNullable) + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static LooniumMobSpawnData create(EntityType type, Weight weight, Optional nbt, + Optional> effectsToApply, + Optional> attributeModifiers) { + return new LooniumMobSpawnData(type, weight, nbt.orElse(null), + effectsToApply.orElse(null), attributeModifiers.orElse(null)); + } + + public static class Builder { + private final EntityType type; + private final int weight; + private @Nullable CompoundTag nbt; + private @Nullable List effectsToApply; + private @Nullable List attributeModifiers; + + private Builder(EntityType type, int weight) { + this.type = type; + this.weight = weight; + } + + public Builder setNbt(CompoundTag nbt) { + this.nbt = nbt; + return this; + } + + public Builder setEffectsToApply(List effectsToApply) { + this.effectsToApply = effectsToApply; + return this; + } + + public Builder setAttributeModifiers( + List attributeModifiers) { + this.attributeModifiers = attributeModifiers; + return this; + } + + public LooniumMobSpawnData build() { + return new LooniumMobSpawnData(type, Weight.of(weight), nbt, effectsToApply, attributeModifiers); + } + } +} diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 9bd0b7442c..6336fbbe6c 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -1,28 +1,15 @@ package vazkii.botania.api.configdata; import com.google.common.collect.ImmutableList; -import com.google.gson.JsonSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ExtraCodecs; -import net.minecraft.util.random.Weight; -import net.minecraft.util.random.WeightedEntry; import net.minecraft.util.random.WeightedRandomList; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - import vazkii.botania.api.BotaniaAPI; import java.util.List; @@ -39,15 +26,19 @@ public class LooniumStructureConfiguration { .forGetter(lsc -> Optional.ofNullable(lsc.manaCost)), ExtraCodecs.POSITIVE_INT.optionalFieldOf("maxNearbyMobs") .forGetter(lsc -> Optional.ofNullable(lsc.maxNearbyMobs)), - StructureSpawnOverride.BoundingBoxType.CODEC.optionalFieldOf("boundingBoxType") + StructureSpawnOverride.BoundingBoxType.CODEC + .optionalFieldOf("boundingBoxType") .forGetter(lsc -> Optional.ofNullable(lsc.boundingBoxType)), - WeightedRandomList.codec(MobSpawnData.CODEC).optionalFieldOf("spawnedMobs") + WeightedRandomList.codec(LooniumMobSpawnData.CODEC) + .optionalFieldOf("spawnedMobs") .forGetter(lsc -> Optional.ofNullable(lsc.spawnedMobs)), - Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") + Codec.list(LooniumMobAttributeModifier.CODEC) + .optionalFieldOf("attributeModifiers") .forGetter(lsc -> Optional.ofNullable(lsc.attributeModifiers)), - Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") + Codec.list(LooniumMobEffectToApply.CODEC) + .optionalFieldOf("effectsToApply") .forGetter(lsc -> Optional.ofNullable(lsc.effectsToApply)) - ).apply(instance, LooniumStructureConfiguration::new) + ).apply(instance, LooniumStructureConfiguration::create) ), lsc -> { if (lsc.parent == null && (lsc.manaCost == null || lsc.boundingBoxType == null || lsc.spawnedMobs == null)) { return DataResult.error(() -> "Mana cost, bounding box type, and spawned mobs must be specified if there is no parent configuration"); @@ -62,20 +53,14 @@ public class LooniumStructureConfiguration { public final Integer manaCost; public final Integer maxNearbyMobs; public final StructureSpawnOverride.BoundingBoxType boundingBoxType; - public final WeightedRandomList spawnedMobs; - public final List attributeModifiers; - public final List effectsToApply; + public final WeightedRandomList spawnedMobs; + public final List attributeModifiers; + public final List effectsToApply; public final ResourceLocation parent; - public LooniumStructureConfiguration(Integer manaCost, Integer maxNearbyMobs, StructureSpawnOverride.BoundingBoxType boundingBoxType, - WeightedRandomList spawnedMobs, List attributeModifiers, - List effectsToApply) { - this(null, manaCost, maxNearbyMobs, boundingBoxType, spawnedMobs, attributeModifiers, effectsToApply); - } - - public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer manaCost, @Nullable Integer maxNearbyMobs, - @Nullable StructureSpawnOverride.BoundingBoxType boundingBoxType, @Nullable WeightedRandomList spawnedMobs, - @Nullable List attributeModifiers, @Nullable List effectsToApply) { + private LooniumStructureConfiguration(ResourceLocation parent, Integer manaCost, Integer maxNearbyMobs, + StructureSpawnOverride.BoundingBoxType boundingBoxType, WeightedRandomList spawnedMobs, + List attributeModifiers, List effectsToApply) { this.manaCost = manaCost; this.maxNearbyMobs = maxNearbyMobs; this.spawnedMobs = spawnedMobs; @@ -85,19 +70,12 @@ public LooniumStructureConfiguration(ResourceLocation parent, @Nullable Integer this.parent = parent; } - private LooniumStructureConfiguration(Optional parent, Optional manaCost, - Optional maxNearbyMobs, - Optional boundingBoxType, - Optional> spawnedMobs, - Optional> attributeModifiers, - Optional> effectsToApply) { - this(parent.orElse(null), manaCost.orElse(null), maxNearbyMobs.orElse(null), boundingBoxType.orElse(null), - spawnedMobs.orElse(null), attributeModifiers.orElse(null), effectsToApply.orElse(null)); + public static Builder builder() { + return new Builder(); } - public LooniumStructureConfiguration(ResourceLocation parent, - StructureSpawnOverride.BoundingBoxType boundingBoxType) { - this(parent, null, null, boundingBoxType, null, null, null); + public static Builder forParent(ResourceLocation parent) { + return builder().parent(parent); } public LooniumStructureConfiguration getEffectiveConfig( @@ -107,7 +85,8 @@ public LooniumStructureConfiguration getEffectiveConfig( } var parentConfig = parentSupplier.apply(parent).getEffectiveConfig(parentSupplier); - return new LooniumStructureConfiguration(manaCost != null ? manaCost : parentConfig.manaCost, + return new LooniumStructureConfiguration(null, + manaCost != null ? manaCost : parentConfig.manaCost, maxNearbyMobs != null ? maxNearbyMobs : parentConfig.maxNearbyMobs, boundingBoxType != null ? boundingBoxType : parentConfig.boundingBoxType, spawnedMobs != null ? spawnedMobs : parentConfig.spawnedMobs, @@ -128,174 +107,70 @@ public String toString() { '}'; } - public static class MobSpawnData extends WeightedEntry.IntrusiveBase { - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance.group( - BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("type").forGetter(o -> o.type), - Weight.CODEC.fieldOf("weight").forGetter(IntrusiveBase::getWeight), - CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(o -> Optional.ofNullable(o.nbt)), - Codec.list(MobEffectToApply.CODEC).optionalFieldOf("effectsToApply") - .forGetter(o -> Optional.ofNullable(o.effectsToApply)), - Codec.list(MobAttributeModifier.CODEC).optionalFieldOf("attributeModifiers") - .forGetter(o -> Optional.ofNullable(o.attributeModifiers)) - ).apply(instance, MobSpawnData::new) - ); - - public final EntityType type; - public final CompoundTag nbt; - public final List effectsToApply; - public final List attributeModifiers; - - public MobSpawnData(EntityType type, int weight) { - this(type, weight, null); - } - - public MobSpawnData(EntityType type, int weight, @Nullable List effectsToApply) { - this(type, weight, effectsToApply, null, null); - } - - public MobSpawnData(EntityType type, int weight, @Nullable List effectsToApply, - @Nullable List attributeModifiers, @Nullable CompoundTag nbt) { - this(type, Weight.of(weight), effectsToApply, attributeModifiers, nbt); - } - - public MobSpawnData(EntityType type, Weight weight, @Nullable List effectsToApply, - @Nullable List attributeModifiers, @Nullable CompoundTag nbt) { - super(weight); - this.type = type; - this.nbt = nbt != null ? nbt.copy() : null; - this.effectsToApply = effectsToApply != null ? ImmutableList.copyOf(effectsToApply) : null; - this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; - } - - private MobSpawnData(EntityType type, Weight weight, Optional nbt, - Optional> effectsToApply, Optional> attributeModifiers) { - this(type, weight, effectsToApply.orElse(null), attributeModifiers.orElse(null), nbt.orElse(null)); - } - - @Override - public String toString() { - return "MobSpawnData{" + - "type=" + type + - ", nbt=" + nbt + - ", effectsToApply=" + effectsToApply + - ", attributeModifiers=" + attributeModifiers + - '}'; - } - } - - public static class MobAttributeModifier { - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance.group( - Codec.STRING.fieldOf("name").forGetter(o -> o.name), - BuiltInRegistries.ATTRIBUTE.byNameCodec().fieldOf("attribute").forGetter(o -> o.attribute), - Codec.DOUBLE.fieldOf("amount").forGetter(o -> o.amount), - Codec.STRING.xmap(MobAttributeModifier::operationFromString, MobAttributeModifier::operationToString) - .fieldOf("operation").forGetter(o -> o.operation) - ).apply(instance, MobAttributeModifier::new) - ); - - private final String name; - public final Attribute attribute; - private final double amount; - private final AttributeModifier.Operation operation; - - public MobAttributeModifier(String name, Attribute attribute, double amount, AttributeModifier.Operation operation) { - this.name = name; - this.attribute = attribute; - this.amount = amount; - this.operation = operation; - } - - public AttributeModifier createAttributeModifier() { - return new AttributeModifier(name, amount, operation); - } - - private static String operationToString(AttributeModifier.Operation operation) { - return switch (operation) { - case ADDITION -> "addition"; - case MULTIPLY_BASE -> "multiply_base"; - case MULTIPLY_TOTAL -> "multiply_total"; - default -> throw new IllegalArgumentException("Unknown operation " + operation); - }; - } - - private static AttributeModifier.Operation operationFromString(String operation) { - return switch (operation) { - case "addition" -> AttributeModifier.Operation.ADDITION; - case "multiply_base" -> AttributeModifier.Operation.MULTIPLY_BASE; - case "multiply_total" -> AttributeModifier.Operation.MULTIPLY_TOTAL; - default -> throw new JsonSyntaxException("Unknown attribute modifier operation " + operation); - }; - } - - @Override - public String toString() { - return "MobAttributeModifier{" + - "name='" + name + '\'' + - ", attribute=" + attribute + - ", amount=" + amount + - ", operation=" + operation + - '}'; - } + // Codecs don't support setting null as intentional default value for optional fields, so we do this. + // (blame com.mojang.datafixers.util.Either::getLeft using Optional::of instead Optional.ofNullable) + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static LooniumStructureConfiguration create(Optional parent, + Optional manaCost, Optional maxNearbyMobs, + Optional boundingBoxType, + Optional> spawnedMobs, + Optional> attributeModifiers, + Optional> effectsToApply) { + return new LooniumStructureConfiguration( + parent.orElse(null), manaCost.orElse(null), maxNearbyMobs.orElse(null), + boundingBoxType.orElse(null), spawnedMobs.orElse(null), + attributeModifiers.orElse(null), effectsToApply.orElse(null)); } - public static class MobEffectToApply { - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance.group( - BuiltInRegistries.MOB_EFFECT.byNameCodec().fieldOf("effect").forGetter(o -> o.effect), - ExtraCodecs.validate(Codec.INT, - duration -> duration > 0 - ? DataResult.success(duration) - : DataResult.error(() -> "Invalid effect duration")) - .optionalFieldOf("duration").forGetter(MobEffectToApply::getOptionalDuration), - Codec.intRange(0, 255) - .optionalFieldOf("amplifier").forGetter(MobEffectToApply::getOptionalAmplifier) - ).apply(instance, MobEffectToApply::new) - ); + public static class Builder { + private ResourceLocation parent; + private Integer manaCost; + private Integer maxNearbyMobs; + private StructureSpawnOverride.BoundingBoxType boundingBoxType; + private WeightedRandomList spawnedMobs; + private List attributeModifiers; + private List effectsToApply; - public final MobEffect effect; - public final int duration; - public final int amplifier; + private Builder() {} - public MobEffectToApply(MobEffect effect) { - this(effect, MobEffectInstance.INFINITE_DURATION); + private Builder parent(ResourceLocation parent) { + this.parent = parent; + return this; } - public MobEffectToApply(MobEffect effect, int duration) { - this(effect, duration, 0); + public Builder manaCost(Integer manaCost) { + this.manaCost = manaCost; + return this; } - public MobEffectToApply(MobEffect effect, int duration, int amplifier) { - this.effect = effect; - this.duration = duration; - this.amplifier = amplifier; + public Builder maxNearbyMobs(Integer maxNearbyMobs) { + this.maxNearbyMobs = maxNearbyMobs; + return this; } - private MobEffectToApply(MobEffect effect, Optional optionalDuration, Optional optionalAmplifier) { - this(effect, optionalDuration.orElse(MobEffectInstance.INFINITE_DURATION), optionalAmplifier.orElse(0)); + public Builder boundingBoxType(StructureSpawnOverride.BoundingBoxType boundingBoxType) { + this.boundingBoxType = boundingBoxType; + return this; } - @NotNull - public MobEffectInstance createMobEffectInstance() { - return new MobEffectInstance(effect, duration, amplifier); + public Builder spawnedMobs(LooniumMobSpawnData... spawnedMobs) { + this.spawnedMobs = WeightedRandomList.create(spawnedMobs); + return this; } - private Optional getOptionalDuration() { - return duration != MobEffectInstance.INFINITE_DURATION ? Optional.of(duration) : Optional.empty(); + public Builder attributeModifiers(LooniumMobAttributeModifier... attributeModifiers) { + this.attributeModifiers = List.of(attributeModifiers); + return this; } - private Optional getOptionalAmplifier() { - return amplifier > 0 ? Optional.of(amplifier) : Optional.empty(); + public Builder effectsToApply(LooniumMobEffectToApply... effectsToApply) { + this.effectsToApply = List.of(effectsToApply); + return this; } - @Override - public String toString() { - return "MobEffectToApply{" + - "effect=" + effect + - ", duration=" + duration + - ", amplifier=" + amplifier + - '}'; + public LooniumStructureConfiguration build() { + return new LooniumStructureConfiguration(parent, manaCost, maxNearbyMobs, boundingBoxType, spawnedMobs, + attributeModifiers, effectsToApply); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 0b8a728409..b9ef6bb6e4 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -21,7 +21,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.Difficulty; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; @@ -45,6 +44,8 @@ import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.block_entity.FunctionalFlowerBlockEntity; import vazkii.botania.api.block_entity.RadiusDescriptor; +import vazkii.botania.api.configdata.LooniumMobEffectToApply; +import vazkii.botania.api.configdata.LooniumMobSpawnData; import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.common.block.BotaniaFlowerBlocks; import vazkii.botania.common.config.ConfigDataManager; @@ -69,14 +70,19 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final String TAG_CONFIG_OVERRIDE = "configOverride"; public static final ResourceLocation DEFAULT_LOOT_TABLE = prefix("loonium/default"); private static final Supplier FALLBACK_CONFIG = - Suppliers.memoize(() -> new LooniumStructureConfiguration(DEFAULT_COST, DEFAULT_MAX_NEARBY_MOBS, - StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create(new LooniumStructureConfiguration.MobSpawnData(EntityType.ZOMBIE, 1)), - List.of(), List.of( - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION), - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE), - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.DAMAGE_RESISTANCE), - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.DAMAGE_BOOST)))); + Suppliers.memoize(() -> LooniumStructureConfiguration.builder() + .manaCost(DEFAULT_COST) + .maxNearbyMobs(DEFAULT_MAX_NEARBY_MOBS) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.PIECE) + .spawnedMobs(LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 1).build()) + .attributeModifiers() + .effectsToApply( + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build(), + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.DAMAGE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.DAMAGE_BOOST).build() + ) + .build()); @Nullable private ResourceLocation lootTableOverride; @@ -139,7 +145,7 @@ public void tickFlower() { spawnMob(world, pickedMobType, pickedConfig, pickedLootTable); } - private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnData pickedMobType, + private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, LooniumStructureConfiguration pickedConfig, LootTable pickedLootTable) { ItemStack lootStack = pickRandomLootItem(world, pickedLootTable); @@ -229,7 +235,7 @@ private void spawnMob(ServerLevel world, LooniumStructureConfiguration.MobSpawnD sync(); } - private static void applyAttributesAndEffects(LooniumStructureConfiguration.MobSpawnData mobSpawnData, + private static void applyAttributesAndEffects(LooniumMobSpawnData mobSpawnData, LooniumStructureConfiguration pickedConfig, Mob mob) { var attributeModifiers = mobSpawnData.attributeModifiers != null ? mobSpawnData.attributeModifiers diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index 8c4e8590a3..9127e8ec44 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -7,7 +7,6 @@ import net.minecraft.data.PackOutput; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.random.WeightedRandomList; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -18,6 +17,9 @@ import org.jetbrains.annotations.NotNull; import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.configdata.LooniumMobAttributeModifier; +import vazkii.botania.api.configdata.LooniumMobEffectToApply; +import vazkii.botania.api.configdata.LooniumMobSpawnData; import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; @@ -41,60 +43,64 @@ public LooniumStructureConfigurationProvider(PackOutput packOutput) { public CompletableFuture run(@NotNull CachedOutput cache) { Map configs = new HashMap<>(); - List effectsToApplyToCreepers = List.of( - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE, 100), - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION, 100) + List effectsToApplyToCreepers = List.of( + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build() ); - CompoundTag chargedCreeperNbt = new CompoundTag(); - chargedCreeperNbt.putBoolean("powered", true); ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; - configs.put(defaultConfigId, new LooniumStructureConfiguration( - LooniumBlockEntity.DEFAULT_COST, LooniumBlockEntity.DEFAULT_MAX_NEARBY_MOBS, - StructureSpawnOverride.BoundingBoxType.PIECE, - WeightedRandomList.create( + configs.put(defaultConfigId, LooniumStructureConfiguration.builder() + .manaCost(LooniumBlockEntity.DEFAULT_COST) + .maxNearbyMobs(LooniumBlockEntity.DEFAULT_MAX_NEARBY_MOBS) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.PIECE) + .spawnedMobs( // weights roughly based on original Loonium mob selection logic - new LooniumStructureConfiguration.MobSpawnData(EntityType.ENDERMAN, 40), - new LooniumStructureConfiguration.MobSpawnData(EntityType.CREEPER, 195, - effectsToApplyToCreepers), - new LooniumStructureConfiguration.MobSpawnData(EntityType.CREEPER, 1, - effectsToApplyToCreepers, null, chargedCreeperNbt), - new LooniumStructureConfiguration.MobSpawnData(EntityType.HUSK, 59), - new LooniumStructureConfiguration.MobSpawnData(EntityType.DROWNED, 106), - new LooniumStructureConfiguration.MobSpawnData(EntityType.ZOMBIE, 423), - new LooniumStructureConfiguration.MobSpawnData(EntityType.STRAY, 59), - new LooniumStructureConfiguration.MobSpawnData(EntityType.SKELETON, 529), - new LooniumStructureConfiguration.MobSpawnData(EntityType.CAVE_SPIDER, 59), - new LooniumStructureConfiguration.MobSpawnData(EntityType.SPIDER, 529) - ), - List.of( - new LooniumStructureConfiguration.MobAttributeModifier("Loonium Modififer Health", + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(effectsToApplyToCreepers, 195, false), + getCreeperSpawnData(effectsToApplyToCreepers, 1, true), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 106).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ) + .attributeModifiers( + new LooniumMobAttributeModifier("Loonium Modififer Health", Attributes.MAX_HEALTH, 2, AttributeModifier.Operation.MULTIPLY_BASE), - new LooniumStructureConfiguration.MobAttributeModifier("Loonium Modififer Damage", + new LooniumMobAttributeModifier("Loonium Modififer Damage", Attributes.ATTACK_DAMAGE, 1.5, AttributeModifier.Operation.MULTIPLY_BASE) - ), - List.of( - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.FIRE_RESISTANCE), - new LooniumStructureConfiguration.MobEffectToApply(MobEffects.REGENERATION) + ).effectsToApply( + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build() ) - )); + .build()); configs.put(BuiltinStructures.OCEAN_RUIN_COLD.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.OCEAN_RUIN_WARM.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.PILLAGER_OUTPOST.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.VILLAGE_DESERT.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.VILLAGE_PLAINS.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.VILLAGE_SAVANNA.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.VILLAGE_SNOWY.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); configs.put(BuiltinStructures.VILLAGE_TAIGA.location(), - new LooniumStructureConfiguration(defaultConfigId, StructureSpawnOverride.BoundingBoxType.STRUCTURE)); + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); var output = new ArrayList>(configs.size()); for (var e : configs.entrySet()) { @@ -107,6 +113,21 @@ public CompletableFuture run(@NotNull CachedOutput cache) { return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } + private static LooniumMobSpawnData getCreeperSpawnData( + List effectsToApplyToCreepers, int weight, boolean charged) { + CompoundTag chargedCreeperNbt; + if (charged) { + chargedCreeperNbt = new CompoundTag(); + chargedCreeperNbt.putBoolean("powered", true); + } else { + chargedCreeperNbt = null; + } + + return LooniumMobSpawnData.entityWeight(EntityType.CREEPER, weight) + .setNbt(chargedCreeperNbt) + .setEffectsToApply(effectsToApplyToCreepers).build(); + } + @NotNull @Override public String getName() { From 6ed621b650b11be3d677a1d97adfe1fc1d56095a Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Mon, 20 May 2024 19:14:35 +0200 Subject: [PATCH 16/26] Add equipment table support to Loonium Equipment tables are not vanilla yet, so they currently use the "selector" loot table type and are applied manually by the Loonium. Nested loot table definitions also currently need to be loot table references, since embedded tables as pool entries are not supported by vanilla yet either. --- .../fabric/data/FabricDatagenInitializer.java | 1 + .../0bff84ccd1f015523369ae53dac0c4959dd87d86 | 98 ++ .../5e449fe289648869bd1f4d4d99715c8b4e0c057d | 2 + .../a864b94d006aba05700c96ad7a5769c8571473bc | 39 +- .../data/botania/config/loonium/default.json | 9 +- .../botania/config/loonium/ocean_ruins.json | 4 + .../data/botania/config/loonium/village.json | 4 + .../equipment/loonium/armor_ancient_city.json | 65 ++ .../loonium/armor_bastion_remnant.json | 20 + .../loonium/armor_desert_pyramid.json | 25 + .../equipment/loonium/armor_end_city.json | 66 ++ .../equipment/loonium/armor_fortress.json | 26 + .../loonium/armor_jungle_temple.json | 25 + .../equipment/loonium/armor_mansion.json | 66 ++ .../equipment/loonium/armor_monument.json | 25 + .../equipment/loonium/armor_outpost.json | 25 + .../equipment/loonium/armor_portal.json | 61 ++ .../equipment/loonium/armor_shipwreck.json | 25 + .../equipment/loonium/armor_stronghold.json | 30 + .../equipment/loonium/armor_trail_ruins.json | 51 + .../loonium/armorset/coast_chain.json | 85 ++ .../loonium/armorset/coast_diamond.json | 85 ++ .../loonium/armorset/coast_iron.json | 85 ++ .../loonium/armorset/costume_enderman.json | 69 ++ .../loonium/armorset/costume_evoker.json | 53 ++ .../loonium/armorset/costume_illusioner.json | 109 +++ .../loonium/armorset/costume_vex.json | 68 ++ .../loonium/armorset/costume_vindicator.json | 80 ++ .../loonium/armorset/dune_diamond.json | 85 ++ .../equipment/loonium/armorset/dune_gold.json | 85 ++ .../equipment/loonium/armorset/dune_iron.json | 85 ++ .../loonium/armorset/eye_diamond.json | 85 ++ .../equipment/loonium/armorset/eye_gold.json | 85 ++ .../equipment/loonium/armorset/eye_iron.json | 85 ++ .../loonium/armorset/host_chain.json | 85 ++ .../equipment/loonium/armorset/host_iron.json | 85 ++ .../loonium/armorset/raiser_gold.json | 85 ++ .../loonium/armorset/raiser_iron.json | 85 ++ .../loonium/armorset/rib_diamond.json | 85 ++ .../equipment/loonium/armorset/rib_gold.json | 85 ++ .../equipment/loonium/armorset/rib_iron.json | 85 ++ .../loonium/armorset/sentry_chain.json | 85 ++ .../loonium/armorset/sentry_diamond.json | 85 ++ .../loonium/armorset/sentry_iron.json | 85 ++ .../loonium/armorset/shaper_diamond.json | 85 ++ .../loonium/armorset/shaper_gold.json | 85 ++ .../loonium/armorset/silence_diamond.json | 85 ++ .../loonium/armorset/silence_gold.json | 85 ++ .../loonium/armorset/snout_gold.json | 85 ++ .../loonium/armorset/snout_netherite.json | 85 ++ .../loonium/armorset/spire_diamond.json | 85 ++ .../loonium/armorset/spire_gold.json | 85 ++ .../loonium/armorset/spire_iron.json | 85 ++ .../loonium/armorset/tide_diamond.json | 85 ++ .../equipment/loonium/armorset/tide_iron.json | 85 ++ .../loonium/armorset/tide_leather.json | 85 ++ .../loonium/armorset/ward_diamond.json | 85 ++ .../equipment/loonium/armorset/ward_iron.json | 85 ++ .../loonium/armorset/wayfinder_chain.json | 85 ++ .../loonium/armorset/wayfinder_diamond.json | 85 ++ .../loonium/armorset/wild_chain.json | 85 ++ .../loonium/armorset/wild_diamond.json | 85 ++ .../equipment/loonium/armorset/wild_gold.json | 85 ++ .../loonium/drowned_ancient_city.json | 25 + .../loonium/drowned_jungle_temple.json | 25 + .../equipment/loonium/drowned_monument.json | 25 + .../equipment/loonium/drowned_portal.json | 25 + .../equipment/loonium/drowned_shipwreck.json | 25 + .../equipment/loonium/drowned_stronghold.json | 25 + .../loonium/drowned_trail_ruins.json | 25 + .../loonium/piglin_bastion_remnant.json | 25 + .../loonium/piglin_ruined_portal.json | 25 + .../loonium/skeleton_ancient_city.json | 25 + .../loonium/skeleton_desert_pyramid.json | 25 + .../equipment/loonium/skeleton_end_city.json | 25 + .../equipment/loonium/skeleton_fortress.json | 25 + .../loonium/skeleton_jungle_temple.json | 25 + .../equipment/loonium/skeleton_monument.json | 25 + .../equipment/loonium/skeleton_outpost.json | 25 + .../equipment/loonium/skeleton_portal.json | 25 + .../equipment/loonium/skeleton_shipwreck.json | 25 + .../loonium/skeleton_stronghold.json | 25 + .../loonium/skeleton_trail_ruins.json | 25 + .../equipment/loonium/weapon_axe.json | 26 + .../equipment/loonium/weapon_axe_gold.json | 26 + .../equipment/loonium/weapon_bow.json | 26 + .../loonium/weapon_by_profession.json | 98 ++ .../equipment/loonium/weapon_crossbow.json | 20 + .../equipment/loonium/weapon_for_piglin.json | 30 + .../loonium/weapon_for_wither_skeleton.json | 28 + .../equipment/loonium/weapon_sword.json | 31 + .../equipment/loonium/weapon_sword_gold.json | 26 + .../equipment/loonium/weapon_trident.json | 15 + .../loonium/zombie_ancient_city.json | 25 + .../loonium/zombie_desert_pyramid.json | 25 + .../equipment/loonium/zombie_end_city.json | 25 + .../equipment/loonium/zombie_fortress.json | 25 + .../loonium/zombie_jungle_temple.json | 25 + .../equipment/loonium/zombie_monument.json | 25 + .../equipment/loonium/zombie_outpost.json | 25 + .../equipment/loonium/zombie_portal.json | 25 + .../equipment/loonium/zombie_shipwreck.json | 25 + .../equipment/loonium/zombie_stronghold.json | 25 + .../equipment/loonium/zombie_trail_ruins.json | 25 + .../tags/items/loonium_offhand_equipment.json | 8 + .../config/loonium/ancient_city.json | 73 ++ .../config/loonium/bastion_remnant.json | 90 ++ .../config/loonium/desert_pyramid.json | 63 ++ .../minecraft/config/loonium/end_city.json | 88 ++ .../minecraft/config/loonium/fortress.json | 74 ++ .../config/loonium/jungle_pyramid.json | 63 ++ .../minecraft/config/loonium/mansion.json | 78 ++ .../minecraft/config/loonium/monument.json | 96 ++ .../config/loonium/ocean_ruin_cold.json | 92 +- .../config/loonium/ocean_ruin_warm.json | 87 +- .../config/loonium/pillager_outpost.json | 67 +- .../config/loonium/ruined_portal.json | 114 +++ .../config/loonium/ruined_portal_desert.json | 100 ++ .../config/loonium/ruined_portal_jungle.json | 104 +++ .../loonium/ruined_portal_mountain.json | 104 +++ .../config/loonium/ruined_portal_nether.json | 98 ++ .../config/loonium/ruined_portal_ocean.json | 131 +++ .../config/loonium/ruined_portal_swamp.json | 104 +++ .../minecraft/config/loonium/shipwreck.json | 92 ++ .../config/loonium/shipwreck_beached.json | 3 + .../minecraft/config/loonium/stronghold.json | 77 ++ .../minecraft/config/loonium/trail_ruins.json | 73 ++ .../config/loonium/village_desert.json | 68 +- .../config/loonium/village_plains.json | 68 +- .../config/loonium/village_savanna.json | 73 +- .../config/loonium/village_snowy.json | 73 +- .../config/loonium/village_taiga.json | 73 +- .../data/minecraft/tags/items/arrows.json | 4 + .../api/configdata/LooniumMobSpawnData.java | 81 +- .../flower/functional/LooniumBlockEntity.java | 51 +- .../common/config/ConfigDataManager.java | 5 +- .../botania/common/lib/BotaniaTags.java | 5 + .../common/loot/BotaniaLootTables.java | 153 +++ .../vazkii/botania/data/ItemTagProvider.java | 9 +- .../data/LooniumEquipmentLootProvider.java | 875 ++++++++++++++++++ ...LooniumStructureConfigurationProvider.java | 721 +++++++++++++-- 141 files changed, 9417 insertions(+), 98 deletions(-) create mode 100644 Xplat/src/generated/resources/.cache/0bff84ccd1f015523369ae53dac0c4959dd87d86 create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/config/loonium/village.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_ancient_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_bastion_remnant.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_desert_pyramid.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_end_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_fortress.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_jungle_temple.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_mansion.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_monument.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_outpost.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_shipwreck.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_stronghold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_chain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_enderman.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_evoker.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_illusioner.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vex.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vindicator.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_chain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_chain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_netherite.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_leather.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_iron.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_chain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_chain.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_diamond.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_ancient_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_jungle_temple.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_monument.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_shipwreck.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_stronghold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_bastion_remnant.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_ruined_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_ancient_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_desert_pyramid.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_end_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_fortress.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_jungle_temple.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_monument.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_outpost.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_shipwreck.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_stronghold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_bow.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_by_profession.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_crossbow.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_piglin.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_wither_skeleton.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword_gold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_trident.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_ancient_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_desert_pyramid.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_end_city.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_fortress.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_jungle_temple.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_monument.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_outpost.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_portal.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_shipwreck.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_stronghold.json create mode 100644 Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/botania/tags/items/loonium_offhand_equipment.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json create mode 100644 Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json create mode 100644 Xplat/src/generated/resources/data/minecraft/tags/items/arrows.json create mode 100644 Xplat/src/main/java/vazkii/botania/common/loot/BotaniaLootTables.java create mode 100644 Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java diff --git a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java index f6b061d51c..37152ac047 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/data/FabricDatagenInitializer.java @@ -43,6 +43,7 @@ private static void configureXplatDatagen(FabricDataGenerator.Pack pack) { pack.addProvider((PackOutput output) -> new BlockLootProvider(output)); pack.addProvider((PackOutput output) -> new LooniumStructureLootProvider(output)); pack.addProvider((PackOutput output) -> new LooniumStructureConfigurationProvider(output)); + pack.addProvider(LooniumEquipmentLootProvider::new); BlockTagProvider blockTagProvider = pack.addProvider(BlockTagProvider::new); pack.addProvider((output, registriesFuture) -> new ItemTagProvider(output, registriesFuture, blockTagProvider.contentsGetter())); pack.addProvider(EntityTagProvider::new); diff --git a/Xplat/src/generated/resources/.cache/0bff84ccd1f015523369ae53dac0c4959dd87d86 b/Xplat/src/generated/resources/.cache/0bff84ccd1f015523369ae53dac0c4959dd87d86 new file mode 100644 index 0000000000..9f1bbe5e0e --- /dev/null +++ b/Xplat/src/generated/resources/.cache/0bff84ccd1f015523369ae53dac0c4959dd87d86 @@ -0,0 +1,98 @@ +// 1.20.1 Botania/Equipment tables for Loonium-spawned mobs +d2d97790090ee9148c5874dce5f8bb0bc0b91ddb data/botania/loot_tables/equipment/loonium/armor_ancient_city.json +c06c1a3ccc8ccb595950f08aaaa240868a681d85 data/botania/loot_tables/equipment/loonium/armor_bastion_remnant.json +197dfbd608b1f8761a35cde1bbfa4437dd396bce data/botania/loot_tables/equipment/loonium/armor_desert_pyramid.json +6c8f153b75966de1b47a89e66903c2733eeffcbc data/botania/loot_tables/equipment/loonium/armor_end_city.json +bbb294e3c587c6aadd91b6de179b16a55d2fc028 data/botania/loot_tables/equipment/loonium/armor_fortress.json +61b88ad4c3ced50cdfc8de265f1bab35b284fed8 data/botania/loot_tables/equipment/loonium/armor_jungle_temple.json +9a7bda203fde78ed212f9f42e153c2db95f9bb71 data/botania/loot_tables/equipment/loonium/armor_mansion.json +9023c47b8e0f2b3ed4bd6ec94f7b63d5e7278019 data/botania/loot_tables/equipment/loonium/armor_monument.json +65fec1f91f060f890366e8dd81d2ae6fc6144c59 data/botania/loot_tables/equipment/loonium/armor_outpost.json +e6467391bc3b6aceb5f13a32c9a1aaa9f4d4b4c2 data/botania/loot_tables/equipment/loonium/armor_portal.json +155849b4490ff9fc0c7cb4645799732c9f2a39f7 data/botania/loot_tables/equipment/loonium/armor_shipwreck.json +1ac5abff926dc65dd07ea1a5b3be1b4eab1f7420 data/botania/loot_tables/equipment/loonium/armor_stronghold.json +1810ab86916bf719cde65837601444d108fd9ba1 data/botania/loot_tables/equipment/loonium/armor_trail_ruins.json +64cdf979d34f80cc152e6d2585534637a9c0ab6a data/botania/loot_tables/equipment/loonium/armorset/coast_chain.json +a4062156d86f0e3118c737aaa15824cf939a8a5e data/botania/loot_tables/equipment/loonium/armorset/coast_diamond.json +b83a0957eafaec881f3834d8f6a2f6ce914b0fb7 data/botania/loot_tables/equipment/loonium/armorset/coast_iron.json +8b6a06d644dd18c79cfaeed5490f66f802178587 data/botania/loot_tables/equipment/loonium/armorset/costume_enderman.json +dd22cdb3c94b865bd7ffb127b7477e1f53196326 data/botania/loot_tables/equipment/loonium/armorset/costume_evoker.json +49269b75243e761cf3ee3c73b7892af6fbe3f99c data/botania/loot_tables/equipment/loonium/armorset/costume_illusioner.json +2f9b423eefa13c866fb93010779f0c4ddc1711f8 data/botania/loot_tables/equipment/loonium/armorset/costume_vex.json +0b73cebe599a21c8a491fa7ce31f92005ab0a808 data/botania/loot_tables/equipment/loonium/armorset/costume_vindicator.json +62b4a0a5d7cc87fb78c720381f50de85e2b25171 data/botania/loot_tables/equipment/loonium/armorset/dune_diamond.json +dee03b0097233fc14f47b00ea1ebff71ae73ea76 data/botania/loot_tables/equipment/loonium/armorset/dune_gold.json +7f51db8be2857081c5cb79ccd5f375322f4385b1 data/botania/loot_tables/equipment/loonium/armorset/dune_iron.json +1e380cf2ea44d74cee496df10cd3c9f86d304ea9 data/botania/loot_tables/equipment/loonium/armorset/eye_diamond.json +c33f9878395c5eab27c766d5be2ad1fc955b8fe7 data/botania/loot_tables/equipment/loonium/armorset/eye_gold.json +df0c65c5d6474d8218b94a2ed72667fff2a84f7f data/botania/loot_tables/equipment/loonium/armorset/eye_iron.json +15d092165619316f80fc055b3f3510942ee18eea data/botania/loot_tables/equipment/loonium/armorset/host_chain.json +5d9368f62b40e31a20bdbc068fb2b70b64e1ad1f data/botania/loot_tables/equipment/loonium/armorset/host_iron.json +18ab8a1947d4ae5f3b9c80703c0d13ede5e1921e data/botania/loot_tables/equipment/loonium/armorset/raiser_gold.json +e875f62f9487282245deb2e514e37d25e4813fc9 data/botania/loot_tables/equipment/loonium/armorset/raiser_iron.json +0adceb4ce9482a45a45f2a3635be711053afc7d9 data/botania/loot_tables/equipment/loonium/armorset/rib_diamond.json +c3f9146437887c9ccee17946ea5772d484fac428 data/botania/loot_tables/equipment/loonium/armorset/rib_gold.json +79f8602bab188cf2eaba5cebb1b5be576bfb78de data/botania/loot_tables/equipment/loonium/armorset/rib_iron.json +fababc8d774bfe1b0abd36d99e92eb1f633fbfbe data/botania/loot_tables/equipment/loonium/armorset/sentry_chain.json +ecf25cd2a32504cc0c25cc2fdf5773e1dde080af data/botania/loot_tables/equipment/loonium/armorset/sentry_diamond.json +1ee7e387838d153a9ce73302317b250273ff72c3 data/botania/loot_tables/equipment/loonium/armorset/sentry_iron.json +afe5bfe4c03564793ca4d1bc581b7c1cbf2c3a92 data/botania/loot_tables/equipment/loonium/armorset/shaper_diamond.json +4547c759f5bb824ed5ab072dcd39020e4fef638c data/botania/loot_tables/equipment/loonium/armorset/shaper_gold.json +d8b9f63fca55aced8f4497377837c659260fdbde data/botania/loot_tables/equipment/loonium/armorset/silence_diamond.json +832dc70e8af71f3a9a6a20bf4c03e57b44891f58 data/botania/loot_tables/equipment/loonium/armorset/silence_gold.json +d03310c712e1a18fbb055e7ec289c99ed06968d7 data/botania/loot_tables/equipment/loonium/armorset/snout_gold.json +fb17211351d534ae8b7d12ee98bbacc0f065ebd1 data/botania/loot_tables/equipment/loonium/armorset/snout_netherite.json +5612788810c9ee76e6cce41c3d2b68926f2ff09a data/botania/loot_tables/equipment/loonium/armorset/spire_diamond.json +49e343184818d17a75963a03eaf4e4585b188bbe data/botania/loot_tables/equipment/loonium/armorset/spire_gold.json +a07226b2c4d4e16dc8d221d6fd6ed53be17f8f33 data/botania/loot_tables/equipment/loonium/armorset/spire_iron.json +1b27407aabdcace073f95a9265ee45aa907b0a55 data/botania/loot_tables/equipment/loonium/armorset/tide_diamond.json +2f6727f2daab0cdcee6ec0931b0e5b9570661e3b data/botania/loot_tables/equipment/loonium/armorset/tide_iron.json +64d88957468cce4f80014cbaf001dd0fe45d463c data/botania/loot_tables/equipment/loonium/armorset/tide_leather.json +27b2e51aec7626ef3085861c959e6cd403ac8f94 data/botania/loot_tables/equipment/loonium/armorset/ward_diamond.json +82d0147c20406301841b5e240561f34040d3fc4f data/botania/loot_tables/equipment/loonium/armorset/ward_iron.json +09c583a95c65f194f157e2874f01acd866cb2e5a data/botania/loot_tables/equipment/loonium/armorset/wayfinder_chain.json +f693f82e1b419579aff3ddb356f8056d0eea045b data/botania/loot_tables/equipment/loonium/armorset/wayfinder_diamond.json +8b5869d12a3dfe73f018c49f095d46059782541b data/botania/loot_tables/equipment/loonium/armorset/wild_chain.json +7ef875de72ebba47568ae592a229dc0dc9d89167 data/botania/loot_tables/equipment/loonium/armorset/wild_diamond.json +226283d2a875bcf4aa7d75f2ebefc0a19fb24c5f data/botania/loot_tables/equipment/loonium/armorset/wild_gold.json +acb3558a9e9a8f4ce94e519f21e7a2bbd8dc6b31 data/botania/loot_tables/equipment/loonium/drowned_ancient_city.json +453432d6efe4299f9f4d18407e3b0a3c91acb276 data/botania/loot_tables/equipment/loonium/drowned_jungle_temple.json +0d974a59acf32a6d5183c80433f259837245e2f4 data/botania/loot_tables/equipment/loonium/drowned_monument.json +ee8aaeda7c9149a5003985e912973d1f4e0229d2 data/botania/loot_tables/equipment/loonium/drowned_portal.json +d94ec76d440f4374d17a547b31958489e69c25b0 data/botania/loot_tables/equipment/loonium/drowned_shipwreck.json +615ae2e7ef1919aeacdf40c5fe5f74e073f1524a data/botania/loot_tables/equipment/loonium/drowned_stronghold.json +3d268d995222e434cee429c935283cef479981a0 data/botania/loot_tables/equipment/loonium/drowned_trail_ruins.json +4c1dfb801ba21ceb2d95f6c7e8c7315eb2de276b data/botania/loot_tables/equipment/loonium/piglin_bastion_remnant.json +0fa752f016f96a8f070139520a01328416d62d3e data/botania/loot_tables/equipment/loonium/piglin_ruined_portal.json +4529a571d5d8b1e99ec82af3570eb649f1e027de data/botania/loot_tables/equipment/loonium/skeleton_ancient_city.json +f8d26c1eb15f9b523ee319f568da517a9ac42b77 data/botania/loot_tables/equipment/loonium/skeleton_desert_pyramid.json +98dde3ae66e2f769a08f77c6386f958e32c39d6e data/botania/loot_tables/equipment/loonium/skeleton_end_city.json +ac43d8215ae8ba53c8e36112f2cf540c4511d65e data/botania/loot_tables/equipment/loonium/skeleton_fortress.json +cb528917009d86e7f9a9390efd8722973233794d data/botania/loot_tables/equipment/loonium/skeleton_jungle_temple.json +3b3f04d1200b9d1dcfb406e0b24d4c0841deb3e7 data/botania/loot_tables/equipment/loonium/skeleton_monument.json +d1e4b4a1449f7fb32b006d3a366c4e3aa0e15413 data/botania/loot_tables/equipment/loonium/skeleton_outpost.json +aec2bfd13e0225e5b97caa4500cf5cdb82b2c33c data/botania/loot_tables/equipment/loonium/skeleton_portal.json +467fb3ddf9b00ca142b5cd36e64a3f836dbdf991 data/botania/loot_tables/equipment/loonium/skeleton_shipwreck.json +9a9522f614252c7f1ffc5c8a91688058c873b245 data/botania/loot_tables/equipment/loonium/skeleton_stronghold.json +da68cba7311b0491de3292f9839286b811978cde data/botania/loot_tables/equipment/loonium/skeleton_trail_ruins.json +4d90fc75701ca64b3dc1ca113a3241332c12dacd data/botania/loot_tables/equipment/loonium/weapon_axe.json +b0a054e7a5c5061d8f158c69c09736f1da96a6f8 data/botania/loot_tables/equipment/loonium/weapon_axe_gold.json +5fc5c5781d1b13e8120753688284c6bef1be5aef data/botania/loot_tables/equipment/loonium/weapon_bow.json +c197fd5bcbed8d185e3dafefb2829015a28ae6f6 data/botania/loot_tables/equipment/loonium/weapon_by_profession.json +810e9e9e3d1bdf67f5ae69d88702f8d264ab0598 data/botania/loot_tables/equipment/loonium/weapon_crossbow.json +5f44d78700ec5dc02bac5e8e2ae5eee455f9c232 data/botania/loot_tables/equipment/loonium/weapon_for_piglin.json +2b754c2dbecebb9fe890984c40cc2c54293ad6de data/botania/loot_tables/equipment/loonium/weapon_for_wither_skeleton.json +1d16d90dc387940cb4c26a2a9473fb3370284687 data/botania/loot_tables/equipment/loonium/weapon_sword.json +c769e1a46ce3e1684bf520099eb62365ae07ae07 data/botania/loot_tables/equipment/loonium/weapon_sword_gold.json +2777fc3f1cc95e99d1220d6e8cb8d06b4d4abdd9 data/botania/loot_tables/equipment/loonium/weapon_trident.json +c5eb14b815137526d5afebffc6101e75a02f7ee4 data/botania/loot_tables/equipment/loonium/zombie_ancient_city.json +818ba2505d70ec63d0dad65f007fa31ecbbbd4bc data/botania/loot_tables/equipment/loonium/zombie_desert_pyramid.json +7da85f3c4060eb361de9d73a7c3f659cef163d9c data/botania/loot_tables/equipment/loonium/zombie_end_city.json +360712cf81439555f12c31903a2c3a06ab429c5a data/botania/loot_tables/equipment/loonium/zombie_fortress.json +7208b89dfe549972a83afc30c7ac7f18f1c08ef7 data/botania/loot_tables/equipment/loonium/zombie_jungle_temple.json +c00bae89ae9f9c64e55a093353d7bb00325e93ef data/botania/loot_tables/equipment/loonium/zombie_monument.json +a496021cf9683d471e481564402e20321d105f7b data/botania/loot_tables/equipment/loonium/zombie_outpost.json +e2c191759bb9573543348c294b61205492cadfa9 data/botania/loot_tables/equipment/loonium/zombie_portal.json +f7df591afa16e5b8e2894486a4bfe78dd88a155f data/botania/loot_tables/equipment/loonium/zombie_shipwreck.json +3e34705ca4212a71301e911e38716aa28a84fe96 data/botania/loot_tables/equipment/loonium/zombie_stronghold.json +cf5952b919dcadc0ae2974fec273e9161a036df1 data/botania/loot_tables/equipment/loonium/zombie_trail_ruins.json diff --git a/Xplat/src/generated/resources/.cache/5e449fe289648869bd1f4d4d99715c8b4e0c057d b/Xplat/src/generated/resources/.cache/5e449fe289648869bd1f4d4d99715c8b4e0c057d index 2d2993363f..54f52a6c65 100644 --- a/Xplat/src/generated/resources/.cache/5e449fe289648869bd1f4d4d99715c8b4e0c057d +++ b/Xplat/src/generated/resources/.cache/5e449fe289648869bd1f4d4d99715c8b4e0c057d @@ -17,6 +17,7 @@ ac3888e68025d31c8c109b225689e7d69ad7f603 data/botania/tags/items/lens.json dfbc18cbf412594282532933002d270b34b3f16f data/botania/tags/items/lens_glue.json bbb827430199d1a6f3b27fc25e2df941f22dc660 data/botania/tags/items/livingwood_logs.json 0f00c4dbb7edb499acbc720f3191a146183c01e7 data/botania/tags/items/loonium_blacklist.json +80976d0e035f6163de9d5c190a3061a5fb95591f data/botania/tags/items/loonium_offhand_equipment.json 8a23702b05296c8af5014d6aa6e9265ded85c7d9 data/botania/tags/items/magnet_ring_blacklist.json bebd5a92d011c3a431c16f368557850a1e108530 data/botania/tags/items/mana_diamond_gems.json 6cf780dc321928fdae9feeacae1c6689c815f40e data/botania/tags/items/mana_dusts.json @@ -55,6 +56,7 @@ f01c4f9608fc5e20c33e12d6862b6d8cee41cdd0 data/botania/tags/items/semi_disposable 2ead7838be1f063018e6e13e8300f3a183adf5f5 data/botania/tags/items/terrasteel_blocks.json 70a32077a4c06e2fc3ed8783037d4b6c659216be data/botania/tags/items/terrasteel_ingots.json de5556cc02036175ac731ce76827076c6b834d25 data/botania/tags/items/terrasteel_nuggets.json +8a23702b05296c8af5014d6aa6e9265ded85c7d9 data/minecraft/tags/items/arrows.json 43bfa13de3ebc0be372fc48b0e4be56a25cb1893 data/minecraft/tags/items/axes.json 65c35efa8dfbdc9f5a8c05624c492fba8408e3b2 data/minecraft/tags/items/bookshelf_books.json a101ef4ecfece48f1cdff62f34f30f9f25b3dbd3 data/minecraft/tags/items/cluster_max_harvestables.json diff --git a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc index 6d20481ae5..6bd4302a99 100644 --- a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc +++ b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc @@ -1,10 +1,31 @@ // 1.20.1 Botania/Loonium structure configuration -f27da6c6a0976510c1a8c2dc652b4d13eda750b3 data/botania/config/loonium/default.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/ocean_ruin_cold.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/ocean_ruin_warm.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/pillager_outpost.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_desert.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_plains.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_savanna.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_snowy.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/minecraft/config/loonium/village_taiga.json +0591cbe7698291e5638b866f3d85e70f58d1a344 data/botania/config/loonium/default.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/ocean_ruins.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/village.json +0c933b1278b153f59c7f189d7d6915c489340893 data/minecraft/config/loonium/ancient_city.json +4baa8c3fc3b3ad342326f1e207e6897ece6a04de data/minecraft/config/loonium/bastion_remnant.json +80b2e51b7d57879bf73aad1b23264032080e8e22 data/minecraft/config/loonium/desert_pyramid.json +0cabae7ec03b982c21a592f0924beb7a3700c59d data/minecraft/config/loonium/end_city.json +81aa1d20a8a656b5110984587367368c7206cfb7 data/minecraft/config/loonium/fortress.json +180b4009f85a3b534c8f55aafc6d5ec3cd2125b6 data/minecraft/config/loonium/jungle_pyramid.json +189f42c5d0b89c43e618e55b6cedd0f01c5fb00c data/minecraft/config/loonium/mansion.json +7bf132334dfc93b6c0a9d74bd4896782819fa3ee data/minecraft/config/loonium/monument.json +7bf474c5eca6f6cf63799e5d1e518dd81b39943c data/minecraft/config/loonium/ocean_ruin_cold.json +70760f4da963f17c462e0e264652776c74d7d178 data/minecraft/config/loonium/ocean_ruin_warm.json +690d302eb1c171f1caaf63d52275fc82b9c40431 data/minecraft/config/loonium/pillager_outpost.json +72a5b2a5af2bb9966f0ac15d00a2fa69e21aa7fc data/minecraft/config/loonium/ruined_portal.json +eaf7c2c1520cf16bb06ca9e6c1e76f32b1571fe2 data/minecraft/config/loonium/ruined_portal_desert.json +17dedb198a79feb28465164299f9e161d0621f72 data/minecraft/config/loonium/ruined_portal_jungle.json +77a93510dc75fe179568fe08cac9848965a7abf2 data/minecraft/config/loonium/ruined_portal_mountain.json +07a632775753dee383465d74d594775b22d68058 data/minecraft/config/loonium/ruined_portal_nether.json +a46cb70ba9a2ea3425f281ac56bdead53b4d121e data/minecraft/config/loonium/ruined_portal_ocean.json +6d6bec7132a26f85357c6c214edd3b3fb4f1e439 data/minecraft/config/loonium/ruined_portal_swamp.json +e07b347d00f8046a129aaa6c370d09051b5b64ec data/minecraft/config/loonium/shipwreck.json +69b7be4e05054ffe7d73ea4625581012af333cf2 data/minecraft/config/loonium/shipwreck_beached.json +daec043e2fd1892c030e279a01f03b36bec78545 data/minecraft/config/loonium/stronghold.json +884bcffda3cef17de3b826764761bf17923cc3a2 data/minecraft/config/loonium/trail_ruins.json +ca49a5ff59f404e97c78004a75404c335ff30385 data/minecraft/config/loonium/village_desert.json +c9e527140f4f775a3dd58af3acdd898b6e504991 data/minecraft/config/loonium/village_plains.json +8ccd5ddf38ead3ad53cc1b5a9f4780adee02cad0 data/minecraft/config/loonium/village_savanna.json +437d9a154644a9e62df0eab1fc07d86dbaf98b82 data/minecraft/config/loonium/village_snowy.json +c4562050c8a5429cb383144e9e57f5267387dbba data/minecraft/config/loonium/village_taiga.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/default.json b/Xplat/src/generated/resources/data/botania/config/loonium/default.json index ca82aa1736..7fa38c2fa3 100644 --- a/Xplat/src/generated/resources/data/botania/config/loonium/default.json +++ b/Xplat/src/generated/resources/data/botania/config/loonium/default.json @@ -3,13 +3,13 @@ { "amount": 2.0, "attribute": "minecraft:generic.max_health", - "name": "Loonium Modififer Health", + "name": "Loonium Modifier Health", "operation": "multiply_base" }, { "amount": 1.5, "attribute": "minecraft:generic.attack_damage", - "name": "Loonium Modififer Damage", + "name": "Loonium Modifier Damage", "operation": "multiply_base" } ], @@ -62,22 +62,27 @@ }, { "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/weapon_sword", "weight": 59 }, { "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", "weight": 106 }, { "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", "weight": 423 }, { "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/weapon_bow", "weight": 59 }, { "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", "weight": 529 }, { diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json b/Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/village.json b/Xplat/src/generated/resources/data/botania/config/loonium/village.json new file mode 100644 index 0000000000..2d6c6ee5fb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/config/loonium/village.json @@ -0,0 +1,4 @@ +{ + "parent": "botania:default", + "boundingBoxType": "full" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_ancient_city.json new file mode 100644 index 0000000000..ae6fe46979 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_ancient_city.json @@ -0,0 +1,65 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/ward_iron", + "weight": 11 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/ward_diamond", + "weight": 5 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/silence_gold", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/silence_diamond" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "equipment": { + "mainhand": { + "items": [ + "minecraft:bow" + ] + } + } + } + }, + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{CustomPotionColor:2696993,CustomPotionEffects:[{Ambient:0b,Amplifier:0b,Duration:200,FactorCalculationData:{factor_current:0.0f,factor_previous_frame:0.0f,factor_start:0.0f,factor_target:1.0f,had_effect_last_tick:0b,padding_duration:22,ticks_active:0},Id:33,ShowIcon:1b,ShowParticles:1b}]}" + } + ], + "name": "minecraft:tipped_arrow" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_bastion_remnant.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_bastion_remnant.json new file mode 100644 index 0000000000..864d5edad7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_bastion_remnant.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/snout_gold", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/snout_netherite" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_desert_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_desert_pyramid.json new file mode 100644 index 0000000000..3e441989c9 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_desert_pyramid.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/dune_iron", + "weight": 5 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/dune_gold", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/dune_diamond" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_end_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_end_city.json new file mode 100644 index 0000000000..935f6c149c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_end_city.json @@ -0,0 +1,66 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/spire_iron", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/spire_gold", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/spire_diamond", + "weight": 2 + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:skeleton" + } + }, + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{CustomPotionColor:13565951,CustomPotionEffects:[{Ambient:0b,Amplifier:0b,Duration:200,Id:25,ShowIcon:1b,ShowParticles:1b}]}" + } + ], + "name": "minecraft:tipped_arrow" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_fortress.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_fortress.json new file mode 100644 index 0000000000..d23393452b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_fortress.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/rib_iron", + "weight": 7 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/rib_gold", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/rib_diamond", + "weight": 2 + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_jungle_temple.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_jungle_temple.json new file mode 100644 index 0000000000..5e72cb06cf --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_jungle_temple.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/wild_chain", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/wild_gold", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/wild_diamond" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_mansion.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_mansion.json new file mode 100644 index 0000000000..ffb316cc30 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_mansion.json @@ -0,0 +1,66 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/costume_evoker", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/costume_vindicator", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/costume_illusioner" + }, + { + "type": "minecraft:loot_table", + "conditions": [ + { + "condition": "minecraft:any_of", + "terms": [ + { + "chance": 0.005, + "condition": "minecraft:random_chance" + }, + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "flags": { + "is_baby": true + } + } + } + ] + } + ], + "name": "botania:equipment/loonium/armorset/costume_vex", + "weight": 45 + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "chance": 0.05, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:totem_of_undying" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_monument.json new file mode 100644 index 0000000000..2dd7ef3d01 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_monument.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/tide_leather", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/tide_iron", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/tide_diamond" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_outpost.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_outpost.json new file mode 100644 index 0000000000..8438e47782 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_outpost.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/sentry_chain", + "weight": 5 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/sentry_iron", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/sentry_diamond" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_portal.json new file mode 100644 index 0000000000..dfc4534f4c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_portal.json @@ -0,0 +1,61 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_shipwreck.json new file mode 100644 index 0000000000..b4252eacc8 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_shipwreck.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/coast_chain", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/coast_iron", + "weight": 4 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/coast_diamond" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_stronghold.json new file mode 100644 index 0000000000..40144be68a --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_stronghold.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/eye_iron", + "weight": 5 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/eye_gold", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/eye_diamond", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/costume_enderman" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_trail_ruins.json new file mode 100644 index 0000000000..1cc7f80eeb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armor_trail_ruins.json @@ -0,0 +1,51 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/host_chain", + "weight": 7 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/wayfinder_chain", + "weight": 7 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/raiser_iron", + "weight": 8 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/host_iron", + "weight": 8 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/raiser_gold", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/shaper_gold", + "weight": 3 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/shaper_diamond", + "weight": 2 + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armorset/wayfinder_diamond", + "weight": 2 + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_chain.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_chain.json new file mode 100644 index 0000000000..5d1755a24a --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_chain.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:chainmail_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:chainmail_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:chainmail_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:chainmail_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_diamond.json new file mode 100644 index 0000000000..6e43476813 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_iron.json new file mode 100644 index 0000000000..4cacb92ce7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/coast_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:coast\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_enderman.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_enderman.json new file mode 100644 index 0000000000..65b8f69675 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_enderman.json @@ -0,0 +1,69 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:eye\"},display:{color:1908001}}" + } + ], + "name": "minecraft:leather_helmet" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{display:{color:1908001}}" + } + ], + "name": "minecraft:leather_chestplate" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{display:{color:1908001}}" + } + ], + "name": "minecraft:leather_leggings" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{display:{color:1908001}}" + } + ], + "name": "minecraft:leather_boots" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_evoker.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_evoker.json new file mode 100644 index 0000000000..67848cd509 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_evoker.json @@ -0,0 +1,53 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:vex\"},display:{color:3290681}}" + } + ], + "name": "minecraft:leather_chestplate" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:vex\"},display:{color:3290681}}" + } + ], + "name": "minecraft:leather_leggings" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "chance": 0.2, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:totem_of_undying" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_illusioner.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_illusioner.json new file mode 100644 index 0000000000..5d8fffe322 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_illusioner.json @@ -0,0 +1,109 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:vex\"},display:{color:3898306}}" + } + ], + "name": "minecraft:leather_helmet" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:vex\"},display:{color:3898306}}" + } + ], + "name": "minecraft:leather_chestplate" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:vex\"},display:{color:3898306}}" + } + ], + "name": "minecraft:leather_leggings" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "name": "minecraft:bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:skeleton" + } + }, + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{CustomPotionColor:2039587,CustomPotionEffects:[{Ambient:0b,Amplifier:0b,Duration:100,Id:15,ShowIcon:1b,ShowParticles:1b}]}" + } + ], + "name": "minecraft:tipped_arrow" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vex.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vex.json new file mode 100644 index 0000000000..7e806cfd70 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vex.json @@ -0,0 +1,68 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:vex\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:diamond_leggings" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "name": "minecraft:iron_sword" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vindicator.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vindicator.json new file mode 100644 index 0000000000..1b82ec83ff --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/costume_vindicator.json @@ -0,0 +1,80 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:netherite\",pattern:\"minecraft:vex\"},display:{color:4673362}}" + } + ], + "name": "minecraft:leather_chestplate" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{display:{color:1477772}}" + } + ], + "name": "minecraft:leather_leggings" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{display:{color:3290681}}" + } + ], + "name": "minecraft:leather_boots" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "chance": 0.9, + "condition": "minecraft:random_chance" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "name": "minecraft:iron_axe" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_diamond.json new file mode 100644 index 0000000000..b2f603ae64 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_gold.json new file mode 100644 index 0000000000..7f66886fb4 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_iron.json new file mode 100644 index 0000000000..73c5d528d2 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/dune_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:dune\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_diamond.json new file mode 100644 index 0000000000..ff503d4ffc --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_gold.json new file mode 100644 index 0000000000..7c6be606e7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_iron.json new file mode 100644 index 0000000000..ee997b2029 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/eye_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:eye\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_chain.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_chain.json new file mode 100644 index 0000000000..49f0c22950 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_chain.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:chainmail_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:chainmail_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:chainmail_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:chainmail_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_iron.json new file mode 100644 index 0000000000..254856801d --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/host_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:host\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_gold.json new file mode 100644 index 0000000000..4827a0c952 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_iron.json new file mode 100644 index 0000000000..75f02c95f0 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/raiser_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:raiser\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_diamond.json new file mode 100644 index 0000000000..09e0bd13f6 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_gold.json new file mode 100644 index 0000000000..8e1c140b0c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_iron.json new file mode 100644 index 0000000000..53841d6200 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/rib_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:iron\",pattern:\"minecraft:rib\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_chain.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_chain.json new file mode 100644 index 0000000000..c980bd7607 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_chain.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:chainmail_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:chainmail_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:chainmail_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:chainmail_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_diamond.json new file mode 100644 index 0000000000..66aae08a09 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_iron.json new file mode 100644 index 0000000000..607c691ee6 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/sentry_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:sentry\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_diamond.json new file mode 100644 index 0000000000..bdcd86dc43 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_gold.json new file mode 100644 index 0000000000..cf52ce83da --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/shaper_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:lapis\",pattern:\"minecraft:shaper\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_diamond.json new file mode 100644 index 0000000000..a180eb0a3b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_gold.json new file mode 100644 index 0000000000..c964063859 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/silence_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:silence\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_gold.json new file mode 100644 index 0000000000..f65b894468 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:netherite\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:netherite\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:netherite\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:netherite\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_netherite.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_netherite.json new file mode 100644 index 0000000000..4f602652b2 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/snout_netherite.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:netherite_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:netherite_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:netherite_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:snout\"}}" + } + ], + "name": "minecraft:netherite_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_diamond.json new file mode 100644 index 0000000000..453bb72fe9 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_gold.json new file mode 100644 index 0000000000..623f614dcc --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_iron.json new file mode 100644 index 0000000000..7f0fa0cd28 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/spire_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:amethyst\",pattern:\"minecraft:spire\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_diamond.json new file mode 100644 index 0000000000..1a43efcc94 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:gold\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_iron.json new file mode 100644 index 0000000000..ad5e47954d --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:diamond\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:diamond\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:diamond\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:diamond\",pattern:\"minecraft:tide\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_leather.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_leather.json new file mode 100644 index 0000000000..7bca535a1b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/tide_leather.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:tide\"},display:{color:1481884}}" + } + ], + "name": "minecraft:leather_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:tide\"},display:{color:1481884}}" + } + ], + "name": "minecraft:leather_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:tide\"},display:{color:1481884}}" + } + ], + "name": "minecraft:leather_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:copper\",pattern:\"minecraft:tide\"},display:{color:1481884}}" + } + ], + "name": "minecraft:leather_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_diamond.json new file mode 100644 index 0000000000..29c15d7c28 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_iron.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_iron.json new file mode 100644 index 0000000000..96cf845419 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/ward_iron.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:iron_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:iron_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:iron_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:quartz\",pattern:\"minecraft:ward\"}}" + } + ], + "name": "minecraft:iron_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_chain.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_chain.json new file mode 100644 index 0000000000..23f9d7fba8 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_chain.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:chainmail_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:chainmail_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:chainmail_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:chainmail_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_diamond.json new file mode 100644 index 0000000000..9679924856 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wayfinder_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:redstone\",pattern:\"minecraft:wayfinder\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_chain.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_chain.json new file mode 100644 index 0000000000..3209b1a8d6 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_chain.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:chainmail_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:chainmail_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:chainmail_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:chainmail_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_diamond.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_diamond.json new file mode 100644 index 0000000000..ad3959eedb --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_diamond.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:diamond_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:diamond_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:diamond_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:diamond_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_gold.json new file mode 100644 index 0000000000..e426259cf7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/armorset/wild_gold.json @@ -0,0 +1,85 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:golden_helmet" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:golden_chestplate" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:golden_leggings" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:set_nbt", + "tag": "{Trim:{material:\"minecraft:emerald\",pattern:\"minecraft:wild\"}}" + } + ], + "name": "minecraft:golden_boots" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_ancient_city.json new file mode 100644 index 0000000000..020aea76e9 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_ancient_city.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_ancient_city" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_jungle_temple.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_jungle_temple.json new file mode 100644 index 0000000000..2d5398c1c1 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_jungle_temple.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_jungle_temple" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_monument.json new file mode 100644 index 0000000000..599209df6b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_monument.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_monument" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_portal.json new file mode 100644 index 0000000000..f2e65bc93e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_portal.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_portal" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_shipwreck.json new file mode 100644 index 0000000000..7aef99664a --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_shipwreck.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_shipwreck" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_stronghold.json new file mode 100644 index 0000000000..1de3f55f59 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_stronghold.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_stronghold" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_trail_ruins.json new file mode 100644 index 0000000000..ff146f049b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/drowned_trail_ruins.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_trident" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_trail_ruins" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_bastion_remnant.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_bastion_remnant.json new file mode 100644 index 0000000000..ba9e451dba --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_bastion_remnant.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_for_piglin" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_bastion_remnant" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_ruined_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_ruined_portal.json new file mode 100644 index 0000000000..0fd2cf390d --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/piglin_ruined_portal.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_portal" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_for_piglin" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_ancient_city.json new file mode 100644 index 0000000000..2f171d1229 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_ancient_city.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_ancient_city" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_desert_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_desert_pyramid.json new file mode 100644 index 0000000000..52c8e2c967 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_desert_pyramid.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_desert_pyramid" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_end_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_end_city.json new file mode 100644 index 0000000000..7e3b0b43d4 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_end_city.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_end_city" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_fortress.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_fortress.json new file mode 100644 index 0000000000..ebc788c2f6 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_fortress.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_for_wither_skeleton" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_fortress" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_jungle_temple.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_jungle_temple.json new file mode 100644 index 0000000000..a3cc20b317 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_jungle_temple.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_jungle_temple" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_monument.json new file mode 100644 index 0000000000..a6099e605c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_monument.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_monument" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_outpost.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_outpost.json new file mode 100644 index 0000000000..8e6987faba --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_outpost.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_outpost" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_portal.json new file mode 100644 index 0000000000..c7d6d8c940 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_portal.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_portal" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_shipwreck.json new file mode 100644 index 0000000000..24842ebd3e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_shipwreck.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_shipwreck" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_stronghold.json new file mode 100644 index 0000000000..1aa541befc --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_stronghold.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_stronghold" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_trail_ruins.json new file mode 100644 index 0000000000..017ff1bcbd --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/skeleton_trail_ruins.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_bow" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_trail_ruins" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe.json new file mode 100644 index 0000000000..2c30a76ee1 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:iron_axe" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe_gold.json new file mode 100644 index 0000000000..c09e4c5b01 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_axe_gold.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_axe" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_bow.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_bow.json new file mode 100644 index 0000000000..0f27b7882e --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_bow.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:bow" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_by_profession.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_by_profession.json new file mode 100644 index 0000000000..b4deea70a1 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_by_profession.json @@ -0,0 +1,98 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "nbt": "{VillagerData:{profession:\"minecraft:butcher\"}}" + } + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "name": "botania:equipment/loonium/weapon_axe" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "nbt": "{VillagerData:{profession:\"minecraft:farmer\"}}" + } + } + ], + "name": "minecraft:iron_hoe" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "nbt": "{VillagerData:{profession:\"minecraft:fisherman\"}}" + } + } + ], + "name": "minecraft:fishing_rod" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "nbt": "{VillagerData:{profession:\"minecraft:toolsmith\"}}" + } + } + ], + "name": "minecraft:iron_pickaxe" + }, + { + "type": "minecraft:loot_table", + "conditions": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "nbt": "{VillagerData:{profession:\"minecraft:weaponsmith\"}}" + } + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_crossbow.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_crossbow.json new file mode 100644 index 0000000000..503494bd41 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_crossbow.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:crossbow" + } + ], + "functions": [ + { + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_piglin.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_piglin.json new file mode 100644 index 0000000000..45476a3180 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_piglin.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword_gold" + }, + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_crossbow" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_wither_skeleton.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_wither_skeleton.json new file mode 100644 index 0000000000..87bf10ef97 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_for_wither_skeleton.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:stone_sword" + }, + { + "type": "minecraft:item", + "name": "minecraft:bow" + } + ], + "functions": [ + { + "function": "minecraft:enchant_randomly" + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 1.0, + "min": -1.0 + } + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword.json new file mode 100644 index 0000000000..42e29e30f7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:iron_sword", + "weight": 4 + }, + { + "type": "minecraft:item", + "name": "minecraft:diamond_sword" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword_gold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword_gold.json new file mode 100644 index 0000000000..9c653987e6 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_sword_gold.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:golden_sword" + } + ], + "functions": [ + { + "conditions": [ + { + "chance": 0.3, + "condition": "minecraft:random_chance" + } + ], + "function": "minecraft:enchant_randomly" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_trident.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_trident.json new file mode 100644 index 0000000000..462c4bad44 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/weapon_trident.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:trident" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_ancient_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_ancient_city.json new file mode 100644 index 0000000000..c1b7b7d98c --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_ancient_city.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_ancient_city" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_desert_pyramid.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_desert_pyramid.json new file mode 100644 index 0000000000..d7e237f9ee --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_desert_pyramid.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_desert_pyramid" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_end_city.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_end_city.json new file mode 100644 index 0000000000..0508220bb5 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_end_city.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_end_city" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_fortress.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_fortress.json new file mode 100644 index 0000000000..9267470c1a --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_fortress.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword_gold" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_fortress" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_jungle_temple.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_jungle_temple.json new file mode 100644 index 0000000000..44314ccfd4 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_jungle_temple.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_jungle_temple" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_monument.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_monument.json new file mode 100644 index 0000000000..481e32b332 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_monument.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_monument" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_outpost.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_outpost.json new file mode 100644 index 0000000000..135f8f5234 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_outpost.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_outpost" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_portal.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_portal.json new file mode 100644 index 0000000000..78c17d78c7 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_portal.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_portal" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword_gold" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_shipwreck.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_shipwreck.json new file mode 100644 index 0000000000..f3f8965ff9 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_shipwreck.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_shipwreck" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_stronghold.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_stronghold.json new file mode 100644 index 0000000000..f2aa134451 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_stronghold.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_stronghold" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_trail_ruins.json b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_trail_ruins.json new file mode 100644 index 0000000000..7e77d24eb5 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/loot_tables/equipment/loonium/zombie_trail_ruins.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:selector", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/weapon_sword" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:loot_table", + "name": "botania:equipment/loonium/armor_trail_ruins" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/botania/tags/items/loonium_offhand_equipment.json b/Xplat/src/generated/resources/data/botania/tags/items/loonium_offhand_equipment.json new file mode 100644 index 0000000000..21a303bd43 --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/tags/items/loonium_offhand_equipment.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + "minecraft:firework_rocket", + "minecraft:totem_of_undying", + "#minecraft:arrows" + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json new file mode 100644 index 0000000000..ca37fbef70 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json @@ -0,0 +1,73 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 99 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_ancient_city", + "weight": 40 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_ancient_city", + "weight": 80 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_ancient_city", + "weight": 410 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_ancient_city", + "weight": 60 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_ancient_city", + "weight": 440 + }, + { + "type": "minecraft:cave_spider", + "weight": 100 + }, + { + "type": "minecraft:spider", + "weight": 200 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json new file mode 100644 index 0000000000..42f5bb89f4 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json @@ -0,0 +1,90 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 99 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_bastion_remnant", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + } + }, + "spawnAsBaby": false, + "weight": 450 + }, + { + "type": "minecraft:piglin_brute", + "attributeModifiers": [ + { + "amount": 1.5, + "attribute": "minecraft:generic.max_health", + "name": "Loonium Modifier Health", + "operation": "multiply_base" + }, + { + "amount": 1.5, + "attribute": "minecraft:generic.attack_damage", + "name": "Loonium Modifier Damage", + "operation": "multiply_base" + } + ], + "equipmentTable": "botania:equipment/loonium/weapon_axe_gold", + "weight": 50 + }, + { + "type": "minecraft:hoglin", + "spawnAsBaby": false, + "weight": 300 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json new file mode 100644 index 0000000000..e2ee96418a --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json @@ -0,0 +1,63 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 50 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_desert_pyramid", + "weight": 450 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_desert_pyramid", + "weight": 50 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_desert_pyramid", + "weight": 500 + }, + { + "type": "minecraft:cave_spider", + "weight": 40 + }, + { + "type": "minecraft:spider", + "weight": 360 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json new file mode 100644 index 0000000000..ce96aa96b4 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json @@ -0,0 +1,88 @@ +{ + "parent": "botania:default", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:slow_falling" + } + ], + "spawnedMobs": [ + { + "type": "minecraft:shulker", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 100 + }, + { + "type": "minecraft:enderman", + "weight": 300 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "duration": 400, + "effect": "minecraft:slow_falling" + } + ], + "weight": 99 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "duration": 400, + "effect": "minecraft:slow_falling" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_end_city", + "weight": 300 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_end_city", + "weight": 300 + }, + { + "type": "minecraft:spider", + "weight": 300 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json new file mode 100644 index 0000000000..94063e7fcf --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json @@ -0,0 +1,74 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 99 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:blaze", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 300 + }, + { + "type": "minecraft:wither_skeleton", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/skeleton_fortress", + "weight": 450 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_fortress", + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/zombie_fortress", + "weight": 400 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json new file mode 100644 index 0000000000..b5c5781b99 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json @@ -0,0 +1,63 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_jungle_temple", + "weight": 40 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_jungle_temple", + "weight": 360 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_jungle_temple", + "weight": 500 + }, + { + "type": "minecraft:cave_spider", + "weight": 300 + }, + { + "type": "minecraft:spider", + "weight": 300 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json new file mode 100644 index 0000000000..75930d670f --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json @@ -0,0 +1,78 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:vindicator", + "equipmentTable": "botania:equipment/loonium/weapon_axe", + "weight": 600 + }, + { + "type": "minecraft:pillager", + "equipmentTable": "botania:equipment/loonium/weapon_crossbow", + "weight": 200 + }, + { + "type": "minecraft:evoker", + "weight": 100 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/armor_mansion", + "weight": 150 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/armor_mansion", + "spawnAsBaby": true, + "weight": 50 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/armor_mansion", + "weight": 200 + }, + { + "type": "minecraft:cave_spider", + "weight": 30 + }, + { + "type": "minecraft:spider", + "weight": 270 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json new file mode 100644 index 0000000000..9b9111560f --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json @@ -0,0 +1,96 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:guardian", + "weight": 200 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_monument", + "weight": 540 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_monument", + "weight": 60 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_monument", + "weight": 40 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_monument", + "weight": 360 + }, + { + "type": "minecraft:cave_spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 30 + }, + { + "type": "minecraft:spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 270 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json index 2d6c6ee5fb..8c63ecaee1 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json @@ -1,4 +1,92 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:ocean_ruins", + "spawnedMobs": [ + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 540 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 60 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 40 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 360 + }, + { + "type": "minecraft:cave_spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 30 + }, + { + "type": "minecraft:spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 270 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json index 2d6c6ee5fb..b31d7b0060 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json @@ -1,4 +1,87 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:ocean_ruins", + "spawnedMobs": [ + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 540 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 60 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 400 + }, + { + "type": "minecraft:cave_spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 30 + }, + { + "type": "minecraft:spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 270 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json index 2d6c6ee5fb..775f265856 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json @@ -1,4 +1,69 @@ { "parent": "botania:default", - "boundingBoxType": "full" + "boundingBoxType": "full", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:pillager", + "equipmentTable": "botania:equipment/loonium/weapon_crossbow", + "weight": 900 + }, + { + "type": "minecraft:vindicator", + "equipmentTable": "botania:equipment/loonium/weapon_axe", + "weight": 175 + }, + { + "type": "minecraft:evoker", + "weight": 25 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_outpost", + "weight": 200 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_outpost", + "weight": 200 + }, + { + "type": "minecraft:spider", + "weight": 200 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json new file mode 100644 index 0000000000..31ecae69ba --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json @@ -0,0 +1,114 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 59 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_portal", + "weight": 106 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 423 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 59 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 529 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json new file mode 100644 index 0000000000..5a8e30c96c --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json @@ -0,0 +1,100 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:enderman", + "weight": 50 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 450 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 450 + }, + { + "type": "minecraft:spider", + "weight": 360 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json new file mode 100644 index 0000000000..73246e160e --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json @@ -0,0 +1,104 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_portal", + "weight": 40 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 360 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 500 + }, + { + "type": "minecraft:cave_spider", + "weight": 250 + }, + { + "type": "minecraft:spider", + "weight": 50 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json new file mode 100644 index 0000000000..9d9d760abb --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json @@ -0,0 +1,104 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 529 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 59 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 529 + }, + { + "type": "minecraft:silverfish", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json new file mode 100644 index 0000000000..aadda5b735 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json @@ -0,0 +1,98 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 125 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + } + }, + "spawnAsBaby": false, + "weight": 500 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 450 + }, + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 200 + }, + { + "type": "minecraft:cave_spider", + "weight": 10 + }, + { + "type": "minecraft:spider", + "weight": 90 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json new file mode 100644 index 0000000000..2fa7397ce3 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json @@ -0,0 +1,131 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_portal", + "weight": 540 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 60 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 400 + }, + { + "type": "minecraft:cave_spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 30 + }, + { + "type": "minecraft:spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 270 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json new file mode 100644 index 0000000000..e0d8709eee --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json @@ -0,0 +1,104 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:zoglin", + "effectsToApply": [ + { + "effect": "minecraft:regeneration" + } + ], + "weight": 25 + }, + { + "type": "minecraft:piglin", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + } + ], + "equipmentTable": "botania:equipment/loonium/piglin_ruined_portal", + "nbt": { + "Brain": { + "memories": { + "minecraft:admiring_disabled": { + "value": 1 + }, + "minecraft:universal_anger": { + "value": 1 + } + } + }, + "IsImmuneToZombification": 1 + }, + "spawnAsBaby": false, + "weight": 50 + }, + { + "type": "minecraft:zombified_piglin", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 50 + }, + { + "type": "minecraft:enderman", + "weight": 30 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_portal", + "weight": 40 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_portal", + "weight": 360 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_portal", + "weight": 500 + }, + { + "type": "minecraft:cave_spider", + "weight": 50 + }, + { + "type": "minecraft:spider", + "weight": 250 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json new file mode 100644 index 0000000000..e153fc825f --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json @@ -0,0 +1,92 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 199 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_shipwreck", + "weight": 540 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_shipwreck", + "weight": 60 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_shipwreck", + "weight": 40 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_shipwreck", + "weight": 360 + }, + { + "type": "minecraft:cave_spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 30 + }, + { + "type": "minecraft:spider", + "effectsToApply": [ + { + "effect": "minecraft:fire_resistance" + }, + { + "effect": "minecraft:regeneration" + }, + { + "effect": "minecraft:water_breathing" + } + ], + "weight": 270 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json new file mode 100644 index 0000000000..4cec9eceb9 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:shipwreck" +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json new file mode 100644 index 0000000000..433353e4cf --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json @@ -0,0 +1,77 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 80 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 149 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_stronghold", + "weight": 40 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_stronghold", + "weight": 40 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_stronghold", + "weight": 410 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_stronghold", + "weight": 60 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_stronghold", + "weight": 440 + }, + { + "type": "minecraft:cave_spider", + "weight": 100 + }, + { + "type": "minecraft:silverfish", + "weight": 100 + }, + { + "type": "minecraft:spider", + "weight": 400 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json new file mode 100644 index 0000000000..c914ac379b --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json @@ -0,0 +1,73 @@ +{ + "parent": "botania:default", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/zombie_trail_ruins", + "weight": 59 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/drowned_trail_ruins", + "weight": 106 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/zombie_trail_ruins", + "weight": 423 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/skeleton_trail_ruins", + "weight": 59 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/skeleton_trail_ruins", + "weight": 529 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] +} \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json index 2d6c6ee5fb..e34d6a19a6 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json @@ -1,4 +1,68 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:village", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 423 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 59 + }, + { + "type": "minecraft:zombie_villager", + "equipmentTable": "botania:equipment/loonium/weapon_by_profession", + "weight": 106 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 600 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json index 2d6c6ee5fb..0741b193ba 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json @@ -1,4 +1,68 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:village", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 59 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 423 + }, + { + "type": "minecraft:zombie_villager", + "equipmentTable": "botania:equipment/loonium/weapon_by_profession", + "weight": 106 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 600 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json index 2d6c6ee5fb..03f13ad323 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json @@ -1,4 +1,73 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:village", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 30 + }, + { + "type": "minecraft:husk", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 30 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 423 + }, + { + "type": "minecraft:zombie_villager", + "equipmentTable": "botania:equipment/loonium/weapon_by_profession", + "weight": 106 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 600 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json index 2d6c6ee5fb..638cfd9b16 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json @@ -1,4 +1,73 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:village", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 59 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 423 + }, + { + "type": "minecraft:zombie_villager", + "equipmentTable": "botania:equipment/loonium/weapon_by_profession", + "weight": 106 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 529 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 59 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json index 2d6c6ee5fb..e7761d6068 100644 --- a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json +++ b/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json @@ -1,4 +1,73 @@ { - "parent": "botania:default", - "boundingBoxType": "full" + "parent": "botania:village", + "spawnedMobs": [ + { + "type": "minecraft:enderman", + "weight": 40 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "weight": 195 + }, + { + "type": "minecraft:creeper", + "effectsToApply": [ + { + "duration": 100, + "effect": "minecraft:fire_resistance" + }, + { + "duration": 100, + "effect": "minecraft:regeneration" + } + ], + "nbt": { + "powered": 1 + }, + "weight": 1 + }, + { + "type": "minecraft:drowned", + "equipmentTable": "botania:equipment/loonium/weapon_trident", + "weight": 59 + }, + { + "type": "minecraft:zombie", + "equipmentTable": "botania:equipment/loonium/weapon_sword", + "weight": 423 + }, + { + "type": "minecraft:zombie_villager", + "equipmentTable": "botania:equipment/loonium/weapon_by_profession", + "weight": 106 + }, + { + "type": "minecraft:stray", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 106 + }, + { + "type": "minecraft:skeleton", + "equipmentTable": "botania:equipment/loonium/weapon_bow", + "weight": 423 + }, + { + "type": "minecraft:cave_spider", + "weight": 59 + }, + { + "type": "minecraft:spider", + "weight": 529 + } + ] } \ No newline at end of file diff --git a/Xplat/src/generated/resources/data/minecraft/tags/items/arrows.json b/Xplat/src/generated/resources/data/minecraft/tags/items/arrows.json new file mode 100644 index 0000000000..5e8aecc986 --- /dev/null +++ b/Xplat/src/generated/resources/data/minecraft/tags/items/arrows.json @@ -0,0 +1,4 @@ +{ + "replace": false, + "values": [] +} \ No newline at end of file diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java index 90cba08f3a..90be93636d 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobSpawnData.java @@ -6,6 +6,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.random.Weight; import net.minecraft.util.random.WeightedEntry; import net.minecraft.world.entity.EntityType; @@ -18,9 +19,12 @@ public class LooniumMobSpawnData extends WeightedEntry.IntrusiveBase { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( - BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("type").forGetter(o -> o.type), + BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("type").forGetter(msd -> msd.type), Weight.CODEC.fieldOf("weight").forGetter(IntrusiveBase::getWeight), + Codec.BOOL.optionalFieldOf("spawnAsBaby").forGetter(msd -> Optional.ofNullable(msd.spawnAsBaby)), CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(msd -> Optional.ofNullable(msd.nbt)), + ResourceLocation.CODEC.optionalFieldOf("equipmentTable") + .forGetter(msd -> Optional.ofNullable(msd.equipmentTable)), Codec.list(LooniumMobEffectToApply.CODEC) .optionalFieldOf("effectsToApply") .forGetter(msd -> Optional.ofNullable(msd.effectsToApply)), @@ -31,16 +35,21 @@ public class LooniumMobSpawnData extends WeightedEntry.IntrusiveBase { ); public final EntityType type; + public final Boolean spawnAsBaby; public final CompoundTag nbt; + public final ResourceLocation equipmentTable; public final List effectsToApply; public final List attributeModifiers; - private LooniumMobSpawnData(EntityType type, Weight weight, @Nullable CompoundTag nbt, + private LooniumMobSpawnData(EntityType type, Weight weight, Boolean spawnAsBaby, @Nullable CompoundTag nbt, + @Nullable ResourceLocation equipmentTable, @Nullable List effectsToApply, @Nullable List attributeModifiers) { super(weight); this.type = type; + this.spawnAsBaby = spawnAsBaby; this.nbt = nbt != null ? nbt.copy() : null; + this.equipmentTable = equipmentTable; this.effectsToApply = effectsToApply != null ? ImmutableList.copyOf(effectsToApply) : null; this.attributeModifiers = attributeModifiers != null ? ImmutableList.copyOf(attributeModifiers) : null; } @@ -53,7 +62,9 @@ public static Builder entityWeight(EntityType type, int weight) { public String toString() { return "MobSpawnData{" + "type=" + type + + ", spawnAsBaby=" + spawnAsBaby + ", nbt=" + nbt + + ", equipmentTable=" + equipmentTable + ", effectsToApply=" + effectsToApply + ", attributeModifiers=" + attributeModifiers + '}'; @@ -62,17 +73,26 @@ public String toString() { // Codecs don't support setting null as intentional default value for optional fields, so we do this. // (blame com.mojang.datafixers.util.Either::getLeft using Optional::of instead Optional.ofNullable) @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static LooniumMobSpawnData create(EntityType type, Weight weight, Optional nbt, + private static LooniumMobSpawnData create(EntityType type, Weight weight, + Optional spawnAsBaby, + Optional nbt, + Optional equipmentTable, Optional> effectsToApply, Optional> attributeModifiers) { - return new LooniumMobSpawnData(type, weight, nbt.orElse(null), - effectsToApply.orElse(null), attributeModifiers.orElse(null)); + return new LooniumMobSpawnData(type, weight, + spawnAsBaby.orElse(null), + nbt.orElse(null), + equipmentTable.orElse(null), + effectsToApply.orElse(null), + attributeModifiers.orElse(null)); } public static class Builder { private final EntityType type; private final int weight; + private @Nullable Boolean spawnAsBaby; private @Nullable CompoundTag nbt; + private @Nullable ResourceLocation equipmentTable; private @Nullable List effectsToApply; private @Nullable List attributeModifiers; @@ -81,24 +101,61 @@ private Builder(EntityType type, int weight) { this.weight = weight; } - public Builder setNbt(CompoundTag nbt) { + /** + * Make the mob spawn as a baby. (This will not prevent AgeableMobs from growing up.) + */ + public Builder spawnAsBaby() { + this.spawnAsBaby = true; + return this; + } + + /** + * Force conversion of a baby mob to be reverted. This may have unintended side effects, + * like an adult zombie sitting on a chicken or an adult piglin not having a weapon. + * The latter case can usually be taken care of via an equipment table. + */ + public Builder spawnAsAdult() { + this.spawnAsBaby = false; + return this; + } + + /** + * Custom NBT data to apply to the mob before finalizing its spawning. + */ + public Builder nbt(CompoundTag nbt) { this.nbt = nbt; return this; } - public Builder setEffectsToApply(List effectsToApply) { - this.effectsToApply = effectsToApply; + /** + * A loot table to define equipment to apply to the mob after it spawned. + */ + public Builder equipmentTable(ResourceLocation equipmentTable) { + this.equipmentTable = equipmentTable; + return this; + } + + /** + * A list of potion effects to apply to the mob. + * (These are applied instead of any mob effects from the structure configuration.) + */ + public Builder effectsToApply(LooniumMobEffectToApply... effectsToApply) { + this.effectsToApply = List.of(effectsToApply); return this; } - public Builder setAttributeModifiers( - List attributeModifiers) { - this.attributeModifiers = attributeModifiers; + /** + * A list of attribute modifiers to apply to the mob. + * (These are applied instead of any attribute modifiers from the structure configuration.) + */ + public Builder attributeModifiers(LooniumMobAttributeModifier... attributeModifiers) { + this.attributeModifiers = List.of(attributeModifiers); return this; } public LooniumMobSpawnData build() { - return new LooniumMobSpawnData(type, Weight.of(weight), nbt, effectsToApply, attributeModifiers); + return new LooniumMobSpawnData(type, Weight.of(weight), spawnAsBaby, nbt, equipmentTable, + effectsToApply, attributeModifiers); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index b9ef6bb6e4..bf7c28c0dd 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -25,7 +25,9 @@ import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.monster.PatrollingMonster; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TieredItem; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; @@ -35,6 +37,7 @@ import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -51,6 +54,7 @@ import vazkii.botania.common.config.ConfigDataManager; import vazkii.botania.common.internal_caps.LooniumComponent; import vazkii.botania.common.lib.BotaniaTags; +import vazkii.botania.common.loot.BotaniaLootTables; import vazkii.botania.xplat.XplatAbstractions; import java.util.*; @@ -68,7 +72,6 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final String TAG_LOOT_TABLE = "lootTable"; private static final String TAG_DETECTED_STRUCTURE = "detectedStructure"; private static final String TAG_CONFIG_OVERRIDE = "configOverride"; - public static final ResourceLocation DEFAULT_LOOT_TABLE = prefix("loonium/default"); private static final Supplier FALLBACK_CONFIG = Suppliers.memoize(() -> LooniumStructureConfiguration.builder() .manaCost(DEFAULT_COST) @@ -179,6 +182,9 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, if (pickedMobType.nbt != null) { mob.readAdditionalSaveData(pickedMobType.nbt); } + if (pickedMobType.spawnAsBaby != null) { + mob.setBaby(pickedMobType.spawnAsBaby); + } mob.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); mob.setDeltaMovement(Vec3.ZERO); @@ -192,11 +198,51 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, } mob.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); + if (Boolean.FALSE.equals(pickedMobType.spawnAsBaby) && mob.isBaby()) { + // Note: might have already affected initial equipment/attribute selection, or even caused a special + // mob configuration (such as chicken jockey) to spawn, which may look weird when reverting to adult. + mob.setBaby(false); + } + + if (pickedMobType.equipmentTable != null) { + LootTable equipmentTable = world.getServer().getLootData().getLootTable(pickedMobType.equipmentTable); + if (equipmentTable != LootTable.EMPTY) { + var lootParams = new LootParams.Builder(world) + .withParameter(LootContextParams.THIS_ENTITY, mob) + .withParameter(LootContextParams.ORIGIN, mob.position()) + // TODO 1.21: replace with LootContextParamSets.EQUIPMENT + .create(LootContextParamSets.SELECTOR); + var equippedSlots = new HashSet(); + equipmentTable.getRandomItems(lootParams, equipmentStack -> { + var slot = equipmentStack.is(BotaniaTags.Items.LOONIUM_OFFHAND_EQUIPMENT) + ? EquipmentSlot.OFFHAND + : LivingEntity.getEquipmentSlotForItem(equipmentStack); + if (equippedSlots.contains(slot)) { + slot = equippedSlots.contains(EquipmentSlot.MAINHAND) + && !(equipmentStack.getItem() instanceof TieredItem) + ? EquipmentSlot.OFFHAND + : EquipmentSlot.MAINHAND; + } + if (!equippedSlots.add(slot)) { + return; + } + mob.setItemSlot(slot, slot.isArmor() ? equipmentStack.copyWithCount(1) : equipmentStack); + }); + } + } + // in case the mob spawned with a vehicle or passenger(s), ensure those don't drop unexpected loot mob.getRootVehicle().getPassengersAndSelf().forEach(e -> { if (e instanceof Mob otherMob) { // prevent armor/weapon drops on player kill, also no nautilus shells from drowned: Arrays.stream(EquipmentSlot.values()).forEach(slot -> otherMob.setDropChance(slot, 0)); + + if (mob instanceof PatrollingMonster patroller && patroller.isPatrolLeader()) { + // Loonium may be presenting challenges, but not that type of challenge + patroller.setPatrolLeader(false); + patroller.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY); + } + if (e == mob) { return; } @@ -281,7 +327,8 @@ private List> determineLootTables(ServerLevel Set structureIds) { var lootTables = new ArrayList>(); LootDataManager lootData = world.getServer().getLootData(); - Supplier defaultLootTableSupplier = Suppliers.memoize(() -> lootData.getLootTable(DEFAULT_LOOT_TABLE)); + Supplier defaultLootTableSupplier = Suppliers.memoize(() -> lootData.getLootTable( + BotaniaLootTables.LOONIUM_DEFAULT_LOOT)); if (lootTableOverride != null) { LootTable lootTable = lootData.getLootTable(lootTableOverride); if (lootTable != LootTable.EMPTY) { diff --git a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java index 4f5132a0bb..5366b231c0 100644 --- a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java +++ b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java @@ -102,7 +102,10 @@ private CompletableFuture scheduleConfigParse(PreparationBarrier barri Map resourceMap = new HashMap<>(); SimpleJsonResourceReloadListener.scanDirectory(manager, "config/" + type.directory, new Gson(), resourceMap); Map configs = new HashMap<>(resourceMap.size()); - resourceMap.forEach((id, jsonElement) -> type.codec.parse(JsonOps.INSTANCE, jsonElement).result().ifPresent(c -> configs.put(id, c))); + resourceMap.forEach((id, jsonElement) -> { + BotaniaAPI.LOGGER.info("Parsing {}", id); + type.codec.parse(JsonOps.INSTANCE, jsonElement).result().ifPresent(c -> configs.put(id, c)); + }); type.validateFunction.accept(configs); return configs; }, backgroundExecutor) diff --git a/Xplat/src/main/java/vazkii/botania/common/lib/BotaniaTags.java b/Xplat/src/main/java/vazkii/botania/common/lib/BotaniaTags.java index 71bef6bb23..2cd4ee8be6 100644 --- a/Xplat/src/main/java/vazkii/botania/common/lib/BotaniaTags.java +++ b/Xplat/src/main/java/vazkii/botania/common/lib/BotaniaTags.java @@ -68,6 +68,11 @@ public static class Items { * Items in this tag cannot be rolled by Looniums */ public static final TagKey LOONIUM_BLACKLIST = tag("loonium_blacklist"); + /** + * Items that should be equipped in the offhand slot if rolled as Loonium mob equipment, + * instead of the default slot for the item. + */ + public static final TagKey LOONIUM_OFFHAND_EQUIPMENT = tag("loonium_offhand_equipment"); /** * Items in this tag are voided by the Elementium Pick diff --git a/Xplat/src/main/java/vazkii/botania/common/loot/BotaniaLootTables.java b/Xplat/src/main/java/vazkii/botania/common/loot/BotaniaLootTables.java new file mode 100644 index 0000000000..980c2e319d --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/common/loot/BotaniaLootTables.java @@ -0,0 +1,153 @@ +package vazkii.botania.common.loot; + +import com.google.common.collect.Sets; + +import net.minecraft.resources.ResourceLocation; + +import java.util.Collections; +import java.util.Set; + +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; + +public class BotaniaLootTables { + private static final Set LOCATIONS = Sets.newHashSet(); + private static final Set IMMUTABLE_LOCATIONS = Collections.unmodifiableSet(LOCATIONS); + + public static final ResourceLocation LOONIUM_DEFAULT_LOOT = register("loonium/default"); + + // TODO 1.21: embed armor set and weapon equipment tables + public static final ResourceLocation LOONIUM_ARMORSET_COAST_CHAIN = register("equipment/loonium/armorset/coast_chain"); + public static final ResourceLocation LOONIUM_ARMORSET_COAST_IRON = register("equipment/loonium/armorset/coast_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_COAST_DIAMOND = register("equipment/loonium/armorset/coast_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_DUNE_GOLD = register("equipment/loonium/armorset/dune_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_DUNE_IRON = register("equipment/loonium/armorset/dune_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_DUNE_DIAMOND = register("equipment/loonium/armorset/dune_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_EYE_GOLD = register("equipment/loonium/armorset/eye_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_EYE_IRON = register("equipment/loonium/armorset/eye_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_EYE_DIAMOND = register("equipment/loonium/armorset/eye_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_HOST_CHAIN = register("equipment/loonium/armorset/host_chain"); + public static final ResourceLocation LOONIUM_ARMORSET_HOST_IRON = register("equipment/loonium/armorset/host_iron"); + + public static final ResourceLocation LOONIUM_ARMORSET_RAISER_IRON = register("equipment/loonium/armorset/raiser_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_RAISER_GOLD = register("equipment/loonium/armorset/raiser_gold"); + + public static final ResourceLocation LOONIUM_ARMORSET_RIB_IRON = register("equipment/loonium/armorset/rib_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_RIB_GOLD = register("equipment/loonium/armorset/rib_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_RIB_DIAMOND = register("equipment/loonium/armorset/rib_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_SENTRY_CHAIN = register("equipment/loonium/armorset/sentry_chain"); + public static final ResourceLocation LOONIUM_ARMORSET_SENTRY_IRON = register("equipment/loonium/armorset/sentry_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_SENTRY_DIAMOND = register("equipment/loonium/armorset/sentry_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_SHAPER_GOLD = register("equipment/loonium/armorset/shaper_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_SHAPER_DIAMOND = register("equipment/loonium/armorset/shaper_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_SILENCE_GOLD = register("equipment/loonium/armorset/silence_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_SILENCE_DIAMOND = register("equipment/loonium/armorset/silence_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_SNOUT_GOLD = register("equipment/loonium/armorset/snout_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_SNOUT_NETHERITE = register("equipment/loonium/armorset/snout_netherite"); + + public static final ResourceLocation LOONIUM_ARMORSET_SPIRE_IRON = register("equipment/loonium/armorset/spire_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_SPIRE_GOLD = register("equipment/loonium/armorset/spire_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_SPIRE_DIAMOND = register("equipment/loonium/armorset/spire_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_TIDE_LEATHER = register("equipment/loonium/armorset/tide_leather"); + public static final ResourceLocation LOONIUM_ARMORSET_TIDE_GOLD = register("equipment/loonium/armorset/tide_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_TIDE_DIAMOND = register("equipment/loonium/armorset/tide_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_WARD_IRON = register("equipment/loonium/armorset/ward_iron"); + public static final ResourceLocation LOONIUM_ARMORSET_WARD_DIAMOND = register("equipment/loonium/armorset/ward_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_WAYFINDER_CHAIN = register("equipment/loonium/armorset/wayfinder_chain"); + public static final ResourceLocation LOONIUM_ARMORSET_WAYFINDER_DIAMOND = register("equipment/loonium/armorset/wayfinder_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_WILD_CHAIN = register("equipment/loonium/armorset/wild_chain"); + public static final ResourceLocation LOONIUM_ARMORSET_WILD_GOLD = register("equipment/loonium/armorset/wild_gold"); + public static final ResourceLocation LOONIUM_ARMORSET_WILD_DIAMOND = register("equipment/loonium/armorset/wild_diamond"); + + public static final ResourceLocation LOONIUM_ARMORSET_COSTUME_ENDERMAN = register("equipment/loonium/armorset/costume_enderman"); + public static final ResourceLocation LOONIUM_ARMORSET_COSTUME_EVOKER = register("equipment/loonium/armorset/costume_evoker"); + public static final ResourceLocation LOONIUM_ARMORSET_COSTUME_VINDICATOR = register("equipment/loonium/armorset/costume_vindicator"); + public static final ResourceLocation LOONIUM_ARMORSET_COSTUME_ILLUSIONER = register("equipment/loonium/armorset/costume_illusioner"); + public static final ResourceLocation LOONIUM_ARMORSET_COSTUME_VEX = register("equipment/loonium/armorset/costume_vex"); + + public static final ResourceLocation LOONIUM_WEAPON_AXE = register("equipment/loonium/weapon_axe"); + public static final ResourceLocation LOONIUM_WEAPON_AXE_GOLD = register("equipment/loonium/weapon_axe_gold"); + public static final ResourceLocation LOONIUM_WEAPON_BOW = register("equipment/loonium/weapon_bow"); + public static final ResourceLocation LOONIUM_WEAPON_CROSSBOW = register("equipment/loonium/weapon_crossbow"); + public static final ResourceLocation LOONIUM_WEAPON_SWORD = register("equipment/loonium/weapon_sword"); + public static final ResourceLocation LOONIUM_WEAPON_SWORD_GOLD = register("equipment/loonium/weapon_sword_gold"); + public static final ResourceLocation LOONIUM_WEAPON_TRIDENT = register("equipment/loonium/weapon_trident"); + public static final ResourceLocation LOONIUM_WEAPON_BY_PROFESSION = register("equipment/loonium/weapon_by_profession"); + public static final ResourceLocation LOONIUM_WEAPON_FOR_PIGLIN = register("equipment/loonium/weapon_for_piglin"); + public static final ResourceLocation LOONIUM_WEAPON_FOR_WITHER_SKELETON = register("equipment/loonium/weapon_for_wither_skeleton"); + + public static final ResourceLocation LOONIUM_ARMOR_ANCIENT_CITY = register("equipment/loonium/armor_ancient_city"); + public static final ResourceLocation LOONIUM_ARMOR_BASTION_REMNANT = register("equipment/loonium/armor_bastion_remnant"); + public static final ResourceLocation LOONIUM_ARMOR_DESERT_PYRAMID = register("equipment/loonium/armor_desert_pyramid"); + public static final ResourceLocation LOONIUM_ARMOR_END_CITY = register("equipment/loonium/armor_end_city"); + public static final ResourceLocation LOONIUM_ARMOR_FORTRESS = register("equipment/loonium/armor_fortress"); + public static final ResourceLocation LOONIUM_ARMOR_JUNGLE_TEMPLE = register("equipment/loonium/armor_jungle_temple"); + public static final ResourceLocation LOONIUM_ARMOR_MANSION = register("equipment/loonium/armor_mansion"); + public static final ResourceLocation LOONIUM_ARMOR_MONUMENT = register("equipment/loonium/armor_monument"); + public static final ResourceLocation LOONIUM_ARMOR_OUTPOST = register("equipment/loonium/armor_outpost"); + public static final ResourceLocation LOONIUM_ARMOR_PORTAL = register("equipment/loonium/armor_portal"); + public static final ResourceLocation LOONIUM_ARMOR_SHIPWRECK = register("equipment/loonium/armor_shipwreck"); + public static final ResourceLocation LOONIUM_ARMOR_STRONGHOLD = register("equipment/loonium/armor_stronghold"); + public static final ResourceLocation LOONIUM_ARMOR_TRAIL_RUINS = register("equipment/loonium/armor_trail_ruins"); + + public static final ResourceLocation LOONIUM_DROWNED_ANCIENT_CITY = register("equipment/loonium/drowned_ancient_city"); + public static final ResourceLocation LOONIUM_DROWNED_JUNGLE_TEMPLE = register("equipment/loonium/drowned_jungle_temple"); + public static final ResourceLocation LOONIUM_DROWNED_MONUMENT = register("equipment/loonium/drowned_monument"); + public static final ResourceLocation LOONIUM_DROWNED_PORTAL = register("equipment/loonium/drowned_portal"); + public static final ResourceLocation LOONIUM_DROWNED_SHIPWRECK = register("equipment/loonium/drowned_shipwreck"); + public static final ResourceLocation LOONIUM_DROWNED_STRONGHOLD = register("equipment/loonium/drowned_stronghold"); + public static final ResourceLocation LOONIUM_DROWNED_TRAIL_RUINS = register("equipment/loonium/drowned_trail_ruins"); + + public static final ResourceLocation LOONIUM_PIGLIN_BASTION_REMNANT = register("equipment/loonium/piglin_bastion_remnant"); + public static final ResourceLocation LOONIUM_PIGLIN_PORTAL = register("equipment/loonium/piglin_ruined_portal"); + + public static final ResourceLocation LOONIUM_SKELETON_ANCIENT_CITY = register("equipment/loonium/skeleton_ancient_city"); + public static final ResourceLocation LOONIUM_SKELETON_DESERT_PYRAMID = register("equipment/loonium/skeleton_desert_pyramid"); + public static final ResourceLocation LOONIUM_SKELETON_JUNGLE_TEMPLE = register("equipment/loonium/skeleton_jungle_temple"); + public static final ResourceLocation LOONIUM_SKELETON_END_CITY = register("equipment/loonium/skeleton_end_city"); + public static final ResourceLocation LOONIUM_SKELETON_FORTRESS = register("equipment/loonium/skeleton_fortress"); + public static final ResourceLocation LOONIUM_SKELETON_MONUMENT = register("equipment/loonium/skeleton_monument"); + public static final ResourceLocation LOONIUM_SKELETON_OUTPOST = register("equipment/loonium/skeleton_outpost"); + public static final ResourceLocation LOONIUM_SKELETON_PORTAL = register("equipment/loonium/skeleton_portal"); + public static final ResourceLocation LOONIUM_SKELETON_SHIPWRECK = register("equipment/loonium/skeleton_shipwreck"); + public static final ResourceLocation LOONIUM_SKELETON_STRONGHOLD = register("equipment/loonium/skeleton_stronghold"); + public static final ResourceLocation LOONIUM_SKELETON_TRAIL_RUINS = register("equipment/loonium/skeleton_trail_ruins"); + + public static final ResourceLocation LOONIUM_ZOMBIE_ANCIENT_CITY = register("equipment/loonium/zombie_ancient_city"); + public static final ResourceLocation LOONIUM_ZOMBIE_DESERT_PYRAMID = register("equipment/loonium/zombie_desert_pyramid"); + public static final ResourceLocation LOONIUM_ZOMBIE_END_CITY = register("equipment/loonium/zombie_end_city"); + public static final ResourceLocation LOONIUM_ZOMBIE_FORTRESS = register("equipment/loonium/zombie_fortress"); + public static final ResourceLocation LOONIUM_ZOMBIE_JUNGLE_TEMPLE = register("equipment/loonium/zombie_jungle_temple"); + public static final ResourceLocation LOONIUM_ZOMBIE_MONUMENT = register("equipment/loonium/zombie_monument"); + public static final ResourceLocation LOONIUM_ZOMBIE_OUTPOST = register("equipment/loonium/zombie_outpost"); + public static final ResourceLocation LOONIUM_ZOMBIE_PORTAL = register("equipment/loonium/zombie_portal"); + public static final ResourceLocation LOONIUM_ZOMBIE_SHIPWRECK = register("equipment/loonium/zombie_shipwreck"); + public static final ResourceLocation LOONIUM_ZOMBIE_STRONGHOLD = register("equipment/loonium/zombie_stronghold"); + public static final ResourceLocation LOONIUM_ZOMBIE_TRAIL_RUINS = register("equipment/loonium/zombie_trail_ruins"); + + private static ResourceLocation register(String path) { + return register(prefix(path)); + } + + private static ResourceLocation register(ResourceLocation location) { + if (LOCATIONS.add(location)) { + return location; + } else { + throw new IllegalArgumentException(location + " is already a registered built-in loot table"); + } + } + + public static Set all() { + return IMMUTABLE_LOCATIONS; + } +} diff --git a/Xplat/src/main/java/vazkii/botania/data/ItemTagProvider.java b/Xplat/src/main/java/vazkii/botania/data/ItemTagProvider.java index bdcf1dbb42..3a2e0a613c 100644 --- a/Xplat/src/main/java/vazkii/botania/data/ItemTagProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/ItemTagProvider.java @@ -141,8 +141,13 @@ protected void addTags(HolderLookup.Provider provider) { allPetals.addTag(petalTag); } - this.tag(BotaniaTags.Items.LOONIUM_BLACKLIST).add(lexicon, overgrowthSeed, - blackLotus, blackerLotus).addTag(ItemTags.MUSIC_DISCS); + this.tag(BotaniaTags.Items.LOONIUM_BLACKLIST) + .add(lexicon, overgrowthSeed, blackLotus, blackerLotus) + .addTag(ItemTags.MUSIC_DISCS); + this.tag(ItemTags.ARROWS); + this.tag(BotaniaTags.Items.LOONIUM_OFFHAND_EQUIPMENT) + .add(Items.FIREWORK_ROCKET, Items.TOTEM_OF_UNDYING) + .addTag(ItemTags.ARROWS); this.tag(BotaniaTags.Items.MAGNET_RING_BLACKLIST); this.tag(BotaniaTags.Items.RODS).add( dirtRod, diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java new file mode 100644 index 0000000000..5a21b3d869 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java @@ -0,0 +1,875 @@ +package vazkii.botania.data; + +import com.google.gson.JsonElement; + +import net.minecraft.advancements.critereon.*; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.item.*; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.armortrim.*; +import net.minecraft.world.level.storage.loot.Deserializers; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.LootPool; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.entries.LootTableReference; +import net.minecraft.world.level.storage.loot.functions.EnchantRandomlyFunction; +import net.minecraft.world.level.storage.loot.functions.SetNbtFunction; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.predicates.AnyOfCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemEntityPropertyCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceCondition; +import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; +import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; + +import org.apache.commons.lang3.function.TriFunction; +import org.jetbrains.annotations.NotNull; + +import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.common.loot.BotaniaLootTables; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +public class LooniumEquipmentLootProvider implements DataProvider { + public static final int COLOR_ENDERMAN_BODY = 0x1d1d21; // (black) + public static final int COLOR_TIDE_LEATHER = 0x169c9c; // (cyan) + public static final int COLOR_EVOKER_COAT = 0x323639; // (black + gray) + public static final int COLOR_VINDICATOR_BOOTS = 0x323639; // (black + gray( + public static final int COLOR_VINDICATOR_JACKET = 0x474f52; // (gray) + public static final int COLOR_VINDICATOR_LEGWEAR = 0x168c8c; // (black + 7 cyan) + public static final int COLOR_ILLUSIONER_COAT = 0x3b7bc2; // (blue + light blue) + + private final PackOutput.PathProvider pathProvider; + private final CompletableFuture registryLookupFuture; + + public LooniumEquipmentLootProvider(PackOutput packOutput, CompletableFuture registryLookupFuture) { + // NOTE: equipment loot tables become a vanilla feature in future versions + this.pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "loot_tables"); + this.registryLookupFuture = registryLookupFuture; + } + + @NotNull + @Override + public CompletableFuture run(@NotNull CachedOutput cache) { + return registryLookupFuture.thenCompose(registryLookup -> this.run(cache, registryLookup)); + } + + private CompletableFuture run(@NotNull CachedOutput cache, HolderLookup.Provider registryLookup) { + HolderLookup.RegistryLookup patternRegistry = registryLookup.lookupOrThrow(Registries.TRIM_PATTERN); + HolderLookup.RegistryLookup materialRegistry = registryLookup.lookupOrThrow(Registries.TRIM_MATERIAL); + BiFunction, ResourceKey, ArmorTrim> trimFactory = + (pattern, material) -> getTrim(patternRegistry, materialRegistry, pattern, material); + BiConsumer trimSetter = (trim, tag) -> addTrimToTag(registryLookup, trim).accept(tag); + BiFunction randomizedSetFactory = + (trim, armorItems) -> createArmorSet(addTrimToTag(registryLookup, trim), true, armorItems); + TriFunction randomizedDyedSetFactory = + (trim, color, armorItems) -> createArmorSet(addTrimToTag(registryLookup, trim) + .andThen(addDyedColorToTag(color)), true, armorItems); + TriFunction fixedDyedSetFactory = + (trim, color, armorItems) -> createArmorSet(addTrimToTag(registryLookup, trim) + .andThen(addDyedColorToTag(color)), false, armorItems); + + Map armorItems = Map.of( + ArmorMaterials.LEATHER, new Item[] { + Items.LEATHER_HELMET, Items.LEATHER_CHESTPLATE, Items.LEATHER_LEGGINGS, Items.LEATHER_BOOTS + }, + ArmorMaterials.CHAIN, new Item[] { + Items.CHAINMAIL_HELMET, Items.CHAINMAIL_CHESTPLATE, Items.CHAINMAIL_LEGGINGS, Items.CHAINMAIL_BOOTS + }, + ArmorMaterials.IRON, new Item[] { + Items.IRON_HELMET, Items.IRON_CHESTPLATE, Items.IRON_LEGGINGS, Items.IRON_BOOTS + }, + ArmorMaterials.GOLD, new Item[] { + Items.GOLDEN_HELMET, Items.GOLDEN_CHESTPLATE, Items.GOLDEN_LEGGINGS, Items.GOLDEN_BOOTS + }, + ArmorMaterials.DIAMOND, new Item[] { + Items.DIAMOND_HELMET, Items.DIAMOND_CHESTPLATE, Items.DIAMOND_LEGGINGS, Items.DIAMOND_BOOTS + }, + ArmorMaterials.NETHERITE, new Item[] { + Items.NETHERITE_HELMET, Items.NETHERITE_CHESTPLATE, Items.NETHERITE_LEGGINGS, Items.NETHERITE_BOOTS + } + ); + + Map tables = new HashMap<>(); + + defineWeaponEquipmentTables(tables); + defineAncientCityEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineBastionRemnantEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineDesertPyramidEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineEndCityEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineJungleTempleEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineFortressEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineOceanMonumentEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory, randomizedDyedSetFactory); + definePillagerOutpostEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineRuinedPortalEquipmentTables(tables); + defineShipwreckEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineStrongholdEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory, trimSetter); + defineTrailRuinsEquipmentTables(tables, armorItems, trimFactory, randomizedSetFactory); + defineWoodlandMansionEquipmentTables(tables, trimFactory, fixedDyedSetFactory, trimSetter); + + // TODO: we should be using LootTableSubProvider implementations instead of three individual loot providers + var output = new ArrayList>(tables.size()); + for (var e : tables.entrySet()) { + Path path = pathProvider.json(e.getKey()); + LootTable.Builder builder = e.getValue(); + // TODO 1.21: use LootContextParamSets.EQUIPMENT instead + LootTable lootTable = builder.setParamSet(LootContextParamSets.SELECTOR).build(); + JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + private void defineWeaponEquipmentTables(Map tables) { + tables.put(BotaniaLootTables.LOONIUM_WEAPON_AXE, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootItem.lootTableItem(Items.IRON_AXE)) + // no need to add diamond axe, it's the same base damage, but actually less enchantable + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_AXE_GOLD, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootItem.lootTableItem(Items.GOLDEN_AXE)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_BOW, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootItem.lootTableItem(Items.BOW)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_CROSSBOW, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment()) + .add(LootItem.lootTableItem(Items.CROSSBOW)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_SWORD, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootItem.lootTableItem(Items.IRON_SWORD).setWeight(4)) + .add(LootItem.lootTableItem(Items.DIAMOND_SWORD)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_SWORD_GOLD, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootItem.lootTableItem(Items.GOLDEN_SWORD)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT, + LootTable.lootTable().withPool(LootPool.lootPool() + // no useful enchantments for mob usage + .add(LootItem.lootTableItem(Items.TRIDENT)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_AXE) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().nbt( + new NbtPredicate(getProfessionNbt(VillagerProfession.BUTCHER)))))) + .add(LootItem.lootTableItem(Items.IRON_HOE) + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().nbt( + new NbtPredicate(getProfessionNbt(VillagerProfession.FARMER)))))) + .add(LootItem.lootTableItem(Items.FISHING_ROD) + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().nbt( + new NbtPredicate(getProfessionNbt(VillagerProfession.FISHERMAN)))))) + .add(LootItem.lootTableItem(Items.IRON_PICKAXE) + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().nbt( + new NbtPredicate(getProfessionNbt(VillagerProfession.TOOLSMITH)))))) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().nbt( + new NbtPredicate(getProfessionNbt(VillagerProfession.WEAPONSMITH)))))) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_FOR_PIGLIN, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD_GOLD)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_CROSSBOW)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_WEAPON_FOR_WITHER_SKELETON, + LootTable.lootTable().withPool(LootPool.lootPool().setRolls(UniformGenerator.between(-1, 1)) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment()) + .add(LootItem.lootTableItem(Items.STONE_SWORD)) + .add(LootItem.lootTableItem(Items.BOW)) + ) + ); + } + + private CompoundTag getProfessionNbt(VillagerProfession profession) { + var villagerDataTag = new CompoundTag(); + BuiltInRegistries.VILLAGER_PROFESSION.byNameCodec().encodeStart(NbtOps.INSTANCE, profession).resultOrPartial( + BotaniaAPI.LOGGER::error).ifPresent(data -> villagerDataTag.put("profession", data)); + var tag = new CompoundTag(); + tag.put("VillagerData", villagerDataTag); + return tag; + } + + private void defineAncientCityEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimWardQuartz = trimFactory.apply(TrimPatterns.WARD, TrimMaterials.QUARTZ); + var trimSilenceCopper = trimFactory.apply(TrimPatterns.SILENCE, TrimMaterials.COPPER); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WARD_IRON, + randomizedSetFactory.apply(trimWardQuartz, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WARD_DIAMOND, + randomizedSetFactory.apply(trimWardQuartz, armorItems.get(ArmorMaterials.DIAMOND))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SILENCE_GOLD, + randomizedSetFactory.apply(trimSilenceCopper, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SILENCE_DIAMOND, + randomizedSetFactory.apply(trimSilenceCopper, armorItems.get(ArmorMaterials.DIAMOND))); + + var darknessEffectTag = getPotionEffectTag(MobEffects.DARKNESS, 200); + tables.put(BotaniaLootTables.LOONIUM_ARMOR_ANCIENT_CITY, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WARD_IRON).setWeight(11)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WARD_DIAMOND).setWeight(5)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SILENCE_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SILENCE_DIAMOND).setWeight(1)) + ).withPool(LootPool.lootPool() + // Note: Slowness from Strays stacks with tipped arrow effects, so just checking for bow here + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity().equipment(EntityEquipmentPredicate.Builder.equipment() + .mainhand(ItemPredicate.Builder.item().of(Items.BOW).build()).build()))) + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.TIPPED_ARROW).apply(SetNbtFunction.setTag(darknessEffectTag))) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_ANCIENT_CITY, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_ANCIENT_CITY))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_ANCIENT_CITY, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_ANCIENT_CITY))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_ANCIENT_CITY, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_ANCIENT_CITY))) + ); + } + + private void defineBastionRemnantEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimSnoutGold = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.GOLD); + var trimSnoutNetherite = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.NETHERITE); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_GOLD, + randomizedSetFactory.apply(trimSnoutNetherite, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_NETHERITE, + randomizedSetFactory.apply(trimSnoutGold, armorItems.get(ArmorMaterials.NETHERITE))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_BASTION_REMNANT, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_GOLD).setWeight(4)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_NETHERITE).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_PIGLIN_BASTION_REMNANT, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_FOR_PIGLIN))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_BASTION_REMNANT))) + ); + } + + private void defineDesertPyramidEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimDuneRedstone = trimFactory.apply(TrimPatterns.DUNE, TrimMaterials.REDSTONE); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_IRON, + randomizedSetFactory.apply(trimDuneRedstone, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_GOLD, + randomizedSetFactory.apply(trimDuneRedstone, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_DIAMOND, + randomizedSetFactory.apply(trimDuneRedstone, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_DESERT_PYRAMID, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_IRON).setWeight(5)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_GOLD).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_DIAMOND).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_DESERT_PYRAMID, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_DESERT_PYRAMID))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_DESERT_PYRAMID, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_DESERT_PYRAMID))) + ); + } + + private void defineEndCityEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimSpireAmethyst = trimFactory.apply(TrimPatterns.SPIRE, TrimMaterials.AMETHYST); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_IRON, + randomizedSetFactory.apply(trimSpireAmethyst, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_GOLD, + randomizedSetFactory.apply(trimSpireAmethyst, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_DIAMOND, + randomizedSetFactory.apply(trimSpireAmethyst, armorItems.get(ArmorMaterials.DIAMOND))); + + var levitationEffectTag = getPotionEffectTag(MobEffects.LEVITATION, 200); + tables.put(BotaniaLootTables.LOONIUM_ARMOR_END_CITY, + LootTable.lootTable().withPool(LootPool.lootPool() + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_IRON).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_GOLD).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_DIAMOND).setWeight(2)) + ).withPool(LootPool.lootPool() + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity() + .entityType(EntityTypePredicate.of(EntityType.SKELETON)))) + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.TIPPED_ARROW) + .apply(SetNbtFunction.setTag(levitationEffectTag))) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_END_CITY, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_END_CITY))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_END_CITY, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_END_CITY))) + ); + } + + private static CompoundTag getPotionEffectTag(MobEffect mobEffect, int duration) { + // [VanillaCopy] based on PotionUtils::setCustomEffects + ListTag effects = new ListTag(); + effects.add(new MobEffectInstance(mobEffect, duration).save(new CompoundTag())); + + CompoundTag effectTag = new CompoundTag(); + effectTag.put(PotionUtils.TAG_CUSTOM_POTION_EFFECTS, effects); + effectTag.putInt(PotionUtils.TAG_CUSTOM_POTION_COLOR, mobEffect.getColor()); + + return effectTag; + } + + private void defineFortressEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimRibIron = trimFactory.apply(TrimPatterns.RIB, TrimMaterials.IRON); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RIB_IRON, + randomizedSetFactory.apply(trimRibIron, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RIB_GOLD, + randomizedSetFactory.apply(trimRibIron, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RIB_DIAMOND, + randomizedSetFactory.apply(trimRibIron, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_FORTRESS, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_RIB_IRON).setWeight(7)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_RIB_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_RIB_DIAMOND).setWeight(2)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_FORTRESS, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_FOR_WITHER_SKELETON))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_FORTRESS))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_FORTRESS, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD_GOLD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_FORTRESS))) + ); + } + + private void defineJungleTempleEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimWildEmerald = trimFactory.apply(TrimPatterns.WILD, TrimMaterials.EMERALD); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WILD_CHAIN, + randomizedSetFactory.apply(trimWildEmerald, armorItems.get(ArmorMaterials.CHAIN))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WILD_GOLD, + randomizedSetFactory.apply(trimWildEmerald, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WILD_DIAMOND, + randomizedSetFactory.apply(trimWildEmerald, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_JUNGLE_TEMPLE, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WILD_CHAIN).setWeight(4)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WILD_GOLD).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WILD_DIAMOND).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_JUNGLE_TEMPLE, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_JUNGLE_TEMPLE))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_JUNGLE_TEMPLE, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_JUNGLE_TEMPLE))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_JUNGLE_TEMPLE, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_JUNGLE_TEMPLE))) + ); + } + + private void defineOceanMonumentEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory, + TriFunction randomizedDyedSetFactory) { + + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_LEATHER, randomizedDyedSetFactory.apply( + trimFactory.apply(TrimPatterns.TIDE, TrimMaterials.COPPER), COLOR_TIDE_LEATHER, armorItems.get(ArmorMaterials.LEATHER))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_GOLD, randomizedSetFactory.apply( + trimFactory.apply(TrimPatterns.TIDE, TrimMaterials.DIAMOND), armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_DIAMOND, randomizedSetFactory.apply( + trimFactory.apply(TrimPatterns.TIDE, TrimMaterials.GOLD), armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_MONUMENT, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_LEATHER).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_TIDE_DIAMOND).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_MONUMENT, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_MONUMENT))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_MONUMENT, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_MONUMENT))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_MONUMENT, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_MONUMENT))) + ); + } + + private void definePillagerOutpostEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimSentryEmerald = trimFactory.apply(TrimPatterns.SENTRY, TrimMaterials.EMERALD); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_CHAIN, + randomizedSetFactory.apply(trimSentryEmerald, armorItems.get(ArmorMaterials.CHAIN))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_IRON, + randomizedSetFactory.apply(trimSentryEmerald, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_DIAMOND, + randomizedSetFactory.apply(trimSentryEmerald, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_OUTPOST, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_CHAIN).setWeight(5)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_IRON).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_DIAMOND).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_OUTPOST, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_OUTPOST))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_OUTPOST, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_OUTPOST))) + ); + } + + private void defineRuinedPortalEquipmentTables(Map tables) { + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_PORTAL, + LootTable.lootTable() + .withPool(LootPool.lootPool().add( + LootItem.lootTableItem(Items.GOLDEN_HELMET)).setRolls(UniformGenerator.between(0, 1))) + .withPool(LootPool.lootPool().add( + LootItem.lootTableItem(Items.GOLDEN_CHESTPLATE)).setRolls(UniformGenerator.between(0, 1))) + .withPool(LootPool.lootPool().add( + LootItem.lootTableItem(Items.GOLDEN_LEGGINGS)).setRolls(UniformGenerator.between(0, 1))) + .withPool(LootPool.lootPool().add( + LootItem.lootTableItem(Items.GOLDEN_BOOTS)).setRolls(UniformGenerator.between(0, 1))) + ); + + tables.put(BotaniaLootTables.LOONIUM_DROWNED_PORTAL, + LootTable.lootTable() + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_PORTAL))) + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + ); + tables.put(BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, + LootTable.lootTable() + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_PORTAL))) + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_FOR_PIGLIN))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_PORTAL, + LootTable.lootTable() + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_PORTAL))) + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL, + LootTable.lootTable() + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_PORTAL))) + .withPool(LootPool.lootPool().add( + LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD_GOLD))) + ); + } + + private void defineShipwreckEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimCoastEmerald = trimFactory.apply(TrimPatterns.COAST, TrimMaterials.EMERALD); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COAST_CHAIN, + randomizedSetFactory.apply(trimCoastEmerald, armorItems.get(ArmorMaterials.CHAIN))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COAST_IRON, + randomizedSetFactory.apply(trimCoastEmerald, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COAST_DIAMOND, + randomizedSetFactory.apply(trimCoastEmerald, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_SHIPWRECK, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COAST_CHAIN).setWeight(4)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COAST_IRON).setWeight(4)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COAST_DIAMOND).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_SHIPWRECK, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_SHIPWRECK))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_SHIPWRECK, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_SHIPWRECK))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_SHIPWRECK, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_SHIPWRECK))) + ); + } + + private void defineStrongholdEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory, + BiConsumer trimSetter) { + + var trimEyeRedstone = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.REDSTONE); + var trimEyeLapis = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.LAPIS); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_EYE_IRON, + randomizedSetFactory.apply(trimEyeLapis, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_EYE_GOLD, + randomizedSetFactory.apply(trimEyeRedstone, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_EYE_DIAMOND, + randomizedSetFactory.apply(trimEyeLapis, armorItems.get(ArmorMaterials.DIAMOND))); + + // Enderman cosplay + var endermanHeadTag = new CompoundTag(); + trimSetter.accept(trimFactory.apply(TrimPatterns.EYE, TrimMaterials.AMETHYST), endermanHeadTag); + addDyedColorToTag(COLOR_ENDERMAN_BODY).accept(endermanHeadTag); + var endermanBodyTag = new CompoundTag(); + addDyedColorToTag(COLOR_ENDERMAN_BODY).accept(endermanBodyTag); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_ENDERMAN, LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_HELMET) + .apply(SetNbtFunction.setTag(endermanHeadTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_CHESTPLATE) + .apply(SetNbtFunction.setTag(endermanBodyTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_LEGGINGS) + .apply(SetNbtFunction.setTag(endermanBodyTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_BOOTS) + .apply(SetNbtFunction.setTag(endermanBodyTag)))) + ); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_STRONGHOLD, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_EYE_IRON).setWeight(5)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_EYE_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_EYE_DIAMOND).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_ENDERMAN).setWeight(1)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_STRONGHOLD, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_STRONGHOLD))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_STRONGHOLD, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_STRONGHOLD))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_STRONGHOLD, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_STRONGHOLD))) + ); + } + + private void defineTrailRuinsEquipmentTables(Map tables, + Map armorItems, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + BiFunction randomizedSetFactory) { + + var trimHostEmerald = trimFactory.apply(TrimPatterns.HOST, TrimMaterials.EMERALD); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_HOST_CHAIN, + randomizedSetFactory.apply(trimHostEmerald, armorItems.get(ArmorMaterials.CHAIN))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_HOST_IRON, + randomizedSetFactory.apply(trimHostEmerald, armorItems.get(ArmorMaterials.IRON))); + + var trimRaiserAmethyst = trimFactory.apply(TrimPatterns.RAISER, TrimMaterials.AMETHYST); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_IRON, + randomizedSetFactory.apply(trimRaiserAmethyst, armorItems.get(ArmorMaterials.IRON))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_GOLD, + randomizedSetFactory.apply(trimRaiserAmethyst, armorItems.get(ArmorMaterials.GOLD))); + + var trimShaperLapis = trimFactory.apply(TrimPatterns.SHAPER, TrimMaterials.LAPIS); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_GOLD, + randomizedSetFactory.apply(trimShaperLapis, armorItems.get(ArmorMaterials.GOLD))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_DIAMOND, + randomizedSetFactory.apply(trimShaperLapis, armorItems.get(ArmorMaterials.DIAMOND))); + + var trimWayfinderRedstone = trimFactory.apply(TrimPatterns.WAYFINDER, TrimMaterials.REDSTONE); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_CHAIN, + randomizedSetFactory.apply(trimWayfinderRedstone, armorItems.get(ArmorMaterials.CHAIN))); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_DIAMOND, + randomizedSetFactory.apply(trimWayfinderRedstone, armorItems.get(ArmorMaterials.DIAMOND))); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_TRAIL_RUINS, + LootTable.lootTable().withPool(LootPool.lootPool() + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_HOST_CHAIN).setWeight(7)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_CHAIN).setWeight(7)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_IRON).setWeight(8)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_HOST_IRON).setWeight(8)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_GOLD).setWeight(3)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_DIAMOND).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_DIAMOND).setWeight(2)) + ) + ); + tables.put(BotaniaLootTables.LOONIUM_DROWNED_TRAIL_RUINS, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_TRAIL_RUINS))) + ); + tables.put(BotaniaLootTables.LOONIUM_SKELETON_TRAIL_RUINS, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_BOW))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_TRAIL_RUINS))) + ); + tables.put(BotaniaLootTables.LOONIUM_ZOMBIE_TRAIL_RUINS, + LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_WEAPON_SWORD))) + .withPool(LootPool.lootPool().add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMOR_TRAIL_RUINS))) + ); + } + + private void defineWoodlandMansionEquipmentTables(Map tables, + BiFunction, ResourceKey, ArmorTrim> trimFactory, + TriFunction fixedDyedSetFactory, + BiConsumer trimSetter) { + + // Evoker cosplay, with higher likelihood of holding a totem + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_EVOKER, fixedDyedSetFactory.apply( + trimFactory.apply(TrimPatterns.VEX, TrimMaterials.GOLD), COLOR_EVOKER_COAT, + new Item[] { Items.LEATHER_CHESTPLATE, Items.LEATHER_LEGGINGS }) + .withPool(LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance(0.2f)) + .add(LootItem.lootTableItem(Items.TOTEM_OF_UNDYING)) + ) + ); + + // Vindicator cosplay, usually including axe (even for ranged mobs) + var vindicatorChestTag = new CompoundTag(); + trimSetter.accept(trimFactory.apply(TrimPatterns.VEX, TrimMaterials.NETHERITE), vindicatorChestTag); + addDyedColorToTag(COLOR_VINDICATOR_JACKET).accept(vindicatorChestTag); + var vindicatorLegsTag = new CompoundTag(); + addDyedColorToTag(COLOR_VINDICATOR_LEGWEAR).accept(vindicatorLegsTag); + var vindicatorBootsTag = new CompoundTag(); + addDyedColorToTag(COLOR_VINDICATOR_BOOTS).accept(vindicatorBootsTag); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_VINDICATOR, LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_CHESTPLATE) + .apply(SetNbtFunction.setTag(vindicatorChestTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_LEGGINGS) + .apply(SetNbtFunction.setTag(vindicatorLegsTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.LEATHER_BOOTS) + .apply(SetNbtFunction.setTag(vindicatorBootsTag)))) + .withPool(LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.IRON_AXE) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))))) + ); + + // Illusioner cosplay, including bow and blindness arrows, even for mobs that don't know how to use bows + var blindnessEffectTag = getPotionEffectTag(MobEffects.BLINDNESS, 100); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_ILLUSIONER, fixedDyedSetFactory.apply( + trimFactory.apply(TrimPatterns.VEX, TrimMaterials.LAPIS), COLOR_ILLUSIONER_COAT, + new Item[] { Items.LEATHER_HELMET, Items.LEATHER_CHESTPLATE, Items.LEATHER_LEGGINGS }) + .withPool(LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.BOW) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))))) + .withPool(LootPool.lootPool() + .when(LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity() + .entityType(EntityTypePredicate.of(EntityType.SKELETON)))) + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.TIPPED_ARROW) + .apply(SetNbtFunction.setTag(blindnessEffectTag)))) + ); + + // Vex cosplay, including sword (even for ranged mobs) + var vexHeadTag = new CompoundTag(); + trimSetter.accept(trimFactory.apply(TrimPatterns.VEX, TrimMaterials.AMETHYST), vexHeadTag); + tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_VEX, LootTable.lootTable() + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.DIAMOND_HELMET) + .apply(SetNbtFunction.setTag(vexHeadTag)))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.DIAMOND_CHESTPLATE))) + .withPool(LootPool.lootPool().add(LootItem.lootTableItem(Items.DIAMOND_LEGGINGS))) + .withPool(LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance(0.9f)) + .add(LootItem.lootTableItem(Items.IRON_SWORD) + .apply(EnchantRandomlyFunction.randomApplicableEnchantment() + .when(LootItemRandomChanceCondition.randomChance(0.3f))))) + ); + + tables.put(BotaniaLootTables.LOONIUM_ARMOR_MANSION, + LootTable.lootTable().withPool(LootPool.lootPool() + // it's cosplays all the way down + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_EVOKER).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_VINDICATOR).setWeight(2)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_ILLUSIONER).setWeight(1)) + .add(LootTableReference.lootTableReference(BotaniaLootTables.LOONIUM_ARMORSET_COSTUME_VEX).setWeight(45) + .when(AnyOfCondition.anyOf( + // focus Vex cosplay on baby mobs, reduce chance for everyone else + LootItemRandomChanceCondition.randomChance(0.005f), + LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, + EntityPredicate.Builder.entity() + .flags(EntityFlagsPredicate.Builder.flags().setIsBaby(true).build())) + ))) + ).withPool(LootPool.lootPool() + .when(LootItemRandomChanceCondition.randomChance(0.05f)) + .add(LootItem.lootTableItem(Items.TOTEM_OF_UNDYING)) + ) + ); + } + + private static ArmorTrim getTrim(HolderLookup.RegistryLookup patternRegistry, + HolderLookup.RegistryLookup materialRegistry, + ResourceKey pattern, ResourceKey material) { + var tidePattern = patternRegistry.get(pattern).orElseThrow(); + var goldMaterial = materialRegistry.get(material).orElseThrow(); + return new ArmorTrim(goldMaterial, tidePattern); + } + + private static Consumer addTrimToTag(HolderLookup.Provider registryLookup, ArmorTrim trim) { + // [VanillaCopy] from ArmorTrim::setTrim, because no access to item tags here + return tag -> tag.put(ArmorTrim.TAG_TRIM_ID, + ArmorTrim.CODEC.encodeStart(RegistryOps.create(NbtOps.INSTANCE, registryLookup), trim) + .result().orElseThrow()); + } + + private static Consumer addDyedColorToTag(int color) { + // [VanillaCopy] implementation based on DyeableLeatherItem::setColor + CompoundTag displayTag = new CompoundTag(); + displayTag.putInt("color", color); + return tag -> tag.put("display", displayTag); + } + + private LootTable.Builder createArmorSet(Consumer tagModifier, boolean randomized, Item... armorItems) { + CompoundTag tag = new CompoundTag(); + tagModifier.accept(tag); + var lootTable = LootTable.lootTable(); + for (Item armorItem : armorItems) { + lootTable.withPool(LootPool.lootPool() + .setRolls(randomized ? UniformGenerator.between(0, 1) : ConstantValue.exactly(1)) + .add(LootItem.lootTableItem(armorItem).apply(SetNbtFunction.setTag(tag)))); + } + return lootTable; + } + + @NotNull + @Override + public String getName() { + return "Equipment tables for Loonium-spawned mobs"; + } +} diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index 9127e8ec44..c6b50171b0 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -1,16 +1,22 @@ package vazkii.botania.data; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.level.levelgen.structure.BuiltinStructures; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; @@ -22,6 +28,7 @@ import vazkii.botania.api.configdata.LooniumMobSpawnData; import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; +import vazkii.botania.common.loot.BotaniaLootTables; import java.nio.file.Path; import java.util.ArrayList; @@ -30,8 +37,12 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; + public class LooniumStructureConfigurationProvider implements DataProvider { + public static final String LOONIUM_MODIFIER_DAMAGE = "Loonium Modifier Damage"; + public static final String LOONIUM_MODIFIER_HEALTH = "Loonium Modifier Health"; private final PackOutput.PathProvider pathProvider; public LooniumStructureConfigurationProvider(PackOutput packOutput) { @@ -42,79 +53,653 @@ public LooniumStructureConfigurationProvider(PackOutput packOutput) { @Override public CompletableFuture run(@NotNull CachedOutput cache) { Map configs = new HashMap<>(); + ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; + configs.put(defaultConfigId, getDefaultConfig()); - List effectsToApplyToCreepers = List.of( - LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), - LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build() + configs.put(BuiltinStructures.ANCIENT_CITY.location(), getConfigAncientCity(defaultConfigId)); + configs.put(BuiltinStructures.BASTION_REMNANT.location(), getConfigBastionRemnant(defaultConfigId)); + configs.put(BuiltinStructures.DESERT_PYRAMID.location(), getConfigDesertPyramid(defaultConfigId)); + configs.put(BuiltinStructures.END_CITY.location(), getConfigEndCity(defaultConfigId)); + configs.put(BuiltinStructures.FORTRESS.location(), getConfigFortress(defaultConfigId)); + configs.put(BuiltinStructures.JUNGLE_TEMPLE.location(), getConfigJungleTemple(defaultConfigId)); + configs.put(BuiltinStructures.OCEAN_MONUMENT.location(), getConfigOceanMonument(defaultConfigId)); + + var oceanRuinId = prefix("ocean_ruins"); + configs.put(oceanRuinId, + LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build() ); + configs.put(BuiltinStructures.OCEAN_RUIN_COLD.location(), getConfigOceanRuinCold(oceanRuinId)); + configs.put(BuiltinStructures.OCEAN_RUIN_WARM.location(), getConfigOceanRuinWarm(oceanRuinId)); - ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; - configs.put(defaultConfigId, LooniumStructureConfiguration.builder() + configs.put(BuiltinStructures.PILLAGER_OUTPOST.location(), getConfigPillagerOutpost(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_DESERT.location(), getConfigRuinedPortalDesert(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_JUNGLE.location(), getConfigRuinedPortalJungle(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_MOUNTAIN.location(), getConfigRuinedPortalMountain(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_NETHER.location(), getConfigRuinedPortalNether(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_OCEAN.location(), getConfigRuinedPortalOcean(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_STANDARD.location(), getConfigRuinedPortalStandard(defaultConfigId)); + configs.put(BuiltinStructures.RUINED_PORTAL_SWAMP.location(), getConfigRuinedPortalSwamp(defaultConfigId)); + + configs.put(BuiltinStructures.SHIPWRECK.location(), getConfigShipwreck(defaultConfigId)); + configs.put(BuiltinStructures.SHIPWRECK_BEACHED.location(), + LooniumStructureConfiguration.forParent(BuiltinStructures.SHIPWRECK.location()).build()); + + configs.put(BuiltinStructures.STRONGHOLD.location(), getConfigStronghold(defaultConfigId)); + configs.put(BuiltinStructures.TRAIL_RUINS.location(), getConfigTrailRuins(defaultConfigId)); + + var villageId = prefix("village"); + configs.put(villageId, LooniumStructureConfiguration.forParent(defaultConfigId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build() + ); + configs.put(BuiltinStructures.VILLAGE_DESERT.location(), getConfigVillageDesert(villageId)); + configs.put(BuiltinStructures.VILLAGE_PLAINS.location(), getConfigVillagePlains(villageId)); + configs.put(BuiltinStructures.VILLAGE_SAVANNA.location(), getConfigVillageSavanna(villageId)); + configs.put(BuiltinStructures.VILLAGE_SNOWY.location(), getConfigVillageSnowy(villageId)); + configs.put(BuiltinStructures.VILLAGE_TAIGA.location(), getConfigVillageTaiga(villageId)); + + configs.put(BuiltinStructures.WOODLAND_MANSION.location(), getConfigWoodlandMansion(defaultConfigId)); + + var output = new ArrayList>(configs.size()); + for (var e : configs.entrySet()) { + Path path = pathProvider.json(e.getKey()); + var config = e.getValue(); + var jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) + .getOrThrow(false, BotaniaAPI.LOGGER::error); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + private static LooniumStructureConfiguration getDefaultConfig() { + return LooniumStructureConfiguration.builder() .manaCost(LooniumBlockEntity.DEFAULT_COST) .maxNearbyMobs(LooniumBlockEntity.DEFAULT_MAX_NEARBY_MOBS) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.PIECE) .spawnedMobs( // weights roughly based on original Loonium mob selection logic LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), - getCreeperSpawnData(effectsToApplyToCreepers, 195, false), - getCreeperSpawnData(effectsToApplyToCreepers, 1, true), - LooniumMobSpawnData.entityWeight(EntityType.HUSK, 59).build(), - LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 106).build(), - LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423).build(), - LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59).build(), - LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() ) .attributeModifiers( - new LooniumMobAttributeModifier("Loonium Modififer Health", + new LooniumMobAttributeModifier(LOONIUM_MODIFIER_HEALTH, Attributes.MAX_HEALTH, 2, AttributeModifier.Operation.MULTIPLY_BASE), - new LooniumMobAttributeModifier("Loonium Modififer Damage", + new LooniumMobAttributeModifier(LOONIUM_MODIFIER_DAMAGE, Attributes.ATTACK_DAMAGE, 1.5, AttributeModifier.Operation.MULTIPLY_BASE) - ).effectsToApply( - LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), - LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build() ) - .build()); + .effectsToApply(getStandardEffects(false, true)) + .build(); + } - configs.put(BuiltinStructures.OCEAN_RUIN_COLD.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.OCEAN_RUIN_WARM.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.PILLAGER_OUTPOST.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.VILLAGE_DESERT.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.VILLAGE_PLAINS.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.VILLAGE_SAVANNA.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.VILLAGE_SNOWY.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); - configs.put(BuiltinStructures.VILLAGE_TAIGA.location(), - LooniumStructureConfiguration.forParent(defaultConfigId) - .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build()); + private static LooniumStructureConfiguration getConfigAncientCity(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(99, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_ANCIENT_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 80) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_ANCIENT_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 410) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_ANCIENT_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_ANCIENT_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 440) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_ANCIENT_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 100).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 200).build() + ).build(); + } - var output = new ArrayList>(configs.size()); - for (var e : configs.entrySet()) { - Path path = pathProvider.json(e.getKey()); - var config = e.getValue(); - var jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) - .getOrThrow(false, BotaniaAPI.LOGGER::error); - output.add(DataProvider.saveStable(cache, jsonTree, path)); - } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + private static LooniumStructureConfiguration getConfigBastionRemnant(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(99, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + getPiglinSpawnData(450, BotaniaLootTables.LOONIUM_PIGLIN_BASTION_REMNANT, false, false), + LooniumMobSpawnData.entityWeight(EntityType.PIGLIN_BRUTE, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_AXE_GOLD) + .attributeModifiers( + new LooniumMobAttributeModifier(LOONIUM_MODIFIER_HEALTH, + Attributes.MAX_HEALTH, 1.5, AttributeModifier.Operation.MULTIPLY_BASE), + new LooniumMobAttributeModifier(LOONIUM_MODIFIER_DAMAGE, + Attributes.ATTACK_DAMAGE, 1.5, AttributeModifier.Operation.MULTIPLY_BASE) + ) + .build(), + LooniumMobSpawnData.entityWeight(EntityType.HOGLIN, 300).spawnAsAdult().build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigDesertPyramid(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 50).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 450) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_DESERT_PYRAMID).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_DESERT_PYRAMID).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 500) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_DESERT_PYRAMID).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 40).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 360).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigEndCity(ResourceLocation parentId) { + LooniumMobEffectToApply[] creeperEffects = { + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.SLOW_FALLING).duration(400).build() + }; + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.SHULKER, 100) + .effectsToApply(getStandardEffects(true, true)).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 300).build(), + getCreeperSpawnData(99, false, creeperEffects), + getCreeperSpawnData(1, true, creeperEffects), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 300) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_END_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 300) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_END_CITY).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 300).build() + ).effectsToApply( + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build(), + LooniumMobEffectToApply.effect(MobEffects.SLOW_FALLING).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigFortress(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(99, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.BLAZE, 300) + .effectsToApply(getStandardEffects(false, false)).build(), + LooniumMobSpawnData.entityWeight(EntityType.WITHER_SKELETON, 450) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_FORTRESS) + .effectsToApply(getStandardEffects(false, false)).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_FORTRESS).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 400) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_FORTRESS) + .effectsToApply(getStandardEffects(false, false)).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigJungleTemple(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_JUNGLE_TEMPLE).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_JUNGLE_TEMPLE).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 500) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_JUNGLE_TEMPLE).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 300).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 300).build() + ).build(); } - private static LooniumMobSpawnData getCreeperSpawnData( - List effectsToApplyToCreepers, int weight, boolean charged) { + private static LooniumStructureConfiguration getConfigOceanMonument(ResourceLocation parentId) { + var standardEffectsInWater = getStandardEffects(true, true); + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.GUARDIAN, 200).build(), + getCreeperSpawnData(199, false, getCreeperEffects(true)), + getCreeperSpawnData(1, true, getCreeperEffects(true)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 540) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_MONUMENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_MONUMENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_MONUMENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_MONUMENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30) + .effectsToApply(standardEffectsInWater).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270) + .effectsToApply(standardEffectsInWater).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLocation parentId) { + var standardEffectsInWater = getStandardEffects(true, true); + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + getCreeperSpawnData(199, false, getCreeperEffects(true)), + getCreeperSpawnData(1, true, getCreeperEffects(true)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 540) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30) + .effectsToApply(standardEffectsInWater).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270) + .effectsToApply(standardEffectsInWater).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigOceanRuinWarm(ResourceLocation parentId) { + var standardEffectsInWater = getStandardEffects(true, true); + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + getCreeperSpawnData(199, false, getCreeperEffects(true)), + getCreeperSpawnData(1, true, getCreeperEffects(true)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 540) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 400) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30) + .effectsToApply(standardEffectsInWater).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270) + .effectsToApply(standardEffectsInWater).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigPillagerOutpost(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId) + .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(199, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.PILLAGER, 900) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_CROSSBOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.VINDICATOR, 175) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_AXE).build(), + LooniumMobSpawnData.entityWeight(EntityType.EVOKER, 25).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 200) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_OUTPOST).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 200) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_OUTPOST).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 200).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalDesert(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 50).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 450) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 450) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 360).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalJungle(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 500) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 250).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 50).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalMountain(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SILVERFISH, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalNether(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 125) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(500, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, false), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 450) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 200) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 10).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 90).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalOcean(ResourceLocation parentId) { + var standardEffectsInWater = getStandardEffects(true, true); + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, true, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + getCreeperSpawnData(199, false, getCreeperEffects(true)), + getCreeperSpawnData(1, true, getCreeperEffects(true)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 540) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 400) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30) + .effectsToApply(standardEffectsInWater).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270) + .effectsToApply(standardEffectsInWater).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalStandard(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigRuinedPortalSwamp(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) + .effectsToApply(getStandardEffects(false, false)).build(), + getPiglinSpawnData(50, BotaniaLootTables.LOONIUM_PIGLIN_PORTAL, false, true), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIFIED_PIGLIN, 50) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 500) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_PORTAL).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 50).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 250).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigShipwreck(ResourceLocation parentId) { + var standardEffectsInWater = getStandardEffects(true, true); + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + getCreeperSpawnData(199, false, getCreeperEffects(true)), + getCreeperSpawnData(1, true, getCreeperEffects(true)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 540) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_SHIPWRECK).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_SHIPWRECK).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_SHIPWRECK).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 360) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_SHIPWRECK).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30) + .effectsToApply(standardEffectsInWater).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270) + .effectsToApply(standardEffectsInWater).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigStronghold(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 80).build(), + getCreeperSpawnData(149, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_STRONGHOLD).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 40) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_STRONGHOLD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 410) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_STRONGHOLD).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 60) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_STRONGHOLD).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 440) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_STRONGHOLD).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 100).build(), + LooniumMobSpawnData.entityWeight(EntityType.SILVERFISH, 100).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 400).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigTrailRuins(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_TRAIL_RUINS).build(), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_DROWNED_TRAIL_RUINS).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_ZOMBIE_TRAIL_RUINS).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_TRAIL_RUINS).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_SKELETON_TRAIL_RUINS).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigVillageDesert(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE_VILLAGER, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 600) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigVillagePlains(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE_VILLAGER, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 600) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigVillageSavanna(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 30) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.HUSK, 30) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE_VILLAGER, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 600) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigVillageSnowy(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE_VILLAGER, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 529) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigVillageTaiga(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(195, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.DROWNED, 59) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_TRIDENT).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_SWORD).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE_VILLAGER, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BY_PROFESSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.STRAY, 106) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 423) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_BOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 59).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 529).build() + ).build(); + } + + private static LooniumStructureConfiguration getConfigWoodlandMansion(ResourceLocation parentId) { + return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( + LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), + getCreeperSpawnData(199, false, getCreeperEffects(false)), + getCreeperSpawnData(1, true, getCreeperEffects(false)), + LooniumMobSpawnData.entityWeight(EntityType.VINDICATOR, 600) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_AXE).build(), + LooniumMobSpawnData.entityWeight(EntityType.PILLAGER, 200) + .equipmentTable(BotaniaLootTables.LOONIUM_WEAPON_CROSSBOW).build(), + LooniumMobSpawnData.entityWeight(EntityType.EVOKER, 100).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 150) + .equipmentTable(BotaniaLootTables.LOONIUM_ARMOR_MANSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 50).spawnAsBaby() + .equipmentTable(BotaniaLootTables.LOONIUM_ARMOR_MANSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.SKELETON, 200) + .equipmentTable(BotaniaLootTables.LOONIUM_ARMOR_MANSION).build(), + LooniumMobSpawnData.entityWeight(EntityType.CAVE_SPIDER, 30).build(), + LooniumMobSpawnData.entityWeight(EntityType.SPIDER, 270).build() + ).build(); + } + + private static LooniumMobEffectToApply[] getStandardEffects(boolean withWaterBreathing, boolean withFireResistance) { + return withFireResistance + ? (withWaterBreathing + ? new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build(), + LooniumMobEffectToApply.effect(MobEffects.WATER_BREATHING).build() + } + : new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build() + }) + : (withWaterBreathing + ? new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build(), + LooniumMobEffectToApply.effect(MobEffects.WATER_BREATHING).build() + } + : new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).build() + }); + } + + private static LooniumMobEffectToApply[] getCreeperEffects(boolean withWaterBreathing) { + return withWaterBreathing + ? new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.WATER_BREATHING).build() + } + : new LooniumMobEffectToApply[] { + LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), + LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build() + }; + } + + private static LooniumMobSpawnData getCreeperSpawnData(int weight, boolean charged, + LooniumMobEffectToApply... creeperEffects) { CompoundTag chargedCreeperNbt; if (charged) { chargedCreeperNbt = new CompoundTag(); @@ -124,8 +709,34 @@ private static LooniumMobSpawnData getCreeperSpawnData( } return LooniumMobSpawnData.entityWeight(EntityType.CREEPER, weight) - .setNbt(chargedCreeperNbt) - .setEffectsToApply(effectsToApplyToCreepers).build(); + .nbt(chargedCreeperNbt) + .effectsToApply(creeperEffects) + .build(); + } + + private static LooniumMobSpawnData getPiglinSpawnData(int weight, ResourceLocation equipmentTable, + boolean needWaterBreathing, boolean zombificationImmune) { + CompoundTag piglinNbt = new CompoundTag(); + if (zombificationImmune) { + piglinNbt.putBoolean("IsImmuneToZombification", true); + } + + var piglinBrain = Brain.provider(List.of(MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.ADMIRING_DISABLED, + MemoryModuleType.ATE_RECENTLY), List.of()) + .makeBrain(new Dynamic<>(NbtOps.INSTANCE)); + piglinBrain.setMemory(MemoryModuleType.UNIVERSAL_ANGER, true); + piglinBrain.setMemory(MemoryModuleType.ADMIRING_DISABLED, true); + piglinBrain.setMemory(MemoryModuleType.ATE_RECENTLY, true); + + DataResult dataResult = piglinBrain.serializeStart(NbtOps.INSTANCE); + dataResult.resultOrPartial(BotaniaAPI.LOGGER::error).ifPresent(tag -> piglinNbt.put("Brain", tag)); + + return LooniumMobSpawnData.entityWeight(EntityType.PIGLIN, weight) + .spawnAsAdult() + .nbt(piglinNbt) + .equipmentTable(equipmentTable) + .effectsToApply(getStandardEffects(needWaterBreathing, true)) + .build(); } @NotNull From ef7086b806db8edc486d953556e36fd529563067 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Fri, 24 May 2024 23:31:55 +0200 Subject: [PATCH 17/26] Fix spawned mobs suffocating and add spawn effect to flower --- .../flower/functional/LooniumBlockEntity.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index bf7c28c0dd..eedff3cc4d 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -21,6 +21,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.Difficulty; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; @@ -29,6 +30,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TieredItem; import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.block.LevelEvent; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.levelgen.structure.Structure; @@ -156,23 +158,17 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, return; } - int bound = RANGE * 2 + 1; - int xp = getEffectivePos().getX() - RANGE + world.random.nextInt(bound); - int yp = getEffectivePos().getY(); - int zp = getEffectivePos().getZ() - RANGE + world.random.nextInt(bound); + RandomSource random = world.random; + double x = getEffectivePos().getX() + 0.5 - RANGE + 2 * RANGE * random.nextDouble(); + double y = getEffectivePos().getY(); + double z = getEffectivePos().getZ() + 0.5 - RANGE + 2 * RANGE * random.nextDouble(); - BlockPos pos = new BlockPos(xp, yp - 1, zp); - do { - pos = pos.above(); - if (pos.getY() >= world.getMaxBuildHeight()) { + while (!world.noCollision(pickedMobType.type.getAABB(x, y, z))) { + y += 1.0; + if (y >= world.getMaxBuildHeight()) { return; } - } while (world.getBlockState(pos).isSuffocating(world, pos)); - pos = pos.above(); - - double x = pos.getX() + Math.random(); - double y = pos.getY() + Math.random(); - double z = pos.getZ() + Math.random(); + } Entity entity = pickedMobType.type.create(world); if (!(entity instanceof Mob mob)) { @@ -186,7 +182,7 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, mob.setBaby(pickedMobType.spawnAsBaby); } - mob.absMoveTo(x, y, z, world.random.nextFloat() * 360F, 0); + mob.absMoveTo(x, y, z, random.nextFloat() * 360F, 0); mob.setDeltaMovement(Vec3.ZERO); applyAttributesAndEffects(pickedMobType, pickedConfig, mob); @@ -197,7 +193,7 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, looniumComponent.setSlowDespawn(true); } - mob.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.SPAWNER, null, null); + mob.finalizeSpawn(world, world.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.SPAWNER, null, null); if (Boolean.FALSE.equals(pickedMobType.spawnAsBaby) && mob.isBaby()) { // Note: might have already affected initial equipment/attribute selection, or even caused a special // mob configuration (such as chicken jockey) to spawn, which may look weird when reverting to adult. @@ -275,6 +271,7 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, } mob.spawnAnim(); + world.levelEvent(LevelEvent.PARTICLES_MOBBLOCK_SPAWN, getBlockPos(), 0); world.gameEvent(mob, GameEvent.ENTITY_PLACE, mob.position()); addMana(-DEFAULT_COST); From 9406d9b0695101db3afa9eb648810781d43751e8 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Fri, 24 May 2024 23:44:44 +0200 Subject: [PATCH 18/26] Actually consume the configured amount of mana --- .../api/configdata/LooniumStructureConfiguration.java | 5 +++++ .../common/block/flower/functional/LooniumBlockEntity.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 6336fbbe6c..38b5f5e97a 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import java.util.List; import java.util.Optional; @@ -46,6 +47,10 @@ public class LooniumStructureConfiguration { if (lsc.spawnedMobs != null && lsc.spawnedMobs.isEmpty()) { return DataResult.error(() -> "Spawned mobs cannot be empty"); } + if (lsc.manaCost != null && lsc.manaCost > LooniumBlockEntity.DEFAULT_COST) { + return DataResult.error(() -> "Mana costs above %d are currently not supported" + .formatted(LooniumBlockEntity.DEFAULT_COST)); + } return DataResult.success(lsc); }); public static final ResourceLocation DEFAULT_CONFIG_ID = new ResourceLocation(BotaniaAPI.MODID, "default"); diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index eedff3cc4d..2be8058b53 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -274,7 +274,7 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, world.levelEvent(LevelEvent.PARTICLES_MOBBLOCK_SPAWN, getBlockPos(), 0); world.gameEvent(mob, GameEvent.ENTITY_PLACE, mob.position()); - addMana(-DEFAULT_COST); + addMana(-pickedConfig.manaCost); sync(); } From 01330e182f3c327f5981a33fc0708b02309ddc0c Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Thu, 30 May 2024 20:09:16 +0200 Subject: [PATCH 19/26] Loonium mobs are on a team and grant an advancement - mobs are spawned on a unique team, which means even Loonium-spawned zoglins don't attack other Loonium-spawned mobs - new challenge advancement "King" requires killing each of the currently 22 different mobs the Loonium spawns in different structures --- .../ca0b139d7ffbdcad7e28a9e04c29c4ff458197e3 | 1 + .../challenge/all_loonium_mobs.json | 419 ++++++++++++++++++ .../flower/functional/LooniumBlockEntity.java | 60 +++ .../botania/data/AdvancementProvider.java | 44 ++ .../vazkii/botania/mixin/EntityMixin.java | 17 + .../resources/assets/botania/lang/en_us.json | 2 + Xplat/src/main/resources/omake.md | 3 +- 7 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 Xplat/src/generated/resources/data/botania/advancements/challenge/all_loonium_mobs.json diff --git a/Xplat/src/generated/resources/.cache/ca0b139d7ffbdcad7e28a9e04c29c4ff458197e3 b/Xplat/src/generated/resources/.cache/ca0b139d7ffbdcad7e28a9e04c29c4ff458197e3 index 16d6fc7b70..80d12c9ca4 100644 --- a/Xplat/src/generated/resources/.cache/ca0b139d7ffbdcad7e28a9e04c29c4ff458197e3 +++ b/Xplat/src/generated/resources/.cache/ca0b139d7ffbdcad7e28a9e04c29c4ff458197e3 @@ -1,5 +1,6 @@ // 1.20.1 Botania/Advancements ab08543643f1a531a05c7a8c557a3ac02791af95 data/botania/advancements/challenge/alf_portal_bread.json +88699a15ceee5f4d6b3da75b7fc8813d6ed7fecc data/botania/advancements/challenge/all_loonium_mobs.json 79ad7a7e7ea785cf536ec8396e1e11673650954b data/botania/advancements/challenge/flugel_eye.json 3e969f922b4184577d256b2c5e197c5dc8a50c4f data/botania/advancements/challenge/gaia_guardian_hardmode.json 90ca240ce76ccf798cf0fc68ba99c1623ed44af0 data/botania/advancements/challenge/gaia_guardian_no_armor.json diff --git a/Xplat/src/generated/resources/data/botania/advancements/challenge/all_loonium_mobs.json b/Xplat/src/generated/resources/data/botania/advancements/challenge/all_loonium_mobs.json new file mode 100644 index 0000000000..d15af8121b --- /dev/null +++ b/Xplat/src/generated/resources/data/botania/advancements/challenge/all_loonium_mobs.json @@ -0,0 +1,419 @@ +{ + "parent": "botania:challenge/root", + "criteria": { + "minecraft:blaze": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:blaze", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:cave_spider": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:cave_spider", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:creeper": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:creeper", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:drowned": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:drowned", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:enderman": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:enderman", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:evoker": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:evoker", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:guardian": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:guardian", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:hoglin": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:hoglin", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:husk": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:husk", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:piglin": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:piglin", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:piglin_brute": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:piglin_brute", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:pillager": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:pillager", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:shulker": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:shulker", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:silverfish": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:silverfish", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:skeleton": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:skeleton", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:stray": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:stray", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:vindicator": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:vindicator", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:wither_skeleton": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:wither_skeleton", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:zoglin": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:zoglin", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:zombie": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:zombie", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:zombie_villager": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:zombie_villager", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + }, + "minecraft:zombified_piglin": { + "conditions": { + "entity": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:zombified_piglin", + "team": "Loonium Monsters" + } + } + ] + }, + "trigger": "minecraft:player_killed_entity" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "translate": "advancement.botania:allLooniumMobs.desc" + }, + "frame": "challenge", + "hidden": false, + "icon": { + "item": "botania:loonium" + }, + "show_toast": true, + "title": { + "translate": "advancement.botania:allLooniumMobs" + } + }, + "requirements": [ + [ + "minecraft:blaze" + ], + [ + "minecraft:cave_spider" + ], + [ + "minecraft:creeper" + ], + [ + "minecraft:drowned" + ], + [ + "minecraft:enderman" + ], + [ + "minecraft:evoker" + ], + [ + "minecraft:guardian" + ], + [ + "minecraft:hoglin" + ], + [ + "minecraft:husk" + ], + [ + "minecraft:piglin" + ], + [ + "minecraft:piglin_brute" + ], + [ + "minecraft:pillager" + ], + [ + "minecraft:shulker" + ], + [ + "minecraft:silverfish" + ], + [ + "minecraft:skeleton" + ], + [ + "minecraft:stray" + ], + [ + "minecraft:vindicator" + ], + [ + "minecraft:wither_skeleton" + ], + [ + "minecraft:zoglin" + ], + [ + "minecraft:zombie_villager" + ], + [ + "minecraft:zombie" + ], + [ + "minecraft:zombified_piglin" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 2be8058b53..d03fb224c1 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -13,12 +13,15 @@ import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.objects.*; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; @@ -42,6 +45,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import net.minecraft.world.scores.Team; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -89,6 +93,62 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { ) .build()); + // this should never collide with the /team command, since space is not allowed in scoreboard team names + public static final String LOONIUM_TEAM_NAME = "Loonium Monsters"; + public static final Team LOONIUM_TEAM = new Team() { + @NotNull + @Override + public String getName() { + return LOONIUM_TEAM_NAME; + } + + @NotNull + @Override + public MutableComponent getFormattedName(Component component) { + return component.copy(); + } + + @Override + public boolean canSeeFriendlyInvisibles() { + return true; + } + + @Override + public boolean isAllowFriendlyFire() { + return true; + } + + @NotNull + @Override + public Visibility getNameTagVisibility() { + return Visibility.ALWAYS; + } + + @NotNull + @Override + public ChatFormatting getColor() { + return ChatFormatting.RESET; + } + + @NotNull + @Override + public Collection getPlayers() { + return List.of(); + } + + @NotNull + @Override + public Visibility getDeathMessageVisibility() { + return Visibility.ALWAYS; + } + + @NotNull + @Override + public CollisionRule getCollisionRule() { + return CollisionRule.ALWAYS; + } + }; + @Nullable private ResourceLocation lootTableOverride; @Nullable diff --git a/Xplat/src/main/java/vazkii/botania/data/AdvancementProvider.java b/Xplat/src/main/java/vazkii/botania/data/AdvancementProvider.java index f80f07f5e2..d92204403e 100644 --- a/Xplat/src/main/java/vazkii/botania/data/AdvancementProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/AdvancementProvider.java @@ -18,6 +18,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -28,6 +29,7 @@ import vazkii.botania.common.block.BotaniaBlocks; import vazkii.botania.common.block.BotaniaFlowerBlocks; import vazkii.botania.common.block.block_entity.corporea.CorporeaIndexBlockEntity; +import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import vazkii.botania.common.entity.BotaniaEntities; import vazkii.botania.common.item.BotaniaItems; import vazkii.botania.common.item.LexicaBotaniaItem; @@ -320,6 +322,31 @@ public void generate(HolderLookup.Provider lookup, Consumer consume public static class BotaniaChallengeAdvancements implements AdvancementSubProvider { + private static final EntityType[] LOONIUM_MOBS_TO_KILL = { + EntityType.BLAZE, + EntityType.CAVE_SPIDER, + EntityType.CREEPER, + EntityType.DROWNED, + EntityType.ENDERMAN, + EntityType.EVOKER, + EntityType.GUARDIAN, + EntityType.HOGLIN, + EntityType.HUSK, + EntityType.PIGLIN, + EntityType.PIGLIN_BRUTE, + EntityType.PILLAGER, + EntityType.SHULKER, + EntityType.SILVERFISH, + EntityType.SKELETON, + EntityType.STRAY, + EntityType.VINDICATOR, + EntityType.WITHER_SKELETON, + EntityType.ZOGLIN, + EntityType.ZOMBIE_VILLAGER, + EntityType.ZOMBIE, + EntityType.ZOMBIFIED_PIGLIN + }; + @Override public void generate(HolderLookup.Provider lookup, Consumer consumer) { Advancement root = Advancement.Builder.advancement() @@ -413,6 +440,23 @@ ContextAwarePredicate.ANY, matchItems(BotaniaItems.pinkinator), LocationPredicat .rewards(AdvancementRewards.Builder.experience(40)) .addCriterion("code_triggered", new ImpossibleTrigger.TriggerInstance()) .save(consumer, challengeId("tiny_potato_birthday")); + addLooniumMobsToKill(Advancement.Builder.advancement()) + .display(simple(BotaniaFlowerBlocks.loonium, "allLooniumMobs", FrameType.CHALLENGE)) + .parent(root) + .requirements(RequirementsStrategy.AND) + .save(consumer, challengeId("all_loonium_mobs")); + } + + private static Advancement.Builder addLooniumMobsToKill(Advancement.Builder builder) { + for (EntityType entityType : LOONIUM_MOBS_TO_KILL) { + builder.addCriterion( + BuiltInRegistries.ENTITY_TYPE.getKey(entityType).toString(), + KilledTrigger.TriggerInstance.playerKilledEntity(EntityPredicate.Builder.entity() + .of(entityType).team(LooniumBlockEntity.LOONIUM_TEAM_NAME)) + ); + } + + return builder; } } diff --git a/Xplat/src/main/java/vazkii/botania/mixin/EntityMixin.java b/Xplat/src/main/java/vazkii/botania/mixin/EntityMixin.java index 1c7cf770cb..0465a5a039 100644 --- a/Xplat/src/main/java/vazkii/botania/mixin/EntityMixin.java +++ b/Xplat/src/main/java/vazkii/botania/mixin/EntityMixin.java @@ -12,6 +12,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.scores.Team; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -20,9 +22,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import vazkii.botania.common.BotaniaDamageTypes; +import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import vazkii.botania.common.item.EquestrianVirusItem; import vazkii.botania.common.item.equipment.bauble.CrimsonPendantItem; import vazkii.botania.common.lib.BotaniaTags; +import vazkii.botania.xplat.XplatAbstractions; @Mixin(Entity.class) public abstract class EntityMixin { @@ -49,4 +53,17 @@ private void checkInvulnerabilities(DamageSource source, CallbackInfoReturnable< } } + /** + * Puts Loonium-spawned mobs on their own team. + * This is used both for easier identification in advancements and to prevent in-fighting. + */ + @Inject(at = @At("HEAD"), method = "getTeam", cancellable = true) + private void getLooniumTeam(CallbackInfoReturnable cir) { + if (((Object) this) instanceof Mob self) { + var looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(self); + if (looniumComponent != null && looniumComponent.isSlowDespawn() && !looniumComponent.getDrop().isEmpty()) { + cir.setReturnValue(LooniumBlockEntity.LOONIUM_TEAM); + } + } + } } diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index 38e0b28571..f0f55df8ea 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -544,6 +544,8 @@ "advancement.botania:tinyPotatoBirthday": "Blessing", "advancement.botania:tinyPotatoBirthday.desc": "Celebrate Tiny Potato's Birthday on July 19th", + "advancement.botania:allLooniumMobs": "King", + "advancement.botania:allLooniumMobs.desc": "Kill one of every Loonium-spawned monster", "botania.challengelevel.easy": "Easy", "botania.challengelevel.normal": "Normal", diff --git a/Xplat/src/main/resources/omake.md b/Xplat/src/main/resources/omake.md index 6d71abfa25..3ba0deb02d 100644 --- a/Xplat/src/main/resources/omake.md +++ b/Xplat/src/main/resources/omake.md @@ -1207,11 +1207,12 @@ WARNING: Some songs are 18+ and inappropriate for children. | Hand in Hand | Place >255 extra blocks at once with Loki Ring | [https://vocadb.net/S/89726](https://vocadb.net/S/89726) | | Innocentia | Obtain Fruit of Grisaia | [https://vocadb.net/S/13385](https://vocadb.net/S/13385) | | One Step Layered | Obtain Thor Ring | [https://vocadb.net/S/365](https://vocadb.net/S/365) | -| Angel of Death | Obtain Flugel Eye | [https://vocadb.net/S/28559](https://vocadb.net/S/28559) | +| Angel of Death | Obtain Flügel Eye | [https://vocadb.net/S/28559](https://vocadb.net/S/28559) | | A Fake, Fake Psychotropic | Obtain King Key | [https://vocadb.net/S/37948](https://vocadb.net/S/37948) | | Lost Time Memory | Obtain Odin Ring | [https://vocadb.net/S/25896](https://vocadb.net/S/25896) | | Decorator | Use Pinkinator | [https://vocadb.net/S/45245](https://vocadb.net/S/45245) | | Blessing | Wish Tiny Potato happy birthday | [https://vocadb.net/S/50703](https://vocadb.net/S/50703) | +| King | Kill one of every Loonium-spawned monster | [https://vocadb.net/S/290384](https://vocadb.net/S/290384) | ## Favorites Hm? You want to know my favorites? From 8387d1bebd59256b4fb0f4de2fb11324f2c8ad69 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Mon, 17 Jun 2024 08:41:39 +0200 Subject: [PATCH 20/26] Hint at Loonium item exclusion list in lexicon description --- Xplat/src/main/resources/assets/botania/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index f0f55df8ea..dc588a37df 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -2379,7 +2379,7 @@ "botania.entry.loonium": "Loonium", "botania.tagline.loonium": "Conjures dungeon loot", "botania.page.loonium0": "Any adventurer knows that the great structures of the world can hold valuable goodies. The $(item)Loonium$(0) will, when fed quite a bit of $(thing)Mana$(0), summon these items for said adventurers to collect.$(p)There's a catch, though: each item is held by a monster protecting it. These monsters are extra-strong, but will drop valuable loot when killed.", - "botania.page.looniumStructures": "Ordinarily the Loonium will summon treasure of the sort you would find in a $(thing)Dungeon$(0). However, the Loonium is sensitive to the large structures you can find in the world; if planted in one such structure, it'll instead summon treasure appropriate for its surroundings.", + "botania.page.looniumStructures": "Ordinarily the Loonium will summon treasure of the sort you would find in a $(thing)Dungeon$(0). However, the Loonium is sensitive to the large structures you can find in the world; if planted in one such structure, it'll instead summon treasure appropriate for its surroundings.$(p)It seems the Loonium is a bit picky, though-- there may be some items that never drop from the monsters it spawns.", "botania.page.loonium1": "$(o)I CAN HAZ PHAT LOOTZ$()?", "botania.entry.daffomill": "Daffomill", From b525e0d48bb9420e4449bf20cb7cf29c0bee79f2 Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Sun, 18 Aug 2024 11:03:16 +0200 Subject: [PATCH 21/26] Code style improvements and review findings - var -> explicit type, unless it's obvious from a constructor call - extracted API interface for ConfigDataManager - replace "drop nothing" flag in LooniumComponent with "override drop"; mobs will drop whatever is defined as "to drop" when that flag is set - don't bother creating specialized map types for detected structures - adjust variable names in renderHUD code - replaced some manually validated attribute CODECs with corresponding predefined ExtraCodecs variants - allow configured mana cost for a structure to be zero - add default translation for botania:loonium_offhand_equipment tag --- .../fabric/FabricCommonInitializer.java | 4 +- .../botania/forge/ForgeCommonInitializer.java | 4 +- .../java/vazkii/botania/api/BotaniaAPI.java | 2 +- .../api/configdata/ConfigDataManager.java | 11 ++ .../configdata/LooniumMobEffectToApply.java | 7 +- .../LooniumStructureConfiguration.java | 9 +- .../flower/functional/LooniumBlockEntity.java | 118 ++++++++---------- ...anager.java => ConfigDataManagerImpl.java} | 18 +-- .../botania/common/impl/BotaniaAPIImpl.java | 5 +- .../internal_caps/LooniumComponent.java | 39 +++--- .../data/LooniumEquipmentLootProvider.java | 49 ++++---- ...LooniumStructureConfigurationProvider.java | 33 ++--- .../data/LooniumStructureLootProvider.java | 6 +- .../resources/assets/botania/lang/en_us.json | 1 + 14 files changed, 151 insertions(+), 155 deletions(-) create mode 100644 Xplat/src/main/java/vazkii/botania/api/configdata/ConfigDataManager.java rename Xplat/src/main/java/vazkii/botania/common/config/{ConfigDataManager.java => ConfigDataManagerImpl.java} (88%) diff --git a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java index dd003159ec..2d41c79736 100644 --- a/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java +++ b/Fabric/src/main/java/vazkii/botania/fabric/FabricCommonInitializer.java @@ -81,7 +81,7 @@ import vazkii.botania.common.brew.BotaniaBrews; import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.command.SkyblockCommand; -import vazkii.botania.common.config.ConfigDataManager; +import vazkii.botania.common.config.ConfigDataManagerImpl; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.entity.BotaniaEntities; import vazkii.botania.common.entity.GaiaGuardianEntity; @@ -139,7 +139,7 @@ public void onInitialize() { PatchouliAPI.get().registerMultiblock(prefix("gaia_ritual"), GaiaGuardianEntity.ARENA_MULTIBLOCK.get()); OrechidManager.registerListener(); - ConfigDataManager.registerListener(); + ConfigDataManagerImpl.registerListener(); CraftyCrateBlockEntity.registerListener(); CorporeaNodeDetectors.register(new FabricTransferCorporeaNodeDetector()); diff --git a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java index 4a9369669b..46ec6f3ec6 100644 --- a/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java +++ b/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java @@ -94,7 +94,7 @@ import vazkii.botania.common.brew.BotaniaMobEffects; import vazkii.botania.common.brew.effect.SoulCrossMobEffect; import vazkii.botania.common.command.SkyblockCommand; -import vazkii.botania.common.config.ConfigDataManager; +import vazkii.botania.common.config.ConfigDataManagerImpl; import vazkii.botania.common.crafting.BotaniaRecipeTypes; import vazkii.botania.common.entity.BotaniaEntities; import vazkii.botania.common.entity.GaiaGuardianEntity; @@ -167,7 +167,7 @@ public void commonSetup(FMLCommonSetupEvent evt) { PatchouliAPI.get().registerMultiblock(prefix("gaia_ritual"), GaiaGuardianEntity.ARENA_MULTIBLOCK.get()); OrechidManager.registerListener(); - ConfigDataManager.registerListener(); + ConfigDataManagerImpl.registerListener(); CraftyCrateBlockEntity.registerListener(); CorporeaNodeDetectors.register(new ForgeCapCorporeaNodeDetector()); if (ModList.get().isLoaded("inventorysorter")) { diff --git a/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java b/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java index 1add27eefb..bd89587840 100644 --- a/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java +++ b/Xplat/src/main/java/vazkii/botania/api/BotaniaAPI.java @@ -30,10 +30,10 @@ import org.slf4j.LoggerFactory; import vazkii.botania.api.brew.Brew; +import vazkii.botania.api.configdata.ConfigDataManager; import vazkii.botania.api.corporea.CorporeaNodeDetector; import vazkii.botania.api.internal.DummyManaNetwork; import vazkii.botania.api.internal.ManaNetwork; -import vazkii.botania.common.config.ConfigDataManager; import java.util.Collections; import java.util.Map; diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/ConfigDataManager.java b/Xplat/src/main/java/vazkii/botania/api/configdata/ConfigDataManager.java new file mode 100644 index 0000000000..af430685e8 --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/ConfigDataManager.java @@ -0,0 +1,11 @@ +package vazkii.botania.api.configdata; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.PreparableReloadListener; + +import org.jetbrains.annotations.Nullable; + +public interface ConfigDataManager extends PreparableReloadListener { + @Nullable + LooniumStructureConfiguration getEffectiveLooniumStructureConfiguration(ResourceLocation id); +} diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java index a9fb492b79..cc5e9c118f 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumMobEffectToApply.java @@ -1,7 +1,6 @@ package vazkii.botania.api.configdata; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.registries.BuiltInRegistries; @@ -17,11 +16,7 @@ public class LooniumMobEffectToApply { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( BuiltInRegistries.MOB_EFFECT.byNameCodec().fieldOf("effect").forGetter(me -> me.effect), - ExtraCodecs.validate(Codec.INT, - duration -> duration > 0 - ? DataResult.success(duration) - : DataResult.error(() -> "Invalid effect duration")) - .optionalFieldOf("duration", MobEffectInstance.INFINITE_DURATION) + ExtraCodecs.POSITIVE_INT.optionalFieldOf("duration", MobEffectInstance.INFINITE_DURATION) .forGetter(me -> me.duration), Codec.intRange(0, 255).optionalFieldOf("amplifier", 0) .forGetter(me -> me.amplifier) diff --git a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java index 38b5f5e97a..22235279ff 100644 --- a/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java +++ b/Xplat/src/main/java/vazkii/botania/api/configdata/LooniumStructureConfiguration.java @@ -11,19 +11,20 @@ import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; import vazkii.botania.api.BotaniaAPI; -import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import java.util.List; import java.util.Optional; import java.util.function.Function; public class LooniumStructureConfiguration { + public static final int DEFAULT_COST = 35000; + public static final int DEFAULT_MAX_NEARBY_MOBS = 10; public static final Codec CODEC = ExtraCodecs.validate( RecordCodecBuilder.create( instance -> instance.group( ResourceLocation.CODEC.optionalFieldOf("parent") .forGetter(lsc -> Optional.ofNullable(lsc.parent)), - ExtraCodecs.POSITIVE_INT.optionalFieldOf("manaCost") + ExtraCodecs.NON_NEGATIVE_INT.optionalFieldOf("manaCost") .forGetter(lsc -> Optional.ofNullable(lsc.manaCost)), ExtraCodecs.POSITIVE_INT.optionalFieldOf("maxNearbyMobs") .forGetter(lsc -> Optional.ofNullable(lsc.maxNearbyMobs)), @@ -47,9 +48,9 @@ public class LooniumStructureConfiguration { if (lsc.spawnedMobs != null && lsc.spawnedMobs.isEmpty()) { return DataResult.error(() -> "Spawned mobs cannot be empty"); } - if (lsc.manaCost != null && lsc.manaCost > LooniumBlockEntity.DEFAULT_COST) { + if (lsc.manaCost != null && lsc.manaCost > DEFAULT_COST) { return DataResult.error(() -> "Mana costs above %d are currently not supported" - .formatted(LooniumBlockEntity.DEFAULT_COST)); + .formatted(DEFAULT_COST)); } return DataResult.success(lsc); }); diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index d03fb224c1..1edac5dce4 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -11,6 +11,7 @@ import com.google.common.base.Suppliers; import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.objects.*; import net.minecraft.ChatFormatting; @@ -28,6 +29,7 @@ import net.minecraft.world.Difficulty; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.monster.PatrollingMonster; import net.minecraft.world.item.ItemStack; @@ -38,6 +40,7 @@ import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.levelgen.structure.Structure; import net.minecraft.world.level.levelgen.structure.StructureSpawnOverride; +import net.minecraft.world.level.levelgen.structure.StructureStart; import net.minecraft.world.level.storage.loot.LootDataManager; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; @@ -53,11 +56,12 @@ import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.block_entity.FunctionalFlowerBlockEntity; import vazkii.botania.api.block_entity.RadiusDescriptor; +import vazkii.botania.api.configdata.ConfigDataManager; +import vazkii.botania.api.configdata.LooniumMobAttributeModifier; import vazkii.botania.api.configdata.LooniumMobEffectToApply; import vazkii.botania.api.configdata.LooniumMobSpawnData; import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.common.block.BotaniaFlowerBlocks; -import vazkii.botania.common.config.ConfigDataManager; import vazkii.botania.common.internal_caps.LooniumComponent; import vazkii.botania.common.lib.BotaniaTags; import vazkii.botania.common.loot.BotaniaLootTables; @@ -71,8 +75,6 @@ import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { - public static final int DEFAULT_COST = 35000; - public static final int DEFAULT_MAX_NEARBY_MOBS = 10; private static final int RANGE = 5; private static final int CHECK_RANGE = 9; private static final String TAG_LOOT_TABLE = "lootTable"; @@ -80,8 +82,8 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final String TAG_CONFIG_OVERRIDE = "configOverride"; private static final Supplier FALLBACK_CONFIG = Suppliers.memoize(() -> LooniumStructureConfiguration.builder() - .manaCost(DEFAULT_COST) - .maxNearbyMobs(DEFAULT_MAX_NEARBY_MOBS) + .manaCost(LooniumStructureConfiguration.DEFAULT_COST) + .maxNearbyMobs(LooniumStructureConfiguration.DEFAULT_MAX_NEARBY_MOBS) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.PIECE) .spawnedMobs(LooniumMobSpawnData.entityWeight(EntityType.ZOMBIE, 1).build()) .attributeModifiers() @@ -180,18 +182,18 @@ public void tickFlower() { return; } - var configData = BotaniaAPI.instance().getConfigData(); - var structureConfigs = determineStructureConfigs(configData, detectedStructures); - var lootTables = determineLootTables(world, structureConfigs.keySet()); + ConfigDataManager configData = BotaniaAPI.instance().getConfigData(); + Map structureConfigs = determineStructureConfigs(configData, detectedStructures); + List> lootTables = determineLootTables(world, structureConfigs.keySet()); if (lootTables.isEmpty()) { return; } - var randomPick = lootTables.get(world.random.nextInt(lootTables.size())); - var pickedConfig = structureConfigs.getOrDefault(randomPick.key(), + Pair randomPick = lootTables.get(world.random.nextInt(lootTables.size())); + LooniumStructureConfiguration pickedConfig = structureConfigs.getOrDefault(randomPick.key(), structureConfigs.get(LooniumStructureConfiguration.DEFAULT_CONFIG_ID)); - var pickedLootTable = randomPick.value(); + LootTable pickedLootTable = randomPick.value(); if (getMana() < pickedConfig.manaCost) { return; @@ -202,7 +204,7 @@ public void tickFlower() { return; } - var pickedMobType = pickedConfig.spawnedMobs.getRandom(world.random).orElse(null); + LooniumMobSpawnData pickedMobType = pickedConfig.spawnedMobs.getRandom(world.random).orElse(null); if (pickedMobType == null) { return; } @@ -249,8 +251,9 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, LooniumComponent looniumComponent = XplatAbstractions.INSTANCE.looniumComponent(mob); if (looniumComponent != null) { - looniumComponent.setDrop(lootStack); looniumComponent.setSlowDespawn(true); + looniumComponent.setOverrideDrop(true); + looniumComponent.setDrop(lootStack); } mob.finalizeSpawn(world, world.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.SPAWNER, null, null); @@ -263,14 +266,14 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, if (pickedMobType.equipmentTable != null) { LootTable equipmentTable = world.getServer().getLootData().getLootTable(pickedMobType.equipmentTable); if (equipmentTable != LootTable.EMPTY) { - var lootParams = new LootParams.Builder(world) + LootParams lootParams = new LootParams.Builder(world) .withParameter(LootContextParams.THIS_ENTITY, mob) .withParameter(LootContextParams.ORIGIN, mob.position()) // TODO 1.21: replace with LootContextParamSets.EQUIPMENT .create(LootContextParamSets.SELECTOR); var equippedSlots = new HashSet(); equipmentTable.getRandomItems(lootParams, equipmentStack -> { - var slot = equipmentStack.is(BotaniaTags.Items.LOONIUM_OFFHAND_EQUIPMENT) + EquipmentSlot slot = equipmentStack.is(BotaniaTags.Items.LOONIUM_OFFHAND_EQUIPMENT) ? EquipmentSlot.OFFHAND : LivingEntity.getEquipmentSlotForItem(equipmentStack); if (equippedSlots.contains(slot)) { @@ -303,7 +306,7 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, return; } - var mobType = pickedConfig.spawnedMobs.unwrap().stream() + Optional mobType = pickedConfig.spawnedMobs.unwrap().stream() .filter(mobSpawnData -> mobSpawnData.type.tryCast(otherMob) != null).findFirst(); ItemStack bonusLoot; @@ -317,11 +320,8 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, LooniumComponent otherLooniumComponent = XplatAbstractions.INSTANCE.looniumComponent(otherMob); if (otherLooniumComponent != null) { otherLooniumComponent.setSlowDespawn(true); - if (bonusLoot.isEmpty()) { - otherLooniumComponent.setDropNothing(true); - } else { - otherLooniumComponent.setDrop(bonusLoot); - } + otherLooniumComponent.setOverrideDrop(true); + otherLooniumComponent.setDrop(bonusLoot); } } }); @@ -340,11 +340,11 @@ private void spawnMob(ServerLevel world, LooniumMobSpawnData pickedMobType, private static void applyAttributesAndEffects(LooniumMobSpawnData mobSpawnData, LooniumStructureConfiguration pickedConfig, Mob mob) { - var attributeModifiers = mobSpawnData.attributeModifiers != null + List attributeModifiers = mobSpawnData.attributeModifiers != null ? mobSpawnData.attributeModifiers : pickedConfig.attributeModifiers; - for (var attributeModifier : attributeModifiers) { - var attribute = mob.getAttribute(attributeModifier.attribute); + for (LooniumMobAttributeModifier attributeModifier : attributeModifiers) { + AttributeInstance attribute = mob.getAttribute(attributeModifier.attribute); if (attribute != null) { attribute.addPermanentModifier(attributeModifier.createAttributeModifier()); if (attribute.getAttribute() == Attributes.MAX_HEALTH) { @@ -353,10 +353,10 @@ private static void applyAttributesAndEffects(LooniumMobSpawnData mobSpawnData, } } - var effectsToApply = mobSpawnData.effectsToApply != null + List effectsToApply = mobSpawnData.effectsToApply != null ? mobSpawnData.effectsToApply : pickedConfig.effectsToApply; - for (var effectToApply : effectsToApply) { + for (LooniumMobEffectToApply effectToApply : effectsToApply) { mob.addEffect(effectToApply.createMobEffectInstance()); } } @@ -392,11 +392,11 @@ private List> determineLootTables(ServerLevel lootTables.add(Pair.of(LooniumStructureConfiguration.DEFAULT_CONFIG_ID, lootTable)); } } else { - for (var structureId : structureIds) { + for (ResourceLocation structureId : structureIds) { if (structureId.equals(LooniumStructureConfiguration.DEFAULT_CONFIG_ID)) { continue; } - var lootTableId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); + ResourceLocation lootTableId = prefix("loonium/%s/%s".formatted(structureId.getNamespace(), structureId.getPath())); LootTable lootTable = lootData.getLootTable(lootTableId); if (lootTable != LootTable.EMPTY) { lootTables.add(Pair.of(structureId, lootTable)); @@ -434,12 +434,12 @@ private Map determineStructureC overrideConfig != null ? overrideConfig : getDefaultConfig(configData)); } - var defaultConfig = getDefaultConfig(configData); + LooniumStructureConfiguration defaultConfig = getDefaultConfig(configData); var structureConfigs = new HashMap(); - for (var structureEntry : structures.object2BooleanEntrySet()) { + for (Object2BooleanMap.Entry structureEntry : structures.object2BooleanEntrySet()) { LooniumStructureConfiguration structureSpecificConfig = configData.getEffectiveLooniumStructureConfiguration(structureEntry.getKey()); - var structureConfig = structureSpecificConfig != null ? structureSpecificConfig : defaultConfig; + LooniumStructureConfiguration structureConfig = structureSpecificConfig != null ? structureSpecificConfig : defaultConfig; if (structureConfig != null && (structureEntry.getBooleanValue() || structureConfig.boundingBoxType == StructureSpawnOverride.BoundingBoxType.STRUCTURE)) { structureConfigs.put(structureEntry.getKey(), structureConfig); @@ -451,7 +451,7 @@ private Map determineStructureC } private static LooniumStructureConfiguration getDefaultConfig(ConfigDataManager configData) { - var defaultConfig = configData.getEffectiveLooniumStructureConfiguration( + LooniumStructureConfiguration defaultConfig = configData.getEffectiveLooniumStructureConfiguration( LooniumStructureConfiguration.DEFAULT_CONFIG_ID); return defaultConfig != null ? defaultConfig : FALLBACK_CONFIG.get(); } @@ -461,10 +461,10 @@ private void detectStructure(ServerLevel world) { var structureMap = new Object2BooleanRBTreeMap(); StructureManager structureManager = world.structureManager(); BlockPos pos = getBlockPos(); - var structures = structureManager.getAllStructuresAt(pos); - for (var entry : structures.entrySet()) { + Map structures = structureManager.getAllStructuresAt(pos); + for (Map.Entry entry : structures.entrySet()) { Structure structure = entry.getKey(); - var start = structureManager.getStructureAt(pos, structure); + StructureStart start = structureManager.getStructureAt(pos, structure); if (start.isValid()) { ResourceLocation structureId = world.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(structure); @@ -475,14 +475,7 @@ private void detectStructure(ServerLevel world) { } } - if (structureMap.isEmpty()) { - detectedStructures = Object2BooleanMaps.emptyMap(); - } else if (structureMap.size() == 1) { - var key = structureMap.firstKey(); - detectedStructures = Object2BooleanMaps.singleton(key, structureMap.getBoolean(key)); - } else { - detectedStructures = new Object2BooleanArrayMap<>(structureMap); - } + detectedStructures = new Object2BooleanArrayMap<>(structureMap); setChanged(); sync(); @@ -495,7 +488,7 @@ public int getColor() { @Override public int getMaxMana() { - return DEFAULT_COST; + return LooniumStructureConfiguration.DEFAULT_COST; } @Override @@ -523,26 +516,22 @@ public void readFromPacketNBT(CompoundTag cmp) { configOverride = new ResourceLocation(cmp.getString(TAG_CONFIG_OVERRIDE)); } if (cmp.contains(TAG_DETECTED_STRUCTURE)) { - var rawString = cmp.getString(TAG_DETECTED_STRUCTURE); + String rawString = cmp.getString(TAG_DETECTED_STRUCTURE); if (rawString.isEmpty()) { detectedStructures = Object2BooleanMaps.emptyMap(); } else { - var structureList = Arrays.stream(rawString.split(",")).map(part -> { + List> structureList = Arrays.stream(rawString.split(",")).map(part -> { if (part.contains("|")) { - var components = part.split("\\|", 2); + String[] components = part.split("\\|", 2); return ObjectBooleanPair.of(new ResourceLocation(components[0]), Boolean.parseBoolean(components[1])); } else { return ObjectBooleanPair.of(new ResourceLocation(part), false); } }).toList(); - if (structureList.size() == 1) { - detectedStructures = Object2BooleanMaps.singleton(structureList.get(0).key(), structureList.get(0).valueBoolean()); - } else { - // list should never contain more than a few entries, so array is fine and retains entry order - var map = new Object2BooleanArrayMap(structureList.size()); - structureList.forEach(entry -> map.put(entry.key(), entry.valueBoolean())); - detectedStructures = map; - } + // list should never contain more than a few entries, so array is fine and retains entry order + var map = new Object2BooleanArrayMap(structureList.size()); + structureList.forEach(entry -> map.put(entry.key(), entry.valueBoolean())); + detectedStructures = map; } } } @@ -559,7 +548,7 @@ public void writeToPacketNBT(CompoundTag cmp) { if (detectedStructures != null) { var stringBuilder = new StringBuilder(); boolean first = true; - for (var entry : detectedStructures.object2BooleanEntrySet()) { + for (Object2BooleanMap.Entry entry : detectedStructures.object2BooleanEntrySet()) { if (first) { first = false; } else { @@ -572,11 +561,10 @@ public void writeToPacketNBT(CompoundTag cmp) { } public static void dropLooniumItems(LivingEntity living, Consumer consumer) { - var comp = XplatAbstractions.INSTANCE.looniumComponent(living); - if (comp != null) - if (!comp.getDrop().isEmpty() || comp.isDropNothing()) { - consumer.accept(comp.getDrop()); - } + LooniumComponent comp = XplatAbstractions.INSTANCE.looniumComponent(living); + if (comp != null && comp.isOverrideDrop()) { + consumer.accept(comp.getDrop()); + } } public static class WandHud extends BindableFlowerWandHud { @@ -595,13 +583,13 @@ public void renderHUD(GuiGraphics gui, Minecraft mc) { lootType = "structure_loot"; } String lootTypeMessage = I18n.get("botaniamisc.loonium." + lootType); - int filterWidth = mc.font.width(lootTypeMessage); - int filterTextStart = (mc.getWindow().getGuiScaledWidth() - filterWidth) / 2; - int halfMinWidth = (filterWidth + 4) / 2; + int lootTypeWidth = mc.font.width(lootTypeMessage); + int lootTypeTextStart = (mc.getWindow().getGuiScaledWidth() - lootTypeWidth) / 2; + int halfMinWidth = (lootTypeWidth + 4) / 2; int centerY = mc.getWindow().getGuiScaledHeight() / 2; super.renderHUD(gui, mc, halfMinWidth, halfMinWidth, 40); - gui.drawString(mc.font, lootTypeMessage, filterTextStart, centerY + 30, flower.getColor()); + gui.drawString(mc.font, lootTypeMessage, lootTypeTextStart, centerY + 30, flower.getColor()); } } } diff --git a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java similarity index 88% rename from Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java rename to Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java index 5366b231c0..6f247384c7 100644 --- a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManager.java +++ b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java @@ -7,7 +7,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; -import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; @@ -16,6 +15,7 @@ import org.jetbrains.annotations.Nullable; import vazkii.botania.api.BotaniaAPI; +import vazkii.botania.api.configdata.ConfigDataManager; import vazkii.botania.api.configdata.LooniumStructureConfiguration; import vazkii.botania.xplat.XplatAbstractions; @@ -27,15 +27,15 @@ import static vazkii.botania.common.lib.ResourceLocationHelper.prefix; -public class ConfigDataManager implements PreparableReloadListener { +public class ConfigDataManagerImpl implements ConfigDataManager { public static void registerListener() { - XplatAbstractions.INSTANCE.registerReloadListener(PackType.SERVER_DATA, prefix("configdata"), new ConfigDataManager()); + XplatAbstractions.INSTANCE.registerReloadListener(PackType.SERVER_DATA, prefix("configdata"), new ConfigDataManagerImpl()); } private final Map looniumConfigs = new HashMap<>(); - @Nullable - public LooniumStructureConfiguration getEffectiveLooniumStructureConfiguration(ResourceLocation id) { + @Override + public @Nullable LooniumStructureConfiguration getEffectiveLooniumStructureConfiguration(ResourceLocation id) { LooniumStructureConfiguration configuration = this.looniumConfigs.get(id); return configuration != null ? configuration.getEffectiveConfig(looniumConfigs::get) : null; } @@ -45,7 +45,7 @@ private static void validateLooniumConfig(Map visitedEntries = new LinkedHashSet<>(); do { errorEntries.clear(); - for (var entry : map.entrySet()) { + for (Map.Entry entry : map.entrySet()) { ResourceLocation id = entry.getKey(); ResourceLocation parent = entry.getValue().parent; if (id.equals(parent)) { @@ -103,7 +103,7 @@ private CompletableFuture scheduleConfigParse(PreparationBarrier barri SimpleJsonResourceReloadListener.scanDirectory(manager, "config/" + type.directory, new Gson(), resourceMap); Map configs = new HashMap<>(resourceMap.size()); resourceMap.forEach((id, jsonElement) -> { - BotaniaAPI.LOGGER.info("Parsing {}", id); + BotaniaAPI.LOGGER.debug("Parsing {} config '{}'", type.directory, id); type.codec.parse(JsonOps.INSTANCE, jsonElement).result().ifPresent(c -> configs.put(id, c)); }); type.validateFunction.accept(configs); @@ -115,10 +115,10 @@ private CompletableFuture scheduleConfigParse(PreparationBarrier barri private record ConfigDataType (Codec codec, String directory, Consumer> validateFunction, - BiConsumer> applyFunction) { + BiConsumer> applyFunction) { private static final ConfigDataType LOONUIM = new ConfigDataType<>(LooniumStructureConfiguration.CODEC, "loonium", - ConfigDataManager::validateLooniumConfig, ConfigDataManager::applyLooniumConfig); + ConfigDataManagerImpl::validateLooniumConfig, ConfigDataManagerImpl::applyLooniumConfig); } } diff --git a/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java b/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java index 25ae9cdf12..c7e867f415 100644 --- a/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java +++ b/Xplat/src/main/java/vazkii/botania/common/impl/BotaniaAPIImpl.java @@ -28,11 +28,12 @@ import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.BotaniaRegistries; import vazkii.botania.api.brew.Brew; +import vazkii.botania.api.configdata.ConfigDataManager; import vazkii.botania.api.corporea.CorporeaNodeDetector; import vazkii.botania.api.internal.ManaNetwork; import vazkii.botania.client.fx.SparkleParticleData; import vazkii.botania.common.block.flower.functional.SolegnoliaBlockEntity; -import vazkii.botania.common.config.ConfigDataManager; +import vazkii.botania.common.config.ConfigDataManagerImpl; import vazkii.botania.common.handler.BotaniaSounds; import vazkii.botania.common.handler.EquipmentHandler; import vazkii.botania.common.handler.ManaNetworkHandler; @@ -203,7 +204,7 @@ public Ingredient getRepairIngredient() { } } - private ConfigDataManager configDataManager = new ConfigDataManager(); + private ConfigDataManager configDataManager = new ConfigDataManagerImpl(); @Override public int apiVersion() { diff --git a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java index 9792468309..d302dce43d 100644 --- a/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java +++ b/Xplat/src/main/java/vazkii/botania/common/internal_caps/LooniumComponent.java @@ -14,11 +14,11 @@ import java.util.Objects; public class LooniumComponent extends SerializableComponent { - protected static final String TAG_TODROP = "toDrop"; - protected static final String TAG_DROP_NOTHING = "dropNothing"; + protected static final String TAG_TO_DROP = "toDrop"; + protected static final String TAG_OVERRIDE_DROP = "overrideDrop"; protected static final String TAG_SLOW_DESPAWN = "slowDespawn"; private ItemStack toDrop = ItemStack.EMPTY; - private boolean dropNothing; + private boolean overrideDrop; private boolean slowDespawn; public ItemStack getDrop() { @@ -29,15 +29,12 @@ public void setDrop(ItemStack stack) { this.toDrop = stack; } - public boolean isDropNothing() { - return dropNothing; + public boolean isOverrideDrop() { + return overrideDrop; } - public void setDropNothing(boolean dropNothing) { - if (dropNothing) { - setDrop(ItemStack.EMPTY); - } - this.dropNothing = dropNothing; + public void setOverrideDrop(boolean overrideDrop) { + this.overrideDrop = overrideDrop; } public boolean isSlowDespawn() { @@ -54,23 +51,23 @@ public boolean equals(Object obj) { return true; } return obj instanceof LooniumComponent component && ItemStack.matches(component.toDrop, toDrop) - && component.dropNothing == dropNothing && component.slowDespawn == slowDespawn; + && component.overrideDrop == overrideDrop && component.slowDespawn == slowDespawn; } @Override public int hashCode() { - return Objects.hash(toDrop.hashCode(), dropNothing, slowDespawn); + return Objects.hash(toDrop.hashCode(), overrideDrop, slowDespawn); } @Override public void readFromNbt(CompoundTag tag) { - if (tag.contains(TAG_TODROP)) { - setDrop(ItemStack.of(tag.getCompound(TAG_TODROP))); + if (tag.contains(TAG_TO_DROP)) { + setDrop(ItemStack.of(tag.getCompound(TAG_TO_DROP))); } else { setDrop(ItemStack.EMPTY); } - if (tag.contains(TAG_DROP_NOTHING)) { - setDropNothing(tag.getBoolean(TAG_DROP_NOTHING)); + if (tag.contains(TAG_OVERRIDE_DROP)) { + setOverrideDrop(tag.getBoolean(TAG_OVERRIDE_DROP)); } if (tag.contains(TAG_SLOW_DESPAWN)) { setSlowDespawn(tag.getBoolean(TAG_SLOW_DESPAWN)); @@ -79,11 +76,11 @@ public void readFromNbt(CompoundTag tag) { @Override public void writeToNbt(CompoundTag tag) { - if (!getDrop().isEmpty()) { - tag.put(TAG_TODROP, getDrop().save(new CompoundTag())); - } - if (isDropNothing()) { - tag.putBoolean(TAG_DROP_NOTHING, true); + if (isOverrideDrop()) { + if (!getDrop().isEmpty()) { + tag.put(TAG_TO_DROP, getDrop().save(new CompoundTag())); + } + tag.putBoolean(TAG_OVERRIDE_DROP, true); } if (isSlowDespawn()) { tag.putBoolean(TAG_SLOW_DESPAWN, true); diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java index 5a21b3d869..738607d861 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumEquipmentLootProvider.java @@ -3,6 +3,7 @@ import com.google.gson.JsonElement; import net.minecraft.advancements.critereon.*; +import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -132,7 +133,7 @@ private CompletableFuture run(@NotNull CachedOutput cache, HolderLookup.Provi // TODO: we should be using LootTableSubProvider implementations instead of three individual loot providers var output = new ArrayList>(tables.size()); - for (var e : tables.entrySet()) { + for (Map.Entry e : tables.entrySet()) { Path path = pathProvider.json(e.getKey()); LootTable.Builder builder = e.getValue(); // TODO 1.21: use LootContextParamSets.EQUIPMENT instead @@ -140,7 +141,7 @@ private CompletableFuture run(@NotNull CachedOutput cache, HolderLookup.Provi JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); output.add(DataProvider.saveStable(cache, jsonTree, path)); } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } private void defineWeaponEquipmentTables(Map tables) { @@ -252,8 +253,8 @@ private void defineAncientCityEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimWardQuartz = trimFactory.apply(TrimPatterns.WARD, TrimMaterials.QUARTZ); - var trimSilenceCopper = trimFactory.apply(TrimPatterns.SILENCE, TrimMaterials.COPPER); + ArmorTrim trimWardQuartz = trimFactory.apply(TrimPatterns.WARD, TrimMaterials.QUARTZ); + ArmorTrim trimSilenceCopper = trimFactory.apply(TrimPatterns.SILENCE, TrimMaterials.COPPER); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WARD_IRON, randomizedSetFactory.apply(trimWardQuartz, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WARD_DIAMOND, @@ -263,7 +264,7 @@ private void defineAncientCityEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimSnoutGold = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.GOLD); - var trimSnoutNetherite = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.NETHERITE); + ArmorTrim trimSnoutGold = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.GOLD); + ArmorTrim trimSnoutNetherite = trimFactory.apply(TrimPatterns.SNOUT, TrimMaterials.NETHERITE); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_GOLD, randomizedSetFactory.apply(trimSnoutNetherite, armorItems.get(ArmorMaterials.GOLD))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SNOUT_NETHERITE, @@ -326,7 +327,7 @@ private void defineDesertPyramidEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimDuneRedstone = trimFactory.apply(TrimPatterns.DUNE, TrimMaterials.REDSTONE); + ArmorTrim trimDuneRedstone = trimFactory.apply(TrimPatterns.DUNE, TrimMaterials.REDSTONE); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_IRON, randomizedSetFactory.apply(trimDuneRedstone, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_DUNE_GOLD, @@ -358,7 +359,7 @@ private void defineEndCityEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimSpireAmethyst = trimFactory.apply(TrimPatterns.SPIRE, TrimMaterials.AMETHYST); + ArmorTrim trimSpireAmethyst = trimFactory.apply(TrimPatterns.SPIRE, TrimMaterials.AMETHYST); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_IRON, randomizedSetFactory.apply(trimSpireAmethyst, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SPIRE_GOLD, @@ -366,7 +367,7 @@ private void defineEndCityEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimRibIron = trimFactory.apply(TrimPatterns.RIB, TrimMaterials.IRON); + ArmorTrim trimRibIron = trimFactory.apply(TrimPatterns.RIB, TrimMaterials.IRON); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RIB_IRON, randomizedSetFactory.apply(trimRibIron, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RIB_GOLD, @@ -444,7 +445,7 @@ private void defineJungleTempleEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimWildEmerald = trimFactory.apply(TrimPatterns.WILD, TrimMaterials.EMERALD); + ArmorTrim trimWildEmerald = trimFactory.apply(TrimPatterns.WILD, TrimMaterials.EMERALD); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WILD_CHAIN, randomizedSetFactory.apply(trimWildEmerald, armorItems.get(ArmorMaterials.CHAIN))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WILD_GOLD, @@ -518,7 +519,7 @@ private void definePillagerOutpostEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimSentryEmerald = trimFactory.apply(TrimPatterns.SENTRY, TrimMaterials.EMERALD); + ArmorTrim trimSentryEmerald = trimFactory.apply(TrimPatterns.SENTRY, TrimMaterials.EMERALD); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_CHAIN, randomizedSetFactory.apply(trimSentryEmerald, armorItems.get(ArmorMaterials.CHAIN))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SENTRY_IRON, @@ -594,7 +595,7 @@ private void defineShipwreckEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimCoastEmerald = trimFactory.apply(TrimPatterns.COAST, TrimMaterials.EMERALD); + ArmorTrim trimCoastEmerald = trimFactory.apply(TrimPatterns.COAST, TrimMaterials.EMERALD); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COAST_CHAIN, randomizedSetFactory.apply(trimCoastEmerald, armorItems.get(ArmorMaterials.CHAIN))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_COAST_IRON, @@ -632,8 +633,8 @@ private void defineStrongholdEquipmentTables(Map randomizedSetFactory, BiConsumer trimSetter) { - var trimEyeRedstone = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.REDSTONE); - var trimEyeLapis = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.LAPIS); + ArmorTrim trimEyeRedstone = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.REDSTONE); + ArmorTrim trimEyeLapis = trimFactory.apply(TrimPatterns.EYE, TrimMaterials.LAPIS); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_EYE_IRON, randomizedSetFactory.apply(trimEyeLapis, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_EYE_GOLD, @@ -688,25 +689,25 @@ private void defineTrailRuinsEquipmentTables(Map, ResourceKey, ArmorTrim> trimFactory, BiFunction randomizedSetFactory) { - var trimHostEmerald = trimFactory.apply(TrimPatterns.HOST, TrimMaterials.EMERALD); + ArmorTrim trimHostEmerald = trimFactory.apply(TrimPatterns.HOST, TrimMaterials.EMERALD); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_HOST_CHAIN, randomizedSetFactory.apply(trimHostEmerald, armorItems.get(ArmorMaterials.CHAIN))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_HOST_IRON, randomizedSetFactory.apply(trimHostEmerald, armorItems.get(ArmorMaterials.IRON))); - var trimRaiserAmethyst = trimFactory.apply(TrimPatterns.RAISER, TrimMaterials.AMETHYST); + ArmorTrim trimRaiserAmethyst = trimFactory.apply(TrimPatterns.RAISER, TrimMaterials.AMETHYST); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_IRON, randomizedSetFactory.apply(trimRaiserAmethyst, armorItems.get(ArmorMaterials.IRON))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_RAISER_GOLD, randomizedSetFactory.apply(trimRaiserAmethyst, armorItems.get(ArmorMaterials.GOLD))); - var trimShaperLapis = trimFactory.apply(TrimPatterns.SHAPER, TrimMaterials.LAPIS); + ArmorTrim trimShaperLapis = trimFactory.apply(TrimPatterns.SHAPER, TrimMaterials.LAPIS); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_GOLD, randomizedSetFactory.apply(trimShaperLapis, armorItems.get(ArmorMaterials.GOLD))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_SHAPER_DIAMOND, randomizedSetFactory.apply(trimShaperLapis, armorItems.get(ArmorMaterials.DIAMOND))); - var trimWayfinderRedstone = trimFactory.apply(TrimPatterns.WAYFINDER, TrimMaterials.REDSTONE); + ArmorTrim trimWayfinderRedstone = trimFactory.apply(TrimPatterns.WAYFINDER, TrimMaterials.REDSTONE); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_CHAIN, randomizedSetFactory.apply(trimWayfinderRedstone, armorItems.get(ArmorMaterials.CHAIN))); tables.put(BotaniaLootTables.LOONIUM_ARMORSET_WAYFINDER_DIAMOND, @@ -779,7 +780,7 @@ private void defineWoodlandMansionEquipmentTables(Map patternRegistry, HolderLookup.RegistryLookup materialRegistry, ResourceKey pattern, ResourceKey material) { - var tidePattern = patternRegistry.get(pattern).orElseThrow(); - var goldMaterial = materialRegistry.get(material).orElseThrow(); + Holder.Reference tidePattern = patternRegistry.get(pattern).orElseThrow(); + Holder.Reference goldMaterial = materialRegistry.get(material).orElseThrow(); return new ArmorTrim(goldMaterial, tidePattern); } @@ -858,7 +859,7 @@ private static Consumer addDyedColorToTag(int color) { private LootTable.Builder createArmorSet(Consumer tagModifier, boolean randomized, Item... armorItems) { CompoundTag tag = new CompoundTag(); tagModifier.accept(tag); - var lootTable = LootTable.lootTable(); + LootTable.Builder lootTable = LootTable.lootTable(); for (Item armorItem : armorItems) { lootTable.withPool(LootPool.lootPool() .setRolls(randomized ? UniformGenerator.between(0, 1) : ConstantValue.exactly(1)) diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index c6b50171b0..a527941a65 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -1,5 +1,6 @@ package vazkii.botania.data; +import com.google.gson.JsonElement; import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; @@ -13,6 +14,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; @@ -27,7 +29,6 @@ import vazkii.botania.api.configdata.LooniumMobEffectToApply; import vazkii.botania.api.configdata.LooniumMobSpawnData; import vazkii.botania.api.configdata.LooniumStructureConfiguration; -import vazkii.botania.common.block.flower.functional.LooniumBlockEntity; import vazkii.botania.common.loot.BotaniaLootTables; import java.nio.file.Path; @@ -64,7 +65,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { configs.put(BuiltinStructures.JUNGLE_TEMPLE.location(), getConfigJungleTemple(defaultConfigId)); configs.put(BuiltinStructures.OCEAN_MONUMENT.location(), getConfigOceanMonument(defaultConfigId)); - var oceanRuinId = prefix("ocean_ruins"); + ResourceLocation oceanRuinId = prefix("ocean_ruins"); configs.put(oceanRuinId, LooniumStructureConfiguration.forParent(defaultConfigId) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build() @@ -88,7 +89,7 @@ public CompletableFuture run(@NotNull CachedOutput cache) { configs.put(BuiltinStructures.STRONGHOLD.location(), getConfigStronghold(defaultConfigId)); configs.put(BuiltinStructures.TRAIL_RUINS.location(), getConfigTrailRuins(defaultConfigId)); - var villageId = prefix("village"); + ResourceLocation villageId = prefix("village"); configs.put(villageId, LooniumStructureConfiguration.forParent(defaultConfigId) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).build() ); @@ -101,20 +102,20 @@ public CompletableFuture run(@NotNull CachedOutput cache) { configs.put(BuiltinStructures.WOODLAND_MANSION.location(), getConfigWoodlandMansion(defaultConfigId)); var output = new ArrayList>(configs.size()); - for (var e : configs.entrySet()) { + for (Map.Entry e : configs.entrySet()) { Path path = pathProvider.json(e.getKey()); - var config = e.getValue(); - var jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) + LooniumStructureConfiguration config = e.getValue(); + JsonElement jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) .getOrThrow(false, BotaniaAPI.LOGGER::error); output.add(DataProvider.saveStable(cache, jsonTree, path)); } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } private static LooniumStructureConfiguration getDefaultConfig() { return LooniumStructureConfiguration.builder() - .manaCost(LooniumBlockEntity.DEFAULT_COST) - .maxNearbyMobs(LooniumBlockEntity.DEFAULT_MAX_NEARBY_MOBS) + .manaCost(LooniumStructureConfiguration.DEFAULT_COST) + .maxNearbyMobs(LooniumStructureConfiguration.DEFAULT_MAX_NEARBY_MOBS) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.PIECE) .spawnedMobs( // weights roughly based on original Loonium mob selection logic @@ -258,7 +259,7 @@ private static LooniumStructureConfiguration getConfigJungleTemple(ResourceLocat } private static LooniumStructureConfiguration getConfigOceanMonument(ResourceLocation parentId) { - var standardEffectsInWater = getStandardEffects(true, true); + LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.GUARDIAN, 200).build(), getCreeperSpawnData(199, false, getCreeperEffects(true)), @@ -279,7 +280,7 @@ private static LooniumStructureConfiguration getConfigOceanMonument(ResourceLoca } private static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLocation parentId) { - var standardEffectsInWater = getStandardEffects(true, true); + LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), getCreeperSpawnData(1, true, getCreeperEffects(true)), @@ -299,7 +300,7 @@ private static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLoca } private static LooniumStructureConfiguration getConfigOceanRuinWarm(ResourceLocation parentId) { - var standardEffectsInWater = getStandardEffects(true, true); + LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), getCreeperSpawnData(1, true, getCreeperEffects(true)), @@ -417,7 +418,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalNether(Resourc } private static LooniumStructureConfiguration getConfigRuinedPortalOcean(ResourceLocation parentId) { - var standardEffectsInWater = getStandardEffects(true, true); + LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -486,7 +487,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalSwamp(Resource } private static LooniumStructureConfiguration getConfigShipwreck(ResourceLocation parentId) { - var standardEffectsInWater = getStandardEffects(true, true); + LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), getCreeperSpawnData(1, true, getCreeperEffects(true)), @@ -721,8 +722,8 @@ private static LooniumMobSpawnData getPiglinSpawnData(int weight, ResourceLocati piglinNbt.putBoolean("IsImmuneToZombification", true); } - var piglinBrain = Brain.provider(List.of(MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.ADMIRING_DISABLED, - MemoryModuleType.ATE_RECENTLY), List.of()) + Brain piglinBrain = Brain.provider(List.of(MemoryModuleType.UNIVERSAL_ANGER, + MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.ATE_RECENTLY), List.of()) .makeBrain(new Dynamic<>(NbtOps.INSTANCE)); piglinBrain.setMemory(MemoryModuleType.UNIVERSAL_ANGER, true); piglinBrain.setMemory(MemoryModuleType.ADMIRING_DISABLED, true); diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index 357917c15b..5248245492 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -174,19 +174,19 @@ public CompletableFuture run(@NotNull CachedOutput cache) { ); var output = new ArrayList>(tables.size()); - for (var e : tables.entrySet()) { + for (Map.Entry e : tables.entrySet()) { Path path = pathProvider.json(e.getKey()); LootTable.Builder builder = e.getValue(); LootTable lootTable = builder.setParamSet(LootContextParamSets.ALL_PARAMS).build(); JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); output.add(DataProvider.saveStable(cache, jsonTree, path)); } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } private static LootTable.Builder buildVillageLootTable(ResourceLocation house, Set villageLootSet) { LootPool.Builder lootPool = LootPool.lootPool().add(LootTableReference.lootTableReference(house).setWeight(3)); - for (var loot : villageLootSet) { + for (VillageLoot loot : villageLootSet) { lootPool.add(LootTableReference.lootTableReference(loot.lootTable)); } return LootTable.lootTable().withPool(lootPool); diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index dc588a37df..d15cfe3772 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -241,6 +241,7 @@ "tag.botania.mana_dusts": "Mana Dusts", "tag.botania.burst_viewers": "Burst Viewers", "tag.botania.seed_apothecary_reagent": "Seed Reagents", + "tag.botania.loonium_offhand_equipment": "Loonium Off-hand Equipment", "key.botania_corporea_request": "Corporea Request", From 64a92415468e428a560e9ae9f1f0d92ee81c3ada Mon Sep 17 00:00:00 2001 From: Artemis System Date: Sat, 5 Oct 2024 16:59:32 +0200 Subject: [PATCH 22/26] config/loonium -> loonium_config --- .../a864b94d006aba05700c96ad7a5769c8571473bc | 60 +++++++++---------- .../loonium => loonium_config}/default.json | 0 .../ocean_ruins.json | 0 .../loonium => loonium_config}/village.json | 0 .../ancient_city.json | 0 .../bastion_remnant.json | 0 .../desert_pyramid.json | 0 .../loonium => loonium_config}/end_city.json | 0 .../loonium => loonium_config}/fortress.json | 0 .../jungle_pyramid.json | 0 .../loonium => loonium_config}/mansion.json | 0 .../loonium => loonium_config}/monument.json | 0 .../ocean_ruin_cold.json | 0 .../ocean_ruin_warm.json | 0 .../pillager_outpost.json | 0 .../ruined_portal.json | 0 .../ruined_portal_desert.json | 0 .../ruined_portal_jungle.json | 0 .../ruined_portal_mountain.json | 0 .../ruined_portal_nether.json | 0 .../ruined_portal_ocean.json | 0 .../ruined_portal_swamp.json | 0 .../loonium => loonium_config}/shipwreck.json | 0 .../shipwreck_beached.json | 0 .../stronghold.json | 0 .../trail_ruins.json | 0 .../village_desert.json | 0 .../village_plains.json | 0 .../village_savanna.json | 0 .../village_snowy.json | 0 .../village_taiga.json | 0 .../common/config/ConfigDataManagerImpl.java | 4 +- ...LooniumStructureConfigurationProvider.java | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) rename Xplat/src/generated/resources/data/botania/{config/loonium => loonium_config}/default.json (100%) rename Xplat/src/generated/resources/data/botania/{config/loonium => loonium_config}/ocean_ruins.json (100%) rename Xplat/src/generated/resources/data/botania/{config/loonium => loonium_config}/village.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ancient_city.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/bastion_remnant.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/desert_pyramid.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/end_city.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/fortress.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/jungle_pyramid.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/mansion.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/monument.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ocean_ruin_cold.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ocean_ruin_warm.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/pillager_outpost.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_desert.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_jungle.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_mountain.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_nether.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_ocean.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/ruined_portal_swamp.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/shipwreck.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/shipwreck_beached.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/stronghold.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/trail_ruins.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/village_desert.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/village_plains.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/village_savanna.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/village_snowy.json (100%) rename Xplat/src/generated/resources/data/minecraft/{config/loonium => loonium_config}/village_taiga.json (100%) diff --git a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc index 6bd4302a99..b41751152f 100644 --- a/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc +++ b/Xplat/src/generated/resources/.cache/a864b94d006aba05700c96ad7a5769c8571473bc @@ -1,31 +1,31 @@ // 1.20.1 Botania/Loonium structure configuration -0591cbe7698291e5638b866f3d85e70f58d1a344 data/botania/config/loonium/default.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/ocean_ruins.json -8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/config/loonium/village.json -0c933b1278b153f59c7f189d7d6915c489340893 data/minecraft/config/loonium/ancient_city.json -4baa8c3fc3b3ad342326f1e207e6897ece6a04de data/minecraft/config/loonium/bastion_remnant.json -80b2e51b7d57879bf73aad1b23264032080e8e22 data/minecraft/config/loonium/desert_pyramid.json -0cabae7ec03b982c21a592f0924beb7a3700c59d data/minecraft/config/loonium/end_city.json -81aa1d20a8a656b5110984587367368c7206cfb7 data/minecraft/config/loonium/fortress.json -180b4009f85a3b534c8f55aafc6d5ec3cd2125b6 data/minecraft/config/loonium/jungle_pyramid.json -189f42c5d0b89c43e618e55b6cedd0f01c5fb00c data/minecraft/config/loonium/mansion.json -7bf132334dfc93b6c0a9d74bd4896782819fa3ee data/minecraft/config/loonium/monument.json -7bf474c5eca6f6cf63799e5d1e518dd81b39943c data/minecraft/config/loonium/ocean_ruin_cold.json -70760f4da963f17c462e0e264652776c74d7d178 data/minecraft/config/loonium/ocean_ruin_warm.json -690d302eb1c171f1caaf63d52275fc82b9c40431 data/minecraft/config/loonium/pillager_outpost.json -72a5b2a5af2bb9966f0ac15d00a2fa69e21aa7fc data/minecraft/config/loonium/ruined_portal.json -eaf7c2c1520cf16bb06ca9e6c1e76f32b1571fe2 data/minecraft/config/loonium/ruined_portal_desert.json -17dedb198a79feb28465164299f9e161d0621f72 data/minecraft/config/loonium/ruined_portal_jungle.json -77a93510dc75fe179568fe08cac9848965a7abf2 data/minecraft/config/loonium/ruined_portal_mountain.json -07a632775753dee383465d74d594775b22d68058 data/minecraft/config/loonium/ruined_portal_nether.json -a46cb70ba9a2ea3425f281ac56bdead53b4d121e data/minecraft/config/loonium/ruined_portal_ocean.json -6d6bec7132a26f85357c6c214edd3b3fb4f1e439 data/minecraft/config/loonium/ruined_portal_swamp.json -e07b347d00f8046a129aaa6c370d09051b5b64ec data/minecraft/config/loonium/shipwreck.json -69b7be4e05054ffe7d73ea4625581012af333cf2 data/minecraft/config/loonium/shipwreck_beached.json -daec043e2fd1892c030e279a01f03b36bec78545 data/minecraft/config/loonium/stronghold.json -884bcffda3cef17de3b826764761bf17923cc3a2 data/minecraft/config/loonium/trail_ruins.json -ca49a5ff59f404e97c78004a75404c335ff30385 data/minecraft/config/loonium/village_desert.json -c9e527140f4f775a3dd58af3acdd898b6e504991 data/minecraft/config/loonium/village_plains.json -8ccd5ddf38ead3ad53cc1b5a9f4780adee02cad0 data/minecraft/config/loonium/village_savanna.json -437d9a154644a9e62df0eab1fc07d86dbaf98b82 data/minecraft/config/loonium/village_snowy.json -c4562050c8a5429cb383144e9e57f5267387dbba data/minecraft/config/loonium/village_taiga.json +0591cbe7698291e5638b866f3d85e70f58d1a344 data/botania/loonium_config/default.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/loonium_config/ocean_ruins.json +8957828d1e1f4fb2748cb4db623d290b89ab3f79 data/botania/loonium_config/village.json +0c933b1278b153f59c7f189d7d6915c489340893 data/minecraft/loonium_config/ancient_city.json +4baa8c3fc3b3ad342326f1e207e6897ece6a04de data/minecraft/loonium_config/bastion_remnant.json +80b2e51b7d57879bf73aad1b23264032080e8e22 data/minecraft/loonium_config/desert_pyramid.json +0cabae7ec03b982c21a592f0924beb7a3700c59d data/minecraft/loonium_config/end_city.json +81aa1d20a8a656b5110984587367368c7206cfb7 data/minecraft/loonium_config/fortress.json +180b4009f85a3b534c8f55aafc6d5ec3cd2125b6 data/minecraft/loonium_config/jungle_pyramid.json +189f42c5d0b89c43e618e55b6cedd0f01c5fb00c data/minecraft/loonium_config/mansion.json +7bf132334dfc93b6c0a9d74bd4896782819fa3ee data/minecraft/loonium_config/monument.json +7bf474c5eca6f6cf63799e5d1e518dd81b39943c data/minecraft/loonium_config/ocean_ruin_cold.json +70760f4da963f17c462e0e264652776c74d7d178 data/minecraft/loonium_config/ocean_ruin_warm.json +690d302eb1c171f1caaf63d52275fc82b9c40431 data/minecraft/loonium_config/pillager_outpost.json +72a5b2a5af2bb9966f0ac15d00a2fa69e21aa7fc data/minecraft/loonium_config/ruined_portal.json +eaf7c2c1520cf16bb06ca9e6c1e76f32b1571fe2 data/minecraft/loonium_config/ruined_portal_desert.json +17dedb198a79feb28465164299f9e161d0621f72 data/minecraft/loonium_config/ruined_portal_jungle.json +77a93510dc75fe179568fe08cac9848965a7abf2 data/minecraft/loonium_config/ruined_portal_mountain.json +07a632775753dee383465d74d594775b22d68058 data/minecraft/loonium_config/ruined_portal_nether.json +a46cb70ba9a2ea3425f281ac56bdead53b4d121e data/minecraft/loonium_config/ruined_portal_ocean.json +6d6bec7132a26f85357c6c214edd3b3fb4f1e439 data/minecraft/loonium_config/ruined_portal_swamp.json +e07b347d00f8046a129aaa6c370d09051b5b64ec data/minecraft/loonium_config/shipwreck.json +69b7be4e05054ffe7d73ea4625581012af333cf2 data/minecraft/loonium_config/shipwreck_beached.json +daec043e2fd1892c030e279a01f03b36bec78545 data/minecraft/loonium_config/stronghold.json +884bcffda3cef17de3b826764761bf17923cc3a2 data/minecraft/loonium_config/trail_ruins.json +ca49a5ff59f404e97c78004a75404c335ff30385 data/minecraft/loonium_config/village_desert.json +c9e527140f4f775a3dd58af3acdd898b6e504991 data/minecraft/loonium_config/village_plains.json +8ccd5ddf38ead3ad53cc1b5a9f4780adee02cad0 data/minecraft/loonium_config/village_savanna.json +437d9a154644a9e62df0eab1fc07d86dbaf98b82 data/minecraft/loonium_config/village_snowy.json +c4562050c8a5429cb383144e9e57f5267387dbba data/minecraft/loonium_config/village_taiga.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/default.json b/Xplat/src/generated/resources/data/botania/loonium_config/default.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/default.json rename to Xplat/src/generated/resources/data/botania/loonium_config/default.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json b/Xplat/src/generated/resources/data/botania/loonium_config/ocean_ruins.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/ocean_ruins.json rename to Xplat/src/generated/resources/data/botania/loonium_config/ocean_ruins.json diff --git a/Xplat/src/generated/resources/data/botania/config/loonium/village.json b/Xplat/src/generated/resources/data/botania/loonium_config/village.json similarity index 100% rename from Xplat/src/generated/resources/data/botania/config/loonium/village.json rename to Xplat/src/generated/resources/data/botania/loonium_config/village.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ancient_city.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ancient_city.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ancient_city.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/bastion_remnant.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/bastion_remnant.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/bastion_remnant.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/desert_pyramid.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/desert_pyramid.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/desert_pyramid.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/end_city.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/end_city.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/end_city.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/fortress.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/fortress.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/fortress.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/jungle_pyramid.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/jungle_pyramid.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/jungle_pyramid.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/mansion.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/mansion.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/mansion.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/monument.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/monument.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/monument.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ocean_ruin_cold.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_cold.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ocean_ruin_cold.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ocean_ruin_warm.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ocean_ruin_warm.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ocean_ruin_warm.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/pillager_outpost.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/pillager_outpost.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/pillager_outpost.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_desert.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_desert.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_desert.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_jungle.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_jungle.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_jungle.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_mountain.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_mountain.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_mountain.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_nether.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_nether.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_nether.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_ocean.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_ocean.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_ocean.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_swamp.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/ruined_portal_swamp.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/ruined_portal_swamp.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/shipwreck.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/shipwreck.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/shipwreck_beached.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/shipwreck_beached.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/shipwreck_beached.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/stronghold.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/stronghold.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/stronghold.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/trail_ruins.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/trail_ruins.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/trail_ruins.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/village_desert.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/village_desert.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/village_desert.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/village_plains.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/village_plains.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/village_plains.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/village_savanna.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/village_savanna.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/village_savanna.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/village_snowy.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/village_snowy.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/village_snowy.json diff --git a/Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json b/Xplat/src/generated/resources/data/minecraft/loonium_config/village_taiga.json similarity index 100% rename from Xplat/src/generated/resources/data/minecraft/config/loonium/village_taiga.json rename to Xplat/src/generated/resources/data/minecraft/loonium_config/village_taiga.json diff --git a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java index 6f247384c7..72201ec2a9 100644 --- a/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java +++ b/Xplat/src/main/java/vazkii/botania/common/config/ConfigDataManagerImpl.java @@ -100,7 +100,7 @@ private CompletableFuture scheduleConfigParse(PreparationBarrier barri Executor backgroundExecutor, Executor gameExecutor, ConfigDataType type) { return CompletableFuture.supplyAsync(() -> { Map resourceMap = new HashMap<>(); - SimpleJsonResourceReloadListener.scanDirectory(manager, "config/" + type.directory, new Gson(), resourceMap); + SimpleJsonResourceReloadListener.scanDirectory(manager, type.directory, new Gson(), resourceMap); Map configs = new HashMap<>(resourceMap.size()); resourceMap.forEach((id, jsonElement) -> { BotaniaAPI.LOGGER.debug("Parsing {} config '{}'", type.directory, id); @@ -117,7 +117,7 @@ private record ConfigDataType (Codec codec, String directory, Consumer> validateFunction, BiConsumer> applyFunction) { private static final ConfigDataType LOONUIM = - new ConfigDataType<>(LooniumStructureConfiguration.CODEC, "loonium", + new ConfigDataType<>(LooniumStructureConfiguration.CODEC, "loonium_config", ConfigDataManagerImpl::validateLooniumConfig, ConfigDataManagerImpl::applyLooniumConfig); } diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index a527941a65..5a66e8aba1 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -47,7 +47,7 @@ public class LooniumStructureConfigurationProvider implements DataProvider { private final PackOutput.PathProvider pathProvider; public LooniumStructureConfigurationProvider(PackOutput packOutput) { - pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "config/loonium"); + pathProvider = packOutput.createPathProvider(PackOutput.Target.DATA_PACK, "loonium_config"); } @NotNull From dbafbb2ee4244b28edaa3fa7764dc80322d8eaa1 Mon Sep 17 00:00:00 2001 From: Artemis System Date: Sun, 6 Oct 2024 11:30:06 +0200 Subject: [PATCH 23/26] Say which structure is attuned to in loonium tooltip --- .../flower/functional/LooniumBlockEntity.java | 31 ++++++++++++--- .../resources/assets/botania/lang/en_us.json | 38 +++++++++++++++++-- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 1edac5dce4..45ebfede4e 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -80,6 +80,7 @@ public class LooniumBlockEntity extends FunctionalFlowerBlockEntity { private static final String TAG_LOOT_TABLE = "lootTable"; private static final String TAG_DETECTED_STRUCTURE = "detectedStructure"; private static final String TAG_CONFIG_OVERRIDE = "configOverride"; + private static final String TAG_ATTUNE_DISPLAY_OVERRIDE = "attuneDisplayOverride"; private static final Supplier FALLBACK_CONFIG = Suppliers.memoize(() -> LooniumStructureConfiguration.builder() .manaCost(LooniumStructureConfiguration.DEFAULT_COST) @@ -157,6 +158,8 @@ public CollisionRule getCollisionRule() { private Object2BooleanMap detectedStructures; @Nullable private ResourceLocation configOverride; + @Nullable + private String attuneDisplayOverride; public LooniumBlockEntity(BlockPos pos, BlockState state) { super(BotaniaFlowerBlocks.LOONIUM, pos, state); @@ -515,6 +518,9 @@ public void readFromPacketNBT(CompoundTag cmp) { if (cmp.contains(TAG_CONFIG_OVERRIDE)) { configOverride = new ResourceLocation(cmp.getString(TAG_CONFIG_OVERRIDE)); } + if (cmp.contains(TAG_ATTUNE_DISPLAY_OVERRIDE)) { + attuneDisplayOverride = cmp.getString(TAG_ATTUNE_DISPLAY_OVERRIDE); + } if (cmp.contains(TAG_DETECTED_STRUCTURE)) { String rawString = cmp.getString(TAG_DETECTED_STRUCTURE); if (rawString.isEmpty()) { @@ -545,6 +551,9 @@ public void writeToPacketNBT(CompoundTag cmp) { if (configOverride != null) { cmp.putString(TAG_CONFIG_OVERRIDE, configOverride.toString()); } + if (attuneDisplayOverride != null) { + cmp.putString(TAG_ATTUNE_DISPLAY_OVERRIDE, attuneDisplayOverride); + } if (detectedStructures != null) { var stringBuilder = new StringBuilder(); boolean first = true; @@ -575,14 +584,26 @@ public WandHud(LooniumBlockEntity flower) { @Override public void renderHUD(GuiGraphics gui, Minecraft mc) { String lootType; - if (flower.lootTableOverride != null) { - lootType = "custom_loot"; + String structureName = ""; + if (flower.attuneDisplayOverride != null) { + lootType = flower.attuneDisplayOverride; + } else if (flower.lootTableOverride != null) { + lootType = "attuned"; } else if (flower.detectedStructures == null || flower.detectedStructures.isEmpty()) { - lootType = "generic_loot"; + lootType = "not_attuned"; } else { - lootType = "structure_loot"; + if (flower.detectedStructures.size() == 1) { + lootType = "attuned_one"; + structureName = flower.detectedStructures + .keySet().stream().findFirst() + .map(rl -> I18n.get("structure." + rl.getNamespace() + "." + rl.getPath().replace("/", "."))) + .orElseGet(() -> ""); + } else { + lootType = "attuned_many"; + } } - String lootTypeMessage = I18n.get("botaniamisc.loonium." + lootType); + + String lootTypeMessage = I18n.get("botaniamisc.loonium." + lootType, structureName); int lootTypeWidth = mc.font.width(lootTypeMessage); int lootTypeTextStart = (mc.getWindow().getGuiScaledWidth() - lootTypeWidth) / 2; int halfMinWidth = (lootTypeWidth + 4) / 2; diff --git a/Xplat/src/main/resources/assets/botania/lang/en_us.json b/Xplat/src/main/resources/assets/botania/lang/en_us.json index d15cfe3772..9966eced1b 100644 --- a/Xplat/src/main/resources/assets/botania/lang/en_us.json +++ b/Xplat/src/main/resources/assets/botania/lang/en_us.json @@ -132,9 +132,10 @@ "botaniamisc.rannuncarpus.state_sensitive": "Match Exact State", "botaniamisc.rannuncarpus.state_insensitive": "Match Block Only", "botaniamisc.lokiRingLimitReached": "Selection limit reached", - "botaniamisc.loonium.generic_loot": "Generic loot", - "botaniamisc.loonium.structure_loot": "Structure loot", - "botaniamisc.loonium.custom_loot": "Customized loot", + "botaniamisc.loonium.not_attuned": "Not attuned", + "botaniamisc.loonium.attuned": "Attuned", + "botaniamisc.loonium.attuned_one": "Attuned to structure: %s", + "botaniamisc.loonium.attuned_many": "Attuned to multiple structures", "botaniamisc.pollidisiac.feed_adults": "Feeding adult animals", "botaniamisc.pollidisiac.feed_babies": "Feeding baby animals", "botaniamisc.pollidisiac.feed_all": "Feeding all animals", @@ -243,6 +244,37 @@ "tag.botania.seed_apothecary_reagent": "Seed Reagents", "tag.botania.loonium_offhand_equipment": "Loonium Off-hand Equipment", + "structure.minecraft.ancient_city": "Ancient City", + "structure.minecraft.bastion_remnant": "Bastion Remnant", + "structure.minecraft.buried_treasure": "Buried Treasure", + "structure.minecraft.desert_pyramid": "Desert Pyramid", + "structure.minecraft.end_city": "End City", + "structure.minecraft.fortress": "Nether Fortress", + "structure.minecraft.jungle_pyramid": "Jungle Pyramid", + "structure.minecraft.mansion": "Woodland Mansion", + "structure.minecraft.mineshaft_mesa": "Badlands Mineshaft", + "structure.minecraft.mineshaft": "Mineshaft", + "structure.minecraft.monument": "Ocean Monument", + "structure.minecraft.ocean_ruin_cold": "Cold Ocean Ruin", + "structure.minecraft.ocean_ruin_warm": "Warm Ocean Ruin", + "structure.minecraft.pillager_outpost": "Pillager Outpost", + "structure.minecraft.ruined_portal_desert": "Desert Ruined Portal", + "structure.minecraft.ruined_portal_jungle": "Jungle Ruined Portal", + "structure.minecraft.ruined_portal_mountain": "Mountain Ruined Portal", + "structure.minecraft.ruined_portal_nether": "Nether Ruined Portal", + "structure.minecraft.ruined_portal_ocean": "Ocean Ruined Portal", + "structure.minecraft.ruined_portal_swamp": "Swamp Ruined Portal", + "structure.minecraft.ruined_portal": "Ruined Portal", + "structure.minecraft.shipwreck_beached": "Beached Shipwreck", + "structure.minecraft.shipwreck": "Shipwreck", + "structure.minecraft.stronghold": "Stronghold", + "structure.minecraft.trail_ruins": "Trail Ruins", + "structure.minecraft.village_desert": "Desert Village", + "structure.minecraft.village_plains": "Plains Village", + "structure.minecraft.village_savanna": "Savanna Village", + "structure.minecraft.village_snowy": "Snowy Village", + "structure.minecraft.village_taiga": "Taiga Village", + "key.botania_corporea_request": "Corporea Request", "botania.triggers.manaDetector": "Mana Burst", From 92cba7486e22dc7c4752fa434dd9aacbe68e8589 Mon Sep 17 00:00:00 2001 From: Artemis System Date: Sun, 6 Oct 2024 11:32:34 +0200 Subject: [PATCH 24/26] make loonium tooltip color readable --- .../common/block/flower/functional/LooniumBlockEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java index 45ebfede4e..e6ba74fd9f 100644 --- a/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java +++ b/Xplat/src/main/java/vazkii/botania/common/block/flower/functional/LooniumBlockEntity.java @@ -486,7 +486,7 @@ private void detectStructure(ServerLevel world) { @Override public int getColor() { - return 0x274A00; + return 0xC29D62; } @Override From 1d7a2baf20c6c6ddc1f42906778941200dd97a43 Mon Sep 17 00:00:00 2001 From: Artemis System Date: Sun, 6 Oct 2024 16:36:34 +0200 Subject: [PATCH 25/26] clean up loonium datagen and make things public --- ...LooniumStructureConfigurationProvider.java | 86 ++++++++++--------- .../data/LooniumStructureLootProvider.java | 43 +++++----- 2 files changed, 68 insertions(+), 61 deletions(-) diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java index 5a66e8aba1..c6f06d8582 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureConfigurationProvider.java @@ -54,6 +54,20 @@ public LooniumStructureConfigurationProvider(PackOutput packOutput) { @Override public CompletableFuture run(@NotNull CachedOutput cache) { Map configs = new HashMap<>(); + addConfigs(configs); + + var output = new ArrayList>(configs.size()); + for (Map.Entry e : configs.entrySet()) { + Path path = pathProvider.json(e.getKey()); + LooniumStructureConfiguration config = e.getValue(); + JsonElement jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) + .getOrThrow(false, BotaniaAPI.LOGGER::error); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + private void addConfigs(Map configs) { ResourceLocation defaultConfigId = LooniumStructureConfiguration.DEFAULT_CONFIG_ID; configs.put(defaultConfigId, getDefaultConfig()); @@ -100,19 +114,9 @@ public CompletableFuture run(@NotNull CachedOutput cache) { configs.put(BuiltinStructures.VILLAGE_TAIGA.location(), getConfigVillageTaiga(villageId)); configs.put(BuiltinStructures.WOODLAND_MANSION.location(), getConfigWoodlandMansion(defaultConfigId)); - - var output = new ArrayList>(configs.size()); - for (Map.Entry e : configs.entrySet()) { - Path path = pathProvider.json(e.getKey()); - LooniumStructureConfiguration config = e.getValue(); - JsonElement jsonTree = LooniumStructureConfiguration.CODEC.encodeStart(JsonOps.INSTANCE, config) - .getOrThrow(false, BotaniaAPI.LOGGER::error); - output.add(DataProvider.saveStable(cache, jsonTree, path)); - } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } - private static LooniumStructureConfiguration getDefaultConfig() { + public static LooniumStructureConfiguration getDefaultConfig() { return LooniumStructureConfiguration.builder() .manaCost(LooniumStructureConfiguration.DEFAULT_COST) .maxNearbyMobs(LooniumStructureConfiguration.DEFAULT_MAX_NEARBY_MOBS) @@ -145,7 +149,7 @@ private static LooniumStructureConfiguration getDefaultConfig() { .build(); } - private static LooniumStructureConfiguration getConfigAncientCity(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigAncientCity(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), getCreeperSpawnData(99, false, getCreeperEffects(false)), @@ -165,7 +169,7 @@ private static LooniumStructureConfiguration getConfigAncientCity(ResourceLocati ).build(); } - private static LooniumStructureConfiguration getConfigBastionRemnant(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigBastionRemnant(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), getCreeperSpawnData(99, false, getCreeperEffects(false)), @@ -184,7 +188,7 @@ private static LooniumStructureConfiguration getConfigBastionRemnant(ResourceLoc ).build(); } - private static LooniumStructureConfiguration getConfigDesertPyramid(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigDesertPyramid(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 50).build(), getCreeperSpawnData(149, false, getCreeperEffects(false)), @@ -200,7 +204,7 @@ private static LooniumStructureConfiguration getConfigDesertPyramid(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigEndCity(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigEndCity(ResourceLocation parentId) { LooniumMobEffectToApply[] creeperEffects = { LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), LooniumMobEffectToApply.effect(MobEffects.REGENERATION).duration(100).build(), @@ -224,7 +228,7 @@ private static LooniumStructureConfiguration getConfigEndCity(ResourceLocation p ).build(); } - private static LooniumStructureConfiguration getConfigFortress(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigFortress(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), getCreeperSpawnData(99, false, getCreeperEffects(false)), @@ -242,7 +246,7 @@ private static LooniumStructureConfiguration getConfigFortress(ResourceLocation ).build(); } - private static LooniumStructureConfiguration getConfigJungleTemple(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigJungleTemple(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 30).build(), getCreeperSpawnData(149, false, getCreeperEffects(false)), @@ -258,7 +262,7 @@ private static LooniumStructureConfiguration getConfigJungleTemple(ResourceLocat ).build(); } - private static LooniumStructureConfiguration getConfigOceanMonument(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigOceanMonument(ResourceLocation parentId) { LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.GUARDIAN, 200).build(), @@ -279,7 +283,7 @@ private static LooniumStructureConfiguration getConfigOceanMonument(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLocation parentId) { LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), @@ -299,7 +303,7 @@ private static LooniumStructureConfiguration getConfigOceanRuinCold(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigOceanRuinWarm(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigOceanRuinWarm(ResourceLocation parentId) { LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), @@ -317,7 +321,7 @@ private static LooniumStructureConfiguration getConfigOceanRuinWarm(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigPillagerOutpost(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigPillagerOutpost(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId) .boundingBoxType(StructureSpawnOverride.BoundingBoxType.STRUCTURE).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), @@ -336,7 +340,7 @@ private static LooniumStructureConfiguration getConfigPillagerOutpost(ResourceLo ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalDesert(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalDesert(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -356,7 +360,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalDesert(Resourc ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalJungle(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalJungle(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -377,7 +381,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalJungle(Resourc ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalMountain(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalMountain(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -398,7 +402,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalMountain(Resou ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalNether(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalNether(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 125) .effectsToApply(getStandardEffects(false, false)).build(), @@ -417,7 +421,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalNether(Resourc ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalOcean(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalOcean(ResourceLocation parentId) { LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) @@ -440,7 +444,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalOcean(Resource ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalStandard(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalStandard(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -465,7 +469,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalStandard(Resou ).build(); } - private static LooniumStructureConfiguration getConfigRuinedPortalSwamp(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigRuinedPortalSwamp(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ZOGLIN, 25) .effectsToApply(getStandardEffects(false, false)).build(), @@ -486,7 +490,7 @@ private static LooniumStructureConfiguration getConfigRuinedPortalSwamp(Resource ).build(); } - private static LooniumStructureConfiguration getConfigShipwreck(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigShipwreck(ResourceLocation parentId) { LooniumMobEffectToApply[] standardEffectsInWater = getStandardEffects(true, true); return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( getCreeperSpawnData(199, false, getCreeperEffects(true)), @@ -506,7 +510,7 @@ private static LooniumStructureConfiguration getConfigShipwreck(ResourceLocation ).build(); } - private static LooniumStructureConfiguration getConfigStronghold(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigStronghold(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 80).build(), getCreeperSpawnData(149, false, getCreeperEffects(false)), @@ -527,7 +531,7 @@ private static LooniumStructureConfiguration getConfigStronghold(ResourceLocatio ).build(); } - private static LooniumStructureConfiguration getConfigTrailRuins(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigTrailRuins(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -547,7 +551,7 @@ private static LooniumStructureConfiguration getConfigTrailRuins(ResourceLocatio ).build(); } - private static LooniumStructureConfiguration getConfigVillageDesert(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigVillageDesert(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -565,7 +569,7 @@ private static LooniumStructureConfiguration getConfigVillageDesert(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigVillagePlains(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigVillagePlains(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -583,7 +587,7 @@ private static LooniumStructureConfiguration getConfigVillagePlains(ResourceLoca ).build(); } - private static LooniumStructureConfiguration getConfigVillageSavanna(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigVillageSavanna(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -603,7 +607,7 @@ private static LooniumStructureConfiguration getConfigVillageSavanna(ResourceLoc ).build(); } - private static LooniumStructureConfiguration getConfigVillageSnowy(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigVillageSnowy(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -623,7 +627,7 @@ private static LooniumStructureConfiguration getConfigVillageSnowy(ResourceLocat ).build(); } - private static LooniumStructureConfiguration getConfigVillageTaiga(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigVillageTaiga(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(195, false, getCreeperEffects(false)), @@ -643,7 +647,7 @@ private static LooniumStructureConfiguration getConfigVillageTaiga(ResourceLocat ).build(); } - private static LooniumStructureConfiguration getConfigWoodlandMansion(ResourceLocation parentId) { + public static LooniumStructureConfiguration getConfigWoodlandMansion(ResourceLocation parentId) { return LooniumStructureConfiguration.forParent(parentId).spawnedMobs( LooniumMobSpawnData.entityWeight(EntityType.ENDERMAN, 40).build(), getCreeperSpawnData(199, false, getCreeperEffects(false)), @@ -664,7 +668,7 @@ private static LooniumStructureConfiguration getConfigWoodlandMansion(ResourceLo ).build(); } - private static LooniumMobEffectToApply[] getStandardEffects(boolean withWaterBreathing, boolean withFireResistance) { + public static LooniumMobEffectToApply[] getStandardEffects(boolean withWaterBreathing, boolean withFireResistance) { return withFireResistance ? (withWaterBreathing ? new LooniumMobEffectToApply[] { @@ -686,7 +690,7 @@ private static LooniumMobEffectToApply[] getStandardEffects(boolean withWaterBre }); } - private static LooniumMobEffectToApply[] getCreeperEffects(boolean withWaterBreathing) { + public static LooniumMobEffectToApply[] getCreeperEffects(boolean withWaterBreathing) { return withWaterBreathing ? new LooniumMobEffectToApply[] { LooniumMobEffectToApply.effect(MobEffects.FIRE_RESISTANCE).duration(100).build(), @@ -699,7 +703,7 @@ private static LooniumMobEffectToApply[] getCreeperEffects(boolean withWaterBrea }; } - private static LooniumMobSpawnData getCreeperSpawnData(int weight, boolean charged, + public static LooniumMobSpawnData getCreeperSpawnData(int weight, boolean charged, LooniumMobEffectToApply... creeperEffects) { CompoundTag chargedCreeperNbt; if (charged) { @@ -715,7 +719,7 @@ private static LooniumMobSpawnData getCreeperSpawnData(int weight, boolean charg .build(); } - private static LooniumMobSpawnData getPiglinSpawnData(int weight, ResourceLocation equipmentTable, + public static LooniumMobSpawnData getPiglinSpawnData(int weight, ResourceLocation equipmentTable, boolean needWaterBreathing, boolean zombificationImmune) { CompoundTag piglinNbt = new CompoundTag(); if (zombificationImmune) { diff --git a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java index 5248245492..b75114ef20 100644 --- a/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java +++ b/Xplat/src/main/java/vazkii/botania/data/LooniumStructureLootProvider.java @@ -29,15 +29,15 @@ public class LooniumStructureLootProvider implements DataProvider { // loot collections based on which village type hoses can actually have chests - private static final EnumSet PLAINS_VILLAGE_LOOT = EnumSet + public static final EnumSet PLAINS_VILLAGE_LOOT = EnumSet .of(VillageLoot.CARTOGRAPHER, VillageLoot.FISHER, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); - private static final EnumSet DESERT_VILLAGE_LOOT = EnumSet + public static final EnumSet DESERT_VILLAGE_LOOT = EnumSet .of(VillageLoot.TEMPLE, VillageLoot.TOOLSMITH, VillageLoot.WEAPONSMITH); - private static final EnumSet SAVANNA_VILLAGE_LOOT = EnumSet + public static final EnumSet SAVANNA_VILLAGE_LOOT = EnumSet .of(VillageLoot.BUTCHER, VillageLoot.CARTOGRAPHER, VillageLoot.MASON, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); - private static final EnumSet SNOWY_VILLAGE_LOOT = EnumSet + public static final EnumSet SNOWY_VILLAGE_LOOT = EnumSet .of(VillageLoot.ARMORER, VillageLoot.CARTOGRAPHER, VillageLoot.SHEPHERD, VillageLoot.TANNERY, VillageLoot.WEAPONSMITH); - private static final EnumSet TAIGA_VILLAGE_LOOT = EnumSet + public static final EnumSet TAIGA_VILLAGE_LOOT = EnumSet .of(VillageLoot.CARTOGRAPHER, VillageLoot.FLETCHER, VillageLoot.TANNERY, VillageLoot.TOOLSMITH, VillageLoot.WEAPONSMITH); private final PackOutput.PathProvider pathProvider; @@ -58,7 +58,20 @@ public static ResourceLocation getStructureId(ResourceLocation structureId) { @Override public CompletableFuture run(@NotNull CachedOutput cache) { Map tables = new HashMap<>(); + addLootTables(tables); + var output = new ArrayList>(tables.size()); + for (Map.Entry e : tables.entrySet()) { + Path path = pathProvider.json(e.getKey()); + LootTable.Builder builder = e.getValue(); + LootTable lootTable = builder.setParamSet(LootContextParamSets.ALL_PARAMS).build(); + JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); + output.add(DataProvider.saveStable(cache, jsonTree, path)); + } + return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); + } + + private void addLootTables(Map tables) { // Note: As far as world generating is concerned, dungeons are "features" (i.e. like trees or geodes), // not "structures" (like everything else the Loonium might care about). tables.put(prefix("default"), buildDelegateLootTable(BuiltInLootTables.SIMPLE_DUNGEON)); @@ -172,19 +185,9 @@ public CompletableFuture run(@NotNull CachedOutput cache) { .add(LootItem.lootTableItem(Items.TOTEM_OF_UNDYING).setWeight(1)) ) ); - - var output = new ArrayList>(tables.size()); - for (Map.Entry e : tables.entrySet()) { - Path path = pathProvider.json(e.getKey()); - LootTable.Builder builder = e.getValue(); - LootTable lootTable = builder.setParamSet(LootContextParamSets.ALL_PARAMS).build(); - JsonElement jsonTree = Deserializers.createLootTableSerializer().create().toJsonTree(lootTable); - output.add(DataProvider.saveStable(cache, jsonTree, path)); - } - return CompletableFuture.allOf(output.toArray(CompletableFuture[]::new)); } - private static LootTable.Builder buildVillageLootTable(ResourceLocation house, Set villageLootSet) { + public static LootTable.Builder buildVillageLootTable(ResourceLocation house, Set villageLootSet) { LootPool.Builder lootPool = LootPool.lootPool().add(LootTableReference.lootTableReference(house).setWeight(3)); for (VillageLoot loot : villageLootSet) { lootPool.add(LootTableReference.lootTableReference(loot.lootTable)); @@ -193,7 +196,7 @@ private static LootTable.Builder buildVillageLootTable(ResourceLocation house, S } @NotNull - private static LootTable.Builder buildShipwreckLootTable() { + public static LootTable.Builder buildShipwreckLootTable() { return LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(BuiltInLootTables.SHIPWRECK_MAP)) .add(LootTableReference.lootTableReference(BuiltInLootTables.SHIPWRECK_SUPPLY)) @@ -202,14 +205,14 @@ private static LootTable.Builder buildShipwreckLootTable() { } @NotNull - private static LootTable.Builder buildDelegateLootTable(ResourceLocation reference) { + public static LootTable.Builder buildDelegateLootTable(ResourceLocation reference) { return LootTable.lootTable().withPool(LootPool.lootPool() .add(LootTableReference.lootTableReference(reference)) ); } @NotNull - private static LootTable.Builder buildOceanRuinLootTable(ResourceLocation archaeology) { + public static LootTable.Builder buildOceanRuinLootTable(ResourceLocation archaeology) { // Note: since the Loonium does not supply a location, treasure maps will roll as empty maps return LootTable.lootTable().withPool(LootPool.lootPool() // 30% of ocean ruin sites generate with a big ruin instead of a small one, @@ -226,7 +229,7 @@ public String getName() { return "Structure-specific loot tables for the Loonium"; } - private enum VillageLoot { + public enum VillageLoot { WEAPONSMITH(BuiltInLootTables.VILLAGE_WEAPONSMITH), TOOLSMITH(BuiltInLootTables.VILLAGE_TOOLSMITH), ARMORER(BuiltInLootTables.VILLAGE_ARMORER), From 867751a6b2a330fbf2da21846cfae6588cb1c84f Mon Sep 17 00:00:00 2001 From: Artemis System Date: Sun, 6 Oct 2024 16:59:19 +0200 Subject: [PATCH 26/26] changelog for loonium changes --- web/changelog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/changelog.md b/web/changelog.md index 01af6433a0..6d0468b289 100644 --- a/web/changelog.md +++ b/web/changelog.md @@ -17,7 +17,10 @@ and start a new "Upcoming" section. {% include changelog_header.html version="Upcoming" %} -(none yet) +* Add: Looniums can now give different loot and mob spawns based on which +structure it's placed in, also further customizable with datapacks. Huuuuge +thanks to Wormbo for a lot of work on this feature! +* Change: More readable color in Loonium tooltip ---