From ab46816313ca43aa7027ac5873c46bd85b2c07a3 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Thu, 12 Feb 2026 23:56:25 +0100 Subject: [PATCH 1/2] Backport 0.5.0 Preview 1 for 1.21.3 to 1.21.1 (#72) --- .../ClientPlayNetworkHandlerExtender.java | 6 +- .../itematic/data/server/RecipeProvider.java | 130 +++++++++++++- .../block/BrewingStandBlockTestSuite.java | 160 ++++++++++++++++++ .../item/TotemOfUndyingTestSuite.java | 31 ++++ .../WeaponItemComponentTestSuite.java | 12 +- .../structure/block.brewing_stand.snbt | 39 +++++ src/gametest/resources/fabric.mod.json | 2 + .../data/minecraft/item/allay_spawn_egg.json | 9 +- .../minecraft/item/armadillo_spawn_egg.json | 9 +- .../minecraft/item/axolotl_spawn_egg.json | 9 +- .../data/minecraft/item/bat_spawn_egg.json | 9 +- .../data/minecraft/item/bee_spawn_egg.json | 9 +- .../data/minecraft/item/beetroot_soup.json | 8 +- .../data/minecraft/item/blaze_spawn_egg.json | 9 +- .../data/minecraft/item/bogged_spawn_egg.json | 9 +- .../data/minecraft/item/breeze_spawn_egg.json | 9 +- .../data/minecraft/item/camel_spawn_egg.json | 9 +- .../data/minecraft/item/cat_spawn_egg.json | 9 +- .../minecraft/item/cave_spider_spawn_egg.json | 9 +- .../data/minecraft/item/chicken.json | 35 ++-- .../minecraft/item/chicken_spawn_egg.json | 9 +- .../data/minecraft/item/cod_spawn_egg.json | 9 +- .../data/minecraft/item/cow_spawn_egg.json | 9 +- .../minecraft/item/creeper_spawn_egg.json | 9 +- .../minecraft/item/dolphin_spawn_egg.json | 9 +- .../data/minecraft/item/donkey_spawn_egg.json | 9 +- .../data/minecraft/item/dragon_breath.json | 3 - .../minecraft/item/drowned_spawn_egg.json | 9 +- .../item/elder_guardian_spawn_egg.json | 9 +- .../item/enchanted_golden_apple.json | 53 +++--- .../item/ender_dragon_spawn_egg.json | 9 +- .../minecraft/item/enderman_spawn_egg.json | 9 +- .../minecraft/item/endermite_spawn_egg.json | 9 +- .../data/minecraft/item/evoker_spawn_egg.json | 9 +- .../data/minecraft/item/fox_spawn_egg.json | 9 +- .../data/minecraft/item/frog_spawn_egg.json | 9 +- .../data/minecraft/item/ghast_spawn_egg.json | 9 +- .../minecraft/item/glow_squid_spawn_egg.json | 9 +- .../data/minecraft/item/goat_spawn_egg.json | 9 +- .../data/minecraft/item/golden_apple.json | 38 +++-- .../data/minecraft/item/golden_axe.json | 8 +- .../data/minecraft/item/golden_hoe.json | 8 +- .../data/minecraft/item/golden_pickaxe.json | 8 +- .../data/minecraft/item/golden_shovel.json | 8 +- .../data/minecraft/item/golden_sword.json | 8 +- .../minecraft/item/guardian_spawn_egg.json | 9 +- .../data/minecraft/item/hoglin_spawn_egg.json | 9 +- .../data/minecraft/item/honey_bottle.json | 8 +- .../data/minecraft/item/horse_spawn_egg.json | 9 +- .../data/minecraft/item/husk_spawn_egg.json | 9 +- .../minecraft/item/iron_golem_spawn_egg.json | 9 +- .../data/minecraft/item/lava_bucket.json | 7 +- .../data/minecraft/item/llama_spawn_egg.json | 9 +- .../minecraft/item/magma_cube_spawn_egg.json | 9 +- .../data/minecraft/item/milk_bucket.json | 8 +- .../minecraft/item/mooshroom_spawn_egg.json | 9 +- .../data/minecraft/item/mule_spawn_egg.json | 9 +- .../data/minecraft/item/mushroom_stew.json | 8 +- .../data/minecraft/item/ocelot_spawn_egg.json | 9 +- .../data/minecraft/item/panda_spawn_egg.json | 9 +- .../data/minecraft/item/parrot_spawn_egg.json | 9 +- .../minecraft/item/phantom_spawn_egg.json | 9 +- .../data/minecraft/item/pig_spawn_egg.json | 9 +- .../item/piglin_brute_spawn_egg.json | 9 +- .../data/minecraft/item/piglin_spawn_egg.json | 9 +- .../minecraft/item/pillager_spawn_egg.json | 9 +- .../data/minecraft/item/poisonous_potato.json | 35 ++-- .../minecraft/item/polar_bear_spawn_egg.json | 9 +- .../generated/data/minecraft/item/potion.json | 5 +- .../data/minecraft/item/pufferfish.json | 46 ++--- .../minecraft/item/pufferfish_spawn_egg.json | 9 +- .../data/minecraft/item/rabbit_spawn_egg.json | 9 +- .../data/minecraft/item/rabbit_stew.json | 8 +- .../minecraft/item/ravager_spawn_egg.json | 9 +- .../data/minecraft/item/rotten_flesh.json | 35 ++-- .../data/minecraft/item/salmon_spawn_egg.json | 9 +- .../data/minecraft/item/sheep_spawn_egg.json | 9 +- .../generated/data/minecraft/item/shield.json | 5 +- .../minecraft/item/shulker_spawn_egg.json | 9 +- .../minecraft/item/silverfish_spawn_egg.json | 9 +- .../item/skeleton_horse_spawn_egg.json | 9 +- .../minecraft/item/skeleton_spawn_egg.json | 9 +- .../data/minecraft/item/slime_spawn_egg.json | 9 +- .../minecraft/item/sniffer_spawn_egg.json | 9 +- .../minecraft/item/snow_golem_spawn_egg.json | 9 +- .../data/minecraft/item/spider_eye.json | 24 ++- .../data/minecraft/item/spider_spawn_egg.json | 9 +- .../data/minecraft/item/squid_spawn_egg.json | 9 +- .../data/minecraft/item/stray_spawn_egg.json | 9 +- .../minecraft/item/strider_spawn_egg.json | 9 +- .../data/minecraft/item/suspicious_stew.json | 8 +- .../minecraft/item/tadpole_spawn_egg.json | 9 +- .../data/minecraft/item/totem_of_undying.json | 50 ++++-- .../item/trader_llama_spawn_egg.json | 9 +- .../item/tropical_fish_spawn_egg.json | 9 +- .../data/minecraft/item/turtle_spawn_egg.json | 9 +- .../data/minecraft/item/vex_spawn_egg.json | 9 +- .../minecraft/item/villager_spawn_egg.json | 9 +- .../minecraft/item/vindicator_spawn_egg.json | 9 +- .../item/wandering_trader_spawn_egg.json | 9 +- .../data/minecraft/item/warden_spawn_egg.json | 9 +- .../data/minecraft/item/water_bucket.json | 3 - .../data/minecraft/item/witch_spawn_egg.json | 9 +- .../item/wither_skeleton_spawn_egg.json | 9 +- .../data/minecraft/item/wither_spawn_egg.json | 9 +- .../data/minecraft/item/wolf_spawn_egg.json | 9 +- .../data/minecraft/item/zoglin_spawn_egg.json | 9 +- .../item/zombie_horse_spawn_egg.json | 9 +- .../data/minecraft/item/zombie_spawn_egg.json | 9 +- .../item/zombie_villager_spawn_egg.json | 9 +- .../item/zombified_piglin_spawn_egg.json | 9 +- .../generated/data/minecraft/recipe/cake.json | 33 ++++ .../data/minecraft/recipe/honey_block.json | 23 +++ .../shulker_box_coloring_black.json | 0 .../shulker_box_coloring_blue.json | 0 .../shulker_box_coloring_brown.json | 0 .../shulker_box_coloring_cyan.json | 0 .../shulker_box_coloring_gray.json | 0 .../shulker_box_coloring_green.json | 0 .../shulker_box_coloring_light_blue.json | 0 .../shulker_box_coloring_light_gray.json | 0 .../shulker_box_coloring_lime.json | 0 .../shulker_box_coloring_magenta.json | 0 .../shulker_box_coloring_orange.json | 0 .../shulker_box_coloring_pink.json | 0 .../shulker_box_coloring_purple.json | 0 .../shulker_box_coloring_red.json | 0 .../shulker_box_coloring_white.json | 0 .../shulker_box_coloring_yellow.json | 0 .../recipe/sugar_from_honey_bottle.json | 19 +++ .../access/entity/LivingEntityAccess.java | 1 + .../itematic/access/item/ItemAccess.java | 3 + .../itematic/access/item/ItemStackAccess.java | 7 + .../access/recipe/IngredientAccess.java | 6 + .../access/recipe/RawShapedRecipeAccess.java | 9 + .../component/ItematicDataComponentTypes.java | 2 + .../type/UseCooldownDataComponent.java | 32 ++++ .../type/UseDurationDataComponent.java | 33 ++-- .../type/UseRemainderDataComponent.java | 40 +++++ .../type/WeaponAttackDamageDataComponent.java | 16 +- .../entity/effect/StatusEffectKeys.java | 15 +- .../errorcraft/itematic/item/ItemUtil.java | 92 ++++++++-- .../item/component/ItemComponent.java | 4 +- .../item/component/ItemComponentTypes.java | 3 - .../components/BlockItemComponent.java | 4 +- .../components/BrushItemComponent.java | 2 +- .../components/ConsumableItemComponent.java | 21 +-- .../components/CooldownItemComponent.java | 23 ++- .../components/DamageableItemComponent.java | 12 +- .../components/EntityItemComponent.java | 112 +++++++++--- .../components/FoodItemComponent.java | 18 +- .../components/FuelItemComponent.java | 22 ++- .../components/LifeSavingItemComponent.java | 37 ---- .../components/PlayableItemComponent.java | 2 +- .../RecipeRemainderItemComponent.java | 31 ---- .../components/ShooterItemComponent.java | 6 +- .../components/SpawnEggItemComponent.java | 24 +-- .../components/ThrowableItemComponent.java | 8 +- .../components/UseableItemComponent.java | 35 +++- .../UseableOnFluidItemComponent.java | 43 ----- .../components/WeaponItemComponent.java | 4 +- .../components/ZoomItemComponent.java | 3 +- .../itematic/item/event/ItemEventKeys.java | 1 + .../itematic/item/event/ItemEventMap.java | 4 + .../itematic/item/event/ItemEvents.java | 1 + .../item/shooter/method/ShooterMethod.java | 2 +- .../methods/ChargeableShooterMethod.java | 7 +- .../method/methods/DirectShooterMethod.java | 8 +- .../use/provider/IntegerProviderTypeKeys.java | 1 + .../use/provider/IntegerProviderTypes.java | 1 + .../providers/IndefiniteIntegerProvider.java | 31 ++++ .../loot/predicate/SideCheckPredicate.java | 4 +- .../AbstractFurnaceBlockEntityExtender.java | 7 +- .../BrewingStandBlockEntityExtender.java | 36 ++-- .../component/type/FoodComponentExtender.java | 32 ++++ .../mixin/entity/LivingEntityExtender.java | 26 +-- .../player/ServerPlayerEntityExtender.java | 10 +- .../itematic/mixin/item/ItemExtender.java | 53 +++--- .../mixin/item/ItemStackExtender.java | 75 +++++++- .../recipe/BannerDuplicateRecipeExtender.java | 16 -- .../recipe/BookCloningRecipeExtender.java | 18 +- .../mixin/recipe/IngredientExtender.java | 66 +++++++- .../mixin/recipe/RawShapedRecipeExtender.java | 51 ++++++ .../itematic/mixin/recipe/RecipeExtender.java | 21 --- .../mixin/recipe/ShapedRecipeExtender.java | 24 +++ .../mixin/recipe/ShapelessRecipeExtender.java | 47 +++++ .../item/ItemPredicateExtraFields.java | 6 +- .../serialization/ItematicCodecs.java | 44 ----- .../itematic/serialization/SetCodec.java | 58 +++++++ .../itematic/world/action/ActionTypeKeys.java | 1 + .../itematic/world/action/ActionTypes.java | 1 + .../actions/AddStatusEffectsAction.java | 45 +++++ src/main/resources/fabric.mod.json | 3 - src/main/resources/itematic.classtweaker | 1 + src/main/resources/itematic.mixins.json | 4 + 195 files changed, 2094 insertions(+), 883 deletions(-) create mode 100644 src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java create mode 100644 src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java create mode 100644 src/gametest/resources/data/itematic/gametest/structure/block.brewing_stand.snbt create mode 100644 src/main/generated/data/minecraft/recipe/cake.json create mode 100644 src/main/generated/data/minecraft/recipe/honey_block.json rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_black.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_blue.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_brown.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_cyan.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_gray.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_green.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_light_blue.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_light_gray.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_lime.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_magenta.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_orange.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_pink.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_purple.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_red.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_white.json (100%) rename src/main/generated/data/minecraft/{recipes => recipe}/shulker_box_coloring_yellow.json (100%) create mode 100644 src/main/generated/data/minecraft/recipe/sugar_from_honey_bottle.json create mode 100644 src/main/java/net/errorcraft/itematic/access/recipe/RawShapedRecipeAccess.java create mode 100644 src/main/java/net/errorcraft/itematic/component/type/UseCooldownDataComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/component/type/UseRemainderDataComponent.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/LifeSavingItemComponent.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/RecipeRemainderItemComponent.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/UseableOnFluidItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/item/use/provider/providers/IndefiniteIntegerProvider.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/recipe/RawShapedRecipeExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/recipe/ShapedRecipeExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/recipe/ShapelessRecipeExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/serialization/SetCodec.java create mode 100644 src/main/java/net/errorcraft/itematic/world/action/actions/AddStatusEffectsAction.java diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayNetworkHandlerExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayNetworkHandlerExtender.java index ab028ced..e94133c6 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayNetworkHandlerExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayNetworkHandlerExtender.java @@ -2,7 +2,7 @@ import net.errorcraft.itematic.access.network.listener.ClientPlayPacketListenerAccess; import net.errorcraft.itematic.item.ItemKeys; -import net.errorcraft.itematic.item.component.ItemComponentTypes; +import net.errorcraft.itematic.item.event.ItemEvents; import net.errorcraft.itematic.network.packet.s2c.play.TwirlS2CPacket; import net.errorcraft.itematic.world.action.actions.TwirlPlayerAction; import net.minecraft.client.MinecraftClient; @@ -36,8 +36,8 @@ protected ClientPlayNetworkHandlerExtender(MinecraftClient client, ClientConnect target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" ) ) - private static boolean isOfForTotemOfUndyingUseItemComponentCheck(ItemStack instance, Item item) { - return instance.itematic$hasComponent(ItemComponentTypes.LIFE_SAVING); + private static boolean isOfForTotemOfUndyingUseEventListenerCheck(ItemStack instance, Item item) { + return instance.itematic$hasEventListener(ItemEvents.BEFORE_DEATH_HOLDER); } @Redirect( diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/RecipeProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/RecipeProvider.java index a7c35f37..7a5f4bf1 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/server/RecipeProvider.java +++ b/src/datagen/java/net/errorcraft/itematic/data/server/RecipeProvider.java @@ -1,33 +1,67 @@ package net.errorcraft.itematic.data.server; +import it.unimi.dsi.fastutil.chars.Char2ObjectMap; +import it.unimi.dsi.fastutil.chars.Char2ObjectOpenHashMap; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.ItematicItemTags; import net.errorcraft.itematic.recipe.ItemColoringRecipe; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricCodecDataProvider; import net.minecraft.data.DataOutput; +import net.minecraft.data.server.recipe.CraftingRecipeJsonBuilder; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.*; import net.minecraft.recipe.book.CraftingRecipeCategory; +import net.minecraft.recipe.book.RecipeCategory; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; +@SuppressWarnings("SameParameterValue") public class RecipeProvider extends FabricCodecDataProvider> { public RecipeProvider(FabricDataOutput dataOutput, CompletableFuture registriesFuture) { - super(dataOutput, registriesFuture, DataOutput.OutputType.DATA_PACK, "recipes", Recipe.CODEC); + super(dataOutput, registriesFuture, DataOutput.OutputType.DATA_PACK, "recipe", Recipe.CODEC); } @Override protected void configure(BiConsumer> provider, RegistryWrapper.WrapperLookup lookup) { RegistryWrapper.Impl items = lookup.getWrapperOrThrow(RegistryKeys.ITEM); + provider.accept( + Identifier.ofVanilla("honey_block"), + shapedRecipe(RecipeCategory.FOOD, items.getOrThrow(ItemKeys.HONEY_BLOCK)) + .input('#', items.getOrThrow(ItemKeys.HONEY_BOTTLE), items.getOrThrow(ItemKeys.GLASS_BOTTLE)) + .pattern("##") + .pattern("##") + .build() + ); + provider.accept( + Identifier.ofVanilla("sugar_from_honey_bottle"), + shapelessRecipe(RecipeCategory.MISC, items.getOrThrow(ItemKeys.SUGAR), 3) + .input(items.getOrThrow(ItemKeys.HONEY_BOTTLE), 1, items.getOrThrow(ItemKeys.GLASS_BOTTLE)) + .build() + ); + provider.accept( + Identifier.ofVanilla("cake"), + shapedRecipe(RecipeCategory.FOOD, items.getOrThrow(ItemKeys.CAKE)) + .input('A', items.getOrThrow(ItemKeys.MILK_BUCKET), items.getOrThrow(ItemKeys.BUCKET)) + .input('B', items.getOrThrow(ItemKeys.SUGAR)) + .input('C', items.getOrThrow(ItemKeys.WHEAT)) + .input('E', items.getOrThrow(ItemKeys.EGG)) + .pattern("AAA") + .pattern("BEB") + .pattern("CCC") + .build() + ); provider.accept(Identifier.ofVanilla("shulker_box_coloring_black"), colorShulkerBox( DyeColor.BLACK, items.getOrThrow(ItemKeys.BLACK_SHULKER_BOX) @@ -102,4 +136,94 @@ public String getName() { private static ItemColoringRecipe colorShulkerBox(DyeColor color, RegistryEntry result) { return new ItemColoringRecipe(CraftingRecipeCategory.MISC, Ingredient.fromTag(ItematicItemTags.SHULKER_BOXES), color, new ItemStack(result)); } + + private static ShapelessRecipeBuilder shapelessRecipe(RecipeCategory category, RegistryEntry result, int count) { + return new ShapelessRecipeBuilder(new ItemStack(result, count), category); + } + + private static ShapedRecipeBuilder shapedRecipe(RecipeCategory category, RegistryEntry result) { + return new ShapedRecipeBuilder(new ItemStack(result), category); + } + + private static class ShapelessRecipeBuilder { + private final ItemStack result; + private final RecipeCategory category; + private final DefaultedList inputs = DefaultedList.of(); + + private ShapelessRecipeBuilder(ItemStack result, RecipeCategory category) { + this.result = result; + this.category = category; + } + + public ShapelessRecipe build() { + return new ShapelessRecipe( + "", + CraftingRecipeJsonBuilder.toCraftingCategory(this.category), + this.result, + this.inputs + ); + } + + public ShapelessRecipeBuilder input(RegistryEntry input) { + this.inputs.add(Ingredient.ofStacks(new ItemStack(input))); + return this; + } + + public ShapelessRecipeBuilder input(RegistryEntry input, int count) { + for (int i = 0; i < count; i++) { + this.inputs.add(Ingredient.ofStacks(new ItemStack(input))); + } + + return this; + } + + public ShapelessRecipeBuilder input(RegistryEntry input, int count, RegistryEntry remainder) { + for (int i = 0; i < count; i++) { + Ingredient ingredient = Ingredient.ofStacks(new ItemStack(input)); + ingredient.itematic$setRemainder(Optional.of(new ItemStack(remainder))); + this.inputs.add(ingredient); + } + + return this; + } + } + + private static class ShapedRecipeBuilder { + private final ItemStack result; + private final RecipeCategory category; + private final Char2ObjectMap inputs = new Char2ObjectOpenHashMap<>(); + private final List pattern = new ArrayList<>(); + + private ShapedRecipeBuilder(ItemStack result, RecipeCategory category) { + this.result = result; + this.category = category; + } + + public ShapedRecipe build() { + return new ShapedRecipe( + "", + CraftingRecipeJsonBuilder.toCraftingCategory(this.category), + RawShapedRecipe.create(this.inputs, this.pattern), + this.result, + true + ); + } + + public ShapedRecipeBuilder input(char key, RegistryEntry input) { + this.inputs.put(key, Ingredient.ofStacks(new ItemStack(input))); + return this; + } + + public ShapedRecipeBuilder input(char key, RegistryEntry input, RegistryEntry remainder) { + Ingredient ingredient = Ingredient.ofStacks(new ItemStack(input)); + ingredient.itematic$setRemainder(Optional.of(new ItemStack(remainder))); + this.inputs.put(key, ingredient); + return this; + } + + public ShapedRecipeBuilder pattern(String pattern) { + this.pattern.add(pattern); + return this; + } + } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java new file mode 100644 index 00000000..7431fea5 --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java @@ -0,0 +1,160 @@ +package net.errorcraft.itematic.gametest.block; + +import net.errorcraft.itematic.component.PotionContentsComponentUtil; +import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potions; +import net.minecraft.screen.BrewingStandScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.test.GameTest; +import net.minecraft.test.TestContext; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameMode; + +public class BrewingStandBlockTestSuite { + private static final BlockPos BLOCK_POSITION = new BlockPos(1, 2, 1); + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingWaterBottleWithNetherWartTurnsItIntoAwkwardPotion(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.WATER)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.NETHER_WART)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); + Assert.itemStackHasPotion(resultPotion, Potions.AWKWARD); + } + ) + .completeIfSuccessful(); + } + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingAwkwardPotionWithSugarTurnsItIntoSwiftnessPotion(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.AWKWARD)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.SUGAR)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); + Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + } + ) + .completeIfSuccessful(); + } + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingSwiftnessPotionWithGlowstoneDustTurnsItIntoStrongSwiftnessPotion(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.SWIFTNESS)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.GLOWSTONE_DUST)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); + Assert.itemStackHasPotion(resultPotion, Potions.STRONG_SWIFTNESS); + } + ) + .completeIfSuccessful(); + } + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingSwiftnessPotionWithRedstoneTurnsItIntoLongSwiftnessPotion(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.SWIFTNESS)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.REDSTONE)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); + Assert.itemStackHasPotion(resultPotion, Potions.LONG_SWIFTNESS); + } + ) + .completeIfSuccessful(); + } + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingSwiftnessPotionWithGunpowderTurnsItIntoSwiftnessSplashPotion(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.SWIFTNESS)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.GUNPOWDER)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.SPLASH_POTION); + Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + } + ) + .completeIfSuccessful(); + } + + @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + public void brewingSwiftnessSplashPotionWithDragonBreathTurnsItIntoSwiftnessLingeringPotionAndLeavesGlassBottle(TestContext context) { + ServerWorld world = context.getWorld(); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + BrewingStandScreenHandler brewingStandMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.BREWING_STAND); + brewingStandMenu.getSlot(0) + .setStack(PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.SPLASH_POTION), Potions.SWIFTNESS)); + brewingStandMenu.getSlot(3) + .setStack(world.itematic$createStack(ItemKeys.DRAGON_BREATH)); + brewingStandMenu.getSlot(4) + .setStack(world.itematic$createStack(ItemKeys.BLAZE_POWDER)); + context.createTimedTaskRunner() + .expectMinDurationAndRun( + 401, + () -> { + ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); + Assert.itemStackIsOf(resultPotion, ItemKeys.LINGERING_POTION); + Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + ItemStack ingredientRemainder = brewingStandMenu.getSlot(3).getStack(); + Assert.itemStackIsOf(ingredientRemainder, ItemKeys.GLASS_BOTTLE); + } + ) + .completeIfSuccessful(); + } +} \ No newline at end of file diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java new file mode 100644 index 00000000..239498bd --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java @@ -0,0 +1,31 @@ +package net.errorcraft.itematic.gametest.item; + +import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.test.GameTest; +import net.minecraft.test.TestContext; +import net.minecraft.util.Hand; +import net.minecraft.world.GameMode; + +public class TotemOfUndyingTestSuite { + @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + public void holdingTotemOfUndyingSavesHolderFromDeath(TestContext context) { + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + ServerWorld world = context.getWorld(); + ItemStack stack = world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING); + player.setStackInHand(Hand.MAIN_HAND, stack); + player.damage(world.getDamageSources().fall(), Float.MAX_VALUE); + context.addInstantFinalTask(() -> { + Assert.areFloatsEqual(player.getHealth(), 1.0f, (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead"); + context.expectEntityHasEffect(player, StatusEffects.REGENERATION, 1); + context.expectEntityHasEffect(player, StatusEffects.ABSORPTION, 1); + context.expectEntityHasEffect(player, StatusEffects.FIRE_RESISTANCE, 0); + Assert.itemStackIsEmpty(player.getStackInHand(Hand.MAIN_HAND)); + }); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/WeaponItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/WeaponItemComponentTestSuite.java index 70ec90a4..72132393 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/WeaponItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/WeaponItemComponentTestSuite.java @@ -38,7 +38,7 @@ public void zombieAttackingUnarmedDealsDamageFromTrueBaseValueAttackDamageAttrib } @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) - public void zombieAttackingWithIronSwordDealsDamageFromIronSword(TestContext context) { + public void zombieAttackingWithIronSwordDealsCorrectDamage(TestContext context) { ServerWorld world = context.getWorld(); ItemStack stack = world.itematic$createStack(ItemKeys.IRON_SWORD); ZombieEntity zombie = TestUtil.createEntity(context, EntityType.ZOMBIE, entity -> entity.setStackInHand(Hand.MAIN_HAND, stack)); @@ -48,14 +48,14 @@ public void zombieAttackingWithIronSwordDealsDamageFromIronSword(TestContext con context.assertTrue(zombie.tryAttack(victim), "Expected attack to be successful"); Assert.areDoublesEqual( victim.getHealth(), - MAX_HEALTH_VICTIM - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), + MAX_HEALTH_VICTIM - zombie.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE) - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" ); }).completeIfSuccessful(); } @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) - public void piglinAttackingWithIronSwordDealsDamageFromIronSword(TestContext context) { + public void piglinAttackingWithIronSwordDealsCorrectDamage(TestContext context) { ServerWorld world = context.getWorld(); ItemStack stack = world.itematic$createStack(ItemKeys.IRON_SWORD); PiglinEntity piglin = TestUtil.createEntity(context, EntityType.PIGLIN, entity -> entity.setStackInHand(Hand.MAIN_HAND, stack)); @@ -65,14 +65,14 @@ public void piglinAttackingWithIronSwordDealsDamageFromIronSword(TestContext con context.assertTrue(piglin.tryAttack(victim), "Expected attack to be successful"); Assert.areDoublesEqual( victim.getHealth(), - MAX_HEALTH_VICTIM - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), + MAX_HEALTH_VICTIM - piglin.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE) - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" ); }).completeIfSuccessful(); } @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) - public void piglinAttackingWithGoldenSwordDealsDamageFromTrueBaseValueAttackDamageAttributeAndGoldenSword(TestContext context) { + public void piglinAttackingWithGoldenSwordDealsCorrectDamage(TestContext context) { ServerWorld world = context.getWorld(); ItemStack stack = world.itematic$createStack(ItemKeys.GOLDEN_SWORD); PiglinEntity piglin = TestUtil.createEntity(context, EntityType.PIGLIN, entity -> entity.setStackInHand(Hand.MAIN_HAND, stack)); @@ -82,7 +82,7 @@ public void piglinAttackingWithGoldenSwordDealsDamageFromTrueBaseValueAttackDama context.assertTrue(piglin.tryAttack(victim), "Expected attack to be successful"); Assert.areDoublesEqual( victim.getHealth(), - MAX_HEALTH_VICTIM - piglin.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE) - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().rules().getFirst().damage().orElseThrow(), + MAX_HEALTH_VICTIM - piglin.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE) - TestUtil.getItemComponent(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" ); }).completeIfSuccessful(); diff --git a/src/gametest/resources/data/itematic/gametest/structure/block.brewing_stand.snbt b/src/gametest/resources/data/itematic/gametest/structure/block.brewing_stand.snbt new file mode 100644 index 00000000..bf3b9963 --- /dev/null +++ b/src/gametest/resources/data/itematic/gametest/structure/block.brewing_stand.snbt @@ -0,0 +1,39 @@ +{ + DataVersion: 3955, + size: [3, 3, 3], + data: [ + {pos: [0, 0, 0], state: "minecraft:bedrock"}, + {pos: [0, 0, 1], state: "minecraft:bedrock"}, + {pos: [0, 0, 2], state: "minecraft:bedrock"}, + {pos: [1, 0, 0], state: "minecraft:bedrock"}, + {pos: [1, 0, 1], state: "minecraft:bedrock"}, + {pos: [1, 0, 2], state: "minecraft:bedrock"}, + {pos: [2, 0, 0], state: "minecraft:bedrock"}, + {pos: [2, 0, 1], state: "minecraft:bedrock"}, + {pos: [2, 0, 2], state: "minecraft:bedrock"}, + {pos: [0, 1, 0], state: "minecraft:air"}, + {pos: [0, 1, 1], state: "minecraft:air"}, + {pos: [0, 1, 2], state: "minecraft:air"}, + {pos: [1, 1, 0], state: "minecraft:air"}, + {pos: [1, 1, 1], state: "minecraft:brewing_stand{has_bottle_0:false,has_bottle_1:false,has_bottle_2:false}", nbt: {BrewTime: 0s, Fuel: 0b, Items: [], id: "minecraft:brewing_stand"}}, + {pos: [1, 1, 2], state: "minecraft:air"}, + {pos: [2, 1, 0], state: "minecraft:air"}, + {pos: [2, 1, 1], state: "minecraft:air"}, + {pos: [2, 1, 2], state: "minecraft:air"}, + {pos: [0, 2, 0], state: "minecraft:air"}, + {pos: [0, 2, 1], state: "minecraft:air"}, + {pos: [0, 2, 2], state: "minecraft:air"}, + {pos: [1, 2, 0], state: "minecraft:air"}, + {pos: [1, 2, 1], state: "minecraft:air"}, + {pos: [1, 2, 2], state: "minecraft:air"}, + {pos: [2, 2, 0], state: "minecraft:air"}, + {pos: [2, 2, 1], state: "minecraft:air"}, + {pos: [2, 2, 2], state: "minecraft:air"} + ], + entities: [], + palette: [ + "minecraft:bedrock", + "minecraft:air", + "minecraft:brewing_stand{has_bottle_0:false,has_bottle_1:false,has_bottle_2:false}" + ] +} diff --git a/src/gametest/resources/fabric.mod.json b/src/gametest/resources/fabric.mod.json index 40887825..22c20bef 100644 --- a/src/gametest/resources/fabric.mod.json +++ b/src/gametest/resources/fabric.mod.json @@ -9,6 +9,7 @@ "fabric-gametest": [ "net.errorcraft.itematic.gametest.block.AnvilBlockTestSuite", "net.errorcraft.itematic.gametest.block.BeehiveBlockTestSuite", + "net.errorcraft.itematic.gametest.block.BrewingStandBlockTestSuite", "net.errorcraft.itematic.gametest.block.CandleBlockTestSuite", "net.errorcraft.itematic.gametest.block.ComposterBlockTestSuite", "net.errorcraft.itematic.gametest.block.DispenserBehaviorTestSuite", @@ -37,6 +38,7 @@ "net.errorcraft.itematic.gametest.item.HoneyBottleTestSuite", "net.errorcraft.itematic.gametest.item.LeadTestSuite", "net.errorcraft.itematic.gametest.item.SignTestSuite", + "net.errorcraft.itematic.gametest.item.TotemOfUndyingTestSuite", "net.errorcraft.itematic.gametest.item.component.BlockItemComponentTestSuite", "net.errorcraft.itematic.gametest.item.component.ConsumableItemComponentTestSuite", "net.errorcraft.itematic.gametest.item.component.EquipmentItemComponentTestSuite", diff --git a/src/main/generated/data/minecraft/item/allay_spawn_egg.json b/src/main/generated/data/minecraft/item/allay_spawn_egg.json index b3453567..5038da96 100644 --- a/src/main/generated/data/minecraft/item/allay_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/allay_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:allay" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 44543 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/armadillo_spawn_egg.json b/src/main/generated/data/minecraft/item/armadillo_spawn_egg.json index 73a6405e..3fcc8b0e 100644 --- a/src/main/generated/data/minecraft/item/armadillo_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/armadillo_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:armadillo" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8538184 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/axolotl_spawn_egg.json b/src/main/generated/data/minecraft/item/axolotl_spawn_egg.json index 777419d2..e3acddcd 100644 --- a/src/main/generated/data/minecraft/item/axolotl_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/axolotl_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:axolotl" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 10890612 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/bat_spawn_egg.json b/src/main/generated/data/minecraft/item/bat_spawn_egg.json index 89cfc5f8..e8b2cf7b 100644 --- a/src/main/generated/data/minecraft/item/bat_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/bat_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:bat" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 986895 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/bee_spawn_egg.json b/src/main/generated/data/minecraft/item/bee_spawn_egg.json index d47eb346..580436c2 100644 --- a/src/main/generated/data/minecraft/item/bee_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/bee_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:bee" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 4400155 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/beetroot_soup.json b/src/main/generated/data/minecraft/item/beetroot_soup.json index 096d3761..2f8adb23 100644 --- a/src/main/generated/data/minecraft/item/beetroot_soup.json +++ b/src/main/generated/data/minecraft/item/beetroot_soup.json @@ -3,9 +3,7 @@ "translation_key": "item.minecraft.beetroot_soup" }, "components": { - "minecraft:consumable": { - "result_item": "minecraft:bowl" - }, + "minecraft:consumable": {}, "minecraft:food": { "nutrition": 6, "saturation": 7.2000003 @@ -13,6 +11,10 @@ "minecraft:stackable": 1, "minecraft:useable": { "animation": "eat", + "remainder": { + "id": "minecraft:bowl", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/blaze_spawn_egg.json b/src/main/generated/data/minecraft/item/blaze_spawn_egg.json index 7e6df0d4..7d20e06e 100644 --- a/src/main/generated/data/minecraft/item/blaze_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/blaze_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:blaze" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16775294 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/bogged_spawn_egg.json b/src/main/generated/data/minecraft/item/bogged_spawn_egg.json index 03d6d1ea..cbe240c8 100644 --- a/src/main/generated/data/minecraft/item/bogged_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/bogged_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:bogged" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 3231003 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/breeze_spawn_egg.json b/src/main/generated/data/minecraft/item/breeze_spawn_egg.json index ca624de9..4aeec6a5 100644 --- a/src/main/generated/data/minecraft/item/breeze_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/breeze_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:breeze" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 9529055 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/camel_spawn_egg.json b/src/main/generated/data/minecraft/item/camel_spawn_egg.json index 986f1ad8..40701bd9 100644 --- a/src/main/generated/data/minecraft/item/camel_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/camel_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:camel" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 13341495 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/cat_spawn_egg.json b/src/main/generated/data/minecraft/item/cat_spawn_egg.json index c1fd6965..d6ef32a8 100644 --- a/src/main/generated/data/minecraft/item/cat_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/cat_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:cat" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 9794134 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/cave_spider_spawn_egg.json b/src/main/generated/data/minecraft/item/cave_spider_spawn_egg.json index 23b818e6..265a3377 100644 --- a/src/main/generated/data/minecraft/item/cave_spider_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/cave_spider_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:cave_spider" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 11013646 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/chicken.json b/src/main/generated/data/minecraft/item/chicken.json index 28f7872c..fa58bd30 100644 --- a/src/main/generated/data/minecraft/item/chicken.json +++ b/src/main/generated/data/minecraft/item/chicken.json @@ -5,16 +5,6 @@ "components": { "minecraft:consumable": {}, "minecraft:food": { - "effects": [ - { - "effect": { - "id": "minecraft:hunger", - "duration": 600, - "show_icon": true - }, - "probability": 0.3 - } - ], "nutrition": 2, "saturation": 1.2 }, @@ -26,5 +16,30 @@ "amount": 32 } } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:poison", + "duration": 600, + "show_icon": true + } + ], + "entity": "this" + }, + "requirements": { + "conditions": { + "chance": 0.3, + "condition": "minecraft:random_chance" + }, + "context": { + "entity": "this", + "position": "this" + } + } + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/chicken_spawn_egg.json b/src/main/generated/data/minecraft/item/chicken_spawn_egg.json index 6395345b..a9c28e0d 100644 --- a/src/main/generated/data/minecraft/item/chicken_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/chicken_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:chicken" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16711680 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/cod_spawn_egg.json b/src/main/generated/data/minecraft/item/cod_spawn_egg.json index c98903a7..fb08ca9d 100644 --- a/src/main/generated/data/minecraft/item/cod_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/cod_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:cod" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15058059 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/cow_spawn_egg.json b/src/main/generated/data/minecraft/item/cow_spawn_egg.json index 64b3cb49..fc45214a 100644 --- a/src/main/generated/data/minecraft/item/cow_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/cow_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:cow" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 10592673 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/creeper_spawn_egg.json b/src/main/generated/data/minecraft/item/creeper_spawn_egg.json index 1effb8f0..be2e1f76 100644 --- a/src/main/generated/data/minecraft/item/creeper_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/creeper_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:creeper" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 0 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/dolphin_spawn_egg.json b/src/main/generated/data/minecraft/item/dolphin_spawn_egg.json index c1380b75..4adb1377 100644 --- a/src/main/generated/data/minecraft/item/dolphin_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/dolphin_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:dolphin" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16382457 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/donkey_spawn_egg.json b/src/main/generated/data/minecraft/item/donkey_spawn_egg.json index f01275a6..14eec093 100644 --- a/src/main/generated/data/minecraft/item/donkey_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/donkey_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:donkey" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8811878 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/dragon_breath.json b/src/main/generated/data/minecraft/item/dragon_breath.json index cbaf8f85..ae6070e5 100644 --- a/src/main/generated/data/minecraft/item/dragon_breath.json +++ b/src/main/generated/data/minecraft/item/dragon_breath.json @@ -4,9 +4,6 @@ "translation_key": "item.minecraft.dragon_breath" }, "components": { - "minecraft:recipe_remainder": { - "item": "minecraft:glass_bottle" - }, "minecraft:stackable": 64 } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/drowned_spawn_egg.json b/src/main/generated/data/minecraft/item/drowned_spawn_egg.json index 9cadc700..8cc24ed2 100644 --- a/src/main/generated/data/minecraft/item/drowned_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/drowned_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:drowned" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7969893 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/elder_guardian_spawn_egg.json b/src/main/generated/data/minecraft/item/elder_guardian_spawn_egg.json index 6b99f9bd..723e4e43 100644 --- a/src/main/generated/data/minecraft/item/elder_guardian_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/elder_guardian_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:elder_guardian" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7632531 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/enchanted_golden_apple.json b/src/main/generated/data/minecraft/item/enchanted_golden_apple.json index 130d8173..fd9a1bcb 100644 --- a/src/main/generated/data/minecraft/item/enchanted_golden_apple.json +++ b/src/main/generated/data/minecraft/item/enchanted_golden_apple.json @@ -8,47 +8,46 @@ "minecraft:consumable": {}, "minecraft:food": { "always_edible": true, - "effects": [ - { - "effect": { + "nutrition": 4, + "saturation": 9.6 + }, + "minecraft:stackable": 64, + "minecraft:useable": { + "animation": "eat", + "ticks": { + "type": "minecraft:constant", + "amount": 32 + } + } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { "id": "minecraft:regeneration", "amplifier": 1, "duration": 400, "show_icon": true - } - }, - { - "effect": { + }, + { "id": "minecraft:resistance", "duration": 6000, "show_icon": true - } - }, - { - "effect": { + }, + { "id": "minecraft:fire_resistance", "duration": 6000, "show_icon": true - } - }, - { - "effect": { + }, + { "id": "minecraft:absorption", - "amplifier": 3, "duration": 2400, "show_icon": true } - } - ], - "nutrition": 4, - "saturation": 9.6 - }, - "minecraft:stackable": 64, - "minecraft:useable": { - "animation": "eat", - "ticks": { - "type": "minecraft:constant", - "amount": 32 + ], + "entity": "this" } } } diff --git a/src/main/generated/data/minecraft/item/ender_dragon_spawn_egg.json b/src/main/generated/data/minecraft/item/ender_dragon_spawn_egg.json index c9ffc3f3..98c24408 100644 --- a/src/main/generated/data/minecraft/item/ender_dragon_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/ender_dragon_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:ender_dragon" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 14711290 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/enderman_spawn_egg.json b/src/main/generated/data/minecraft/item/enderman_spawn_egg.json index 597ac26b..b17ef2a3 100644 --- a/src/main/generated/data/minecraft/item/enderman_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/enderman_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:enderman" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 0 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/endermite_spawn_egg.json b/src/main/generated/data/minecraft/item/endermite_spawn_egg.json index 7fc794a2..233816c7 100644 --- a/src/main/generated/data/minecraft/item/endermite_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/endermite_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:endermite" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7237230 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/evoker_spawn_egg.json b/src/main/generated/data/minecraft/item/evoker_spawn_egg.json index db495197..624ce2cf 100644 --- a/src/main/generated/data/minecraft/item/evoker_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/evoker_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:evoker" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 1973274 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/fox_spawn_egg.json b/src/main/generated/data/minecraft/item/fox_spawn_egg.json index d4efdb7b..186ca6af 100644 --- a/src/main/generated/data/minecraft/item/fox_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/fox_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:fox" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 13396256 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/frog_spawn_egg.json b/src/main/generated/data/minecraft/item/frog_spawn_egg.json index f292ee9d..ebe0c664 100644 --- a/src/main/generated/data/minecraft/item/frog_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/frog_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:frog" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16762748 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/ghast_spawn_egg.json b/src/main/generated/data/minecraft/item/ghast_spawn_egg.json index 9f9f78bf..f8c3e9f4 100644 --- a/src/main/generated/data/minecraft/item/ghast_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/ghast_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:ghast" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 12369084 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/glow_squid_spawn_egg.json b/src/main/generated/data/minecraft/item/glow_squid_spawn_egg.json index 0ee47e47..734801d3 100644 --- a/src/main/generated/data/minecraft/item/glow_squid_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/glow_squid_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:glow_squid" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8778172 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/goat_spawn_egg.json b/src/main/generated/data/minecraft/item/goat_spawn_egg.json index 92927fe6..e321a601 100644 --- a/src/main/generated/data/minecraft/item/goat_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/goat_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:goat" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5589310 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/golden_apple.json b/src/main/generated/data/minecraft/item/golden_apple.json index 07e03992..eb580510 100644 --- a/src/main/generated/data/minecraft/item/golden_apple.json +++ b/src/main/generated/data/minecraft/item/golden_apple.json @@ -7,23 +7,6 @@ "minecraft:consumable": {}, "minecraft:food": { "always_edible": true, - "effects": [ - { - "effect": { - "id": "minecraft:regeneration", - "amplifier": 1, - "duration": 100, - "show_icon": true - } - }, - { - "effect": { - "id": "minecraft:absorption", - "duration": 2400, - "show_icon": true - } - } - ], "nutrition": 4, "saturation": 9.6 }, @@ -35,5 +18,26 @@ "amount": 32 } } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:regeneration", + "amplifier": 1, + "duration": 100, + "show_icon": true + }, + { + "id": "minecraft:absorption", + "duration": 2400, + "show_icon": true + } + ], + "entity": "this" + } + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/golden_axe.json b/src/main/generated/data/minecraft/item/golden_axe.json index 438b2948..1e1409b8 100644 --- a/src/main/generated/data/minecraft/item/golden_axe.json +++ b/src/main/generated/data/minecraft/item/golden_axe.json @@ -29,13 +29,7 @@ "minecraft:weapon": { "attack_damage": { "default_damage": 7.0, - "rules": [ - { - "add_base": true, - "damage": 6.0, - "entities": "#minecraft:proficient_with_golden_weapons" - } - ] + "rules": [] }, "attack_speed": 0.25, "damage_per_hit": 2 diff --git a/src/main/generated/data/minecraft/item/golden_hoe.json b/src/main/generated/data/minecraft/item/golden_hoe.json index e83b1fe5..6ed0a82a 100644 --- a/src/main/generated/data/minecraft/item/golden_hoe.json +++ b/src/main/generated/data/minecraft/item/golden_hoe.json @@ -29,13 +29,7 @@ "minecraft:weapon": { "attack_damage": { "default_damage": 1.0, - "rules": [ - { - "add_base": true, - "damage": 0.0, - "entities": "#minecraft:proficient_with_golden_weapons" - } - ] + "rules": [] }, "attack_speed": 0.25, "damage_per_hit": 2 diff --git a/src/main/generated/data/minecraft/item/golden_pickaxe.json b/src/main/generated/data/minecraft/item/golden_pickaxe.json index fb351533..384f3ac0 100644 --- a/src/main/generated/data/minecraft/item/golden_pickaxe.json +++ b/src/main/generated/data/minecraft/item/golden_pickaxe.json @@ -29,13 +29,7 @@ "minecraft:weapon": { "attack_damage": { "default_damage": 2.0, - "rules": [ - { - "add_base": true, - "damage": 1.0, - "entities": "#minecraft:proficient_with_golden_weapons" - } - ] + "rules": [] }, "attack_speed": 0.3, "damage_per_hit": 2 diff --git a/src/main/generated/data/minecraft/item/golden_shovel.json b/src/main/generated/data/minecraft/item/golden_shovel.json index 924a52a1..3250849c 100644 --- a/src/main/generated/data/minecraft/item/golden_shovel.json +++ b/src/main/generated/data/minecraft/item/golden_shovel.json @@ -29,13 +29,7 @@ "minecraft:weapon": { "attack_damage": { "default_damage": 2.5, - "rules": [ - { - "add_base": true, - "damage": 1.5, - "entities": "#minecraft:proficient_with_golden_weapons" - } - ] + "rules": [] }, "attack_speed": 0.25, "damage_per_hit": 2 diff --git a/src/main/generated/data/minecraft/item/golden_sword.json b/src/main/generated/data/minecraft/item/golden_sword.json index 14454b67..26598c9c 100644 --- a/src/main/generated/data/minecraft/item/golden_sword.json +++ b/src/main/generated/data/minecraft/item/golden_sword.json @@ -30,13 +30,7 @@ "minecraft:weapon": { "attack_damage": { "default_damage": 4.0, - "rules": [ - { - "add_base": true, - "damage": 3.0, - "entities": "#minecraft:proficient_with_golden_weapons" - } - ] + "rules": [] }, "attack_speed": 0.4 } diff --git a/src/main/generated/data/minecraft/item/guardian_spawn_egg.json b/src/main/generated/data/minecraft/item/guardian_spawn_egg.json index 80e8465b..040848d3 100644 --- a/src/main/generated/data/minecraft/item/guardian_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/guardian_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:guardian" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15826224 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/hoglin_spawn_egg.json b/src/main/generated/data/minecraft/item/hoglin_spawn_egg.json index ae666c09..5fcfeb7f 100644 --- a/src/main/generated/data/minecraft/item/hoglin_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/hoglin_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:hoglin" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 6251620 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/honey_bottle.json b/src/main/generated/data/minecraft/item/honey_bottle.json index 93f7a440..241a0875 100644 --- a/src/main/generated/data/minecraft/item/honey_bottle.json +++ b/src/main/generated/data/minecraft/item/honey_bottle.json @@ -5,19 +5,19 @@ "components": { "minecraft:consumable": { "has_consume_particles": false, - "result_item": "minecraft:glass_bottle", "sound": "minecraft:item.honey_bottle.drink" }, "minecraft:food": { "nutrition": 6, "saturation": 1.2 }, - "minecraft:recipe_remainder": { - "item": "minecraft:glass_bottle" - }, "minecraft:stackable": 16, "minecraft:useable": { "animation": "drink", + "remainder": { + "id": "minecraft:glass_bottle", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 40 diff --git a/src/main/generated/data/minecraft/item/horse_spawn_egg.json b/src/main/generated/data/minecraft/item/horse_spawn_egg.json index 74a715bf..de1055ba 100644 --- a/src/main/generated/data/minecraft/item/horse_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/horse_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:horse" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15656192 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/husk_spawn_egg.json b/src/main/generated/data/minecraft/item/husk_spawn_egg.json index 93bf5def..d4b4c0ea 100644 --- a/src/main/generated/data/minecraft/item/husk_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/husk_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:husk" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15125652 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/iron_golem_spawn_egg.json b/src/main/generated/data/minecraft/item/iron_golem_spawn_egg.json index fa473ac5..7068257b 100644 --- a/src/main/generated/data/minecraft/item/iron_golem_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/iron_golem_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:iron_golem" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7643954 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/lava_bucket.json b/src/main/generated/data/minecraft/item/lava_bucket.json index 9ffb2ca7..93c4de58 100644 --- a/src/main/generated/data/minecraft/item/lava_bucket.json +++ b/src/main/generated/data/minecraft/item/lava_bucket.json @@ -12,11 +12,12 @@ "behavior": "minecraft:use_bucket" }, "minecraft:fuel": { + "remainder": { + "id": "minecraft:bucket", + "count": 1 + }, "ticks": 20000 }, - "minecraft:recipe_remainder": { - "item": "minecraft:bucket" - }, "minecraft:stackable": 1 } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/llama_spawn_egg.json b/src/main/generated/data/minecraft/item/llama_spawn_egg.json index b624b4df..f54207d5 100644 --- a/src/main/generated/data/minecraft/item/llama_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/llama_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:llama" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 10051392 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/magma_cube_spawn_egg.json b/src/main/generated/data/minecraft/item/magma_cube_spawn_egg.json index f549ba95..5451f91e 100644 --- a/src/main/generated/data/minecraft/item/magma_cube_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/magma_cube_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:magma_cube" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16579584 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/milk_bucket.json b/src/main/generated/data/minecraft/item/milk_bucket.json index 8c3a57f9..a644b23d 100644 --- a/src/main/generated/data/minecraft/item/milk_bucket.json +++ b/src/main/generated/data/minecraft/item/milk_bucket.json @@ -5,15 +5,15 @@ "components": { "minecraft:consumable": { "has_consume_particles": false, - "result_item": "minecraft:bucket", "sound": "minecraft:entity.generic.drink" }, - "minecraft:recipe_remainder": { - "item": "minecraft:bucket" - }, "minecraft:stackable": 1, "minecraft:useable": { "animation": "drink", + "remainder": { + "id": "minecraft:bucket", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/mooshroom_spawn_egg.json b/src/main/generated/data/minecraft/item/mooshroom_spawn_egg.json index 38d1d3bf..d1dd3bd9 100644 --- a/src/main/generated/data/minecraft/item/mooshroom_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/mooshroom_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:mooshroom" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 12040119 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/mule_spawn_egg.json b/src/main/generated/data/minecraft/item/mule_spawn_egg.json index bce47c59..dcbbe93d 100644 --- a/src/main/generated/data/minecraft/item/mule_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/mule_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:mule" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5321501 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/mushroom_stew.json b/src/main/generated/data/minecraft/item/mushroom_stew.json index 6773cea3..ccdff293 100644 --- a/src/main/generated/data/minecraft/item/mushroom_stew.json +++ b/src/main/generated/data/minecraft/item/mushroom_stew.json @@ -3,9 +3,7 @@ "translation_key": "item.minecraft.mushroom_stew" }, "components": { - "minecraft:consumable": { - "result_item": "minecraft:bowl" - }, + "minecraft:consumable": {}, "minecraft:food": { "nutrition": 6, "saturation": 7.2000003 @@ -13,6 +11,10 @@ "minecraft:stackable": 1, "minecraft:useable": { "animation": "eat", + "remainder": { + "id": "minecraft:bowl", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/ocelot_spawn_egg.json b/src/main/generated/data/minecraft/item/ocelot_spawn_egg.json index f453d1dd..fb9629a0 100644 --- a/src/main/generated/data/minecraft/item/ocelot_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/ocelot_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:ocelot" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5653556 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/panda_spawn_egg.json b/src/main/generated/data/minecraft/item/panda_spawn_egg.json index f1e6fcf6..74dd3705 100644 --- a/src/main/generated/data/minecraft/item/panda_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/panda_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:panda" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 1776418 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/parrot_spawn_egg.json b/src/main/generated/data/minecraft/item/parrot_spawn_egg.json index 43f971ed..a0f3aa30 100644 --- a/src/main/generated/data/minecraft/item/parrot_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/parrot_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:parrot" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16711680 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/phantom_spawn_egg.json b/src/main/generated/data/minecraft/item/phantom_spawn_egg.json index b61a7d14..e6494186 100644 --- a/src/main/generated/data/minecraft/item/phantom_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/phantom_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:phantom" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8978176 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/pig_spawn_egg.json b/src/main/generated/data/minecraft/item/pig_spawn_egg.json index 8ab03f29..960b126d 100644 --- a/src/main/generated/data/minecraft/item/pig_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/pig_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:pig" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 14377823 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/piglin_brute_spawn_egg.json b/src/main/generated/data/minecraft/item/piglin_brute_spawn_egg.json index d6291a94..c7ff6c73 100644 --- a/src/main/generated/data/minecraft/item/piglin_brute_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/piglin_brute_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:piglin_brute" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16380836 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/piglin_spawn_egg.json b/src/main/generated/data/minecraft/item/piglin_spawn_egg.json index 754224e4..f74a1f76 100644 --- a/src/main/generated/data/minecraft/item/piglin_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/piglin_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:piglin" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16380836 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/pillager_spawn_egg.json b/src/main/generated/data/minecraft/item/pillager_spawn_egg.json index e2fd25ea..73d0a224 100644 --- a/src/main/generated/data/minecraft/item/pillager_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/pillager_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:pillager" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 9804699 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/poisonous_potato.json b/src/main/generated/data/minecraft/item/poisonous_potato.json index e535b2e1..96751e5c 100644 --- a/src/main/generated/data/minecraft/item/poisonous_potato.json +++ b/src/main/generated/data/minecraft/item/poisonous_potato.json @@ -5,16 +5,6 @@ "components": { "minecraft:consumable": {}, "minecraft:food": { - "effects": [ - { - "effect": { - "id": "minecraft:poison", - "duration": 100, - "show_icon": true - }, - "probability": 0.6 - } - ], "nutrition": 2, "saturation": 1.2 }, @@ -26,5 +16,30 @@ "amount": 32 } } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:poison", + "duration": 100, + "show_icon": true + } + ], + "entity": "this" + }, + "requirements": { + "conditions": { + "chance": 0.6, + "condition": "minecraft:random_chance" + }, + "context": { + "entity": "this", + "position": "this" + } + } + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/polar_bear_spawn_egg.json b/src/main/generated/data/minecraft/item/polar_bear_spawn_egg.json index 0ddabc3c..5bbc5110 100644 --- a/src/main/generated/data/minecraft/item/polar_bear_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/polar_bear_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:polar_bear" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 14014157 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/potion.json b/src/main/generated/data/minecraft/item/potion.json index 00b2ee63..19fb7895 100644 --- a/src/main/generated/data/minecraft/item/potion.json +++ b/src/main/generated/data/minecraft/item/potion.json @@ -5,7 +5,6 @@ "components": { "minecraft:consumable": { "has_consume_particles": false, - "result_item": "minecraft:glass_bottle", "sound": "minecraft:entity.generic.drink" }, "minecraft:dispensable": { @@ -23,6 +22,10 @@ }, "minecraft:useable": { "animation": "drink", + "remainder": { + "id": "minecraft:glass_bottle", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/pufferfish.json b/src/main/generated/data/minecraft/item/pufferfish.json index 1f3452cd..fd62bc51 100644 --- a/src/main/generated/data/minecraft/item/pufferfish.json +++ b/src/main/generated/data/minecraft/item/pufferfish.json @@ -5,40 +5,42 @@ "components": { "minecraft:consumable": {}, "minecraft:food": { - "effects": [ - { - "effect": { + "nutrition": 1, + "saturation": 0.2 + }, + "minecraft:stackable": 64, + "minecraft:useable": { + "animation": "eat", + "ticks": { + "type": "minecraft:constant", + "amount": 32 + } + } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { "id": "minecraft:poison", "amplifier": 1, "duration": 1200, "show_icon": true - } - }, - { - "effect": { + }, + { "id": "minecraft:hunger", "amplifier": 2, "duration": 300, "show_icon": true - } - }, - { - "effect": { + }, + { "id": "minecraft:nausea", "duration": 300, "show_icon": true } - } - ], - "nutrition": 1, - "saturation": 0.2 - }, - "minecraft:stackable": 64, - "minecraft:useable": { - "animation": "eat", - "ticks": { - "type": "minecraft:constant", - "amount": 32 + ], + "entity": "this" } } } diff --git a/src/main/generated/data/minecraft/item/pufferfish_spawn_egg.json b/src/main/generated/data/minecraft/item/pufferfish_spawn_egg.json index 1f4bb78c..9182ef47 100644 --- a/src/main/generated/data/minecraft/item/pufferfish_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/pufferfish_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:pufferfish" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 3654642 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/rabbit_spawn_egg.json b/src/main/generated/data/minecraft/item/rabbit_spawn_egg.json index 48947d1f..a42f5ea0 100644 --- a/src/main/generated/data/minecraft/item/rabbit_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/rabbit_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:rabbit" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7555121 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/rabbit_stew.json b/src/main/generated/data/minecraft/item/rabbit_stew.json index f43ca5b1..aea402ee 100644 --- a/src/main/generated/data/minecraft/item/rabbit_stew.json +++ b/src/main/generated/data/minecraft/item/rabbit_stew.json @@ -3,9 +3,7 @@ "translation_key": "item.minecraft.rabbit_stew" }, "components": { - "minecraft:consumable": { - "result_item": "minecraft:bowl" - }, + "minecraft:consumable": {}, "minecraft:food": { "nutrition": 10, "saturation": 12.0 @@ -13,6 +11,10 @@ "minecraft:stackable": 1, "minecraft:useable": { "animation": "eat", + "remainder": { + "id": "minecraft:bowl", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/ravager_spawn_egg.json b/src/main/generated/data/minecraft/item/ravager_spawn_egg.json index bce202f7..d3e75881 100644 --- a/src/main/generated/data/minecraft/item/ravager_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/ravager_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:ravager" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5984329 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/rotten_flesh.json b/src/main/generated/data/minecraft/item/rotten_flesh.json index c4e0a533..e15eee55 100644 --- a/src/main/generated/data/minecraft/item/rotten_flesh.json +++ b/src/main/generated/data/minecraft/item/rotten_flesh.json @@ -5,16 +5,6 @@ "components": { "minecraft:consumable": {}, "minecraft:food": { - "effects": [ - { - "effect": { - "id": "minecraft:hunger", - "duration": 600, - "show_icon": true - }, - "probability": 0.8 - } - ], "nutrition": 4, "saturation": 0.8 }, @@ -26,5 +16,30 @@ "amount": 32 } } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:hunger", + "duration": 600, + "show_icon": true + } + ], + "entity": "this" + }, + "requirements": { + "conditions": { + "chance": 0.8, + "condition": "minecraft:random_chance" + }, + "context": { + "entity": "this", + "position": "this" + } + } + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/salmon_spawn_egg.json b/src/main/generated/data/minecraft/item/salmon_spawn_egg.json index 98de7e68..62b99676 100644 --- a/src/main/generated/data/minecraft/item/salmon_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/salmon_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:salmon" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 951412 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/sheep_spawn_egg.json b/src/main/generated/data/minecraft/item/sheep_spawn_egg.json index 23a9292c..5ca28200 100644 --- a/src/main/generated/data/minecraft/item/sheep_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/sheep_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:sheep" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16758197 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/shield.json b/src/main/generated/data/minecraft/item/shield.json index 6db391ee..0df6a2d2 100644 --- a/src/main/generated/data/minecraft/item/shield.json +++ b/src/main/generated/data/minecraft/item/shield.json @@ -19,7 +19,10 @@ }, "minecraft:stackable": 1, "minecraft:useable": { - "animation": "block" + "animation": "block", + "ticks": { + "type": "minecraft:indefinite" + } } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/shulker_spawn_egg.json b/src/main/generated/data/minecraft/item/shulker_spawn_egg.json index 30b453af..aa92968b 100644 --- a/src/main/generated/data/minecraft/item/shulker_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/shulker_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:shulker" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5060690 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/silverfish_spawn_egg.json b/src/main/generated/data/minecraft/item/silverfish_spawn_egg.json index 8e798313..c434f1a2 100644 --- a/src/main/generated/data/minecraft/item/silverfish_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/silverfish_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:silverfish" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 3158064 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/skeleton_horse_spawn_egg.json b/src/main/generated/data/minecraft/item/skeleton_horse_spawn_egg.json index 3e0bc420..e57c6636 100644 --- a/src/main/generated/data/minecraft/item/skeleton_horse_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/skeleton_horse_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:skeleton_horse" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15066584 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/skeleton_spawn_egg.json b/src/main/generated/data/minecraft/item/skeleton_spawn_egg.json index b5f8545d..3ac113f7 100644 --- a/src/main/generated/data/minecraft/item/skeleton_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/skeleton_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:skeleton" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 4802889 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/slime_spawn_egg.json b/src/main/generated/data/minecraft/item/slime_spawn_egg.json index fc661e76..e8b88014 100644 --- a/src/main/generated/data/minecraft/item/slime_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/slime_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:slime" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8306542 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/sniffer_spawn_egg.json b/src/main/generated/data/minecraft/item/sniffer_spawn_egg.json index 11130e7f..58aab764 100644 --- a/src/main/generated/data/minecraft/item/sniffer_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/sniffer_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:sniffer" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 2468720 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/snow_golem_spawn_egg.json b/src/main/generated/data/minecraft/item/snow_golem_spawn_egg.json index 15f1626d..4f9c541a 100644 --- a/src/main/generated/data/minecraft/item/snow_golem_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/snow_golem_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:snow_golem" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 8496292 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/spider_eye.json b/src/main/generated/data/minecraft/item/spider_eye.json index cf3e8806..8e14e2c6 100644 --- a/src/main/generated/data/minecraft/item/spider_eye.json +++ b/src/main/generated/data/minecraft/item/spider_eye.json @@ -5,15 +5,6 @@ "components": { "minecraft:consumable": {}, "minecraft:food": { - "effects": [ - { - "effect": { - "id": "minecraft:poison", - "duration": 100, - "show_icon": true - } - } - ], "nutrition": 2, "saturation": 3.2 }, @@ -25,5 +16,20 @@ "amount": 32 } } + }, + "events": { + "minecraft:consume_item": { + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:poison", + "duration": 100, + "show_icon": true + } + ], + "entity": "this" + } + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/spider_spawn_egg.json b/src/main/generated/data/minecraft/item/spider_spawn_egg.json index 5bd71b1e..106bcfca 100644 --- a/src/main/generated/data/minecraft/item/spider_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/spider_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:spider" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 11013646 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/squid_spawn_egg.json b/src/main/generated/data/minecraft/item/squid_spawn_egg.json index b1b688b8..9d2ca3d3 100644 --- a/src/main/generated/data/minecraft/item/squid_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/squid_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:squid" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7375001 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/stray_spawn_egg.json b/src/main/generated/data/minecraft/item/stray_spawn_egg.json index c25ea4bc..18773366 100644 --- a/src/main/generated/data/minecraft/item/stray_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/stray_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:stray" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 14543594 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/strider_spawn_egg.json b/src/main/generated/data/minecraft/item/strider_spawn_egg.json index baa88a61..2af53c57 100644 --- a/src/main/generated/data/minecraft/item/strider_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/strider_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:strider" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5065037 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/suspicious_stew.json b/src/main/generated/data/minecraft/item/suspicious_stew.json index 6c702e45..10605cf8 100644 --- a/src/main/generated/data/minecraft/item/suspicious_stew.json +++ b/src/main/generated/data/minecraft/item/suspicious_stew.json @@ -3,9 +3,7 @@ "translation_key": "item.minecraft.suspicious_stew" }, "components": { - "minecraft:consumable": { - "result_item": "minecraft:bowl" - }, + "minecraft:consumable": {}, "minecraft:food": { "always_edible": true, "nutrition": 6, @@ -14,6 +12,10 @@ "minecraft:stackable": 1, "minecraft:useable": { "animation": "eat", + "remainder": { + "id": "minecraft:bowl", + "count": 1 + }, "ticks": { "type": "minecraft:constant", "amount": 32 diff --git a/src/main/generated/data/minecraft/item/tadpole_spawn_egg.json b/src/main/generated/data/minecraft/item/tadpole_spawn_egg.json index e36db0ee..ec238103 100644 --- a/src/main/generated/data/minecraft/item/tadpole_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/tadpole_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:tadpole" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 1444352 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/totem_of_undying.json b/src/main/generated/data/minecraft/item/totem_of_undying.json index 65a51aa2..3edfcd72 100644 --- a/src/main/generated/data/minecraft/item/totem_of_undying.json +++ b/src/main/generated/data/minecraft/item/totem_of_undying.json @@ -4,27 +4,43 @@ "translation_key": "item.minecraft.totem_of_undying" }, "components": { - "minecraft:life_saving": { - "effects": [ - { - "id": "minecraft:regeneration", - "amplifier": 1, - "duration": 900, - "show_icon": true - }, + "minecraft:stackable": 1 + }, + "events": { + "minecraft:before_death_holder": { + "action": [ { - "id": "minecraft:absorption", - "amplifier": 1, - "duration": 100, - "show_icon": true + "action": { + "type": "minecraft:clear_status_effects", + "entity": "this" + } }, { - "id": "minecraft:fire_resistance", - "duration": 800, - "show_icon": true + "action": { + "type": "minecraft:add_status_effects", + "effects": [ + { + "id": "minecraft:regeneration", + "amplifier": 1, + "duration": 900, + "show_icon": true + }, + { + "id": "minecraft:absorption", + "amplifier": 1, + "duration": 100, + "show_icon": true + }, + { + "id": "minecraft:fire_resistance", + "duration": 800, + "show_icon": true + } + ], + "entity": "this" + } } ] - }, - "minecraft:stackable": 1 + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/trader_llama_spawn_egg.json b/src/main/generated/data/minecraft/item/trader_llama_spawn_egg.json index 7b110f17..b9b0d454 100644 --- a/src/main/generated/data/minecraft/item/trader_llama_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/trader_llama_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:trader_llama" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 4547222 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/tropical_fish_spawn_egg.json b/src/main/generated/data/minecraft/item/tropical_fish_spawn_egg.json index c9204991..afa394e2 100644 --- a/src/main/generated/data/minecraft/item/tropical_fish_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/tropical_fish_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:tropical_fish" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 16775663 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/turtle_spawn_egg.json b/src/main/generated/data/minecraft/item/turtle_spawn_egg.json index db11c88d..0545648c 100644 --- a/src/main/generated/data/minecraft/item/turtle_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/turtle_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:turtle" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 44975 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/vex_spawn_egg.json b/src/main/generated/data/minecraft/item/vex_spawn_egg.json index 8ab06401..7e0b7c95 100644 --- a/src/main/generated/data/minecraft/item/vex_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/vex_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:vex" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15265265 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/villager_spawn_egg.json b/src/main/generated/data/minecraft/item/villager_spawn_egg.json index 1cd9be26..44aad272 100644 --- a/src/main/generated/data/minecraft/item/villager_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/villager_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:villager" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 12422002 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/vindicator_spawn_egg.json b/src/main/generated/data/minecraft/item/vindicator_spawn_egg.json index 82f0c83e..bbf61f3e 100644 --- a/src/main/generated/data/minecraft/item/vindicator_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/vindicator_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:vindicator" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 2580065 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wandering_trader_spawn_egg.json b/src/main/generated/data/minecraft/item/wandering_trader_spawn_egg.json index d44e55bb..3152f291 100644 --- a/src/main/generated/data/minecraft/item/wandering_trader_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/wandering_trader_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:wandering_trader" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15377456 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/warden_spawn_egg.json b/src/main/generated/data/minecraft/item/warden_spawn_egg.json index 957046a9..5a5f2ca3 100644 --- a/src/main/generated/data/minecraft/item/warden_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/warden_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:warden" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 3790560 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/water_bucket.json b/src/main/generated/data/minecraft/item/water_bucket.json index 35e66c95..3fffa7b5 100644 --- a/src/main/generated/data/minecraft/item/water_bucket.json +++ b/src/main/generated/data/minecraft/item/water_bucket.json @@ -11,9 +11,6 @@ "minecraft:dispensable": { "behavior": "minecraft:use_bucket" }, - "minecraft:recipe_remainder": { - "item": "minecraft:bucket" - }, "minecraft:stackable": 1 } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/witch_spawn_egg.json b/src/main/generated/data/minecraft/item/witch_spawn_egg.json index 42742b47..041da8f0 100644 --- a/src/main/generated/data/minecraft/item/witch_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/witch_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:witch" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5349438 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wither_skeleton_spawn_egg.json b/src/main/generated/data/minecraft/item/wither_skeleton_spawn_egg.json index 3a149eee..ee6f12f6 100644 --- a/src/main/generated/data/minecraft/item/wither_skeleton_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/wither_skeleton_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:wither_skeleton" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 4672845 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wither_spawn_egg.json b/src/main/generated/data/minecraft/item/wither_spawn_egg.json index 64f4f9cd..221e66e0 100644 --- a/src/main/generated/data/minecraft/item/wither_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/wither_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:wither" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5075616 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wolf_spawn_egg.json b/src/main/generated/data/minecraft/item/wolf_spawn_egg.json index f4f365a6..984ef7cc 100644 --- a/src/main/generated/data/minecraft/item/wolf_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/wolf_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:wolf" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 13545366 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/zoglin_spawn_egg.json b/src/main/generated/data/minecraft/item/zoglin_spawn_egg.json index dca9ffdc..1bc8a024 100644 --- a/src/main/generated/data/minecraft/item/zoglin_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/zoglin_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:zoglin" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 15132390 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/zombie_horse_spawn_egg.json b/src/main/generated/data/minecraft/item/zombie_horse_spawn_egg.json index 68c31783..aa33d097 100644 --- a/src/main/generated/data/minecraft/item/zombie_horse_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/zombie_horse_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:zombie_horse" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 9945732 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/zombie_spawn_egg.json b/src/main/generated/data/minecraft/item/zombie_spawn_egg.json index 905a5476..bcd84d12 100644 --- a/src/main/generated/data/minecraft/item/zombie_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/zombie_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:zombie" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7969893 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/zombie_villager_spawn_egg.json b/src/main/generated/data/minecraft/item/zombie_villager_spawn_egg.json index 9b9765d5..cbedfeab 100644 --- a/src/main/generated/data/minecraft/item/zombie_villager_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/zombie_villager_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:zombie_villager" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 7969893 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/zombified_piglin_spawn_egg.json b/src/main/generated/data/minecraft/item/zombified_piglin_spawn_egg.json index d105257b..7b09fdad 100644 --- a/src/main/generated/data/minecraft/item/zombified_piglin_spawn_egg.json +++ b/src/main/generated/data/minecraft/item/zombified_piglin_spawn_egg.json @@ -10,7 +10,11 @@ "allow_item_data": true, "entity": { "type": "minecraft:zombified_piglin" - } + }, + "passes": [ + "block", + "fluid" + ] }, "minecraft:spawn_egg": {}, "minecraft:stackable": 64, @@ -22,7 +26,6 @@ 5009705 ] } - }, - "minecraft:useable_on_fluid": {} + } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/recipe/cake.json b/src/main/generated/data/minecraft/recipe/cake.json new file mode 100644 index 00000000..e5e7a773 --- /dev/null +++ b/src/main/generated/data/minecraft/recipe/cake.json @@ -0,0 +1,33 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "items": { + "item": "minecraft:milk_bucket" + }, + "remainder": { + "id": "minecraft:bucket", + "count": 1 + } + }, + "B": { + "item": "minecraft:sugar" + }, + "C": { + "item": "minecraft:wheat" + }, + "E": { + "item": "minecraft:egg" + } + }, + "pattern": [ + "AAA", + "BEB", + "CCC" + ], + "result": { + "id": "minecraft:cake", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/recipe/honey_block.json b/src/main/generated/data/minecraft/recipe/honey_block.json new file mode 100644 index 00000000..7069cdaa --- /dev/null +++ b/src/main/generated/data/minecraft/recipe/honey_block.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "#": { + "items": { + "item": "minecraft:honey_bottle" + }, + "remainder": { + "id": "minecraft:glass_bottle", + "count": 1 + } + } + }, + "pattern": [ + "##", + "##" + ], + "result": { + "id": "minecraft:honey_block", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_black.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_black.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_black.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_black.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_blue.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_blue.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_blue.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_blue.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_brown.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_brown.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_brown.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_brown.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_cyan.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_cyan.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_cyan.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_cyan.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_gray.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_gray.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_gray.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_gray.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_green.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_green.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_green.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_green.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_light_blue.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_light_blue.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_light_blue.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_light_blue.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_light_gray.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_light_gray.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_light_gray.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_light_gray.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_lime.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_lime.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_lime.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_lime.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_magenta.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_magenta.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_magenta.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_magenta.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_orange.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_orange.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_orange.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_orange.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_pink.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_pink.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_pink.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_pink.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_purple.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_purple.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_purple.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_purple.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_red.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_red.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_red.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_red.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_white.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_white.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_white.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_white.json diff --git a/src/main/generated/data/minecraft/recipes/shulker_box_coloring_yellow.json b/src/main/generated/data/minecraft/recipe/shulker_box_coloring_yellow.json similarity index 100% rename from src/main/generated/data/minecraft/recipes/shulker_box_coloring_yellow.json rename to src/main/generated/data/minecraft/recipe/shulker_box_coloring_yellow.json diff --git a/src/main/generated/data/minecraft/recipe/sugar_from_honey_bottle.json b/src/main/generated/data/minecraft/recipe/sugar_from_honey_bottle.json new file mode 100644 index 00000000..cc09f813 --- /dev/null +++ b/src/main/generated/data/minecraft/recipe/sugar_from_honey_bottle.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "items": { + "item": "minecraft:honey_bottle" + }, + "remainder": { + "id": "minecraft:glass_bottle", + "count": 1 + } + } + ], + "result": { + "id": "minecraft:sugar", + "count": 3 + } +} \ No newline at end of file diff --git a/src/main/java/net/errorcraft/itematic/access/entity/LivingEntityAccess.java b/src/main/java/net/errorcraft/itematic/access/entity/LivingEntityAccess.java index f880d8a9..5f105786 100644 --- a/src/main/java/net/errorcraft/itematic/access/entity/LivingEntityAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/entity/LivingEntityAccess.java @@ -23,4 +23,5 @@ public interface LivingEntityAccess { default double itematic$getAttackDamage() { return 0.0d; } + default void itematic$addOrDropStack(ItemStack stack) {} } diff --git a/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java b/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java index 979d561b..0c778a09 100644 --- a/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java @@ -36,6 +36,9 @@ public interface ItemAccess { default boolean itematic$invokeEvent(ItemEvent event, ActionContext context) { return false; } + default boolean itematic$hasEventListener(ItemEvent event) { + return false; + } default boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { return true; } diff --git a/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java b/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java index 5243381b..28f8f100 100644 --- a/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java @@ -6,6 +6,7 @@ import net.errorcraft.itematic.world.action.context.ActionContext; import net.minecraft.block.BlockState; import net.minecraft.component.ComponentMapImpl; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -39,6 +40,9 @@ public interface ItemStackAccess { return false; } default void itematic$damage(int amount, ActionContext context) {} + default ItemStack itematic$applyUseEffects(LivingEntity user, ItemStack stackBeforeUse) { + return ItemStack.EMPTY; + } default > boolean itematic$hasComponent(ItemComponentType type) { return false; } @@ -48,6 +52,9 @@ public interface ItemStackAccess { default boolean itematic$invokeEvent(ItemEvent event, ActionContext context) { return false; } + default boolean itematic$hasEventListener(ItemEvent beforeDeathHolder) { + return false; + } default boolean itematic$canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { return false; } diff --git a/src/main/java/net/errorcraft/itematic/access/recipe/IngredientAccess.java b/src/main/java/net/errorcraft/itematic/access/recipe/IngredientAccess.java index ce1ab3fe..34a4f941 100644 --- a/src/main/java/net/errorcraft/itematic/access/recipe/IngredientAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/recipe/IngredientAccess.java @@ -3,8 +3,14 @@ import net.minecraft.item.ItemStack; import net.minecraft.registry.RegistryWrapper; +import java.util.Optional; + public interface IngredientAccess { default ItemStack[] itematic$getMatchingStacks(RegistryWrapper.WrapperLookup lookup) { return new ItemStack[0]; } + default Optional itematic$remainder() { + return Optional.empty(); + } + default void itematic$setRemainder(Optional remainder) {} } diff --git a/src/main/java/net/errorcraft/itematic/access/recipe/RawShapedRecipeAccess.java b/src/main/java/net/errorcraft/itematic/access/recipe/RawShapedRecipeAccess.java new file mode 100644 index 00000000..5e775a13 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/access/recipe/RawShapedRecipeAccess.java @@ -0,0 +1,9 @@ +package net.errorcraft.itematic.access.recipe; + +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.input.CraftingRecipeInput; +import net.minecraft.util.collection.DefaultedList; + +public interface RawShapedRecipeAccess { + DefaultedList itematic$remainder(CraftingRecipeInput input); +} diff --git a/src/main/java/net/errorcraft/itematic/component/ItematicDataComponentTypes.java b/src/main/java/net/errorcraft/itematic/component/ItematicDataComponentTypes.java index 6b51a92a..d4db9e29 100644 --- a/src/main/java/net/errorcraft/itematic/component/ItematicDataComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/component/ItematicDataComponentTypes.java @@ -34,6 +34,8 @@ public class ItematicDataComponentTypes { public static final ComponentType SHOOTER_DEFAULT_CHARGING_SOUNDS = DataComponentTypesAccessor.register("shooter_default_charging_sounds", builder -> builder.codec(CrossbowItem.LoadingSounds.CODEC).packetCodec(ChargingSoundsUtil.PACKET_CODEC).cache()); public static final ComponentType SHOOTER_CHARGED_POWER_RULES = DataComponentTypesAccessor.register("shooter_charged_power_rules", builder -> builder.codec(ChargeableShooterMethod.ChargedPowerRules.CODEC).packetCodec(ChargeableShooterMethod.ChargedPowerRules.PACKET_CODEC)); public static final ComponentType> SHOOTER_SHOOT_SOUND = DataComponentTypesAccessor.register("shooter_shoot_sound", builder -> builder.codec(SoundEvent.ENTRY_CODEC).packetCodec(SoundEvent.ENTRY_PACKET_CODEC)); + public static final ComponentType USE_REMAINDER = DataComponentTypesAccessor.register("use_remainder", builder -> builder.codec(UseRemainderDataComponent.CODEC).packetCodec(UseRemainderDataComponent.PACKET_CODEC).cache()); + public static final ComponentType USE_COOLDOWN = DataComponentTypesAccessor.register("use_cooldown", builder -> builder.codec(UseCooldownDataComponent.CODEC).packetCodec(UseCooldownDataComponent.PACKET_CODEC).cache()); private ItematicDataComponentTypes() {} diff --git a/src/main/java/net/errorcraft/itematic/component/type/UseCooldownDataComponent.java b/src/main/java/net/errorcraft/itematic/component/type/UseCooldownDataComponent.java new file mode 100644 index 00000000..f4be4f01 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/component/type/UseCooldownDataComponent.java @@ -0,0 +1,32 @@ +package net.errorcraft.itematic.component.type; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.netty.buffer.ByteBuf; +import net.minecraft.SharedConstants; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.codec.PacketCodec; +import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.util.dynamic.Codecs; + +public record UseCooldownDataComponent(float seconds) { + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance.group( + Codecs.POSITIVE_FLOAT.fieldOf("seconds").forGetter(UseCooldownDataComponent::seconds) + ).apply(instance, UseCooldownDataComponent::new)); + public static final PacketCodec PACKET_CODEC = PacketCodecs.FLOAT.xmap( + UseCooldownDataComponent::new, + UseCooldownDataComponent::seconds + ); + + public int ticks() { + return (int)(this.seconds * SharedConstants.TICKS_PER_SECOND); + } + + public void set(ItemStack stack, LivingEntity user) { + if (user instanceof PlayerEntity player) { + player.getItemCooldownManager().set(stack.getItem(), this.ticks()); + } + } +} diff --git a/src/main/java/net/errorcraft/itematic/component/type/UseDurationDataComponent.java b/src/main/java/net/errorcraft/itematic/component/type/UseDurationDataComponent.java index 2c12373e..cedd69cc 100644 --- a/src/main/java/net/errorcraft/itematic/component/type/UseDurationDataComponent.java +++ b/src/main/java/net/errorcraft/itematic/component/type/UseDurationDataComponent.java @@ -1,8 +1,6 @@ package net.errorcraft.itematic.component.type; import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.item.use.provider.IntegerProvider; import net.errorcraft.itematic.item.use.provider.providers.ConstantIntegerProvider; import net.minecraft.entity.LivingEntity; @@ -11,39 +9,32 @@ import net.minecraft.item.ItemUsage; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; -import net.minecraft.network.codec.PacketCodecs; import net.minecraft.util.Hand; import net.minecraft.util.dynamic.Codecs; import net.minecraft.world.World; -import java.util.Optional; - -public record UseDurationDataComponent(Optional ticks) { - public static final UseDurationDataComponent INDEFINITE = new UseDurationDataComponent(Optional.empty()); - public static final MapCodec MAP_CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - IntegerProvider.CODEC.optionalFieldOf("ticks").forGetter(UseDurationDataComponent::ticks) - ).apply(instance, UseDurationDataComponent::new)); +public record UseDurationDataComponent(IntegerProvider ticks) { + private static final Codec FULL_CODEC = IntegerProvider.CODEC.xmap( + UseDurationDataComponent::new, + UseDurationDataComponent::ticks + ); public static final Codec CODEC = Codec.withAlternative( - MAP_CODEC.codec(), + FULL_CODEC, Codecs.POSITIVE_INT, UseDurationDataComponent::new ); - public static final PacketCodec PACKET_CODEC = PacketCodecs.optional(IntegerProvider.PACKET_CODEC) - .xmap(UseDurationDataComponent::new, UseDurationDataComponent::ticks); + public static final PacketCodec PACKET_CODEC = IntegerProvider.PACKET_CODEC.xmap( + UseDurationDataComponent::new, + UseDurationDataComponent::ticks + ); public static final int INDEFINITE_USE_DURATION = -1; - public UseDurationDataComponent(IntegerProvider ticks) { - this(Optional.of(ticks)); - } - private UseDurationDataComponent(int ticks) { this(new ConstantIntegerProvider(ticks)); } public int ticks(ItemStack stack, LivingEntity user) { - return this.ticks.map(useDuration -> useDuration.get(stack, user)) - .map(useDuration -> useDuration.orElse(0)) - .orElse(INDEFINITE_USE_DURATION); + return this.ticks.get(stack, user).orElse(0); } public boolean startUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { @@ -51,11 +42,13 @@ public boolean startUsing(World world, PlayerEntity user, Hand hand, ItemStack s if (ticks == 0) { return false; } + if (ticks == INDEFINITE_USE_DURATION) { ItemUsage.consumeHeldItem(world, user, hand); } else { user.itematic$startUsingHand(hand, ticks); } + return true; } } diff --git a/src/main/java/net/errorcraft/itematic/component/type/UseRemainderDataComponent.java b/src/main/java/net/errorcraft/itematic/component/type/UseRemainderDataComponent.java new file mode 100644 index 00000000..6e5d3f76 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/component/type/UseRemainderDataComponent.java @@ -0,0 +1,40 @@ +package net.errorcraft.itematic.component.type; + +import com.mojang.serialization.Codec; +import net.minecraft.item.ItemStack; +import net.minecraft.network.RegistryByteBuf; +import net.minecraft.network.codec.PacketCodec; + +public record UseRemainderDataComponent(ItemStack remainder) { + public static final Codec CODEC = ItemStack.CODEC.xmap( + UseRemainderDataComponent::new, + UseRemainderDataComponent::remainder + ); + public static final PacketCodec PACKET_CODEC = ItemStack.PACKET_CODEC.xmap( + UseRemainderDataComponent::new, + UseRemainderDataComponent::remainder + ); + + public ItemStack convert(ItemStack stack, int oldCount, boolean inCreativeMode, RemainderConsumer inserter) { + if (inCreativeMode) { + return stack; + } + + if (stack.getCount() >= oldCount) { + return stack; + } + + ItemStack remainder = this.remainder.copy(); + if (stack.isEmpty()) { + return remainder; + } + + inserter.apply(remainder); + return stack; + } + + @FunctionalInterface + public interface RemainderConsumer { + void apply(ItemStack stack); + } +} diff --git a/src/main/java/net/errorcraft/itematic/component/type/WeaponAttackDamageDataComponent.java b/src/main/java/net/errorcraft/itematic/component/type/WeaponAttackDamageDataComponent.java index 861ba041..09a2d5b4 100644 --- a/src/main/java/net/errorcraft/itematic/component/type/WeaponAttackDamageDataComponent.java +++ b/src/main/java/net/errorcraft/itematic/component/type/WeaponAttackDamageDataComponent.java @@ -11,11 +11,9 @@ import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; import net.minecraft.predicate.item.ItemPredicate; -import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryCodecs; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.registry.tag.TagKey; import java.util.List; import java.util.Optional; @@ -37,6 +35,7 @@ public double getDamage(ItemStack stack, Entity entity) { return rule.damage.get(); } } + return this.defaultDamage; } @@ -46,7 +45,8 @@ public boolean shouldAddBase(ItemStack stack, Entity entity) { return rule.addBase.get(); } } - return false; + + return true; } public record Rule(Optional>> entities, Optional item, Optional damage, Optional addBase) { @@ -64,20 +64,12 @@ public record Rule(Optional>> entities, Optional Rule::new ); - public static Rule addsToBase(TagKey> entityTypes, double damage) { - return new Rule( - Optional.ofNullable(Registries.ENTITY_TYPE.getOrCreateEntryList(entityTypes)), - Optional.empty(), - Optional.of(damage), - Optional.of(true) - ); - } - @SuppressWarnings("deprecation") public boolean matches(ItemStack stack, Entity entity) { if (this.entities.isPresent() && !this.entities.get().contains(entity.getType().getRegistryEntry())) { return false; } + return this.item.map(item -> item.test(stack)) .orElse(true); } diff --git a/src/main/java/net/errorcraft/itematic/entity/effect/StatusEffectKeys.java b/src/main/java/net/errorcraft/itematic/entity/effect/StatusEffectKeys.java index d0ab3050..f6799c94 100644 --- a/src/main/java/net/errorcraft/itematic/entity/effect/StatusEffectKeys.java +++ b/src/main/java/net/errorcraft/itematic/entity/effect/StatusEffectKeys.java @@ -6,16 +6,19 @@ import net.minecraft.util.Identifier; public class StatusEffectKeys { - public static final RegistryKey JUMP_BOOST = of("jump_boost"); - public static final RegistryKey REGENERATION = of("regeneration"); - public static final RegistryKey FIRE_RESISTANCE = of("fire_resistance"); + public static final RegistryKey ABSORPTION = of("absorption"); public static final RegistryKey BLINDNESS = of("blindness"); + public static final RegistryKey FIRE_RESISTANCE = of("fire_resistance"); + public static final RegistryKey HUNGER = of("hunger"); + public static final RegistryKey JUMP_BOOST = of("jump_boost"); + public static final RegistryKey NAUSEA = of("nausea"); public static final RegistryKey NIGHT_VISION = of("night_vision"); - public static final RegistryKey WEAKNESS = of("weakness"); public static final RegistryKey POISON = of("poison"); - public static final RegistryKey WITHER = of("wither"); - public static final RegistryKey ABSORPTION = of("absorption"); + public static final RegistryKey REGENERATION = of("regeneration"); + public static final RegistryKey RESISTANCE = of("resistance"); public static final RegistryKey SATURATION = of("saturation"); + public static final RegistryKey WEAKNESS = of("weakness"); + public static final RegistryKey WITHER = of("wither"); private static RegistryKey of(String id) { return RegistryKey.of(RegistryKeys.STATUS_EFFECT, Identifier.ofVanilla(id)); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index 52acf641..06084204 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -31,6 +31,7 @@ import net.errorcraft.itematic.item.shooter.method.methods.DirectShooterMethod; import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; import net.errorcraft.itematic.item.smithing.template.SmithingTemplates; +import net.errorcraft.itematic.item.use.provider.providers.IndefiniteIntegerProvider; import net.errorcraft.itematic.loot.predicate.SideCheckPredicate; import net.errorcraft.itematic.mixin.component.type.BundleContentsComponentAccessor; import net.errorcraft.itematic.mixin.item.*; @@ -199,7 +200,6 @@ private void bootstrapConsumables() { .noConsumeParticles() .consumeSound(this.soundEvents.getOrThrow(SoundEventKeys.GENERIC_DRINK)) .build()) - .with(RecipeRemainderItemComponent.of(this.items.getOrThrow(ItemKeys.BUCKET))) .build(), ItemEventMap.builder() .add(ItemEvents.CONSUME_ITEM, ActionEntry.of(ClearStatusEffectsAction.of(ActionContextParameter.THIS))) @@ -421,6 +421,17 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.CHICKEN).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + ActionRequirements.of( + ActionContextParameters.of(ActionContextParameter.THIS, ActionContextParameter.THIS), + RandomChanceLootCondition.builder(0.3f).build() + ), + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.POISON), 600) + ) + )) .build() )); this.registerable.register(ItemKeys.COOKED_CHICKEN, create( @@ -484,6 +495,15 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.PUFFERFISH).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.POISON), 1200, 1), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.HUNGER), 300, 2), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.NAUSEA), 300) + ) + )) .build() )); this.registerable.register(ItemKeys.COOKED_COD, create( @@ -548,6 +568,17 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.ROTTEN_FLESH).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + ActionRequirements.of( + ActionContextParameters.of(ActionContextParameter.THIS, ActionContextParameter.THIS), + RandomChanceLootCondition.builder(0.8f).build() + ), + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.HUNGER), 600) + ) + )) .build() )); this.registerable.register(ItemKeys.SPIDER_EYE, create( @@ -555,6 +586,13 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.SPIDER_EYE).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.POISON), 100) + ) + )) .build() )); this.registerable.register(ItemKeys.POISONOUS_POTATO, create( @@ -562,6 +600,17 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.POISONOUS_POTATO).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + ActionRequirements.of( + ActionContextParameters.of(ActionContextParameter.THIS, ActionContextParameter.THIS), + RandomChanceLootCondition.builder(0.6f).build() + ), + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.POISON), 100) + ) + )) .build() )); this.registerable.register(ItemKeys.GOLDEN_APPLE, create( @@ -571,6 +620,14 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.GOLDEN_APPLE).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.REGENERATION), 100, 1), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.ABSORPTION), 2400) + ) + )) .build() )); this.registerable.register(ItemKeys.ENCHANTED_GOLDEN_APPLE, create( @@ -581,6 +638,16 @@ private void bootstrapFood() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ConsumableItemComponent.builder(FoodComponents.ENCHANTED_GOLDEN_APPLE).build()) + .build(), + ItemEventMap.builder() + .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( + AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.REGENERATION), 400, 1), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.RESISTANCE), 6000), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.FIRE_RESISTANCE), 6000), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.ABSORPTION), 2400) + ) + )) .build() )); this.registerable.register(ItemKeys.GOLDEN_CARROT, create( @@ -609,7 +676,6 @@ private void bootstrapFood() { .noConsumeParticles() .consumeSound(this.soundEvents.getOrThrow(SoundEventKeys.HONEY_BOTTLE_DRINK)) .build()) - .with(RecipeRemainderItemComponent.of(this.items.getOrThrow(ItemKeys.GLASS_BOTTLE))) .build(), ItemEventMap.builder() .add(ItemEvents.CONSUME_ITEM, ActionEntry.of( @@ -7100,6 +7166,7 @@ private void bootstrapEquipment() { ItemComponentSet.builder() .with(StackableItemComponent.of(1)) .with(UseableItemComponent.builder() + .useFor(IndefiniteIntegerProvider.INSTANCE) .animation(UseAction.BLOCK) .build()) .with(DamageableItemComponent.of(336)) @@ -9497,15 +9564,13 @@ private void bootstrapBuckets() { ItemBase.Builder.forItem(ItemKeys.WATER_BUCKET).build(), ItemComponentSet.builder() .with(BucketItemComponent.fluid(this.fluids.getOrThrow(FluidKeys.WATER), this.soundEvents.getOrThrow(SoundEventKeys.BUCKET_EMPTY), this.items, this.dispenseBehaviors)) - .with(RecipeRemainderItemComponent.of(this.items.getOrThrow(ItemKeys.BUCKET))) .build() )); this.registerable.register(ItemKeys.LAVA_BUCKET, create( ItemBase.Builder.forItem(ItemKeys.LAVA_BUCKET).build(), ItemComponentSet.builder() .with(BucketItemComponent.fluid(this.fluids.getOrThrow(FluidKeys.LAVA), this.soundEvents.getOrThrow(SoundEventKeys.BUCKET_EMPTY_LAVA), this.items, this.dispenseBehaviors)) - .with(FuelItemComponent.of(FurnaceBlockEntityUtil.LAVA_FUEL_TIME)) - .with(RecipeRemainderItemComponent.of(this.items.getOrThrow(ItemKeys.BUCKET))) + .with(FuelItemComponent.of(FurnaceBlockEntityUtil.LAVA_FUEL_TIME, this.items.getOrThrow(ItemKeys.BUCKET))) .build() )); this.registerable.register(ItemKeys.POWDER_SNOW_BUCKET, create( @@ -10286,7 +10351,7 @@ private void bootstrapMiscellaneous() { .with(StackableItemComponent.of(1)) .with(ZoomItemComponent.of(SpyglassItem.FOV_MULTIPLIER, this.soundEvents.getOrThrow(SoundEventKeys.SPYGLASS_USE), this.soundEvents.getOrThrow(SoundEventKeys.SPYGLASS_STOP_USING))) .with(UseableItemComponent.builder() - .ticks(SpyglassItem.MAX_USE_TIME) + .useFor(SpyglassItem.MAX_USE_TIME) .animation(UseAction.SPYGLASS) .build()) .build() @@ -10530,7 +10595,6 @@ private void bootstrapMiscellaneous() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(RecipeRemainderItemComponent.of(this.items.getOrThrow(ItemKeys.GLASS_BOTTLE))) .build() )); this.registerable.register(ItemKeys.TOTEM_OF_UNDYING, create( @@ -10539,10 +10603,16 @@ private void bootstrapMiscellaneous() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(1)) - .with(LifeSavingItemComponent.of( - new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.REGENERATION), 900, 1), - new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.ABSORPTION), 100, 1), - new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.FIRE_RESISTANCE), 800, 0) + .build(), + ItemEventMap.builder() + .add(ItemEvents.BEFORE_DEATH_HOLDER, ActionEntry.of( + UncheckedSequenceHandler.builder() + .add(ClearStatusEffectsAction.of(ActionContextParameter.THIS)) + .add(AddStatusEffectsAction.of( + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.REGENERATION), 900, 1), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.ABSORPTION), 100, 1), + new StatusEffectInstance(this.statusEffects.getOrThrow(StatusEffectKeys.FIRE_RESISTANCE), 800, 0) + )) )) .build() )); diff --git a/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java index c5fef10c..dc5ae68d 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java @@ -54,7 +54,9 @@ default boolean postMine(ItemStack stack, World world, BlockState state, BlockPo default void using(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks) {} - default void stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) {} + default boolean stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { + return false; + } default void finishUsing(World world, LivingEntity user, ItemStack stack, int usedTicks, ItemStackConsumer resultStackConsumer) {} diff --git a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java index c86f5e83..69f04c15 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -25,7 +25,6 @@ public class ItemComponentTypes { public static final ItemComponentType DYE = register("dye", new ItemComponentType<>(DyeItemComponent.CODEC)); public static final ItemComponentType DYEABLE = register("dyeable", new ItemComponentType<>(DyeableItemComponent.CODEC)); public static final ItemComponentType TINTED = register("tinted", new ItemComponentType<>(TintedItemComponent.CODEC)); - public static final ItemComponentType USEABLE_ON_FLUID = register("useable_on_fluid", new ItemComponentType<>(UseableOnFluidItemComponent.CODEC)); public static final ItemComponentType SPAWN_EGG = register("spawn_egg", new ItemComponentType<>(SpawnEggItemComponent.CODEC)); public static final ItemComponentType DISPENSABLE = register("dispensable", new ItemComponentType<>(DispensableItemComponent.CODEC)); public static final ItemComponentType SHOOTER = register("shooter", new ItemComponentType<>(ShooterItemComponent.CODEC)); @@ -54,11 +53,9 @@ public class ItemComponentTypes { public static final ItemComponentType ZOOM = register("zoom", new ItemComponentType<>(ZoomItemComponent.CODEC)); public static final ItemComponentType ITEM_HOLDER = register("item_holder", new ItemComponentType<>(ItemHolderItemComponent.CODEC)); public static final ItemComponentType IMMUNE_TO_DAMAGE = register("immune_to_damage", new ItemComponentType<>(ImmuneToDamageItemComponent.CODEC)); - public static final ItemComponentType LIFE_SAVING = register("life_saving", new ItemComponentType<>(LifeSavingItemComponent.CODEC)); public static final ItemComponentType UNLOCK_RECIPES = register("unlock_recipes", new ItemComponentType<>(UnlockRecipesItemComponent.CODEC)); public static final ItemComponentType DEBUG_STICK = register("debug_stick", new ItemComponentType<>(DebugStickItemComponent.CODEC)); public static final ItemComponentType SUSPICIOUS_EFFECT_INGREDIENT = register("suspicious_effect_ingredient", new ItemComponentType<>(SuspiciousEffectIngredientItemComponent.CODEC)); - public static final ItemComponentType RECIPE_REMAINDER = register("recipe_remainder", new ItemComponentType<>(RecipeRemainderItemComponent.CODEC)); public static final ItemComponentType CASTABLE = register("castable", new ItemComponentType<>(CastableItemComponent.CODEC)); public static final ItemComponentType STACKABLE = register("stackable", new ItemComponentType<>(StackableItemComponent.CODEC)); public static final ItemComponentType ATTRIBUTE_MODIFIERS = register("attribute_modifiers", new ItemComponentType<>(AttributeModifiersItemComponent.CODEC)); diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/BlockItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/BlockItemComponent.java index 0e2195bd..602b5a2d 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/BlockItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/BlockItemComponent.java @@ -11,7 +11,7 @@ import net.errorcraft.itematic.item.placement.block.picker.pickers.AttachedToSideBlockPicker; import net.errorcraft.itematic.item.placement.block.picker.pickers.SimpleBlockPicker; import net.errorcraft.itematic.mixin.item.ItemAccessor; -import net.errorcraft.itematic.serialization.ItematicCodecs; +import net.errorcraft.itematic.serialization.SetCodec; import net.minecraft.block.Block; import net.minecraft.block.ShulkerBoxBlock; import net.minecraft.component.ComponentMap; @@ -42,7 +42,7 @@ public record BlockItemComponent(BlockPicker block, boolean operatorOnly, Set public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( BlockPicker.CODEC.fieldOf("block").forGetter(BlockItemComponent::block), Codec.BOOL.optionalFieldOf("operator_only", false).forGetter(BlockItemComponent::operatorOnly), - ItematicCodecs.setCodec(Pass.CODEC).optionalFieldOf("passes", Pass.DEFAULT_PASSES).forGetter(BlockItemComponent::passes) + SetCodec.forEnum(Pass.CODEC).optionalFieldOf("passes", Pass.DEFAULT_PASSES).forGetter(BlockItemComponent::passes) ).apply(instance, BlockItemComponent::new)); public static BlockItemComponent of(BlockPicker block, boolean operatorOnly, Set passes) { diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/BrushItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/BrushItemComponent.java index cf420ae2..1e484c59 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/BrushItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/BrushItemComponent.java @@ -19,7 +19,7 @@ public record BrushItemComponent() implements ItemComponent public static ItemComponent[] of(int brushTicks) { return new ItemComponent[] { UseableItemComponent.builder() - .ticks(brushTicks) + .useFor(brushTicks) .animation(UseAction.BRUSH) .passes(UseableItemComponent.Pass.BLOCK) .build(), diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ConsumableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ConsumableItemComponent.java index 785adc8f..6cbbc4c8 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ConsumableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ConsumableItemComponent.java @@ -15,11 +15,8 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsage; import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryFixedCodec; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvent; @@ -31,19 +28,17 @@ import java.util.HashSet; import java.util.Objects; -import java.util.Optional; import java.util.Set; -public record ConsumableItemComponent(Optional> resultItem, boolean hasConsumeParticles, RegistryEntry sound) implements ItemComponent { +public record ConsumableItemComponent(boolean hasConsumeParticles, RegistryEntry sound) implements ItemComponent { private static final RegistryEntry DEFAULT_SOUND = Registries.SOUND_EVENT.getEntry(SoundEvents.ENTITY_GENERIC_EAT); public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryFixedCodec.of(RegistryKeys.ITEM).optionalFieldOf("result_item").forGetter(ConsumableItemComponent::resultItem), Codec.BOOL.optionalFieldOf("has_consume_particles", true).forGetter(ConsumableItemComponent::hasConsumeParticles), SoundEvent.ENTRY_CODEC.optionalFieldOf("sound", DEFAULT_SOUND).forGetter(ConsumableItemComponent::sound) ).apply(instance, ConsumableItemComponent::new)); - public static ConsumableItemComponent of(RegistryEntry resultItem, boolean hasConsumeParticles, RegistryEntry sound) { - return new ConsumableItemComponent(Optional.ofNullable(resultItem), hasConsumeParticles, sound); + public static ConsumableItemComponent of(boolean hasConsumeParticles, RegistryEntry sound) { + return new ConsumableItemComponent(hasConsumeParticles, sound); } public static Builder builder(int useDuration) { @@ -77,9 +72,8 @@ public void consume(LivingEntity user, ItemStack stack, ItemStackConsumer result .build(); stack.itematic$invokeEvent(ItemEvents.CONSUME_ITEM, context); } - this.resultItem.map(ItemStack::new) - .map(resultStack -> ItemUsage.exchangeStack(stack, player, resultStack)) - .ifPresentOrElse(resultStackConsumer::set, () -> stack.decrementUnlessCreative(1, user)); + + stack.decrementUnlessCreative(1, user); if (player instanceof ServerPlayerEntity serverPlayer) { Criteria.CONSUME_ITEM.trigger(serverPlayer, stack); } @@ -102,11 +96,12 @@ private Builder(int useDuration) { public ItemComponent[] build() { Set> behavior = new HashSet<>(); behavior.add(UseableItemComponent.builder() - .ticks(this.useDuration) + .useFor(this.useDuration) .animation(this.useAnimation) + .remainder(this.resultItem) .build() ); - behavior.add(ConsumableItemComponent.of(this.resultItem, this.hasConsumeParticles, this.consumeSound)); + behavior.add(ConsumableItemComponent.of(this.hasConsumeParticles, this.consumeSound)); if (this.food != null) { behavior.add(this.food); } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/CooldownItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/CooldownItemComponent.java index ec289228..15866af8 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/CooldownItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/CooldownItemComponent.java @@ -2,22 +2,24 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.item.ItemStackConsumer; +import net.errorcraft.itematic.component.ItematicDataComponentTypes; +import net.errorcraft.itematic.component.type.UseCooldownDataComponent; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; +import net.minecraft.SharedConstants; +import net.minecraft.component.ComponentMap; import net.minecraft.util.dynamic.Codecs; -import net.minecraft.world.World; public record CooldownItemComponent(int ticks) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codecs.POSITIVE_INT.fieldOf("ticks").forGetter(CooldownItemComponent::ticks) ).apply(instance, CooldownItemComponent::new)); + public static CooldownItemComponent of(int ticks) { + return new CooldownItemComponent(ticks); + } + @Override public ItemComponentType type() { return ItemComponentTypes.COOLDOWN; @@ -29,12 +31,7 @@ public Codec codec() { } @Override - public ActionResult use(World world, PlayerEntity user, Hand hand, ItemStack stack, ItemStackConsumer resultStackConsumer) { - user.getItemCooldownManager().set(stack.getItem(), this.ticks); - return ActionResult.PASS; - } - - public static CooldownItemComponent of(int ticks) { - return new CooldownItemComponent(ticks); + public void addComponents(ComponentMap.Builder builder) { + builder.add(ItematicDataComponentTypes.USE_COOLDOWN, new UseCooldownDataComponent((float) this.ticks / SharedConstants.TICKS_PER_SECOND)); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/DamageableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/DamageableItemComponent.java index 9b04a728..87a58345 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/DamageableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/DamageableItemComponent.java @@ -2,7 +2,6 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.component.type.WeaponAttackDamageDataComponent; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; @@ -21,7 +20,6 @@ import net.minecraft.sound.SoundEvent; import net.minecraft.util.dynamic.Codecs; -import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -57,10 +55,7 @@ public static ItemComponent[] sword(ToolMaterial material, TagKey repai WeaponItemComponent.of( 1, attackDamage, - 0.4d, - Arrays.stream(proficientEntityTypeTags) - .map(proficientEntityTypeTag -> WeaponAttackDamageDataComponent.Rule.addsToBase(proficientEntityTypeTag, attackDamage - 1.0d)) - .toArray(WeaponAttackDamageDataComponent.Rule[]::new) + 0.4d ), EnchantableItemComponent.of(material), RepairableItemComponent.of(repairItemsTag) @@ -102,10 +97,7 @@ private static ItemComponent[] tool(ToolMaterial material, double attackDamag WeaponItemComponent.of( 2, realAttackDamage, - attackSpeed, - Arrays.stream(proficientEntityTypeTags) - .map(proficientEntityTypeTag -> WeaponAttackDamageDataComponent.Rule.addsToBase(proficientEntityTypeTag, realAttackDamage - 1.0d)) - .toArray(WeaponAttackDamageDataComponent.Rule[]::new) + attackSpeed ), EnchantableItemComponent.of(material), RepairableItemComponent.of(repairItemsTag) diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/EntityItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/EntityItemComponent.java index b4f4195e..62ddd0d0 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/EntityItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/EntityItemComponent.java @@ -13,11 +13,14 @@ import net.errorcraft.itematic.item.dispense.behavior.DispenseBehaviors; import net.errorcraft.itematic.item.placement.EntityPlacer; import net.errorcraft.itematic.mixin.item.DecorationItemAccessor; +import net.errorcraft.itematic.mixin.item.ItemAccessor; import net.errorcraft.itematic.mixin.item.SpawnEggItemAccessor; +import net.errorcraft.itematic.serialization.SetCodec; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.NbtComponent; import net.minecraft.entity.EntityType; import net.minecraft.entity.decoration.painting.PaintingEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; @@ -28,18 +31,41 @@ import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; +import net.minecraft.util.Hand; +import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.world.RaycastContext; +import net.minecraft.world.World; import java.util.List; import java.util.Optional; +import java.util.Set; -public record EntityItemComponent(EntityInitializer entity, boolean allowItemData) implements ItemComponent { +public record EntityItemComponent(EntityInitializer entity, boolean allowItemData, Set passes) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( EntityInitializer.CODEC.fieldOf("entity").forGetter(EntityItemComponent::entity), - Codec.BOOL.optionalFieldOf("allow_item_data", false).forGetter(EntityItemComponent::allowItemData) + Codec.BOOL.optionalFieldOf("allow_item_data", false).forGetter(EntityItemComponent::allowItemData), + SetCodec.forEnum(Pass.CODEC).optionalFieldOf("passes", Pass.DEFAULT_PASSES).forGetter(EntityItemComponent::passes) ).apply(instance, EntityItemComponent::new)); private static final MapCodec> ENTITY_TYPE_MAP_CODEC = SpawnEggItemAccessor.entityTypeMapCodec(); private static final Text RANDOM_TEXT = DecorationItemAccessor.randomText(); + public static EntityItemComponent of(EntityInitializer entity) { + return new EntityItemComponent(entity, false, Pass.DEFAULT_PASSES); + } + + public static EntityItemComponent of(EntityInitializer entity, boolean allowItemData, Pass... passes) { + return new EntityItemComponent(entity, allowItemData, Set.of(passes)); + } + + public static ItemComponent[] from(EntityInitializer entity, RegistryEntryLookup dispenseBehaviors) { + return new ItemComponent[] { + of(entity), + DispensableItemComponent.of(dispenseBehaviors.getOrThrow(DispenseBehaviors.SPAWN_ENTITY_FROM_ITEM)) + }; + } + @Override public ItemComponentType type() { return ItemComponentTypes.ENTITY; @@ -50,6 +76,38 @@ public Codec codec() { return CODEC; } + @Override + public ActionResult use(World world, PlayerEntity user, Hand hand, ItemStack stack, ItemStackConsumer resultStackConsumer) { + if (this.isUnuseable(Pass.FLUID)) { + return ActionResult.PASS; + } + + if (world.isClient()) { + return ActionResult.SUCCESS; + } + + BlockHitResult blockHitResult = ItemAccessor.raycast(world, user, RaycastContext.FluidHandling.SOURCE_ONLY); + if (blockHitResult.getType() != HitResult.Type.BLOCK) { + return ActionResult.PASS; + } + + ItemUsageContext itemUsageContext = new ItemUsageContext(world, user, hand, stack, blockHitResult); + return this.place(itemUsageContext, resultStackConsumer); + } + + @Override + public ActionResult useOnBlock(ItemUsageContext context, ItemStackConsumer resultStackConsumer) { + if (this.isUnuseable(Pass.BLOCK)) { + return ActionResult.PASS; + } + + if (context.getWorld().isClient()) { + return ActionResult.SUCCESS; + } + + return this.place(context, resultStackConsumer); + } + @Override public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { if (this.entity.type() != EntityType.PAINTING) { @@ -81,43 +139,43 @@ public void appendTooltip(ItemStack stack, Item.TooltipContext context, List entity) { - return of(entity, false); - } - - public static EntityItemComponent of(EntityInitializer entity, boolean allowItemData) { - return new EntityItemComponent(entity, allowItemData); - } - - public static ItemComponent[] from(EntityInitializer entity, RegistryEntryLookup dispenseBehaviors) { - return from(entity, false, dispenseBehaviors); - } - - public static ItemComponent[] from(EntityInitializer entity, boolean allowItemData, RegistryEntryLookup dispenseBehaviors) { - return new ItemComponent[] { - of(entity, allowItemData), - DispensableItemComponent.of(dispenseBehaviors.getOrThrow(DispenseBehaviors.SPAWN_ENTITY_FROM_ITEM)) - }; + private boolean isUnuseable(Pass pass) { + return !this.passes.contains(pass); } - @Override - public ActionResult useOnBlock(ItemUsageContext context, ItemStackConsumer resultStackConsumer) { - ItemStack stack = context.getStack(); - if (context.getWorld().isClient()) { - return ActionResult.SUCCESS; - } - EntityPlacer placer = EntityPlacer.spawned(context, stack, resultStackConsumer, this); - return placer.place(); + private ActionResult place(ItemUsageContext context, ItemStackConsumer resultStackConsumer) { + return EntityPlacer.spawned(context, context.getStack(), resultStackConsumer, this) + .place(); } public EntityInitializer getEntityInitializer(ItemStack stack) { if (!this.allowItemData) { return this.entity; } + NbtComponent entityData = stack.getOrDefault(DataComponentTypes.ENTITY_DATA, NbtComponent.DEFAULT); Optional> initializer = entityData.get(ENTITY_TYPE_MAP_CODEC) .result() .map(SimpleEntityInitializer::new); return initializer.orElse(this.entity); } + + public enum Pass implements StringIdentifiable { + BLOCK("block"), + FLUID("fluid"); + + public static final Set DEFAULT_PASSES = Set.of(BLOCK); + public static final Codec CODEC = StringIdentifiable.createCodec(Pass::values); + + private final String name; + + Pass(String name) { + this.name = name; + } + + @Override + public String asString() { + return this.name; + } + } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/FoodItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/FoodItemComponent.java index 72ee669d..3f348776 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/FoodItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/FoodItemComponent.java @@ -18,16 +18,15 @@ import java.util.List; import java.util.Optional; -public record FoodItemComponent(int nutrition, float saturation, boolean alwaysEdible, List effects) implements ItemComponent { +public record FoodItemComponent(int nutrition, float saturation, boolean alwaysEdible) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codecs.NONNEGATIVE_INT.fieldOf("nutrition").forGetter(FoodItemComponent::nutrition), Codec.FLOAT.fieldOf("saturation").forGetter(FoodItemComponent::saturation), - Codec.BOOL.optionalFieldOf("always_edible", false).forGetter(FoodItemComponent::alwaysEdible), - FoodComponent.StatusEffectEntry.CODEC.listOf().optionalFieldOf("effects", List.of()).forGetter(FoodItemComponent::effects) + Codec.BOOL.optionalFieldOf("always_edible", false).forGetter(FoodItemComponent::alwaysEdible) ).apply(instance, FoodItemComponent::new)); public static FoodItemComponent of(FoodComponent food) { - return new FoodItemComponent(food.nutrition(), food.saturation(), food.canAlwaysEat(), food.effects()); + return new FoodItemComponent(food.nutrition(), food.saturation(), food.canAlwaysEat()); } @Override @@ -50,10 +49,15 @@ public void finishUsing(World world, LivingEntity user, ItemStack stack, int use @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.FOOD, new FoodComponent(this.nutrition, this.saturation, false, 1.0f, Optional.empty(), this.effects)); + builder.add(DataComponentTypes.FOOD, new FoodComponent(this.nutrition, this.saturation, this.alwaysEdible, 1.0f, Optional.empty(), List.of())); } - public boolean mayStartUsing(PlayerEntity user) { - return user.canConsume(this.alwaysEdible); + public boolean mayStartUsing(PlayerEntity user, ItemStack stack) { + FoodComponent food = stack.get(DataComponentTypes.FOOD); + if (food == null) { + return false; + } + + return user.canConsume(food.canAlwaysEat()); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/FuelItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/FuelItemComponent.java index f52ce833..f2f48f9a 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/FuelItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/FuelItemComponent.java @@ -5,13 +5,27 @@ import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.dynamic.Codecs; -public record FuelItemComponent(int ticks) implements ItemComponent { +import java.util.Optional; + +public record FuelItemComponent(int ticks, Optional remainder) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codecs.POSITIVE_INT.fieldOf("ticks").forGetter(FuelItemComponent::ticks) + Codecs.POSITIVE_INT.fieldOf("ticks").forGetter(FuelItemComponent::ticks), + ItemStack.CODEC.optionalFieldOf("remainder").forGetter(FuelItemComponent::remainder) ).apply(instance, FuelItemComponent::new)); + public static FuelItemComponent of(int ticks) { + return new FuelItemComponent(ticks, Optional.empty()); + } + + public static FuelItemComponent of(int ticks, RegistryEntry remainder) { + return new FuelItemComponent(ticks, Optional.of(new ItemStack(remainder))); + } + @Override public ItemComponentType type() { return ItemComponentTypes.FUEL; @@ -21,8 +35,4 @@ public ItemComponentType type() { public Codec codec() { return CODEC; } - - public static FuelItemComponent of(int ticks) { - return new FuelItemComponent(ticks); - } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/LifeSavingItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/LifeSavingItemComponent.java deleted file mode 100644 index 00f7f35c..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/LifeSavingItemComponent.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.errorcraft.itematic.item.component.components; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.item.component.ItemComponent; -import net.errorcraft.itematic.item.component.ItemComponentType; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.effect.StatusEffectInstance; - -import java.util.List; - -public record LifeSavingItemComponent(List effects) implements ItemComponent { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - StatusEffectInstance.CODEC.listOf().fieldOf("effects").forGetter(LifeSavingItemComponent::effects) - ).apply(instance, LifeSavingItemComponent::new)); - - @Override - public ItemComponentType type() { - return ItemComponentTypes.LIFE_SAVING; - } - - @Override - public Codec codec() { - return CODEC; - } - - public void apply(LivingEntity target) { - for (StatusEffectInstance effect : this.effects) { - target.addStatusEffect(new StatusEffectInstance(effect)); - } - } - - public static LifeSavingItemComponent of(StatusEffectInstance... effects) { - return new LifeSavingItemComponent(List.of(effects)); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableItemComponent.java index 9a94c0b4..c53f9ffe 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableItemComponent.java @@ -37,7 +37,7 @@ public record PlayableItemComponent(TagKey instruments) implements I public static ItemComponent[] of(TagKey instruments) { return new ItemComponent[] { UseableItemComponent.builder() - .ticks(PlayableIntegerProvider.INSTANCE) + .useFor(PlayableIntegerProvider.INSTANCE) .animation(UseAction.TOOT_HORN) .build(), new PlayableItemComponent(instruments) diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/RecipeRemainderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/RecipeRemainderItemComponent.java deleted file mode 100644 index 7d127bdf..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/RecipeRemainderItemComponent.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.errorcraft.itematic.item.component.components; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.item.component.ItemComponent; -import net.errorcraft.itematic.item.component.ItemComponentType; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.item.Item; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryFixedCodec; - -public record RecipeRemainderItemComponent(RegistryEntry item) implements ItemComponent { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryFixedCodec.of(RegistryKeys.ITEM).fieldOf("item").forGetter(RecipeRemainderItemComponent::item) - ).apply(instance, RecipeRemainderItemComponent::new)); - - @Override - public ItemComponentType type() { - return ItemComponentTypes.RECIPE_REMAINDER; - } - - @Override - public Codec codec() { - return CODEC; - } - - public static RecipeRemainderItemComponent of(RegistryEntry item) { - return new RecipeRemainderItemComponent(item); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ShooterItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ShooterItemComponent.java index 3ab04895..ce1f2f11 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ShooterItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ShooterItemComponent.java @@ -48,7 +48,7 @@ public record ShooterItemComponent(RegistryEntryList heldAmmunition, Regis public static ItemComponent[] of(UseAction animation, RegistryEntryList heldAmmunition, RegistryEntryList ammunition, int range, ShooterMethod method, ItemDamageRulesDataComponent.Rule... rules) { return new ItemComponent[] { UseableItemComponent.builder() - .ticks(ShooterIntegerProvider.INSTANCE) + .useFor(ShooterIntegerProvider.INSTANCE) .animation(animation) .build(), new ShooterItemComponent( @@ -86,8 +86,8 @@ public void using(ItemStack stack, World world, LivingEntity user, int usedTicks } @Override - public void stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { - this.method.stop(this, stack, world, user, usedTicks); + public boolean stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { + return this.method.stop(this, stack, world, user, usedTicks); } @Override diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/SpawnEggItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/SpawnEggItemComponent.java index 9e09c771..fe7293da 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/SpawnEggItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/SpawnEggItemComponent.java @@ -26,6 +26,15 @@ public record SpawnEggItemComponent() implements ItemComponent CODEC = Codec.unit(INSTANCE); + public static ItemComponent[] from(RegistryEntry> entity, int primaryColor, int secondaryColor, RegistryEntryLookup dispenseBehaviors) { + return new ItemComponent[] { + EntityItemComponent.of(SimpleEntityInitializer.of(entity.value()), true, EntityItemComponent.Pass.BLOCK, EntityItemComponent.Pass.FLUID), + INSTANCE, + TintedItemComponent.of(IndexItemColor.of(primaryColor, secondaryColor)), + DispensableItemComponent.of(dispenseBehaviors.getOrThrow(DispenseBehaviors.SPAWN_ENTITY_FROM_ITEM)) + }; + } + @Override public ItemComponentType type() { return ItemComponentTypes.SPAWN_EGG; @@ -41,36 +50,31 @@ public Optional spawnBaby(PlayerEntity user, MobEntity entity, Entity if (entityItemComponent.isEmpty()) { return Optional.empty(); } + if (entityItemComponent.get().getEntityInitializer(stack).type() != entityType) { return Optional.empty(); } + MobEntity mobEntity = this.createEntity(entity, entityType, world); if (mobEntity == null) { return Optional.empty(); } + if (!mobEntity.itematic$trySetBaby(true)) { return Optional.empty(); } + mobEntity.refreshPositionAfterTeleport(pos); Text customName = stack.get(DataComponentTypes.CUSTOM_NAME); if (customName != null) { mobEntity.setCustomName(customName); } + world.spawnEntityAndPassengers(mobEntity); stack.decrementUnlessCreative(1, user); return Optional.of(mobEntity); } - public static ItemComponent[] from(RegistryEntry> entity, int primaryColor, int secondaryColor, RegistryEntryLookup dispenseBehaviors) { - return new ItemComponent[] { - EntityItemComponent.of(SimpleEntityInitializer.of(entity.value()), true), - INSTANCE, - UseableOnFluidItemComponent.INSTANCE, - TintedItemComponent.of(IndexItemColor.of(primaryColor, secondaryColor)), - DispensableItemComponent.of(dispenseBehaviors.getOrThrow(DispenseBehaviors.SPAWN_ENTITY_FROM_ITEM)) - }; - } - private MobEntity createEntity(MobEntity entity, EntityType entityType, ServerWorld world) { if (entity instanceof PassiveEntity passiveEntity) { return passiveEntity.createChild(world, passiveEntity); diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ThrowableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ThrowableItemComponent.java index 33471d36..487a8d19 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ThrowableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ThrowableItemComponent.java @@ -46,7 +46,7 @@ public static ThrowableItemComponent of(float speed, float angleOffset) { public static ItemComponent[] trident(float speed, float angleOffset, int minDrawDuration) { return new ItemComponent[] { UseableItemComponent.builder() - .ticks(TridentIntegerProvider.INSTANCE) + .useFor(TridentIntegerProvider.INSTANCE) .animation(UseAction.SPEAR) .build(), new ThrowableItemComponent(speed, angleOffset, Optional.of(NumberRange.IntRange.atLeast(minDrawDuration))) @@ -72,13 +72,17 @@ public ActionResult use(World world, PlayerEntity user, Hand hand, ItemStack sta } @Override - public void stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { + public boolean stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { if (this.drawDuration.filter(drawDuration -> drawDuration.test(usedTicks)).isPresent()) { this.createEntity(world, user, stack, resultStackConsumer); if (user instanceof PlayerEntity player) { player.incrementStat(Stats.USED.itematic$getOrCreateStat(stack.getRegistryEntry())); } + + return true; } + + return false; } private ActionResult createEntity(World world, LivingEntity user, ItemStack stack, ItemStackConsumer resultStackConsumer) { diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/UseableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/UseableItemComponent.java index 04390989..c53aa414 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/UseableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/UseableItemComponent.java @@ -4,32 +4,38 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.component.ItematicDataComponentTypes; import net.errorcraft.itematic.component.type.UseDurationDataComponent; +import net.errorcraft.itematic.component.type.UseRemainderDataComponent; import net.errorcraft.itematic.item.ItemStackConsumer; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.use.provider.IntegerProvider; import net.errorcraft.itematic.item.use.provider.providers.ConstantIntegerProvider; -import net.errorcraft.itematic.serialization.ItematicCodecs; +import net.errorcraft.itematic.item.use.provider.providers.IndefiniteIntegerProvider; +import net.errorcraft.itematic.serialization.SetCodec; import net.errorcraft.itematic.util.UseActionUtil; import net.minecraft.component.ComponentMap; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.StringIdentifiable; import net.minecraft.util.UseAction; import net.minecraft.world.World; +import java.util.Optional; import java.util.Set; -public record UseableItemComponent(UseDurationDataComponent ticks, UseAction animation, Set passes) implements ItemComponent { +public record UseableItemComponent(Optional ticks, UseAction animation, Optional remainder, Set passes) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - UseDurationDataComponent.MAP_CODEC.forGetter(UseableItemComponent::ticks), + UseDurationDataComponent.CODEC.optionalFieldOf("ticks").forGetter(UseableItemComponent::ticks), UseActionUtil.CODEC.optionalFieldOf("animation", UseAction.NONE).forGetter(UseableItemComponent::animation), - ItematicCodecs.setCodec(Pass.CODEC).optionalFieldOf("passes", Pass.DEFAULT_PASSES).forGetter(UseableItemComponent::passes) + ItemStack.CODEC.optionalFieldOf("remainder").forGetter(UseableItemComponent::remainder), + SetCodec.forEnum(Pass.CODEC).optionalFieldOf("passes", Pass.DEFAULT_PASSES).forGetter(UseableItemComponent::passes) ).apply(instance, UseableItemComponent::new)); public static Builder builder() { @@ -86,8 +92,9 @@ private static ActionResult tryStartUsing(World world, PlayerEntity user, Hand h @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(ItematicDataComponentTypes.USE_DURATION, this.ticks); + this.ticks.ifPresent(ticks -> builder.add(ItematicDataComponentTypes.USE_DURATION, ticks)); builder.add(ItematicDataComponentTypes.USE_ANIMATION, this.animation); + this.remainder.ifPresent(remainder -> builder.add(ItematicDataComponentTypes.USE_REMAINDER, new UseRemainderDataComponent(remainder))); } private boolean isUnuseable(Pass pass) { @@ -97,33 +104,45 @@ private boolean isUnuseable(Pass pass) { public static class Builder { private IntegerProvider ticks; private UseAction animation = UseAction.NONE; + private RegistryEntry remainder; private Set passes = Pass.DEFAULT_PASSES; private Builder() {} public UseableItemComponent build() { return new UseableItemComponent( - this.ticks == null ? UseDurationDataComponent.INDEFINITE : new UseDurationDataComponent(this.ticks), + Optional.ofNullable(this.ticks).map(UseDurationDataComponent::new), this.animation, + Optional.ofNullable(this.remainder).map(ItemStack::new), this.passes ); } - public Builder ticks(int ticks) { + public Builder useFor(int ticks) { this.ticks = new ConstantIntegerProvider(ticks); return this; } - public Builder ticks(IntegerProvider ticks) { + public Builder useFor(IntegerProvider ticks) { this.ticks = ticks; return this; } + public Builder useIndefinitely() { + this.ticks = IndefiniteIntegerProvider.INSTANCE; + return this; + } + public Builder animation(UseAction animation) { this.animation = animation; return this; } + public Builder remainder(RegistryEntry remainder) { + this.remainder = remainder; + return this; + } + public Builder passes(Pass... passes) { this.passes = Set.of(passes); return this; diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/UseableOnFluidItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/UseableOnFluidItemComponent.java deleted file mode 100644 index 0f869028..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/UseableOnFluidItemComponent.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.errorcraft.itematic.item.component.components; - -import com.mojang.serialization.Codec; -import net.errorcraft.itematic.item.ItemStackConsumer; -import net.errorcraft.itematic.item.component.ItemComponent; -import net.errorcraft.itematic.item.component.ItemComponentType; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.mixin.item.ItemAccessor; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsageContext; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; -import net.minecraft.world.RaycastContext; -import net.minecraft.world.World; - -public record UseableOnFluidItemComponent() implements ItemComponent { - public static final UseableOnFluidItemComponent INSTANCE = new UseableOnFluidItemComponent(); - public static final Codec CODEC = Codec.unit(INSTANCE); - - @Override - public ItemComponentType type() { - return ItemComponentTypes.USEABLE_ON_FLUID; - } - - @Override - public Codec codec() { - return CODEC; - } - - @Override - public ActionResult use(World world, PlayerEntity user, Hand hand, ItemStack stack, ItemStackConsumer resultStackConsumer) { - BlockHitResult blockHitResult = ItemAccessor.raycast(world, user, RaycastContext.FluidHandling.SOURCE_ONLY); - if (blockHitResult.getType() != HitResult.Type.BLOCK) { - return ActionResult.PASS; - } - - ItemUsageContext itemUsageContext = new ItemUsageContext(world, user, hand, stack, blockHitResult); - return stack.useOnBlock(itemUsageContext); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/WeaponItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/WeaponItemComponent.java index 966a008e..61bf0d91 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/WeaponItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/WeaponItemComponent.java @@ -37,10 +37,10 @@ public record WeaponItemComponent(int damagePerHit, WeaponAttackDamageDataCompon ).apply(instance, WeaponItemComponent::new)); private static final MaceItem DUMMY = new MaceItem(new Item.Settings()); - public static WeaponItemComponent of(int damagePerHit, double attackDamage, double attackSpeed, WeaponAttackDamageDataComponent.Rule... rules) { + public static WeaponItemComponent of(int damagePerHit, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, - new WeaponAttackDamageDataComponent(List.of(rules), attackDamage), + new WeaponAttackDamageDataComponent(List.of(), attackDamage), attackSpeed, false ); diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ZoomItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ZoomItemComponent.java index dc19399f..668513c1 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ZoomItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ZoomItemComponent.java @@ -46,8 +46,9 @@ public ActionResult use(World world, PlayerEntity user, Hand hand, ItemStack sta } @Override - public void stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { + public boolean stopUsing(ItemStack stack, World world, LivingEntity user, int usedTicks, int remainingUseTicks, ItemStackConsumer resultStackConsumer) { this.playStopSound(user); + return true; } @Override diff --git a/src/main/java/net/errorcraft/itematic/item/event/ItemEventKeys.java b/src/main/java/net/errorcraft/itematic/item/event/ItemEventKeys.java index c28fd3e3..dd51574d 100644 --- a/src/main/java/net/errorcraft/itematic/item/event/ItemEventKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/event/ItemEventKeys.java @@ -22,6 +22,7 @@ public class ItemEventKeys { public static final RegistryKey EQUIP_ITEM = of("equip_item"); public static final RegistryKey CONSUME_ITEM = of("consume_item"); public static final RegistryKey THROW_PROJECTILE = of("throw_projectile"); + public static final RegistryKey BEFORE_DEATH_HOLDER = of("before_death_holder"); private ItemEventKeys() {} diff --git a/src/main/java/net/errorcraft/itematic/item/event/ItemEventMap.java b/src/main/java/net/errorcraft/itematic/item/event/ItemEventMap.java index b3e74424..29cd7d60 100644 --- a/src/main/java/net/errorcraft/itematic/item/event/ItemEventMap.java +++ b/src/main/java/net/errorcraft/itematic/item/event/ItemEventMap.java @@ -39,6 +39,10 @@ public boolean invokeEvent(ItemEvent event, ActionContext context) { .orElse(false); } + public boolean hasListener(ItemEvent event) { + return this.events.containsKey(event); + } + public static class Builder { private final Map> events = new HashMap<>(); diff --git a/src/main/java/net/errorcraft/itematic/item/event/ItemEvents.java b/src/main/java/net/errorcraft/itematic/item/event/ItemEvents.java index 6582f5db..19d87e15 100644 --- a/src/main/java/net/errorcraft/itematic/item/event/ItemEvents.java +++ b/src/main/java/net/errorcraft/itematic/item/event/ItemEvents.java @@ -22,6 +22,7 @@ public class ItemEvents { public static final ItemEvent EQUIP_ITEM = register(ItemEventKeys.EQUIP_ITEM); public static final ItemEvent CONSUME_ITEM = register(ItemEventKeys.CONSUME_ITEM); public static final ItemEvent THROW_PROJECTILE = register(ItemEventKeys.THROW_PROJECTILE); + public static final ItemEvent BEFORE_DEATH_HOLDER = register(ItemEventKeys.BEFORE_DEATH_HOLDER); private ItemEvents() {} diff --git a/src/main/java/net/errorcraft/itematic/item/shooter/method/ShooterMethod.java b/src/main/java/net/errorcraft/itematic/item/shooter/method/ShooterMethod.java index 4e5bed3c..b833a5a4 100644 --- a/src/main/java/net/errorcraft/itematic/item/shooter/method/ShooterMethod.java +++ b/src/main/java/net/errorcraft/itematic/item/shooter/method/ShooterMethod.java @@ -21,7 +21,7 @@ public interface ShooterMethod { void addComponents(ComponentMap.Builder builder); boolean tryShoot(ShooterItemComponent component, ItemStack stack, World world, LivingEntity user, Hand hand); void hold(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks); - void stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks); + boolean stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks); default void initializeProjectile(LivingEntity user, ProjectileEntity projectile, int index, float power, float uncertainty, float angle, boolean critical, @Nullable LivingEntity target) { if (critical && projectile instanceof PersistentProjectileEntity persistentProjectile) { persistentProjectile.setCritical(true); diff --git a/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/ChargeableShooterMethod.java b/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/ChargeableShooterMethod.java index 90b75542..cac4d3f5 100644 --- a/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/ChargeableShooterMethod.java +++ b/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/ChargeableShooterMethod.java @@ -110,18 +110,19 @@ public void hold(ShooterItemComponent shooter, ItemStack stack, World world, Liv } @Override - public void stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks) { + public boolean stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks) { if (usedTicks < CrossbowItem.getPullTime(stack, user)) { - return; + return false; } if (CrossbowItem.isCharged(stack) || !chargeProjectiles(user, stack)) { - return; + return false; } CrossbowItem.LoadingSounds chargingSounds = this.chargingSounds(stack); float pitch = MathHelper.lerp(world.getRandom().nextFloat(), 0.87f, 1.2f); chargingSounds.end().ifPresent(sound -> world.playSound(null, user.getX(), user.getY(), user.getZ(), sound.value(), user.getSoundCategory(), 1.0f, pitch)); + return true; } @Override diff --git a/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/DirectShooterMethod.java b/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/DirectShooterMethod.java index 90b98098..3e4afc29 100644 --- a/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/DirectShooterMethod.java +++ b/src/main/java/net/errorcraft/itematic/item/shooter/method/methods/DirectShooterMethod.java @@ -60,15 +60,15 @@ public boolean tryShoot(ShooterItemComponent component, ItemStack stack, World w public void hold(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks) {} @Override - public void stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks) { + public boolean stop(ShooterItemComponent shooter, ItemStack stack, World world, LivingEntity user, int usedTicks) { ItemStack ammunition = user.itematic$getAmmunition(stack); if (ammunition.isEmpty()) { - return; + return false; } float pullProgress = this.pullProgress(usedTicks); if (pullProgress < 0.1f) { - return; + return false; } List projectiles = RangedWeaponItemAccessor.load(stack, ammunition, user); @@ -84,6 +84,8 @@ public void stop(ShooterItemComponent shooter, ItemStack stack, World world, Liv if (user instanceof PlayerEntity playerEntity) { playerEntity.incrementStat(Stats.USED.itematic$getOrCreateStat(stack.getRegistryEntry())); } + + return true; } @Override diff --git a/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypeKeys.java b/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypeKeys.java index 126335a4..6c76524e 100644 --- a/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypeKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypeKeys.java @@ -10,6 +10,7 @@ public class IntegerProviderTypeKeys { public static final RegistryKey> SHOOTER = of("shooter"); public static final RegistryKey> TRIDENT = of("trident"); public static final RegistryKey> CONDITION = of("condition"); + public static final RegistryKey> INDEFINITE = of("indefinite"); private IntegerProviderTypeKeys() {} diff --git a/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypes.java b/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypes.java index 0258bd8c..9fc81498 100644 --- a/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/use/provider/IntegerProviderTypes.java @@ -11,6 +11,7 @@ public class IntegerProviderTypes { public static final IntegerProviderType SHOOTER = register(IntegerProviderTypeKeys.SHOOTER, new IntegerProviderType<>(ShooterIntegerProvider.CODEC, ShooterIntegerProvider.PACKET_CODEC)); public static final IntegerProviderType TRIDENT = register(IntegerProviderTypeKeys.TRIDENT, new IntegerProviderType<>(TridentIntegerProvider.CODEC, TridentIntegerProvider.PACKET_CODEC)); public static final IntegerProviderType CONDITION = register(IntegerProviderTypeKeys.CONDITION, new IntegerProviderType<>(ConditionIntegerProvider.CODEC, ConditionIntegerProvider.PACKET_CODEC)); + public static final IntegerProviderType INDEFINITE = register(IntegerProviderTypeKeys.INDEFINITE, new IntegerProviderType<>(IndefiniteIntegerProvider.CODEC, IndefiniteIntegerProvider.PACKET_CODEC)); private IntegerProviderTypes() {} diff --git a/src/main/java/net/errorcraft/itematic/item/use/provider/providers/IndefiniteIntegerProvider.java b/src/main/java/net/errorcraft/itematic/item/use/provider/providers/IndefiniteIntegerProvider.java new file mode 100644 index 00000000..9175b949 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/use/provider/providers/IndefiniteIntegerProvider.java @@ -0,0 +1,31 @@ +package net.errorcraft.itematic.item.use.provider.providers; + +import com.mojang.serialization.MapCodec; +import io.netty.buffer.ByteBuf; +import net.errorcraft.itematic.component.type.UseDurationDataComponent; +import net.errorcraft.itematic.item.use.provider.IntegerProvider; +import net.errorcraft.itematic.item.use.provider.IntegerProviderType; +import net.errorcraft.itematic.item.use.provider.IntegerProviderTypes; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.codec.PacketCodec; + +import java.util.OptionalInt; + +public class IndefiniteIntegerProvider implements IntegerProvider { + public static final IndefiniteIntegerProvider INSTANCE = new IndefiniteIntegerProvider(); + public static final MapCodec CODEC = MapCodec.unit(INSTANCE); + public static final PacketCodec PACKET_CODEC = PacketCodec.unit(INSTANCE); + + private IndefiniteIntegerProvider() {} + + @Override + public IntegerProviderType type() { + return IntegerProviderTypes.INDEFINITE; + } + + @Override + public OptionalInt get(ItemStack stack, LivingEntity user) { + return OptionalInt.of(UseDurationDataComponent.INDEFINITE_USE_DURATION); + } +} diff --git a/src/main/java/net/errorcraft/itematic/loot/predicate/SideCheckPredicate.java b/src/main/java/net/errorcraft/itematic/loot/predicate/SideCheckPredicate.java index 61267334..7bcd7432 100644 --- a/src/main/java/net/errorcraft/itematic/loot/predicate/SideCheckPredicate.java +++ b/src/main/java/net/errorcraft/itematic/loot/predicate/SideCheckPredicate.java @@ -3,7 +3,7 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.loot.context.ItematicLootContextParameters; -import net.errorcraft.itematic.serialization.ItematicCodecs; +import net.errorcraft.itematic.serialization.SetCodec; import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.condition.LootConditionType; import net.minecraft.loot.context.LootContext; @@ -13,7 +13,7 @@ public record SideCheckPredicate(Set sides) implements LootCondition { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - ItematicCodecs.setCodec(Direction.CODEC).fieldOf("sides").forGetter(SideCheckPredicate::sides) + SetCodec.forEnum(Direction.CODEC).fieldOf("sides").forGetter(SideCheckPredicate::sides) ).apply(instance, SideCheckPredicate::new)); @Override diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/entity/AbstractFurnaceBlockEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/entity/AbstractFurnaceBlockEntityExtender.java index 86f91b5e..edfbe1e9 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/entity/AbstractFurnaceBlockEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/entity/AbstractFurnaceBlockEntityExtender.java @@ -4,7 +4,6 @@ import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.FuelItemComponent; -import net.errorcraft.itematic.item.component.components.RecipeRemainderItemComponent; import net.minecraft.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; @@ -146,9 +145,9 @@ private boolean isValidIsOfForBucketUseRegistryKeyCheck(ItemStack instance, Item ) @SuppressWarnings("unchecked") private static E setRemainderItemStackUseItemComponent(E element, @Local(ordinal = 0) Item item) { - return (E) item.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) + return (E) item.itematic$getComponent(ItemComponentTypes.FUEL) + .flatMap(FuelItemComponent::remainder) + .map(ItemStack::copy) .orElse(ItemStack.EMPTY); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/entity/BrewingStandBlockEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/entity/BrewingStandBlockEntityExtender.java index cf071736..f8eeeee0 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/entity/BrewingStandBlockEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/entity/BrewingStandBlockEntityExtender.java @@ -1,20 +1,24 @@ package net.errorcraft.itematic.mixin.block.entity; import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.RecipeRemainderItemComponent; import net.minecraft.block.entity.BrewingStandBlockEntity; import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.recipe.BrewingRecipeRegistry; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(BrewingStandBlockEntity.class) public class BrewingStandBlockEntityExtender { @@ -73,7 +77,10 @@ private boolean isOfRemainingItemChecksReturnFalse(ItemStack instance, Item item } @Redirect( - method = { "isValid", "canExtract" }, + method = { + "isValid", + "canExtract" + }, at = @At( value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z", @@ -114,17 +121,24 @@ private static boolean isOfForBlazePowderUseRegistryKeyCheckStatic(ItemStack ins return instance.itematic$isOf(ItemKeys.BLAZE_POWDER); } - @Redirect( + @Inject( method = "craft", at = @At( - value = "NEW", - target = "(Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/item/ItemStack;" + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;decrement(I)V", + shift = At.Shift.AFTER ) ) - private static ItemStack newItemStackForRemainderUseItemComponent(ItemConvertible item, @Local ItemStack stack) { - return stack.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) - .orElse(ItemStack.EMPTY); + private static void setRemainderForDragonBreath(World world, BlockPos pos, DefaultedList slots, CallbackInfo info, @Local LocalRef ingredient) { + if (!ingredient.get().itematic$isOf(ItemKeys.DRAGON_BREATH)) { + return; + } + + ItemStack remainder = world.itematic$createStack(ItemKeys.GLASS_BOTTLE); + if (ingredient.get().isEmpty()) { + ingredient.set(remainder); + } else { + ItemScatterer.spawn(world, pos.getX(), pos.getY(), pos.getZ(), remainder); + } } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/component/type/FoodComponentExtender.java b/src/main/java/net/errorcraft/itematic/mixin/component/type/FoodComponentExtender.java index a0515fdf..ae90bb9a 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/component/type/FoodComponentExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/component/type/FoodComponentExtender.java @@ -1,13 +1,45 @@ package net.errorcraft.itematic.mixin.component.type; +import com.mojang.datafixers.kinds.App; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.component.type.FoodComponent; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; +import net.minecraft.util.dynamic.Codecs; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +@Mixin(FoodComponent.class) public class FoodComponentExtender { + @ModifyArg( + method = "", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/serialization/codecs/RecordCodecBuilder;create(Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;", + remap = false + ) + ) + private static Function, ? extends App, FoodComponent>> removeUnusedFields(Function, ? extends App, FoodComponent>> builder) { + return instance -> instance.group( + Codecs.NONNEGATIVE_INT.fieldOf("nutrition").forGetter(FoodComponent::nutrition), + Codec.FLOAT.fieldOf("saturation").forGetter(FoodComponent::saturation), + Codec.BOOL.optionalFieldOf("can_always_eat", false).forGetter(FoodComponent::canAlwaysEat) + ).apply(instance, (FoodComponentExtender::create)); + } + + @Unique + private static FoodComponent create(int nutrition, float saturation, boolean alwaysEdible) { + return new FoodComponent(nutrition, saturation, alwaysEdible, 1.0f, Optional.empty(), List.of()); + } + @Mixin(FoodComponent.Builder.class) public static class BuilderExtender { @Redirect( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java index 51597db8..23ff85d8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java @@ -13,7 +13,6 @@ import net.errorcraft.itematic.item.ItemStackConsumer; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.ConsumableItemComponent; -import net.errorcraft.itematic.item.component.components.LifeSavingItemComponent; import net.errorcraft.itematic.item.event.ItemEvents; import net.errorcraft.itematic.world.action.context.ActionContext; import net.errorcraft.itematic.world.action.context.parameter.ActionContextParameter; @@ -24,7 +23,6 @@ import net.minecraft.entity.attribute.AttributeContainer; import net.minecraft.entity.attribute.EntityAttribute; import net.minecraft.entity.attribute.EntityAttributes; -import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.item.Equipment; @@ -49,7 +47,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Optional; import java.util.function.Predicate; @Mixin(LivingEntity.class) @@ -237,10 +234,8 @@ private boolean isOfForDragonHeadUseRegistryKeyCheck(ItemStack instance, Item it target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" ) ) - private boolean isOfForTotemOfUndyingUseItemComponent(ItemStack instance, Item item, @Share("lifeSavingItemComponent") LocalRef lifeSavingItemComponent) { - Optional optionalComponent = instance.itematic$getComponent(ItemComponentTypes.LIFE_SAVING); - optionalComponent.ifPresent(lifeSavingItemComponent::set); - return optionalComponent.isPresent(); + private boolean isOfForTotemOfUndyingUseEventListenerCheck(ItemStack instance, Item item) { + return instance.itematic$hasEventListener(ItemEvents.BEFORE_DEATH_HOLDER); } @Redirect( @@ -254,16 +249,23 @@ private Stat getOrCreateStatUseRegistryEntry(StatType instance, return instance.itematic$getOrCreateStat(stack.getRegistryEntry()); } - @Inject( + @Redirect( method = "tryUseTotem", at = @At( value = "INVOKE", - target = "Lnet/minecraft/entity/LivingEntity;clearStatusEffects()Z", - shift = At.Shift.AFTER + target = "Lnet/minecraft/entity/LivingEntity;clearStatusEffects()Z" ) ) - private void addEffectsFromLifeSavingItemComponent(DamageSource source, CallbackInfoReturnable info, @Share("lifeSavingItemComponent") LocalRef lifeSavingItemComponent) { - lifeSavingItemComponent.get().apply((LivingEntity)(Object) this); + private boolean addEffectsFromLifeSavingItemComponent(LivingEntity instance, @Local(ordinal = 0) ItemStack stack) { + if (!(this.getWorld() instanceof ServerWorld serverWorld)) { + return false; + } + + ActionContext context = ActionContext.builder(serverWorld) + .entityPosition(ActionContextParameter.THIS, this) + .stack(stack) + .build(); + return stack.itematic$invokeEvent(ItemEvents.BEFORE_DEATH_HOLDER, context); } @Redirect( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/player/ServerPlayerEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/player/ServerPlayerEntityExtender.java index 7aef5d48..b3845789 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/player/ServerPlayerEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/player/ServerPlayerEntityExtender.java @@ -2,6 +2,7 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.authlib.GameProfile; +import net.errorcraft.itematic.access.entity.LivingEntityAccess; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -23,7 +24,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ServerPlayerEntity.class) -public abstract class ServerPlayerEntityExtender extends PlayerEntity { +public abstract class ServerPlayerEntityExtender extends PlayerEntity implements LivingEntityAccess { public ServerPlayerEntityExtender(World world, BlockPos pos, float yaw, GameProfile gameProfile) { super(world, pos, yaw, gameProfile); } @@ -111,4 +112,11 @@ private Stat getOrCreateStatUseRegistryEntry(StatType instance, .getEntry((Item) key); return instance.itematic$getOrCreateStat(itemEntry); } + + @Override + public void itematic$addOrDropStack(ItemStack stack) { + if (!this.getInventory().insertStack(stack)) { + this.dropStack(stack); + } + } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java index 43e116db..302f2176 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java @@ -11,7 +11,10 @@ import net.errorcraft.itematic.item.component.ItemComponentSet; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.*; +import net.errorcraft.itematic.item.component.components.BlockItemComponent; +import net.errorcraft.itematic.item.component.components.DamageableItemComponent; +import net.errorcraft.itematic.item.component.components.EnchantableItemComponent; +import net.errorcraft.itematic.item.component.components.RepairableItemComponent; import net.errorcraft.itematic.item.event.ItemEvent; import net.errorcraft.itematic.item.event.ItemEventMap; import net.errorcraft.itematic.item.event.ItemEvents; @@ -90,7 +93,8 @@ private void checkStackableItemComponent(CallbackInfoReturnable info) { cancellable = true ) public void useUseItemComponent(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable> info) { - ItemStack stack = user.getStackInHand(hand); + ItemStack stack = user.getStackInHand(hand).copy(); + ItemStack stackBeforeUsing = stack.copy(); StackReference stackReference = StackReferenceUtil.of(stack); ActionResult result = ActionResult.PASS; for (ItemComponent component : this.itemComponents) { @@ -108,6 +112,12 @@ public void useUseItemComponent(World world, PlayerEntity user, Hand hand, Callb .build(); this.itematic$invokeEvent(ItemEvents.USE, context); } + + if (stack.getMaxUseTime(user) <= 0 && result.isAccepted()) { + ItemStack remainder = stackReference.get().itematic$applyUseEffects(user, stackBeforeUsing); + stackReference.set(remainder); + } + info.setReturnValue(new TypedActionResult<>(result, stackReference.get())); } @@ -246,10 +256,12 @@ private void onItemEntityDestroyedUseItemComponent(ItemEntity entity, CallbackIn */ @Overwrite public void onStoppedUsing(ItemStack stack, World world, LivingEntity user, int remainingUseTicks) { + ItemStack stackBeforeUsing = stack.copy(); + boolean result = false; int usedTicks = user.itematic$itemUsedTicks(); StackReference stackReference = StackReferenceUtil.of(stack); for (ItemComponent component : this.itemComponents) { - component.stopUsing(stack, world, user, usedTicks, remainingUseTicks, stackReference::set); + result |= component.stopUsing(stack, world, user, usedTicks, remainingUseTicks, stackReference::set); } if (world instanceof ServerWorld serverWorld) { @@ -259,6 +271,10 @@ public void onStoppedUsing(ItemStack stack, World world, LivingEntity user, int this.itematic$invokeEvent(ItemEvents.STOPPED_USING, context); } + if (result) { + stackReference.set(stackReference.get().itematic$applyUseEffects(user, stackBeforeUsing)); + } + tryUpdateItemStack(user, Hand.MAIN_HAND, stack, stackReference); } @@ -268,6 +284,7 @@ public void onStoppedUsing(ItemStack stack, World world, LivingEntity user, int cancellable = true ) public void finishUsingUseItemComponent(ItemStack stack, World world, LivingEntity user, CallbackInfoReturnable info) { + ItemStack stackBeforeUsing = stack.copy(); int usedTicks = user.itematic$itemUsedTicks(); StackReference stackReference = StackReferenceUtil.of(stack); for (ItemComponent component : this.itemComponents) { @@ -283,6 +300,7 @@ public void finishUsingUseItemComponent(ItemStack stack, World world, LivingEnti this.itematic$getComponent(ItemComponentTypes.CONSUMABLE) .ifPresent(c -> c.consume(user, stack, stackReference::set, world, user.getActiveHand())); + stackReference.set(stackReference.get().itematic$applyUseEffects(user, stackBeforeUsing)); info.setReturnValue(stackReference.get()); } @@ -426,15 +444,6 @@ public void checkPointableItemComponent(ItemStack stack, CallbackInfoReturnable< } } - /** - * @author ErrorCraft - * @reason Uses the ItemComponent implementation for data-driven items. - */ - @Overwrite - public boolean hasRecipeRemainder() { - return this.itematic$hasComponent(ItemComponentTypes.RECIPE_REMAINDER); - } - /** * @author ErrorCraft * @reason Uses the ItemComponent implementation for data-driven items. @@ -619,19 +628,15 @@ private void checkTextHolderItemComponent(ItemStack stack, CallbackInfoReturnabl } @Override - public boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { - return this.itematic$getComponent(ItemComponentTypes.FOOD) - .map(c -> c.mayStartUsing(user)) - .orElse(true); + public boolean itematic$hasEventListener(ItemEvent event) { + return this.events.hasListener(event); } @Override - public ItemStack getRecipeRemainder(ItemStack stack) { - // Use the ItemComponent implementation for data-driven items, so we don't get a NullPointerException - return this.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) - .orElse(ItemStack.EMPTY); + public boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { + return this.itematic$getComponent(ItemComponentTypes.FOOD) + .map(c -> c.mayStartUsing(user, stack)) + .orElse(true); } @Override @@ -644,10 +649,12 @@ private static void tryUpdateItemStack(LivingEntity target, Hand hand, ItemStack if (target == null) { return; } + ItemStack newStack = stackReference.get(); if (stack == newStack) { return; } + target.setStackInHand(hand, newStack); } @@ -661,10 +668,12 @@ private ComponentMap initializeComponents() { component.addComponents(componentsBuilder); component.addAttributeModifiers(attributeModifiersBuilder, this.itemComponents); } + AttributeModifiersComponent attributeModifiers = attributeModifiersBuilder.build(); if (!attributeModifiers.modifiers().isEmpty()) { componentsBuilder.add(DataComponentTypes.ATTRIBUTE_MODIFIERS, attributeModifiers); } + return COMPONENT_INTERNER.intern(componentsBuilder.build()); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java b/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java index 0f596ef0..72a72f9d 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java @@ -1,5 +1,6 @@ package net.errorcraft.itematic.mixin.item; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.sugar.Local; @@ -8,6 +9,8 @@ import net.errorcraft.itematic.access.item.ItemStackAccess; import net.errorcraft.itematic.component.ItematicDataComponentTypes; import net.errorcraft.itematic.component.type.ImmuneToDamageComponent; +import net.errorcraft.itematic.component.type.UseCooldownDataComponent; +import net.errorcraft.itematic.component.type.UseRemainderDataComponent; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.ItemUtil; import net.errorcraft.itematic.item.ItematicItemTags; @@ -157,9 +160,7 @@ private void registryEntryConstructorSetFields(RegistryEntry entry, int co at = @At("TAIL") ) private void componentChangesConstructorSetFields(RegistryEntry item, int count, ComponentChanges changes, CallbackInfo info) { - this.entry = item; - this.components = ComponentMapImpl.create(item.value().getComponents(), changes); - item.value().postProcessComponents((ItemStack)(Object) this); + this.setFields(item, changes); } @Redirect( @@ -287,6 +288,17 @@ public RegistryEntry getRegistryEntry() { return this.entry; } + @ModifyExpressionValue( + method = "getItem", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;isEmpty()Z" + ) + ) + private boolean isEmptyCheckUnboundRegistryEntry(boolean original) { + return original || !this.entry.hasKeyAndValue(); + } + @Redirect( method = "getItem", at = @At( @@ -652,6 +664,17 @@ public String toString() { return this.count + " " + this.itematic$key().getValue().toString(); } + @Inject( + method = "hashCode", + at = @At("HEAD"), + cancellable = true + ) + private static void checkEmptyStack(ItemStack stack, CallbackInfoReturnable info) { + if (stack != null && (stack.isEmpty() || !stack.getRegistryEntry().hasKeyAndValue())) { + info.setReturnValue(0); + } + } + @Override public boolean canBeEnchantedWith(RegistryEntry enchantment, EnchantingContext context) { // Use the original implementation again @@ -724,6 +747,32 @@ public boolean canBeEnchantedWith(RegistryEntry enchantment, Enchan this.context = null; } + @Override + @SuppressWarnings("DataFlowIssue") + public ItemStack itematic$applyUseEffects(LivingEntity user, ItemStack stackBeforeUsing) { + if (!stackBeforeUsing.itematic$hasComponent(ItemComponentTypes.USEABLE)) { + return (ItemStack)(Object) this; + } + + UseRemainderDataComponent useRemainder = stackBeforeUsing.get(ItematicDataComponentTypes.USE_REMAINDER); + ItemStack trueRemainder = (ItemStack)(Object) this; + if (useRemainder != null) { + trueRemainder = useRemainder.convert( + (ItemStack)(Object) this, + stackBeforeUsing.getCount(), + user.isInCreativeMode(), + user::itematic$addOrDropStack + ); + } + + UseCooldownDataComponent useCooldown = stackBeforeUsing.get(ItematicDataComponentTypes.USE_COOLDOWN); + if (useCooldown != null) { + useCooldown.set(stackBeforeUsing, user); + } + + return trueRemainder; + } + @Override public > boolean itematic$hasComponent(ItemComponentType type) { return this.entry != null && this.entry.value().itematic$hasComponent(type); @@ -754,6 +803,15 @@ public boolean canBeEnchantedWith(RegistryEntry enchantment, Enchan return result; } + @Override + public boolean itematic$hasEventListener(ItemEvent event) { + if (this.entry == null) { + return false; + } + + return this.entry.value().itematic$hasEventListener(event); + } + @Override public boolean itematic$canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { if (this.entry == null) { @@ -805,6 +863,17 @@ private void setFields(RegistryEntry entry) { } } + @Unique + private void setFields(RegistryEntry entry, ComponentChanges changes) { + this.entry = entry; + if (entry.hasKeyAndValue()) { + this.components = ComponentMapImpl.create(entry.value().getComponents(), changes); + entry.value().postProcessComponents((ItemStack)(Object) this); + } else { + this.components = new ComponentMapImpl(ComponentMap.EMPTY); + } + } + @Unique private void onItemBroken(Item item, Entity entity, ActionContext context) { if (entity instanceof LivingEntity livingEntity) { diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/BannerDuplicateRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/BannerDuplicateRecipeExtender.java index 41da2a34..c587626e 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/BannerDuplicateRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/BannerDuplicateRecipeExtender.java @@ -5,10 +5,8 @@ import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.BannerPatternHolderItemComponent; -import net.errorcraft.itematic.item.component.components.RecipeRemainderItemComponent; import net.minecraft.item.BannerItem; import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.recipe.BannerDuplicateRecipe; import net.minecraft.util.DyeColor; @@ -52,18 +50,4 @@ private Item castToBannerItemUseNull(Item instance) { private DyeColor getColorUseItemComponent(BannerItem instance, @Share("dyeColor") LocalRef dyeColor) { return dyeColor.get(); } - - @Redirect( - method = "getRemainder(Lnet/minecraft/recipe/input/CraftingRecipeInput;)Lnet/minecraft/util/collection/DefaultedList;", - at = @At( - value = "NEW", - target = "(Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/item/ItemStack;" - ) - ) - private ItemStack newItemStackForRemainderUseItemComponent(ItemConvertible item, @Local ItemStack stack) { - return stack.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) - .orElse(ItemStack.EMPTY); - } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java index b13b5393..98076f01 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java @@ -3,9 +3,7 @@ import com.llamalad7.mixinextras.sugar.Local; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.RecipeRemainderItemComponent; import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.item.WrittenBookItem; import net.minecraft.recipe.BookCloningRecipe; @@ -52,20 +50,6 @@ private boolean isOfForWritableBookUseRegistryKeyCheck(ItemStack instance, Item return instance.itematic$isOf(ItemKeys.WRITABLE_BOOK); } - @Redirect( - method = "getRemainder(Lnet/minecraft/recipe/input/CraftingRecipeInput;)Lnet/minecraft/util/collection/DefaultedList;", - at = @At( - value = "NEW", - target = "(Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/item/ItemStack;" - ) - ) - private ItemStack newItemStackForRemainderUseItemComponent(ItemConvertible item, @Local ItemStack stack) { - return stack.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) - .orElse(ItemStack.EMPTY); - } - @ModifyConstant( method = "getRemainder(Lnet/minecraft/recipe/input/CraftingRecipeInput;)Lnet/minecraft/util/collection/DefaultedList;", constant = @Constant( @@ -73,6 +57,6 @@ private ItemStack newItemStackForRemainderUseItemComponent(ItemConvertible item, ) ) private boolean instanceOfWrittenBookItemUseItemComponentCheck(Object reference, Class clazz, @Local ItemStack inputStack) { - return inputStack.itematic$hasComponent(ItemComponentTypes.RECIPE_REMAINDER); + return inputStack.itematic$hasComponent(ItemComponentTypes.TEXT_HOLDER); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/IngredientExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/IngredientExtender.java index 871ba4a8..be8ec3fb 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/IngredientExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/IngredientExtender.java @@ -1,5 +1,8 @@ package net.errorcraft.itematic.mixin.recipe; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.access.recipe.IngredientAccess; import net.errorcraft.itematic.access.recipe.IngredientEntryAccess; import net.minecraft.item.Item; @@ -11,23 +14,28 @@ import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.tag.TagKey; import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; import java.util.function.Function; import java.util.stream.Stream; @Mixin(Ingredient.class) public class IngredientExtender implements IngredientAccess { + @Shadow + @Final + @Mutable + public static Codec ALLOW_EMPTY_CODEC; + + @Shadow + @Final + @Mutable + public static Codec DISALLOW_EMPTY_CODEC; + @Shadow @Final private Ingredient.Entry[] entries; @@ -36,6 +44,15 @@ public class IngredientExtender implements IngredientAccess { @Nullable private ItemStack[] matchingStacks; + @Unique + private Optional remainder = Optional.empty(); + + static { + // Modify the codec fields in a static initializer block due to Fabric API using a cancellable @Inject for their own additions, which makes @ModifyReturnValue not work + ALLOW_EMPTY_CODEC = addRemainder(ALLOW_EMPTY_CODEC); + DISALLOW_EMPTY_CODEC = addRemainder(DISALLOW_EMPTY_CODEC); + } + @Redirect( method = "", at = @At( @@ -90,6 +107,41 @@ private void testUseDirectEntries(ItemStack itemStack, CallbackInfoReturnable itematic$remainder() { + return this.remainder; + } + + @Override + public void itematic$setRemainder(Optional remainder) { + this.remainder = remainder; + } + + @Unique + private static Codec addRemainder(Codec original) { + Codec fullCodec = RecordCodecBuilder.create(instance -> instance.group( + original.fieldOf("items").forGetter(Function.identity()), + ItemStack.CODEC.optionalFieldOf("remainder").forGetter(Ingredient::itematic$remainder) + ).apply(instance, IngredientExtender::setFields)); + return Codec.either(original, fullCodec) + .xmap( + either -> either.map(Function.identity(), Function.identity()), + ingredient -> { + if (ingredient.itematic$remainder().isEmpty()) { + return Either.left(ingredient); + } + + return Either.right(ingredient); + } + ); + } + + @Unique + private static Ingredient setFields(Ingredient ingredient, Optional remainder) { + ingredient.itematic$setRemainder(remainder); + return ingredient; + } + @Mixin(Ingredient.Entry.class) public interface EntryExtender extends IngredientEntryAccess {} diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/RawShapedRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/RawShapedRecipeExtender.java new file mode 100644 index 00000000..7d8ca7ce --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/RawShapedRecipeExtender.java @@ -0,0 +1,51 @@ +package net.errorcraft.itematic.mixin.recipe; + +import net.errorcraft.itematic.access.recipe.RawShapedRecipeAccess; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RawShapedRecipe; +import net.minecraft.recipe.input.CraftingRecipeInput; +import net.minecraft.util.collection.DefaultedList; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(RawShapedRecipe.class) +public abstract class RawShapedRecipeExtender implements RawShapedRecipeAccess { + @Shadow + @Final + private int width; + + @Shadow + @Final + private int height; + + @Shadow + @Final + private boolean symmetrical; + + @Shadow + @Final + private DefaultedList ingredients; + + @Shadow + protected abstract boolean matches(CraftingRecipeInput input, boolean mirrored); + + @Override + public DefaultedList itematic$remainder(CraftingRecipeInput input) { + boolean actuallyMirrored = !this.symmetrical && this.matches(input, true); + DefaultedList remainders = DefaultedList.ofSize(input.getSize(), ItemStack.EMPTY); + for(int y = 0; y < this.height; y++) { + for(int x = 0; x < this.width; x++) { + int index = actuallyMirrored ? + this.width - x - 1 + y * this.width : + x + y * this.width; + this.ingredients.get(index) + .itematic$remainder() + .ifPresent(remainder -> remainders.set(index, remainder.copy())); + } + } + + return remainders; + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/RecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/RecipeExtender.java index ecc45404..262eca52 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/RecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/RecipeExtender.java @@ -1,30 +1,9 @@ package net.errorcraft.itematic.mixin.recipe; -import com.llamalad7.mixinextras.sugar.Local; import net.errorcraft.itematic.access.recipe.RecipeAccess; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.RecipeRemainderItemComponent; -import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; import net.minecraft.recipe.Recipe; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(Recipe.class) public interface RecipeExtender extends RecipeAccess { - @Redirect( - method = "getRemainder", - at = @At( - value = "NEW", - target = "(Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/item/ItemStack;" - ) - ) - private ItemStack newItemStackForRemainderUseItemComponent(ItemConvertible itemConvertible, @Local Item item) { - return item.itematic$getComponent(ItemComponentTypes.RECIPE_REMAINDER) - .map(RecipeRemainderItemComponent::item) - .map(ItemStack::new) - .orElse(ItemStack.EMPTY); - } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapedRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapedRecipeExtender.java new file mode 100644 index 00000000..ee1749a2 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapedRecipeExtender.java @@ -0,0 +1,24 @@ +package net.errorcraft.itematic.mixin.recipe; + +import net.errorcraft.itematic.access.recipe.RawShapedRecipeAccess; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.CraftingRecipe; +import net.minecraft.recipe.RawShapedRecipe; +import net.minecraft.recipe.ShapedRecipe; +import net.minecraft.recipe.input.CraftingRecipeInput; +import net.minecraft.util.collection.DefaultedList; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ShapedRecipe.class) +public abstract class ShapedRecipeExtender implements CraftingRecipe { + @Shadow + @Final + RawShapedRecipe raw; + + @Override + public DefaultedList getRemainder(CraftingRecipeInput input) { + return ((RawShapedRecipeAccess)(Object) this.raw).itematic$remainder(input); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapelessRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapelessRecipeExtender.java new file mode 100644 index 00000000..5c205db8 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/ShapelessRecipeExtender.java @@ -0,0 +1,47 @@ +package net.errorcraft.itematic.mixin.recipe; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.CraftingRecipe; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.ShapelessRecipe; +import net.minecraft.recipe.input.CraftingRecipeInput; +import net.minecraft.util.collection.DefaultedList; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ShapelessRecipe.class) +public abstract class ShapelessRecipeExtender implements CraftingRecipe { + @Shadow + @Final + DefaultedList ingredients; + + @Override + public DefaultedList getRemainder(CraftingRecipeInput input) { + IntSet foundInputs = new IntOpenHashSet(); + DefaultedList remainders = DefaultedList.ofSize(input.getSize(), ItemStack.EMPTY); + for (Ingredient ingredient : this.ingredients) { + if (ingredient.itematic$remainder().isEmpty()) { + continue; + } + + for (int i = 0; i < input.getSize(); i++) { + if (foundInputs.contains(i)) { + continue; + } + + if (!ingredient.test(input.getStackInSlot(i))) { + continue; + } + + remainders.set(i, ingredient.itematic$remainder().get().copy()); + foundInputs.add(i); + break; + } + } + + return remainders; + } +} diff --git a/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateExtraFields.java b/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateExtraFields.java index f68b28e4..a54d4a1e 100644 --- a/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateExtraFields.java +++ b/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateExtraFields.java @@ -6,7 +6,7 @@ import net.errorcraft.itematic.network.codec.PacketCodecUtil; import net.errorcraft.itematic.registry.ItematicRegistries; import net.errorcraft.itematic.registry.ItematicRegistryKeys; -import net.errorcraft.itematic.serialization.ItematicCodecs; +import net.errorcraft.itematic.serialization.SetCodec; import net.minecraft.component.ComponentType; import net.minecraft.item.ItemStack; import net.minecraft.network.RegistryByteBuf; @@ -20,8 +20,8 @@ public record ItemPredicateExtraFields(Optional>> behavior, Optional>> dataComponents) { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - ItematicCodecs.setCodec(ItematicRegistries.ITEM_COMPONENT_TYPE.getCodec()).optionalFieldOf("behavior").forGetter(ItemPredicateExtraFields::behavior), - ItematicCodecs.setCodec(Registries.DATA_COMPONENT_TYPE.getCodec()).optionalFieldOf("data_components").forGetter(ItemPredicateExtraFields::dataComponents) + SetCodec.forRegistry(ItematicRegistries.ITEM_COMPONENT_TYPE).optionalFieldOf("behavior").forGetter(ItemPredicateExtraFields::behavior), + SetCodec.forRegistry(Registries.DATA_COMPONENT_TYPE).optionalFieldOf("data_components").forGetter(ItemPredicateExtraFields::dataComponents) ).apply(instance, ItemPredicateExtraFields::new)); public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( PacketCodecs.registryValue(ItematicRegistryKeys.ITEM_COMPONENT_TYPE).collect(PacketCodecUtil::set).collect(PacketCodecs::optional), ItemPredicateExtraFields::behavior, diff --git a/src/main/java/net/errorcraft/itematic/serialization/ItematicCodecs.java b/src/main/java/net/errorcraft/itematic/serialization/ItematicCodecs.java index 63af13ae..c8edb56a 100644 --- a/src/main/java/net/errorcraft/itematic/serialization/ItematicCodecs.java +++ b/src/main/java/net/errorcraft/itematic/serialization/ItematicCodecs.java @@ -1,20 +1,12 @@ package net.errorcraft.itematic.serialization; -import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; -import com.mojang.serialization.DynamicOps; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.mixin.util.dynamic.CodecsAccessor; import net.minecraft.util.dynamic.Codecs; import org.apache.commons.lang3.math.Fraction; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - public class ItematicCodecs { public static final Codec NON_NEGATIVE_FLOAT = Codec.FLOAT.validate(value -> { if (value >= 0 && value <= Float.MAX_VALUE) { @@ -48,10 +40,6 @@ public static Codec index(int size) { }); } - public static Codec> setCodec(Codec codec) { - return new SetCodec<>(codec); - } - public static Codec positiveFloat(float maxInclusive) { if (maxInclusive <= 0.0f) { throw new IllegalArgumentException("maxInclusive must be positive, got " + maxInclusive + " instead"); @@ -70,36 +58,4 @@ public static Codec positiveFraction(int maxInclusive) { return DataResult.success(fraction); }); } - - private static class SetCodec implements Codec> { - private final Codec> listCodec; - - private SetCodec(Codec codec) { - this.listCodec = codec.listOf(); - } - - @Override - public DataResult, T>> decode(DynamicOps ops, T input) { - return this.listCodec.decode(ops, input) - .flatMap(pair -> { - List elements = pair.getFirst(); - Set set = new HashSet<>(); - Set duplicates = new HashSet<>(); - for (E element : elements) { - if (!set.add(element)) { - duplicates.add(element); - } - } - if (!duplicates.isEmpty()) { - return DataResult.error(() -> "Set contained duplicate entries: " + duplicates.stream().map(E::toString).collect(Collectors.joining(", "))); - } - return DataResult.success(Pair.of(set, pair.getSecond())); - }); - } - - @Override - public DataResult encode(Set input, DynamicOps ops, T prefix) { - return this.listCodec.encode(new ArrayList<>(input), ops, prefix); - } - } } diff --git a/src/main/java/net/errorcraft/itematic/serialization/SetCodec.java b/src/main/java/net/errorcraft/itematic/serialization/SetCodec.java new file mode 100644 index 00000000..00fa4c1f --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/serialization/SetCodec.java @@ -0,0 +1,58 @@ +package net.errorcraft.itematic.serialization; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import net.minecraft.registry.Registry; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class SetCodec implements Codec> { + private final Codec> listCodec; + private final Comparator comparator; + + private SetCodec(Codec codec, Comparator comparator) { + this.listCodec = codec.listOf(); + this.comparator = comparator; + } + + @SuppressWarnings("DataFlowIssue") + public static Codec> forRegistry(Registry registry) { + return new SetCodec<>(registry.getCodec(), Comparator.comparing(registry::getId)); + } + + public static > Codec> forEnum(Codec codec) { + return new SetCodec<>(codec, Enum::compareTo); + } + + @Override + public DataResult, T>> decode(DynamicOps ops, T input) { + return this.listCodec.decode(ops, input) + .flatMap(pair -> { + List elements = pair.getFirst(); + Set set = new HashSet<>(); + Set duplicates = new HashSet<>(); + for (E element : elements) { + if (!set.add(element)) { + duplicates.add(element); + } + } + + if (!duplicates.isEmpty()) { + return DataResult.error(() -> "Set contained duplicate entries: " + duplicates.stream().map(E::toString).collect(Collectors.joining(", "))); + } + + return DataResult.success(Pair.of(set, pair.getSecond())); + }); + } + + @Override + public DataResult encode(Set input, DynamicOps ops, T prefix) { + return this.listCodec.encode(input.stream().sorted(this.comparator).toList(), ops, prefix); + } +} diff --git a/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java b/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java index e2a3a08a..ebca8365 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java @@ -49,6 +49,7 @@ public class ActionTypeKeys { public static final RegistryKey> USE_BUCKET = of("use_bucket"); public static final RegistryKey> REMOVE_STATUS_EFFECTS = of("remove_status_effects"); public static final RegistryKey> INCREMENT_STAT = of("increment_stat"); + public static final RegistryKey> ADD_STATUS_EFFECTS = of("add_status_effects"); private ActionTypeKeys() {} diff --git a/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java b/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java index d7f5bf64..8dfc4db3 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java @@ -50,6 +50,7 @@ public class ActionTypes { public static final ActionType USE_BUCKET = register(ActionTypeKeys.USE_BUCKET, new ActionType<>(UseBucketAction.CODEC)); public static final ActionType REMOVE_STATUS_EFFECTS = register(ActionTypeKeys.REMOVE_STATUS_EFFECTS, new ActionType<>(RemoveStatusEffectsAction.CODEC)); public static final ActionType INCREMENT_STAT = register(ActionTypeKeys.INCREMENT_STAT, new ActionType<>(IncrementStatAction.CODEC)); + public static final ActionType ADD_STATUS_EFFECTS = register(ActionTypeKeys.ADD_STATUS_EFFECTS, new ActionType<>(AddStatusEffectsAction.CODEC)); private ActionTypes() {} diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/AddStatusEffectsAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/AddStatusEffectsAction.java new file mode 100644 index 00000000..0f75a8dd --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/world/action/actions/AddStatusEffectsAction.java @@ -0,0 +1,45 @@ +package net.errorcraft.itematic.world.action.actions; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.world.action.Action; +import net.errorcraft.itematic.world.action.ActionType; +import net.errorcraft.itematic.world.action.ActionTypes; +import net.errorcraft.itematic.world.action.context.ActionContext; +import net.errorcraft.itematic.world.action.context.parameter.ActionContextParameter; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; + +import java.util.List; + +public record AddStatusEffectsAction(List effects, ActionContextParameter entity) implements Action { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + StatusEffectInstance.CODEC.listOf().fieldOf("effects").forGetter(AddStatusEffectsAction::effects), + ActionContextParameter.CODEC.fieldOf("entity").forGetter(AddStatusEffectsAction::entity) + ).apply(instance, AddStatusEffectsAction::new)); + + public static AddStatusEffectsAction of(StatusEffectInstance... effects) { + return new AddStatusEffectsAction(List.of(effects), ActionContextParameter.THIS); + } + + @Override + public ActionType type() { + return ActionTypes.ADD_STATUS_EFFECTS; + } + + @Override + public boolean execute(ActionContext context) { + return context.livingEntity(this.entity) + .map(this::addStatusEffects) + .orElse(false); + } + + private boolean addStatusEffects(LivingEntity target) { + boolean addedStatusEffects = false; + for (StatusEffectInstance effect : this.effects) { + addedStatusEffects |= target.addStatusEffect(effect); + } + + return addedStatusEffects; + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 7fd35eac..36407203 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -81,9 +81,6 @@ "net/minecraft/class_1845\u0024class_9665": [ "net/errorcraft/itematic/access/recipe/BrewingRecipeRegistryBuilderAccess" ], - "net/minecraft/class_1856": [ - "net/errorcraft/itematic/access/recipe/IngredientAccess" - ], "net/minecraft/class_1856\u0024class_1859": [ "net/errorcraft/itematic/access/recipe/IngredientEntryAccess" ], diff --git a/src/main/resources/itematic.classtweaker b/src/main/resources/itematic.classtweaker index 98b60cb3..fe2e686e 100644 --- a/src/main/resources/itematic.classtweaker +++ b/src/main/resources/itematic.classtweaker @@ -10,3 +10,4 @@ accessible class net/minecraft/client/gui/screen/world/CustomizeFlatLevelS inject-interface net/minecraft/util/DyeColor net/errorcraft/itematic/access/util/DyeColorAccess inject-interface net/minecraft/item/tooltip/BundleTooltipData net/errorcraft/itematic/access/item/tooltip/BundleTooltipDataAccess +inject-interface net/minecraft/recipe/Ingredient net/errorcraft/itematic/access/recipe/IngredientAccess diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 609acb75..ecdf3bb1 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -88,6 +88,7 @@ "component.type.BundleContentsComponentExtender$BuilderExtender", "component.type.ChargedProjectilesComponentExtender", "component.type.DyedColorComponentExtender", + "component.type.FoodComponentExtender", "component.type.FoodComponentExtender$BuilderExtender", "component.type.ToolComponentExtender", "component.type.ToolComponentExtender$RuleExtender", @@ -329,9 +330,12 @@ "recipe.InputSlotFillerExtender", "recipe.MapCloningRecipeExtender", "recipe.MapExtendingRecipeExtender", + "recipe.RawShapedRecipeExtender", "recipe.RecipeExtender", "recipe.RecipeMatcherExtender", "recipe.RepairItemRecipeExtender", + "recipe.ShapedRecipeExtender", + "recipe.ShapelessRecipeExtender", "recipe.ShieldDecorationRecipeExtender", "recipe.SmeltingRecipeExtender", "recipe.SmithingRecipeExtender", From 0d5b353441fcb6f853817db9764eab98c16518b2 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Fri, 13 Feb 2026 17:06:16 +0100 Subject: [PATCH 2/2] Increment version to 0.5.0-preview.1+1.21.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6863d751..2f8e84ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.18.4 # Mod Properties - mod_version = 0.4.1+1.21.1 + mod_version = 0.5.0-preview.1+1.21.1 maven_group = net.errorcraft archives_base_name = itematic