diff --git a/src/generated/resources/.cache/ba67a98c0428003f026a2912fde427457f2de26a b/src/generated/resources/.cache/ba67a98c0428003f026a2912fde427457f2de26a new file mode 100644 index 000000000..88ffe5437 --- /dev/null +++ b/src/generated/resources/.cache/ba67a98c0428003f026a2912fde427457f2de26a @@ -0,0 +1,4 @@ +// 1.20.4 2024-03-13T03:30:52.2359302 Global Loot Modifiers : actuallyadditions +c314f845c2f475a0e11bbbeaf9ce082f283e84ed data/actuallyadditions/loot_modifiers/bat_loot.json +f77519b3b0453bb66d43569f8c67e59de6e49a2f data/actuallyadditions/loot_modifiers/dungeon_loot.json +24211d6853742ccd8fc0116f93710ef5ee759c29 data/neoforge/loot_modifiers/global_loot_modifiers.json diff --git a/src/generated/resources/data/actuallyadditions/loot_modifiers/bat_loot.json b/src/generated/resources/data/actuallyadditions/loot_modifiers/bat_loot.json new file mode 100644 index 000000000..7ce50c713 --- /dev/null +++ b/src/generated/resources/data/actuallyadditions/loot_modifiers/bat_loot.json @@ -0,0 +1,12 @@ +{ + "type": "actuallyadditions:bat_loot", + "conditions": [ + { + "condition": "minecraft:killed_by_player" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:entities/bat" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/actuallyadditions/loot_modifiers/dungeon_loot.json b/src/generated/resources/data/actuallyadditions/loot_modifiers/dungeon_loot.json new file mode 100644 index 000000000..99b1593e7 --- /dev/null +++ b/src/generated/resources/data/actuallyadditions/loot_modifiers/dungeon_loot.json @@ -0,0 +1,46 @@ +{ + "type": "actuallyadditions:dungeon_loot", + "conditions": [ + { + "condition": "minecraft:any_of", + "terms": [ + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/simple_dungeon" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/abandoned_mineshaft" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/village/village_weaponsmith" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/stronghold_library" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/igloo_chest" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/desert_pyramid" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/nether_bridge" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/end_city_treasure" + }, + { + "condition": "neoforge:loot_table_id", + "loot_table_id": "minecraft:chests/woodland_mansion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json b/src/generated/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json new file mode 100644 index 000000000..09eddb703 --- /dev/null +++ b/src/generated/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json @@ -0,0 +1,7 @@ +{ + "entries": [ + "actuallyadditions:dungeon_loot", + "actuallyadditions:bat_loot" + ], + "replace": false +} \ No newline at end of file diff --git a/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java b/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java index 398dc5592..db869498c 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java +++ b/src/main/java/de/ellpeck/actuallyadditions/data/ActuallyAdditionsData.java @@ -66,6 +66,8 @@ public class ActuallyAdditionsData { generator.addProvider(true, new PachouliGenerator(packOutput)); + generator.addProvider(true, new GlobalLootModifierGenerator(packOutput)); + generator.addProvider(event.includeServer(), new DatapackBuiltinEntriesProvider( packOutput, patchedProvider, Set.of(ActuallyAdditions.MODID))); } diff --git a/src/main/java/de/ellpeck/actuallyadditions/data/GlobalLootModifierGenerator.java b/src/main/java/de/ellpeck/actuallyadditions/data/GlobalLootModifierGenerator.java new file mode 100644 index 000000000..2e8633d34 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/data/GlobalLootModifierGenerator.java @@ -0,0 +1,42 @@ +package de.ellpeck.actuallyadditions.data; + +import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; +import de.ellpeck.actuallyadditions.mod.lootmodifier.BatLootModifier; +import de.ellpeck.actuallyadditions.mod.lootmodifier.DungeonLootModifier; +import net.minecraft.data.PackOutput; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.predicates.AnyOfCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemKilledByPlayerCondition; +import net.neoforged.neoforge.common.data.GlobalLootModifierProvider; +import net.neoforged.neoforge.common.loot.LootTableIdCondition; + +public class GlobalLootModifierGenerator extends GlobalLootModifierProvider { + public GlobalLootModifierGenerator(PackOutput packOutput) { + super(packOutput, ActuallyAdditions.MODID); + } + + @Override + protected void start() { + this.add("bat_loot", new BatLootModifier( + new LootItemCondition[]{ + LootItemKilledByPlayerCondition.killedByPlayer().build(), + LootTableIdCondition.builder(EntityType.BAT.getDefaultLootTable()).build() + })); + this.add("dungeon_loot", new DungeonLootModifier( + new LootItemCondition[]{ + AnyOfCondition.anyOf( + LootTableIdCondition.builder(BuiltInLootTables.SIMPLE_DUNGEON), + LootTableIdCondition.builder(BuiltInLootTables.ABANDONED_MINESHAFT), + LootTableIdCondition.builder(BuiltInLootTables.VILLAGE_WEAPONSMITH), + LootTableIdCondition.builder(BuiltInLootTables.STRONGHOLD_LIBRARY), + LootTableIdCondition.builder(BuiltInLootTables.IGLOO_CHEST), + LootTableIdCondition.builder(BuiltInLootTables.DESERT_PYRAMID), + LootTableIdCondition.builder(BuiltInLootTables.NETHER_BRIDGE), + LootTableIdCondition.builder(BuiltInLootTables.END_CITY_TREASURE), + LootTableIdCondition.builder(BuiltInLootTables.WOODLAND_MANSION) + ).build() + })); + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/ActuallyAdditions.java b/src/main/java/de/ellpeck/actuallyadditions/mod/ActuallyAdditions.java index d6a4f9b64..c885262a8 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/ActuallyAdditions.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/ActuallyAdditions.java @@ -35,6 +35,7 @@ import de.ellpeck.actuallyadditions.mod.inventory.ActuallyContainers; import de.ellpeck.actuallyadditions.mod.items.ActuallyItems; import de.ellpeck.actuallyadditions.mod.items.ItemCoffee; import de.ellpeck.actuallyadditions.mod.items.Worm; +import de.ellpeck.actuallyadditions.mod.lootmodifier.ActuallyLootModifiers; import de.ellpeck.actuallyadditions.mod.misc.BannerHelper; import de.ellpeck.actuallyadditions.mod.misc.apiimpl.LaserRelayConnectionHandler; import de.ellpeck.actuallyadditions.mod.misc.apiimpl.MethodHandler; @@ -116,6 +117,7 @@ public class ActuallyAdditions { ActuallyVillagers.init(eventBus); ActuallyPOITypes.init(eventBus); ActuallyAttachments.init(eventBus); + ActuallyLootModifiers.init(eventBus); ActuallyContainers.CONTAINERS.register(eventBus); ENTITIES.register(eventBus); CONDITION_CODECS.register(eventBus); diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/config/CommonConfig.java b/src/main/java/de/ellpeck/actuallyadditions/mod/config/CommonConfig.java index c7b626cb9..62a8b319f 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/config/CommonConfig.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/config/CommonConfig.java @@ -87,6 +87,7 @@ public class CommonConfig { public static ModConfigSpec.BooleanValue DO_UPDATE_CHECK; public static ModConfigSpec.BooleanValue UPDATE_CHECK_VERSION_SPECIFIC; public static ModConfigSpec.BooleanValue DO_CAT_DROPS; + public static ModConfigSpec.BooleanValue DO_BAT_DROPS; public static ModConfigSpec.IntValue FUR_CHANCE; public static ModConfigSpec.BooleanValue WORMS; public static ModConfigSpec.IntValue WORMS_DIE_TIME; @@ -121,6 +122,9 @@ public class CommonConfig { DO_CAT_DROPS = BUILDER.comment("If true, Cats drop Hairy Balls Occasionally.") .define("doCatDrops", true); + DO_BAT_DROPS = BUILDER.comment("Should Bat wings drop from Bats?") + .define("doBatDrops", true); + FUR_CHANCE = BUILDER.comment("The 1/n drop chance, per tick, for a fur ball to be dropped.") .defineInRange("furDropChance", 5000, 1, Integer.MAX_VALUE); diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/ActuallyLootModifiers.java b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/ActuallyLootModifiers.java new file mode 100644 index 000000000..452a47b4d --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/ActuallyLootModifiers.java @@ -0,0 +1,21 @@ +package de.ellpeck.actuallyadditions.mod.lootmodifier; + +import com.mojang.serialization.Codec; +import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.common.loot.IGlobalLootModifier; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; + +import java.util.function.Supplier; + +public class ActuallyLootModifiers { + private static final DeferredRegister> GLM = DeferredRegister.create(NeoForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, ActuallyAdditions.MODID); + + public static final Supplier> BAT_LOOT = GLM.register("bat_loot", BatLootModifier.CODEC); + public static final Supplier> DUNGEON_LOOT = GLM.register("dungeon_loot", DungeonLootModifier.CODEC); + + public static void init(IEventBus evt) { + GLM.register(evt); + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/BatLootModifier.java b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/BatLootModifier.java new file mode 100644 index 000000000..c95fe0ca7 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/BatLootModifier.java @@ -0,0 +1,47 @@ +package de.ellpeck.actuallyadditions.mod.lootmodifier; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.ellpeck.actuallyadditions.mod.config.CommonConfig; +import de.ellpeck.actuallyadditions.mod.items.ActuallyItems; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.ambient.Bat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.neoforged.neoforge.common.loot.IGlobalLootModifier; +import net.neoforged.neoforge.common.loot.LootModifier; + +public class BatLootModifier extends LootModifier { + public static final Supplier> CODEC = Suppliers.memoize(() -> + RecordCodecBuilder.create(inst -> codecStart(inst).apply(inst, BatLootModifier::new))); + + public BatLootModifier(LootItemCondition[] conditionsIn) { + super(conditionsIn); + } + + @Override + protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { + RandomSource random = context.getRandom(); + if (CommonConfig.Other.DO_BAT_DROPS.get() && + context.hasParam(LootContextParams.KILLER_ENTITY) && + context.hasParam(LootContextParams.DAMAGE_SOURCE) && + context.hasParam(LootContextParams.THIS_ENTITY) && + context.getParam(LootContextParams.THIS_ENTITY) instanceof Bat) { + int looting = context.getLootingModifier(); + if (random.nextInt(15) <= looting * 2) { + generatedLoot.add(new ItemStack(ActuallyItems.BATS_WING.get(), random.nextInt(2 + looting) + 1)); + } + } + return generatedLoot; + } + + @Override + public Codec codec() { + return CODEC.get(); + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/DungeonLootModifier.java b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/DungeonLootModifier.java new file mode 100644 index 000000000..9f7f771a7 --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/lootmodifier/DungeonLootModifier.java @@ -0,0 +1,141 @@ +package de.ellpeck.actuallyadditions.mod.lootmodifier; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.ellpeck.actuallyadditions.api.ActuallyTags; +import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; +import de.ellpeck.actuallyadditions.mod.blocks.ActuallyBlocks; +import de.ellpeck.actuallyadditions.mod.config.CommonConfig; +import de.ellpeck.actuallyadditions.mod.items.ActuallyItems; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.neoforged.neoforge.common.loot.IGlobalLootModifier; +import net.neoforged.neoforge.common.loot.LootModifier; + +public class DungeonLootModifier extends LootModifier { + public static final Supplier> CODEC = Suppliers.memoize(() -> + RecordCodecBuilder.create(inst -> codecStart(inst).apply(inst, DungeonLootModifier::new))); + + public DungeonLootModifier(LootItemCondition[] conditionsIn) { + super(conditionsIn); + } + + @Override + protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { + RandomSource random = context.getRandom(); + if (CommonConfig.Other.DUNGEON_LOOT.get()) { + ResourceLocation lootTable = context.getQueriedLootTableId(); + boolean addCrystals = false; + boolean addDrillCore = false; + boolean addQuartz = false; + boolean addBatWings = false; + if (BuiltInLootTables.SIMPLE_DUNGEON.equals(lootTable)) { + addCrystals = true; + addDrillCore = true; + addQuartz = true; + } else if (BuiltInLootTables.ABANDONED_MINESHAFT.equals(lootTable)) { + addCrystals = true; + addDrillCore = true; + } else if (BuiltInLootTables.VILLAGE_WEAPONSMITH.equals(lootTable)) { + addDrillCore = true; + addQuartz = true; + } else if (BuiltInLootTables.STRONGHOLD_LIBRARY.equals(lootTable)) { + addBatWings = true; + } else if (BuiltInLootTables.IGLOO_CHEST.equals(lootTable)) { + addBatWings = true; + } else if (BuiltInLootTables.DESERT_PYRAMID.equals(lootTable)) { + addDrillCore = true; + addBatWings = true; + } else if (BuiltInLootTables.NETHER_BRIDGE.equals(lootTable)) { + addBatWings = true; + addCrystals = true; + addDrillCore = true; + } else if (BuiltInLootTables.END_CITY_TREASURE.equals(lootTable)) { + addBatWings = true; + addCrystals = true; + addDrillCore = true; + addQuartz = true; + } else if (BuiltInLootTables.WOODLAND_MANSION.equals(lootTable)) { + addBatWings = true; + addCrystals = true; + addDrillCore = true; + addQuartz = true; + } + + if (addCrystals) { +// LootFunction damage = new SetMetadata(noCondition, new RandomValueRange(0, TheCrystals.values().length - 1)); +// LootFunction amount = new SetCount(noCondition, new RandomValueRange(1, 3)); +// LootFunction[] functions = new LootFunction[] { damage, amount }; +// pool.addEntry(new LootEntryItem(InitItems.itemCrystal, 20, 0, functions, noCondition, ActuallyAdditions.MODID + ":crystalItems")); +// pool.addEntry(new LootEntryItem(Item.getItemFromBlock(InitBlocks.blockCrystal), 3, 0, functions, noCondition, ActuallyAdditions.MODID + ":crystalBlocks")); + if (random.nextInt(5) == 0) { + int count = random.nextInt(3) + 1; + Item crystal = getRandomItem(random, ActuallyTags.Items.CRYSTALS, ActuallyItems.RESTONIA_CRYSTAL.get()); + generatedLoot.add(new ItemStack(crystal, count)); + } + + if (random.nextInt(15) == 0) { + int count = random.nextInt(3) + 1; + Item crystal = getRandomItem(random, ActuallyTags.Items.CRYSTAL_BLOCKS, ActuallyBlocks.RESTONIA_CRYSTAL.getItem()); + generatedLoot.add(new ItemStack(crystal, count)); + } + } + if (addDrillCore) { + System.out.println("Deciding to add drill core or not"); + if (random.nextInt(10) == 0) { + generatedLoot.add(new ItemStack(ActuallyItems.DRILL_CORE.get())); + } +// LootFunction damage = new SetMetadata(noCondition, new RandomValueRange(TheMiscItems.DRILL_CORE.ordinal())); +// pool.addEntry(new LootEntryItem(InitItems.itemMisc, 5, 0, new LootFunction[] { damage }, noCondition, ActuallyAdditions.MODID + ":drillCore")); + } + if (addQuartz) { + if (random.nextInt(5) == 0) { + int count = random.nextInt(5) + 1; + generatedLoot.add(new ItemStack(ActuallyItems.BLACK_QUARTZ.get(), count)); + } +// LootFunction damage = new SetMetadata(noCondition, new RandomValueRange(TheMiscItems.QUARTZ.ordinal())); +// LootFunction amount = new SetCount(noCondition, new RandomValueRange(1, 5)); +// pool.addEntry(new LootEntryItem(InitItems.itemMisc, 20, 0, new LootFunction[] { damage, amount }, noCondition, ActuallyAdditions.MODID + ":quartz")); + } + if (addBatWings) { + if (random.nextInt(10) == 0) { + int count = random.nextInt(2) + 1; + generatedLoot.add(new ItemStack(ActuallyItems.BATS_WING.get(), count)); + } +// LootFunction damage = new SetMetadata(noCondition, new RandomValueRange(TheMiscItems.BAT_WING.ordinal())); +// LootFunction amount = new SetCount(noCondition, new RandomValueRange(1, 2)); +// pool.addEntry(new LootEntryItem(InitItems.itemMisc, 5, 0, new LootFunction[] { damage, amount }, noCondition, ActuallyAdditions.MODID + ":batWings")); + } + } + return generatedLoot; + } + + private Item getRandomItem(RandomSource random, TagKey tagKey, Item defaultItem) { + HolderSet.Named holderSet = BuiltInRegistries.ITEM.getTag(tagKey).orElse(null); + if (holderSet != null) { + Holder itemHolder = holderSet.getRandomElement(random).orElse(null); + if (itemHolder != null) { + return itemHolder.value(); + } + } + return defaultItem; + } + + @Override + public Codec codec() { + return CODEC.get(); + } +}