From 05fe61c41bd1b0fb491088c722d1f19f83d2b27f Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Sat, 28 Mar 2026 00:40:50 +0100 Subject: [PATCH 01/12] Port to 25w02a --- gradle.properties | 6 +- ...lientPlayerInteractionManagerExtender.java | 33 ---------- .../resources/itematic.client.mixins.json | 1 - .../data/server/tag/ItemTagProvider.java | 5 +- .../PotionItemComponentTestSuite.java | 9 +-- .../mixin/gametest/TestContextExtender.java | 11 ++++ .../data/minecraft/item/diamond_axe.json | 3 +- .../data/minecraft/item/diamond_hoe.json | 2 +- .../data/minecraft/item/diamond_pickaxe.json | 2 +- .../data/minecraft/item/diamond_shovel.json | 2 +- .../data/minecraft/item/diamond_sword.json | 1 + .../data/minecraft/item/golden_axe.json | 3 +- .../data/minecraft/item/golden_hoe.json | 2 +- .../data/minecraft/item/golden_pickaxe.json | 2 +- .../data/minecraft/item/golden_shovel.json | 2 +- .../data/minecraft/item/golden_sword.json | 1 + .../data/minecraft/item/iron_axe.json | 3 +- .../data/minecraft/item/iron_hoe.json | 2 +- .../data/minecraft/item/iron_pickaxe.json | 2 +- .../data/minecraft/item/iron_shovel.json | 2 +- .../data/minecraft/item/iron_sword.json | 1 + .../data/minecraft/item/leaf_litter.json | 15 +++++ .../generated/data/minecraft/item/mace.json | 2 +- .../data/minecraft/item/netherite_axe.json | 3 +- .../data/minecraft/item/netherite_hoe.json | 2 +- .../minecraft/item/netherite_pickaxe.json | 2 +- .../data/minecraft/item/netherite_shovel.json | 2 +- .../data/minecraft/item/netherite_sword.json | 1 + .../generated/data/minecraft/item/potion.json | 1 - .../data/minecraft/item/stone_axe.json | 3 +- .../data/minecraft/item/stone_hoe.json | 2 +- .../data/minecraft/item/stone_pickaxe.json | 2 +- .../data/minecraft/item/stone_shovel.json | 2 +- .../data/minecraft/item/stone_sword.json | 1 + .../data/minecraft/item/trident.json | 3 +- .../data/minecraft/item/wildflowers.json | 15 +++++ .../data/minecraft/item/wooden_axe.json | 3 +- .../data/minecraft/item/wooden_hoe.json | 2 +- .../data/minecraft/item/wooden_pickaxe.json | 2 +- .../data/minecraft/item/wooden_shovel.json | 2 +- .../data/minecraft/item/wooden_sword.json | 1 + .../functional_blocks.json | 4 +- .../tags/item/item_group/plants.json | 2 + .../item/prevents_mining_in_creative.json | 6 -- .../itematic/access/item/ItemStackAccess.java | 5 -- .../itematic/access/world/WorldAccess.java | 2 +- .../errorcraft/itematic/block/BlockKeys.java | 2 + .../errorcraft/itematic/item/ItemKeys.java | 2 + .../errorcraft/itematic/item/ItemUtil.java | 22 ++++++- .../itematic/item/ItematicItemTags.java | 1 - .../item/component/ItemComponent.java | 3 +- .../item/component/ItemComponentTypes.java | 1 - .../components/DamageableItemComponent.java | 13 ++-- .../components/DebugStickItemComponent.java | 18 ++++-- .../components/PotionHolderItemComponent.java | 12 ++++ .../components/PotionItemComponent.java | 35 ----------- .../components/ToolItemComponent.java | 21 +++++-- .../components/WeaponItemComponent.java | 39 +++++++----- .../itematic/item/placement/FluidPlacer.java | 12 +++- .../mixin/block/CanReplaceBlockExtender.java | 8 ++- .../mixin/block/SegmentedExtender.java | 23 +++++++ .../mixin/block/TntBlockExtender.java | 6 +- .../mixin/entity/EntityTypeExtender.java | 10 +-- .../mixin/item/DebugStickItemAccessor.java | 2 +- .../itematic/mixin/item/ItemExtender.java | 12 ++-- .../mixin/item/ItemStackExtender.java | 51 +++++++-------- .../recipe/BookCloningRecipeExtender.java | 62 ------------------- .../SmithingTransformRecipeExtender.java | 20 +----- .../mixin/recipe/TransmuteRecipeExtender.java | 25 ++------ .../recipe/TransmuteRecipeResultExtender.java | 30 +++++++++ ...erverPlayerInteractionManagerExtender.java | 32 ---------- .../itematic/mixin/world/WorldExtender.java | 7 ++- .../actions/SetEntityNameFromItemAction.java | 2 +- src/main/resources/itematic.mixins.json | 4 +- 74 files changed, 309 insertions(+), 346 deletions(-) delete mode 100644 src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayerInteractionManagerExtender.java create mode 100644 src/main/generated/data/minecraft/item/leaf_litter.json create mode 100644 src/main/generated/data/minecraft/item/wildflowers.json delete mode 100644 src/main/generated/data/minecraft/tags/item/prevents_mining_in_creative.json delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/PotionItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/block/SegmentedExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeResultExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/server/ServerPlayerInteractionManagerExtender.java diff --git a/gradle.properties b/gradle.properties index fee1b16f..83eb7e90 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.21.4 - yarn_mappings=1.21.4+build.8 + minecraft_version=25w02a + yarn_mappings=25w02a+build.12 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.119.4+1.21.4 + fabric_version=0.114.3+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayerInteractionManagerExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayerInteractionManagerExtender.java deleted file mode 100644 index b082d966..00000000 --- a/src/client/java/net/errorcraft/itematic/mixin/client/network/ClientPlayerInteractionManagerExtender.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.errorcraft.itematic.mixin.client.network; - -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ClientPlayerInteractionManager.class) -public class ClientPlayerInteractionManagerExtender { - @Shadow - @Final - private MinecraftClient client; - - @Redirect( - method = "breakBlock", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/Item;canMine(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/player/PlayerEntity;)Z" - ) - ) - @SuppressWarnings("ConstantConditions") - private boolean breakBlockCanMineUseItemStackVersion(Item instance, BlockState state, World world, BlockPos pos, PlayerEntity miner) { - return this.client.player.getMainHandStack().itematic$canMine(state, world, pos, miner); - } -} diff --git a/src/client/resources/itematic.client.mixins.json b/src/client/resources/itematic.client.mixins.json index d07ca01a..29d4d2d6 100644 --- a/src/client/resources/itematic.client.mixins.json +++ b/src/client/resources/itematic.client.mixins.json @@ -40,7 +40,6 @@ "gui.tooltip.TooltipComponentExtender", "network.AbstractClientPlayerEntityExtender", "network.ClientPlayerEntityExtender", - "network.ClientPlayerInteractionManagerExtender", "network.ClientPlayNetworkHandlerExtender", "option.HotbarStorageEntryExtender", "particle.CrackParticleExtender$SlimeballFactoryExtender", diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java index dee2d04c..0e8aa177 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java +++ b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java @@ -948,6 +948,8 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.TORCHFLOWER) .add(ItemKeys.WITHER_ROSE) .add(ItemKeys.PINK_PETALS) + .add(ItemKeys.WILDFLOWERS) + .add(ItemKeys.LEAF_LITTER) .add(ItemKeys.SPORE_BLOSSOM) .add(ItemKeys.BAMBOO) .add(ItemKeys.SUGAR_CANE) @@ -1390,9 +1392,6 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.RED_SHULKER_BOX) .add(ItemKeys.WHITE_SHULKER_BOX) .add(ItemKeys.YELLOW_SHULKER_BOX); - this.getOrCreateTagBuilder(ItematicItemTags.PREVENTS_MINING_IN_CREATIVE) - .forceAddTag(ItemTags.SWORDS) - .add(ItemKeys.TRIDENT); this.getOrCreateTagBuilder(ItematicItemTags.PREVENTS_TAKING_POTTED_ITEM_OUT) .add(ItemKeys.OAK_SAPLING) .add(ItemKeys.SPRUCE_SAPLING) diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java index 6c5790d1..1638eed9 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java @@ -1,9 +1,7 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.component.ItematicDataComponentTypes; 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.fabricmc.fabric.api.gametest.v1.FabricGameTest; import net.minecraft.entity.player.PlayerEntity; @@ -20,12 +18,15 @@ public class PotionItemComponentTestSuite { public void drinkingPotionItemAddsEffects(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.LEAPING); + ItemStack stack = PotionContentsComponentUtil.setPotion( + world.itematic$createStack(ItemKeys.POTION), + Potions.LEAPING + ); player.setStackInHand(Hand.MAIN_HAND, stack); world.spawnEntity(player); stack.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - TestUtil.getDataComponent(stack, ItematicDataComponentTypes.USE_DURATION).ticks(stack, player), + stack.getMaxUseTime(player), () -> Assert.forAll( Potions.LEAPING.value().getEffects(), effectInstance -> context.expectEntityHasEffect(player, effectInstance.getEffectType(), effectInstance.getAmplifier()) diff --git a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java index bd4b8bc2..281bc7b4 100644 --- a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java +++ b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java @@ -2,10 +2,12 @@ import com.llamalad7.mixinextras.injector.ModifyReturnValue; import net.errorcraft.itematic.access.gametest.GameTestStateAccess; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.test.GameTestState; import net.minecraft.test.TestContext; import net.minecraft.text.Text; +import net.minecraft.world.GameMode; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -17,6 +19,15 @@ public class TestContextExtender { @Final private GameTestState test; + @ModifyReturnValue( + method = "createMockPlayer", + at = @At("TAIL") + ) + private PlayerEntity setPlayerAbilities(PlayerEntity original, GameMode gameMode) { + gameMode.setAbilities(original.getAbilities()); + return original; + } + @ModifyReturnValue( method = "createMockCreativeServerPlayerInWorld", at = @At("TAIL") diff --git a/src/main/generated/data/minecraft/item/diamond_axe.json b/src/main/generated/data/minecraft/item/diamond_axe.json index c704e4ac..56cdfdb1 100644 --- a/src/main/generated/data/minecraft/item/diamond_axe.json +++ b/src/main/generated/data/minecraft/item/diamond_axe.json @@ -29,7 +29,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_hoe.json b/src/main/generated/data/minecraft/item/diamond_hoe.json index 2d1cca75..5b2c5723 100644 --- a/src/main/generated/data/minecraft/item/diamond_hoe.json +++ b/src/main/generated/data/minecraft/item/diamond_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 1.0, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_pickaxe.json b/src/main/generated/data/minecraft/item/diamond_pickaxe.json index 0e2a1e0f..f19ee33b 100644 --- a/src/main/generated/data/minecraft/item/diamond_pickaxe.json +++ b/src/main/generated/data/minecraft/item/diamond_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_shovel.json b/src/main/generated/data/minecraft/item/diamond_shovel.json index 6878e057..38de1809 100644 --- a/src/main/generated/data/minecraft/item/diamond_shovel.json +++ b/src/main/generated/data/minecraft/item/diamond_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_sword.json b/src/main/generated/data/minecraft/item/diamond_sword.json index 97eaaf27..25c556fa 100644 --- a/src/main/generated/data/minecraft/item/diamond_sword.json +++ b/src/main/generated/data/minecraft/item/diamond_sword.json @@ -11,6 +11,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item/golden_axe.json b/src/main/generated/data/minecraft/item/golden_axe.json index e1feb855..efdb2f7b 100644 --- a/src/main/generated/data/minecraft/item/golden_axe.json +++ b/src/main/generated/data/minecraft/item/golden_axe.json @@ -29,7 +29,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_hoe.json b/src/main/generated/data/minecraft/item/golden_hoe.json index 7b0a13ee..a8bcf253 100644 --- a/src/main/generated/data/minecraft/item/golden_hoe.json +++ b/src/main/generated/data/minecraft/item/golden_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_pickaxe.json b/src/main/generated/data/minecraft/item/golden_pickaxe.json index f9e06186..dd51e963 100644 --- a/src/main/generated/data/minecraft/item/golden_pickaxe.json +++ b/src/main/generated/data/minecraft/item/golden_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_shovel.json b/src/main/generated/data/minecraft/item/golden_shovel.json index b496c65f..43d55cd5 100644 --- a/src/main/generated/data/minecraft/item/golden_shovel.json +++ b/src/main/generated/data/minecraft/item/golden_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_sword.json b/src/main/generated/data/minecraft/item/golden_sword.json index 5562ad6f..48c096cf 100644 --- a/src/main/generated/data/minecraft/item/golden_sword.json +++ b/src/main/generated/data/minecraft/item/golden_sword.json @@ -11,6 +11,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item/iron_axe.json b/src/main/generated/data/minecraft/item/iron_axe.json index 0b7da415..a7adf296 100644 --- a/src/main/generated/data/minecraft/item/iron_axe.json +++ b/src/main/generated/data/minecraft/item/iron_axe.json @@ -29,7 +29,8 @@ "rules": [] }, "attack_speed": 0.225, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_hoe.json b/src/main/generated/data/minecraft/item/iron_hoe.json index 45981982..f3ab1d68 100644 --- a/src/main/generated/data/minecraft/item/iron_hoe.json +++ b/src/main/generated/data/minecraft/item/iron_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.75, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_pickaxe.json b/src/main/generated/data/minecraft/item/iron_pickaxe.json index 8e29e465..479d5d9f 100644 --- a/src/main/generated/data/minecraft/item/iron_pickaxe.json +++ b/src/main/generated/data/minecraft/item/iron_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_shovel.json b/src/main/generated/data/minecraft/item/iron_shovel.json index e8870512..792ec354 100644 --- a/src/main/generated/data/minecraft/item/iron_shovel.json +++ b/src/main/generated/data/minecraft/item/iron_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_sword.json b/src/main/generated/data/minecraft/item/iron_sword.json index 40c0d960..8b9a089c 100644 --- a/src/main/generated/data/minecraft/item/iron_sword.json +++ b/src/main/generated/data/minecraft/item/iron_sword.json @@ -11,6 +11,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item/leaf_litter.json b/src/main/generated/data/minecraft/item/leaf_litter.json new file mode 100644 index 00000000..fe257ef4 --- /dev/null +++ b/src/main/generated/data/minecraft/item/leaf_litter.json @@ -0,0 +1,15 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:leaf_litter" + }, + "minecraft:fuel": { + "ticks": 100 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:leaf_litter", + "translation_key": "block.minecraft.leaf_litter" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/mace.json b/src/main/generated/data/minecraft/item/mace.json index 8997490a..549af49b 100644 --- a/src/main/generated/data/minecraft/item/mace.json +++ b/src/main/generated/data/minecraft/item/mace.json @@ -16,7 +16,7 @@ }, "minecraft:weapon": { "attack_damage": { - "default_damage": 6.0, + "default_damage": 5.0, "rules": [] }, "attack_speed": 0.15, diff --git a/src/main/generated/data/minecraft/item/netherite_axe.json b/src/main/generated/data/minecraft/item/netherite_axe.json index 61ac2508..08d4b9ba 100644 --- a/src/main/generated/data/minecraft/item/netherite_axe.json +++ b/src/main/generated/data/minecraft/item/netherite_axe.json @@ -32,7 +32,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_hoe.json b/src/main/generated/data/minecraft/item/netherite_hoe.json index 3c53188a..864fb5d7 100644 --- a/src/main/generated/data/minecraft/item/netherite_hoe.json +++ b/src/main/generated/data/minecraft/item/netherite_hoe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 1.0, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_pickaxe.json b/src/main/generated/data/minecraft/item/netherite_pickaxe.json index 648220e6..6f8d2a07 100644 --- a/src/main/generated/data/minecraft/item/netherite_pickaxe.json +++ b/src/main/generated/data/minecraft/item/netherite_pickaxe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_shovel.json b/src/main/generated/data/minecraft/item/netherite_shovel.json index bff386d9..94bd38bc 100644 --- a/src/main/generated/data/minecraft/item/netherite_shovel.json +++ b/src/main/generated/data/minecraft/item/netherite_shovel.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_sword.json b/src/main/generated/data/minecraft/item/netherite_sword.json index 3f59ccda..fac68759 100644 --- a/src/main/generated/data/minecraft/item/netherite_sword.json +++ b/src/main/generated/data/minecraft/item/netherite_sword.json @@ -14,6 +14,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item/potion.json b/src/main/generated/data/minecraft/item/potion.json index f22fd7cb..9bae58e2 100644 --- a/src/main/generated/data/minecraft/item/potion.json +++ b/src/main/generated/data/minecraft/item/potion.json @@ -7,7 +7,6 @@ "minecraft:dispensable": { "behavior": "minecraft:use_item_on_block_or_dispense_item" }, - "minecraft:potion": {}, "minecraft:potion_holder": { "duration_multiplier": 1.0 }, diff --git a/src/main/generated/data/minecraft/item/stone_axe.json b/src/main/generated/data/minecraft/item/stone_axe.json index 9c0ca595..f6d992f7 100644 --- a/src/main/generated/data/minecraft/item/stone_axe.json +++ b/src/main/generated/data/minecraft/item/stone_axe.json @@ -29,7 +29,8 @@ "rules": [] }, "attack_speed": 0.2, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_hoe.json b/src/main/generated/data/minecraft/item/stone_hoe.json index 6a3916bc..af9ba7b7 100644 --- a/src/main/generated/data/minecraft/item/stone_hoe.json +++ b/src/main/generated/data/minecraft/item/stone_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.5, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_pickaxe.json b/src/main/generated/data/minecraft/item/stone_pickaxe.json index 1387786d..a65ac304 100644 --- a/src/main/generated/data/minecraft/item/stone_pickaxe.json +++ b/src/main/generated/data/minecraft/item/stone_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_shovel.json b/src/main/generated/data/minecraft/item/stone_shovel.json index 2120a114..de83a079 100644 --- a/src/main/generated/data/minecraft/item/stone_shovel.json +++ b/src/main/generated/data/minecraft/item/stone_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_sword.json b/src/main/generated/data/minecraft/item/stone_sword.json index 250f6465..51e67bc9 100644 --- a/src/main/generated/data/minecraft/item/stone_sword.json +++ b/src/main/generated/data/minecraft/item/stone_sword.json @@ -11,6 +11,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item/trident.json b/src/main/generated/data/minecraft/item/trident.json index 1e5dfaf7..8a84fd7f 100644 --- a/src/main/generated/data/minecraft/item/trident.json +++ b/src/main/generated/data/minecraft/item/trident.json @@ -19,6 +19,7 @@ "speed": 2.5 }, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [] }, @@ -30,7 +31,7 @@ }, "minecraft:weapon": { "attack_damage": { - "default_damage": 9.0, + "default_damage": 8.0, "rules": [] }, "attack_speed": 0.275 diff --git a/src/main/generated/data/minecraft/item/wildflowers.json b/src/main/generated/data/minecraft/item/wildflowers.json new file mode 100644 index 00000000..643698d2 --- /dev/null +++ b/src/main/generated/data/minecraft/item/wildflowers.json @@ -0,0 +1,15 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:wildflowers" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:wildflowers", + "translation_key": "block.minecraft.wildflowers" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wooden_axe.json b/src/main/generated/data/minecraft/item/wooden_axe.json index 68077771..aa8cc6bf 100644 --- a/src/main/generated/data/minecraft/item/wooden_axe.json +++ b/src/main/generated/data/minecraft/item/wooden_axe.json @@ -32,7 +32,8 @@ "rules": [] }, "attack_speed": 0.2, - "damage_per_hit": 2 + "can_disable_blocking": true, + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_hoe.json b/src/main/generated/data/minecraft/item/wooden_hoe.json index d8d36a08..5356c7cb 100644 --- a/src/main/generated/data/minecraft/item/wooden_hoe.json +++ b/src/main/generated/data/minecraft/item/wooden_hoe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_pickaxe.json b/src/main/generated/data/minecraft/item/wooden_pickaxe.json index 011de7bf..412e19c3 100644 --- a/src/main/generated/data/minecraft/item/wooden_pickaxe.json +++ b/src/main/generated/data/minecraft/item/wooden_pickaxe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_shovel.json b/src/main/generated/data/minecraft/item/wooden_shovel.json index 8f11fc3a..d5caa0d2 100644 --- a/src/main/generated/data/minecraft/item/wooden_shovel.json +++ b/src/main/generated/data/minecraft/item/wooden_shovel.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_sword.json b/src/main/generated/data/minecraft/item/wooden_sword.json index fc9be2e1..0db64b5e 100644 --- a/src/main/generated/data/minecraft/item/wooden_sword.json +++ b/src/main/generated/data/minecraft/item/wooden_sword.json @@ -14,6 +14,7 @@ }, "minecraft:stackable": 1, "minecraft:tool": { + "can_destroy_blocks_in_creative": false, "damage_per_block": 2, "rules": [ { diff --git a/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json b/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json index 140e3e88..a752fb5b 100644 --- a/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json +++ b/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json @@ -126,7 +126,9 @@ } ], "minecraft:hide_additional_tooltip": {}, - "minecraft:item_name": "{\"translate\":\"block.minecraft.ominous_banner\"}", + "minecraft:item_name": { + "translate": "block.minecraft.ominous_banner" + }, "minecraft:rarity": "uncommon" }, "item": "minecraft:white_banner" diff --git a/src/main/generated/data/minecraft/tags/item/item_group/plants.json b/src/main/generated/data/minecraft/tags/item/item_group/plants.json index a13f080e..78ce8d35 100644 --- a/src/main/generated/data/minecraft/tags/item/item_group/plants.json +++ b/src/main/generated/data/minecraft/tags/item/item_group/plants.json @@ -26,6 +26,8 @@ "minecraft:torchflower", "minecraft:wither_rose", "minecraft:pink_petals", + "minecraft:wildflowers", + "minecraft:leaf_litter", "minecraft:spore_blossom", "minecraft:bamboo", "minecraft:sugar_cane", diff --git a/src/main/generated/data/minecraft/tags/item/prevents_mining_in_creative.json b/src/main/generated/data/minecraft/tags/item/prevents_mining_in_creative.json deleted file mode 100644 index 95a6daa0..00000000 --- a/src/main/generated/data/minecraft/tags/item/prevents_mining_in_creative.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "values": [ - "#minecraft:swords", - "minecraft:trident" - ] -} \ No newline at end of file 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 acf767be..19f54e13 100644 --- a/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/item/ItemStackAccess.java @@ -4,7 +4,6 @@ import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.event.ItemEvent; import net.errorcraft.itematic.world.action.context.ActionContext; -import net.minecraft.block.BlockState; import net.minecraft.component.MergedComponentMap; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -12,7 +11,6 @@ import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import java.util.Optional; @@ -51,9 +49,6 @@ public interface ItemStackAccess { default boolean itematic$hasEventListener(ItemEvent event) { return false; } - default boolean itematic$canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { - return false; - } default boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { return false; } diff --git a/src/main/java/net/errorcraft/itematic/access/world/WorldAccess.java b/src/main/java/net/errorcraft/itematic/access/world/WorldAccess.java index aef72918..e5f5d5e5 100644 --- a/src/main/java/net/errorcraft/itematic/access/world/WorldAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/world/WorldAccess.java @@ -7,5 +7,5 @@ import org.jetbrains.annotations.Nullable; public interface WorldAccess { - default void itematic$playSound(@Nullable PlayerEntity except, Vec3d pos, SoundEvent sound, SoundCategory category, float volume, float pitch) {} + default void itematic$playSound(@Nullable PlayerEntity source, Vec3d pos, SoundEvent sound, SoundCategory category, float volume, float pitch) {} } diff --git a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java index 221d8813..665c39c3 100644 --- a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java +++ b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java @@ -1012,6 +1012,8 @@ public class BlockKeys { public static final RegistryKey FLOWERING_AZALEA = of("flowering_azalea"); public static final RegistryKey MOSS_CARPET = of("moss_carpet"); public static final RegistryKey PINK_PETALS = of("pink_petals"); + public static final RegistryKey WILDFLOWERS = of("wildflowers"); + public static final RegistryKey LEAF_LITTER = of("leaf_litter"); public static final RegistryKey MOSS_BLOCK = of("moss_block"); public static final RegistryKey BIG_DRIPLEAF = of("big_dripleaf"); public static final RegistryKey SMALL_DRIPLEAF = of("small_dripleaf"); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java index 8020c448..79faf535 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java @@ -261,6 +261,8 @@ public class ItemKeys { public static final RegistryKey SUGAR_CANE = register("sugar_cane"); public static final RegistryKey KELP = register("kelp"); public static final RegistryKey PINK_PETALS = register("pink_petals"); + public static final RegistryKey WILDFLOWERS = register("wildflowers"); + public static final RegistryKey LEAF_LITTER = register("leaf_litter"); public static final RegistryKey MOSS_CARPET = register("moss_carpet"); public static final RegistryKey MOSS_BLOCK = register("moss_block"); public static final RegistryKey PALE_MOSS_CARPET = register("pale_moss_carpet"); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index d775207e..3e920593 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -199,7 +199,6 @@ private void bootstrapConsumables() { .with(ConsumableItemComponent.builder(ConsumableComponents.DRINK) .remainder(this.items.getOrThrow(ItemKeys.GLASS_BOTTLE)) .build()) - .with(PotionItemComponent.INSTANCE) .with(PotionHolderItemComponent.of(1.0f)) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.USE_ITEM_ON_BLOCK_OR_DISPENSE_ITEM))) .build(), @@ -5473,8 +5472,9 @@ private void bootstrapToolsAndWeapons() { .with(StackableItemComponent.of(1)) .with(DamageableItemComponent.ofPreserved(250)) .with(ToolItemComponent.builder(2) + .preventCreativeDestruction() .build()) - .with(WeaponItemComponent.of(1, TridentItem.ATTACK_DAMAGE + 1, 0.275d)) + .with(WeaponItemComponent.of(1, false, TridentItem.ATTACK_DAMAGE, 0.275d)) .with(ThrowableItemComponent.trident(TridentItem.THROW_SPEED, 0.0f, TridentItem.MIN_DRAW_DURATION)) .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.TRIDENT))) .with(EnchantableItemComponent.of(1)) @@ -5557,7 +5557,7 @@ private void bootstrapToolsAndWeapons() { .with(StackableItemComponent.of(1)) .with(DamageableItemComponent.of(500)) .with(ToolItemComponent.builder(2).build()) - .with(WeaponItemComponent.ofSmashing(1, 6.0d, 0.15d)) + .with(WeaponItemComponent.ofSmashing(1, 5.0d, 0.15d)) .with(EnchantableItemComponent.of(15)) .with(RepairableItemComponent.of(RegistryEntryList.of( this.items.getOrThrow(ItemKeys.BREEZE_ROD) @@ -6699,6 +6699,14 @@ private void bootstrapCompostables() { .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) .build() )); + this.registerable.register(ItemKeys.WILDFLOWERS, create( + ItemDisplay.Builder.forBlock(ItemKeys.WILDFLOWERS).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WILDFLOWERS))) + .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .build() + )); this.registerable.register(ItemKeys.FLOWERING_AZALEA_LEAVES, create( ItemDisplay.Builder.forBlock(ItemKeys.FLOWERING_AZALEA_LEAVES).build(), ItemComponentSet.builder() @@ -9470,6 +9478,14 @@ private void bootstrapFuel() { .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); + this.registerable.register(ItemKeys.LEAF_LITTER, create( + ItemDisplay.Builder.forBlock(ItemKeys.LEAF_LITTER).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LEAF_LITTER))) + .with(FuelItemComponent.of(FuelTimes.PLANT)) + .build() + )); } private void bootstrapProjectiles() { diff --git a/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java b/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java index ae56727b..b663a84c 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java +++ b/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java @@ -149,7 +149,6 @@ public class ItematicItemTags { public static final TagKey BANNED_BUNDLE_ITEMS = of("banned_bundle_items"); public static final TagKey SHULKER_BOXES = of("shulker_boxes"); - public static final TagKey PREVENTS_MINING_IN_CREATIVE = of("prevents_mining_in_creative"); public static final TagKey PREVENTS_TAKING_POTTED_ITEM_OUT = of("prevents_taking_potted_item_out"); public static final TagKey BREWING_INPUTS = of("brewing_inputs"); 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 798ad585..4aa28ebf 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java @@ -43,8 +43,7 @@ default ItemResult useOnEntity(PlayerEntity user, LivingEntity target, Hand hand return ItemResult.PASS; } - default boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, ItemStackExchanger stackExchanger) { - return false; + default void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, ItemStackExchanger stackExchanger) { } default boolean postMine(ItemStack stack, World world, BlockState state, BlockPos pos, LivingEntity miner, ItemStackExchanger stackExchanger) { 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 ad24c21d..ea8ecbc7 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -32,7 +32,6 @@ public class ItemComponentTypes { public static final ItemComponentType FIREWORK = register("firework", new ItemComponentType<>(FireworkItemComponent.CODEC)); public static final ItemComponentType BUCKET = register("bucket", new ItemComponentType<>(BucketItemComponent.CODEC)); public static final ItemComponentType CONSUMABLE = register("consumable", new ItemComponentType<>(ConsumableItemComponent.CODEC)); - public static final ItemComponentType POTION = register("potion", new ItemComponentType<>(PotionItemComponent.CODEC)); public static final ItemComponentType POTION_HOLDER = register("potion_holder", new ItemComponentType<>(PotionHolderItemComponent.CODEC)); public static final ItemComponentType SADDLE = register("saddle", new ItemComponentType<>(SaddleItemComponent.CODEC)); public static final ItemComponentType STEERING = register("steering", new ItemComponentType<>(SteeringItemComponent.CODEC)); 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 55034de6..a2f6cd15 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 @@ -48,11 +48,13 @@ public static ItemComponent[] sword(RegistryEntryLookup blocks, ToolMa StackableItemComponent.of(1), DamageableItemComponent.of(material.durability()), ToolItemComponent.builder(2) + .preventCreativeDestruction() .rule(ToolComponent.Rule.ofAlwaysDropping(RegistryEntryList.of(blocks.getOrThrow(BlockKeys.COBWEB)), 15.0f)) .rule(ToolComponent.Rule.of(blocks.getOrThrow(BlockTags.SWORD_EFFICIENT), 1.5f)) .build(), WeaponItemComponent.of( 1, + false, attackDamage, 0.4d ), @@ -62,19 +64,19 @@ public static ItemComponent[] sword(RegistryEntryLookup blocks, ToolMa } public static ItemComponent[] shovel(RegistryEntryLookup blocks, ToolMaterial material, RegistryEntryList repairItems) { - return tool(blocks, material, 2.5d, 0.25d, BlockTags.SHOVEL_MINEABLE, repairItems); + return tool(blocks, material, false, 2.5d, 0.25d, BlockTags.SHOVEL_MINEABLE, repairItems); } public static ItemComponent[] pickaxe(RegistryEntryLookup blocks, ToolMaterial material, RegistryEntryList repairItems) { - return tool(blocks, material, 2.0d, 0.3d, BlockTags.PICKAXE_MINEABLE, repairItems); + return tool(blocks, material, false, 2.0d, 0.3d, BlockTags.PICKAXE_MINEABLE, repairItems); } public static ItemComponent[] axe(RegistryEntryLookup blocks, ToolMaterial material, double attackDamage, double attackSpeed, RegistryEntryList repairItems) { - return tool(blocks, material, attackDamage, attackSpeed, BlockTags.AXE_MINEABLE, repairItems); + return tool(blocks, material, true, attackDamage, attackSpeed, BlockTags.AXE_MINEABLE, repairItems); } public static ItemComponent[] hoe(RegistryEntryLookup blocks, ToolMaterial material, double attackDamage, double attackSpeed, RegistryEntryList repairItems) { - return tool(blocks, material, attackDamage, attackSpeed, BlockTags.HOE_MINEABLE, repairItems); + return tool(blocks, material, false, attackDamage, attackSpeed, BlockTags.HOE_MINEABLE, repairItems); } @Override @@ -82,7 +84,7 @@ public ItemComponentType type() { return ItemComponentTypes.DAMAGEABLE; } - private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMaterial material, double attackDamage, double attackSpeed, TagKey mineableBlocks, RegistryEntryList repairItems) { + private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMaterial material, boolean canDisableBlocking, double attackDamage, double attackSpeed, TagKey mineableBlocks, RegistryEntryList repairItems) { double realAttackDamage = attackDamage + material.attackDamageBonus(); return new ItemComponent[] { StackableItemComponent.of(1), @@ -90,6 +92,7 @@ private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMa ToolItemComponent.of(blocks, material, mineableBlocks), WeaponItemComponent.of( 2, + canDisableBlocking, realAttackDamage, attackSpeed ), diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/DebugStickItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/DebugStickItemComponent.java index 73ed3067..b96fc462 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/DebugStickItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/DebugStickItemComponent.java @@ -11,20 +11,23 @@ import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.DebugStickStateComponent; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.DebugStickItem; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; -import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; -public record DebugStickItemComponent() implements ItemComponent { +public class DebugStickItemComponent implements ItemComponent { public static final DebugStickItemComponent INSTANCE = new DebugStickItemComponent(); public static final Codec CODEC = Codec.unit(INSTANCE); private static final DebugStickItemAccessor DUMMY = (DebugStickItemAccessor) new DebugStickItem(new Item.Settings()); + private DebugStickItemComponent() {} + @Override public ItemComponentType type() { return ItemComponentTypes.DEBUG_STICK; @@ -41,14 +44,17 @@ public ItemResult useOnBlock(ItemUsageContext context, ItemStackExchanger stackE if (world.isClient()) { return ItemResult.PASS; } + PlayerEntity player = context.getPlayer(); if (player == null) { return ItemResult.PASS; } + BlockPos pos = context.getBlockPos(); - if (!DUMMY.callUse(player, world.getBlockState(pos), world, pos, true, context.getStack())) { + if (!DUMMY.itematic$use(player, world.getBlockState(pos), world, pos, true, context.getStack())) { return ItemResult.PASS; } + return ItemResult.SUCCEED; } @@ -57,9 +63,9 @@ public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.DEBUG_STICK_STATE, DebugStickStateComponent.DEFAULT); } - public void use(PlayerEntity miner, BlockState state, WorldAccess world, BlockPos pos) { - if (!world.isClient()) { - DUMMY.callUse(miner, state, world, pos, false, miner.getStackInHand(Hand.MAIN_HAND)); + public void use(LivingEntity user, BlockState state, WorldAccess world, BlockPos pos, ItemStack stack) { + if (!world.isClient() && user instanceof PlayerEntity playerUser) { + DUMMY.itematic$use(playerUser, state, world, pos, false, stack); } } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java index c9fe7e8e..1656e09e 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java @@ -5,14 +5,17 @@ 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.world.action.context.ItemStackExchanger; import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.PotionContentsComponent; +import net.minecraft.entity.LivingEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipType; import net.minecraft.text.Text; import net.minecraft.util.dynamic.Codecs; +import net.minecraft.world.World; import java.util.List; @@ -31,9 +34,18 @@ public Codec codec() { return CODEC; } + @Override + public void finishUsing(World world, LivingEntity user, ItemStack stack, int usedTicks, ItemStackExchanger stackExchanger) { + PotionContentsComponent potionContents = stack.get(DataComponentTypes.POTION_CONTENTS); + if (potionContents != null) { + potionContents.apply(user, stack.getOrDefault(DataComponentTypes.POTION_DURATION_SCALE, 1.0f)); + } + } + @Override public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT); + builder.add(DataComponentTypes.POTION_DURATION_SCALE, this.durationMultiplier); } @Override diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PotionItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PotionItemComponent.java deleted file mode 100644 index 1cadc8de..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PotionItemComponent.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.errorcraft.itematic.item.component.components; - -import com.mojang.serialization.Codec; -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.world.action.context.ItemStackExchanger; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.PotionContentsComponent; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; - -public record PotionItemComponent() implements ItemComponent { - public static final PotionItemComponent INSTANCE = new PotionItemComponent(); - public static final Codec CODEC = Codec.unit(INSTANCE); - - @Override - public ItemComponentType type() { - return ItemComponentTypes.POTION; - } - - @Override - public Codec codec() { - return CODEC; - } - - @Override - public void finishUsing(World world, LivingEntity user, ItemStack stack, int usedTicks, ItemStackExchanger stackExchanger) { - PotionContentsComponent potionContents = stack.get(DataComponentTypes.POTION_CONTENTS); - if (potionContents != null) { - potionContents.apply(user); - } - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ToolItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ToolItemComponent.java index c4018510..4bfacfe2 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ToolItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ToolItemComponent.java @@ -31,15 +31,15 @@ public record ToolItemComponent(ToolComponent tool) implements ItemComponent CODEC = ToolComponent.CODEC.xmap(ToolItemComponent::new, ToolItemComponent::tool); public static ToolItemComponent of(RegistryEntryLookup blocks, ToolMaterial material, TagKey mineableBlocks) { - ToolComponent tool = new ToolComponent( + return new ToolItemComponent(new ToolComponent( List.of( ToolComponent.Rule.ofNeverDropping(blocks.getOrThrow(material.incorrectBlocksForDrops())), ToolComponent.Rule.ofAlwaysDropping(blocks.getOrThrow(mineableBlocks), material.speed()) ), 1.0f, - 1 - ); - return new ToolItemComponent(tool); + 1, + true + )); } public static Builder builder(int damage) { @@ -95,13 +95,24 @@ private void useTool(ItemStack stack, World world, BlockPos pos, LivingEntity mi public static class Builder { private final int damage; private final List rules = new ArrayList<>(); + private boolean canDestroyBlocksInCreative = true; public Builder(int damage) { this.damage = damage; } public ToolItemComponent build() { - return new ToolItemComponent(new ToolComponent(this.rules, 1.0f, this.damage)); + return new ToolItemComponent(new ToolComponent( + this.rules, + 1.0f, + this.damage, + this.canDestroyBlocksInCreative + )); + } + + public Builder preventCreativeDestruction() { + this.canDestroyBlocksInCreative = false; + return this; } public Builder rule(ToolComponent.Rule rule) { 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 882a0857..116cab77 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 @@ -13,7 +13,9 @@ import net.errorcraft.itematic.world.action.context.ActionContext; import net.errorcraft.itematic.world.action.context.ItemStackExchanger; import net.minecraft.component.ComponentMap; +import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.AttributeModifiersComponent; +import net.minecraft.component.type.WeaponComponent; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.EntityAttributes; @@ -29,30 +31,33 @@ import java.util.List; -public record WeaponItemComponent(int damagePerHit, WeaponAttackDamageDataComponent attackDamage, double attackSpeed, boolean maySmash) implements ItemComponent { +public record WeaponItemComponent(int damagePerAttack, boolean canDisableBlocking, boolean maySmash, WeaponAttackDamageDataComponent attackDamage, double attackSpeed) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codecs.NON_NEGATIVE_INT.optionalFieldOf("damage_per_hit", 1).forGetter(WeaponItemComponent::damagePerHit), + Codecs.NON_NEGATIVE_INT.optionalFieldOf("damage_per_attack", 1).forGetter(WeaponItemComponent::damagePerAttack), + Codec.BOOL.optionalFieldOf("can_disable_blocking", false).forGetter(WeaponItemComponent::canDisableBlocking), + Codec.BOOL.optionalFieldOf("may_smash", false).forGetter(WeaponItemComponent::maySmash), WeaponAttackDamageDataComponent.CODEC.fieldOf("attack_damage").forGetter(WeaponItemComponent::attackDamage), - ItematicCodecs.NON_NEGATIVE_DOUBLE.fieldOf("attack_speed").forGetter(WeaponItemComponent::attackSpeed), - Codec.BOOL.optionalFieldOf("may_smash", false).forGetter(WeaponItemComponent::maySmash) + ItematicCodecs.NON_NEGATIVE_DOUBLE.fieldOf("attack_speed").forGetter(WeaponItemComponent::attackSpeed) ).apply(instance, WeaponItemComponent::new)); private static final MaceItem DUMMY = new MaceItem(new Item.Settings()); - public static WeaponItemComponent of(int damagePerHit, double attackDamage, double attackSpeed) { + public static WeaponItemComponent of(int damagePerHit, boolean canDisableBlocking, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, + canDisableBlocking, + false, new WeaponAttackDamageDataComponent(List.of(), attackDamage), - attackSpeed, - false + attackSpeed ); } public static WeaponItemComponent ofSmashing(int damagePerHit, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, + false, + true, new WeaponAttackDamageDataComponent(List.of(), attackDamage), - attackSpeed, - true + attackSpeed ); } @@ -67,16 +72,15 @@ public Codec codec() { } @Override - public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, ItemStackExchanger stackExchanger) { - if (this.maySmash && !DUMMY.postHit(stack, target, attacker)) { - return false; + public void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, ItemStackExchanger stackExchanger) { + if (this.maySmash) { + DUMMY.postHit(stack, target, attacker); } if (!(attacker.getWorld() instanceof ServerWorld serverWorld)) { - return true; + return; } - ActionContext context = ActionContext.builder(serverWorld) .stackExchanger(stackExchanger) .add(LootContextParameters.THIS_ENTITY, attacker) @@ -87,12 +91,15 @@ public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attack .add(ItematicContextParameters.EQUIPMENT_SLOT, EquipmentSlot.MAINHAND) .build(); stack.itematic$invokeEvent(ItemEvents.USE_WEAPON, context); - stack.itematic$damage(this.damagePerHit, context); - return true; + WeaponComponent weapon = stack.get(DataComponentTypes.WEAPON); + if (weapon != null) { + stack.itematic$damage(weapon.damagePerAttack(), context); + } } @Override public void addComponents(ComponentMap.Builder builder) { + builder.add(DataComponentTypes.WEAPON, new WeaponComponent(this.damagePerAttack, this.canDisableBlocking)); builder.add(ItematicDataComponentTypes.WEAPON_ATTACK_DAMAGE, this.attackDamage); builder.add(ItematicDataComponentTypes.ATTACK_SPEED_MULTIPLIER, this.attackSpeed); } diff --git a/src/main/java/net/errorcraft/itematic/item/placement/FluidPlacer.java b/src/main/java/net/errorcraft/itematic/item/placement/FluidPlacer.java index 0a9390d2..1f8d381b 100644 --- a/src/main/java/net/errorcraft/itematic/item/placement/FluidPlacer.java +++ b/src/main/java/net/errorcraft/itematic/item/placement/FluidPlacer.java @@ -48,7 +48,7 @@ public static FluidPlacer of(ItemStack stack, ItemStackExchanger stackExchanger, @Override public ItemResult place() { BlockPos offset = this.blockPos.offset(this.direction); - if (this.player != null && (!this.world.canPlayerModifyAt(this.player, this.blockPos) || !this.player.canPlaceOn(offset, this.direction, this.stack))) { + if (this.player != null && (!this.world.canEntityModifyAt(this.player, this.blockPos) || !this.player.canPlaceOn(offset, this.direction, this.stack))) { return ItemResult.PASS; } @@ -148,7 +148,15 @@ private boolean tryEvaporate(BlockPos pos) { this.world.playSound(this.player, pos, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5f, 2.6f + (this.world.random.nextFloat() - this.world.random.nextFloat()) * 0.8f); for (int i = 0; i < 8; i++) { - this.world.addParticle(ParticleTypes.LARGE_SMOKE, pos.getX() + Math.random(), pos.getY() + Math.random(), pos.getZ() + Math.random(), 0.0d, 0.0d, 0.0d); + this.world.addParticleClient( + ParticleTypes.LARGE_SMOKE, + pos.getX() + Math.random(), + pos.getY() + Math.random(), + pos.getZ() + Math.random(), + 0.0d, + 0.0d, + 0.0d + ); } return true; diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/CanReplaceBlockExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/CanReplaceBlockExtender.java index dab0c327..b0c7eff2 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/CanReplaceBlockExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/CanReplaceBlockExtender.java @@ -7,7 +7,13 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin({ FlowerbedBlock.class, ScaffoldingBlock.class, SeaPickleBlock.class, SlabBlock.class, SnowBlock.class, TurtleEggBlock.class }) +@Mixin({ + ScaffoldingBlock.class, + SeaPickleBlock.class, + SlabBlock.class, + SnowBlock.class, + TurtleEggBlock.class +}) public class CanReplaceBlockExtender extends Block { public CanReplaceBlockExtender(Settings settings) { super(settings); diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/SegmentedExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/SegmentedExtender.java new file mode 100644 index 00000000..29244989 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/block/SegmentedExtender.java @@ -0,0 +1,23 @@ +package net.errorcraft.itematic.mixin.block; + +import net.errorcraft.itematic.access.block.AbstractBlockAccess; +import net.minecraft.block.Segmented; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Segmented.class) +public interface SegmentedExtender extends AbstractBlockAccess { + @Redirect( + method = "shouldAddSegment", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" + ) + ) + private boolean isOfUseRegistryKeyCheck(ItemStack instance, Item item) { + return instance.itematic$isOf(this.itematic$asItemKey()); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java index a1f3b685..b42c889d 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java @@ -3,8 +3,8 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.block.TntBlock; +import net.minecraft.entity.Entity; import net.minecraft.entity.TntEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.sound.SoundCategory; @@ -51,8 +51,8 @@ private static TntEntity setBlockState(TntEntity original, World world, BlockPos method = "primeTnt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/LivingEntity;)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/World;playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V" + target = "Lnet/minecraft/world/World;playSound(Lnet/minecraft/entity/Entity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V" ) ) - private static void doNotPlaySound(World instance, PlayerEntity source, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch) {} + private static void doNotPlaySound(World instance, Entity source, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch) {} } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/EntityTypeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/EntityTypeExtender.java index 73a9ae75..45f15810 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/EntityTypeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/EntityTypeExtender.java @@ -12,16 +12,12 @@ import net.errorcraft.itematic.entity.initializer.initializers.*; import net.errorcraft.itematic.item.ItemStackUtil; import net.errorcraft.itematic.world.action.context.ActionContext; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.EyeOfEnderEntity; -import net.minecraft.entity.SpawnReason; +import net.minecraft.entity.*; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.entity.decoration.GlowItemFrameEntity; import net.minecraft.entity.decoration.ItemFrameEntity; import net.minecraft.entity.decoration.painting.PaintingEntity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.*; import net.minecraft.entity.vehicle.*; import net.minecraft.item.ItemStack; @@ -43,7 +39,7 @@ @Mixin(EntityType.class) public abstract class EntityTypeExtender implements EntityTypeAccess { @Shadow - public static Consumer copier(Consumer chained, World world, ItemStack stack, @Nullable PlayerEntity player) { + public static Consumer copier(Consumer chained, World world, ItemStack stack, @Nullable LivingEntity spawner) { return null; } @@ -472,7 +468,7 @@ private static Consumer copier(ActionContext context, @Nul callback == null ?entity -> {} : entity -> callback.accept(entity, stack), context.world(), stack, - context.get(LootContextParameters.THIS_ENTITY, PlayerEntity.class) + context.get(LootContextParameters.THIS_ENTITY, LivingEntity.class) ); } diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/DebugStickItemAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/item/DebugStickItemAccessor.java index 09934c6e..5555bf0e 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/DebugStickItemAccessor.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/DebugStickItemAccessor.java @@ -12,5 +12,5 @@ @Mixin(DebugStickItem.class) public interface DebugStickItemAccessor { @Invoker("use") - boolean callUse(PlayerEntity player, BlockState state, WorldAccess world, BlockPos pos, boolean update, ItemStack stack); + boolean itematic$use(PlayerEntity player, BlockState state, WorldAccess world, BlockPos pos, boolean update, ItemStack 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 24dfd3bd..8b52883c 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java @@ -257,11 +257,10 @@ public ActionResult useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity * @reason Uses the ItemComponent implementation for data-driven items. */ @Overwrite - public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) { - boolean result = false; + public void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) { ItemStackExchanger stackExchanger = ItemStackExchanger.forEntity(attacker, stack); for (ItemComponent component : this.itemComponents) { - result |= component.postHit(stack, target, attacker, stackExchanger); + component.postHit(stack, target, attacker, stackExchanger); } if (attacker.getWorld() instanceof ServerWorld serverWorld) { @@ -278,7 +277,6 @@ public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attack } tryUpdateItemStack(attacker, Hand.MAIN_HAND, stack, stackExchanger); - return result; } /** @@ -456,10 +454,10 @@ public void appendTooltip(ItemStack stack, Item.TooltipContext context, List info) { + private void useDebugStickItemComponent(ItemStack stack, BlockState state, World world, BlockPos pos, LivingEntity user, CallbackInfoReturnable info) { this.itematic$getBehavior(ItemComponentTypes.DEBUG_STICK) - .ifPresent(c -> { - c.use(miner, state, world, pos); + .ifPresent(debugStick -> { + debugStick.use(user, state, world, pos, stack); info.setReturnValue(false); }); } 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 cced66df..4c7d137f 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java @@ -9,7 +9,6 @@ import net.errorcraft.itematic.component.ItematicDataComponentTypes; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.ItemUtil; -import net.errorcraft.itematic.item.ItematicItemTags; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; @@ -22,11 +21,8 @@ import net.errorcraft.itematic.world.action.context.ActionContext; import net.fabricmc.fabric.api.item.v1.EnchantingContext; import net.fabricmc.fabric.api.item.v1.FabricItemStack; -import net.minecraft.block.BlockState; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.ComponentHolder; -import net.minecraft.component.ComponentMap; -import net.minecraft.component.MergedComponentMap; +import net.minecraft.component.*; +import net.minecraft.component.type.WeaponComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.Entity; import net.minecraft.entity.EquipmentSlot; @@ -50,7 +46,6 @@ import net.minecraft.stat.StatType; import net.minecraft.text.Text; import net.minecraft.util.*; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; @@ -237,12 +232,23 @@ public void checkEmptyStackActionResult(CallbackInfoReturnable inf at = @At("HEAD"), cancellable = true ) - public void checkEmptyStackBoolean(CallbackInfoReturnable info) { + public void checkEmptyStackBooleanFalse(CallbackInfoReturnable info) { if (this.isEmpty()) { info.setReturnValue(false); } } + @Inject( + method = "canMine", + at = @At("HEAD"), + cancellable = true + ) + public void checkEmptyStackBooleanTrue(CallbackInfoReturnable info) { + if (this.isEmpty()) { + info.setReturnValue(true); + } + } + @Inject( method = { "usageTick", @@ -550,15 +556,15 @@ private void onClickedUseRegistryEntryNullCheck(ItemStack stack, Slot slot, Clic } } - @Inject( - method = "postMine", - at = @At("HEAD"), - cancellable = true + @Redirect( + method = "postDamageEntity", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;" + ) ) - private void postMineUseRegistryEntryNullCheck(World world, BlockState state, BlockPos pos, PlayerEntity miner, CallbackInfo info) { - if (this.isEmpty()) { - info.cancel(); - } + private Object getWeaponDataComponentReturnNull(ItemStack instance, ComponentType type) { + return null; } @ModifyReturnValue( @@ -776,19 +782,6 @@ public boolean canBeEnchantedWith(RegistryEntry enchantment, Enchan return this.entry.value().itematic$hasEventListener(event); } - @Override - public boolean itematic$canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { - if (this.entry == null) { - return true; - } - - if (miner.isCreative() && this.isIn(ItematicItemTags.PREVENTS_MINING_IN_CREATIVE)) { - return false; - } - - return this.entry.value().canMine(state, world, pos, miner); - } - @Override public boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { if (this.entry == null) { diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java deleted file mode 100644 index ef2829c5..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/BookCloningRecipeExtender.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.errorcraft.itematic.mixin.recipe; - -import com.llamalad7.mixinextras.sugar.Local; -import net.errorcraft.itematic.item.ItemKeys; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.WrittenBookItem; -import net.minecraft.recipe.BookCloningRecipe; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.*; - -@Mixin(BookCloningRecipe.class) -public class BookCloningRecipeExtender { - @Redirect( - method = { - "matches(Lnet/minecraft/recipe/input/CraftingRecipeInput;Lnet/minecraft/world/World;)Z", - "craft(Lnet/minecraft/recipe/input/CraftingRecipeInput;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)Lnet/minecraft/item/ItemStack;" - }, - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z", - ordinal = 0 - ) - ) - private boolean isOfForWrittenBookUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.WRITTEN_BOOK); - } - - @Redirect( - method = { - "matches(Lnet/minecraft/recipe/input/CraftingRecipeInput;Lnet/minecraft/world/World;)Z", - "craft(Lnet/minecraft/recipe/input/CraftingRecipeInput;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)Lnet/minecraft/item/ItemStack;" - }, - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z", - ordinal = 0 - ), - slice = @Slice( - from = @At( - value = "FIELD", - target = "Lnet/minecraft/item/Items;WRITABLE_BOOK:Lnet/minecraft/item/Item;", - opcode = Opcodes.GETSTATIC - ) - ) - ) - private boolean isOfForWritableBookUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.WRITABLE_BOOK); - } - - @ModifyConstant( - method = "getRecipeRemainders", - constant = @Constant( - classValue = WrittenBookItem.class - ) - ) - private boolean instanceOfWrittenBookItemUseItemComponentCheck(Object reference, Class clazz, @Local(ordinal = 0) ItemStack inputStack) { - return inputStack.itematic$hasBehavior(ItemComponentTypes.TEXT_HOLDER); - } -} diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java index a5e8138b..e6d19e86 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java @@ -3,10 +3,9 @@ import net.errorcraft.itematic.access.recipe.RecipeAccess; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.SmithingTransformRecipe; +import net.minecraft.recipe.TransmuteRecipeResult; import net.minecraft.recipe.display.RecipeDisplay; import net.minecraft.recipe.display.SlotDisplay; import net.minecraft.recipe.display.SmithingRecipeDisplay; @@ -14,8 +13,6 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import java.util.List; import java.util.Optional; @@ -36,18 +33,7 @@ public class SmithingTransformRecipeExtender implements RecipeAccess { @Shadow @Final - ItemStack result; - - @Redirect( - method = "craft(Lnet/minecraft/recipe/input/SmithingRecipeInput;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)Lnet/minecraft/item/ItemStack;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;copyComponentsToNewStack(Lnet/minecraft/item/ItemConvertible;I)Lnet/minecraft/item/ItemStack;" - ) - ) - private ItemStack copyComponentsToNewStackUseRegistryEntry(ItemStack instance, ItemConvertible item, int count) { - return instance.itematic$copyComponentsToNewStack(this.result.getRegistryEntry(), count); - } + TransmuteRecipeResult result; @Override public List itematic$displays(RegistryEntryLookup items) { @@ -56,7 +42,7 @@ private ItemStack copyComponentsToNewStackUseRegistryEntry(ItemStack instance, I Ingredient.toDisplay(this.template), Ingredient.toDisplay(this.base), Ingredient.toDisplay(this.addition), - new SlotDisplay.StackSlotDisplay(this.result), + this.result.createSlotDisplay(), new SlotDisplay.ItemSlotDisplay(items.getOrThrow(ItemKeys.SMITHING_TABLE)) ) ); diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeExtender.java index b4c19cfe..c3733999 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeExtender.java @@ -3,23 +3,20 @@ import net.errorcraft.itematic.access.recipe.RecipeAccess; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.item.Item; -import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.recipe.CraftingRecipe; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.TransmuteRecipe; +import net.minecraft.recipe.TransmuteRecipeResult; import net.minecraft.recipe.display.RecipeDisplay; import net.minecraft.recipe.display.ShapelessCraftingRecipeDisplay; import net.minecraft.recipe.display.SlotDisplay; import net.minecraft.recipe.input.CraftingRecipeInput; import net.minecraft.registry.RegistryEntryLookup; -import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.collection.DefaultedList; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import java.util.List; @@ -35,21 +32,7 @@ public abstract class TransmuteRecipeExtender implements CraftingRecipe, RecipeA @Shadow @Final - RegistryEntry result; - - @Shadow - public abstract List getDisplays(); - - @Redirect( - method = "craft(Lnet/minecraft/recipe/input/CraftingRecipeInput;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)Lnet/minecraft/item/ItemStack;", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;copyComponentsToNewStack(Lnet/minecraft/item/ItemConvertible;I)Lnet/minecraft/item/ItemStack;" - ) - ) - private ItemStack copyComponentsToNewStackUseRegistryEntry(ItemStack instance, ItemConvertible item, int count) { - return instance.itematic$copyComponentsToNewStack(this.result, count); - } + TransmuteRecipeResult result; @Override public DefaultedList getRecipeRemainders(CraftingRecipeInput input) { @@ -62,7 +45,7 @@ public DefaultedList getRecipeRemainders(CraftingRecipeInput input) { } final int index = i; - if (!foundInput && this.input.test(stack) && !stack.itemMatches(this.result)) { + if (!foundInput && this.input.test(stack) && !stack.itemMatches(this.result.itemEntry())) { foundInput = true; this.input.itematic$remainder() .map(ItemStack::copy) @@ -85,7 +68,7 @@ public DefaultedList getRecipeRemainders(CraftingRecipeInput input) { this.input.toDisplay(), this.material.toDisplay() ), - new SlotDisplay.ItemSlotDisplay(this.result), + this.result.createSlotDisplay(), new SlotDisplay.ItemSlotDisplay(items.getOrThrow(ItemKeys.CRAFTING_TABLE)) ) ); diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeResultExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeResultExtender.java new file mode 100644 index 00000000..68a1caed --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/TransmuteRecipeResultExtender.java @@ -0,0 +1,30 @@ +package net.errorcraft.itematic.mixin.recipe; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemConvertible; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.TransmuteRecipeResult; +import net.minecraft.registry.entry.RegistryEntry; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(TransmuteRecipeResult.class) +public class TransmuteRecipeResultExtender { + @Shadow + @Final + private RegistryEntry itemEntry; + + @Redirect( + method = "apply", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;copyComponentsToNewStack(Lnet/minecraft/item/ItemConvertible;I)Lnet/minecraft/item/ItemStack;" + ) + ) + private ItemStack copyComponentsToNewStackUseRegistryEntry(ItemStack instance, ItemConvertible item, int count) { + return instance.itematic$copyComponentsToNewStack(this.itemEntry, count); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/server/ServerPlayerInteractionManagerExtender.java b/src/main/java/net/errorcraft/itematic/mixin/server/ServerPlayerInteractionManagerExtender.java deleted file mode 100644 index 97a9f034..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/server/ServerPlayerInteractionManagerExtender.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.errorcraft.itematic.mixin.server; - -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.ServerPlayerInteractionManager; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ServerPlayerInteractionManager.class) -public class ServerPlayerInteractionManagerExtender { - @Shadow - @Final - protected ServerPlayerEntity player; - - @Redirect( - method = "tryBreakBlock", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/Item;canMine(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/player/PlayerEntity;)Z" - ) - ) - private boolean tryBreakBlockCanMineUseItemStackVersion(Item instance, BlockState state, World world, BlockPos pos, PlayerEntity miner) { - return this.player.getMainHandStack().itematic$canMine(state, world, pos, miner); - } -} diff --git a/src/main/java/net/errorcraft/itematic/mixin/world/WorldExtender.java b/src/main/java/net/errorcraft/itematic/mixin/world/WorldExtender.java index a42db218..018cb5b8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/world/WorldExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/world/WorldExtender.java @@ -3,6 +3,7 @@ import net.errorcraft.itematic.access.world.WorldAccess; import net.errorcraft.itematic.access.world.WorldViewAccess; import net.errorcraft.itematic.item.ItemAccess; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.registry.DynamicRegistryManager; @@ -25,7 +26,7 @@ @Mixin(World.class) public abstract class WorldExtender implements WorldViewAccess, WorldAccess { @Shadow - public abstract void playSound(@Nullable PlayerEntity except, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch); + public abstract void playSound(@Nullable Entity source, double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch); @Unique private ItemAccess itemAccess; @@ -49,7 +50,7 @@ private void constructorSetItemAccess(MutableWorldProperties properties, Registr } @Override - public void itematic$playSound(@Nullable PlayerEntity except, Vec3d pos, SoundEvent sound, SoundCategory category, float volume, float pitch) { - this.playSound(except, pos.getX(), pos.getY(), pos.getZ(), sound, category, volume, pitch); + public void itematic$playSound(@Nullable PlayerEntity source, Vec3d pos, SoundEvent sound, SoundCategory category, float volume, float pitch) { + this.playSound(source, pos.getX(), pos.getY(), pos.getZ(), sound, category, volume, pitch); } } diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/SetEntityNameFromItemAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/SetEntityNameFromItemAction.java index 91ee5fd3..d48da4bc 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/SetEntityNameFromItemAction.java +++ b/src/main/java/net/errorcraft/itematic/world/action/actions/SetEntityNameFromItemAction.java @@ -50,7 +50,7 @@ public boolean execute(ActionContext context) { } private static boolean trySetName(LivingEntity target, Text name) { - if (!target.getType().isSaveable() || !target.canBeNameTagged()) { + if (!target.getType().isSaveable() || !target.isAlive()) { return false; } diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 71ef2423..76d0ba56 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -50,6 +50,7 @@ "block.PumpkinBlockExtender", "block.RespawnAnchorBlockExtender", "block.ScaffoldingBlockExtender", + "block.SegmentedExtender", "block.ShulkerBoxBlockExtender", "block.StemBlockExtender", "block.SweetBerryBushBlockExtender", @@ -309,7 +310,6 @@ "recipe.ArmorDyeRecipeExtender", "recipe.BannerDuplicateRecipeExtender", "recipe.BlastingRecipeExtender", - "recipe.BookCloningRecipeExtender", "recipe.CampfireCookingRecipeExtender", "recipe.CraftingDecoratedPotRecipeExtender", "recipe.FireworkRocketRecipeExtender", @@ -334,6 +334,7 @@ "recipe.StonecuttingRecipeExtender", "recipe.TippedArrowRecipeExtender", "recipe.TransmuteRecipeExtender", + "recipe.TransmuteRecipeResultExtender", "recipe.book.RecipeBookOptionsExtender", "recipe.display.SlotDisplayExtender$AnyFuelSlotDisplayExtender", "recipe.display.SlotDisplayExtender$ItemSlotDisplayExtender", @@ -370,7 +371,6 @@ "screen.ScreenHandlerTypeAccessor", "screen.ScreenHandlerTypeExtender", "screen.slot.FurnaceFuelSlotExtender", - "server.ServerPlayerInteractionManagerExtender", "server.command.ScoreboardCommandExtender", "server.network.ServerPlayNetworkHandlerExtender", "sound.SoundCategoryExtender", From b22427bad43f5bfb597847457a69acdf5ddb9017 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Sat, 4 Apr 2026 01:03:54 +0200 Subject: [PATCH 02/12] Port to 25w03a --- build.gradle | 2 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 14 +- gradlew.bat | 3 +- .../HorseArmorFeatureRendererExtender.java | 25 - .../resources/itematic.client.mixins.json | 1 - .../errorcraft/itematic/assertion/Assert.java | 101 ++ .../itematic/assertion/BlockStateAssert.java | 87 + .../itematic/assertion/DoublesAssert.java | 30 + .../itematic/assertion/FloatsAssert.java | 43 + .../itematic/assertion/FluidStateAssert.java | 44 + .../itematic/assertion/IntsAssert.java | 30 + .../itematic/assertion/ItemStackAssert.java | 194 +++ .../assertion/LivingEntityAssert.java | 93 ++ .../errorcraft/itematic/gametest/Assert.java | 154 -- .../gametest/block/AnvilBlockTestSuite.java | 57 +- .../gametest/block/BeehiveBlockTestSuite.java | 10 +- .../block/BrewingStandBlockTestSuite.java | 83 +- .../gametest/block/CandleBlockTestSuite.java | 27 +- .../block/ComposterBlockTestSuite.java | 29 +- .../block/DispenserBehaviorTestSuite.java | 1089 +++++++------ .../block/EnchantingTableTestSuite.java | 73 +- .../gametest/block/GrindstoneTestSuite.java | 79 +- .../gametest/block/PickBlockTestSuite.java | 844 ++++++---- .../block/ShulkerBoxBlockTestSuite.java | 10 +- .../block/WaterCauldronBlockTestSuite.java | 24 +- .../gametest/entity/PickEntityTestSuite.java | 580 ++++--- .../passive/ArmadilloEntityTestSuite.java | 23 +- .../passive/AxolotlEntityTestSuite.java | 23 +- .../entity/passive/CamelEntityTestSuite.java | 23 +- .../entity/passive/FrogEntityTestSuite.java | 23 +- .../entity/passive/GoatEntityTestSuite.java | 23 +- .../passive/MooshroomEntityTestSuite.java | 62 +- .../entity/passive/SheepEntityTestSuite.java | 26 +- .../passive/SnifferEntityTestSuite.java | 23 +- .../entity/passive/WolfEntityTestSuite.java | 40 +- .../gametest/item/BeetrootSoupTestSuite.java | 20 +- .../itematic/gametest/item/BowTestSuite.java | 14 +- .../gametest/item/BrushTestSuite.java | 48 +- .../gametest/item/BundleTestSuite.java | 82 +- .../gametest/item/CompassTestSuite.java | 71 +- .../gametest/item/CrossbowTestSuite.java | 42 +- .../gametest/item/FishingRodTestSuite.java | 34 +- .../gametest/item/FlowerPotItemTestSuite.java | 1434 ++++++++++------- .../gametest/item/HoneyBottleTestSuite.java | 18 +- .../itematic/gametest/item/LeadTestSuite.java | 45 +- .../itematic/gametest/item/SignTestSuite.java | 113 +- .../item/TotemOfUndyingTestSuite.java | 25 +- .../BlockItemComponentTestSuite.java | 198 +-- .../BucketItemComponentTestSuite.java | 94 +- .../ConsumableItemComponentTestSuite.java | 26 +- .../EntityItemComponentTestSuite.java | 24 +- .../EquipmentItemComponentTestSuite.java | 62 +- .../component/FoodItemComponentTestSuite.java | 55 +- .../ImmuneToDamageItemComponentTestSuite.java | 74 +- .../ItemHolderItemComponentTestSuite.java | 108 +- .../LifeSavingItemComponentTestSuite.java | 33 +- .../MappableItemComponentTestSuite.java | 32 +- .../PotionItemComponentTestSuite.java | 21 +- .../ShooterItemComponentTestSuite.java | 60 +- .../ThrowableItemComponentTestSuite.java | 121 +- .../UseableOnFluidItemComponentTestSuite.java | 82 +- .../WeaponItemComponentTestSuite.java | 82 +- .../StructureTestListenerExtender.java | 53 - .../mixin/gametest/TestContextExtender.java | 9 +- .../StructureTemplateManagerExtender.java | 45 + .../itematic/{gametest => util}/TestUtil.java | 48 +- .../resources/assets/itematic/lang/en_us.json | 27 + .../item.brush.platform.short_grass.snbt | 40 - .../structure/item.brush.platform.snbt | 38 - .../item.brush.platform.suspicious_sand.snbt | 39 - .../structure/item.brush.platform.nbt | Bin 0 -> 218 bytes .../item.brush.platform.short_grass.nbt | Bin 0 -> 355 bytes .../item.brush.platform.suspicious_sand.nbt | Bin 0 -> 283 bytes .../resources/itematic-gametest.mixins.json | 4 +- .../minecraft/dispense_behavior/saddle.json | 8 - .../data/minecraft/item/diamond_axe.json | 2 +- .../data/minecraft/item/diamond_hoe.json | 2 +- .../data/minecraft/item/diamond_pickaxe.json | 2 +- .../data/minecraft/item/diamond_shovel.json | 2 +- .../data/minecraft/item/golden_axe.json | 2 +- .../data/minecraft/item/golden_hoe.json | 2 +- .../data/minecraft/item/golden_pickaxe.json | 2 +- .../data/minecraft/item/golden_shovel.json | 2 +- .../data/minecraft/item/iron_axe.json | 2 +- .../data/minecraft/item/iron_hoe.json | 2 +- .../data/minecraft/item/iron_pickaxe.json | 2 +- .../data/minecraft/item/iron_shovel.json | 2 +- .../data/minecraft/item/netherite_axe.json | 2 +- .../data/minecraft/item/netherite_hoe.json | 2 +- .../minecraft/item/netherite_pickaxe.json | 2 +- .../data/minecraft/item/netherite_shovel.json | 2 +- .../generated/data/minecraft/item/saddle.json | 10 +- .../data/minecraft/item/stone_axe.json | 2 +- .../data/minecraft/item/stone_hoe.json | 2 +- .../data/minecraft/item/stone_pickaxe.json | 2 +- .../data/minecraft/item/stone_shovel.json | 2 +- .../data/minecraft/item/wooden_axe.json | 2 +- .../data/minecraft/item/wooden_hoe.json | 2 +- .../data/minecraft/item/wooden_pickaxe.json | 2 +- .../data/minecraft/item/wooden_shovel.json | 2 +- .../village/VillagerProfessionAccess.java | 3 +- .../errorcraft/itematic/item/ItemUtil.java | 11 +- .../item/component/ItemComponentTypes.java | 1 - .../components/EntityItemComponent.java | 31 +- .../components/SaddleItemComponent.java | 57 - .../components/WeaponItemComponent.java | 8 +- .../dispense/behavior/DispenseBehaviors.java | 3 - .../PaintingVariantItemGroupEntry.java | 24 +- .../EnchantmentHelperAccessor.java | 16 + .../task/GatherItemsVillagerTaskExtender.java | 20 +- .../entity/mob/CreakingEntityExtender.java | 23 + .../passive/AbstractHorseEntityExtender.java | 25 - .../entity/passive/PigEntityExtender.java | 24 - .../entity/passive/StriderEntityExtender.java | 24 - .../passive/VillagerEntityExtender.java | 2 +- .../WanderingTraderEntityExtender.java | 4 +- .../mixin/item/ItemStackExtender.java | 2 +- .../screen/HorseScreenHandlerExtender.java | 24 - .../mixin/village/VillagerDataExtender.java | 7 +- .../village/VillagerProfessionExtender.java | 34 +- .../itematic/village/trade/Trades.java | 17 +- .../modifiers/ItemFromTypeTradeModifier.java | 10 +- .../itematic/world/action/ActionTypeKeys.java | 1 - .../itematic/world/action/ActionTypes.java | 1 - .../actions/SaddleEntityAtPositionAction.java | 65 - src/main/resources/fabric.mod.json | 6 - src/main/resources/itematic.classtweaker | 2 + src/main/resources/itematic.mixins.json | 4 +- 131 files changed, 4485 insertions(+), 3351 deletions(-) delete mode 100644 src/client/java/net/errorcraft/itematic/mixin/client/render/entity/feature/HorseArmorFeatureRendererExtender.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/Assert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/BlockStateAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/DoublesAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/FloatsAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/FluidStateAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/IntsAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/ItemStackAssert.java create mode 100644 src/gametest/java/net/errorcraft/itematic/assertion/LivingEntityAssert.java delete mode 100644 src/gametest/java/net/errorcraft/itematic/gametest/Assert.java delete mode 100644 src/gametest/java/net/errorcraft/itematic/mixin/gametest/StructureTestListenerExtender.java create mode 100644 src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java rename src/gametest/java/net/errorcraft/itematic/{gametest => util}/TestUtil.java (80%) create mode 100644 src/gametest/resources/assets/itematic/lang/en_us.json delete mode 100644 src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.short_grass.snbt delete mode 100644 src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.snbt delete mode 100644 src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.suspicious_sand.snbt create mode 100644 src/gametest/resources/data/itematic/structure/item.brush.platform.nbt create mode 100644 src/gametest/resources/data/itematic/structure/item.brush.platform.short_grass.nbt create mode 100644 src/gametest/resources/data/itematic/structure/item.brush.platform.suspicious_sand.nbt delete mode 100644 src/main/generated/data/minecraft/dispense_behavior/saddle.json delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/SaddleItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/enchantment/EnchantmentHelperAccessor.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/entity/mob/CreakingEntityExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/screen/HorseScreenHandlerExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/world/action/actions/SaddleEntityAtPositionAction.java diff --git a/build.gradle b/build.gradle index cb72795b..489c2c40 100644 --- a/build.gradle +++ b/build.gradle @@ -107,7 +107,7 @@ loom { gametestClient { inherit client name "GameTest Client" - vmArg "-Dfabric-api.gametest.structures.output-dir=${file("src/gametest/resources/data/itematic/gametest/structure")}" + vmArg "-Ditematic.gametest.structure-output-directory=${file("src/gametest/resources/data")}" runDir "run" source sourceSets.gametest diff --git a/gradle.properties b/gradle.properties index 83eb7e90..c8db22f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w02a - yarn_mappings=25w02a+build.12 + minecraft_version=25w03a + yarn_mappings=25w03a+build.3 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.114.3+1.21.5 + fabric_version=0.115.0+1.21.5 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 40682 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Ðt5p(LLtXn?pxm3OZHd|13r);5)1uCW40m{;j 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 A;{X5v delta 35496 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bad7c246..dbc3ce4a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d..0262dcbd 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a218..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/render/entity/feature/HorseArmorFeatureRendererExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/render/entity/feature/HorseArmorFeatureRendererExtender.java deleted file mode 100644 index 12ddeda3..00000000 --- a/src/client/java/net/errorcraft/itematic/mixin/client/render/entity/feature/HorseArmorFeatureRendererExtender.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.errorcraft.itematic.mixin.client.render.entity.feature; - -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.feature.HorseArmorFeatureRenderer; -import net.minecraft.client.render.entity.state.HorseEntityRenderState; -import net.minecraft.client.util.math.MatrixStack; -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.callback.CallbackInfo; - -@Mixin(HorseArmorFeatureRenderer.class) -public class HorseArmorFeatureRendererExtender { - @Inject( - method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/HorseEntityRenderState;FF)V", - at = @At("HEAD"), - cancellable = true - ) - private void checkPresenceEquipmentBehavior(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, HorseEntityRenderState horseEntityRenderState, float f, float g, CallbackInfo info) { - if (!horseEntityRenderState.armor.itematic$hasBehavior(ItemComponentTypes.EQUIPMENT)) { - info.cancel(); - } - } -} diff --git a/src/client/resources/itematic.client.mixins.json b/src/client/resources/itematic.client.mixins.json index 29d4d2d6..cba0235a 100644 --- a/src/client/resources/itematic.client.mixins.json +++ b/src/client/resources/itematic.client.mixins.json @@ -53,7 +53,6 @@ "render.entity.feature.ArmorFeatureRendererExtender", "render.entity.feature.CapeFeatureRendererExtender", "render.entity.feature.ElytraFeatureRendererExtender", - "render.entity.feature.HorseArmorFeatureRendererExtender", "render.entity.feature.WolfArmorFeatureRendererExtender", "render.entity.state.ItemStackEntityRenderStateExtender", "render.item.HeldItemRendererExtender", diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/Assert.java b/src/gametest/java/net/errorcraft/itematic/assertion/Assert.java new file mode 100644 index 00000000..276312c4 --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/Assert.java @@ -0,0 +1,101 @@ +package net.errorcraft.itematic.assertion; + +import net.errorcraft.itematic.util.TestUtil; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.fluid.FluidState; +import net.minecraft.item.ItemStack; +import net.minecraft.test.TestContext; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class Assert { + private Assert() {} + + public static void isTrue(TestContext helper, boolean condition, Supplier message) { + if (!condition) { + throw helper.createError(Text.literal(message.get())); + } + } + + public static void isFalse(TestContext helper, boolean condition, Supplier message) { + isTrue(helper, !condition, message); + } + + public static T isNotNull(TestContext helper, T object, String name) { + if (object == null) { + throw helper.createError( + "test.error.expected_not_null", + name + ); + } + + return object; + } + + public static void areEqual(TestContext helper, T value, T expected, String type) { + if (Objects.equals(value, expected)) { + return; + } + + throw helper.createError( + "test.error.expected_type", + type, + value, + expected + ); + } + + public static void isInstance(TestContext helper, T value, Class expectedClass, Supplier message, Consumer assertion) { + if (expectedClass.isInstance(value)) { + assertion.accept(expectedClass.cast(value)); + return; + } + + throw helper.createError(Text.literal(message.get())); + } + + public static IntsAssert ints(TestContext helper, int value, String name) { + return new IntsAssert(helper, value, name); + } + + public static FloatsAssert floats(TestContext helper, float value, String name) { + return new FloatsAssert(helper, value, name); + } + + public static DoublesAssert doubles(TestContext helper, double value, String name) { + return new DoublesAssert(helper, value, name); + } + + public static BlockStateAssert blockState(TestContext helper, BlockPos pos) { + BlockState state = helper.getWorld().getBlockState(helper.getAbsolutePos(pos)); + return new BlockStateAssert(helper, state); + } + + public static void blockEntity(TestContext helper, BlockPos pos, BlockEntityType type, Consumer assertion) { + assertion.accept(TestUtil.getBlockEntity(helper, pos, type)); + } + + public static FluidStateAssert fluidState(TestContext helper, BlockPos pos) { + FluidState state = helper.getWorld().getFluidState(helper.getAbsolutePos(pos)); + return new FluidStateAssert(helper, state); + } + + public static LivingEntityAssert livingEntity(TestContext helper, LivingEntity entity) { + return new LivingEntityAssert(helper, entity); + } + + public static ItemStackAssert itemStack(TestContext helper, ItemStack stack) { + return new ItemStackAssert(helper, stack); + } + + public static ItemStackAssert itemStack(TestContext helper, ItemStack stack, String name) { + return new ItemStackAssert(helper, stack, name); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/BlockStateAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/BlockStateAssert.java new file mode 100644 index 00000000..74c763a6 --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/BlockStateAssert.java @@ -0,0 +1,87 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.registry.Registries; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.state.property.IntProperty; +import net.minecraft.state.property.Property; +import net.minecraft.test.TestContext; +import net.minecraft.text.Text; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class BlockStateAssert { + private final TestContext helper; + private final BlockState state; + + BlockStateAssert(TestContext helper, BlockState state) { + this.helper = Objects.requireNonNull(helper); + this.state = Assert.isNotNull(this.helper, state, "block state"); + } + + public BlockStateAssert is(Block block) { + if (this.state.isOf(block)) { + return this; + } + + throw this.helper.createError( + "test.error.expected_type", + "block", + Registries.BLOCK.getId(block), + Registries.BLOCK.getId(this.state.getBlock()) + ); + } + + public BlockStateAssert isNot(Block block) { + if (!this.state.isOf(block)) { + return this; + } + + throw this.helper.createError( + "test.error.did_not_expect_type", + "block", + Registries.BLOCK.getId(block) + ); + } + + public BlockStateAssert is(TagKey tag) { + if (this.state.isIn(tag)) { + return this; + } + + throw this.helper.createError( + "test.error.expected_tag", + "block", + tag.id() + ); + } + + public > BlockStateAssert hasProperty(Property property, T expected) { + if (expected.equals(this.state.get(property))) { + return this; + } + + throw this.helper.createError( + "test.error.expected_type", + property.getName() + " block state property", + expected, + this.state.get(property) + ); + } + + public > BlockStateAssert hasProperty(Property expected, T value, Supplier message) { + if (value.equals(this.state.get(expected))) { + return this; + } + + throw this.helper.createError(Text.literal(message.get())); + } + + public BlockStateAssert hasProperty(IntProperty property, Consumer expectedAssertion) { + expectedAssertion.accept(Assert.ints(this.helper, this.state.get(property), property.getName() + " block state property")); + return this; + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/DoublesAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/DoublesAssert.java new file mode 100644 index 00000000..837945ee --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/DoublesAssert.java @@ -0,0 +1,30 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.test.TestContext; + +import java.util.Objects; + +public class DoublesAssert { + private final TestContext helper; + private final double value; + private final String name; + + DoublesAssert(TestContext helper, double value, String name) { + this.helper = Objects.requireNonNull(helper); + this.value = value; + this.name = Objects.requireNonNull(name); + } + + public DoublesAssert equals(double expected) { + if (this.value == expected) { + return this; + } + + throw this.helper.createError( + "test.error.value_not_equal", + this.name, + expected, + this.value + ); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/FloatsAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/FloatsAssert.java new file mode 100644 index 00000000..1174007b --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/FloatsAssert.java @@ -0,0 +1,43 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.test.TestContext; + +import java.util.Objects; + +public class FloatsAssert { + private final TestContext helper; + private final float value; + private final String name; + + FloatsAssert(TestContext helper, float value, String name) { + this.helper = Objects.requireNonNull(helper); + this.value = value; + this.name = Objects.requireNonNull(name); + } + + public FloatsAssert equals(float expected) { + if (this.value == expected) { + return this; + } + + throw this.helper.createError( + "test.error.value_not_equal", + this.name, + expected, + this.value + ); + } + + public FloatsAssert isGreaterThan(float expected) { + if (this.value > expected) { + return this; + } + + throw this.helper.createError( + "test.error.expected_value_greater_than", + this.name, + expected, + this.value + ); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/FluidStateAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/FluidStateAssert.java new file mode 100644 index 00000000..ad1f2b0f --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/FluidStateAssert.java @@ -0,0 +1,44 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.registry.Registries; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.test.TestContext; + +import java.util.Objects; + +public class FluidStateAssert { + private final TestContext helper; + private final FluidState state; + + FluidStateAssert(TestContext helper, FluidState state) { + this.helper = Objects.requireNonNull(helper); + this.state = Assert.isNotNull(this.helper, state, "fluid state"); + } + + public FluidStateAssert is(Fluid fluid) { + if (this.state.isOf(fluid)) { + return this; + } + + throw this.helper.createError( + "test.error.expected_type", + "fluid", + Registries.FLUID.getId(fluid), + Registries.FLUID.getId(this.state.getFluid()) + ); + } + + public FluidStateAssert is(TagKey tag) { + if (this.state.isIn(tag)) { + return this; + } + + throw this.helper.createError( + "test.error.expected_tag", + "fluid", + tag.id() + ); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/IntsAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/IntsAssert.java new file mode 100644 index 00000000..773ed86d --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/IntsAssert.java @@ -0,0 +1,30 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.test.TestContext; + +import java.util.Objects; + +public class IntsAssert { + private final TestContext helper; + private final int value; + private final String name; + + IntsAssert(TestContext helper, int value, String name) { + this.helper = Objects.requireNonNull(helper); + this.value = value; + this.name = Objects.requireNonNull(name); + } + + public IntsAssert equals(int expected) { + if (this.value == expected) { + return this; + } + + throw this.helper.createError( + "test.error.value_not_equal", + this.name, + expected, + this.value + ); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/ItemStackAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/ItemStackAssert.java new file mode 100644 index 00000000..fc43e792 --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/ItemStackAssert.java @@ -0,0 +1,194 @@ +package net.errorcraft.itematic.assertion; + +import net.errorcraft.itematic.mixin.enchantment.EnchantmentHelperAccessor; +import net.errorcraft.itematic.util.TestUtil; +import net.minecraft.component.ComponentType; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.test.TestContext; +import net.minecraft.util.Identifier; + +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class ItemStackAssert { + private final TestContext helper; + private final ItemStack stack; + private final String name; + + ItemStackAssert(TestContext helper, ItemStack stack) { + this(helper, stack, "item stack"); + } + + ItemStackAssert(TestContext helper, ItemStack stack, String name) { + this.helper = Objects.requireNonNull(helper); + this.stack = Assert.isNotNull(this.helper, stack, name); + this.name = Objects.requireNonNull(name); + } + + public ItemStackAssert is(RegistryKey id) { + if (this.stack.itematic$isOf(id)) { + return this; + } + + throw this.helper.createError( + "test.error.expected_type", + this.name, + id.getValue(), + this.stack.getRegistryEntry().getIdAsString() + ); + } + + public ItemStackAssert isEmpty() { + if (this.stack.isEmpty()) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.expected_empty", + this.name, + this.stack.getRegistryEntry().getIdAsString() + ); + } + + public ItemStackAssert isNotEmpty() { + if (!this.stack.isEmpty()) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.expected_not_empty", + this.name + ); + } + + public ItemStackAssert hasCount(Consumer countAssertion) { + countAssertion.accept(Assert.ints(this.helper, this.stack.getCount(), "item stack count")); + return this; + } + + public ItemStackAssert isDamaged() { + if (this.stack.isDamaged()) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.damaged", + this.name + ); + } + + public ItemStackAssert isNotDamaged() { + if (!this.stack.isDamaged()) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.expected_not_damaged", + this.name + ); + } + + public ItemStackAssert hasComponent(ComponentType type) { + if (this.stack.contains(type)) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.expected_data_component", + this.name, + type + ); + } + + public ItemStackAssert hasComponent(ComponentType type, Consumer assertion) { + assertion.accept(TestUtil.getDataComponent(this.helper, this.stack, type)); + return this; + } + + public ItemStackAssert doesNotHaveComponent(ComponentType type) { + if (!this.stack.contains(type)) { + return this; + } + + throw this.helper.createError( + "test.error.item_stack.did_not_expect_data_component", + this.name, + type + ); + } + + public ItemStackAssert hasPotion(RegistryEntry expected) { + return this.hasComponent(DataComponentTypes.POTION_CONTENTS, potionContents -> { + RegistryEntry potion = potionContents.potion() + .orElseThrow(() -> this.helper.createError( + "test.error.item_stack.expected_potion", + this.name, + expected.getIdAsString() + )); + if (expected != potion) { + throw this.helper.createError( + "test.error.item_stack.expected_other_potion", + this.name, + expected.getIdAsString(), + potion.getIdAsString() + ); + } + }); + } + + public ItemStackAssert hasEnchantments() { + return this.hasComponent(EnchantmentHelperAccessor.getComponentType(this.stack), enchantments -> { + if (enchantments.isEmpty()) { + throw this.helper.createError( + "test.error.item_stack.expected_enchantments", + this.name + ); + } + }); + } + + public ItemStackAssert hasNoEnchantments() { + return this.hasComponent(EnchantmentHelperAccessor.getComponentType(this.stack), enchantments -> { + if (!enchantments.isEmpty()) { + throw this.helper.createError( + "test.error.item_stack.expected_no_enchantments", + this.name + ); + } + }); + } + + @SafeVarargs + public final ItemStackAssert hasEnchantments(RegistryKey... expected) { + return this.hasComponent(EnchantmentHelperAccessor.getComponentType(this.stack), enchantments -> { + Set> remaining = new HashSet<>(List.of(expected)); + for (RegistryEntry enchantment : enchantments.getEnchantments()) { + enchantment.getKey().ifPresent(remaining::remove); + } + + if (remaining.isEmpty()) { + return; + } + + throw this.helper.createError( + "test.error.item_stack.expected_specified_enchantments", + this.name, + remaining.stream() + .map(RegistryKey::getValue) + .sorted() + .map(Identifier::toString) + .collect(Collectors.joining(", ")) + ); + }); + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/assertion/LivingEntityAssert.java b/src/gametest/java/net/errorcraft/itematic/assertion/LivingEntityAssert.java new file mode 100644 index 00000000..efeb3d6b --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/assertion/LivingEntityAssert.java @@ -0,0 +1,93 @@ +package net.errorcraft.itematic.assertion; + +import net.minecraft.component.type.PotionContentsComponent; +import net.minecraft.component.type.SuspiciousStewEffectsComponent; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffect; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.potion.Potion; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.test.TestContext; +import net.minecraft.util.Hand; + +import java.util.List; +import java.util.function.Consumer; + +public class LivingEntityAssert { + private final TestContext helper; + private final LivingEntity entity; + + LivingEntityAssert(TestContext helper, LivingEntity entity) { + this.helper = helper; + this.entity = entity; + } + + public LivingEntityAssert hasHealth(Consumer healthAssertion) { + healthAssertion.accept(Assert.floats(this.helper, this.entity.getHealth(), "entity health")); + return this; + } + + public LivingEntityAssert hasStackInHand(Hand hand, Consumer stackAssertion) { + stackAssertion.accept(Assert.itemStack(this.helper, this.entity.getStackInHand(hand), "item stack in hand")); + return this; + } + + public LivingEntityAssert hasEquippedStack(EquipmentSlot slot, Consumer stackAssertion) { + stackAssertion.accept(Assert.itemStack(this.helper, this.entity.getEquippedStack(slot), "equipped item stack")); + return this; + } + + public LivingEntityAssert hasEffect(RegistryEntry effect) { + if (this.entity.hasStatusEffect(effect)) { + return this; + } + + throw this.helper.createError( + "test.error.entity.expected_effect", + this.entity.getName(), + PotionContentsComponent.getEffectText(effect, 0) + ); + } + + public LivingEntityAssert hasEffect(RegistryEntry effect, int amplifier) { + StatusEffectInstance effectInstance = this.entity.getStatusEffect(effect); + if (effectInstance != null && effectInstance.getAmplifier() == amplifier) { + return this; + } + + throw this.helper.createError( + "test.error.entity.expected_effect", + this.entity.getName(), + PotionContentsComponent.getEffectText(effect, amplifier) + ); + } + + public LivingEntityAssert doesNotHaveEffect(RegistryEntry effect) { + if (!this.entity.hasStatusEffect(effect)) { + return this; + } + + throw this.helper.createError( + "test.error.entity.did_not_expect_effect", + this.entity.getName(), + PotionContentsComponent.getEffectText(effect, 0) + ); + } + + public LivingEntityAssert hasEffects(RegistryEntry potion) { + for (StatusEffectInstance effect : potion.value().getEffects()) { + this.hasEffect(effect.getEffectType(), effect.getAmplifier()); + } + + return this; + } + + public LivingEntityAssert hasEffects(List effects) { + for (SuspiciousStewEffectsComponent.StewEffect effect : effects) { + this.hasEffect(effect.effect(), effect.createStatusEffectInstance().getAmplifier()); + } + + return this; + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/Assert.java b/src/gametest/java/net/errorcraft/itematic/gametest/Assert.java deleted file mode 100644 index 13d1b661..00000000 --- a/src/gametest/java/net/errorcraft/itematic/gametest/Assert.java +++ /dev/null @@ -1,154 +0,0 @@ -package net.errorcraft.itematic.gametest; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.component.ComponentType; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ItemEnchantmentsComponent; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.effect.StatusEffect; -import net.minecraft.fluid.Fluid; -import net.minecraft.fluid.FluidState; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.potion.Potion; -import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.tag.TagKey; -import net.minecraft.test.GameTestException; -import net.minecraft.test.TestContext; -import net.minecraft.util.math.BlockPos; - -import java.util.function.Consumer; - -public class Assert { - private Assert() {} - - public static void fluidIsOf(TestContext context, Fluid fluid, BlockPos pos) { - FluidState state = context.getWorld().getFluidState(context.getAbsolutePos(pos)); - if (!state.isOf(fluid)) { - throw new GameTestException("Expected fluid to be of " + Registries.FLUID.getId(fluid) + ", got " + Registries.FLUID.getId(state.getFluid()) + " instead"); - } - } - - public static void fluidIsIn(TestContext context, TagKey fluid, BlockPos pos) { - FluidState state = context.getWorld().getFluidState(context.getAbsolutePos(pos)); - if (!state.isIn(fluid)) { - throw new GameTestException("Expected fluid to be in " + fluid.id() + ", got " + Registries.FLUID.getId(state.getFluid()) + " instead"); - } - } - - public static void itemStackIsOf(ItemStack value, RegistryKey expected) { - if (value == null) { - throw new GameTestException("Expected item stack to be of " + expected + ", but the item stack was null"); - } - - if (!value.itematic$isOf(expected)) { - throw new GameTestException("Expected item stack to be of " + expected + ", got " + value.itematic$key() + " instead"); - } - } - - public static void itemStackIsEmpty(ItemStack value) { - if (!value.isEmpty()) { - throw new GameTestException("Expected item stack to be empty, got " + value + " instead"); - } - } - - public static void itemStackIsNotEmpty(ItemStack value) { - if (value.isEmpty()) { - throw new GameTestException("Expected item stack not to be empty"); - } - } - - public static void itemStackHasDataComponent(ItemStack value, ComponentType type) { - if (value.get(type) == null) { - throw new GameTestException("Expected item stack to contain the " + type + " component"); - } - } - - public static void itemStackDoesNotHaveDataComponent(ItemStack value, ComponentType type) { - if (value.get(type) != null) { - throw new GameTestException("Expected item stack to not contain the " + type + " component"); - } - } - - public static void itemStackHasDataComponent(ItemStack value, ComponentType type, Consumer assertion) { - itemStackHasDataComponent(value, type); - assertion.accept(TestUtil.getDataComponent(value, type)); - } - - public static void itemStackHasPotion(ItemStack value, RegistryEntry expected) { - itemStackHasDataComponent(value, DataComponentTypes.POTION_CONTENTS, component -> { - RegistryEntry potion = component.potion() - .orElseThrow(() -> new GameTestException("Expected item stack to have potion " + expected.getKey().orElseThrow())); - if (expected != potion) { - throw new GameTestException("Expected item stack to have potion " + expected.getKey().orElseThrow() + ", got " + potion.getKey().orElseThrow() + " instead"); - } - }); - } - - public static void dataComponentHasEnchantment(ItemEnchantmentsComponent enchantments, RegistryKey expected) { - for (RegistryEntry enchantment : enchantments.getEnchantments()) { - if (enchantment.matchesKey(expected)) { - return; - } - } - - throw new GameTestException("Expected data component to have enchantment " + expected); - } - - public static void entityDoesNotHaveStatusEffect(LivingEntity entity, RegistryEntry effect) { - if (entity.getStatusEffect(effect) != null) { - throw new GameTestException("Expected entity to not have the " + effect.getKey().orElseThrow() + " status effect"); - } - } - - public static void blockEntityExists(TestContext context, BlockPos pos, BlockEntityType type, Consumer assertion) { - assertion.accept(TestUtil.getBlockEntity(context, pos, type)); - } - - public static void areIntsEqual(int value, int expected) { - areIntsEqual(value, expected, (v, e) -> "Expected value to be " + e + ", got " + v + " instead"); - } - - public static void areIntsEqual(int value, int expected, ComparingIntStringSupplier messageSupplier) { - if (value != expected) { - throw new GameTestException(messageSupplier.get(value, expected)); - } - } - - public static void areFloatsEqual(float value, float expected, ComparingFloatStringSupplier messageSupplier) { - if (value != expected) { - throw new GameTestException(messageSupplier.get(value, expected)); - } - } - - public static void areDoublesEqual(double value, double expected, ComparingDoubleStringSupplier messageSupplier) { - if (value != expected) { - throw new GameTestException(messageSupplier.get(value, expected)); - } - } - - public static void forAll(Iterable elements, Consumer elementAssertion) { - for (T element : elements) { - elementAssertion.accept(element); - } - } - - @FunctionalInterface - public interface ComparingIntStringSupplier { - String get(int value, int expected); - } - - @FunctionalInterface - public interface ComparingFloatStringSupplier { - String get(float value, float expected); - } - - @FunctionalInterface - public interface ComparingDoubleStringSupplier { - String get(double value, double expected); - } -} diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/AnvilBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/AnvilBlockTestSuite.java index bb864064..f7471b8b 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/AnvilBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/AnvilBlockTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.minecraft.component.DataComponentTypes; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.screen.AnvilScreenHandler; 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; @@ -18,7 +16,7 @@ public class AnvilBlockTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.anvil") + @GameTest(structure = "itematic:block.anvil") public void combiningEnchantedItemsWithSameIdInAnvilCombinesEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -27,17 +25,12 @@ public void combiningEnchantedItemsWithSameIdInAnvilCombinesEnchantments(TestCon .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); anvilMenu.getSlot(1) .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.EFFICIENCY)); - context.addInstantFinalTask(() -> { - ItemStack result = anvilMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.IRON_PICKAXE); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - Assert.dataComponentHasEnchantment(enchantments, Enchantments.UNBREAKING); - Assert.dataComponentHasEnchantment(enchantments, Enchantments.EFFICIENCY); - }); - }); + context.addFinalTask(() -> Assert.itemStack(context, anvilMenu.getSlot(2).getStack()) + .is(ItemKeys.IRON_PICKAXE) + .hasEnchantments(Enchantments.UNBREAKING, Enchantments.EFFICIENCY)); } - @GameTest(templateName = "itematic:block.anvil") + @GameTest(structure = "itematic:block.anvil") public void combiningEnchantedItemsWithDifferentIdsInAnvilRejectsCombination(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -46,10 +39,11 @@ public void combiningEnchantedItemsWithDifferentIdsInAnvilRejectsCombination(Tes .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); anvilMenu.getSlot(1) .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.DIAMOND_PICKAXE, Enchantments.EFFICIENCY)); - context.addInstantFinalTask(() -> Assert.itemStackIsEmpty(anvilMenu.getSlot(2).getStack())); + context.addFinalTask(() -> Assert.itemStack(context, anvilMenu.getSlot(2).getStack()) + .isEmpty()); } - @GameTest(templateName = "itematic:block.anvil") + @GameTest(structure = "itematic:block.anvil") public void combiningItemWithEnchantedBookInAnvilAddsEnchantment(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -58,17 +52,12 @@ public void combiningItemWithEnchantedBookInAnvilAddsEnchantment(TestContext con .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); anvilMenu.getSlot(1) .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.EFFICIENCY)); - context.addInstantFinalTask(() -> { - ItemStack result = anvilMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.IRON_PICKAXE); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - Assert.dataComponentHasEnchantment(enchantments, Enchantments.UNBREAKING); - Assert.dataComponentHasEnchantment(enchantments, Enchantments.EFFICIENCY); - }); - }); + context.addFinalTask(() -> Assert.itemStack(context, anvilMenu.getSlot(2).getStack()) + .is(ItemKeys.IRON_PICKAXE) + .hasEnchantments(Enchantments.UNBREAKING, Enchantments.EFFICIENCY)); } - @GameTest(templateName = "itematic:block.anvil") + @GameTest(structure = "itematic:block.anvil") public void combiningItemWithEnchantedBookWithIncompatibleEnchantmentInAnvilRejectsCombination(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -77,10 +66,11 @@ public void combiningItemWithEnchantedBookWithIncompatibleEnchantmentInAnvilReje .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); anvilMenu.getSlot(1) .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.SHARPNESS)); - context.addInstantFinalTask(() -> Assert.itemStackIsEmpty(anvilMenu.getSlot(2).getStack())); + context.addFinalTask(() -> Assert.itemStack(context, anvilMenu.getSlot(2).getStack()) + .isEmpty()); } - @GameTest(templateName = "itematic:block.anvil") + @GameTest(structure = "itematic:block.anvil") public void combiningEnchantedBooksInAnvilCombinesEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -89,13 +79,8 @@ public void combiningEnchantedBooksInAnvilCombinesEnchantments(TestContext conte .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.UNBREAKING)); anvilMenu.getSlot(1) .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.EFFICIENCY)); - context.addInstantFinalTask(() -> { - ItemStack result = anvilMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.ENCHANTED_BOOK); - Assert.itemStackHasDataComponent(result, DataComponentTypes.STORED_ENCHANTMENTS, storedEnchantments -> { - Assert.dataComponentHasEnchantment(storedEnchantments, Enchantments.UNBREAKING); - Assert.dataComponentHasEnchantment(storedEnchantments, Enchantments.EFFICIENCY); - }); - }); + context.addFinalTask(() -> Assert.itemStack(context, anvilMenu.getSlot(2).getStack()) + .is(ItemKeys.ENCHANTED_BOOK) + .hasEnchantments(Enchantments.UNBREAKING, Enchantments.EFFICIENCY)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/BeehiveBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/BeehiveBlockTestSuite.java index d8617395..fb01b616 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/BeehiveBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/BeehiveBlockTestSuite.java @@ -1,10 +1,10 @@ package net.errorcraft.itematic.gametest.block; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; 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; @@ -12,23 +12,23 @@ public class BeehiveBlockTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.beehive") + @GameTest(structure = "itematic:block.beehive") public void breakingBeehiveWithHoneyInCreativeModeDropsBeehive(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.CREATIVE); ServerWorld world = context.getWorld(); BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); state.getBlock().onBreak(world, absolutePos, state, player); - context.addInstantFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.BEEHIVE).value())); + context.addFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.BEEHIVE).value())); } - @GameTest(templateName = "itematic:block.bee_nest") + @GameTest(structure = "itematic:block.bee_nest") public void breakingBeeNestWithHoneyInCreativeModeDropsBeeNest(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.CREATIVE); ServerWorld world = context.getWorld(); BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); state.getBlock().onBreak(world, absolutePos, state, player); - context.addInstantFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.BEE_NEST).value())); + context.addFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.BEE_NEST).value())); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java index fef85671..25d52957 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/BrewingStandBlockTestSuite.java @@ -1,16 +1,16 @@ package net.errorcraft.itematic.gametest.block; +import net.errorcraft.itematic.assertion.Assert; 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.errorcraft.itematic.screen.BrewingStandMenuDelegate; import net.errorcraft.itematic.screen.ItematicScreenHandlerTypes; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.potion.Potions; 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; @@ -18,7 +18,7 @@ public class BrewingStandBlockTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingWaterBottleWithNetherWartTurnsItIntoAwkwardPotion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -32,16 +32,14 @@ public void brewingWaterBottleWithNetherWartTurnsItIntoAwkwardPotion(TestContext context.createTimedTaskRunner() .expectMinDurationAndRun( 401, - () -> { - ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(resultPotion, Potions.AWKWARD); - } + () -> Assert.itemStack(context, brewingStandMenu.getSlot(0).getStack()) + .is(ItemKeys.POTION) + .hasPotion(Potions.AWKWARD) ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingAwkwardPotionWithSugarTurnsItIntoSwiftnessPotion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -57,14 +55,15 @@ public void brewingAwkwardPotionWithSugarTurnsItIntoSwiftnessPotion(TestContext 401, () -> { ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + Assert.itemStack(context, resultPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.SWIFTNESS); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingSwiftnessPotionWithGlowstoneDustTurnsItIntoStrongSwiftnessPotion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -80,14 +79,15 @@ public void brewingSwiftnessPotionWithGlowstoneDustTurnsItIntoStrongSwiftnessPot 401, () -> { ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(resultPotion, Potions.STRONG_SWIFTNESS); + Assert.itemStack(context, resultPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.STRONG_SWIFTNESS); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingSwiftnessPotionWithRedstoneTurnsItIntoLongSwiftnessPotion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -103,14 +103,15 @@ public void brewingSwiftnessPotionWithRedstoneTurnsItIntoLongSwiftnessPotion(Tes 401, () -> { ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(resultPotion, Potions.LONG_SWIFTNESS); + Assert.itemStack(context, resultPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.LONG_SWIFTNESS); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingSwiftnessPotionWithGunpowderTurnsItIntoSwiftnessSplashPotion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -126,14 +127,15 @@ public void brewingSwiftnessPotionWithGunpowderTurnsItIntoSwiftnessSplashPotion( 401, () -> { ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.SPLASH_POTION); - Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + Assert.itemStack(context, resultPotion) + .is(ItemKeys.SPLASH_POTION) + .hasPotion(Potions.SWIFTNESS); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingSwiftnessSplashPotionWithDragonBreathTurnsItIntoSwiftnessLingeringPotionAndLeavesGlassBottle(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -149,16 +151,18 @@ public void brewingSwiftnessSplashPotionWithDragonBreathTurnsItIntoSwiftnessLing 401, () -> { ItemStack resultPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(resultPotion, ItemKeys.LINGERING_POTION); - Assert.itemStackHasPotion(resultPotion, Potions.SWIFTNESS); + Assert.itemStack(context, resultPotion) + .is(ItemKeys.LINGERING_POTION) + .hasPotion(Potions.SWIFTNESS); ItemStack ingredientRemainder = brewingStandMenu.getSlot(3).getStack(); - Assert.itemStackIsOf(ingredientRemainder, ItemKeys.GLASS_BOTTLE); + Assert.itemStack(context, ingredientRemainder) + .is(ItemKeys.GLASS_BOTTLE); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingDifferentPotionsOnlyModifiesCorrectTargets(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -178,20 +182,23 @@ public void brewingDifferentPotionsOnlyModifiesCorrectTargets(TestContext contex 401, () -> { ItemStack firstPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(firstPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(firstPotion, Potions.SWIFTNESS); + Assert.itemStack(context, firstPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.SWIFTNESS); ItemStack secondPotion = brewingStandMenu.getSlot(1).getStack(); - Assert.itemStackIsOf(secondPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(secondPotion, Potions.AWKWARD); + Assert.itemStack(context, secondPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.AWKWARD); ItemStack thirdPotion = brewingStandMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(thirdPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(thirdPotion, Potions.LEAPING); + Assert.itemStack(context, thirdPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.LEAPING); } ) .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.brewing_stand", tickLimit = 401) + @GameTest(structure = "itematic:block.brewing_stand", maxTicks = 401) public void brewingPotionsTargetingMultipleValidRecipesModifiesBoth(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -209,11 +216,13 @@ public void brewingPotionsTargetingMultipleValidRecipesModifiesBoth(TestContext 401, () -> { ItemStack firstPotion = brewingStandMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(firstPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(firstPotion, Potions.MUNDANE); + Assert.itemStack(context, firstPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.MUNDANE); ItemStack secondPotion = brewingStandMenu.getSlot(1).getStack(); - Assert.itemStackIsOf(secondPotion, ItemKeys.POTION); - Assert.itemStackHasPotion(secondPotion, Potions.SWIFTNESS); + Assert.itemStack(context, secondPotion) + .is(ItemKeys.POTION) + .hasPotion(Potions.SWIFTNESS); } ) .completeIfSuccessful(); diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/CandleBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/CandleBlockTestSuite.java index 5c0bdecc..313fc9bb 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/CandleBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/CandleBlockTestSuite.java @@ -1,13 +1,14 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; import net.minecraft.block.CandleBlock; 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.util.math.BlockPos; @@ -18,25 +19,27 @@ public class CandleBlockTestSuite { private static final BlockPos GROUND_POSITION = new BlockPos(1, 0, 1); private static final BlockPos PLACED_BLOCK_POSITION = GROUND_POSITION.add(0, 1, 0); - @GameTest(templateName = "itematic:block.white_candle") + @GameTest(structure = "itematic:block.white_candle") public void usingSameCandleOnCandleBlockIncreasesCandles(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_CANDLE); + ItemStack whiteCandle = world.itematic$createStack(ItemKeys.WHITE_CANDLE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, whiteCandle); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlockProperty(PLACED_BLOCK_POSITION, CandleBlock.CANDLES, 2)); + TestUtil.useStackOnBlockInside(context, player, whiteCandle, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .hasProperty(CandleBlock.CANDLES, 2)); } - @GameTest(templateName = "itematic:block.white_candle") + @GameTest(structure = "itematic:block.white_candle") public void usingDifferentlyColoredCandleOnCandleBlockDoesNotReplaceBlock(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_CANDLE); + ItemStack whiteCandle = world.itematic$createStack(ItemKeys.WHITE_CANDLE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, whiteCandle); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.WHITE_CANDLE, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, whiteCandle, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.WHITE_CANDLE)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/ComposterBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/ComposterBlockTestSuite.java index 6f288616..ae8cf541 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/ComposterBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/ComposterBlockTestSuite.java @@ -1,11 +1,10 @@ package net.errorcraft.itematic.gametest.block; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Properties; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -14,29 +13,21 @@ public class ComposterBlockTestSuite { private static final BlockPos COMPOSTER_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.composter.empty") + @GameTest(structure = "itematic:block.composter.empty") public void usingCompostableItemOnComposterIncreasesLevel(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PUMPKIN_PIE); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.PUMPKIN_PIE)); context.useBlock(COMPOSTER_POSITION, player); - context.addInstantFinalTask(() -> context.checkBlockState( - COMPOSTER_POSITION, - state -> state.get(Properties.LEVEL_8) == 1, - () -> "Composter block level did not increase to 1" - )); + context.addFinalTask(() -> Assert.blockState(context, COMPOSTER_POSITION) + .hasProperty(Properties.LEVEL_8, 1, () -> "Expected Composter level to increase to 1")); } - @GameTest(templateName = "itematic:block.composter.full") + @GameTest(structure = "itematic:block.composter.full") public void usingBlockOnFullComposterEmptiesComposterAndSpawnsBoneMeal(TestContext context) { context.useBlock(COMPOSTER_POSITION); - context.addInstantFinalTask(() -> { - context.checkBlockState( - COMPOSTER_POSITION, - state -> state.get(Properties.LEVEL_8) == 0, - () -> "Composter block was not emptied" - ); + context.addFinalTask(() -> { + Assert.blockState(context, COMPOSTER_POSITION) + .hasProperty(Properties.LEVEL_8, 0, () -> "Expected Composter to be emptied"); context.expectItem(context.getWorld().itematic$getItem(ItemKeys.BONE_MEAL).value()); }); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/DispenserBehaviorTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/DispenserBehaviorTestSuite.java index 60ba2b7e..1ea0f1e6 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/DispenserBehaviorTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/DispenserBehaviorTestSuite.java @@ -1,9 +1,10 @@ package net.errorcraft.itematic.gametest.block; +import net.errorcraft.itematic.assertion.Assert; 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.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.BeehiveBlock; import net.minecraft.block.Blocks; import net.minecraft.block.FacingBlock; @@ -20,7 +21,6 @@ import net.minecraft.registry.tag.FluidTags; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Properties; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -32,125 +32,137 @@ public class DispenserBehaviorTestSuite { private static final BlockPos OUTPUT_POSITION = DISPENSER_POSITION.add(0, 0, -1); private static final BlockPos ABOVE_OUTPUT_POSITION = OUTPUT_POSITION.add(0, 1, 0); - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingArrowSpawnsArrow(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ARROW); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.ARROW); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.ARROW)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.ARROW); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingExperienceBottleSpawnsExperienceBottle(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.EXPERIENCE_BOTTLE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.EXPERIENCE_BOTTLE); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.EXPERIENCE_BOTTLE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.EXPERIENCE_BOTTLE); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingFireworkRocketSpawnsFireworkRocket(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FIREWORK_ROCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.FIREWORK_ROCKET); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.FIREWORK_ROCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.FIREWORK_ROCKET); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingFireChargeSpawnsEntity(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FIRE_CHARGE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.SMALL_FIREBALL); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.FIRE_CHARGE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.SMALL_FIREBALL); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingPigSpawnEggSpawnsPig(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.PIG); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.PIG_SPAWN_EGG)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.PIG); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingArmorStandSpawnsArmorStand(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ARMOR_STAND); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.ARMOR_STAND); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.ARMOR_STAND)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.ARMOR_STAND); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingSpruceBoatSpawnsSpruceBoat(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SPRUCE_BOAT); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntityAt(EntityType.SPRUCE_BOAT, OUTPUT_POSITION); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.SPRUCE_BOAT)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntityAt(EntityType.SPRUCE_BOAT, OUTPUT_POSITION); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.grass_block") + @GameTest(structure = "itematic:block.dispenser.grass_block") public void dispensingBoneMealFertilizesBlock(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BONE_MEAL); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectBlock(Blocks.AIR, ABOVE_OUTPUT_POSITION); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.BONE_MEAL)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, ABOVE_OUTPUT_POSITION) + .isNot(Blocks.AIR); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingBoneMealOnInvalidBlockKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BONE_MEAL); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlock(Blocks.AIR, ABOVE_OUTPUT_POSITION); - context.dontExpectItem(world.itematic$getItem(ItemKeys.BONE_MEAL).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.BONE_MEAL); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.BONE_MEAL)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, ABOVE_OUTPUT_POSITION) + .is(Blocks.AIR); + context.dontExpectItem(world.itematic$getItem(ItemKeys.BONE_MEAL).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.BONE_MEAL); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingEquipmentEquipsEntity(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); @@ -159,27 +171,33 @@ public void dispensingEquipmentEquipsEntity(TestContext context) { world.spawnEntity(player); ItemStack stack = world.itematic$createStack(ItemKeys.IRON_HELMET); blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(player.getEquippedStack(EquipmentSlot.HEAD), ItemKeys.IRON_HELMET); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.itemStack(context, player.getEquippedStack(EquipmentSlot.HEAD)) + .is(ItemKeys.IRON_HELMET); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingEquipmentWithNoEntityDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.IRON_HELMET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.IRON_HELMET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.IRON_HELMET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.IRON_HELMET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingHeadEquipsEntity(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); @@ -188,365 +206,424 @@ public void dispensingHeadEquipsEntity(TestContext context) { world.spawnEntity(player); ItemStack stack = world.itematic$createStack(ItemKeys.SKELETON_SKULL); blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(player.getEquippedStack(EquipmentSlot.HEAD), ItemKeys.SKELETON_SKULL); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.itemStack(context, player.getEquippedStack(EquipmentSlot.HEAD)) + .is(ItemKeys.SKELETON_SKULL); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingHeadWithNoEntityKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SKELETON_SKULL); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.SKELETON_SKULL).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.SKELETON_SKULL); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SKELETON_SKULL)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.SKELETON_SKULL).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.SKELETON_SKULL); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingWaterBucketPlacesWater(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WATER_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.fluidIsIn(context, FluidTags.WATER, OUTPUT_POSITION); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.BUCKET); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.WATER_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.fluidState(context, OUTPUT_POSITION) + .is(FluidTags.WATER); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.BUCKET); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingWaterBucketWithObstructedBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WATER_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.WATER_BUCKET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.WATER_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.WATER_BUCKET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingPowderSnowBucketPlacesPowderSnow(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlock(Blocks.POWDER_SNOW, OUTPUT_POSITION); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.BUCKET); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .is(Blocks.POWDER_SNOW); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.BUCKET); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingPowderSnowBucketWithObstructedBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.POWDER_SNOW_BUCKET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.POWDER_SNOW_BUCKET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingSalmonBucketPlacesWaterAndSpawnsSalmon(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SALMON_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.fluidIsIn(context, FluidTags.WATER, OUTPUT_POSITION); - context.expectEntity(EntityType.SALMON); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.BUCKET); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.SALMON_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.fluidState(context, OUTPUT_POSITION) + .is(FluidTags.WATER); + context.expectEntity(EntityType.SALMON); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.BUCKET); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingSalmonBucketWithObstructedBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SALMON_BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.SALMON_BUCKET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SALMON_BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.SALMON_BUCKET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.water") + @GameTest(structure = "itematic:block.dispenser.water") public void dispensingBucketPicksUpFluid(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.fluidIsOf(context, Fluids.EMPTY, OUTPUT_POSITION); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.WATER_BUCKET); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.fluidState(context, OUTPUT_POSITION) + .is(Fluids.EMPTY); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.WATER_BUCKET); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingBucketWithNothingToPickUpDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.BUCKET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.BUCKET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.BUCKET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.dirt") + @GameTest(structure = "itematic:block.dispenser.dirt") public void dispensingWaterBottleConvertsBlockToMud(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); ItemStack stack = PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.WATER); blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlock(Blocks.MUD, OUTPUT_POSITION); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.GLASS_BOTTLE); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .is(Blocks.MUD); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.GLASS_BOTTLE); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingWaterBottleOnInvalidBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); ItemStack stack = PotionContentsComponentUtil.setPotion(world.itematic$createStack(ItemKeys.POTION), Potions.WATER); blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.POTION).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.POTION).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.beehive") + @GameTest(structure = "itematic:block.dispenser.beehive") public void dispensingGlassBottleOnBeehiveFillsBottleWithHoney(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLASS_BOTTLE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.checkBlockState( - OUTPUT_POSITION, - state -> state.get(Properties.HONEY_LEVEL) == 0, - () -> "Honey level was not reset" - ); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.HONEY_BOTTLE); - })); - } - - @GameTest(templateName = "itematic:block.dispenser.water") + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.GLASS_BOTTLE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .hasProperty(Properties.HONEY_LEVEL, 0, () -> "Expected honey level to be reset"); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.HONEY_BOTTLE); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser.water") public void dispensingGlassBottleOnWaterFillsBottleWithWater(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLASS_BOTTLE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.POTION); - Assert.itemStackHasPotion(blockEntity.getStack(0), Potions.WATER); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.GLASS_BOTTLE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.POTION) + .hasPotion(Potions.WATER)) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingGlassBottleOnInvalidBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLASS_BOTTLE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.GLASS_BOTTLE).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.GLASS_BOTTLE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.GLASS_BOTTLE).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingHorseArmorOnHorseEquipsHorse(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.IRON_HORSE_ARMOR); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.IRON_HORSE_ARMOR)); HorseEntity horse = TestUtil.createEntity(context, EntityType.HORSE, entity -> { TestUtil.setEntityPos(context, entity, OUTPUT_POSITION); entity.setTame(true); }); world.spawnEntity(horse); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(horse.getBodyArmor(), ItemKeys.IRON_HORSE_ARMOR); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.itemStack(context, horse.getBodyArmor()) + .is(ItemKeys.IRON_HORSE_ARMOR); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingHorseArmorWithNoEntityDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.IRON_HORSE_ARMOR); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.IRON_HORSE_ARMOR).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.IRON_HORSE_ARMOR)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.IRON_HORSE_ARMOR).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingCarpetOnLlamaEquipsLlama(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_CARPET); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.WHITE_CARPET)); LlamaEntity llama = TestUtil.createEntity(context, EntityType.LLAMA, entity -> { TestUtil.setEntityPos(context, entity, OUTPUT_POSITION); entity.setTame(true); }); world.spawnEntity(llama); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(llama.getBodyArmor(), ItemKeys.WHITE_CARPET); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.itemStack(context, llama.getBodyArmor()) + .is(ItemKeys.WHITE_CARPET); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingCarpetWithNoEntityDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_CARPET); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.WHITE_CARPET).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.WHITE_CARPET)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.WHITE_CARPET).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingChestOnMuleEquipsMuleWithChest(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CHEST); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.CHEST)); MuleEntity mule = TestUtil.createEntity(context, EntityType.MULE, entity -> { TestUtil.setEntityPos(context, entity, OUTPUT_POSITION); entity.setTame(true); }); world.spawnEntity(mule); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.assertTrue(mule.hasChest(), "Expected mule to have a chest"); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.isTrue( + context, + mule.hasChest(), + () -> "Expected Mule to have a chest" + ); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingChestOnLlamaEquipsLlamaWithChest(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CHEST); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.CHEST)); LlamaEntity llama = TestUtil.createEntity(context, EntityType.LLAMA, entity -> { TestUtil.setEntityPos(context, entity, OUTPUT_POSITION); entity.setTame(true); }); world.spawnEntity(llama); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.assertTrue(llama.hasChest(), "Expected llama to have a chest"); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.isTrue( + context, + llama.hasChest(), + () -> "Expected Llama to have a chest" + ); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingChestWithNoEntityDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CHEST); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.CHEST).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.CHEST)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.CHEST).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingShulkerBoxWithBlockBelowOutputPlacesShulkerBoxFacingUp(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHULKER_BOX); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlockProperty(OUTPUT_POSITION, FacingBlock.FACING, Direction.UP); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.SHULKER_BOX)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .hasProperty(FacingBlock.FACING, Direction.UP); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.gap_below_output") + @GameTest(structure = "itematic:block.dispenser.gap_below_output") public void dispensingShulkerBoxWithoutBlockBelowOutputPlacesShulkerBoxWithDispenserDirection(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHULKER_BOX); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - Direction dispenserDirection = context.getBlockState(DISPENSER_POSITION).get(FacingBlock.FACING); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlockProperty(OUTPUT_POSITION, FacingBlock.FACING, dispenserDirection); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.SHULKER_BOX)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Direction dispenserDirection = context.getBlockState(DISPENSER_POSITION).get(FacingBlock.FACING); + Assert.blockState(context, OUTPUT_POSITION) + .hasProperty(FacingBlock.FACING, dispenserDirection); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.bedrock") + @GameTest(structure = "itematic:block.dispenser.bedrock") public void dispensingShulkerBoxWithObstructedBlockKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHULKER_BOX); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.SHULKER_BOX).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.SHULKER_BOX); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SHULKER_BOX)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.SHULKER_BOX).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.SHULKER_BOX); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingTntSpawnsTnt(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TNT); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.TNT); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.TNT)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.TNT); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingCarvedPumpkinEquipsEntity(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); @@ -555,245 +632,289 @@ public void dispensingCarvedPumpkinEquipsEntity(TestContext context) { world.spawnEntity(player); ItemStack stack = world.itematic$createStack(ItemKeys.CARVED_PUMPKIN); blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - Assert.itemStackIsOf(player.getEquippedStack(EquipmentSlot.HEAD), ItemKeys.CARVED_PUMPKIN); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.itemStack(context, player.getEquippedStack(EquipmentSlot.HEAD)) + .is(ItemKeys.CARVED_PUMPKIN); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.iron_golem_structure") + @GameTest(structure = "itematic:block.dispenser.iron_golem_structure") public void dispensingCarvedPumpkinPlacesCarvedPumpkinOnIronGolemStructure(TestContext context) { BlockPos offset = new BlockPos(0, 2, 0); DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION.add(offset), BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CARVED_PUMPKIN); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION.add(offset)); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectEntity(EntityType.IRON_GOLEM); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.CARVED_PUMPKIN)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION.add(offset))) + .expectMinDurationAndRun(4, () -> { + context.expectEntity(EntityType.IRON_GOLEM); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingCarvedPumpkinWithNoValidTargetKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CARVED_PUMPKIN); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.CARVED_PUMPKIN).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.CARVED_PUMPKIN); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.CARVED_PUMPKIN)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.CARVED_PUMPKIN).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.CARVED_PUMPKIN); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.respawn_anchor") + @GameTest(structure = "itematic:block.dispenser.respawn_anchor") public void dispensingGlowstoneOnRespawnAnchorChargesRespawnAnchor(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLOWSTONE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlockProperty(OUTPUT_POSITION, RespawnAnchorBlock.CHARGES, 1); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.GLOWSTONE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .hasProperty(RespawnAnchorBlock.CHARGES, 1); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.respawn_anchor.full") + @GameTest(structure = "itematic:block.dispenser.respawn_anchor.full") public void dispensingGlowstoneOnFullRespawnAnchorKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLOWSTONE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.GLOWSTONE).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.GLOWSTONE); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.GLOWSTONE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.GLOWSTONE).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.GLOWSTONE); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingGlowstoneOnInvalidBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.GLOWSTONE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.GLOWSTONE).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.GLOWSTONE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.GLOWSTONE).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingShearsOnSheepShearsSheep(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHEARS); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SHEARS)); SheepEntity sheep = context.spawnEntity(EntityType.SHEEP, OUTPUT_POSITION); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.assertTrue(sheep.isSheared(), "Expected sheep to be sheared"); - context.expectItem(world.itematic$getItem(ItemKeys.WHITE_WOOL).value()); - context.assertTrue(blockEntity.getStack(0).isDamaged(), "Expected item stack to be damaged"); - })); - } - - @GameTest(templateName = "itematic:block.dispenser.beehive") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.isTrue( + context, + sheep.isSheared(), + () -> "Expected Sheep to be sheared" + ); + context.expectItem(world.itematic$getItem(ItemKeys.WHITE_WOOL).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isDamaged(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser.beehive") public void dispensingShearsOnBeehiveWithHoneyShearsBeehive(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHEARS); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlockProperty(OUTPUT_POSITION, BeehiveBlock.HONEY_LEVEL, 0); - context.expectItem(world.itematic$getItem(ItemKeys.HONEYCOMB).value()); - context.assertTrue(blockEntity.getStack(0).isDamaged(), "Expected item stack to be damaged"); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SHEARS)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .hasProperty(BeehiveBlock.HONEY_LEVEL, 0); + context.expectItem(world.itematic$getItem(ItemKeys.HONEYCOMB).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingShearsWithNoValidTargetKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHEARS); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.SHEARS).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.SHEARS); - context.assertFalse(blockEntity.getStack(0).isDamaged(), "Expected item stack not to be damaged"); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SHEARS)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.SHEARS).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.SHEARS) + .isNotDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingSaddleOnPigEquipsPig(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SADDLE); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SADDLE)); PigEntity pig = context.spawnEntity(EntityType.PIG, OUTPUT_POSITION); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.assertTrue(pig.isSaddled(), "Expected pig to be saddled"); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.livingEntity(context, pig) + .hasEquippedStack(EquipmentSlot.SADDLE, stack -> stack.is(ItemKeys.SADDLE)); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingSaddleOnHorseEquipsHorse(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SADDLE); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SADDLE)); HorseEntity horse = TestUtil.createEntity(context, EntityType.HORSE, entity -> { TestUtil.setEntityPos(context, entity, OUTPUT_POSITION); entity.setTame(true); }); world.spawnEntity(horse); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.assertTrue(horse.isSaddled(), "Expected horse to be saddled"); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); - } - - @GameTest(templateName = "itematic:block.dispenser") + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.livingEntity(context, horse) + .hasEquippedStack(EquipmentSlot.SADDLE, stack -> stack.is(ItemKeys.SADDLE)); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); + } + + @GameTest(structure = "itematic:block.dispenser") public void dispensingSaddleWithNoEntityDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SADDLE); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.SADDLE).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.SADDLE)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.SADDLE).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingFlintAndSteelPlacesFire(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FLINT_AND_STEEL); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlock(Blocks.FIRE, OUTPUT_POSITION); - context.assertTrue(blockEntity.getStack(0).isDamaged(), "Expected item stack to be damaged"); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.FLINT_AND_STEEL)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .is(Blocks.FIRE); + Assert.itemStack(context, blockEntity.getStack(0)) + .isDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.gap_below_output") + @GameTest(structure = "itematic:block.dispenser.gap_below_output") public void dispensingFlintAndSteelOnInvalidBlockKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FLINT_AND_STEEL); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.FLINT_AND_STEEL).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.FLINT_AND_STEEL); - context.assertFalse(blockEntity.getStack(0).isDamaged(), "Expected item stack not to be damaged"); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.FLINT_AND_STEEL)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.FLINT_AND_STEEL).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.FLINT_AND_STEEL) + .isNotDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingBrushDropsArmadilloScute(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BRUSH); - blockEntity.addToFirstFreeSlot(stack); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.BRUSH)); context.spawnEntity(EntityType.ARMADILLO, OUTPUT_POSITION); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.ARMADILLO_SCUTE).value()); - context.assertTrue(blockEntity.getStack(0).isDamaged(), "Expected item stack to be damaged"); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.ARMADILLO_SCUTE).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingBrushWithNoEntityKeepsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BRUSH); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.dontExpectItem(world.itematic$getItem(ItemKeys.BRUSH).value()); - Assert.itemStackIsOf(blockEntity.getStack(0), ItemKeys.BRUSH); - context.assertFalse(blockEntity.getStack(0).isDamaged(), "Expected item stack not to be damaged"); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.BRUSH)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.dontExpectItem(world.itematic$getItem(ItemKeys.BRUSH).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .is(ItemKeys.BRUSH) + .isNotDamaged(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser.copper_block") + @GameTest(structure = "itematic:block.dispenser.copper_block") public void dispensingHoneycombWaxesBlock(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.HONEYCOMB); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectBlock(Blocks.WAXED_COPPER_BLOCK, OUTPUT_POSITION); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(context.getWorld().itematic$createStack(ItemKeys.HONEYCOMB)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + Assert.blockState(context, OUTPUT_POSITION) + .is(Blocks.WAXED_COPPER_BLOCK); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } - @GameTest(templateName = "itematic:block.dispenser") + @GameTest(structure = "itematic:block.dispenser") public void dispensingHoneycombOnInvalidBlockDropsItem(TestContext context) { DispenserBlockEntity blockEntity = TestUtil.getBlockEntity(context, DISPENSER_POSITION, BlockEntityType.DISPENSER); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.HONEYCOMB); - blockEntity.addToFirstFreeSlot(stack); - context.pushButton(BUTTON_POSITION); - context.runAtTick(4, () -> context.addFinalTask(() -> { - context.expectItem(world.itematic$getItem(ItemKeys.HONEYCOMB).value()); - Assert.itemStackIsEmpty(blockEntity.getStack(0)); - })); + blockEntity.addToFirstFreeSlot(world.itematic$createStack(ItemKeys.HONEYCOMB)); + context.createTimedTaskRunner() + .createAndAddReported(() -> context.pushButton(BUTTON_POSITION)) + .expectMinDurationAndRun(4, () -> { + context.expectItem(world.itematic$getItem(ItemKeys.HONEYCOMB).value()); + Assert.itemStack(context, blockEntity.getStack(0)) + .isEmpty(); + }) + .completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/EnchantingTableTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/EnchantingTableTestSuite.java index e176b5e5..3de057bc 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/EnchantingTableTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/EnchantingTableTestSuite.java @@ -1,16 +1,15 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.screen.EnchantmentScreenHandler; 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; @@ -18,7 +17,7 @@ public class EnchantingTableTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.enchanting_table") + @GameTest(structure = "itematic:block.enchanting_table") public void placingEnchantableItemWithoutEnchantmentsSuggestsEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -27,12 +26,14 @@ public void placingEnchantableItemWithoutEnchantmentsSuggestsEnchantments(TestCo .setStack(world.itematic$createStack(ItemKeys.IRON_PICKAXE)); enchantmentMenu.getSlot(1) .setStack(world.itematic$createStack(ItemKeys.LAPIS_LAZULI)); - context.addInstantFinalTask(() -> { - context.assertTrue(enchantmentMenu.enchantmentPower[0] > 0, "Expected enchantments to be suggested"); - }); + context.addFinalTask(() -> Assert.isTrue( + context, + enchantmentMenu.enchantmentPower[0] > 0, + () -> "Expected enchantments to be suggested" + )); } - @GameTest(templateName = "itematic:block.enchanting_table") + @GameTest(structure = "itematic:block.enchanting_table") public void placingUnenchantableItemInEnchantingTableDoesNotSuggestEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -41,12 +42,14 @@ public void placingUnenchantableItemInEnchantingTableDoesNotSuggestEnchantments( .setStack(world.itematic$createStack(ItemKeys.STICK)); enchantmentMenu.getSlot(1) .setStack(world.itematic$createStack(ItemKeys.LAPIS_LAZULI)); - context.addInstantFinalTask(() -> { - context.assertTrue(enchantmentMenu.enchantmentPower[0] == 0, "Expected no enchantments to be suggested"); - }); + context.addFinalTask(() -> Assert.isTrue( + context, + enchantmentMenu.enchantmentPower[0] == 0, + () -> "Expected no enchantments to be suggested" + )); } - @GameTest(templateName = "itematic:block.enchanting_table") + @GameTest(structure = "itematic:block.enchanting_table") public void placingEnchantableItemWithEnchantmentsInEnchantingTableDoesNotSuggestEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -55,12 +58,14 @@ public void placingEnchantableItemWithEnchantmentsInEnchantingTableDoesNotSugges .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); enchantmentMenu.getSlot(1) .setStack(world.itematic$createStack(ItemKeys.LAPIS_LAZULI)); - context.addInstantFinalTask(() -> { - context.assertTrue(enchantmentMenu.enchantmentPower[0] == 0, "Expected no enchantments to be suggested"); - }); + context.addFinalTask(() -> Assert.isTrue( + context, + enchantmentMenu.enchantmentPower[0] == 0, + () -> "Expected no enchantments to be suggested" + )); } - @GameTest(templateName = "itematic:block.enchanting_table") + @GameTest(structure = "itematic:block.enchanting_table") public void enchantingEnchantableItemInEnchantingTableAddsEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -71,16 +76,12 @@ public void enchantingEnchantableItemInEnchantingTableAddsEnchantments(TestConte enchantmentMenu.getSlot(1) .setStack(world.itematic$createStack(ItemKeys.LAPIS_LAZULI)); enchantmentMenu.onButtonClick(player, 0); - context.addInstantFinalTask(() -> { - ItemStack result = enchantmentMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(result, ItemKeys.IRON_PICKAXE); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - context.assertFalse(enchantments.isEmpty(), "Expected enchantments to be added to " + DataComponentTypes.ENCHANTMENTS); - }); - }); + context.addFinalTask(() -> Assert.itemStack(context, enchantmentMenu.getSlot(0).getStack()) + .is(ItemKeys.IRON_PICKAXE) + .hasEnchantments()); } - @GameTest(templateName = "itematic:block.enchanting_table") + @GameTest(structure = "itematic:block.enchanting_table") public void enchantingBookInEnchantingTableTransformsItemIntoEnchantedBookAndAddsEnchantmentsToStoredEnchantments(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); @@ -91,15 +92,17 @@ public void enchantingBookInEnchantingTableTransformsItemIntoEnchantedBookAndAdd enchantmentMenu.getSlot(1) .setStack(world.itematic$createStack(ItemKeys.LAPIS_LAZULI)); enchantmentMenu.onButtonClick(player, 0); - context.addInstantFinalTask(() -> { - ItemStack result = enchantmentMenu.getSlot(0).getStack(); - Assert.itemStackIsOf(result, ItemKeys.ENCHANTED_BOOK); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - context.assertTrue(enchantments.isEmpty(), "Expected enchantments not to be added to " + DataComponentTypes.ENCHANTMENTS); - }); - Assert.itemStackHasDataComponent(result, DataComponentTypes.STORED_ENCHANTMENTS, storedEnchantments -> { - context.assertFalse(storedEnchantments.isEmpty(), "Expected enchantments to be added to " + DataComponentTypes.STORED_ENCHANTMENTS); - }); - }); + context.addFinalTask(() -> Assert.itemStack(context, enchantmentMenu.getSlot(0).getStack()) + .is(ItemKeys.ENCHANTED_BOOK) + .hasComponent(DataComponentTypes.ENCHANTMENTS, enchantments -> Assert.isTrue( + context, + enchantments.isEmpty(), + () -> "Expected enchantments not to be added to " + DataComponentTypes.ENCHANTMENTS + )) + .hasComponent(DataComponentTypes.STORED_ENCHANTMENTS, storedEnchantments -> Assert.isFalse( + context, + storedEnchantments.isEmpty(), + () -> "Expected enchantments to be added to " + DataComponentTypes.STORED_ENCHANTMENTS + ))); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/GrindstoneTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/GrindstoneTestSuite.java index f327500b..33d2fff6 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/GrindstoneTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/GrindstoneTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.minecraft.component.DataComponentTypes; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.screen.GrindstoneScreenHandler; 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; @@ -18,65 +16,60 @@ public class GrindstoneTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.grindstone") + @GameTest(structure = "itematic:block.grindstone") public void placingEnchantedItemInGrindstoneDisenchantsItem(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); GrindstoneScreenHandler grindstoneMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.GRINDSTONE); - grindstoneMenu.getSlot(0) - .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING)); - context.addInstantFinalTask(() -> { - ItemStack result = grindstoneMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.IRON_PICKAXE); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - context.assertTrue(enchantments.isEmpty(), "Expected item to not have any enchantments"); - }); - }); + grindstoneMenu.getSlot(0).setStack( + TestUtil.createItemStackWithEnchantment(world, ItemKeys.IRON_PICKAXE, Enchantments.UNBREAKING) + ); + context.addFinalTask(() -> Assert.itemStack(context, grindstoneMenu.getSlot(2).getStack()) + .is(ItemKeys.IRON_PICKAXE) + .hasNoEnchantments()); } - @GameTest(templateName = "itematic:block.grindstone") + @GameTest(structure = "itematic:block.grindstone") public void placingEnchantedBookInGrindstoneTransformsItemIntoBook(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); GrindstoneScreenHandler grindstoneMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.GRINDSTONE); - grindstoneMenu.getSlot(0) - .setStack(TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.UNBREAKING)); - context.addInstantFinalTask(() -> { - ItemStack result = grindstoneMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.BOOK); - Assert.itemStackHasDataComponent(result, DataComponentTypes.ENCHANTMENTS, enchantments -> { - context.assertTrue(enchantments.isEmpty(), "Expected item to not have any enchantments"); - }); - }); + grindstoneMenu.getSlot(0).setStack( + TestUtil.createItemStackWithEnchantment(world, ItemKeys.ENCHANTED_BOOK, Enchantments.UNBREAKING) + ); + context.addFinalTask(() -> Assert.itemStack(context, grindstoneMenu.getSlot(2).getStack()) + .is(ItemKeys.BOOK) + .hasNoEnchantments()); } - @GameTest(templateName = "itematic:block.grindstone") + @GameTest(structure = "itematic:block.grindstone") public void placingDamageableItemsWithSameIsInGrindstoneRepairsItem(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); GrindstoneScreenHandler grindstoneMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.GRINDSTONE); - grindstoneMenu.getSlot(0) - .setStack(TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE)); - grindstoneMenu.getSlot(1) - .setStack(TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE)); - context.addInstantFinalTask(() -> { - ItemStack result = grindstoneMenu.getSlot(2).getStack(); - Assert.itemStackIsOf(result, ItemKeys.IRON_PICKAXE); - context.assertFalse(result.isDamaged(), "Expected item stack not to be damaged"); - }); + grindstoneMenu.getSlot(0).setStack( + TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE) + ); + grindstoneMenu.getSlot(1).setStack( + TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE) + ); + context.addFinalTask(() -> Assert.itemStack(context, grindstoneMenu.getSlot(2).getStack()) + .is(ItemKeys.IRON_PICKAXE) + .isNotDamaged()); } - @GameTest(templateName = "itematic:block.grindstone") + @GameTest(structure = "itematic:block.grindstone") public void placingDamageableItemsWithDifferentIdsInGrindstoneRejectsRepair(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); GrindstoneScreenHandler grindstoneMenu = TestUtil.getMenuFromBlock(context, BLOCK_POSITION, player, ScreenHandlerType.GRINDSTONE); - grindstoneMenu.getSlot(0) - .setStack(TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE)); - grindstoneMenu.getSlot(1) - .setStack(TestUtil.createItemStackWithSlightDamage(world, ItemKeys.DIAMOND_PICKAXE)); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(grindstoneMenu.getSlot(2).getStack()); - }); + grindstoneMenu.getSlot(0).setStack( + TestUtil.createItemStackWithSlightDamage(world, ItemKeys.IRON_PICKAXE) + ); + grindstoneMenu.getSlot(1).setStack( + TestUtil.createItemStackWithSlightDamage(world, ItemKeys.DIAMOND_PICKAXE) + ); + context.addFinalTask(() -> Assert.itemStack(context, grindstoneMenu.getSlot(2).getStack()) + .isEmpty()); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/PickBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/PickBlockTestSuite.java index 3b397a89..336bf9d1 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/PickBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/PickBlockTestSuite.java @@ -1,1133 +1,1413 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.math.BlockPos; public class PickBlockTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.piston_head") + @GameTest(structure = "itematic:block.piston_head") public void getPickStackOnPistonHeadGivesPistonItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PISTON)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PISTON) + ); } - @GameTest(templateName = "itematic:block.piston_head.sticky") + @GameTest(structure = "itematic:block.piston_head.sticky") public void getPickStackOnStickyPistonHeadGivesStickyPistonItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.STICKY_PISTON)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.STICKY_PISTON) + ); } - @GameTest(templateName = "itematic:block.redstone_wire") + @GameTest(structure = "itematic:block.redstone_wire") public void getPickStackOnRedstoneWireGivesRedstoneItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.REDSTONE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.REDSTONE) + ); } - @GameTest(templateName = "itematic:block.tripwire") + @GameTest(structure = "itematic:block.tripwire") public void getPickStackOnTripwireGivesStringItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.STRING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.STRING) + ); } - @GameTest(templateName = "itematic:block.wall_torch") + @GameTest(structure = "itematic:block.wall_torch") public void getPickStackOnWallTorchGivesTorchItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TORCH)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TORCH) + ); } - @GameTest(templateName = "itematic:block.redstone_wall_torch") + @GameTest(structure = "itematic:block.redstone_wall_torch") public void getPickStackOnRedstoneWallTorchGivesRedstoneTorchItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.REDSTONE_TORCH)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.REDSTONE_TORCH) + ); } - @GameTest(templateName = "itematic:block.soul_wall_torch") + @GameTest(structure = "itematic:block.soul_wall_torch") public void getPickStackOnSoulWallTorchGivesSoulTorchItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SOUL_TORCH)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SOUL_TORCH) + ); } - @GameTest(templateName = "itematic:block.oak_wall_sign") + @GameTest(structure = "itematic:block.oak_wall_sign") public void getPickStackOnOakWallSignGivesOakSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OAK_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OAK_SIGN) + ); } - @GameTest(templateName = "itematic:block.spruce_wall_sign") + @GameTest(structure = "itematic:block.spruce_wall_sign") public void getPickStackOnSpruceWallSignGivesSpruceSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPRUCE_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPRUCE_SIGN) + ); } - @GameTest(templateName = "itematic:block.birch_wall_sign") + @GameTest(structure = "itematic:block.birch_wall_sign") public void getPickStackOnBirchWallSignGivesBirchSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIRCH_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIRCH_SIGN) + ); } - @GameTest(templateName = "itematic:block.acacia_wall_sign") + @GameTest(structure = "itematic:block.acacia_wall_sign") public void getPickStackOnAcaciaWallSignGivesAcaciaSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ACACIA_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ACACIA_SIGN) + ); } - @GameTest(templateName = "itematic:block.cherry_wall_sign") + @GameTest(structure = "itematic:block.cherry_wall_sign") public void getPickStackOnCherryWallSignGivesCherrySignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHERRY_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHERRY_SIGN) + ); } - @GameTest(templateName = "itematic:block.pale_oak_wall_sign") + @GameTest(structure = "itematic:block.pale_oak_wall_sign") public void getPickStackOnPaleOakWallSignGivesPaleOakSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PALE_OAK_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PALE_OAK_SIGN) + ); } - @GameTest(templateName = "itematic:block.jungle_wall_sign") + @GameTest(structure = "itematic:block.jungle_wall_sign") public void getPickStackOnJungleWallSignGivesJungleSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.JUNGLE_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.JUNGLE_SIGN) + ); } - @GameTest(templateName = "itematic:block.dark_oak_wall_sign") + @GameTest(structure = "itematic:block.dark_oak_wall_sign") public void getPickStackOnDarkOakWallSignGivesDarkOakSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DARK_OAK_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DARK_OAK_SIGN) + ); } - @GameTest(templateName = "itematic:block.mangrove_wall_sign") + @GameTest(structure = "itematic:block.mangrove_wall_sign") public void getPickStackOnMangroveWallSignGivesMangroveSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MANGROVE_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MANGROVE_SIGN) + ); } - @GameTest(templateName = "itematic:block.bamboo_wall_sign") + @GameTest(structure = "itematic:block.bamboo_wall_sign") public void getPickStackOnBambooWallSignGivesBambooSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO_SIGN) + ); } - @GameTest(templateName = "itematic:block.crimson_wall_sign") + @GameTest(structure = "itematic:block.crimson_wall_sign") public void getPickStackOnCrimsonWallSignGivesCrimsonSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CRIMSON_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CRIMSON_SIGN) + ); } - @GameTest(templateName = "itematic:block.warped_wall_sign") + @GameTest(structure = "itematic:block.warped_wall_sign") public void getPickStackOnWarpedWallSignGivesWarpedSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WARPED_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WARPED_SIGN) + ); } - @GameTest(templateName = "itematic:block.oak_wall_hanging_sign") + @GameTest(structure = "itematic:block.oak_wall_hanging_sign") public void getPickStackOnOakWallHangingSignGivesOakHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OAK_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OAK_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.spruce_wall_hanging_sign") + @GameTest(structure = "itematic:block.spruce_wall_hanging_sign") public void getPickStackOnSpruceWallHangingSignGivesSpruceHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPRUCE_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPRUCE_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.birch_wall_hanging_sign") + @GameTest(structure = "itematic:block.birch_wall_hanging_sign") public void getPickStackOnBirchWallHangingSignGivesBirchHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIRCH_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIRCH_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.acacia_wall_hanging_sign") + @GameTest(structure = "itematic:block.acacia_wall_hanging_sign") public void getPickStackOnAcaciaWallHangingSignGivesAcaciaHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ACACIA_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ACACIA_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.cherry_wall_hanging_sign") + @GameTest(structure = "itematic:block.cherry_wall_hanging_sign") public void getPickStackOnCherryWallHangingSignGivesCherryHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHERRY_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHERRY_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.pale_oak_wall_hanging_sign") + @GameTest(structure = "itematic:block.pale_oak_wall_hanging_sign") public void getPickStackOnPaleOakWallHangingSignGivesPaleOakHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PALE_OAK_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PALE_OAK_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.jungle_wall_hanging_sign") + @GameTest(structure = "itematic:block.jungle_wall_hanging_sign") public void getPickStackOnJungleWallHangingSignGivesJungleHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.JUNGLE_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.JUNGLE_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.dark_oak_wall_hanging_sign") + @GameTest(structure = "itematic:block.dark_oak_wall_hanging_sign") public void getPickStackOnDarkOakWallHangingSignGivesDarkOakHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DARK_OAK_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DARK_OAK_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.mangrove_wall_hanging_sign") + @GameTest(structure = "itematic:block.mangrove_wall_hanging_sign") public void getPickStackOnMangroveWallHangingSignGivesMangroveHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MANGROVE_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MANGROVE_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.crimson_wall_hanging_sign") + @GameTest(structure = "itematic:block.crimson_wall_hanging_sign") public void getPickStackOnCrimsonWallHangingSignGivesCrimsonHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CRIMSON_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CRIMSON_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.warped_wall_hanging_sign") + @GameTest(structure = "itematic:block.warped_wall_hanging_sign") public void getPickStackOnWarpedWallHangingSignGivesWarpedHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WARPED_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WARPED_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.bamboo_wall_hanging_sign") + @GameTest(structure = "itematic:block.bamboo_wall_hanging_sign") public void getPickStackOnBambooWallHangingSignGivesBambooHangingSignItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO_HANGING_SIGN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO_HANGING_SIGN) + ); } - @GameTest(templateName = "itematic:block.attached_pumpkin_stem") + @GameTest(structure = "itematic:block.attached_pumpkin_stem") public void getPickStackOnAttachedPumpkinStemGivesPumpkinSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PUMPKIN_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PUMPKIN_SEEDS) + ); } - @GameTest(templateName = "itematic:block.attached_melon_stem") + @GameTest(structure = "itematic:block.attached_melon_stem") public void getPickStackOnAttachedMelonStemGivesMelonSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MELON_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MELON_SEEDS) + ); } - @GameTest(templateName = "itematic:block.pumpkin_stem") + @GameTest(structure = "itematic:block.pumpkin_stem") public void getPickStackOnPumpkinStemGivesPumpkinSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PUMPKIN_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PUMPKIN_SEEDS) + ); } - @GameTest(templateName = "itematic:block.melon_stem") + @GameTest(structure = "itematic:block.melon_stem") public void getPickStackOnMelonStemGivesMelonSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MELON_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MELON_SEEDS) + ); } - @GameTest(templateName = "itematic:block.cocoa") + @GameTest(structure = "itematic:block.cocoa") public void getPickStackOnCocoaGivesCocoaBeansItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.COCOA_BEANS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.COCOA_BEANS) + ); } - @GameTest(templateName = "itematic:block.carrots") + @GameTest(structure = "itematic:block.carrots") public void getPickStackOnCarrotsGivesCarrotItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CARROT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CARROT) + ); } - @GameTest(templateName = "itematic:block.potatoes") + @GameTest(structure = "itematic:block.potatoes") public void getPickStackOnPotatoesGivesPotatoItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.POTATO)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.POTATO) + ); } - @GameTest(templateName = "itematic:block.torchflower_crop") + @GameTest(structure = "itematic:block.torchflower_crop") public void getPickStackOnTorchflowerCropGivesTorchflowerSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TORCHFLOWER_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TORCHFLOWER_SEEDS) + ); } - @GameTest(templateName = "itematic:block.pitcher_crop") + @GameTest(structure = "itematic:block.pitcher_crop") public void getPickStackOnPitcherCropGivesPitcherPodItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PITCHER_POD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PITCHER_POD) + ); } - @GameTest(templateName = "itematic:block.beetroots") + @GameTest(structure = "itematic:block.beetroots") public void getPickStackOnBeetrootsGivesBeetrootSeedsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BEETROOT_SEEDS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BEETROOT_SEEDS) + ); } - @GameTest(templateName = "itematic:block.cave_vines") + @GameTest(structure = "itematic:block.cave_vines") public void getPickStackOnCaveVinesGivesGlowBerriesItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GLOW_BERRIES)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GLOW_BERRIES) + ); } - @GameTest(templateName = "itematic:block.cave_vines_plant") + @GameTest(structure = "itematic:block.cave_vines_plant") public void getPickStackOnCaveVinesPlantGivesGlowBerriesItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GLOW_BERRIES)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GLOW_BERRIES) + ); } - @GameTest(templateName = "itematic:block.big_dripleaf_stem") + @GameTest(structure = "itematic:block.big_dripleaf_stem") public void getPickStackOnBigDripleafStemGivesBigDripleafItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIG_DRIPLEAF)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIG_DRIPLEAF) + ); } - @GameTest(templateName = "itematic:block.tall_seagrass") + @GameTest(structure = "itematic:block.tall_seagrass") public void getPickStackOnTallSeagrassGivesSeagrassItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SEAGRASS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SEAGRASS) + ); } - @GameTest(templateName = "itematic:block.kelp_plant") + @GameTest(structure = "itematic:block.kelp_plant") public void getPickStackOnKelpPlantGivesKelpItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.KELP)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.KELP) + ); } - @GameTest(templateName = "itematic:block.water_cauldron") + @GameTest(structure = "itematic:block.water_cauldron") public void getPickStackOnWaterCauldronGivesCauldronItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAULDRON)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAULDRON) + ); } - @GameTest(templateName = "itematic:block.lava_cauldron") + @GameTest(structure = "itematic:block.lava_cauldron") public void getPickStackOnLavaCauldronGivesCauldronItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAULDRON)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAULDRON) + ); } - @GameTest(templateName = "itematic:block.powder_snow_cauldron") + @GameTest(structure = "itematic:block.powder_snow_cauldron") public void getPickStackOnPowderSnowCauldronGivesCauldronItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAULDRON)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAULDRON) + ); } - @GameTest(templateName = "itematic:block.powder_snow") + @GameTest(structure = "itematic:block.powder_snow") public void getPickStackOnPowderSnowGivesPowderSnowBucketItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.POWDER_SNOW_BUCKET)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.POWDER_SNOW_BUCKET) + ); } - @GameTest(templateName = "itematic:block.potted_torchflower") + @GameTest(structure = "itematic:block.potted_torchflower") public void getPickStackOnPottedTorchflowerGivesTorchflowerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TORCHFLOWER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TORCHFLOWER) + ); } - @GameTest(templateName = "itematic:block.potted_oak_sapling") + @GameTest(structure = "itematic:block.potted_oak_sapling") public void getPickStackOnPottedOakSaplingGivesOakSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OAK_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OAK_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_spruce_sapling") + @GameTest(structure = "itematic:block.potted_spruce_sapling") public void getPickStackOnPottedSpruceSaplingGivesSpruceSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPRUCE_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPRUCE_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_birch_sapling") + @GameTest(structure = "itematic:block.potted_birch_sapling") public void getPickStackOnPottedBirchSaplingGivesBirchSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIRCH_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIRCH_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_jungle_sapling") + @GameTest(structure = "itematic:block.potted_jungle_sapling") public void getPickStackOnPottedJungleSaplingGivesJungleSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.JUNGLE_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.JUNGLE_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_acacia_sapling") + @GameTest(structure = "itematic:block.potted_acacia_sapling") public void getPickStackOnPottedAcaciaSaplingGivesAcaciaSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ACACIA_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ACACIA_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_cherry_sapling") + @GameTest(structure = "itematic:block.potted_cherry_sapling") public void getPickStackOnPottedCherrySaplingGivesCherrySaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHERRY_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHERRY_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_dark_oak_sapling") + @GameTest(structure = "itematic:block.potted_dark_oak_sapling") public void getPickStackOnPottedDarkOakSaplingGivesDarkOakSaplingItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DARK_OAK_SAPLING)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DARK_OAK_SAPLING) + ); } - @GameTest(templateName = "itematic:block.potted_mangrove_propagule") + @GameTest(structure = "itematic:block.potted_mangrove_propagule") public void getPickStackOnPottedMangrovePropaguleGivesMangrovePropaguleItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MANGROVE_PROPAGULE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MANGROVE_PROPAGULE) + ); } - @GameTest(templateName = "itematic:block.potted_fern") + @GameTest(structure = "itematic:block.potted_fern") public void getPickStackOnPottedFernGivesFernItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.FERN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.FERN) + ); } - @GameTest(templateName = "itematic:block.potted_dandelion") + @GameTest(structure = "itematic:block.potted_dandelion") public void getPickStackOnPottedDandelionGivesDandelionItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DANDELION)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DANDELION) + ); } - @GameTest(templateName = "itematic:block.potted_poppy") + @GameTest(structure = "itematic:block.potted_poppy") public void getPickStackOnPottedPoppyGivesPoppyItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.POPPY)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.POPPY) + ); } - @GameTest(templateName = "itematic:block.potted_blue_orchid") + @GameTest(structure = "itematic:block.potted_blue_orchid") public void getPickStackOnPottedBlueOrchidGivesBlueOrchidItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BLUE_ORCHID)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BLUE_ORCHID) + ); } - @GameTest(templateName = "itematic:block.potted_allium") + @GameTest(structure = "itematic:block.potted_allium") public void getPickStackOnPottedAlliumGivesAlliumItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ALLIUM)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ALLIUM) + ); } - @GameTest(templateName = "itematic:block.potted_azure_bluet") + @GameTest(structure = "itematic:block.potted_azure_bluet") public void getPickStackOnPottedAzureBluetGivesAzureBluetItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.AZURE_BLUET)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.AZURE_BLUET) + ); } - @GameTest(templateName = "itematic:block.potted_red_tulip") + @GameTest(structure = "itematic:block.potted_red_tulip") public void getPickStackOnPottedRedTulipGivesRedTulipItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.RED_TULIP)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.RED_TULIP) + ); } - @GameTest(templateName = "itematic:block.potted_orange_tulip") + @GameTest(structure = "itematic:block.potted_orange_tulip") public void getPickStackOnPottedOrangeTulipGivesOrangeTulipItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ORANGE_TULIP)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ORANGE_TULIP) + ); } - @GameTest(templateName = "itematic:block.potted_white_tulip") + @GameTest(structure = "itematic:block.potted_white_tulip") public void getPickStackOnPottedWhiteTulipGivesWhiteTulipItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WHITE_TULIP)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WHITE_TULIP) + ); } - @GameTest(templateName = "itematic:block.potted_pink_tulip") + @GameTest(structure = "itematic:block.potted_pink_tulip") public void getPickStackOnPottedPinkTulipGivesPinkTulipItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PINK_TULIP)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PINK_TULIP) + ); } - @GameTest(templateName = "itematic:block.potted_oxeye_daisy") + @GameTest(structure = "itematic:block.potted_oxeye_daisy") public void getPickStackOnPottedOxeyeDaisyGivesOxeyeDaisyItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OXEYE_DAISY)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OXEYE_DAISY) + ); } - @GameTest(templateName = "itematic:block.potted_cornflower") + @GameTest(structure = "itematic:block.potted_cornflower") public void getPickStackOnPottedCornflowerGivesCornflowerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CORNFLOWER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CORNFLOWER) + ); } - @GameTest(templateName = "itematic:block.potted_lily_of_the_valley") + @GameTest(structure = "itematic:block.potted_lily_of_the_valley") public void getPickStackOnPottedLilyOfTheValleyGivesLilyOfTheValleyItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.LILY_OF_THE_VALLEY)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.LILY_OF_THE_VALLEY) + ); } - @GameTest(templateName = "itematic:block.potted_wither_rose") + @GameTest(structure = "itematic:block.potted_wither_rose") public void getPickStackOnPottedWitherRoseGivesWitherRoseItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WITHER_ROSE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WITHER_ROSE) + ); } - @GameTest(templateName = "itematic:block.potted_red_mushroom") + @GameTest(structure = "itematic:block.potted_red_mushroom") public void getPickStackOnPottedRedMushroomGivesRedMushroomItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.RED_MUSHROOM)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.RED_MUSHROOM) + ); } - @GameTest(templateName = "itematic:block.potted_brown_mushroom") + @GameTest(structure = "itematic:block.potted_brown_mushroom") public void getPickStackOnPottedBrownMushroomGivesBrownMushroomItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BROWN_MUSHROOM)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BROWN_MUSHROOM) + ); } - @GameTest(templateName = "itematic:block.potted_dead_bush") + @GameTest(structure = "itematic:block.potted_dead_bush") public void getPickStackOnPottedDeadBushGivesDeadBushItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_BUSH)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_BUSH) + ); } - @GameTest(templateName = "itematic:block.potted_cactus") + @GameTest(structure = "itematic:block.potted_cactus") public void getPickStackOnPottedCactusGivesCactusItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CACTUS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CACTUS) + ); } - @GameTest(templateName = "itematic:block.potted_bamboo") + @GameTest(structure = "itematic:block.potted_bamboo") public void getPickStackOnPottedBambooGivesBambooItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO) + ); } - @GameTest(templateName = "itematic:block.potted_crimson_fungus") + @GameTest(structure = "itematic:block.potted_crimson_fungus") public void getPickStackOnPottedCrimsonFungusGivesCrimsonFungusItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CRIMSON_FUNGUS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CRIMSON_FUNGUS) + ); } - @GameTest(templateName = "itematic:block.potted_warped_fungus") + @GameTest(structure = "itematic:block.potted_warped_fungus") public void getPickStackOnPottedWarpedFungusGivesWarpedFungusItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WARPED_FUNGUS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WARPED_FUNGUS) + ); } - @GameTest(templateName = "itematic:block.potted_crimson_roots") + @GameTest(structure = "itematic:block.potted_crimson_roots") public void getPickStackOnPottedCrimsonRootsGivesCrimsonRootsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CRIMSON_ROOTS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CRIMSON_ROOTS) + ); } - @GameTest(templateName = "itematic:block.potted_warped_roots") + @GameTest(structure = "itematic:block.potted_warped_roots") public void getPickStackOnPottedWarpedRootsGivesWarpedRootsItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WARPED_ROOTS)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WARPED_ROOTS) + ); } - @GameTest(templateName = "itematic:block.potted_azalea_bush") + @GameTest(structure = "itematic:block.potted_azalea_bush") public void getPickStackOnPottedAzaleaBushGivesAzaleaItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.AZALEA)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.AZALEA) + ); } - @GameTest(templateName = "itematic:block.potted_flowering_azalea_bush") + @GameTest(structure = "itematic:block.potted_flowering_azalea_bush") public void getPickStackOnPottedFloweringAzaleaBushGivesFloweringAzaleaItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.FLOWERING_AZALEA)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.FLOWERING_AZALEA) + ); } - @GameTest(templateName = "itematic:block.potted_open_eyeblossom") + @GameTest(structure = "itematic:block.potted_open_eyeblossom") public void getPickStackOnPottedOpenEyeblossomGivesOpenEyeblossomItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OPEN_EYEBLOSSOM)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OPEN_EYEBLOSSOM) + ); } - @GameTest(templateName = "itematic:block.potted_closed_eyeblossom") + @GameTest(structure = "itematic:block.potted_closed_eyeblossom") public void getPickStackOnPottedClosedEyeblossomGivesClosedEyeblossomItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CLOSED_EYEBLOSSOM)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CLOSED_EYEBLOSSOM) + ); } - @GameTest(templateName = "itematic:block.skeleton_wall_skull") + @GameTest(structure = "itematic:block.skeleton_wall_skull") public void getPickStackOnSkeletonWallSkullGivesSkeletonSkullItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SKELETON_SKULL)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SKELETON_SKULL) + ); } - @GameTest(templateName = "itematic:block.wither_skeleton_wall_skull") + @GameTest(structure = "itematic:block.wither_skeleton_wall_skull") public void getPickStackOnWitherSkeletonWallSkullGivesWitherSkeletonSkullItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WITHER_SKELETON_SKULL)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WITHER_SKELETON_SKULL) + ); } - @GameTest(templateName = "itematic:block.zombie_wall_head") + @GameTest(structure = "itematic:block.zombie_wall_head") public void getPickStackOnZombieWallHeadGivesZombieHeadItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOMBIE_HEAD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOMBIE_HEAD) + ); } - @GameTest(templateName = "itematic:block.player_wall_head") + @GameTest(structure = "itematic:block.player_wall_head") public void getPickStackOnPlayerWallHeadGivesPlayerHeadItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PLAYER_HEAD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PLAYER_HEAD) + ); } - @GameTest(templateName = "itematic:block.creeper_wall_head") + @GameTest(structure = "itematic:block.creeper_wall_head") public void getPickStackOnCreeperWallHeadGivesCreeperHeadItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CREEPER_HEAD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CREEPER_HEAD) + ); } - @GameTest(templateName = "itematic:block.dragon_wall_head") + @GameTest(structure = "itematic:block.dragon_wall_head") public void getPickStackOnDragonWallHeadGivesDragonHeadItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DRAGON_HEAD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DRAGON_HEAD) + ); } - @GameTest(templateName = "itematic:block.piglin_wall_head") + @GameTest(structure = "itematic:block.piglin_wall_head") public void getPickStackOnPiglinWallHeadGivesPiglinHeadItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PIGLIN_HEAD)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PIGLIN_HEAD) + ); } - @GameTest(templateName = "itematic:block.white_wall_banner") + @GameTest(structure = "itematic:block.white_wall_banner") public void getPickStackOnWhiteWallBannerGivesWhiteBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WHITE_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WHITE_BANNER) + ); } - @GameTest(templateName = "itematic:block.orange_wall_banner") + @GameTest(structure = "itematic:block.orange_wall_banner") public void getPickStackOnOrangeWallBannerGivesOrangeBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ORANGE_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ORANGE_BANNER) + ); } - @GameTest(templateName = "itematic:block.magenta_wall_banner") + @GameTest(structure = "itematic:block.magenta_wall_banner") public void getPickStackOnMagentaWallBannerGivesMagentaBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MAGENTA_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MAGENTA_BANNER) + ); } - @GameTest(templateName = "itematic:block.light_blue_wall_banner") + @GameTest(structure = "itematic:block.light_blue_wall_banner") public void getPickStackOnLightBlueWallBannerGivesLightBlueBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.LIGHT_BLUE_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.LIGHT_BLUE_BANNER) + ); } - @GameTest(templateName = "itematic:block.yellow_wall_banner") + @GameTest(structure = "itematic:block.yellow_wall_banner") public void getPickStackOnYellowWallBannerGivesYellowBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.YELLOW_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.YELLOW_BANNER) + ); } - @GameTest(templateName = "itematic:block.lime_wall_banner") + @GameTest(structure = "itematic:block.lime_wall_banner") public void getPickStackOnLimeWallBannerGivesLimeBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.LIME_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.LIME_BANNER) + ); } - @GameTest(templateName = "itematic:block.pink_wall_banner") + @GameTest(structure = "itematic:block.pink_wall_banner") public void getPickStackOnPinkWallBannerGivesPinkBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PINK_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PINK_BANNER) + ); } - @GameTest(templateName = "itematic:block.gray_wall_banner") + @GameTest(structure = "itematic:block.gray_wall_banner") public void getPickStackOnGrayWallBannerGivesGrayBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GRAY_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GRAY_BANNER) + ); } - @GameTest(templateName = "itematic:block.light_gray_wall_banner") + @GameTest(structure = "itematic:block.light_gray_wall_banner") public void getPickStackOnLightGrayWallBannerGivesLightGrayBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.LIGHT_GRAY_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.LIGHT_GRAY_BANNER) + ); } - @GameTest(templateName = "itematic:block.cyan_wall_banner") + @GameTest(structure = "itematic:block.cyan_wall_banner") public void getPickStackOnCyanWallBannerGivesCyanBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CYAN_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CYAN_BANNER) + ); } - @GameTest(templateName = "itematic:block.purple_wall_banner") + @GameTest(structure = "itematic:block.purple_wall_banner") public void getPickStackOnPurpleWallBannerGivesPurpleBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PURPLE_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PURPLE_BANNER) + ); } - @GameTest(templateName = "itematic:block.blue_wall_banner") + @GameTest(structure = "itematic:block.blue_wall_banner") public void getPickStackOnBlueWallBannerGivesBlueBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BLUE_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BLUE_BANNER) + ); } - @GameTest(templateName = "itematic:block.brown_wall_banner") + @GameTest(structure = "itematic:block.brown_wall_banner") public void getPickStackOnBrownWallBannerGivesBrownBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BROWN_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BROWN_BANNER) + ); } - @GameTest(templateName = "itematic:block.green_wall_banner") + @GameTest(structure = "itematic:block.green_wall_banner") public void getPickStackOnGreenWallBannerGivesGreenBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GREEN_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GREEN_BANNER) + ); } - @GameTest(templateName = "itematic:block.red_wall_banner") + @GameTest(structure = "itematic:block.red_wall_banner") public void getPickStackOnRedWallBannerGivesRedBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.RED_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.RED_BANNER) + ); } - @GameTest(templateName = "itematic:block.black_wall_banner") + @GameTest(structure = "itematic:block.black_wall_banner") public void getPickStackOnBlackWallBannerGivesBlackBannerItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BLACK_BANNER)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BLACK_BANNER) + ); } - @GameTest(templateName = "itematic:block.dead_tube_coral_wall_fan") + @GameTest(structure = "itematic:block.dead_tube_coral_wall_fan") public void getPickStackOnDeadTubeCoralWallFanGivesDeadTubeCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_TUBE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_TUBE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.dead_brain_coral_wall_fan") + @GameTest(structure = "itematic:block.dead_brain_coral_wall_fan") public void getPickStackOnDeadBrainCoralWallFanGivesDeadBrainCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_BRAIN_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_BRAIN_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.dead_bubble_coral_wall_fan") + @GameTest(structure = "itematic:block.dead_bubble_coral_wall_fan") public void getPickStackOnDeadBubbleCoralWallFanGivesDeadBubbleCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_BUBBLE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_BUBBLE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.dead_fire_coral_wall_fan") + @GameTest(structure = "itematic:block.dead_fire_coral_wall_fan") public void getPickStackOnDeadFireCoralWallFanGivesDeadFireCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_FIRE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_FIRE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.dead_horn_coral_wall_fan") + @GameTest(structure = "itematic:block.dead_horn_coral_wall_fan") public void getPickStackOnDeadHornCoralWallFanGivesDeadHornCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DEAD_HORN_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DEAD_HORN_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.tube_coral_wall_fan") + @GameTest(structure = "itematic:block.tube_coral_wall_fan") public void getPickStackOnTubeCoralWallFanGivesTubeCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TUBE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TUBE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.brain_coral_wall_fan") + @GameTest(structure = "itematic:block.brain_coral_wall_fan") public void getPickStackOnBrainCoralWallFanGivesBrainCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BRAIN_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BRAIN_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.bubble_coral_wall_fan") + @GameTest(structure = "itematic:block.bubble_coral_wall_fan") public void getPickStackOnBubbleCoralWallFanGivesBubbleCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BUBBLE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BUBBLE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.fire_coral_wall_fan") + @GameTest(structure = "itematic:block.fire_coral_wall_fan") public void getPickStackOnFireCoralWallFanGivesFireCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.FIRE_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.FIRE_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.horn_coral_wall_fan") + @GameTest(structure = "itematic:block.horn_coral_wall_fan") public void getPickStackOnHornCoralWallFanGivesHornCoralFanItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.HORN_CORAL_FAN)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.HORN_CORAL_FAN) + ); } - @GameTest(templateName = "itematic:block.bamboo_sapling") + @GameTest(structure = "itematic:block.bamboo_sapling") public void getPickStackOnBambooSaplingGivesBambooItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO) + ); } - @GameTest(templateName = "itematic:block.sweet_berry_bush") + @GameTest(structure = "itematic:block.sweet_berry_bush") public void getPickStackOnSweetBerryBushGivesSweetBerriesItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SWEET_BERRIES)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SWEET_BERRIES) + ); } - @GameTest(templateName = "itematic:block.weeping_vines_plant") + @GameTest(structure = "itematic:block.weeping_vines_plant") public void getPickStackOnWeepingVinesPlantGivesWeepingVinesItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WEEPING_VINES)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WEEPING_VINES) + ); } - @GameTest(templateName = "itematic:block.twisting_vines_plant") + @GameTest(structure = "itematic:block.twisting_vines_plant") public void getPickStackOnTwistingVinesPlantGivesTwistingVinesItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TWISTING_VINES)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TWISTING_VINES) + ); } - @GameTest(templateName = "itematic:block.candle_cake") + @GameTest(structure = "itematic:block.candle_cake") public void getPickStackOnCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.white_candle_cake") + @GameTest(structure = "itematic:block.white_candle_cake") public void getPickStackOnWhiteCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.orange_candle_cake") + @GameTest(structure = "itematic:block.orange_candle_cake") public void getPickStackOnOrangeCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.magenta_candle_cake") + @GameTest(structure = "itematic:block.magenta_candle_cake") public void getPickStackOnMagentaCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.light_blue_candle_cake") + @GameTest(structure = "itematic:block.light_blue_candle_cake") public void getPickStackOnLightBlueCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.yellow_candle_cake") + @GameTest(structure = "itematic:block.yellow_candle_cake") public void getPickStackOnYellowCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.lime_candle_cake") + @GameTest(structure = "itematic:block.lime_candle_cake") public void getPickStackOnLimeCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.pink_candle_cake") + @GameTest(structure = "itematic:block.pink_candle_cake") public void getPickStackOnPinkCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.gray_candle_cake") + @GameTest(structure = "itematic:block.gray_candle_cake") public void getPickStackOnGrayCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.light_gray_candle_cake") + @GameTest(structure = "itematic:block.light_gray_candle_cake") public void getPickStackOnLightGrayCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.cyan_candle_cake") + @GameTest(structure = "itematic:block.cyan_candle_cake") public void getPickStackOnCyanCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.purple_candle_cake") + @GameTest(structure = "itematic:block.purple_candle_cake") public void getPickStackOnPurpleCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.blue_candle_cake") + @GameTest(structure = "itematic:block.blue_candle_cake") public void getPickStackOnBlueCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.brown_candle_cake") + @GameTest(structure = "itematic:block.brown_candle_cake") public void getPickStackOnBrownCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.green_candle_cake") + @GameTest(structure = "itematic:block.green_candle_cake") public void getPickStackOnGreenCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.red_candle_cake") + @GameTest(structure = "itematic:block.red_candle_cake") public void getPickStackOnRedCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } - @GameTest(templateName = "itematic:block.black_candle_cake") + @GameTest(structure = "itematic:block.black_candle_cake") public void getPickStackOnBlackCandleCakeGivesCakeItemStack(TestContext context) { BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); ItemStack stack = state.getPickStack(context.getWorld(), absolutePos, false); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAKE)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAKE) + ); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/ShulkerBoxBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/ShulkerBoxBlockTestSuite.java index 5edad272..a6828c58 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/ShulkerBoxBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/ShulkerBoxBlockTestSuite.java @@ -1,10 +1,10 @@ package net.errorcraft.itematic.gametest.block; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; 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; @@ -12,23 +12,23 @@ public class ShulkerBoxBlockTestSuite { private static final BlockPos BLOCK_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.shulker_box") + @GameTest(structure = "itematic:block.shulker_box") public void breakingShulkerBoxInCreativeModeDropsShulkerBox(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.CREATIVE); ServerWorld world = context.getWorld(); BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); state.getBlock().onBreak(world, absolutePos, state, player); - context.addInstantFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.SHULKER_BOX).value())); + context.addFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.SHULKER_BOX).value())); } - @GameTest(templateName = "itematic:block.red_shulker_box") + @GameTest(structure = "itematic:block.red_shulker_box") public void breakingRedShulkerBoxInCreativeModeDropsRedShulkerBox(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.CREATIVE); ServerWorld world = context.getWorld(); BlockState state = context.getBlockState(BLOCK_POSITION); BlockPos absolutePos = context.getAbsolutePos(BLOCK_POSITION); state.getBlock().onBreak(world, absolutePos, state, player); - context.addInstantFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.RED_SHULKER_BOX).value())); + context.addFinalTask(() -> context.expectItem(context.getWorld().itematic$getItem(ItemKeys.RED_SHULKER_BOX).value())); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java index b47ea56d..bb35ec47 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java @@ -1,13 +1,13 @@ package net.errorcraft.itematic.gametest.block; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.DyedColorComponent; 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.util.math.BlockPos; @@ -16,26 +16,28 @@ public class WaterCauldronBlockTestSuite { private static final BlockPos WATER_CAULDRON_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:block.water_cauldron") + @GameTest(structure = "itematic:block.water_cauldron") public void usingColoredShulkerBoxOnWaterCauldronClearsColor(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_SHULKER_BOX); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack whiteShulkerBox = world.itematic$createStack(ItemKeys.WHITE_SHULKER_BOX); + player.setStackInHand(Hand.MAIN_HAND, whiteShulkerBox); world.spawnEntity(player); context.useBlock(WATER_CAULDRON_POSITION, player); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.SHULKER_BOX)); + context.addFinalTask(() -> Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .is(ItemKeys.SHULKER_BOX)); } - @GameTest(templateName = "itematic:block.water_cauldron") + @GameTest(structure = "itematic:block.water_cauldron") public void usingColoredWolfArmorOnWaterCauldronClearsColor(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WOLF_ARMOR); - stack.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(0xffffff, true)); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack wolfArmor = world.itematic$createStack(ItemKeys.WOLF_ARMOR); + wolfArmor.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(0xffffff, true)); + player.setStackInHand(Hand.MAIN_HAND, wolfArmor); world.spawnEntity(player); context.useBlock(WATER_CAULDRON_POSITION, player); - context.addFinalTask(() -> Assert.itemStackDoesNotHaveDataComponent(player.getStackInHand(Hand.MAIN_HAND), DataComponentTypes.DYED_COLOR)); + context.addFinalTask(() -> Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .doesNotHaveComponent(DataComponentTypes.DYED_COLOR)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/PickEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/PickEntityTestSuite.java index 6955d6d7..c9554365 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/PickEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/PickEntityTestSuite.java @@ -1,7 +1,8 @@ package net.errorcraft.itematic.gametest.entity; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.boss.WitherEntity; import net.minecraft.entity.boss.dragon.EnderDragonEntity; @@ -12,682 +13,873 @@ import net.minecraft.entity.vehicle.ChestRaftEntity; import net.minecraft.entity.vehicle.RaftEntity; import net.minecraft.item.ItemStack; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.math.BlockPos; public class PickEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnArmadilloGivesArmadilloSpawnEggItemStack(TestContext context) { ArmadilloEntity armadillo = context.spawnEntity(EntityType.ARMADILLO, SPAWN_POSITION); ItemStack stack = armadillo.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ARMADILLO_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ARMADILLO_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnAllayGivesAllaySpawnEggItemStack(TestContext context) { AllayEntity allay = context.spawnEntity(EntityType.ALLAY, SPAWN_POSITION); ItemStack stack = allay.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ALLAY_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ALLAY_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnAxolotlGivesAxolotlSpawnEggItemStack(TestContext context) { AxolotlEntity axolotl = context.spawnEntity(EntityType.AXOLOTL, SPAWN_POSITION); ItemStack stack = axolotl.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.AXOLOTL_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.AXOLOTL_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBatGivesBatSpawnEggItemStack(TestContext context) { BatEntity bat = context.spawnEntity(EntityType.BAT, SPAWN_POSITION); ItemStack stack = bat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBeeGivesBeeSpawnEggItemStack(TestContext context) { BeeEntity bee = context.spawnEntity(EntityType.BEE, SPAWN_POSITION); ItemStack stack = bee.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BEE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BEE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBlazeGivesBlazeSpawnEggItemStack(TestContext context) { BlazeEntity blaze = context.spawnEntity(EntityType.BLAZE, SPAWN_POSITION); ItemStack stack = blaze.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BLAZE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BLAZE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCatGivesCatSpawnEggItemStack(TestContext context) { CatEntity cat = context.spawnEntity(EntityType.CAT, SPAWN_POSITION); ItemStack stack = cat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCamelGivesCamelSpawnEggItemStack(TestContext context) { CamelEntity camel = context.spawnEntity(EntityType.CAMEL, SPAWN_POSITION); ItemStack stack = camel.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAMEL_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAMEL_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCaveSpiderGivesCaveSpiderSpawnEggItemStack(TestContext context) { CaveSpiderEntity caveSpider = context.spawnEntity(EntityType.CAVE_SPIDER, SPAWN_POSITION); ItemStack stack = caveSpider.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CAVE_SPIDER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CAVE_SPIDER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnChickenGivesChickenSpawnEggItemStack(TestContext context) { ChickenEntity chicken = context.spawnEntity(EntityType.CHICKEN, SPAWN_POSITION); ItemStack stack = chicken.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHICKEN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHICKEN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCodGivesCodSpawnEggItemStack(TestContext context) { CodEntity cod = context.spawnEntity(EntityType.COD, SPAWN_POSITION); ItemStack stack = cod.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.COD_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.COD_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCowGivesCowSpawnEggItemStack(TestContext context) { CowEntity cow = context.spawnEntity(EntityType.COW, SPAWN_POSITION); ItemStack stack = cow.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.COW_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.COW_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCreeperGivesCreeperSpawnEggItemStack(TestContext context) { CreeperEntity creeper = context.spawnEntity(EntityType.CREEPER, SPAWN_POSITION); ItemStack stack = creeper.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CREEPER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CREEPER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnDolphinGivesDolphinSpawnEggItemStack(TestContext context) { DolphinEntity dolphin = context.spawnEntity(EntityType.DOLPHIN, SPAWN_POSITION); ItemStack stack = dolphin.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DOLPHIN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DOLPHIN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnDonkeyGivesDonkeySpawnEggItemStack(TestContext context) { DonkeyEntity donkey = context.spawnEntity(EntityType.DONKEY, SPAWN_POSITION); ItemStack stack = donkey.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DONKEY_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DONKEY_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnDrownedGivesDrownedSpawnEggItemStack(TestContext context) { DrownedEntity drowned = context.spawnEntity(EntityType.DROWNED, SPAWN_POSITION); ItemStack stack = drowned.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DROWNED_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DROWNED_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnElderGuardianGivesElderGuardianSpawnEggItemStack(TestContext context) { ElderGuardianEntity elderGuardian = context.spawnEntity(EntityType.ELDER_GUARDIAN, SPAWN_POSITION); ItemStack stack = elderGuardian.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ELDER_GUARDIAN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ELDER_GUARDIAN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnEnderDragonGivesEnderDragonSpawnEggItemStack(TestContext context) { EnderDragonEntity enderDragon = context.spawnEntity(EntityType.ENDER_DRAGON, SPAWN_POSITION); ItemStack stack = enderDragon.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ENDER_DRAGON_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ENDER_DRAGON_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnEndermanGivesEndermanSpawnEggItemStack(TestContext context) { EndermanEntity enderman = context.spawnEntity(EntityType.ENDERMAN, SPAWN_POSITION); ItemStack stack = enderman.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ENDERMAN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ENDERMAN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnEndermiteGivesEndermiteSpawnEggItemStack(TestContext context) { EndermiteEntity endermite = context.spawnEntity(EntityType.ENDERMITE, SPAWN_POSITION); ItemStack stack = endermite.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ENDERMITE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ENDERMITE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnEvokerGivesEvokerSpawnEggItemStack(TestContext context) { EvokerEntity evoker = context.spawnEntity(EntityType.EVOKER, SPAWN_POSITION); ItemStack stack = evoker.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.EVOKER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.EVOKER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnFoxGivesFoxSpawnEggItemStack(TestContext context) { FoxEntity fox = context.spawnEntity(EntityType.FOX, SPAWN_POSITION); ItemStack stack = fox.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.FOX_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.FOX_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnFrogGivesFrogSpawnEggItemStack(TestContext context) { FrogEntity frog = context.spawnEntity(EntityType.FROG, SPAWN_POSITION); ItemStack stack = frog.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.FROG_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.FROG_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnGhastGivesGhastSpawnEggItemStack(TestContext context) { GhastEntity ghast = context.spawnEntity(EntityType.GHAST, SPAWN_POSITION); ItemStack stack = ghast.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GHAST_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GHAST_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnGlowSquidGivesGlowSquidSpawnEggItemStack(TestContext context) { GlowSquidEntity glowSquid = context.spawnEntity(EntityType.GLOW_SQUID, SPAWN_POSITION); ItemStack stack = glowSquid.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GLOW_SQUID_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GLOW_SQUID_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnGoatGivesGoatSpawnEggItemStack(TestContext context) { GoatEntity goat = context.spawnEntity(EntityType.GOAT, SPAWN_POSITION); ItemStack stack = goat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GOAT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GOAT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnGuardianGivesGuardianSpawnEggItemStack(TestContext context) { GuardianEntity guardian = context.spawnEntity(EntityType.GUARDIAN, SPAWN_POSITION); ItemStack stack = guardian.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.GUARDIAN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.GUARDIAN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnHoglinGivesHoglinSpawnEggItemStack(TestContext context) { HoglinEntity hoglin = context.spawnEntity(EntityType.HOGLIN, SPAWN_POSITION); ItemStack stack = hoglin.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.HOGLIN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.HOGLIN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnHorseGivesHorseSpawnEggItemStack(TestContext context) { HorseEntity horse = context.spawnEntity(EntityType.HORSE, SPAWN_POSITION); ItemStack stack = horse.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.HORSE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.HORSE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnHuskGivesHuskSpawnEggItemStack(TestContext context) { HuskEntity husk = context.spawnEntity(EntityType.HUSK, SPAWN_POSITION); ItemStack stack = husk.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.HUSK_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.HUSK_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnIronGolemGivesIronGolemSpawnEggItemStack(TestContext context) { IronGolemEntity ironGolem = context.spawnEntity(EntityType.IRON_GOLEM, SPAWN_POSITION); ItemStack stack = ironGolem.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.IRON_GOLEM_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.IRON_GOLEM_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnLlamaGivesLlamaSpawnEggItemStack(TestContext context) { LlamaEntity llama = context.spawnEntity(EntityType.LLAMA, SPAWN_POSITION); ItemStack stack = llama.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.LLAMA_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.LLAMA_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnMagmaCubeGivesMagmaCubeSpawnEggItemStack(TestContext context) { MagmaCubeEntity magmaCube = context.spawnEntity(EntityType.MAGMA_CUBE, SPAWN_POSITION); ItemStack stack = magmaCube.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MAGMA_CUBE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MAGMA_CUBE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnMooshroomGivesMooshroomSpawnEggItemStack(TestContext context) { MooshroomEntity mooshroom = context.spawnEntity(EntityType.MOOSHROOM, SPAWN_POSITION); ItemStack stack = mooshroom.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MOOSHROOM_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MOOSHROOM_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnMuleGivesMuleSpawnEggItemStack(TestContext context) { MuleEntity mule = context.spawnEntity(EntityType.MULE, SPAWN_POSITION); ItemStack stack = mule.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MULE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MULE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnOcelotGivesOcelotSpawnEggItemStack(TestContext context) { OcelotEntity ocelot = context.spawnEntity(EntityType.OCELOT, SPAWN_POSITION); ItemStack stack = ocelot.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OCELOT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OCELOT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPandaGivesPandaSpawnEggItemStack(TestContext context) { PandaEntity panda = context.spawnEntity(EntityType.PANDA, SPAWN_POSITION); ItemStack stack = panda.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PANDA_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PANDA_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnParrotGivesParrotSpawnEggItemStack(TestContext context) { ParrotEntity parrot = context.spawnEntity(EntityType.PARROT, SPAWN_POSITION); ItemStack stack = parrot.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PARROT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PARROT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPhantomGivesPhantomSpawnEggItemStack(TestContext context) { PhantomEntity phantom = context.spawnEntity(EntityType.PHANTOM, SPAWN_POSITION); ItemStack stack = phantom.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PHANTOM_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PHANTOM_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPigGivesPigSpawnEggItemStack(TestContext context) { PigEntity pig = context.spawnEntity(EntityType.PIG, SPAWN_POSITION); ItemStack stack = pig.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PIG_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PIG_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPiglinGivesPiglinSpawnEggItemStack(TestContext context) { PiglinEntity piglin = context.spawnEntity(EntityType.PIGLIN, SPAWN_POSITION); ItemStack stack = piglin.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PIGLIN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PIGLIN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPiglinBruteGivesPiglinBruteSpawnEggItemStack(TestContext context) { PiglinBruteEntity piglinBrute = context.spawnEntity(EntityType.PIGLIN_BRUTE, SPAWN_POSITION); ItemStack stack = piglinBrute.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PIGLIN_BRUTE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PIGLIN_BRUTE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPillagerGivesPillagerSpawnEggItemStack(TestContext context) { PillagerEntity pillager = context.spawnEntity(EntityType.PILLAGER, SPAWN_POSITION); ItemStack stack = pillager.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PILLAGER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PILLAGER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPolarBearGivesPolarBearSpawnEggItemStack(TestContext context) { PolarBearEntity polarBear = context.spawnEntity(EntityType.POLAR_BEAR, SPAWN_POSITION); ItemStack stack = polarBear.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.POLAR_BEAR_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.POLAR_BEAR_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnPufferfishGivesPufferfishSpawnEggItemStack(TestContext context) { PufferfishEntity pufferfish = context.spawnEntity(EntityType.PUFFERFISH, SPAWN_POSITION); ItemStack stack = pufferfish.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.PUFFERFISH_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.PUFFERFISH_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnRabbitGivesRabbitSpawnEggItemStack(TestContext context) { RabbitEntity rabbit = context.spawnEntity(EntityType.RABBIT, SPAWN_POSITION); ItemStack stack = rabbit.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.RABBIT_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.RABBIT_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnRavagerGivesRavagerSpawnEggItemStack(TestContext context) { RavagerEntity ravager = context.spawnEntity(EntityType.RAVAGER, SPAWN_POSITION); ItemStack stack = ravager.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.RAVAGER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.RAVAGER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSalmonGivesSalmonSpawnEggItemStack(TestContext context) { SalmonEntity salmon = context.spawnEntity(EntityType.SALMON, SPAWN_POSITION); ItemStack stack = salmon.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SALMON_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SALMON_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSheepGivesSheepSpawnEggItemStack(TestContext context) { SheepEntity sheep = context.spawnEntity(EntityType.SHEEP, SPAWN_POSITION); ItemStack stack = sheep.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SHEEP_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SHEEP_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnShulkerGivesShulkerSpawnEggItemStack(TestContext context) { ShulkerEntity shulker = context.spawnEntity(EntityType.SHULKER, SPAWN_POSITION); ItemStack stack = shulker.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SHULKER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SHULKER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSilverfishGivesSilverfishSpawnEggItemStack(TestContext context) { SilverfishEntity silverfish = context.spawnEntity(EntityType.SILVERFISH, SPAWN_POSITION); ItemStack stack = silverfish.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SILVERFISH_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SILVERFISH_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSkeletonGivesSkeletonSpawnEggItemStack(TestContext context) { SkeletonEntity skeleton = context.spawnEntity(EntityType.SKELETON, SPAWN_POSITION); ItemStack stack = skeleton.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SKELETON_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SKELETON_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSkeletonHorseGivesSkeletonHorseSpawnEggItemStack(TestContext context) { SkeletonHorseEntity skeletonHorse = context.spawnEntity(EntityType.SKELETON_HORSE, SPAWN_POSITION); ItemStack stack = skeletonHorse.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SKELETON_HORSE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SKELETON_HORSE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSlimeGivesSlimeSpawnEggItemStack(TestContext context) { SlimeEntity slime = context.spawnEntity(EntityType.SLIME, SPAWN_POSITION); ItemStack stack = slime.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SLIME_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SLIME_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSnifferGivesSnifferSpawnEggItemStack(TestContext context) { SnifferEntity sniffer = context.spawnEntity(EntityType.SNIFFER, SPAWN_POSITION); ItemStack stack = sniffer.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SNIFFER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SNIFFER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSnowGolemGivesSnowGolemSpawnEggItemStack(TestContext context) { SnowGolemEntity snowGolem = context.spawnEntity(EntityType.SNOW_GOLEM, SPAWN_POSITION); ItemStack stack = snowGolem.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SNOW_GOLEM_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SNOW_GOLEM_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSpiderGivesSpiderSpawnEggItemStack(TestContext context) { SpiderEntity spider = context.spawnEntity(EntityType.SPIDER, SPAWN_POSITION); ItemStack stack = spider.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPIDER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPIDER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSquidGivesSquidSpawnEggItemStack(TestContext context) { SquidEntity squid = context.spawnEntity(EntityType.SQUID, SPAWN_POSITION); ItemStack stack = squid.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SQUID_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SQUID_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnStrayGivesStraySpawnEggItemStack(TestContext context) { StrayEntity stray = context.spawnEntity(EntityType.STRAY, SPAWN_POSITION); ItemStack stack = stray.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.STRAY_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.STRAY_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnStriderGivesStriderSpawnEggItemStack(TestContext context) { StriderEntity strider = context.spawnEntity(EntityType.STRIDER, SPAWN_POSITION); ItemStack stack = strider.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.STRIDER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.STRIDER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnTadpoleGivesTadpoleSpawnEggItemStack(TestContext context) { TadpoleEntity tadpole = context.spawnEntity(EntityType.TADPOLE, SPAWN_POSITION); ItemStack stack = tadpole.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TADPOLE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TADPOLE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnTraderLlamaGivesTraderLlamaSpawnEggItemStack(TestContext context) { TraderLlamaEntity traderLlama = context.spawnEntity(EntityType.TRADER_LLAMA, SPAWN_POSITION); ItemStack stack = traderLlama.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TRADER_LLAMA_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TRADER_LLAMA_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnTropicalFishGivesTropicalFishSpawnEggItemStack(TestContext context) { TropicalFishEntity tropicalFish = context.spawnEntity(EntityType.TROPICAL_FISH, SPAWN_POSITION); ItemStack stack = tropicalFish.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TROPICAL_FISH_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TROPICAL_FISH_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnTurtleGivesTurtleSpawnEggItemStack(TestContext context) { TurtleEntity turtle = context.spawnEntity(EntityType.TURTLE, SPAWN_POSITION); ItemStack stack = turtle.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.TURTLE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.TURTLE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnVexGivesVexSpawnEggItemStack(TestContext context) { VexEntity vex = context.spawnEntity(EntityType.VEX, SPAWN_POSITION); ItemStack stack = vex.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.VEX_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.VEX_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnVillagerGivesVillagerSpawnEggItemStack(TestContext context) { VillagerEntity villager = context.spawnEntity(EntityType.VILLAGER, SPAWN_POSITION); ItemStack stack = villager.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.VILLAGER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.VILLAGER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnVindicatorGivesVindicatorSpawnEggItemStack(TestContext context) { VindicatorEntity vindicator = context.spawnEntity(EntityType.VINDICATOR, SPAWN_POSITION); ItemStack stack = vindicator.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.VINDICATOR_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.VINDICATOR_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWanderingTraderGivesWanderingTraderSpawnEggItemStack(TestContext context) { WanderingTraderEntity wanderingTrader = context.spawnEntity(EntityType.WANDERING_TRADER, SPAWN_POSITION); ItemStack stack = wanderingTrader.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WANDERING_TRADER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WANDERING_TRADER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWardenGivesWardenSpawnEggItemStack(TestContext context) { WardenEntity warden = context.spawnEntity(EntityType.WARDEN, SPAWN_POSITION); ItemStack stack = warden.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WARDEN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WARDEN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWitchGivesWitchSpawnEggItemStack(TestContext context) { WitchEntity witch = context.spawnEntity(EntityType.WITCH, SPAWN_POSITION); ItemStack stack = witch.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WITCH_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WITCH_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWitherGivesWitherSpawnEggItemStack(TestContext context) { WitherEntity wither = context.spawnEntity(EntityType.WITHER, SPAWN_POSITION); ItemStack stack = wither.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WITHER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WITHER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWitherSkeletonGivesWitherSkeletonSpawnEggItemStack(TestContext context) { WitherSkeletonEntity witherSkeleton = context.spawnEntity(EntityType.WITHER_SKELETON, SPAWN_POSITION); ItemStack stack = witherSkeleton.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WITHER_SKELETON_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WITHER_SKELETON_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnWolfGivesWolfSpawnEggItemStack(TestContext context) { WolfEntity wolf = context.spawnEntity(EntityType.WOLF, SPAWN_POSITION); ItemStack stack = wolf.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.WOLF_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.WOLF_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnZoglinGivesZoglinSpawnEggItemStack(TestContext context) { ZoglinEntity zoglin = context.spawnEntity(EntityType.ZOGLIN, SPAWN_POSITION); ItemStack stack = zoglin.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOGLIN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOGLIN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnZombieGivesZombieSpawnEggItemStack(TestContext context) { ZombieEntity zombie = context.spawnEntity(EntityType.ZOMBIE, SPAWN_POSITION); ItemStack stack = zombie.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOMBIE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOMBIE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnZombieHorseGivesZombieHorseSpawnEggItemStack(TestContext context) { ZombieHorseEntity zombieHorse = context.spawnEntity(EntityType.ZOMBIE_HORSE, SPAWN_POSITION); ItemStack stack = zombieHorse.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOMBIE_HORSE_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOMBIE_HORSE_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnZombieVillagerGivesZombieVillagerSpawnEggItemStack(TestContext context) { ZombieVillagerEntity zombieVillager = context.spawnEntity(EntityType.ZOMBIE_VILLAGER, SPAWN_POSITION); ItemStack stack = zombieVillager.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOMBIE_VILLAGER_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOMBIE_VILLAGER_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnZombifiedPiglinGivesZombifiedPiglinSpawnEggItemStack(TestContext context) { ZombifiedPiglinEntity zombifiedPiglin = context.spawnEntity(EntityType.ZOMBIFIED_PIGLIN, SPAWN_POSITION); ItemStack stack = zombifiedPiglin.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ZOMBIFIED_PIGLIN_SPAWN_EGG)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ZOMBIFIED_PIGLIN_SPAWN_EGG) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnAcaciaBoatGivesAcaciaBoatItemStack(TestContext context) { BoatEntity acaciaBoat = context.spawnEntity(EntityType.ACACIA_BOAT, SPAWN_POSITION); ItemStack stack = acaciaBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ACACIA_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ACACIA_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnAcaciaChestBoatGivesAcaciaChestBoatItemStack(TestContext context) { ChestBoatEntity acaciaChestBoat = context.spawnEntity(EntityType.ACACIA_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = acaciaChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.ACACIA_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.ACACIA_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBambooRaftGivesBambooRaftItemStack(TestContext context) { RaftEntity bambooRaft = context.spawnEntity(EntityType.BAMBOO_RAFT, SPAWN_POSITION); ItemStack stack = bambooRaft.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO_RAFT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO_RAFT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBambooChestRaftGivesBambooChestRaftItemStack(TestContext context) { ChestRaftEntity bambooChestRaft = context.spawnEntity(EntityType.BAMBOO_CHEST_RAFT, SPAWN_POSITION); ItemStack stack = bambooChestRaft.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BAMBOO_CHEST_RAFT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BAMBOO_CHEST_RAFT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBirchBoatGivesBirchBoatItemStack(TestContext context) { BoatEntity birchBoat = context.spawnEntity(EntityType.BIRCH_BOAT, SPAWN_POSITION); ItemStack stack = birchBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIRCH_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIRCH_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnBirchChestBoatGivesBirchChestBoatItemStack(TestContext context) { ChestBoatEntity birchChestBoat = context.spawnEntity(EntityType.BIRCH_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = birchChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.BIRCH_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.BIRCH_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCherryBoatGivesCherryBoatItemStack(TestContext context) { BoatEntity cherryBoat = context.spawnEntity(EntityType.CHERRY_BOAT, SPAWN_POSITION); ItemStack stack = cherryBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHERRY_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHERRY_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnCherryChestBoatGivesCherryChestBoatItemStack(TestContext context) { ChestBoatEntity cherryChestBoat = context.spawnEntity(EntityType.CHERRY_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = cherryChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.CHERRY_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.CHERRY_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnDarkOakBoatGivesDarkOakBoatItemStack(TestContext context) { BoatEntity darkOakBoat = context.spawnEntity(EntityType.DARK_OAK_BOAT, SPAWN_POSITION); ItemStack stack = darkOakBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DARK_OAK_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DARK_OAK_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnDarkOakChestBoatGivesDarkOakChestBoatItemStack(TestContext context) { ChestBoatEntity darkOakChestBoat = context.spawnEntity(EntityType.DARK_OAK_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = darkOakChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.DARK_OAK_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.DARK_OAK_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnJungleBoatGivesJungleBoatItemStack(TestContext context) { BoatEntity jungleBoat = context.spawnEntity(EntityType.JUNGLE_BOAT, SPAWN_POSITION); ItemStack stack = jungleBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.JUNGLE_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.JUNGLE_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnJungleChestBoatGivesJungleChestBoatItemStack(TestContext context) { ChestBoatEntity jungleChestBoat = context.spawnEntity(EntityType.JUNGLE_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = jungleChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.JUNGLE_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.JUNGLE_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnMangroveBoatGivesMangroveBoatItemStack(TestContext context) { BoatEntity mangroveBoat = context.spawnEntity(EntityType.MANGROVE_BOAT, SPAWN_POSITION); ItemStack stack = mangroveBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MANGROVE_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MANGROVE_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnMangroveChestBoatGivesMangroveChestBoatItemStack(TestContext context) { ChestBoatEntity mangroveChestBoat = context.spawnEntity(EntityType.MANGROVE_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = mangroveChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.MANGROVE_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.MANGROVE_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnOakBoatGivesOakBoatItemStack(TestContext context) { BoatEntity oakBoat = context.spawnEntity(EntityType.OAK_BOAT, SPAWN_POSITION); ItemStack stack = oakBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OAK_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OAK_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnOakChestBoatGivesOakChestBoatItemStack(TestContext context) { ChestBoatEntity oakChestBoat = context.spawnEntity(EntityType.OAK_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = oakChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.OAK_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.OAK_CHEST_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSpruceBoatGivesSpruceBoatItemStack(TestContext context) { BoatEntity spruceBoat = context.spawnEntity(EntityType.SPRUCE_BOAT, SPAWN_POSITION); ItemStack stack = spruceBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPRUCE_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPRUCE_BOAT) + ); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void getPickStackOnSpruceChestBoatGivesSpruceChestBoatItemStack(TestContext context) { ChestBoatEntity spruceChestBoat = context.spawnEntity(EntityType.SPRUCE_CHEST_BOAT, SPAWN_POSITION); ItemStack stack = spruceChestBoat.getPickBlockStack(); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(stack, ItemKeys.SPRUCE_CHEST_BOAT)); + context.addFinalTask(() -> Assert.itemStack(context, stack) + .is(ItemKeys.SPRUCE_CHEST_BOAT) + ); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/ArmadilloEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/ArmadilloEntityTestSuite.java index 17ded874..a8ba6298 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/ArmadilloEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/ArmadilloEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.ArmadilloEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class ArmadilloEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingSpiderEyeTemptsArmadillo(TestContext context) { ArmadilloEntity armadillo = context.spawnEntity(EntityType.ARMADILLO, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SPIDER_EYE); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.SPIDER_EYE)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = armadillo.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Armadillo was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Armadillo was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Armadillo was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Armadillo was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/AxolotlEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/AxolotlEntityTestSuite.java index 44ac7e82..64e0dd45 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/AxolotlEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/AxolotlEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.AxolotlEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class AxolotlEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingTropicalFishBucketTemptsAxolotl(TestContext context) { AxolotlEntity axolotl = context.spawnEntity(EntityType.AXOLOTL, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TROPICAL_FISH_BUCKET); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.TROPICAL_FISH_BUCKET)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = axolotl.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Axolotl was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Axolotl was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Axolotl was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Axolotl was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/CamelEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/CamelEntityTestSuite.java index fbf88a25..ac785c79 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/CamelEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/CamelEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.CamelEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class CamelEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingCactusTemptsCamel(TestContext context) { CamelEntity camel = context.spawnEntity(EntityType.CAMEL, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CACTUS); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.CACTUS)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = camel.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Camel was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Camel was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Camel was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Camel was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/FrogEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/FrogEntityTestSuite.java index 4d45d647..5e64b892 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/FrogEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/FrogEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.FrogEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class FrogEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingSlimeBallTemptsFrog(TestContext context) { FrogEntity frog = context.spawnEntity(EntityType.FROG, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SLIME_BALL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.SLIME_BALL)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = frog.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Frog was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Frog was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Frog was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Frog was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/GoatEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/GoatEntityTestSuite.java index 45ec4d5a..2665e625 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/GoatEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/GoatEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.GoatEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class GoatEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingWheatTemptsGoat(TestContext context) { GoatEntity goat = context.spawnEntity(EntityType.GOAT, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHEAT); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.WHEAT)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = goat.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Goat was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Goat was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Goat was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Goat was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/MooshroomEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/MooshroomEntityTestSuite.java index d0d4196a..4a91abe8 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/MooshroomEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/MooshroomEntityTestSuite.java @@ -1,14 +1,13 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.MooshroomEntity; 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.ActionResult; import net.minecraft.util.Hand; @@ -18,39 +17,54 @@ public class MooshroomEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void usingFlowerOnBrownMooshroomGivesMooshroomSuspiciousEffects(TestContext context) { MooshroomEntity mooshroom = context.spawnEntity(EntityType.MOOSHROOM, SPAWN_POSITION); - mooshroom.setVariant(MooshroomEntity.Type.BROWN); + mooshroom.setComponent(DataComponentTypes.MOOSHROOM_VARIANT, MooshroomEntity.Variant.BROWN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DANDELION); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = mooshroom.interactMob(player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected interaction with dandelion on brown Mooshroom to be successful"); + context.addFinalTask(() -> { + ServerWorld world = context.getWorld(); + player.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.DANDELION)); + ActionResult dandelionResult = mooshroom.interactMob(player, Hand.MAIN_HAND); + Assert.isTrue( + context, + dandelionResult.isAccepted(), + () -> "Expected interaction with Dandelion on brown Mooshroom to be successful" + ); player.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.BOWL)); ActionResult bowlResult = mooshroom.interactMob(player, Hand.MAIN_HAND); - context.assertTrue(bowlResult.isAccepted(), "Expected interaction with bowl on brown Mooshroom to be successful"); - ItemStack heldStack = player.getStackInHand(Hand.MAIN_HAND); - Assert.itemStackIsOf(heldStack, ItemKeys.SUSPICIOUS_STEW); - Assert.itemStackHasDataComponent(heldStack, DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, - component -> context.assertTrue(!component.effects().isEmpty(), "Expected item stack to have suspicious effects") + Assert.isTrue( + context, + bowlResult.isAccepted(), + () -> "Expected interaction with Bowl on brown Mooshroom to be successful" ); + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .is(ItemKeys.SUSPICIOUS_STEW) + .hasComponent( + DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, + suspiciousStewEffects -> Assert.isFalse( + context, + suspiciousStewEffects.effects().isEmpty(), + () -> "Expected item stack to have suspicious effects" + ) + ); }); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void usingBowlOnMooshroomGivesMushroomStew(TestContext context) { MooshroomEntity mooshroom = context.spawnEntity(EntityType.MOOSHROOM, SPAWN_POSITION); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BOWL); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = mooshroom.interactMob(player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected interaction with bowl on Mooshroom to be successful"); - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.MUSHROOM_STEW); + context.addFinalTask(() -> { + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.BOWL)); + ActionResult bowlResult = mooshroom.interactMob(player, Hand.MAIN_HAND); + Assert.isTrue( + context, + bowlResult.isAccepted(), + () -> "Expected interaction with Bowl on Mooshroom to be successful" + ); + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .is(ItemKeys.MUSHROOM_STEW); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SheepEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SheepEntityTestSuite.java index 42b9d0c4..e13fa0f8 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SheepEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SheepEntityTestSuite.java @@ -1,8 +1,9 @@ package net.errorcraft.itematic.gametest.entity.passive; +import net.errorcraft.itematic.assertion.Assert; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.SheepEntity; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.DyeColor; import net.minecraft.util.math.BlockPos; @@ -10,33 +11,34 @@ public class SheepEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") - @SuppressWarnings("DataFlowIssue") + @GameTest(structure = "itematic:entity.platform") public void breedingRedAndYellowSheepResultsInOrangeSheep(TestContext context) { SheepEntity firstSheep = context.spawnEntity(EntityType.SHEEP, SPAWN_POSITION); firstSheep.setColor(DyeColor.RED); SheepEntity secondSheep = context.spawnEntity(EntityType.SHEEP, SPAWN_POSITION); secondSheep.setColor(DyeColor.YELLOW); SheepEntity childSheep = firstSheep.createChild(context.getWorld(), secondSheep); - context.addInstantFinalTask(() -> { - context.assertTrue(childSheep != null, "Expected child sheep to exist"); - DyeColor color = childSheep.getColor(); - context.assertTrue(color == DyeColor.ORANGE, "Expected child sheep to be orange, got " + color + " instead"); + context.addFinalTask(() -> { + Assert.isNotNull(context, childSheep, "child Sheep"); + Assert.areEqual(context, childSheep.getColor(), DyeColor.ORANGE, "child Sheep"); }); } - @GameTest(templateName = "itematic:entity.platform") - @SuppressWarnings("DataFlowIssue") + @GameTest(structure = "itematic:entity.platform") public void breedingRedAndLimeSheepResultsInEitherColorSheep(TestContext context) { SheepEntity firstSheep = context.spawnEntity(EntityType.SHEEP, SPAWN_POSITION); firstSheep.setColor(DyeColor.RED); SheepEntity secondSheep = context.spawnEntity(EntityType.SHEEP, SPAWN_POSITION); secondSheep.setColor(DyeColor.LIME); SheepEntity childSheep = firstSheep.createChild(context.getWorld(), secondSheep); - context.addInstantFinalTask(() -> { - context.assertTrue(childSheep != null, "Expected child sheep to exist"); + context.addFinalTask(() -> { + Assert.isNotNull(context, childSheep, "child Sheep"); DyeColor color = childSheep.getColor(); - context.assertTrue(color == DyeColor.RED || color == DyeColor.LIME, "Expected child sheep to be red or lime, got " + color + " instead"); + Assert.isTrue( + context, + color == DyeColor.RED || color == DyeColor.LIME, + () -> "Expected child Sheep to be red or lime, got " + color + " instead" + ); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SnifferEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SnifferEntityTestSuite.java index 59ce951c..52bd67bd 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SnifferEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/SnifferEntityTestSuite.java @@ -1,16 +1,14 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ai.brain.MemoryModuleType; import net.minecraft.entity.passive.SnifferEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -20,24 +18,17 @@ public class SnifferEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingTorchflowerSeedsTemptsSniffer(TestContext context) { SnifferEntity sniffer = context.spawnEntity(EntityType.SNIFFER, SPAWN_POSITION); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TORCHFLOWER_SEEDS); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.TORCHFLOWER_SEEDS)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); context.addInstantFinalTask(() -> { Optional temptingPlayer = sniffer.getBrain().getOptionalRegisteredMemory(MemoryModuleType.TEMPTING_PLAYER); - if (temptingPlayer.isEmpty()) { - throw new GameTestException("Sniffer was not tempted by a player"); - } - - if (temptingPlayer.get() != player) { - throw new GameTestException("Sniffer was not tempted by the expected player"); - } + Assert.isTrue(context, temptingPlayer.isPresent(), () -> "Sniffer was not tempted by a Player"); + Assert.areEqual(context, temptingPlayer.get(), player, "Sniffer was not tempted by the expected Player"); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/WolfEntityTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/WolfEntityTestSuite.java index de343d49..d7abb7f5 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/WolfEntityTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/entity/passive/WolfEntityTestSuite.java @@ -1,14 +1,13 @@ package net.errorcraft.itematic.gametest.entity.passive; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.WolfEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -17,42 +16,45 @@ public class WolfEntityTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingBoneTemptsWolf(TestContext context) { WolfEntity wolf = context.spawnEntity(EntityType.WOLF, SPAWN_POSITION); wolf.setTamed(true, true); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BONE); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.BONE)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); - context.addInstantFinalTask(() -> context.assertTrue(wolf.isBegging(), "Expected wolf to be begging")); + context.addInstantFinalTask(() -> Assert.isTrue( + context, + wolf.isBegging(), + () -> "Expected wolf to be begging" + )); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") @SuppressWarnings("removal") public void holdingMeatTemptsWolf(TestContext context) { WolfEntity wolf = context.spawnEntity(EntityType.WOLF, SPAWN_POSITION); wolf.setTamed(true, true); ServerPlayerEntity player = context.createMockCreativeServerPlayerInWorld(); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BEEF); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.BEEF)); TestUtil.setEntityPos(context, player, SPAWN_POSITION); - context.addInstantFinalTask(() -> context.assertTrue(wolf.isBegging(), "Expected wolf to be begging")); + context.addInstantFinalTask(() -> Assert.isTrue( + context, + wolf.isBegging(), + () -> "Expected wolf to be begging" + )); } - @GameTest(templateName = "itematic:entity.platform") + @GameTest(structure = "itematic:entity.platform") public void feedingWolfMeatHealsWolf(TestContext context) { WolfEntity wolf = context.spawnEntity(EntityType.WOLF, SPAWN_POSITION); wolf.setTamed(true, true); context.setHealthLow(wolf); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BEEF); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, context.getWorld().itematic$createStack(ItemKeys.BEEF)); wolf.interactMob(player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> context.assertTrue(wolf.getHealth() > 0.25f, "Expected wolf to be healed")); + context.addFinalTask(() -> Assert.livingEntity(context, wolf) + .hasHealth(health -> health.isGreaterThan(0.25f))); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/BeetrootSoupTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/BeetrootSoupTestSuite.java index e20dc6d6..dbd6bcd2 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/BeetrootSoupTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/BeetrootSoupTestSuite.java @@ -1,29 +1,33 @@ package net.errorcraft.itematic.gametest.item; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; 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 BeetrootSoupTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void eatingBeetrootSoupLeavesBowlAfterConsuming(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); player.getHungerManager().setFoodLevel(0); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BEETROOT_SOUP); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack beetrootSoup = world.itematic$createStack(ItemKeys.BEETROOT_SOUP); + player.setStackInHand(Hand.MAIN_HAND, beetrootSoup); world.spawnEntity(player); context.createTimedTaskRunner() - .createAndAddReported(() -> stack.use(world, player, Hand.MAIN_HAND)) + .createAndAddReported(() -> beetrootSoup.use(world, player, Hand.MAIN_HAND)) .expectMinDurationAndRun( - stack.getMaxUseTime(player), - () -> context.assertTrue(player.getInventory().contains(s -> s.itematic$isOf(ItemKeys.BOWL)), "Expected Player to have a Bowl in their inventory") + beetrootSoup.getMaxUseTime(player), + () -> Assert.isTrue( + context, + player.getInventory().contains(stack -> stack.itematic$isOf(ItemKeys.BOWL)), + () -> "Expected Player to have a Bowl in their inventory" + ) ) .completeIfSuccessful(); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/BowTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/BowTestSuite.java index 5432f4cf..db1c8cd6 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/BowTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/BowTestSuite.java @@ -1,14 +1,14 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.TestUtil; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.RegistryKeys; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -17,11 +17,11 @@ public class BowTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:item.bow.platform") + @GameTest(structure = "itematic:item.bow.platform") public void usingBowWithMultishotSpawnsMultipleArrows(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BOW); - stack.addEnchantment( + ItemStack bow = world.itematic$createStack(ItemKeys.BOW); + bow.addEnchantment( world.getRegistryManager() .getOrThrow(RegistryKeys.ENCHANTMENT) .getOrThrow(Enchantments.MULTISHOT), @@ -30,11 +30,11 @@ public void usingBowWithMultishotSpawnsMultipleArrows(TestContext context) { ItemStack ammunition = world.itematic$createStack(ItemKeys.ARROW); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, bow); player.getInventory().insertStack(ammunition); world.spawnEntity(player); context.createTimedTaskRunner() - .createAndAddReported(() -> stack.use(world, player, Hand.MAIN_HAND)) + .createAndAddReported(() -> bow.use(world, player, Hand.MAIN_HAND)) .expectMinDurationAndRun(20, () -> { player.stopUsingItem(); context.expectEntities(EntityType.ARROW, 3); diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/BrushTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/BrushTestSuite.java index d7a9801a..c5b6835d 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/BrushTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/BrushTestSuite.java @@ -1,11 +1,12 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; 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.util.math.BlockPos; @@ -13,37 +14,52 @@ import net.minecraft.world.GameMode; public class BrushTestSuite { - private static final BlockPos BLOCK_POSITION = new BlockPos(2, 0, 2); + private static final BlockPos BLOCK_POSITION = new BlockPos(1, 2, 1); + private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 0); - @GameTest(templateName = "itematic:item.brush.platform") + @GameTest(structure = "itematic:item.brush.platform") public void usingBrushDoesNotStartBrushing(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BRUSH); + ItemStack brush = world.itematic$createStack(ItemKeys.BRUSH); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> context.assertFalse(player.isUsingItem(), "Expected player to not have started using a Brush")); + player.setStackInHand(Hand.MAIN_HAND, brush); + brush.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.isFalse( + context, + player.isUsingItem(), + () -> "Expected Player not to have started using a Brush" + )); } - @GameTest(templateName = "itematic:item.brush.platform.suspicious_sand") + @GameTest(structure = "itematic:item.brush.platform.suspicious_sand") public void usingBrushOnBlockStartsBrushing(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BRUSH); + ItemStack brush = world.itematic$createStack(ItemKeys.BRUSH); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + TestUtil.setEntityPos(context, player, SPAWN_POSITION); + player.setStackInHand(Hand.MAIN_HAND, brush); world.spawnEntity(player); TestUtil.useBlock(context, BLOCK_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> context.assertTrue(player.isUsingItem(), "Expected player to have started using a Brush")); + context.addFinalTask(() -> Assert.isTrue( + context, + player.isUsingItem(), + () -> "Expected Player to have started using a Brush" + )); } - @GameTest(templateName = "itematic:item.brush.platform.short_grass") + @GameTest(structure = "itematic:item.brush.platform.short_grass") public void usingBrushOnIntangibleBlockDoesNotStartBrushing(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BRUSH); + ItemStack brush = world.itematic$createStack(ItemKeys.BRUSH); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + TestUtil.setEntityPos(context, player, SPAWN_POSITION); + player.setStackInHand(Hand.MAIN_HAND, brush); world.spawnEntity(player); TestUtil.useBlock(context, BLOCK_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> context.assertFalse(player.isUsingItem(), "Expected player to not have started using a Brush")); + context.addFinalTaskWithDuration(1, () -> Assert.isFalse( + context, + player.isUsingItem(), + () -> "Expected Player not to have started using a Brush" + )); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/BundleTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/BundleTestSuite.java index a59524f1..bfa27116 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/BundleTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/BundleTestSuite.java @@ -1,18 +1,17 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.mixin.component.type.BundleContentsComponentAccessor; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.slot.Slot; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.ClickType; import net.minecraft.world.GameMode; @@ -20,7 +19,7 @@ public class BundleTestSuite { private static final int SLOT_INDEX = 0; - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void addingNormalItemToBundleAddsIt(TestContext context) { ServerWorld world = context.getWorld(); ItemStack bundleStack = world.itematic$createStack(ItemKeys.BUNDLE); @@ -29,16 +28,24 @@ public void addingNormalItemToBundleAddsIt(TestContext context) { PlayerInventory inventory = player.getInventory(); inventory.insertStack(SLOT_INDEX, addedStack); Slot slot = new Slot(inventory, SLOT_INDEX, 0, 0); - context.addInstantFinalTask(() -> { - context.assertTrue(bundleStack.onStackClicked(slot, ClickType.RIGHT, player), "Expected right-clicking with Bundle to be successful"); - Assert.itemStackIsEmpty(slot.getStack()); - Assert.itemStackHasDataComponent(bundleStack, DataComponentTypes.BUNDLE_CONTENTS, bundleContents -> { - Assert.itemStackIsOf(bundleContents.get(0), ItemKeys.STICK); - }); + context.addFinalTask(() -> { + Assert.isTrue( + context, + bundleStack.onStackClicked(slot, ClickType.RIGHT, player), + () -> "Expected right clicking on slot with Bundle to be successful" + ); + Assert.itemStack(context, slot.getStack()) + .isEmpty(); + Assert.itemStack(context, bundleStack) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + bundleContents -> Assert.itemStack(context, bundleContents.get(0)) + .is(ItemKeys.STICK) + ); }); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void addingShulkerBoxToBundleRejectsIt(TestContext context) { ServerWorld world = context.getWorld(); ItemStack bundleStack = world.itematic$createStack(ItemKeys.BUNDLE); @@ -47,32 +54,47 @@ public void addingShulkerBoxToBundleRejectsIt(TestContext context) { PlayerInventory inventory = player.getInventory(); inventory.insertStack(SLOT_INDEX, addedStack); Slot slot = new Slot(inventory, SLOT_INDEX, 0, 0); - context.addInstantFinalTask(() -> { - context.assertTrue(bundleStack.onStackClicked(slot, ClickType.RIGHT, player), "Expected right-clicking with Bundle to be successful"); - Assert.itemStackIsNotEmpty(slot.getStack()); - Assert.itemStackHasDataComponent(bundleStack, DataComponentTypes.BUNDLE_CONTENTS, bundleContents -> { - context.assertTrue(bundleContents.isEmpty(), "Expected Bundle to be empty"); - }); + context.addFinalTask(() -> { + Assert.isTrue( + context, + bundleStack.onStackClicked(slot, ClickType.RIGHT, player), + () -> "Expected right clicking on slot with Bundle to be successful" + ); + Assert.itemStack(context, slot.getStack()) + .isNotEmpty(); + Assert.itemStack(context, bundleStack) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + bundleContents -> Assert.isTrue(context, bundleContents.isEmpty(), () -> "Expected Bundle to be empty") + ); }); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void addingBundleToBundleAddsItWithPenalty(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack bundleStack = world.itematic$createStack(ItemKeys.BUNDLE); - ItemStack addedStack = world.itematic$createStack(ItemKeys.BUNDLE); + ItemStack bundle = world.itematic$createStack(ItemKeys.BUNDLE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); PlayerInventory inventory = player.getInventory(); - inventory.insertStack(SLOT_INDEX, addedStack); + inventory.insertStack(SLOT_INDEX, world.itematic$createStack(ItemKeys.BUNDLE)); Slot slot = new Slot(inventory, SLOT_INDEX, 0, 0); - context.addInstantFinalTask(() -> { - context.assertTrue(bundleStack.onStackClicked(slot, ClickType.RIGHT, player), "Expected right-clicking with Bundle to be successful"); - Assert.itemStackIsEmpty(slot.getStack()); - Assert.itemStackHasDataComponent(bundleStack, DataComponentTypes.BUNDLE_CONTENTS, bundleContents -> { - Assert.itemStackIsOf(bundleContents.get(0), ItemKeys.BUNDLE); - }); - context.assertEquals( - TestUtil.getItemBehavior(bundleStack, ItemComponentTypes.ITEM_HOLDER).occupancy(bundleStack), + context.addFinalTask(() -> { + Assert.isTrue( + context, + bundle.onStackClicked(slot, ClickType.RIGHT, player), + () -> "Expected right clicking on slot with Bundle to be successful" + ); + Assert.itemStack(context, slot.getStack()) + .isEmpty(); + Assert.itemStack(context, bundle) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + bundleContents -> Assert.itemStack(context, bundleContents.get(0)) + .is(ItemKeys.BUNDLE) + ); + Assert.areEqual( + context, + TestUtil.getItemBehavior(context, bundle, ItemComponentTypes.ITEM_HOLDER).occupancy(bundle), BundleContentsComponentAccessor.nestedBundleOccupancy(), "occupancy" ); diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/CompassTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/CompassTestSuite.java index 9d4b1eef..85887bd2 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/CompassTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/CompassTestSuite.java @@ -1,13 +1,13 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; 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.util.math.BlockPos; @@ -20,51 +20,68 @@ public class CompassTestSuite { private static final BlockPos LODESTONE_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:item.compass.platform.lodestone") + @GameTest(structure = "itematic:item.compass.platform.lodestone") public void usingCompassOnLodestoneSetsTrackedDataFromBlock(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.COMPASS); + ItemStack compass = world.itematic$createStack(ItemKeys.COMPASS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, compass); world.spawnEntity(player); - ItemStack resultStack = TestUtil.useStackOnBlockInside(context, player, stack, LODESTONE_POSITION, Direction.UP) + ItemStack resultStack = TestUtil.useStackOnBlockInside(context, player, compass, LODESTONE_POSITION, Direction.UP) .orElseThrow(); - context.addInstantFinalTask(() -> { - Assert.itemStackHasDataComponent(resultStack, DataComponentTypes.LODESTONE_TRACKER, lodestoneTracker -> { - context.assertTrue(lodestoneTracker.tracked(), "Expected Lodestone Compass to be tracked"); + context.addFinalTask(() -> Assert.itemStack(context, resultStack) + .hasComponent(DataComponentTypes.LODESTONE_TRACKER, lodestoneTracker -> { + Assert.isTrue( + context, + lodestoneTracker.tracked(), + () -> "Expected Lodestone Compass to be tracked" + ); Optional target = lodestoneTracker.target(); - context.assertTrue(target.isPresent(), "Expected Lodestone Compass to have a target"); - context.assertEquals( - target.orElseThrow().dimension(), + Assert.isTrue( + context, + target.isPresent(), + () -> "Expected Lodestone Compass to have a target" + ); + Assert.areEqual( + context, + target.get().dimension(), context.getWorld().getRegistryKey(), "Lodestone dimension" ); - context.assertEquals( - target.orElseThrow().pos(), + Assert.areEqual( + context, + target.get().pos(), context.getAbsolutePos(LODESTONE_POSITION), "Lodestone position" ); - }); - }); + })); } - @GameTest(templateName = "itematic:item.compass.platform.lodestone") + @GameTest(structure = "itematic:item.compass.platform.lodestone") public void destroyingLodestoneRemovesTrackedDataFromLodestoneCompass(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.COMPASS); + ItemStack compass = world.itematic$createStack(ItemKeys.COMPASS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, compass); world.spawnEntity(player); - ItemStack resultStack = TestUtil.useStackOnBlockInside(context, player, stack, LODESTONE_POSITION, Direction.UP) + ItemStack resultStack = TestUtil.useStackOnBlockInside(context, player, compass, LODESTONE_POSITION, Direction.UP) .orElseThrow(); context.removeBlock(LODESTONE_POSITION); context.createTimedTaskRunner() - .expectMinDurationAndRun(1, () -> { - Assert.itemStackHasDataComponent(resultStack, DataComponentTypes.LODESTONE_TRACKER, lodestoneTracker -> { - context.assertTrue(lodestoneTracker.tracked(), "Expected Lodestone Compass to be tracked"); - context.assertTrue(lodestoneTracker.target().isEmpty(), "Expected Lodestone Compass not to have a target"); - }); - }) + .expectMinDurationAndRun(1, () -> Assert.itemStack(context, resultStack) + .hasComponent(DataComponentTypes.LODESTONE_TRACKER, lodestoneTracker -> { + Assert.isTrue( + context, + lodestoneTracker.tracked(), + () -> "Expected Lodestone Compass to be tracked" + ); + Assert.isTrue( + context, + lodestoneTracker.target().isEmpty(), + () -> "Expected Lodestone Compass not to have a target" + ); + }) + ) .completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/CrossbowTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/CrossbowTestSuite.java index 807858c9..f93ed78e 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/CrossbowTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/CrossbowTestSuite.java @@ -1,43 +1,45 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.registry.RegistryKeys; 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 CrossbowTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void usingCrossbowWithInfinityChargesArrowFromInventoryButDoesNotConsumeTheArrow(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CROSSBOW); - stack.addEnchantment( - world.getRegistryManager() - .getOrThrow(RegistryKeys.ENCHANTMENT) - .getOrThrow(Enchantments.INFINITY), - 1 - ); - ItemStack ammunition = world.itematic$createStack(ItemKeys.ARROW); + ItemStack crossbow = TestUtil.createItemStackWithEnchantment(world, ItemKeys.CROSSBOW, Enchantments.INFINITY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); - player.getInventory().insertStack(ammunition); + player.setStackInHand(Hand.MAIN_HAND, crossbow); + player.getInventory().insertStack(world.itematic$createStack(ItemKeys.ARROW)); world.spawnEntity(player); context.createTimedTaskRunner() - .createAndAddReported(() -> stack.use(world, player, Hand.MAIN_HAND)) - .expectMinDurationAndRun(stack.getMaxUseTime(player), () -> { + .createAndAddReported(() -> crossbow.use(world, player, Hand.MAIN_HAND)) + .expectMinDurationAndRun(crossbow.getMaxUseTime(player), () -> { player.stopUsingItem(); - Assert.itemStackHasDataComponent(player.getStackInHand(Hand.MAIN_HAND), DataComponentTypes.CHARGED_PROJECTILES, - component -> context.assertTrue(component.itematic$contains(ItemKeys.ARROW), "Expected item stack to have an Arrow as a charged projectile") + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .hasComponent( + DataComponentTypes.CHARGED_PROJECTILES, + component -> Assert.isTrue( + context, + component.itematic$contains(ItemKeys.ARROW), + () -> "Expected item stack to have an Arrow as a charged projectile" + ) + ); + Assert.isTrue( + context, + player.getInventory().contains(s -> s.itematic$isOf(ItemKeys.ARROW)), + () -> "Expected Player to have an Arrow in their inventory" ); - context.assertTrue(player.getInventory().contains(s -> s.itematic$isOf(ItemKeys.ARROW)), "Expected player to have an Arrow in their inventory"); }) .completeIfSuccessful(); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/FishingRodTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/FishingRodTestSuite.java index ac72172a..29a2775e 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/FishingRodTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/FishingRodTestSuite.java @@ -1,36 +1,44 @@ package net.errorcraft.itematic.gametest.item; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.FishingBobberEntity; import net.minecraft.entity.projectile.ProjectileEntity; 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 FishingRodTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingFishingRodCastsFishingRod(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FISHING_ROD); - player.setStackInHand(Hand.MAIN_HAND, stack); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> context.assertTrue(player.fishHook != null, "Expected player to have cast a fishing rod")); + ItemStack fishingRod = world.itematic$createStack(ItemKeys.FISHING_ROD); + player.setStackInHand(Hand.MAIN_HAND, fishingRod); + fishingRod.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.isTrue( + context, + player.fishHook != null, + () -> "Expected Player to have cast a Fishing Rod" + )); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingCastFishingRodRetractsFishingRod(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FISHING_ROD); - player.setStackInHand(Hand.MAIN_HAND, stack); - ProjectileEntity.spawn(new FishingBobberEntity(player, world, 0, 0), world, stack); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> context.assertTrue(player.fishHook == null, "Expected player to have retracted a fishing rod")); + ItemStack fishingRod = world.itematic$createStack(ItemKeys.FISHING_ROD); + player.setStackInHand(Hand.MAIN_HAND, fishingRod); + ProjectileEntity.spawn(new FishingBobberEntity(player, world, 0, 0), world, fishingRod); + fishingRod.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.isTrue( + context, + player.fishHook == null, + () -> "Expected Player to have retracted a Fishing Rod" + )); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/FlowerPotItemTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/FlowerPotItemTestSuite.java index b33ebe48..d9e0921a 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/FlowerPotItemTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/FlowerPotItemTestSuite.java @@ -1,13 +1,13 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; 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.util.math.BlockPos; @@ -17,1363 +17,1567 @@ public class FlowerPotItemTestSuite { private static final BlockPos FLOWER_POT_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingOakSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SAPLING); + ItemStack oakSapling = world.itematic$createStack(ItemKeys.OAK_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_OAK_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, oakSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, oakSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_OAK_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingOakSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SAPLING); + ItemStack oakSapling = world.itematic$createStack(ItemKeys.OAK_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.OAK_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, oakSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.OAK_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingSpruceSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SPRUCE_SAPLING); + ItemStack spruceSapling = world.itematic$createStack(ItemKeys.SPRUCE_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, spruceSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_SPRUCE_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, spruceSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, spruceSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_SPRUCE_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingSpruceSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SPRUCE_SAPLING); + ItemStack spruceSapling = world.itematic$createStack(ItemKeys.SPRUCE_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, spruceSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.SPRUCE_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, spruceSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.SPRUCE_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingBirchSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BIRCH_SAPLING); + ItemStack birchSapling = world.itematic$createStack(ItemKeys.BIRCH_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, birchSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_BIRCH_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, birchSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, birchSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_BIRCH_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingBirchSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BIRCH_SAPLING); + ItemStack birchSapling = world.itematic$createStack(ItemKeys.BIRCH_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, birchSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.BIRCH_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, birchSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BIRCH_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingJungleSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.JUNGLE_SAPLING); + ItemStack jungleSapling = world.itematic$createStack(ItemKeys.JUNGLE_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, jungleSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_JUNGLE_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, jungleSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, jungleSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_JUNGLE_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingJungleSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.JUNGLE_SAPLING); + ItemStack jungleSapling = world.itematic$createStack(ItemKeys.JUNGLE_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, jungleSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.JUNGLE_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, jungleSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.JUNGLE_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingAcaciaSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ACACIA_SAPLING); + ItemStack acaciaSapling = world.itematic$createStack(ItemKeys.ACACIA_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, acaciaSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_ACACIA_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, acaciaSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, acaciaSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_ACACIA_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingAcaciaSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ACACIA_SAPLING); + ItemStack acaciaSapling = world.itematic$createStack(ItemKeys.ACACIA_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, acaciaSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.ACACIA_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, acaciaSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ACACIA_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingCherrySaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CHERRY_SAPLING); + ItemStack cherrySapling = world.itematic$createStack(ItemKeys.CHERRY_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cherrySapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_CHERRY_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cherrySapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, cherrySapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_CHERRY_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingCherrySaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CHERRY_SAPLING); + ItemStack cherrySapling = world.itematic$createStack(ItemKeys.CHERRY_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cherrySapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.CHERRY_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cherrySapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CHERRY_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingDarkOakSaplingOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DARK_OAK_SAPLING); + ItemStack darkOakSapling = world.itematic$createStack(ItemKeys.DARK_OAK_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, darkOakSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_DARK_OAK_SAPLING, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, darkOakSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, darkOakSapling) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_DARK_OAK_SAPLING); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingDarkOakSaplingOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DARK_OAK_SAPLING); + ItemStack darkOakSapling = world.itematic$createStack(ItemKeys.DARK_OAK_SAPLING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, darkOakSapling); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.DARK_OAK_SAPLING); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, darkOakSapling, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DARK_OAK_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingCrimsonFungusOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CRIMSON_FUNGUS); + ItemStack crimsonFungus = world.itematic$createStack(ItemKeys.CRIMSON_FUNGUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crimsonFungus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_CRIMSON_FUNGUS, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, crimsonFungus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, crimsonFungus) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_CRIMSON_FUNGUS); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingCrimsonFungusOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CRIMSON_FUNGUS); + ItemStack crimsonFungus = world.itematic$createStack(ItemKeys.CRIMSON_FUNGUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crimsonFungus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.CRIMSON_FUNGUS); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, crimsonFungus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CRIMSON_FUNGUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingWarpedFungusOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WARPED_FUNGUS); + ItemStack warpedFungus = world.itematic$createStack(ItemKeys.WARPED_FUNGUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, warpedFungus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_WARPED_FUNGUS, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, warpedFungus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, warpedFungus) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_WARPED_FUNGUS); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingWarpedFungusOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WARPED_FUNGUS); + ItemStack warpedFungus = world.itematic$createStack(ItemKeys.WARPED_FUNGUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, warpedFungus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.WARPED_FUNGUS); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, warpedFungus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WARPED_FUNGUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingCrimsonRootsOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CRIMSON_ROOTS); + ItemStack crimsonRoots = world.itematic$createStack(ItemKeys.CRIMSON_ROOTS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crimsonRoots); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_CRIMSON_ROOTS, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, crimsonRoots, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, crimsonRoots) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_CRIMSON_ROOTS); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingCrimsonRootsOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CRIMSON_ROOTS); + ItemStack crimsonRoots = world.itematic$createStack(ItemKeys.CRIMSON_ROOTS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crimsonRoots); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.CRIMSON_ROOTS); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, crimsonRoots, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CRIMSON_ROOTS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingWarpedRootsOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WARPED_ROOTS); + ItemStack warpedRoots = world.itematic$createStack(ItemKeys.WARPED_ROOTS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, warpedRoots); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_WARPED_ROOTS, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, warpedRoots, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, warpedRoots) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_WARPED_ROOTS); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingWarpedRootsOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WARPED_ROOTS); + ItemStack warpedRoots = world.itematic$createStack(ItemKeys.WARPED_ROOTS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, warpedRoots); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.WARPED_ROOTS); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, warpedRoots, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WARPED_ROOTS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingAzaleaBushOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.AZALEA); + ItemStack azalea = world.itematic$createStack(ItemKeys.AZALEA); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, azalea); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_AZALEA_BUSH, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, azalea, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, azalea) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_AZALEA_BUSH); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingAzaleaBushOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.AZALEA); + ItemStack azalea = world.itematic$createStack(ItemKeys.AZALEA); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, azalea); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.AZALEA); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, azalea, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.AZALEA); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingFloweringAzaleaBushOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FLOWERING_AZALEA); + ItemStack floweringAzalea = world.itematic$createStack(ItemKeys.FLOWERING_AZALEA); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, floweringAzalea); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_FLOWERING_AZALEA_BUSH, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, floweringAzalea, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, floweringAzalea) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_FLOWERING_AZALEA_BUSH); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingFloweringAzaleaBushOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FLOWERING_AZALEA); + ItemStack floweringAzalea = world.itematic$createStack(ItemKeys.FLOWERING_AZALEA); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, floweringAzalea); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.FLOWERING_AZALEA); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, floweringAzalea, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.FLOWERING_AZALEA); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingMangrovePropaguleOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.MANGROVE_PROPAGULE); + ItemStack mangrovePropagule = world.itematic$createStack(ItemKeys.MANGROVE_PROPAGULE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, mangrovePropagule); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_MANGROVE_PROPAGULE, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, mangrovePropagule, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, mangrovePropagule) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_MANGROVE_PROPAGULE); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingMangrovePropaguleOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.MANGROVE_PROPAGULE); + ItemStack mangrovePropagule = world.itematic$createStack(ItemKeys.MANGROVE_PROPAGULE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, mangrovePropagule); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.MANGROVE_PROPAGULE); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, mangrovePropagule, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.MANGROVE_PROPAGULE); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingCactusOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CACTUS); + ItemStack cactus = world.itematic$createStack(ItemKeys.CACTUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cactus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_CACTUS, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cactus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, cactus) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_CACTUS); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingCactusOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CACTUS); + ItemStack cactus = world.itematic$createStack(ItemKeys.CACTUS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cactus); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.CACTUS); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cactus, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CACTUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingDeadBushOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DEAD_BUSH); + ItemStack deadBush = world.itematic$createStack(ItemKeys.DEAD_BUSH); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, deadBush); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_DEAD_BUSH, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, deadBush, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, deadBush) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_DEAD_BUSH); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingDeadBushOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DEAD_BUSH); + ItemStack deadBush = world.itematic$createStack(ItemKeys.DEAD_BUSH); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, deadBush); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.DEAD_BUSH); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, deadBush, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DEAD_BUSH); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingBambooOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BAMBOO); + ItemStack bamboo = world.itematic$createStack(ItemKeys.BAMBOO); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, bamboo); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_BAMBOO, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, bamboo, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, bamboo) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_BAMBOO); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingBambooOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BAMBOO); + ItemStack bamboo = world.itematic$createStack(ItemKeys.BAMBOO); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, bamboo); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.BAMBOO); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, bamboo, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BAMBOO); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingFernOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FERN); + ItemStack fern = world.itematic$createStack(ItemKeys.FERN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, fern); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_FERN, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, fern, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, fern) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_FERN); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingFernOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.FERN); + ItemStack fern = world.itematic$createStack(ItemKeys.FERN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, fern); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.FERN); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, fern, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.FERN); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingDandelionOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DANDELION); + ItemStack dandelion = world.itematic$createStack(ItemKeys.DANDELION); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, dandelion); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_DANDELION, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, dandelion, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, dandelion) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_DANDELION); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingDandelionOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.DANDELION); + ItemStack dandelion = world.itematic$createStack(ItemKeys.DANDELION); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, dandelion); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.DANDELION); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, dandelion, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DANDELION); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingPoppyOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.POPPY); + ItemStack poppy = world.itematic$createStack(ItemKeys.POPPY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, poppy); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, poppy, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, poppy) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_dandelion") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_dandelion") public void usingPoppyOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.POPPY); + ItemStack poppy = world.itematic$createStack(ItemKeys.POPPY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, poppy); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.POPPY); - context.expectBlock(Blocks.POTTED_DANDELION, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, poppy, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.POPPY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_DANDELION); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingBlueOrchidOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BLUE_ORCHID); + ItemStack blueOrchid = world.itematic$createStack(ItemKeys.BLUE_ORCHID); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, blueOrchid); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_BLUE_ORCHID, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, blueOrchid, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, blueOrchid) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_BLUE_ORCHID); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingBlueOrchidOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BLUE_ORCHID); + ItemStack blueOrchid = world.itematic$createStack(ItemKeys.BLUE_ORCHID); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, blueOrchid); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.BLUE_ORCHID); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, blueOrchid, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BLUE_ORCHID); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingAlliumOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ALLIUM); + ItemStack allium = world.itematic$createStack(ItemKeys.ALLIUM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, allium); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_ALLIUM, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, allium, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, allium) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_ALLIUM); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingAlliumOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ALLIUM); + ItemStack allium = world.itematic$createStack(ItemKeys.ALLIUM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, allium); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.ALLIUM); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, allium, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ALLIUM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingAzureBluetOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.AZURE_BLUET); + ItemStack azureBluet = world.itematic$createStack(ItemKeys.AZURE_BLUET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, azureBluet); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_AZURE_BLUET, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, azureBluet, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, azureBluet) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_AZURE_BLUET); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingAzureBluetOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.AZURE_BLUET); + ItemStack azureBluet = world.itematic$createStack(ItemKeys.AZURE_BLUET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, azureBluet); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.AZURE_BLUET); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, azureBluet, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.AZURE_BLUET); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingRedTulipOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.RED_TULIP); + ItemStack redTulip = world.itematic$createStack(ItemKeys.RED_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, redTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_RED_TULIP, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, redTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, redTulip) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_RED_TULIP); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingRedTulipOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.RED_TULIP); + ItemStack redTulip = world.itematic$createStack(ItemKeys.RED_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, redTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.RED_TULIP); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, redTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.RED_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingOrangeTulipOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ORANGE_TULIP); + ItemStack orangeTulip = world.itematic$createStack(ItemKeys.ORANGE_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, orangeTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_ORANGE_TULIP, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, orangeTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, orangeTulip) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_ORANGE_TULIP); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingOrangeTulipOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ORANGE_TULIP); + ItemStack orangeTulip = world.itematic$createStack(ItemKeys.ORANGE_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, orangeTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.ORANGE_TULIP); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, orangeTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ORANGE_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingWhiteTulipOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_TULIP); + ItemStack whiteTulip = world.itematic$createStack(ItemKeys.WHITE_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, whiteTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_WHITE_TULIP, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, whiteTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, whiteTulip) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_WHITE_TULIP); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingWhiteTulipOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WHITE_TULIP); + ItemStack whiteTulip = world.itematic$createStack(ItemKeys.WHITE_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, whiteTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.WHITE_TULIP); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, whiteTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WHITE_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingPinkTulipOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PINK_TULIP); + ItemStack pinkTulip = world.itematic$createStack(ItemKeys.PINK_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, pinkTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_PINK_TULIP, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, pinkTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, pinkTulip) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_PINK_TULIP); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingPinkTulipOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PINK_TULIP); + ItemStack pinkTulip = world.itematic$createStack(ItemKeys.PINK_TULIP); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, pinkTulip); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.PINK_TULIP); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, pinkTulip, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.PINK_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingOxeyeDaisyOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OXEYE_DAISY); + ItemStack oxeyeDaisy = world.itematic$createStack(ItemKeys.OXEYE_DAISY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oxeyeDaisy); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_OXEYE_DAISY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, oxeyeDaisy, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, oxeyeDaisy) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_OXEYE_DAISY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingOxeyeDaisyOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OXEYE_DAISY); + ItemStack oxeyeDaisy = world.itematic$createStack(ItemKeys.OXEYE_DAISY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oxeyeDaisy); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.OXEYE_DAISY); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, oxeyeDaisy, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.OXEYE_DAISY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingCornflowerOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CORNFLOWER); + ItemStack cornflower = world.itematic$createStack(ItemKeys.CORNFLOWER); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cornflower); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_CORNFLOWER, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cornflower, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, cornflower) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_CORNFLOWER); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingCornflowerOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CORNFLOWER); + ItemStack cornflower = world.itematic$createStack(ItemKeys.CORNFLOWER); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, cornflower); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.CORNFLOWER); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, cornflower, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CORNFLOWER); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingLilyOfTheValleyOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LILY_OF_THE_VALLEY); + ItemStack lilyOfTheValley = world.itematic$createStack(ItemKeys.LILY_OF_THE_VALLEY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, lilyOfTheValley); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_LILY_OF_THE_VALLEY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, lilyOfTheValley, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, lilyOfTheValley) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_LILY_OF_THE_VALLEY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingLilyOfTheValleyOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LILY_OF_THE_VALLEY); + ItemStack lilyOfTheValley = world.itematic$createStack(ItemKeys.LILY_OF_THE_VALLEY); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, lilyOfTheValley); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.LILY_OF_THE_VALLEY); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, lilyOfTheValley, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.LILY_OF_THE_VALLEY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingWitherRoseOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WITHER_ROSE); + ItemStack witherRose = world.itematic$createStack(ItemKeys.WITHER_ROSE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, witherRose); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_WITHER_ROSE, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, witherRose, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, witherRose) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_WITHER_ROSE); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingWitherRoseOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WITHER_ROSE); + ItemStack witherRose = world.itematic$createStack(ItemKeys.WITHER_ROSE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, witherRose); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.WITHER_ROSE); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, witherRose, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WITHER_ROSE); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingTorchflowerOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TORCHFLOWER); + ItemStack torchflower = world.itematic$createStack(ItemKeys.TORCHFLOWER); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, torchflower); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_TORCHFLOWER, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, torchflower, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, torchflower) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_TORCHFLOWER); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingTorchflowerOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TORCHFLOWER); + ItemStack torchflower = world.itematic$createStack(ItemKeys.TORCHFLOWER); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, torchflower); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.TORCHFLOWER); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, torchflower, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.TORCHFLOWER); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingRedMushroomOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.RED_MUSHROOM); + ItemStack redMushroom = world.itematic$createStack(ItemKeys.RED_MUSHROOM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, redMushroom); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_RED_MUSHROOM, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, redMushroom, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, redMushroom) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_RED_MUSHROOM); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingRedMushroomOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.RED_MUSHROOM); + ItemStack redMushroom = world.itematic$createStack(ItemKeys.RED_MUSHROOM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, redMushroom); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.RED_MUSHROOM); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, redMushroom, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.RED_MUSHROOM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.flower_pot") + @GameTest(structure = "itematic:item.flower_pot.platform.flower_pot") public void usingBrownMushroomOnFlowerPotReplacesFlowerPot(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BROWN_MUSHROOM); + ItemStack brownMushroom = world.itematic$createStack(ItemKeys.BROWN_MUSHROOM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, brownMushroom); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsEmpty(stack); - context.expectBlock(Blocks.POTTED_BROWN_MUSHROOM, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, brownMushroom, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, brownMushroom) + .isEmpty(); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_BROWN_MUSHROOM); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingBrownMushroomOnPottedFlowerPotDoesNotReplacePottedFlower(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BROWN_MUSHROOM); + ItemStack brownMushroom = world.itematic$createStack(ItemKeys.BROWN_MUSHROOM); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, brownMushroom); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, FLOWER_POT_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.BROWN_MUSHROOM); - context.expectBlock(Blocks.POTTED_POPPY, FLOWER_POT_POSITION); + TestUtil.useStackOnBlockInside(context, player, brownMushroom, FLOWER_POT_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BROWN_MUSHROOM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.POTTED_POPPY); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_oak_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_oak_sapling") public void usingHandOnPottedOakSaplingEmptiesPottedOakSaplingAndGivesOakSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.OAK_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.OAK_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_spruce_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_spruce_sapling") public void usingHandOnPottedSpruceSaplingEmptiesPottedSpruceSaplingAndGivesSpruceSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.SPRUCE_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.SPRUCE_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_birch_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_birch_sapling") public void usingHandOnPottedBirchSaplingEmptiesPottedBirchSaplingAndGivesBirchSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.BIRCH_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BIRCH_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_jungle_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_jungle_sapling") public void usingHandOnPottedJungleSaplingEmptiesPottedJungleSaplingAndGivesJungleSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.JUNGLE_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.JUNGLE_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_acacia_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_acacia_sapling") public void usingHandOnPottedAcaciaSaplingEmptiesPottedAcaciaSaplingAndGivesAcaciaSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.ACACIA_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ACACIA_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_cherry_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_cherry_sapling") public void usingHandOnPottedCherrySaplingEmptiesPottedCherrySaplingAndGivesCherrySapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.CHERRY_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CHERRY_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_dark_oak_sapling") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_dark_oak_sapling") public void usingHandOnPottedDarkOakSaplingEmptiesPottedDarkOakSaplingAndGivesDarkOakSapling(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.DARK_OAK_SAPLING); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DARK_OAK_SAPLING); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_crimson_fungus") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_crimson_fungus") public void usingHandOnPottedCrimsonFungusEmptiesPottedCrimsonFungusAndGivesCrimsonFungus(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.CRIMSON_FUNGUS); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CRIMSON_FUNGUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_warped_fungus") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_warped_fungus") public void usingHandOnPottedWarpedFungusEmptiesPottedWarpedFungusAndGivesWarpedFungus(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.WARPED_FUNGUS); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WARPED_FUNGUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_crimson_roots") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_crimson_roots") public void usingHandOnPottedCrimsonRootsEmptiesPottedCrimsonRootsAndGivesCrimsonRoots(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.CRIMSON_ROOTS); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CRIMSON_ROOTS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_warped_roots") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_warped_roots") public void usingHandOnPottedWarpedRootsEmptiesPottedWarpedRootsAndGivesWarpedRoots(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.WARPED_ROOTS); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WARPED_ROOTS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_azalea_bush") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_azalea_bush") public void usingHandOnPottedAzaleaEmptiesPottedAzaleaAndGivesAzalea(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.AZALEA); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.AZALEA); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_flowering_azalea_bush") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_flowering_azalea_bush") public void usingHandOnPottedFloweringAzaleaEmptiesPottedFloweringAzaleaAndGivesFloweringAzalea(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.FLOWERING_AZALEA); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.FLOWERING_AZALEA); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_mangrove_propagule") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_mangrove_propagule") public void usingHandOnPottedMangrovePropaguleEmptiesPottedMangrovePropaguleAndGivesMangrovePropagule(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.MANGROVE_PROPAGULE); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.MANGROVE_PROPAGULE); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_cactus") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_cactus") public void usingHandOnPottedCactusEmptiesPottedCactusAndGivesCactus(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.CACTUS); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CACTUS); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_dead_bush") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_dead_bush") public void usingHandOnPottedDeadBushEmptiesPottedDeadBushAndGivesDeadBush(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.DEAD_BUSH); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DEAD_BUSH); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_bamboo") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_bamboo") public void usingHandOnPottedBambooEmptiesPottedBambooAndGivesBamboo(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.BAMBOO); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BAMBOO); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_fern") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_fern") public void usingHandOnPottedFernEmptiesPottedFernAndGivesFern(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.FERN); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.FERN); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_dandelion") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_dandelion") public void usingHandOnPottedDandelionEmptiesPottedDandelionAndGivesDandelion(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.DANDELION); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.DANDELION); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_poppy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_poppy") public void usingHandOnPottedPoppyEmptiesPottedPoppyAndGivesPoppy(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.POPPY); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.POPPY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_blue_orchid") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_blue_orchid") public void usingHandOnPottedBlueOrchidEmptiesPottedBlueOrchidAndGivesBlueOrchid(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.BLUE_ORCHID); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BLUE_ORCHID); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_allium") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_allium") public void usingHandOnPottedAlliumEmptiesPottedAlliumAndGivesAllium(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.ALLIUM); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ALLIUM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_azure_bluet") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_azure_bluet") public void usingHandOnPottedAzureBluetEmptiesPottedAzureBluetAndGivesAzureBluet(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.AZURE_BLUET); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.AZURE_BLUET); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_red_tulip") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_red_tulip") public void usingHandOnPottedRedTulipEmptiesPottedRedTulipAndGivesRedTulip(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.RED_TULIP); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.RED_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_orange_tulip") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_orange_tulip") public void usingHandOnPottedOrangeTulipEmptiesPottedOrangeTulipAndGivesOrangeTulip(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.ORANGE_TULIP); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.ORANGE_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_white_tulip") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_white_tulip") public void usingHandOnPottedWhiteTulipEmptiesPottedWhiteTulipAndGivesWhiteTulip(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.WHITE_TULIP); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WHITE_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_pink_tulip") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_pink_tulip") public void usingHandOnPottedPinkTulipEmptiesPottedPinkTulipAndGivesPinkTulip(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.PINK_TULIP); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.PINK_TULIP); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_oxeye_daisy") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_oxeye_daisy") public void usingHandOnPottedOxeyeDaisyEmptiesPottedOxeyeDaisyAndGivesOxeyeDaisy(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.OXEYE_DAISY); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.OXEYE_DAISY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_cornflower") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_cornflower") public void usingHandOnPottedCornflowerEmptiesPottedCornflowerAndGivesCornflower(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.CORNFLOWER); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.CORNFLOWER); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_lily_of_the_valley") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_lily_of_the_valley") public void usingHandOnPottedLilyOfTheValleyEmptiesPottedLilyOfTheValleyAndGivesLilyOfTheValley(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.LILY_OF_THE_VALLEY); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.LILY_OF_THE_VALLEY); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_wither_rose") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_wither_rose") public void usingHandOnPottedWitherRoseEmptiesPottedWitherRoseAndGivesWitherRose(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.WITHER_ROSE); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.WITHER_ROSE); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_torchflower") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_torchflower") public void usingHandOnPottedTorchflowerEmptiesPottedTorchflowerAndGivesTorchflower(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.TORCHFLOWER); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.TORCHFLOWER); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_red_mushroom") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_red_mushroom") public void usingHandOnPottedRedMushroomEmptiesPottedRedMushroomAndGivesRedMushroom(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.RED_MUSHROOM); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.RED_MUSHROOM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } - @GameTest(templateName = "itematic:item.flower_pot.platform.potted_brown_mushroom") + @GameTest(structure = "itematic:item.flower_pot.platform.potted_brown_mushroom") public void usingHandOnPottedBrownMushroomEmptiesPottedBrownMushroomAndGivesBrownMushroom(TestContext context) { ServerWorld world = context.getWorld(); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); world.spawnEntity(player); TestUtil.useBlock(context, FLOWER_POT_POSITION, player, Direction.UP); - context.addInstantFinalTask(() -> { - Assert.itemStackIsOf(player.getMainHandStack(), ItemKeys.BROWN_MUSHROOM); - context.expectBlock(Blocks.FLOWER_POT, FLOWER_POT_POSITION); + context.addFinalTask(() -> { + Assert.itemStack(context, player.getMainHandStack()) + .is(ItemKeys.BROWN_MUSHROOM); + Assert.blockState(context, FLOWER_POT_POSITION) + .is(Blocks.FLOWER_POT); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/HoneyBottleTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/HoneyBottleTestSuite.java index 8ea63d9f..465307f3 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/HoneyBottleTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/HoneyBottleTestSuite.java @@ -1,33 +1,33 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.effect.StatusEffectInstance; 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 HoneyBottleTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void consumingHoneyBottleRemovesPoisonStatusEffect(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); player.getHungerManager().setFoodLevel(0); player.addStatusEffect(new StatusEffectInstance(StatusEffects.POISON, StatusEffectInstance.INFINITE)); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.HONEY_BOTTLE); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack honeyBottle = world.itematic$createStack(ItemKeys.HONEY_BOTTLE); + player.setStackInHand(Hand.MAIN_HAND, honeyBottle); world.spawnEntity(player); context.createTimedTaskRunner() - .createAndAddReported(() -> stack.use(world, player, Hand.MAIN_HAND)) + .createAndAddReported(() -> honeyBottle.use(world, player, Hand.MAIN_HAND)) .expectMinDurationAndRun( - stack.getMaxUseTime(player) + 1, - () -> Assert.entityDoesNotHaveStatusEffect(player, StatusEffects.POISON) + honeyBottle.getMaxUseTime(player) + 1, + () -> Assert.livingEntity(context, player) + .doesNotHaveEffect(StatusEffects.POISON) ) .completeIfSuccessful(); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/LeadTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/LeadTestSuite.java index 55f4bd27..7e0370bb 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/LeadTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/LeadTestSuite.java @@ -1,14 +1,15 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.HorseEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.BoatEntity; 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.ActionResult; import net.minecraft.util.Hand; @@ -18,33 +19,49 @@ public class LeadTestSuite { private static final BlockPos PLACED_ENTITY_POSITION = new BlockPos(1, 1, 0); - @GameTest(templateName = "itematic:item.lead.platform") + @GameTest(structure = "itematic:item.lead.platform") public void usingLeadOnHorseLeashesHorse(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LEAD); + ItemStack lead = world.itematic$createStack(ItemKeys.LEAD); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, lead); world.spawnEntity(player); HorseEntity horse = TestUtil.createEntityAt(context, EntityType.HORSE, PLACED_ENTITY_POSITION, entity -> {}); - context.addInstantFinalTask(() -> { + context.addFinalTask(() -> { ActionResult result = horse.interact(player, Hand.MAIN_HAND); - context.assertTrue(result.isAccepted(), "Expected interaction with Horse to be successful"); - context.assertTrue(horse.isLeashed(), "Expected Horse to be leashed"); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected interaction with Horse to be successful" + ); + Assert.isTrue( + context, + horse.isLeashed(), + () -> "Expected Horse to be leashed" + ); }); } - @GameTest(templateName = "itematic:item.lead.platform") + @GameTest(structure = "itematic:item.lead.platform") public void usingLeadOnBoatLeashesBoat(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LEAD); + ItemStack lead = world.itematic$createStack(ItemKeys.LEAD); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, lead); world.spawnEntity(player); BoatEntity boat = TestUtil.createEntityAt(context, EntityType.OAK_BOAT, PLACED_ENTITY_POSITION, entity -> {}); - context.addInstantFinalTask(() -> { + context.addFinalTask(() -> { ActionResult result = boat.interact(player, Hand.MAIN_HAND); - context.assertTrue(result.isAccepted(), "Expected interaction with Oak Boat to be successful"); - context.assertTrue(boat.isLeashed(), "Expected Oak Boat to be leashed"); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected interaction with Oak Boat to be successful" + ); + Assert.isTrue( + context, + boat.isLeashed(), + () -> "Expected Oak Boat to be leashed" + ); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/SignTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/SignTestSuite.java index 31ebf408..668bdb9f 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/SignTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/SignTestSuite.java @@ -1,8 +1,9 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.component.DataComponentTypes; @@ -12,8 +13,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -25,77 +24,91 @@ public class SignTestSuite { private static final BlockPos PLACED_BLOCK_POSITION = GROUND_POSITION.add(0, 1, 0); private static final BlockPos ABOVE_PLACED_BLOCK_POSITION = PLACED_BLOCK_POSITION.add(0, 1, 0); - @GameTest(templateName = "itematic:item.sign.platform") + @GameTest(structure = "itematic:item.sign.platform") public void placingSignOpensSignMenu(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SIGN); + ItemStack oakSign = world.itematic$createStack(ItemKeys.OAK_SIGN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - context.expectBlock(Blocks.OAK_SIGN, PLACED_BLOCK_POSITION); - Assert.blockEntityExists(context, PLACED_BLOCK_POSITION, BlockEntityType.SIGN, blockEntity -> { - if (!player.getUuid().equals(blockEntity.getEditor())) { - throw new GameTestException("Sign menu was not opened by the player"); - } - }); + TestUtil.useStackOnBlockInside(context, player, oakSign, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_SIGN); + Assert.blockEntity(context, PLACED_BLOCK_POSITION, BlockEntityType.SIGN, + blockEntity -> Assert.isTrue( + context, + player.getUuid().equals(blockEntity.getEditor()), + () -> "Sign menu was not opened by the Player" + ) + ); }); } - @GameTest(templateName = "itematic:item.sign.platform") + @GameTest(structure = "itematic:item.sign.platform") + @SuppressWarnings("DataFlowIssue") public void placingSignWithBlockEntityDataDoesNotOpenSignMenu(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SIGN); - NbtComponent.set(DataComponentTypes.BLOCK_ENTITY_DATA, stack, nbt -> nbt.putString(Entity.ID_KEY, Registries.BLOCK_ENTITY_TYPE.getId(BlockEntityType.SIGN).toString())); + ItemStack oakSign = world.itematic$createStack(ItemKeys.OAK_SIGN); + NbtComponent.set(DataComponentTypes.BLOCK_ENTITY_DATA, oakSign, nbt -> nbt.putString(Entity.ID_KEY, Registries.BLOCK_ENTITY_TYPE.getId(BlockEntityType.SIGN).toString())); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - context.expectBlock(Blocks.OAK_SIGN, PLACED_BLOCK_POSITION); - Assert.blockEntityExists(context, PLACED_BLOCK_POSITION, BlockEntityType.SIGN, blockEntity -> { - if (player.getUuid().equals(blockEntity.getEditor())) { - throw new GameTestException("Sign menu was opened by the player"); - } - }); + TestUtil.useStackOnBlockInside(context, player, oakSign, GROUND_POSITION, Direction.UP); + context.addFinalTaskWithDuration(1, () -> { + Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_SIGN); + Assert.blockEntity(context, PLACED_BLOCK_POSITION, BlockEntityType.SIGN, + blockEntity -> Assert.isFalse( + context, + player.getUuid().equals(blockEntity.getEditor()), + () -> "Sign menu was opened by the Player" + ) + ); }); } - @GameTest(templateName = "itematic:item.sign.platform.ceiling") + @GameTest(structure = "itematic:item.sign.platform.ceiling") public void placingHangingSignOpensSignMenu(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); + ItemStack oakHangingSign = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakHangingSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); - context.addInstantFinalTask(() -> { - context.expectBlock(Blocks.OAK_HANGING_SIGN, PLACED_BLOCK_POSITION); - Assert.blockEntityExists(context, PLACED_BLOCK_POSITION, BlockEntityType.HANGING_SIGN, blockEntity -> { - if (!player.getUuid().equals(blockEntity.getEditor())) { - throw new GameTestException("Sign menu was not opened by the player"); - } - }); + TestUtil.useStackOnBlockInside(context, player, oakHangingSign, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); + context.addFinalTask(() -> { + Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_HANGING_SIGN); + Assert.blockEntity(context, PLACED_BLOCK_POSITION, BlockEntityType.HANGING_SIGN, + blockEntity -> Assert.isTrue( + context, + player.getUuid().equals(blockEntity.getEditor()), + () -> "Sign menu was not opened by the Player" + ) + ); }); } - @GameTest(templateName = "itematic:item.sign.platform.ceiling") + @GameTest(structure = "itematic:item.sign.platform.ceiling") + @SuppressWarnings("DataFlowIssue") public void placingHangingSignWithBlockEntityDataDoesNotOpenSignMenu(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); - NbtComponent.set(DataComponentTypes.BLOCK_ENTITY_DATA, stack, nbt -> nbt.putString(Entity.ID_KEY, Registries.BLOCK_ENTITY_TYPE.getId(BlockEntityType.SIGN).toString())); + ItemStack oakHangingSign = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); + NbtComponent.set(DataComponentTypes.BLOCK_ENTITY_DATA, oakHangingSign, nbt -> nbt.putString(Entity.ID_KEY, Registries.BLOCK_ENTITY_TYPE.getId(BlockEntityType.SIGN).toString())); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakHangingSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); - context.addInstantFinalTask(() -> { - context.expectBlock(Blocks.OAK_HANGING_SIGN, PLACED_BLOCK_POSITION); - Assert.blockEntityExists(context, PLACED_BLOCK_POSITION, BlockEntityType.HANGING_SIGN, blockEntity -> { - if (player.getUuid().equals(blockEntity.getEditor())) { - throw new GameTestException("Sign menu was opened by the player"); - } - }); + TestUtil.useStackOnBlockInside(context, player, oakHangingSign, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); + context.addFinalTaskWithDuration(1, () -> { + Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_HANGING_SIGN); + Assert.blockEntity(context, PLACED_BLOCK_POSITION, BlockEntityType.HANGING_SIGN, + blockEntity -> Assert.isFalse( + context, + player.getUuid().equals(blockEntity.getEditor()), + () -> "Sign menu was opened by the Player" + ) + ); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java index 2fc0a359..922b2152 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/TotemOfUndyingTestSuite.java @@ -1,31 +1,30 @@ package net.errorcraft.itematic.gametest.item; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; +import net.errorcraft.itematic.assertion.ItemStackAssert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; 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) + @GameTest 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); + ItemStack totemOfUndying = world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING); + player.setStackInHand(Hand.MAIN_HAND, totemOfUndying); player.damage(world, 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)); - }); + context.addFinalTask(() -> Assert.livingEntity(context, player) + .hasHealth(health -> health.equals(1.0f)) + .hasEffect(StatusEffects.REGENERATION, 1) + .hasEffect(StatusEffects.ABSORPTION, 1) + .hasEffect(StatusEffects.FIRE_RESISTANCE, 0) + .hasStackInHand(Hand.MAIN_HAND, ItemStackAssert::isEmpty)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BlockItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BlockItemComponentTestSuite.java index b5b97399..ed9ff439 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BlockItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BlockItemComponentTestSuite.java @@ -1,7 +1,9 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; import net.minecraft.block.ScaffoldingBlock; import net.minecraft.block.enums.DoubleBlockHalf; @@ -10,7 +12,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Properties; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -22,201 +23,218 @@ public class BlockItemComponentTestSuite { private static final BlockPos PLACED_BLOCK_POSITION = GROUND_POSITION.add(0, 1, 0); private static final BlockPos ABOVE_PLACED_BLOCK_POSITION = PLACED_BLOCK_POSITION.add(0, 1, 0); private static final BlockPos WALL_POSITION = GROUND_POSITION.add(0, 1, 1); - private static final int BEYOND_MAX_SCAFFOLDING_DISTANCE = ScaffoldingBlock.MAX_DISTANCE + 1; private static final BlockPos HORIZONTAL_SCAFFOLDING_OFFSET = PLACED_BLOCK_POSITION.add(0, 0, 1); private static final BlockPos VERTICAL_SCAFFOLDING_OFFSET = PLACED_BLOCK_POSITION.add(0, 1, 0); private static final BlockPos HORIZONTAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET = PLACED_BLOCK_POSITION.add(0, 0, BEYOND_MAX_SCAFFOLDING_DISTANCE); private static final BlockPos VERTICAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET = PLACED_BLOCK_POSITION.add(0, BEYOND_MAX_SCAFFOLDING_DISTANCE, 0); - @GameTest(templateName = "itematic:item.component.block.platform") + @GameTest(structure = "itematic:item.component.block.platform") public void usingStoneOnGroundPlacesStone(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.STONE); + ItemStack stone = world.itematic$createStack(ItemKeys.STONE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, stone); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.STONE, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, stone, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.STONE)); } - @GameTest(templateName = "itematic:item.component.block.platform") + @GameTest(structure = "itematic:item.component.block.platform") public void usingOakSlabOnGroundPlacesOakSlab(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SLAB); + ItemStack oakSlab = world.itematic$createStack(ItemKeys.OAK_SLAB); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSlab); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.checkBlockState(PLACED_BLOCK_POSITION, state -> state.get(Properties.SLAB_TYPE) == SlabType.BOTTOM, () -> "Expected placed oak slab to be of bottom type")); + TestUtil.useStackOnBlockInside(context, player, oakSlab, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .hasProperty(Properties.SLAB_TYPE, SlabType.BOTTOM, () -> "Expected placed Oak Slab to be of bottom type")); } - @GameTest(templateName = "itematic:item.component.block.oak_slab.lower") + @GameTest(structure = "itematic:item.component.block.oak_slab.lower") public void usingOakSlabOnLowerOakSlabPlacesDoubleOakSlab(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SLAB); + ItemStack oakSlab = world.itematic$createStack(ItemKeys.OAK_SLAB); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSlab); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.DOWN); - context.addInstantFinalTask(() -> context.checkBlockState(PLACED_BLOCK_POSITION, state -> state.get(Properties.SLAB_TYPE) == SlabType.DOUBLE, () -> "Expected placed oak slab to be of double type")); + TestUtil.useStackOnBlockInside(context, player, oakSlab, PLACED_BLOCK_POSITION, Direction.DOWN); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .hasProperty(Properties.SLAB_TYPE, SlabType.DOUBLE, () -> "Expected placed Oak Slab to be of double type")); } - @GameTest(templateName = "itematic:item.component.block.oak_slab.upper") + @GameTest(structure = "itematic:item.component.block.oak_slab.upper") public void usingOakSlabOnUpperOakSlabPlacesDoubleOakSlab(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_SLAB); + ItemStack oakSlab = world.itematic$createStack(ItemKeys.OAK_SLAB); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakSlab); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.DOWN); - context.addInstantFinalTask(() -> context.checkBlockState(PLACED_BLOCK_POSITION, state -> state.get(Properties.SLAB_TYPE) == SlabType.DOUBLE, () -> "Expected placed oak slab to be of double type")); + TestUtil.useStackOnBlockInside(context, player, oakSlab, PLACED_BLOCK_POSITION, Direction.DOWN); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .hasProperty(Properties.SLAB_TYPE, SlabType.DOUBLE, () -> "Expected placed Oak Slab to be of double type")); } - @GameTest(templateName = "itematic:item.component.block.platform.grass_block") + @GameTest(structure = "itematic:item.component.block.platform.grass_block") public void usingTallGrassOnGroundPlacesTallGrass(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TALL_GRASS); + ItemStack tallGrass = world.itematic$createStack(ItemKeys.TALL_GRASS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, tallGrass); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> { - context.checkBlockState(PLACED_BLOCK_POSITION, state -> state.get(Properties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER, () -> "Expected lower half of tall grass to be placed"); - context.checkBlockState(ABOVE_PLACED_BLOCK_POSITION, state -> state.get(Properties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER, () -> "Expected upper half of tall grass to be placed"); + TestUtil.useStackOnBlockInside(context, player, tallGrass, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> { + Assert.blockState(context, PLACED_BLOCK_POSITION) + .hasProperty(Properties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER, () -> "Expected lower half of Tall Grass to be placed"); + Assert.blockState(context, ABOVE_PLACED_BLOCK_POSITION) + .hasProperty(Properties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER, () -> "Expected upper half of Tall Grass to be placed"); }); } - @GameTest(templateName = "itematic:item.component.block.platform.grass_block.blocked_off_above") + @GameTest(structure = "itematic:item.component.block.platform.grass_block.blocked_off_above") public void usingTallGrassOnGroundWhileBlockedOffDoesNotPlaceTallGrass(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TALL_GRASS); + ItemStack tallGrass = world.itematic$createStack(ItemKeys.TALL_GRASS); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, tallGrass); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.dontExpectBlock(Blocks.TALL_GRASS, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, tallGrass, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .isNot(Blocks.TALL_GRASS)); } - @GameTest(templateName = "itematic:item.component.block.platform") + @GameTest(structure = "itematic:item.component.block.platform") public void usingSkeletonSkullOnGroundPlacesSkeletonSkull(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SKELETON_SKULL); + ItemStack skeletonSkull = world.itematic$createStack(ItemKeys.SKELETON_SKULL); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, skeletonSkull); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SKELETON_SKULL, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, skeletonSkull, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.SKELETON_SKULL)); } - @GameTest(templateName = "itematic:item.component.block.platform.wall") + @GameTest(structure = "itematic:item.component.block.platform.wall") public void usingSkeletonSkullOnWallPlacesSkeletonWallSkull(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SKELETON_SKULL); + ItemStack skeletonSkull = world.itematic$createStack(ItemKeys.SKELETON_SKULL); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, skeletonSkull); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, WALL_POSITION, Direction.NORTH); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SKELETON_WALL_SKULL, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, skeletonSkull, WALL_POSITION, Direction.NORTH); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.SKELETON_WALL_SKULL)); } - @GameTest(templateName = "itematic:item.component.block.platform.ceiling") + @GameTest(structure = "itematic:item.component.block.platform.ceiling") public void usingOakHangingSignOnCeilingPlacesOakHangingSign(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); + ItemStack oakHangingSign = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakHangingSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.OAK_HANGING_SIGN, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, oakHangingSign, ABOVE_PLACED_BLOCK_POSITION, Direction.DOWN); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_HANGING_SIGN)); } - @GameTest(templateName = "itematic:item.component.block.platform.wall") + @GameTest(structure = "itematic:item.component.block.platform.wall") public void usingOakHangingSignOnWallPlacesOakWallHangingSign(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); + ItemStack oakHangingSign = world.itematic$createStack(ItemKeys.OAK_HANGING_SIGN); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakHangingSign); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, WALL_POSITION, Direction.NORTH); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.OAK_WALL_HANGING_SIGN, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, oakHangingSign, WALL_POSITION, Direction.NORTH); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.OAK_WALL_HANGING_SIGN)); } - @GameTest(templateName = "itematic:item.component.block.platform") + @GameTest(structure = "itematic:item.component.block.platform") public void usingScaffoldingOnGroundPlacesScaffolding(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SCAFFOLDING, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .is(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.scaffolding.single_block") + @GameTest(structure = "itematic:item.component.block.scaffolding.single_block") public void usingScaffoldingOnTopFaceOfScaffoldingPlacesScaffoldingHorizontally(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SCAFFOLDING, HORIZONTAL_SCAFFOLDING_OFFSET)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, PLACED_BLOCK_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, HORIZONTAL_SCAFFOLDING_OFFSET) + .is(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.scaffolding.single_block") + @GameTest(structure = "itematic:item.component.block.scaffolding.single_block") public void usingScaffoldingOnTopFaceOfBlockBelowScaffoldingPlacesScaffoldingHorizontally(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); player.setYaw(0.0f); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SCAFFOLDING, HORIZONTAL_SCAFFOLDING_OFFSET)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, HORIZONTAL_SCAFFOLDING_OFFSET) + .is(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.scaffolding.single_block") + @GameTest(structure = "itematic:item.component.block.scaffolding.single_block") public void usingScaffoldingOnSideFaceOfScaffoldingPlacesScaffoldingVertically(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.SOUTH); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SCAFFOLDING, VERTICAL_SCAFFOLDING_OFFSET)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, PLACED_BLOCK_POSITION, Direction.SOUTH); + context.addFinalTask(() -> Assert.blockState(context, VERTICAL_SCAFFOLDING_OFFSET) + .is(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.scaffolding.horizontal.max_distance") + @GameTest(structure = "itematic:item.component.block.scaffolding.horizontal.max_distance") public void usingScaffoldingForHorizontalPlacementFailsAfterReachingMaxDistance(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.dontExpectBlock(Blocks.SCAFFOLDING, HORIZONTAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, PLACED_BLOCK_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, HORIZONTAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET) + .isNot(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.scaffolding.vertical.max_distance") + @GameTest(structure = "itematic:item.component.block.scaffolding.vertical.max_distance") public void usingScaffoldingForVerticalPlacementIgnoresMaxDistance(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SCAFFOLDING); + ItemStack scaffolding = world.itematic$createStack(ItemKeys.SCAFFOLDING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, scaffolding); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, PLACED_BLOCK_POSITION, Direction.SOUTH); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.SCAFFOLDING, VERTICAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET)); + TestUtil.useStackOnBlockInside(context, player, scaffolding, PLACED_BLOCK_POSITION, Direction.SOUTH); + context.addFinalTask(() -> Assert.blockState(context, VERTICAL_SCAFFOLDING_BEYOND_MAX_DISTANCE_OFFSET) + .is(Blocks.SCAFFOLDING)); } - @GameTest(templateName = "itematic:item.component.block.platform") + @GameTest(structure = "itematic:item.component.block.platform") public void usingCommandBlockInSurvivalModeOnGroundDoesNotPlaceCommandBlock(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.COMMAND_BLOCK); + ItemStack commandBlock = world.itematic$createStack(ItemKeys.COMMAND_BLOCK); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, commandBlock); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.dontExpectBlock(Blocks.COMMAND_BLOCK, PLACED_BLOCK_POSITION)); + TestUtil.useStackOnBlockInside(context, player, commandBlock, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> Assert.blockState(context, PLACED_BLOCK_POSITION) + .isNot(Blocks.COMMAND_BLOCK)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BucketItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BucketItemComponentTestSuite.java index 04152659..e7d4adb8 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BucketItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/BucketItemComponentTestSuite.java @@ -1,8 +1,9 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; import net.minecraft.command.argument.EntityAnchorArgumentType; import net.minecraft.entity.EntityType; @@ -10,8 +11,6 @@ import net.minecraft.fluid.Fluids; import net.minecraft.item.ItemStack; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -24,84 +23,95 @@ public class BucketItemComponentTestSuite { private static final BlockPos FACE_POSITION = new BlockPos(1, 1, 1); private static final BlockPos PLACED_POSITION = FACE_POSITION; - @GameTest(templateName = "itematic:item.component.bucket.platform.water") + @GameTest(structure = "itematic:item.component.bucket.platform.water") public void usingBucketOnWaterTakesWaterAndGivesWaterBucket(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET); + ItemStack bucket = world.itematic$createStack(ItemKeys.BUCKET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION))); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, bucket); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - Assert.fluidIsOf(context, Fluids.EMPTY, PLACED_POSITION); - if (!(result instanceof ActionResult.Success successResult)) { - throw new GameTestException("Expected bucket usage to be successful"); - } - - Assert.itemStackIsOf(successResult.getNewHandStack(), ItemKeys.WATER_BUCKET); + ActionResult result = bucket.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> { + Assert.fluidState(context, PLACED_POSITION) + .is(Fluids.EMPTY); + Assert.isInstance( + context, + result, + ActionResult.Success.class, + () -> "Expected Bucket usage to be successful", + success -> Assert.itemStack(context, success.getNewHandStack()) + .is(ItemKeys.WATER_BUCKET) + ); }); } - @GameTest(templateName = "itematic:item.component.bucket.platform.powder_snow") + @GameTest(structure = "itematic:item.component.bucket.platform.powder_snow") public void usingBucketOnPowderSnowTakesWaterAndGivesPowderSnowBucket(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET); + ItemStack bucket = world.itematic$createStack(ItemKeys.BUCKET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION))); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, bucket); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - Assert.fluidIsOf(context, Fluids.EMPTY, PLACED_POSITION); - if (!(result instanceof ActionResult.Success successResult)) { - throw new GameTestException("Expected bucket usage to be successful"); - } - - Assert.itemStackIsOf(successResult.getNewHandStack(), ItemKeys.POWDER_SNOW_BUCKET); + ActionResult result = bucket.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> { + Assert.fluidState(context, PLACED_POSITION) + .is(Fluids.EMPTY); + Assert.isInstance( + context, + result, + ActionResult.Success.class, + () -> "Expected Bucket usage to be successful", + success -> Assert.itemStack(context, success.getNewHandStack()) + .is(ItemKeys.POWDER_SNOW_BUCKET) + ); }); } - @GameTest(templateName = "itematic:item.component.bucket.platform") + @GameTest(structure = "itematic:item.component.bucket.platform") public void usingWaterBucketOnGroundPlacesWater(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.WATER_BUCKET); + ItemStack waterBucket = world.itematic$createStack(ItemKeys.WATER_BUCKET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION))); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, waterBucket); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> Assert.fluidIsOf(context, Fluids.WATER, PLACED_POSITION)); + waterBucket.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.fluidState(context, PLACED_POSITION) + .is(Fluids.WATER)); } - @GameTest(templateName = "itematic:item.component.bucket.platform") + @GameTest(structure = "itematic:item.component.bucket.platform") public void usingPowderSnowBucketOnGroundPlacesPowderSnow(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET); + ItemStack powderSnowBucket = world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION))); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, powderSnowBucket); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> context.expectBlock(Blocks.POWDER_SNOW, PLACED_POSITION)); + powderSnowBucket.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.blockState(context, PLACED_POSITION) + .is(Blocks.POWDER_SNOW)); } - @GameTest(templateName = "itematic:item.component.bucket.platform") + @GameTest(structure = "itematic:item.component.bucket.platform") public void usingPufferfishBucketOnGroundPlacesWaterAndPufferfish(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PUFFERFISH_BUCKET); + ItemStack pufferfishBucket = world.itematic$createStack(ItemKeys.PUFFERFISH_BUCKET); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION))); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, pufferfishBucket); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - Assert.fluidIsOf(context, Fluids.WATER, PLACED_POSITION); + pufferfishBucket.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> { + Assert.fluidState(context, PLACED_POSITION) + .is(Fluids.WATER); context.expectEntityAt(EntityType.PUFFERFISH, PLACED_POSITION); }); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ConsumableItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ConsumableItemComponentTestSuite.java index 97ceb116..ef818e0c 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ConsumableItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ConsumableItemComponentTestSuite.java @@ -1,31 +1,31 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.component.ItematicDataComponentTypes; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; 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 ConsumableItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void consumingHoneyBottleReplacesItemWithGlassBottle(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); player.getHungerManager().setFoodLevel(0); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.HONEY_BOTTLE); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack honeyBottle = world.itematic$createStack(ItemKeys.HONEY_BOTTLE); + player.setStackInHand(Hand.MAIN_HAND, honeyBottle); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); - context.createTimedTaskRunner().expectMinDurationAndRun( - TestUtil.getDataComponent(stack, ItematicDataComponentTypes.USE_DURATION).ticks(stack, player), - () -> Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.GLASS_BOTTLE) - ).completeIfSuccessful(); + context.createTimedTaskRunner() + .createAndAddReported(() -> honeyBottle.use(world, player, Hand.MAIN_HAND)) + .expectMinDurationAndRun( + honeyBottle.getMaxUseTime(player), + () -> Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .is(ItemKeys.GLASS_BOTTLE) + ) + .completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EntityItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EntityItemComponentTestSuite.java index 501a7910..5d037db5 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EntityItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EntityItemComponentTestSuite.java @@ -1,12 +1,12 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.TestUtil; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; 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.util.math.BlockPos; @@ -17,25 +17,25 @@ public class EntityItemComponentTestSuite { private static final BlockPos GROUND_POSITION = new BlockPos(1, 0, 0); private static final BlockPos PLACED_ENTITY_POSITION = GROUND_POSITION.add(0, 1, 0); - @GameTest(templateName = "itematic:item.component.entity.platform") + @GameTest(structure = "itematic:item.component.entity.platform") public void usingOakBoatOnGroundPlacesOakBoat(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.OAK_BOAT); + ItemStack oakBoat = world.itematic$createStack(ItemKeys.OAK_BOAT); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, oakBoat); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectEntityAt(EntityType.OAK_BOAT, PLACED_ENTITY_POSITION)); + TestUtil.useStackOnBlockInside(context, player, oakBoat, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> context.expectEntityAt(EntityType.OAK_BOAT, PLACED_ENTITY_POSITION)); } - @GameTest(templateName = "itematic:item.component.entity.platform") + @GameTest(structure = "itematic:item.component.entity.platform") public void usingPigSpawnEggOnGroundPlacesPig(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); + ItemStack pigSpawnEgg = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, pigSpawnEgg); world.spawnEntity(player); - TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP); - context.addInstantFinalTask(() -> context.expectEntityAt(EntityType.PIG, PLACED_ENTITY_POSITION)); + TestUtil.useStackOnBlockInside(context, player, pigSpawnEgg, GROUND_POSITION, Direction.UP); + context.addFinalTask(() -> context.expectEntityAt(EntityType.PIG, PLACED_ENTITY_POSITION)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EquipmentItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EquipmentItemComponentTestSuite.java index 854f11e2..42fb3591 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EquipmentItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/EquipmentItemComponentTestSuite.java @@ -1,60 +1,66 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.EquippableComponent; import net.minecraft.entity.EquipmentSlot; 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.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.world.GameMode; public class EquipmentItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingItemEquipsStack(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LEATHER_HELMET); - player.setStackInHand(Hand.MAIN_HAND, stack); - EquippableComponent equippable = TestUtil.getDataComponent(stack, DataComponentTypes.EQUIPPABLE); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> Assert.itemStackIsOf(player.getEquippedStack(equippable.slot()), ItemKeys.LEATHER_HELMET)); + ItemStack leatherHelmet = world.itematic$createStack(ItemKeys.LEATHER_HELMET); + player.setStackInHand(Hand.MAIN_HAND, leatherHelmet); + EquippableComponent equippable = TestUtil.getDataComponent(context, leatherHelmet, DataComponentTypes.EQUIPPABLE); + leatherHelmet.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.itemStack(context, player.getEquippedStack(equippable.slot())) + .is(ItemKeys.LEATHER_HELMET) + ); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingItemThatIsNotSwappableDoesNotEquipStack(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SHIELD); - player.setStackInHand(Hand.MAIN_HAND, stack); - EquippableComponent equippable = TestUtil.getDataComponent(stack, DataComponentTypes.EQUIPPABLE); - stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> Assert.itemStackIsEmpty(player.getEquippedStack(equippable.slot()))); + ItemStack shield = world.itematic$createStack(ItemKeys.SHIELD); + player.setStackInHand(Hand.MAIN_HAND, shield); + EquippableComponent equippable = TestUtil.getDataComponent(context, shield, DataComponentTypes.EQUIPPABLE); + shield.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.itemStack(context, player.getEquippedStack(equippable.slot())) + .isEmpty() + ); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingItemWithAlreadyEquippedStackSwapsStacks(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); player.equipStack(EquipmentSlot.HEAD, world.itematic$createStack(ItemKeys.IRON_HELMET)); - ItemStack stack = world.itematic$createStack(ItemKeys.LEATHER_HELMET); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - if (!(result instanceof ActionResult.Success successResult)) { - throw new GameTestException("Expected equipment usage to be successful"); - } - - Assert.itemStackIsOf(player.getEquippedStack(EquipmentSlot.HEAD), ItemKeys.LEATHER_HELMET); - Assert.itemStackIsOf(successResult.getNewHandStack(), ItemKeys.IRON_HELMET); + ItemStack leatherHelmet = world.itematic$createStack(ItemKeys.LEATHER_HELMET); + player.setStackInHand(Hand.MAIN_HAND, leatherHelmet); + context.addFinalTask(() -> { + ActionResult result = leatherHelmet.use(world, player, Hand.MAIN_HAND); + Assert.isInstance( + context, + result, + ActionResult.Success.class, + () -> "Expected equipment item usage to be successful", + success -> Assert.itemStack(context, success.getNewHandStack()) + .is(ItemKeys.IRON_HELMET) + ); + Assert.itemStack(context, player.getEquippedStack(EquipmentSlot.HEAD)) + .is(ItemKeys.LEATHER_HELMET); }); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/FoodItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/FoodItemComponentTestSuite.java index 67b24653..e59d257e 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/FoodItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/FoodItemComponentTestSuite.java @@ -1,18 +1,16 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.component.ItematicDataComponentTypes; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.FoodItemComponent; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.SuspiciousStewEffectsComponent; 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; @@ -20,46 +18,43 @@ import java.util.List; public class FoodItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void eatingFoodItemAddsNutrition(TestContext context) { + ServerWorld world = context.getWorld(); + ItemStack apple = world.itematic$createStack(ItemKeys.APPLE); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); player.getHungerManager().setFoodLevel(0); - ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.APPLE); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, apple); world.spawnEntity(player); - FoodItemComponent component = TestUtil.getItemBehavior(stack, ItemComponentTypes.FOOD); - stack.use(world, player, Hand.MAIN_HAND); + FoodItemComponent component = TestUtil.getItemBehavior(context, apple, ItemComponentTypes.FOOD); + apple.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - TestUtil.getDataComponent(stack, ItematicDataComponentTypes.USE_DURATION).ticks(stack, player), + apple.getMaxUseTime(player), () -> { - Assert.itemStackIsEmpty(player.getStackInHand(Hand.MAIN_HAND)); - Assert.areIntsEqual( - player.getHungerManager().getFoodLevel(), - component.nutrition(), - (value, expected) -> "Expected nutrition to be " + expected + ", got " + value + " instead" - ); + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .isEmpty(); + Assert.ints(context, player.getHungerManager().getFoodLevel(), "nutrition") + .equals(component.nutrition()); } ).completeIfSuccessful(); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void eatingSuspiciousStewAddsSuspiciousEffects(TestContext context) { - PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SUSPICIOUS_STEW); - List effects = TestUtil.getItemBehavior(world.itematic$createStack(ItemKeys.DANDELION), ItemComponentTypes.SUSPICIOUS_EFFECT_INGREDIENT) + ItemStack suspiciousStew = world.itematic$createStack(ItemKeys.SUSPICIOUS_STEW); + List effects = TestUtil.getItemBehavior(context, world.itematic$createStack(ItemKeys.DANDELION), ItemComponentTypes.SUSPICIOUS_EFFECT_INGREDIENT) .effects(); - stack.set(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, new SuspiciousStewEffectsComponent(effects)); - player.setStackInHand(Hand.MAIN_HAND, stack); + suspiciousStew.set(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, new SuspiciousStewEffectsComponent(effects)); + PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); + player.setStackInHand(Hand.MAIN_HAND, suspiciousStew); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); + suspiciousStew.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - TestUtil.getDataComponent(stack, ItematicDataComponentTypes.USE_DURATION).ticks(stack, player), - () -> { - Assert.forAll(effects, effect -> context.expectEntityHasEffect(player, effect.effect(), effect.createStatusEffectInstance().getAmplifier())); - Assert.itemStackIsOf(player.getStackInHand(Hand.MAIN_HAND), ItemKeys.BOWL); - } + suspiciousStew.getMaxUseTime(player), + () -> Assert.livingEntity(context, player) + .hasEffects(effects) + .hasStackInHand(Hand.MAIN_HAND, stack -> stack.is(ItemKeys.BOWL)) ).completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ImmuneToDamageItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ImmuneToDamageItemComponentTestSuite.java index c8f552e6..149ebd7b 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ImmuneToDamageItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ImmuneToDamageItemComponentTestSuite.java @@ -1,56 +1,74 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.TestUtil; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.ItemEntity; -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.math.BlockPos; public class ImmuneToDamageItemComponentTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void explodingNetherStarKeepsItemAlive(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.NETHER_STAR); - ItemEntity item = new ItemEntity(world, 0.0d, 0.0d, 0.0d, stack); - TestUtil.spawnEntity(context, item, SPAWN_POSITION); - item.damage(world, world.getDamageSources().explosion(null), Float.MAX_VALUE); - context.addInstantFinalTask(() -> context.expectEntity(EntityType.ITEM)); + ItemEntity netherStar = new ItemEntity( + world, + 0.0d, + 0.0d, + 0.0d, + world.itematic$createStack(ItemKeys.NETHER_STAR) + ); + TestUtil.spawnEntity(context, netherStar, SPAWN_POSITION); + netherStar.damage(world, world.getDamageSources().explosion(null), Float.MAX_VALUE); + context.addFinalTask(() -> context.expectEntity(EntityType.ITEM)); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void explodingStickDestroysItem(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.STICK); - ItemEntity item = new ItemEntity(world, 0.0d, 0.0d, 0.0d, stack); - TestUtil.spawnEntity(context, item, SPAWN_POSITION); - item.damage(world, world.getDamageSources().explosion(null), Float.MAX_VALUE); - context.addInstantFinalTask(() -> context.dontExpectEntity(EntityType.ITEM)); + ItemEntity stick = new ItemEntity( + world, + 0.0d, + 0.0d, + 0.0d, + world.itematic$createStack(ItemKeys.STICK) + ); + TestUtil.spawnEntity(context, stick, SPAWN_POSITION); + stick.damage(world, world.getDamageSources().explosion(null), Float.MAX_VALUE); + context.addFinalTask(() -> context.dontExpectEntity(EntityType.ITEM)); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void settingNetheriteIngotOnFireKeepsItemAlive(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.NETHERITE_INGOT); - ItemEntity item = new ItemEntity(world, 0.0d, 0.0d, 0.0d, stack); - TestUtil.spawnEntity(context, item, SPAWN_POSITION); - item.damage(world, world.getDamageSources().inFire(), Float.MAX_VALUE); - context.addInstantFinalTask(() -> context.expectEntity(EntityType.ITEM)); + ItemEntity netheriteIngot = new ItemEntity( + world, + 0.0d, + 0.0d, + 0.0d, + world.itematic$createStack(ItemKeys.NETHERITE_INGOT) + ); + TestUtil.spawnEntity(context, netheriteIngot, SPAWN_POSITION); + netheriteIngot.damage(world, world.getDamageSources().inFire(), Float.MAX_VALUE); + context.addFinalTask(() -> context.expectEntity(EntityType.ITEM)); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void settingStickOnFireDestroysItem(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.STICK); - ItemEntity item = new ItemEntity(world, 0.0d, 0.0d, 0.0d, stack); - TestUtil.spawnEntity(context, item, SPAWN_POSITION); - item.damage(world, world.getDamageSources().inFire(), Float.MAX_VALUE); - context.addInstantFinalTask(() -> context.dontExpectEntity(EntityType.ITEM)); + ItemEntity stick = new ItemEntity( + world, + 0.0d, + 0.0d, + 0.0d, + world.itematic$createStack(ItemKeys.STICK) + ); + TestUtil.spawnEntity(context, stick, SPAWN_POSITION); + stick.damage(world, world.getDamageSources().inFire(), Float.MAX_VALUE); + context.addFinalTask(() -> context.dontExpectEntity(EntityType.ITEM)); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ItemHolderItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ItemHolderItemComponentTestSuite.java index 02e20154..3ba7ac14 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ItemHolderItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ItemHolderItemComponentTestSuite.java @@ -1,11 +1,11 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.inventory.SimpleStackReference; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.BundleContentsComponent; import net.minecraft.entity.player.PlayerEntity; @@ -14,7 +14,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.screen.slot.Slot; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; import net.minecraft.test.TestContext; import net.minecraft.util.ClickType; import net.minecraft.world.GameMode; @@ -24,7 +23,7 @@ public class ItemHolderItemComponentTestSuite { private static final int SLOT = 0; - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void rightClickingOnStackWithItemHolderAddsStackToItemHolder(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); @@ -33,37 +32,52 @@ public void rightClickingOnStackWithItemHolderAddsStackToItemHolder(TestContext inventory.insertStack(SLOT, world.itematic$createStack(ItemKeys.STICK)); Slot slot = new Slot(inventory, SLOT, 0, 0); world.spawnEntity(player); - boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player); - context.addInstantFinalTask(() -> { - context.assertTrue(success, "Expected right clicking with item holder to be successful"); - Assert.itemStackIsEmpty(inventory.getStack(SLOT)); - Assert.itemStackHasDataComponent(bundle, DataComponentTypes.BUNDLE_CONTENTS, - component -> Assert.itemStackIsOf(component.get(0), ItemKeys.STICK) + context.addFinalTask(() -> { + boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player); + Assert.isTrue( + context, + success, + () -> "Expected right clicking on slot with item holder to be successful" ); + Assert.itemStack(context, inventory.getStack(SLOT)) + .isEmpty(); + Assert.itemStack(context, bundle) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + component -> Assert.itemStack(context, component.get(0)) + .is(ItemKeys.STICK) + ); }); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void rightClickingOnEmptySlotPlacesLastStackFromItemHolderInSlot(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); PlayerInventory inventory = player.getInventory(); ItemStack bundle = world.itematic$createStack(ItemKeys.BUNDLE); - ItemStack stackToRemove = world.itematic$createStack(ItemKeys.STICK); - addToBundleContentsComponent(bundle, stackToRemove); + addToBundleContentsComponent(context, bundle, world.itematic$createStack(ItemKeys.STICK)); Slot slot = new Slot(inventory, SLOT, 0, 0); world.spawnEntity(player); - boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player); - context.addInstantFinalTask(() -> { - context.assertTrue(success, "Expected right clicking with item holder to be successful"); - Assert.itemStackIsOf(inventory.getStack(SLOT), ItemKeys.STICK); - Assert.itemStackHasDataComponent(bundle, DataComponentTypes.BUNDLE_CONTENTS, - component -> context.assertTrue(component.isEmpty(), "Expected item holder to be empty") + context.addFinalTask(() -> { + boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player); + Assert.isTrue( + context, + success, + () -> "Expected right clicking on slot with item holder to be successful" ); + Assert.itemStack(context, inventory.getStack(SLOT)) + .is(ItemKeys.STICK); + Assert.itemStack(context, bundle) + .hasComponent(DataComponentTypes.BUNDLE_CONTENTS, component -> Assert.isTrue( + context, + component.isEmpty(), + () -> "Expected item holder contents to be empty" + )); }); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void rightClickingOnItemHolderWithStackAddsStackToItemHolder(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); @@ -74,41 +88,59 @@ public void rightClickingOnItemHolderWithStackAddsStackToItemHolder(TestContext StackReference cursorStack = SimpleStackReference.of(stackToAdd); Slot slot = new Slot(inventory, SLOT, 0, 0); world.spawnEntity(player); - boolean success = bundle.onClicked(stackToAdd, slot, ClickType.RIGHT, player, cursorStack); - context.addInstantFinalTask(() -> { - context.assertTrue(success, "Expected right clicking on item holder to be successful"); - Assert.itemStackIsEmpty(cursorStack.get()); - Assert.itemStackHasDataComponent(inventory.getStack(SLOT), DataComponentTypes.BUNDLE_CONTENTS, - component -> Assert.itemStackIsOf(component.get(0), ItemKeys.STICK) + context.addFinalTask(() -> { + boolean success = bundle.onClicked(stackToAdd, slot, ClickType.RIGHT, player, cursorStack); + Assert.isTrue( + context, + success, + () -> "Expected right clicking on item holder to be successful" ); + Assert.itemStack(context, cursorStack.get()) + .isEmpty(); + Assert.itemStack(context, inventory.getStack(SLOT)) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + component -> Assert.itemStack(context, component.get(0)) + .is(ItemKeys.STICK) + ); }); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void rightClickingOnItemHolderRemovesStackFromItemHolder(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); PlayerInventory inventory = player.getInventory(); inventory.insertStack(SLOT, world.itematic$createStack(ItemKeys.BUNDLE)); ItemStack bundle = inventory.getStack(SLOT); - ItemStack stackToRemove = world.itematic$createStack(ItemKeys.STICK); - addToBundleContentsComponent(bundle, stackToRemove); + addToBundleContentsComponent(context, bundle, world.itematic$createStack(ItemKeys.STICK)); StackReference cursorStack = SimpleStackReference.of(ItemStack.EMPTY); Slot slot = new Slot(inventory, SLOT, 0, 0); world.spawnEntity(player); - boolean success = bundle.onClicked(ItemStack.EMPTY, slot, ClickType.RIGHT, player, cursorStack); - context.addInstantFinalTask(() -> { - context.assertTrue(success, "Expected right clicking on item holder to be successful"); - Assert.itemStackIsOf(cursorStack.get(), ItemKeys.STICK); - Assert.itemStackHasDataComponent(inventory.getStack(SLOT), DataComponentTypes.BUNDLE_CONTENTS, - component -> context.assertTrue(component.isEmpty(), "Expected item holder to be empty") + context.addFinalTask(() -> { + boolean success = bundle.onClicked(ItemStack.EMPTY, slot, ClickType.RIGHT, player, cursorStack); + Assert.isTrue( + context, + success, + () -> "Expected right clicking on item holder to be successful" ); + Assert.itemStack(context, cursorStack.get()) + .is(ItemKeys.STICK); + Assert.itemStack(context, inventory.getStack(SLOT)) + .hasComponent( + DataComponentTypes.BUNDLE_CONTENTS, + component -> Assert.isTrue( + context, + component.isEmpty(), + () -> "Expected item holder to be empty" + ) + ); }); } - private static void addToBundleContentsComponent(ItemStack bundle, ItemStack stackToAdd) { + private static void addToBundleContentsComponent(TestContext helper, ItemStack bundle, ItemStack stackToAdd) { BundleContentsComponent.Builder builder = Objects.requireNonNull( - TestUtil.getItemBehavior(bundle, ItemComponentTypes.ITEM_HOLDER).createBuilder(bundle) + TestUtil.getItemBehavior(helper, bundle, ItemComponentTypes.ITEM_HOLDER).createBuilder(bundle) ); builder.add(stackToAdd); bundle.set(DataComponentTypes.BUNDLE_CONTENTS, builder.build()); diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/LifeSavingItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/LifeSavingItemComponentTestSuite.java index 9d541b0c..c1b1b764 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/LifeSavingItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/LifeSavingItemComponentTestSuite.java @@ -1,40 +1,39 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; 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 LifeSavingItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void dyingWhileHoldingTotemOfUndyingKeepsPlayerAlive(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING)); player.damage(world, 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); - }); + context.addFinalTask(() -> Assert.livingEntity(context, player) + .hasHealth(health -> health.equals(1.0f)) + .hasEffect(StatusEffects.REGENERATION, 1) + .hasEffect(StatusEffects.ABSORPTION, 1) + .hasEffect(StatusEffects.FIRE_RESISTANCE, 0)); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void dyingFromBypassedInvulnerabilityDamageWhileHoldingTotemOfUndyingKillsPlayer(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING); PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.TOTEM_OF_UNDYING)); player.damage(world, world.getDamageSources().genericKill(), Float.MAX_VALUE); - context.addInstantFinalTask(() -> context.assertTrue(player.isDead(), "Expected player to be dead")); + context.addFinalTask(() -> Assert.isTrue( + context, + player.isDead(), + () -> "Expected Player to be dead" + )); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/MappableItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/MappableItemComponentTestSuite.java index c2b52190..8a92b426 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/MappableItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/MappableItemComponentTestSuite.java @@ -1,36 +1,34 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; 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.GameTestException; import net.minecraft.test.TestContext; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.world.GameMode; public class MappableItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void usingMapFillsMap(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.MAP); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack map = world.itematic$createStack(ItemKeys.MAP); + player.setStackInHand(Hand.MAIN_HAND, map); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - if (!(result instanceof ActionResult.Success successResult)) { - throw new GameTestException("Expected mappable usage to be successful"); - } - - ItemStack resultStack = successResult.getNewHandStack(); - Assert.itemStackIsOf(resultStack, ItemKeys.FILLED_MAP); - Assert.itemStackHasDataComponent(resultStack, DataComponentTypes.MAP_ID); - }); + ActionResult result = map.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> Assert.isInstance( + context, + result, + ActionResult.Success.class, + () -> "Expected mappable item usage to be successful", + success -> Assert.itemStack(context, success.getNewHandStack()) + .is(ItemKeys.FILLED_MAP) + .hasComponent(DataComponentTypes.MAP_ID) + )); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java index 1638eed9..2622c384 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/PotionItemComponentTestSuite.java @@ -1,36 +1,33 @@ package net.errorcraft.itematic.gametest.item.component; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.component.PotionContentsComponentUtil; -import net.errorcraft.itematic.gametest.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.potion.Potions; 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 PotionItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void drinkingPotionItemAddsEffects(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = PotionContentsComponentUtil.setPotion( + ItemStack potion = PotionContentsComponentUtil.setPotion( world.itematic$createStack(ItemKeys.POTION), Potions.LEAPING ); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, potion); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); + potion.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - stack.getMaxUseTime(player), - () -> Assert.forAll( - Potions.LEAPING.value().getEffects(), - effectInstance -> context.expectEntityHasEffect(player, effectInstance.getEffectType(), effectInstance.getAmplifier()) - ) + potion.getMaxUseTime(player), + () -> Assert.livingEntity(context, player) + .hasEffects(Potions.LEAPING) ).completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ShooterItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ShooterItemComponentTestSuite.java index 4934d321..57655f23 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ShooterItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ShooterItemComponentTestSuite.java @@ -1,58 +1,74 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.component.DataComponentTypes; 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 ShooterItemComponentTestSuite { - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void usingCrossbowChargesArrowFromInventory(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CROSSBOW); + ItemStack crossbow = world.itematic$createStack(ItemKeys.CROSSBOW); ItemStack ammunition = world.itematic$createStack(ItemKeys.ARROW); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crossbow); player.getInventory().insertStack(ammunition); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); + crossbow.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - stack.getMaxUseTime(player), + crossbow.getMaxUseTime(player), () -> { - stack.onStoppedUsing(world, player, player.getItemUseTimeLeft()); - Assert.itemStackHasDataComponent(player.getStackInHand(Hand.MAIN_HAND), DataComponentTypes.CHARGED_PROJECTILES, - component -> context.assertTrue(component.itematic$contains(ItemKeys.ARROW), "Expected item stack to have an Arrow as a charged projectile") + crossbow.onStoppedUsing(world, player, player.getItemUseTimeLeft()); + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .hasComponent( + DataComponentTypes.CHARGED_PROJECTILES, + chargedProjectiles -> Assert.isTrue( + context, + chargedProjectiles.itematic$contains(ItemKeys.ARROW), + () -> "Expected item stack to have an Arrow as a charged projectile" + ) + ); + Assert.isFalse( + context, + player.getInventory().contains(s -> s.itematic$isOf(ItemKeys.ARROW)), + () -> "Expected Player not to have any Arrows in their inventory" ); - context.assertTrue(!player.getInventory().contains(s -> s.itematic$isOf(ItemKeys.ARROW)), "Expected player to have no Arrows in their inventory"); } ).completeIfSuccessful(); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest(maxTicks = 100) public void usingCrossbowChargesFireworkRocketFromOffhand(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.CROSSBOW); + ItemStack crossbow = world.itematic$createStack(ItemKeys.CROSSBOW); ItemStack ammunition = world.itematic$createStack(ItemKeys.FIREWORK_ROCKET); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, crossbow); player.setStackInHand(Hand.OFF_HAND, ammunition); world.spawnEntity(player); - stack.use(world, player, Hand.MAIN_HAND); + crossbow.use(world, player, Hand.MAIN_HAND); context.createTimedTaskRunner().expectMinDurationAndRun( - stack.getMaxUseTime(player), + crossbow.getMaxUseTime(player), () -> { - stack.onStoppedUsing(world, player, player.getItemUseTimeLeft()); - Assert.itemStackHasDataComponent(player.getStackInHand(Hand.MAIN_HAND), DataComponentTypes.CHARGED_PROJECTILES, - component -> context.assertTrue(component.itematic$contains(ItemKeys.FIREWORK_ROCKET), "Expected item stack to have a Firework Rocket as a charged projectile") - ); - Assert.itemStackIsEmpty(player.getStackInHand(Hand.OFF_HAND)); + crossbow.onStoppedUsing(world, player, player.getItemUseTimeLeft()); + Assert.itemStack(context, player.getStackInHand(Hand.MAIN_HAND)) + .hasComponent( + DataComponentTypes.CHARGED_PROJECTILES, + chargedProjectiles -> Assert.isTrue( + context, + chargedProjectiles.itematic$contains(ItemKeys.FIREWORK_ROCKET), + () -> "Expected item stack to have a Firework Rocket as a charged projectile" + ) + ); + Assert.itemStack(context, player.getStackInHand(Hand.OFF_HAND)) + .isEmpty(); } ).completeIfSuccessful(); } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java index 4d95c1a0..73525ce4 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java @@ -1,16 +1,17 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.component.ItemComponentTypes; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.predicate.NumberRange; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTest; -import net.minecraft.test.GameTestException; import net.minecraft.test.TestContext; +import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -19,106 +20,138 @@ public class ThrowableItemComponentTestSuite { private static final BlockPos SPAWN_POSITION = new BlockPos(1, 1, 1); - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingEggSpawnsEggAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.EGG); + ItemStack egg = world.itematic$createStack(ItemKeys.EGG); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, egg); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Egg usage to be successful"); + ActionResult result = egg.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Egg usage to be successful" + ); context.expectEntityAt(EntityType.EGG, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingEnderPearlSpawnsEnderPearlAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.ENDER_PEARL); + ItemStack enderPearl = world.itematic$createStack(ItemKeys.ENDER_PEARL); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, enderPearl); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Ender Pearl usage to be successful"); + ActionResult result = enderPearl.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Ender Pearl usage to be successful" + ); context.expectEntityAt(EntityType.ENDER_PEARL, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingSnowballSpawnsSnowballAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SNOWBALL); + ItemStack snowball = world.itematic$createStack(ItemKeys.SNOWBALL); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, snowball); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Snowball usage to be successful"); + ActionResult result = snowball.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Snowball usage to be successful" + ); context.expectEntityAt(EntityType.SNOWBALL, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingExperienceBottleSpawnsExperienceBottleAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.EXPERIENCE_BOTTLE); + ItemStack experienceBottle = world.itematic$createStack(ItemKeys.EXPERIENCE_BOTTLE); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, experienceBottle); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Experience Bottle usage to be successful"); + ActionResult result = experienceBottle.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Experience Bottle usage to be successful" + ); context.expectEntityAt(EntityType.EXPERIENCE_BOTTLE, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingSplashPotionSpawnsPotionAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.SPLASH_POTION); + ItemStack splashPotion = world.itematic$createStack(ItemKeys.SPLASH_POTION); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, splashPotion); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Splash Potion usage to be successful"); + ActionResult result = splashPotion.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Splash Potion usage to be successful" + ); context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingLingeringPotionSpawnsPotionAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LINGERING_POTION); + ItemStack lingeringPotion = world.itematic$createStack(ItemKeys.LINGERING_POTION); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, lingeringPotion); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); context.addFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Lingering Potion usage to be successful"); + ActionResult result = lingeringPotion.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Lingering Potion usage to be successful" + ); context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } - @GameTest(templateName = "itematic:item.component.throwable.platform") + @GameTest(structure = "itematic:item.component.throwable.platform") public void throwingTridentSpawnsTridentAtEyePosition(TestContext context) { ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.TRIDENT); - int minDrawDuration = TestUtil.getItemBehavior(stack, ItemComponentTypes.THROWABLE) + ItemStack trident = world.itematic$createStack(ItemKeys.TRIDENT); + int minDrawDuration = TestUtil.getItemBehavior(context, trident, ItemComponentTypes.THROWABLE) .drawDuration() .flatMap(NumberRange.IntRange::min) - .orElseThrow(() -> new GameTestException("Trident does not have a minimum draw duration")); + .orElseThrow(() -> context.createError(Text.literal("Trident does not have a minimum draw duration"))); PlayerEntity player = TestUtil.createMockPlayer(context, GameMode.SURVIVAL, SPAWN_POSITION); - player.setStackInHand(Hand.MAIN_HAND, stack); + player.setStackInHand(Hand.MAIN_HAND, trident); world.spawnEntity(player); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.assertTrue(result.isAccepted(), "Expected Trident usage to be successful"); - context.runAtTick(minDrawDuration, () -> context.addFinalTask(() -> { - stack.onStoppedUsing(world, player, player.getItemUseTimeLeft()); - context.expectEntityAt(EntityType.TRIDENT, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); - })); + context.createTimedTaskRunner() + .createAndAddReported(() -> { + ActionResult result = trident.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Trident usage to be successful" + ); + }) + .expectMinDurationAndRun(minDrawDuration, () -> { + trident.onStoppedUsing(world, player, player.getItemUseTimeLeft()); + context.expectEntityAt(EntityType.TRIDENT, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); + }) + .completeIfSuccessful(); } } diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/UseableOnFluidItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/UseableOnFluidItemComponentTestSuite.java index 982307a4..3ff68041 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/UseableOnFluidItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/UseableOnFluidItemComponentTestSuite.java @@ -1,14 +1,15 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.block.Blocks; import net.minecraft.command.argument.EntityAnchorArgumentType; import net.minecraft.entity.EntityType; 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.ActionResult; import net.minecraft.util.Hand; @@ -27,74 +28,91 @@ public class UseableOnFluidItemComponentTestSuite { private static final BlockPos ABOVE_LOOK_AT_WATER_POSITION_IN_WATER = LOOK_AT_WATER_POSITION_IN_WATER.add(0, 1, 0); private static final BlockPos LOOK_AT_AIR_POSITION_IN_WATER = SPAWN_POSITION_IN_WATER.add(0, 3, 0); - @GameTest(templateName = "itematic:item.component.useable_on_fluid.water_hole") + @GameTest(structure = "itematic:item.component.useable_on_fluid.water_hole") public void usingLilyPadWhileLookingAtWaterPlacesLilyPad(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION_ON_LAND); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(LOOK_AT_WATER_POSITION_ON_LAND))); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.LILY_PAD); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Lily Pad usage to be successful"); - context.expectBlock(Blocks.LILY_PAD, ABOVE_LOOK_AT_WATER_POSITION_ON_LAND); + ItemStack lilyPad = world.itematic$createStack(ItemKeys.LILY_PAD); + player.setStackInHand(Hand.MAIN_HAND, lilyPad); + context.addFinalTask(() -> { + ActionResult result = lilyPad.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Lily Pad usage to be successful" + ); + Assert.blockState(context, ABOVE_LOOK_AT_WATER_POSITION_ON_LAND) + .is(Blocks.LILY_PAD); }); } - @GameTest(templateName = "itematic:item.component.useable_on_fluid.water_hole") + @GameTest(structure = "itematic:item.component.useable_on_fluid.water_hole") public void usingPigSpawnEggWhileLookingAtWaterSpawnsPigAtWater(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION_ON_LAND); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(LOOK_AT_WATER_POSITION_ON_LAND))); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Pig Spawn Egg usage to be successful"); + ItemStack pigSpawnEgg = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); + player.setStackInHand(Hand.MAIN_HAND, pigSpawnEgg); + context.addFinalTask(() -> { + ActionResult result = pigSpawnEgg.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Pig Spawn Egg usage to be successful" + ); context.expectEntityAt(EntityType.PIG, LOOK_AT_WATER_POSITION_ON_LAND); }); } - @GameTest(templateName = "itematic:item.component.useable_on_fluid.water_hole") + @GameTest(structure = "itematic:item.component.useable_on_fluid.water_hole") public void usingPigSpawnEggWhileLookingAtAirDoesNotSpawnPig(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION_ON_LAND); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(LOOK_AT_AIR_POSITION_ON_LAND))); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertFalse(result.isAccepted(), "Expected Pig Spawn Egg usage to be unsuccessful"); + ItemStack pigSpawnEgg = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); + player.setStackInHand(Hand.MAIN_HAND, pigSpawnEgg); + context.addFinalTask(() -> { + ActionResult result = pigSpawnEgg.use(world, player, Hand.MAIN_HAND); + Assert.isFalse( + context, + result.isAccepted(), + () -> "Expected Pig Spawn Egg usage to be unsuccessful" + ); context.dontExpectEntity(EntityType.PIG); }); } - @GameTest(templateName = "itematic:item.component.useable_on_fluid.water_hole") + @GameTest(structure = "itematic:item.component.useable_on_fluid.water_hole") public void usingPigSpawnEggWhileLookingAtGroundUnderWaterSpawnsPigOnGroundUnderWater(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION_IN_WATER); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(LOOK_AT_WATER_POSITION_IN_WATER))); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); - player.setStackInHand(Hand.MAIN_HAND, stack); - TestUtil.useStackOnBlockInside(context, player, stack, ABOVE_LOOK_AT_WATER_POSITION_IN_WATER, Direction.DOWN); - context.addInstantFinalTask(() -> context.expectEntityAt(EntityType.PIG, ABOVE_LOOK_AT_WATER_POSITION_IN_WATER)); + ItemStack pigSpawnEgg = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); + player.setStackInHand(Hand.MAIN_HAND, pigSpawnEgg); + TestUtil.useStackOnBlockInside(context, player, pigSpawnEgg, ABOVE_LOOK_AT_WATER_POSITION_IN_WATER, Direction.DOWN); + context.addFinalTask(() -> context.expectEntityAt(EntityType.PIG, ABOVE_LOOK_AT_WATER_POSITION_IN_WATER)); } - @GameTest(templateName = "itematic:item.component.useable_on_fluid.water_hole") + @GameTest(structure = "itematic:item.component.useable_on_fluid.water_hole") public void usingPigSpawnEggWhileLookingAtWaterUnderWaterSpawnsPigAtPlayerEyes(TestContext context) { PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); TestUtil.setEntityPos(context, player, SPAWN_POSITION_IN_WATER); player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(LOOK_AT_AIR_POSITION_IN_WATER))); ServerWorld world = context.getWorld(); - ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); - player.setStackInHand(Hand.MAIN_HAND, stack); - ActionResult result = stack.use(world, player, Hand.MAIN_HAND); - context.addInstantFinalTask(() -> { - context.assertTrue(result.isAccepted(), "Expected Pig Spawn Egg usage to be successful"); + ItemStack pigSpawnEgg = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG); + player.setStackInHand(Hand.MAIN_HAND, pigSpawnEgg); + ActionResult result = pigSpawnEgg.use(world, player, Hand.MAIN_HAND); + context.addFinalTask(() -> { + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Pig Spawn Egg usage to be successful" + ); BlockPos eyeBlockPos = SPAWN_POSITION_IN_WATER.add(0, (int) player.getStandingEyeHeight(), 0); context.expectEntityAt(EntityType.PIG, eyeBlockPos); }); 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 e1c26436..e6fd467d 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 @@ -1,18 +1,15 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.gametest.Assert; -import net.errorcraft.itematic.gametest.TestUtil; +import net.errorcraft.itematic.assertion.Assert; import net.errorcraft.itematic.item.ItemKeys; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; +import net.errorcraft.itematic.util.TestUtil; +import net.fabricmc.fabric.api.gametest.v1.GameTest; import net.minecraft.entity.EntityType; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.mob.PiglinEntity; import net.minecraft.entity.mob.ZombieEntity; import net.minecraft.entity.passive.PigEntity; -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; @@ -21,70 +18,83 @@ public class WeaponItemComponentTestSuite { private static final double MAX_HEALTH_VICTIM = 100.0d; - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest public void zombieAttackingUnarmedDealsDamageFromTrueBaseValueAttackDamageAttribute(TestContext context) { ServerWorld world = context.getWorld(); ZombieEntity zombie = TestUtil.createEntity(context, EntityType.ZOMBIE, entity -> {}); world.spawnEntity(zombie); PigEntity victim = spawnVictim(context); context.createTimedTaskRunner().expectMinDurationAndRun(1, () -> { - context.assertTrue(zombie.tryAttack(world, victim), "Expected attack to be successful"); - Assert.areDoublesEqual( - victim.getHealth(), - MAX_HEALTH_VICTIM - zombie.getAttributeBaseValue(EntityAttributes.ATTACK_DAMAGE), - (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" + Assert.isTrue( + context, + zombie.tryAttack(world, victim), + () -> "Expected attack to be successful" ); + Assert.doubles(context, victim.getHealth(), "health") + .equals(MAX_HEALTH_VICTIM - zombie.itematic$getAttackDamage()); }).completeIfSuccessful(); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest 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)); + ZombieEntity zombie = TestUtil.createEntity( + context, + EntityType.ZOMBIE, + entity -> entity.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.IRON_SWORD)) + ); world.spawnEntity(zombie); PigEntity victim = spawnVictim(context); context.createTimedTaskRunner().expectMinDurationAndRun(1, () -> { - context.assertTrue(zombie.tryAttack(world, victim), "Expected attack to be successful"); - Assert.areDoublesEqual( - victim.getHealth(), - MAX_HEALTH_VICTIM - zombie.getAttributeBaseValue(EntityAttributes.ATTACK_DAMAGE) - TestUtil.getItemBehavior(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), - (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" + Assert.isTrue( + context, + zombie.tryAttack(world, victim), + () -> "Expected attack to be successful" ); + Assert.doubles(context, victim.getHealth(), "health") + .equals(MAX_HEALTH_VICTIM - zombie.itematic$getAttackDamage()); }).completeIfSuccessful(); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest 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)); + PiglinEntity piglin = TestUtil.createEntity( + context, + EntityType.PIGLIN, + entity -> world.itematic$createStack(ItemKeys.IRON_SWORD) + ); world.spawnEntity(piglin); PigEntity victim = spawnVictim(context); context.createTimedTaskRunner().expectMinDurationAndRun(1, () -> { - context.assertTrue(piglin.tryAttack(world, victim), "Expected attack to be successful"); - Assert.areDoublesEqual( - victim.getHealth(), - MAX_HEALTH_VICTIM - piglin.getAttributeBaseValue(EntityAttributes.ATTACK_DAMAGE) - TestUtil.getItemBehavior(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), - (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" + Assert.isTrue( + context, + piglin.tryAttack(world, victim), + () -> "Expected attack to be successful" ); + Assert.doubles(context, victim.getHealth(), "health") + .equals(MAX_HEALTH_VICTIM - piglin.itematic$getAttackDamage()); }).completeIfSuccessful(); } - @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) + @GameTest 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)); + PiglinEntity piglin = TestUtil.createEntity( + context, + EntityType.PIGLIN, + entity -> entity.setStackInHand(Hand.MAIN_HAND, world.itematic$createStack(ItemKeys.GOLDEN_SWORD)) + ); world.spawnEntity(piglin); PigEntity victim = spawnVictim(context); context.createTimedTaskRunner().expectMinDurationAndRun(1, () -> { - context.assertTrue(piglin.tryAttack(world, victim), "Expected attack to be successful"); - Assert.areDoublesEqual( - victim.getHealth(), - MAX_HEALTH_VICTIM - piglin.getAttributeBaseValue(EntityAttributes.ATTACK_DAMAGE) - TestUtil.getItemBehavior(stack, ItemComponentTypes.WEAPON).attackDamage().defaultDamage(), - (value, expected) -> "Expected health to be " + expected + ", got " + value + " instead" + Assert.isTrue( + context, + piglin.tryAttack(world, victim), + () -> "Expected attack to be successful" ); + Assert.doubles(context, victim.getHealth(), "health") + .equals(MAX_HEALTH_VICTIM - piglin.itematic$getAttackDamage()); }).completeIfSuccessful(); } diff --git a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/StructureTestListenerExtender.java b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/StructureTestListenerExtender.java deleted file mode 100644 index 31d4ded9..00000000 --- a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/StructureTestListenerExtender.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.errorcraft.itematic.mixin.gametest; - -import net.errorcraft.itematic.item.ItemKeys; -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTestState; -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.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(targets = "net.minecraft.test.StructureTestListener") -public class StructureTestListenerExtender { - @Unique - private static ServerWorld world; - - @Inject( - method = "createTestOutputLectern", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/test/StructureTestListener;createBookWithText(Ljava/lang/String;ZLjava/lang/String;)Lnet/minecraft/item/ItemStack;" - ) - ) - private static void storeWorld(GameTestState test, String output, CallbackInfo info) { - world = test.getWorld(); - } - - @Inject( - method = "createTestOutputLectern", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/test/StructureTestListener;createBookWithText(Ljava/lang/String;ZLjava/lang/String;)Lnet/minecraft/item/ItemStack;", - shift = At.Shift.AFTER - ) - ) - private static void resetWorld(GameTestState test, String output, CallbackInfo info) { - world = null; - } - - @Redirect( - method = "createBookWithText", - at = @At( - value = "NEW", - target = "(Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/item/ItemStack;" - ) - ) - private static ItemStack newItemStackForWritableBookUseCreateStack(ItemConvertible item) { - return world.itematic$createStack(ItemKeys.WRITABLE_BOOK); - } -} diff --git a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java index 281bc7b4..ad498e73 100644 --- a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java +++ b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java @@ -7,6 +7,7 @@ import net.minecraft.test.GameTestState; import net.minecraft.test.TestContext; import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -14,16 +15,20 @@ import org.spongepowered.asm.mixin.injection.At; @Mixin(TestContext.class) -public class TestContextExtender { +public abstract class TestContextExtender { @Shadow @Final private GameTestState test; + @Shadow + public abstract Vec3d getAbsolute(Vec3d pos); + @ModifyReturnValue( method = "createMockPlayer", at = @At("TAIL") ) - private PlayerEntity setPlayerAbilities(PlayerEntity original, GameMode gameMode) { + private PlayerEntity setPlayerData(PlayerEntity original, GameMode gameMode) { + original.setPosition(this.getAbsolute(Vec3d.ZERO)); gameMode.setAbilities(original.getAbilities()); return original; } diff --git a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java new file mode 100644 index 00000000..91879d2c --- /dev/null +++ b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java @@ -0,0 +1,45 @@ +package net.errorcraft.itematic.mixin.gametest.structure; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.minecraft.structure.StructureTemplateManager; +import org.objectweb.asm.Opcodes; +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.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@Mixin(StructureTemplateManager.class) +public class StructureTemplateManagerExtender { + @Unique + private static final String STRUCTURE_OUTPUT_DIR = System.getProperty("itematic.gametest.structure-output-directory"); + + @ModifyExpressionValue( + method = "getTemplatePath", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/structure/StructureTemplateManager;generatedPath:Ljava/nio/file/Path;", + opcode = Opcodes.GETFIELD + ) + ) + private Path useCustomStructureOutputDirectory(Path original) { + if (STRUCTURE_OUTPUT_DIR != null) { + return Paths.get(STRUCTURE_OUTPUT_DIR); + } + + return original; + } + + @ModifyConstant( + method = "getTemplatePath", + constant = @Constant( + stringValue = "structures" + ) + ) + private String useSingularNameForStructureOutputDirectory(String constant) { + return "structure"; + } +} diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/TestUtil.java b/src/gametest/java/net/errorcraft/itematic/util/TestUtil.java similarity index 80% rename from src/gametest/java/net/errorcraft/itematic/gametest/TestUtil.java rename to src/gametest/java/net/errorcraft/itematic/util/TestUtil.java index f34e4914..828a1fa8 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/TestUtil.java +++ b/src/gametest/java/net/errorcraft/itematic/util/TestUtil.java @@ -1,4 +1,4 @@ -package net.errorcraft.itematic.gametest; +package net.errorcraft.itematic.util; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; @@ -22,8 +22,6 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.server.world.ServerWorld; -import net.minecraft.test.GameTestException; -import net.minecraft.test.PositionedException; import net.minecraft.test.TestContext; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -58,23 +56,34 @@ public static ItemStack createItemStackWithEnchantment(ServerWorld world, Regist return stack; } - public static > T getItemBehavior(ItemStack stack, ItemComponentType type) { + public static > T getItemBehavior(TestContext helper, ItemStack stack, ItemComponentType type) { return stack.itematic$getBehavior(type) - .orElseThrow(() -> new GameTestException("Item " + stack.itematic$key() + " does not have the " + ItematicRegistries.ITEM_COMPONENT_TYPE.getKey(type).orElseThrow() + " behavior")); + .orElseThrow(() -> helper.createError( + "test.error.item.expected_item_behavior", + ItematicRegistries.ITEM_COMPONENT_TYPE.getId(type) + )); } - public static T getDataComponent(ItemStack stack, ComponentType type) { + public static T getDataComponent(TestContext helper, ItemStack stack, ComponentType type) { T component = stack.get(type); - if (component == null) { - throw new GameTestException("Item stack does not contain the " + type + " data component"); + if (component != null) { + return component; } - return component; + throw helper.createError( + "test.error.item_stack.expected_data_component", + "item stack", + type + ); } public static T getBlockEntity(TestContext context, BlockPos pos, BlockEntityType type) { return context.getWorld().getBlockEntity(context.getAbsolutePos(pos), type) - .orElseThrow(() -> new GameTestException("Block entity at position " + pos + " was not of type " + Registries.BLOCK_ENTITY_TYPE.getKey(type).orElseThrow())); + .orElseThrow(() -> context.createError( + pos, + "test.error.block_entity.expected_block_entity_type", + Registries.BLOCK_ENTITY_TYPE.getId(type) + )); } public static PlayerEntity createMockPlayer(TestContext context, GameMode gameMode, BlockPos pos) { @@ -90,7 +99,10 @@ public static T createEntity(TestContext context, EntityType< public static T createEntityAt(TestContext context, EntityType type, BlockPos pos, Consumer initializer) { T entity = type.create(context.getWorld(), SpawnReason.COMMAND); if (entity == null) { - throw new GameTestException("Entity is null"); + throw context.createError( + "test.error.entity_type.cannot_create_entity", + type.getName() + ); } setEntityPos(context, entity, pos); @@ -134,12 +146,12 @@ public static T getMenuFromBlock(TestContext context, BlockPos absolutePos = context.getAbsolutePos(pos); NamedScreenHandlerFactory factory = context.getBlockState(pos).createScreenHandlerFactory(context.getWorld(), absolutePos); if (factory == null) { - throw new PositionedException("Block does not provide a menu", absolutePos, pos, context.getTick()); + throw context.createError(pos, "test.error.menu.does_not_provide_menu"); } ScreenHandler menu = factory.createMenu(-1, player.getInventory(), player); if (menu == null) { - throw new PositionedException("Block does not create a menu", absolutePos, pos, context.getTick()); + throw context.createError(pos, "test.error.menu.does_not_create_menu"); } try { @@ -148,14 +160,14 @@ public static T getMenuFromBlock(TestContext context, return (T) menu; } - throw new PositionedException( - "Block has the incorrect menu type " + Registries.SCREEN_HANDLER.getId(actualType) + ", expected " + Registries.SCREEN_HANDLER.getId(type), - absolutePos, + throw context.createError( pos, - context.getTick() + "test.error.menu.has_incorrect_menu_type", + Registries.SCREEN_HANDLER.getId(actualType), + Registries.SCREEN_HANDLER.getId(type) ); } catch (UnsupportedOperationException ignored) { - throw new PositionedException("Block does not create a menu by type", absolutePos, pos, context.getTick()); + throw context.createError(pos, "test.error.menu.does_not_create_menu_by_type"); } } } diff --git a/src/gametest/resources/assets/itematic/lang/en_us.json b/src/gametest/resources/assets/itematic/lang/en_us.json new file mode 100644 index 00000000..72c9d294 --- /dev/null +++ b/src/gametest/resources/assets/itematic/lang/en_us.json @@ -0,0 +1,27 @@ +{ + "test.error.expected_not_null": "Expected %s to exist", + "test.error.expected_value_greater_than": "Expected %s to be greater than %s, got %s instead", + "test.error.expected_type": "Expected %s to be %s, got %s instead", + "test.error.did_not_expect_type": "Expected %s not to be %s", + "test.error.expected_tag": "Expected %s to be #%s", + "test.error.block_entity.expected_block_entity_type": "Expected block entity type to be %s", + "test.error.entity.expected_effect": "Expected entity %s to have effect %s", + "test.error.entity.did_not_expect_effect": "Expected entity %s not to have effect %s", + "test.error.entity_type.cannot_create_entity": "Cannot create entity with type %s", + "test.error.item.expected_item_behavior": "Expected item to have the %s behavior", + "test.error.item_stack.expected_damaged": "Expected %s to be damaged", + "test.error.item_stack.expected_not_damaged": "Expected %s not to be damaged", + "test.error.item_stack.expected_potion": "Expected %s to have potion %s", + "test.error.item_stack.expected_other_potion": "Expected %s to have potion %s, got %s instead", + "test.error.item_stack.expected_data_component": "Expected %s to have the %s data component", + "test.error.item_stack.did_not_expect_data_component": "Expected %s not to have the %s data component", + "test.error.item_stack.expected_empty": "Expected %s to be empty, got %s instead", + "test.error.item_stack.expected_not_empty": "Expected %s not to be empty", + "test.error.item_stack.expected_enchantments": "Expected %s to have enchantments", + "test.error.item_stack.expected_no_enchantments": "Expected %s not to have enchantments", + "test.error.item_stack.expected_specified_enchantments": "Expected %s to have enchantments: %s", + "test.error.menu.does_not_provide_menu": "Block does not provide a menu", + "test.error.menu.does_not_create_menu": "Block does not create a menu", + "test.error.menu.has_incorrect_menu_type": "Block has the incorrect menu type %s, expected %s", + "test.error.menu.does_not_create_menu_by_type": "Block does not create a menu by type" +} diff --git a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.short_grass.snbt b/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.short_grass.snbt deleted file mode 100644 index a41a4449..00000000 --- a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.short_grass.snbt +++ /dev/null @@ -1,40 +0,0 @@ -{ - DataVersion: 3839, - 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:grass_block{snowy:false}"}, - {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:short_grass"}, - {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:grass_block{snowy:false}", - "minecraft:air", - "minecraft:short_grass" - ] -} diff --git a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.snbt b/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.snbt deleted file mode 100644 index 5693ba04..00000000 --- a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.snbt +++ /dev/null @@ -1,38 +0,0 @@ -{ - DataVersion: 3839, - 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:air"}, - {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" - ] -} diff --git a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.suspicious_sand.snbt b/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.suspicious_sand.snbt deleted file mode 100644 index 1db6483e..00000000 --- a/src/gametest/resources/data/itematic/gametest/structure/item.brush.platform.suspicious_sand.snbt +++ /dev/null @@ -1,39 +0,0 @@ -{ - DataVersion: 3839, - 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:suspicious_sand{dusted:0}", nbt: {id: "minecraft:brushable_block"}}, - {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:suspicious_sand{dusted:0}" - ] -} diff --git a/src/gametest/resources/data/itematic/structure/item.brush.platform.nbt b/src/gametest/resources/data/itematic/structure/item.brush.platform.nbt new file mode 100644 index 0000000000000000000000000000000000000000..47ef87c22b592931b5fe7faf04cc364df9933270 GIT binary patch literal 218 zcmb2|=3oGW|Gk$_a~(1eXnkmWxoV}-i(BS}Z*MLA9pTQA6+LTBjhFmMu4CL8wvBpT z|GsfE&tzcz^gw?aS=!``^FPul!YRTF2!9=x zGJTg~cwtwEb*ple%=JnbMbw_!X LxFQ52Sr`}qjl5$M literal 0 HcmV?d00001 diff --git a/src/gametest/resources/data/itematic/structure/item.brush.platform.short_grass.nbt b/src/gametest/resources/data/itematic/structure/item.brush.platform.short_grass.nbt new file mode 100644 index 0000000000000000000000000000000000000000..09b27d2189c5d86af7f70dda67a3ba2ec7e46073 GIT binary patch literal 355 zcmb2|=3oGW|Gm==dL1zkagC3=y>Ttat`FfcJIZv|-Qk;QxcI1F^rVIt;lDh$HRq>E z+?p=^V$qX5Mf^J_Tyqh9y6|VAq~Kip)m>iKkE)sJUD%=(m3yo1x8$pjPZuuAdC`2} z_|!nbMZNFplllx94l_(<^x-pTJtT3!TjDG->SokWG(kc^&r|h`X3s1(7k{_sfJ8%L z!$}4;_8CrzM`AwS=6#Gx0`UzW9OaG+Z_bVF$=kK;^Q2GdyURWMFuKA%kmTmRw|TvBAX#7aLqO?Unh^zdm$^Ap^q;3>jQx$YDbc8#=SW zg=y9XW^F!fn9rJv3^{DbVMAv=>B^BbMNGlI!rj3)QU>=HAB)iIyDMthegD&EYR`2% zFqfUHB}N%vfF#A{*&PJ8vs9_Vm^K|<{~kFXhA#O_Xgdkxo04K%^%|uDJsdC08fved hFMZqVPF+(Cy{?{IbgvTBw+(Rfi7(YBt~0#^004Wad@cY0 literal 0 HcmV?d00001 diff --git a/src/gametest/resources/itematic-gametest.mixins.json b/src/gametest/resources/itematic-gametest.mixins.json index 23487eb3..046215aa 100644 --- a/src/gametest/resources/itematic-gametest.mixins.json +++ b/src/gametest/resources/itematic-gametest.mixins.json @@ -8,9 +8,9 @@ }, "mixins": [ "GameTestStateExtender", - "StructureTestListenerExtender", "TestContextExtender", - "TestServerExtender" + "TestServerExtender", + "structure.StructureTemplateManagerExtender" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/generated/data/minecraft/dispense_behavior/saddle.json b/src/main/generated/data/minecraft/dispense_behavior/saddle.json deleted file mode 100644 index a0f75122..00000000 --- a/src/main/generated/data/minecraft/dispense_behavior/saddle.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "entry": { - "action": { - "type": "minecraft:saddle_entity_at_position", - "position": "interacted" - } - } -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/diamond_axe.json b/src/main/generated/data/minecraft/item/diamond_axe.json index 56cdfdb1..5fd5b500 100644 --- a/src/main/generated/data/minecraft/item/diamond_axe.json +++ b/src/main/generated/data/minecraft/item/diamond_axe.json @@ -30,7 +30,7 @@ }, "attack_speed": 0.25, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_hoe.json b/src/main/generated/data/minecraft/item/diamond_hoe.json index 5b2c5723..5ae52a51 100644 --- a/src/main/generated/data/minecraft/item/diamond_hoe.json +++ b/src/main/generated/data/minecraft/item/diamond_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 1.0, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_pickaxe.json b/src/main/generated/data/minecraft/item/diamond_pickaxe.json index f19ee33b..9ee48825 100644 --- a/src/main/generated/data/minecraft/item/diamond_pickaxe.json +++ b/src/main/generated/data/minecraft/item/diamond_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/diamond_shovel.json b/src/main/generated/data/minecraft/item/diamond_shovel.json index 38de1809..8896cb70 100644 --- a/src/main/generated/data/minecraft/item/diamond_shovel.json +++ b/src/main/generated/data/minecraft/item/diamond_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_axe.json b/src/main/generated/data/minecraft/item/golden_axe.json index efdb2f7b..06d72ac6 100644 --- a/src/main/generated/data/minecraft/item/golden_axe.json +++ b/src/main/generated/data/minecraft/item/golden_axe.json @@ -30,7 +30,7 @@ }, "attack_speed": 0.25, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_hoe.json b/src/main/generated/data/minecraft/item/golden_hoe.json index a8bcf253..2ac767f0 100644 --- a/src/main/generated/data/minecraft/item/golden_hoe.json +++ b/src/main/generated/data/minecraft/item/golden_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_pickaxe.json b/src/main/generated/data/minecraft/item/golden_pickaxe.json index dd51e963..f3805ab3 100644 --- a/src/main/generated/data/minecraft/item/golden_pickaxe.json +++ b/src/main/generated/data/minecraft/item/golden_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/golden_shovel.json b/src/main/generated/data/minecraft/item/golden_shovel.json index 43d55cd5..3ffcc5f2 100644 --- a/src/main/generated/data/minecraft/item/golden_shovel.json +++ b/src/main/generated/data/minecraft/item/golden_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_axe.json b/src/main/generated/data/minecraft/item/iron_axe.json index a7adf296..c9e248fa 100644 --- a/src/main/generated/data/minecraft/item/iron_axe.json +++ b/src/main/generated/data/minecraft/item/iron_axe.json @@ -30,7 +30,7 @@ }, "attack_speed": 0.225, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_hoe.json b/src/main/generated/data/minecraft/item/iron_hoe.json index f3ab1d68..b6eadcde 100644 --- a/src/main/generated/data/minecraft/item/iron_hoe.json +++ b/src/main/generated/data/minecraft/item/iron_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.75, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_pickaxe.json b/src/main/generated/data/minecraft/item/iron_pickaxe.json index 479d5d9f..0b3058d1 100644 --- a/src/main/generated/data/minecraft/item/iron_pickaxe.json +++ b/src/main/generated/data/minecraft/item/iron_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/iron_shovel.json b/src/main/generated/data/minecraft/item/iron_shovel.json index 792ec354..b1f3dc6a 100644 --- a/src/main/generated/data/minecraft/item/iron_shovel.json +++ b/src/main/generated/data/minecraft/item/iron_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_axe.json b/src/main/generated/data/minecraft/item/netherite_axe.json index 08d4b9ba..989f439c 100644 --- a/src/main/generated/data/minecraft/item/netherite_axe.json +++ b/src/main/generated/data/minecraft/item/netherite_axe.json @@ -33,7 +33,7 @@ }, "attack_speed": 0.25, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_hoe.json b/src/main/generated/data/minecraft/item/netherite_hoe.json index 864fb5d7..5bcde35c 100644 --- a/src/main/generated/data/minecraft/item/netherite_hoe.json +++ b/src/main/generated/data/minecraft/item/netherite_hoe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 1.0, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_pickaxe.json b/src/main/generated/data/minecraft/item/netherite_pickaxe.json index 6f8d2a07..580d81a2 100644 --- a/src/main/generated/data/minecraft/item/netherite_pickaxe.json +++ b/src/main/generated/data/minecraft/item/netherite_pickaxe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/netherite_shovel.json b/src/main/generated/data/minecraft/item/netherite_shovel.json index 94bd38bc..00521bca 100644 --- a/src/main/generated/data/minecraft/item/netherite_shovel.json +++ b/src/main/generated/data/minecraft/item/netherite_shovel.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/saddle.json b/src/main/generated/data/minecraft/item/saddle.json index 4fb39cdc..81944b62 100644 --- a/src/main/generated/data/minecraft/item/saddle.json +++ b/src/main/generated/data/minecraft/item/saddle.json @@ -1,9 +1,15 @@ { "behavior": { "minecraft:dispensable": { - "behavior": "minecraft:saddle" + "behavior": "minecraft:equip_entity" + }, + "minecraft:equipment": { + "allowed_entities": "#minecraft:can_equip_saddle", + "asset_id": "minecraft:saddle", + "equip_on_interact": true, + "equip_sound": "minecraft:entity.horse.saddle", + "slot": "saddle" }, - "minecraft:saddle": {}, "minecraft:stackable": 1 }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_axe.json b/src/main/generated/data/minecraft/item/stone_axe.json index f6d992f7..631e6d46 100644 --- a/src/main/generated/data/minecraft/item/stone_axe.json +++ b/src/main/generated/data/minecraft/item/stone_axe.json @@ -30,7 +30,7 @@ }, "attack_speed": 0.2, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_hoe.json b/src/main/generated/data/minecraft/item/stone_hoe.json index af9ba7b7..d29e71ea 100644 --- a/src/main/generated/data/minecraft/item/stone_hoe.json +++ b/src/main/generated/data/minecraft/item/stone_hoe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.5, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_pickaxe.json b/src/main/generated/data/minecraft/item/stone_pickaxe.json index a65ac304..6d2db1b3 100644 --- a/src/main/generated/data/minecraft/item/stone_pickaxe.json +++ b/src/main/generated/data/minecraft/item/stone_pickaxe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/stone_shovel.json b/src/main/generated/data/minecraft/item/stone_shovel.json index de83a079..35e9f06c 100644 --- a/src/main/generated/data/minecraft/item/stone_shovel.json +++ b/src/main/generated/data/minecraft/item/stone_shovel.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_axe.json b/src/main/generated/data/minecraft/item/wooden_axe.json index aa8cc6bf..c8f30db9 100644 --- a/src/main/generated/data/minecraft/item/wooden_axe.json +++ b/src/main/generated/data/minecraft/item/wooden_axe.json @@ -33,7 +33,7 @@ }, "attack_speed": 0.2, "can_disable_blocking": true, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_hoe.json b/src/main/generated/data/minecraft/item/wooden_hoe.json index 5356c7cb..0ae7ebd5 100644 --- a/src/main/generated/data/minecraft/item/wooden_hoe.json +++ b/src/main/generated/data/minecraft/item/wooden_hoe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_pickaxe.json b/src/main/generated/data/minecraft/item/wooden_pickaxe.json index 412e19c3..2341574b 100644 --- a/src/main/generated/data/minecraft/item/wooden_pickaxe.json +++ b/src/main/generated/data/minecraft/item/wooden_pickaxe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.3, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_shovel.json b/src/main/generated/data/minecraft/item/wooden_shovel.json index d5caa0d2..8e6720b4 100644 --- a/src/main/generated/data/minecraft/item/wooden_shovel.json +++ b/src/main/generated/data/minecraft/item/wooden_shovel.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_attack": 2 + "item_damage_per_attack": 2 } }, "display": { diff --git a/src/main/java/net/errorcraft/itematic/access/village/VillagerProfessionAccess.java b/src/main/java/net/errorcraft/itematic/access/village/VillagerProfessionAccess.java index efe4b93d..5bcca79d 100644 --- a/src/main/java/net/errorcraft/itematic/access/village/VillagerProfessionAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/village/VillagerProfessionAccess.java @@ -6,7 +6,8 @@ public interface VillagerProfessionAccess { @Nullable - default TagKey itematic$gatherableItemsTag() { + default TagKey itematic$gatherableItems() { return null; } + default void itematic$setGatherableItems(TagKey gatherableItems) {} } diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index 3e920593..b918673d 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -72,6 +72,7 @@ import net.minecraft.registry.tag.*; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; import net.minecraft.stat.Stats; import net.minecraft.state.property.Properties; import net.minecraft.util.DyeColor; @@ -10627,8 +10628,14 @@ private void bootstrapMiscellaneous() { ItemDisplay.Builder.forItem(ItemKeys.SADDLE).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(1)) - .with(SaddleItemComponent.INSTANCE) - .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SADDLE))) + .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.SADDLE) + .equipSound(SoundEvents.ENTITY_HORSE_SADDLE) + .model(EquipmentAssetKeys.SADDLE) + .allowedEntities(this.entityTypes.getOrThrow(EntityTypeTags.CAN_EQUIP_SADDLE)) + .equipOnInteract(true) + .build() + )) + .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); this.registerable.register(ItemKeys.TURTLE_SCUTE, create( 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 ea8ecbc7..bd651543 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -33,7 +33,6 @@ public class ItemComponentTypes { public static final ItemComponentType BUCKET = register("bucket", new ItemComponentType<>(BucketItemComponent.CODEC)); public static final ItemComponentType CONSUMABLE = register("consumable", new ItemComponentType<>(ConsumableItemComponent.CODEC)); public static final ItemComponentType POTION_HOLDER = register("potion_holder", new ItemComponentType<>(PotionHolderItemComponent.CODEC)); - public static final ItemComponentType SADDLE = register("saddle", new ItemComponentType<>(SaddleItemComponent.CODEC)); public static final ItemComponentType STEERING = register("steering", new ItemComponentType<>(SteeringItemComponent.CODEC)); public static final ItemComponentType POINTABLE = register("pointable", new ItemComponentType<>(PointableItemComponent.CODEC)); public static final ItemComponentType PREVENT_USE_WHEN_USED_ON_TARGET = register("prevent_use_when_used_on_target", new ItemComponentType<>(PreventUseWhenUsedOnTargetItemComponent.CODEC)); 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 f321ced2..afd9c881 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 @@ -21,14 +21,13 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnReason; -import net.minecraft.entity.decoration.painting.PaintingEntity; +import net.minecraft.entity.decoration.painting.PaintingVariant; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; import net.minecraft.item.tooltip.TooltipType; import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.nbt.NbtOps; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.RegistryKeys; @@ -36,7 +35,6 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.StringIdentifiable; import net.minecraft.util.hit.BlockHitResult; @@ -120,27 +118,12 @@ public void appendTooltip(ItemStack stack, Item.TooltipContext context, List { - variant.getKey().ifPresent((key) -> { - tooltip.add(Text.translatable(key.getValue().toTranslationKey("painting", "title")).formatted(Formatting.YELLOW)); - tooltip.add(Text.translatable(key.getValue().toTranslationKey("painting", "author")).formatted(Formatting.GRAY)); - }); - tooltip.add(Text.translatable("painting.dimensions", variant.value().width(), variant.value().height())); - }, - () -> tooltip.add(RANDOM_TEXT) - ); - return; - } - - if (type.isCreative()) { + RegistryEntry paintingVariant = stack.get(DataComponentTypes.PAINTING_VARIANT); + if (paintingVariant != null) { + paintingVariant.value().title().ifPresent(tooltip::add); + paintingVariant.value().author().ifPresent(tooltip::add); + tooltip.add(Text.translatable("painting.dimensions", paintingVariant.value().width(), paintingVariant.value().height())); + } else if (type.isCreative()) { tooltip.add(RANDOM_TEXT); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/SaddleItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/SaddleItemComponent.java deleted file mode 100644 index dad2ac69..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/SaddleItemComponent.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.errorcraft.itematic.item.component.components; - -import com.mojang.serialization.Codec; -import net.errorcraft.itematic.item.ItemResult; -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.world.action.context.ItemStackExchanger; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.Saddleable; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundCategory; -import net.minecraft.util.Hand; -import net.minecraft.world.World; -import net.minecraft.world.event.GameEvent; - -public record SaddleItemComponent() implements ItemComponent { - public static final SaddleItemComponent INSTANCE = new SaddleItemComponent(); - public static final Codec CODEC = Codec.unit(INSTANCE); - - @Override - public ItemComponentType type() { - return ItemComponentTypes.SADDLE; - } - - @Override - public Codec codec() { - return CODEC; - } - - @Override - public ItemResult useOnEntity(PlayerEntity user, LivingEntity target, Hand hand, ItemStack stack, ItemStackExchanger stackExchanger) { - if (this.trySaddle(target, user.getWorld(), stack, SoundCategory.NEUTRAL)) { - return ItemResult.SUCCEED; - } - - return ItemResult.PASS; - } - - public boolean trySaddle(LivingEntity target, World world, ItemStack stack, SoundCategory soundCategory) { - if (!(target instanceof Saddleable saddleable)) { - return false; - } - - if (!target.isAlive() || saddleable.isSaddled() || !saddleable.canBeSaddled()) { - return false; - } - - if (!world.isClient()) { - saddleable.saddle(stack.split(1), soundCategory); - target.getWorld().emitGameEvent(target, GameEvent.EQUIP, target.getPos()); - } - - return true; - } -} 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 116cab77..6ac74f19 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 @@ -31,9 +31,9 @@ import java.util.List; -public record WeaponItemComponent(int damagePerAttack, boolean canDisableBlocking, boolean maySmash, WeaponAttackDamageDataComponent attackDamage, double attackSpeed) implements ItemComponent { +public record WeaponItemComponent(int itemDamagePerAttack, boolean canDisableBlocking, boolean maySmash, WeaponAttackDamageDataComponent attackDamage, double attackSpeed) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codecs.NON_NEGATIVE_INT.optionalFieldOf("damage_per_attack", 1).forGetter(WeaponItemComponent::damagePerAttack), + Codecs.NON_NEGATIVE_INT.optionalFieldOf("item_damage_per_attack", 1).forGetter(WeaponItemComponent::itemDamagePerAttack), Codec.BOOL.optionalFieldOf("can_disable_blocking", false).forGetter(WeaponItemComponent::canDisableBlocking), Codec.BOOL.optionalFieldOf("may_smash", false).forGetter(WeaponItemComponent::maySmash), WeaponAttackDamageDataComponent.CODEC.fieldOf("attack_damage").forGetter(WeaponItemComponent::attackDamage), @@ -93,13 +93,13 @@ public void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, stack.itematic$invokeEvent(ItemEvents.USE_WEAPON, context); WeaponComponent weapon = stack.get(DataComponentTypes.WEAPON); if (weapon != null) { - stack.itematic$damage(weapon.damagePerAttack(), context); + stack.itematic$damage(weapon.itemDamagePerAttack(), context); } } @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.WEAPON, new WeaponComponent(this.damagePerAttack, this.canDisableBlocking)); + builder.add(DataComponentTypes.WEAPON, new WeaponComponent(this.itemDamagePerAttack, this.canDisableBlocking)); builder.add(ItematicDataComponentTypes.WEAPON_ATTACK_DAMAGE, this.attackDamage); builder.add(ItematicDataComponentTypes.ATTACK_SPEED_MULTIPLIER, this.attackSpeed); } diff --git a/src/main/java/net/errorcraft/itematic/item/dispense/behavior/DispenseBehaviors.java b/src/main/java/net/errorcraft/itematic/item/dispense/behavior/DispenseBehaviors.java index 20b59001..15e3d40c 100644 --- a/src/main/java/net/errorcraft/itematic/item/dispense/behavior/DispenseBehaviors.java +++ b/src/main/java/net/errorcraft/itematic/item/dispense/behavior/DispenseBehaviors.java @@ -113,9 +113,6 @@ public static void bootstrap(Registerable registerable) { .add(PlaceCarvedPumpkinAction.of(PositionTarget.INTERACTED_POSITION)) .add(EquipEntityAtPositionAction.of(PositionTarget.INTERACTED_POSITION))) ).doNotDispenseOnFailure().build()); - registerable.register(SADDLE, DispenseBehavior.builder( - SaddleEntityAtPositionAction.of(PositionTarget.INTERACTED_POSITION) - ).build()); registerable.register(SHEAR, DispenseBehavior.builder( PassingSequenceHandler.builder() .add(ShearAtPositionAction.of(PositionTarget.INTERACTED_POSITION)) diff --git a/src/main/java/net/errorcraft/itematic/item/group/entry/entries/PaintingVariantItemGroupEntry.java b/src/main/java/net/errorcraft/itematic/item/group/entry/entries/PaintingVariantItemGroupEntry.java index 0f4b7af2..7e2432c9 100644 --- a/src/main/java/net/errorcraft/itematic/item/group/entry/entries/PaintingVariantItemGroupEntry.java +++ b/src/main/java/net/errorcraft/itematic/item/group/entry/entries/PaintingVariantItemGroupEntry.java @@ -1,34 +1,23 @@ package net.errorcraft.itematic.item.group.entry.entries; -import com.mojang.logging.LogUtils; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.entity.EntityTypeKeys; import net.errorcraft.itematic.item.group.entry.ItemGroupEntryType; import net.errorcraft.itematic.item.group.entry.PossiblyHiddenItemGroupEntry; import net.errorcraft.itematic.mixin.item.ItemGroupsAccessor; import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.NbtComponent; -import net.minecraft.entity.Entity; -import net.minecraft.entity.decoration.painting.PaintingEntity; import net.minecraft.entity.decoration.painting.PaintingVariant; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtOps; import net.minecraft.predicate.TagPredicate; import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.RegistryOps; -import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryFixedCodec; import net.minecraft.registry.tag.TagKey; -import org.slf4j.Logger; import java.util.Collection; import java.util.Comparator; -import java.util.Optional; public class PaintingVariantItemGroupEntry extends PossiblyHiddenItemGroupEntry { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> createCodec(instance).and(instance.group( @@ -36,7 +25,6 @@ public class PaintingVariantItemGroupEntry extends PossiblyHiddenItemGroupEntry TagPredicate.createCodec(RegistryKeys.PAINTING_VARIANT).fieldOf("tag").forGetter(entry -> entry.tag) )).apply(instance, PaintingVariantItemGroupEntry::new)); private static final Comparator> PAINTING_VARIANT_COMPARATOR = ItemGroupsAccessor.paintingVariantComparator(); - private static final Logger LOGGER = LogUtils.getLogger(); private final RegistryEntry item; private final TagPredicate tag; @@ -66,18 +54,14 @@ public ItemGroupEntryType type() { @Override protected Collection createStacks(ItemGroup.DisplayContext context) { - RegistryWrapper.WrapperLookup lookup = context.lookup(); - RegistryOps ops = lookup.getOps(NbtOps.INSTANCE); - return lookup.getOrThrow(RegistryKeys.PAINTING_VARIANT) + return context.lookup() + .getOrThrow(RegistryKeys.PAINTING_VARIANT) .streamEntries() .filter(this.tag::test) .sorted(PAINTING_VARIANT_COMPARATOR) - .map(variant -> NbtComponent.DEFAULT.with(ops, PaintingEntity.VARIANT_MAP_CODEC, variant).resultOrPartial(LOGGER::error)) - .flatMap(Optional::stream) - .map(nbt -> nbt.apply(newNbt -> newNbt.putString(Entity.ID_KEY, EntityTypeKeys.PAINTING.getValue().toString()))) - .map(nbt -> { + .map(paintingVariant -> { ItemStack stack = new ItemStack(this.item); - stack.set(DataComponentTypes.ENTITY_DATA, nbt); + stack.set(DataComponentTypes.PAINTING_VARIANT, paintingVariant); return stack; }) .toList(); diff --git a/src/main/java/net/errorcraft/itematic/mixin/enchantment/EnchantmentHelperAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/enchantment/EnchantmentHelperAccessor.java new file mode 100644 index 00000000..2f021410 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/enchantment/EnchantmentHelperAccessor.java @@ -0,0 +1,16 @@ +package net.errorcraft.itematic.mixin.enchantment; + +import net.minecraft.component.ComponentType; +import net.minecraft.component.type.ItemEnchantmentsComponent; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(EnchantmentHelper.class) +public interface EnchantmentHelperAccessor { + @Invoker("getEnchantmentsComponentType") + static ComponentType getComponentType(ItemStack stack) { + throw new AssertionError(); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/GatherItemsVillagerTaskExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/GatherItemsVillagerTaskExtender.java index 6af17c0d..f3bff071 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/GatherItemsVillagerTaskExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/GatherItemsVillagerTaskExtender.java @@ -12,7 +12,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; -import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; @@ -26,7 +25,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; import java.util.Set; @@ -54,15 +52,8 @@ private Map getItemFoodPointsUseRegistryKey(ServerWorld serverWor Map.Entry::getValue )); } - return this.itemFoodPointsCache; - } - @Inject( - method = "getGatherableItems", - at = @At("HEAD") - ) - private static void storeItemAccess(VillagerEntity entity, VillagerEntity target, CallbackInfoReturnable> info, @Share("itemAccess")LocalRef> itemRegistry) { - itemRegistry.set(entity.getWorld().getRegistryManager().getOrThrow(RegistryKeys.ITEM)); + return this.itemFoodPointsCache; } @Redirect( @@ -72,13 +63,14 @@ private static void storeItemAccess(VillagerEntity entity, VillagerEntity target target = "Lnet/minecraft/village/VillagerProfession;gatherableItems()Lcom/google/common/collect/ImmutableSet;" ) ) - private static ImmutableSet gatherableItemsUseDynamicRegistry(VillagerProfession instance, VillagerEntity entity, @Share("itemAccess")LocalRef> itemRegistry) { - TagKey tag = instance.itematic$gatherableItemsTag(); + private static ImmutableSet gatherableItemsUseDynamicRegistry(VillagerProfession instance, VillagerEntity entity) { + TagKey tag = instance.itematic$gatherableItems(); if (tag == null) { return ImmutableSet.of(); } - return itemRegistry.get() + return entity.getRegistryManager() + .getOrThrow(RegistryKeys.ITEM) .getOptional(tag) .stream() .flatMap(RegistryEntryList::stream) @@ -105,7 +97,7 @@ private Item keepRunningGetWheatUseDynamicRegistry(ServerWorld serverWorld) { target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;" ) ) - private static void storeInventoryStackEntry(VillagerEntity villager, Set validItems, LivingEntity target, CallbackInfo info, @Local(ordinal = 1) ItemStack inventoryStack, @Share("registryEntry") LocalRef> foundItem) { + private static void storeInventoryStackRegistryEntry(VillagerEntity villager, Set validItems, LivingEntity target, CallbackInfo info, @Local(ordinal = 1) ItemStack inventoryStack, @Share("registryEntry") LocalRef> foundItem) { foundItem.set(inventoryStack.getRegistryEntry()); } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/mob/CreakingEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/mob/CreakingEntityExtender.java new file mode 100644 index 00000000..47582d52 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/mob/CreakingEntityExtender.java @@ -0,0 +1,23 @@ +package net.errorcraft.itematic.mixin.entity.mob; + +import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.CreakingEntity; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CreakingEntity.class) +public abstract class CreakingEntityExtender extends MobEntityExtender { + protected CreakingEntityExtender(EntityType entityType, World world) { + super(entityType, world); + } + + @Override + protected @Nullable RegistryKey pickBlockKey() { + return ItemKeys.CREAKING_SPAWN_EGG; + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/AbstractHorseEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/AbstractHorseEntityExtender.java index 7baee081..eb495593 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/AbstractHorseEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/AbstractHorseEntityExtender.java @@ -144,29 +144,4 @@ private boolean isOfForGoldenAppleUseRegistryKeyCheck(ItemStack instance, Item i private boolean isOfForEnchantedGoldenAppleUseRegistryKeyCheck(ItemStack instance, Item item) { return instance.itematic$isOf(ItemKeys.ENCHANTED_GOLDEN_APPLE); } - - @Redirect( - method = "readCustomDataFromNbt", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForSaddleUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SADDLE); - } - - @Mixin(targets = "net/minecraft/entity/passive/AbstractHorseEntity$2") - public static class SaddleStackReferenceExtender { - @Redirect( - method = "set", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForSaddleUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SADDLE); - } - } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/PigEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/PigEntityExtender.java index 3e3990d7..191dbebf 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/PigEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/PigEntityExtender.java @@ -4,7 +4,6 @@ import net.errorcraft.itematic.item.ItematicItemTags; import net.errorcraft.itematic.mixin.entity.mob.MobEntityExtender; import net.minecraft.entity.EntityType; -import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ai.goal.Goal; import net.minecraft.entity.ai.goal.GoalSelector; import net.minecraft.entity.passive.AnimalEntity; @@ -15,7 +14,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.tag.TagKey; -import net.minecraft.server.world.ServerWorld; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -67,28 +65,6 @@ private ItemStack newItemStackForGoldenSwordUseCreateStack(ItemConvertible item) return this.getWorld().itematic$createStack(ItemKeys.GOLDEN_SWORD); } - @Redirect( - method = "interactMob", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForSaddleUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SADDLE); - } - - @Redirect( - method = "dropInventory", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/entity/passive/PigEntity;dropItem(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/entity/ItemEntity;" - ) - ) - private ItemEntity dropItemForSaddleUseRegistryKey(PigEntity instance, ServerWorld world, ItemConvertible itemConvertible) { - return this.itematic$dropItem(world, ItemKeys.SADDLE); - } - @Redirect( method = "getControllingPassenger", at = @At( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/StriderEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/StriderEntityExtender.java index e78b02b0..ddf57137 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/StriderEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/StriderEntityExtender.java @@ -4,7 +4,6 @@ import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.mixin.entity.mob.MobEntityExtender; import net.minecraft.entity.EntityType; -import net.minecraft.entity.ItemEntity; import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.passive.StriderEntity; import net.minecraft.entity.player.PlayerEntity; @@ -12,7 +11,6 @@ import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.registry.RegistryKey; -import net.minecraft.server.world.ServerWorld; import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -26,28 +24,6 @@ protected StriderEntityExtender(EntityType entityType, W super(entityType, world); } - @Redirect( - method = "interactMob", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForSaddleUseRegistryKey(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SADDLE); - } - - @Redirect( - method = "dropInventory", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/entity/passive/StriderEntity;dropItem(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/entity/ItemEntity;" - ) - ) - private ItemEntity dropItemForSaddleUseRegistryKey(StriderEntity instance, ServerWorld world, ItemConvertible itemConvertible) { - return this.itematic$dropItem(world, ItemKeys.SADDLE); - } - @Redirect( method = "getControllingPassenger", at = @At( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/VillagerEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/VillagerEntityExtender.java index 018a4082..b7fda21b 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/VillagerEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/VillagerEntityExtender.java @@ -46,7 +46,7 @@ protected VillagerEntityExtender(EntityType entityType, ) ) private boolean containsForGatherableItemsUseItemTagCheck(ImmutableSet instance, Object o, @Local(argsOnly = true) ItemStack stack) { - TagKey tag = this.getVillagerData().getProfession().itematic$gatherableItemsTag(); + TagKey tag = this.getVillagerData().profession().value().itematic$gatherableItems(); if (tag == null) { return false; } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java index 526904bb..46b95335 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java @@ -22,6 +22,7 @@ import net.minecraft.util.Util; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -61,7 +62,8 @@ private ItemStack newItemStackForPotionUseCreateStack(Item item, RegistryEntry

profession; @Shadow @Final @@ -34,11 +35,11 @@ public class VillagerDataExtender implements VillagerDataAccess { }; public @Nullable TagKey itematic$tradeTag() { - if (this.profession.workSound() == null) { + if (this.profession.value().workSound() == null) { return null; } - Identifier tag = Identifier.ofVanilla(this.profession.id() + "_" + this.levelName()); + Identifier tag = Identifier.ofVanilla(this.profession.value().id() + "_" + this.levelName()); return TagKey.of(ItematicRegistryKeys.TRADE, tag); } diff --git a/src/main/java/net/errorcraft/itematic/mixin/village/VillagerProfessionExtender.java b/src/main/java/net/errorcraft/itematic/mixin/village/VillagerProfessionExtender.java index 6eea7a95..0e03d36c 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/village/VillagerProfessionExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/village/VillagerProfessionExtender.java @@ -1,38 +1,40 @@ package net.errorcraft.itematic.mixin.village; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.errorcraft.itematic.access.village.VillagerProfessionAccess; import net.errorcraft.itematic.item.ItematicItemTags; import net.minecraft.item.Item; import net.minecraft.registry.tag.TagKey; import net.minecraft.village.VillagerProfession; 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.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(VillagerProfession.class) public class VillagerProfessionExtender implements VillagerProfessionAccess { - @Shadow - @Final - public static VillagerProfession FARMER; - @Unique - private TagKey gatherableItemsTag; + private TagKey gatherableItems; - @Inject( - method = "", - at = @At("TAIL") + @ModifyExpressionValue( + method = "registerAndGetDefault", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/village/VillagerProfession;register(Lnet/minecraft/registry/Registry;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/registry/RegistryKey;Lcom/google/common/collect/ImmutableSet;Lcom/google/common/collect/ImmutableSet;Lnet/minecraft/sound/SoundEvent;)Lnet/minecraft/village/VillagerProfession;" + ) ) - private static void staticSetGatherableItemsTag(CallbackInfo info) { - ((VillagerProfessionExtender)(Object) FARMER).gatherableItemsTag = ItematicItemTags.FARMER_VILLAGER_GATHERABLE_ITEMS; + private static VillagerProfession setGatherableItemsTag(VillagerProfession original) { + original.itematic$setGatherableItems(ItematicItemTags.FARMER_VILLAGER_GATHERABLE_ITEMS); + return original; + } + + @Override + public @Nullable TagKey itematic$gatherableItems() { + return this.gatherableItems; } @Override - public @Nullable TagKey itematic$gatherableItemsTag() { - return this.gatherableItemsTag; + public void itematic$setGatherableItems(TagKey gatherableItems) { + this.gatherableItems = gatherableItems; } } diff --git a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java index a4433d63..4547c53a 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java @@ -378,6 +378,7 @@ public static void bootstrap(Registerable registerable) { RegistryEntryLookup enchantments = registerable.getRegistryLookup(RegistryKeys.ENCHANTMENT); RegistryEntryLookup statusEffects = registerable.getRegistryLookup(RegistryKeys.STATUS_EFFECT); RegistryEntryLookup potions = registerable.getRegistryLookup(RegistryKeys.POTION); + RegistryEntryLookup villagerTypes = registerable.getRegistryLookup(RegistryKeys.VILLAGER_TYPE); registerable.register(BUY_WHEAT, buy(items, items.getOrThrow(ItemKeys.WHEAT), 20, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); registerable.register(BUY_POTATO, buy(items, items.getOrThrow(ItemKeys.POTATO), 26, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); @@ -410,13 +411,13 @@ public static void bootstrap(Registerable registerable) { registerable.register(BUY_TROPICAL_FISH, buy(items, items.getOrThrow(ItemKeys.TROPICAL_FISH), 6, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertBuyTradeExperience())); registerable.register(BUY_PUFFERFISH, buy(items, items.getOrThrow(ItemKeys.PUFFERFISH), 4, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.masterTradeExperience())); registerable.register(BUY_BOAT, buyFromType(items, items.getOrThrow(ItemKeys.OAK_BOAT), Map.of( - VillagerType.PLAINS, items.getOrThrow(ItemKeys.OAK_BOAT), - VillagerType.TAIGA, items.getOrThrow(ItemKeys.SPRUCE_BOAT), - VillagerType.SNOW, items.getOrThrow(ItemKeys.SPRUCE_BOAT), - VillagerType.DESERT, items.getOrThrow(ItemKeys.JUNGLE_BOAT), - VillagerType.JUNGLE, items.getOrThrow(ItemKeys.JUNGLE_BOAT), - VillagerType.SAVANNA, items.getOrThrow(ItemKeys.ACACIA_BOAT), - VillagerType.SWAMP, items.getOrThrow(ItemKeys.DARK_OAK_BOAT) + villagerTypes.getOrThrow(VillagerType.PLAINS), items.getOrThrow(ItemKeys.OAK_BOAT), + villagerTypes.getOrThrow(VillagerType.TAIGA), items.getOrThrow(ItemKeys.SPRUCE_BOAT), + villagerTypes.getOrThrow(VillagerType.SNOW), items.getOrThrow(ItemKeys.SPRUCE_BOAT), + villagerTypes.getOrThrow(VillagerType.DESERT), items.getOrThrow(ItemKeys.JUNGLE_BOAT), + villagerTypes.getOrThrow(VillagerType.JUNGLE), items.getOrThrow(ItemKeys.JUNGLE_BOAT), + villagerTypes.getOrThrow(VillagerType.SAVANNA), items.getOrThrow(ItemKeys.ACACIA_BOAT), + villagerTypes.getOrThrow(VillagerType.SWAMP), items.getOrThrow(ItemKeys.DARK_OAK_BOAT) ))); registerable.register(BUY_WHITE_WOOL, buy(items, items.getOrThrow(ItemKeys.WHITE_WOOL), 18, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); registerable.register(BUY_BROWN_WOOL, buy(items, items.getOrThrow(ItemKeys.BROWN_WOOL), 18, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); @@ -728,7 +729,7 @@ private static Trade buy(RegistryEntryLookup items, RegistryEntry it .build(); } - private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry item, Map> types) { + private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry item, Map, RegistryEntry> types) { return Trade.builder(Trade.Entry.ofEmerald(items)) .wants(Trade.Entry.of(item)) .tradeExperience(TradeOffersAccessor.masterTradeExperience()) diff --git a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java index df0faf6b..d0da8dc9 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java @@ -23,12 +23,12 @@ import java.util.Map; import java.util.Optional; -public record ItemFromTypeTradeModifier(Map> types) implements TradeModifier { +public record ItemFromTypeTradeModifier(Map, RegistryEntry> types) implements TradeModifier { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - Codec.simpleMap(Registries.VILLAGER_TYPE.getCodec(), RegistryFixedCodec.of(RegistryKeys.ITEM), Registries.VILLAGER_TYPE).fieldOf("types").forGetter(ItemFromTypeTradeModifier::types) + Codec.simpleMap(Registries.VILLAGER_TYPE.getEntryCodec(), RegistryFixedCodec.of(RegistryKeys.ITEM), Registries.VILLAGER_TYPE).fieldOf("types").forGetter(ItemFromTypeTradeModifier::types) ).apply(instance, ItemFromTypeTradeModifier::new)); - public static ItemFromTypeTradeModifier of(Map> types) { + public static ItemFromTypeTradeModifier of(Map, RegistryEntry> types) { return new ItemFromTypeTradeModifier(types); } @@ -42,10 +42,12 @@ public Optional apply(Trade.Input wants, ItemStack gives, LootContex if (!(context.get(LootContextParameters.THIS_ENTITY) instanceof VillagerDataContainer container)) { return Optional.empty(); } - VillagerType type = container.getVillagerData().getType(); + + RegistryEntry type = container.getVillagerData().type(); if (!this.types.containsKey(type)) { return Optional.empty(); } + ItemStack givesActual = gives.itematic$copyWithItem(this.types.get(type)); return Optional.of(new TradedItem(givesActual.getRegistryEntry(), givesActual.getCount(), ComponentPredicate.of(givesActual.getComponents()))); } 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 ebca8365..7637ee05 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java @@ -40,7 +40,6 @@ public class ActionTypeKeys { public static final RegistryKey> INVOKE_GAME_EVENT = of("invoke_game_event"); public static final RegistryKey> INVOKE_ITEM_EVENT = of("invoke_item_event"); public static final RegistryKey> PLACE_CARVED_PUMPKIN = of("place_carved_pumpkin"); - public static final RegistryKey> SADDLE_ENTITY_AT_POSITION = of("saddle_entity_at_position"); public static final RegistryKey> SHEAR_AT_POSITION = of("shear_at_position"); public static final RegistryKey> SHOOT_PROJECTILE_FROM_ITEM = of("shoot_projectile_from_item"); public static final RegistryKey> SPAWN_ENTITY = of("spawn_entity"); 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 8dfc4db3..9731220d 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java @@ -41,7 +41,6 @@ public class ActionTypes { public static final ActionType INVOKE_GAME_EVENT = register(ActionTypeKeys.INVOKE_GAME_EVENT, new ActionType<>(InvokeGameEventAction.CODEC)); public static final ActionType INVOKE_ITEM_EVENT = register(ActionTypeKeys.INVOKE_ITEM_EVENT, new ActionType<>(InvokeItemEventAction.CODEC)); public static final ActionType PLACE_CARVED_PUMPKIN = register(ActionTypeKeys.PLACE_CARVED_PUMPKIN, new ActionType<>(PlaceCarvedPumpkinAction.CODEC)); - public static final ActionType SADDLE_ENTITY_AT_POSITION = register(ActionTypeKeys.SADDLE_ENTITY_AT_POSITION, new ActionType<>(SaddleEntityAtPositionAction.CODEC)); public static final ActionType SHEAR_AT_POSITION = register(ActionTypeKeys.SHEAR_AT_POSITION, new ActionType<>(ShearAtPositionAction.CODEC)); public static final ActionType SHOOT_PROJECTILE_FROM_ITEM = register(ActionTypeKeys.SHOOT_PROJECTILE_FROM_ITEM, new ActionType<>(ShootProjectileFromItemAction.CODEC)); public static final ActionType SPAWN_ENTITY = register(ActionTypeKeys.SPAWN_ENTITY, new ActionType<>(SpawnEntityAction.CODEC)); diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/SaddleEntityAtPositionAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/SaddleEntityAtPositionAction.java deleted file mode 100644 index 784dd84f..00000000 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/SaddleEntityAtPositionAction.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.errorcraft.itematic.world.action.actions; - -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.SaddleItemComponent; -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.PositionTarget; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.Saddleable; -import net.minecraft.item.ItemStack; -import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.sound.SoundCategory; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; - -import java.util.List; - -public record SaddleEntityAtPositionAction(PositionTarget position) implements Action { - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - PositionTarget.CODEC.fieldOf("position").forGetter(SaddleEntityAtPositionAction::position) - ).apply(instance, SaddleEntityAtPositionAction::new)); - - public static SaddleEntityAtPositionAction of(PositionTarget position) { - return new SaddleEntityAtPositionAction(position); - } - - @Override - public ActionType type() { - return ActionTypes.SADDLE_ENTITY_AT_POSITION; - } - - @Override - public boolean execute(ActionContext context) { - ItemStack stack = context.getOrDefault(LootContextParameters.TOOL, ItemStack.EMPTY); - return stack.itematic$getBehavior(ItemComponentTypes.SADDLE) - .map(saddle -> this.trySaddle(saddle, stack, context)) - .orElse(false); - } - - private boolean trySaddle(SaddleItemComponent saddle, ItemStack stack, ActionContext context) { - BlockPos pos = context.getBlockPos(this.position.parameter()); - if (pos == null) { - return false; - } - - ServerWorld world = context.world(); - List targets = world.getEntitiesByClass( - LivingEntity.class, - new Box(pos), - entity -> entity instanceof Saddleable - ); - for (LivingEntity target : targets) { - if (saddle.trySaddle(target, world, stack, SoundCategory.BLOCKS)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 7f18687c..f192ff59 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -94,12 +94,6 @@ "net/minecraft/class_3611": [ "net/errorcraft/itematic/access/fluid/FluidAccess" ], - "net/minecraft/class_3850": [ - "net/errorcraft/itematic/access/village/VillagerDataAccess" - ], - "net/minecraft/class_3852": [ - "net/errorcraft/itematic/access/village/VillagerProfessionAccess" - ], "net/minecraft/class_4059\u0024class_9076": [ "net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess" ], diff --git a/src/main/resources/itematic.classtweaker b/src/main/resources/itematic.classtweaker index 5955614d..65206267 100644 --- a/src/main/resources/itematic.classtweaker +++ b/src/main/resources/itematic.classtweaker @@ -19,3 +19,5 @@ inject-interface net/minecraft/item/ItemUsageContext net/errorcraft/itemat inject-interface net/minecraft/entity/EntityType net/errorcraft/itematic/access/entity/EntityTypeAccess inject-interface net/minecraft/entity/EntityType$Builder net/errorcraft/itematic/access/entity/EntityTypeBuilderAccess inject-interface net/minecraft/block/entity/BlockEntity net/errorcraft/itematic/access/block/entity/BlockEntityAccess +inject-interface net/minecraft/village/VillagerData net/errorcraft/itematic/access/village/VillagerDataAccess +inject-interface net/minecraft/village/VillagerProfession net/errorcraft/itematic/access/village/VillagerProfessionAccess diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 76d0ba56..2f7915f5 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -92,6 +92,7 @@ "component.type.ToolComponentExtender", "component.type.ToolComponentExtender$RuleExtender", "datafixer.SchemasExtender", + "enchantment.EnchantmentHelperAccessor", "enchantment.EnchantmentHelperExtender", "entity.BucketableExtender", "entity.CrossbowUserExtender", @@ -132,6 +133,7 @@ "entity.mob.BlazeEntityExtender", "entity.mob.BoggedEntityExtender", "entity.mob.CaveSpiderEntityExtender", + "entity.mob.CreakingEntityExtender", "entity.mob.CreeperEntityExtender", "entity.mob.DrownedEntityExtender", "entity.mob.DrownedEntityExtender$TridentAttackGoalExtender", @@ -175,7 +177,6 @@ "entity.passive.AbstractDonkeyEntityExtender", "entity.passive.AbstractDonkeyEntityExtender$StackReferenceExtender", "entity.passive.AbstractHorseEntityExtender", - "entity.passive.AbstractHorseEntityExtender$SaddleStackReferenceExtender", "entity.passive.AllayEntityExtender", "entity.passive.ArmadilloEntityExtender", "entity.passive.AxolotlEntityExtender", @@ -363,7 +364,6 @@ "screen.EnchantmentScreenHandlerExtender$LapisLazuliSlotExtender", "screen.GrindstoneScreenHandlerExtender", "screen.GrindstoneScreenHandlerExtender$EnchantedItemSlotExtender", - "screen.HorseScreenHandlerExtender$SaddleSlotExtender", "screen.LoomScreenHandlerExtender", "screen.LoomScreenHandlerExtender$BannerPatternSlotExtender", "screen.LoomScreenHandlerExtender$BannerSlotExtender", From d053fc58bab26c6ffe71b157241794ce9a848268 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Mon, 6 Apr 2026 00:19:15 +0200 Subject: [PATCH 03/12] Port to 25w04a --- gradle.properties | 6 +- .../screen/ingame/SmithingScreenExtender.java | 13 +- .../itematic/data/ItematicData.java | 1 - .../registry/SmithingTemplateProvider.java | 24 - .../block/WaterCauldronBlockTestSuite.java | 2 +- .../ThrowableItemComponentTestSuite.java | 4 +- .../StructureTemplateManagerExtender.java | 6 +- .../data/minecraft/item/amethyst_shard.json | 3 +- .../bolt_armor_trim_smithing_template.json | 37 +- .../coast_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/copper_ingot.json | 3 +- .../data/minecraft/item/diamond.json | 3 +- .../data/minecraft/item/diamond_axe.json | 2 +- .../minecraft/item/diamond_horse_armor.json | 5 +- .../dune_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/emerald.json | 3 +- .../eye_armor_trim_smithing_template.json | 37 +- .../flow_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/goat_horn.json | 2 +- .../data/minecraft/item/gold_ingot.json | 3 +- .../data/minecraft/item/golden_axe.json | 2 +- .../minecraft/item/golden_horse_armor.json | 5 +- .../host_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/iron_axe.json | 2 +- .../data/minecraft/item/iron_horse_armor.json | 5 +- .../data/minecraft/item/iron_ingot.json | 3 +- .../data/minecraft/item/lapis_lazuli.json | 3 +- .../data/minecraft/item/leaf_litter.json | 3 + .../minecraft/item/leather_horse_armor.json | 5 +- .../data/minecraft/item/lingering_potion.json | 2 +- .../data/minecraft/item/netherite_axe.json | 2 +- .../data/minecraft/item/netherite_ingot.json | 3 +- .../netherite_upgrade_smithing_template.json | 35 +- .../generated/data/minecraft/item/quartz.json | 3 +- .../raiser_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/redstone.json | 3 +- .../data/minecraft/item/resin_brick.json | 3 +- .../rib_armor_trim_smithing_template.json | 37 +- .../sentry_armor_trim_smithing_template.json | 37 +- .../shaper_armor_trim_smithing_template.json | 37 +- .../generated/data/minecraft/item/shield.json | 10 + .../silence_armor_trim_smithing_template.json | 37 +- .../snout_armor_trim_smithing_template.json | 37 +- .../spire_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/splash_potion.json | 2 +- .../data/minecraft/item/stone_axe.json | 2 +- .../tide_armor_trim_smithing_template.json | 37 +- .../vex_armor_trim_smithing_template.json | 37 +- .../ward_armor_trim_smithing_template.json | 37 +- ...ayfinder_armor_trim_smithing_template.json | 37 +- .../wild_armor_trim_smithing_template.json | 37 +- .../data/minecraft/item/wolf_armor.json | 3 + .../data/minecraft/item/wooden_axe.json | 2 +- .../data/minecraft/item/written_book.json | 25 - .../functional_blocks.json | 8 +- .../smithing_template/bolt_pattern.json | 4 - .../smithing_template/coast_pattern.json | 4 - .../smithing_template/dune_pattern.json | 4 - .../smithing_template/eye_pattern.json | 4 - .../smithing_template/flow_pattern.json | 4 - .../smithing_template/host_pattern.json | 4 - .../smithing_template/netherite_upgrade.json | 5 - .../smithing_template/raiser_pattern.json | 4 - .../smithing_template/rib_pattern.json | 4 - .../smithing_template/sentry_pattern.json | 4 - .../smithing_template/shaper_pattern.json | 4 - .../smithing_template/silence_pattern.json | 4 - .../smithing_template/snout_pattern.json | 4 - .../smithing_template/spire_pattern.json | 4 - .../smithing_template/tide_pattern.json | 4 - .../smithing_template/vex_pattern.json | 4 - .../smithing_template/ward_pattern.json | 4 - .../smithing_template/wayfinder_pattern.json | 4 - .../smithing_template/wild_pattern.json | 4 - .../net/errorcraft/itematic/Itematic.java | 4 +- .../access/block/entity/SherdsAccess.java | 3 - .../item/AnimalArmorItemTypeAccess.java | 15 - .../itematic/access/item/ItemAccess.java | 5 + .../itematic/block/ComposterBlockUtil.java | 11 - .../itematic/entity/EntityTypeKeys.java | 3 +- .../AttributeModifiers.java} | 12 +- .../errorcraft/itematic/item/ItemDisplay.java | 7 +- .../errorcraft/itematic/item/ItemUtil.java | 615 ++++++++++-------- .../errorcraft/itematic/item/Tooltips.java | 44 ++ .../item/component/ItemComponent.java | 4 +- .../item/component/ItemComponentTypes.java | 4 +- .../AttackBlockingItemComponent.java | 35 + .../BannerPatternHolderItemComponent.java | 12 +- .../BannerPatternItemComponent.java | 7 + .../components/BlockItemComponent.java | 9 - .../components/DamageableItemComponent.java | 31 +- .../components/EntityItemComponent.java | 12 +- .../components/EquipmentItemComponent.java | 37 +- .../FireworkExplosionHolderItemComponent.java | 14 - .../components/FireworkItemComponent.java | 11 - .../components/MapHolderItemComponent.java | 9 - .../OminousEffectProviderItemComponent.java | 13 - .../components/PlayableItemComponent.java | 46 +- .../components/PlayableSongItemComponent.java | 2 +- .../components/PotionHolderItemComponent.java | 21 +- .../SmithingTemplateItemComponent.java | 58 -- ...SmithingTemplateProviderItemComponent.java | 28 + .../components/TextHolderItemComponent.java | 32 +- .../TrimMaterialProviderItemComponent.java | 37 ++ .../components/WeaponItemComponent.java | 38 +- .../item/composting/CompostChances.java | 11 + .../entries/InstrumentItemGroupEntry.java | 3 +- .../smithing/template/SmithingTemplate.java | 7 +- .../template/SmithingTemplateType.java | 6 - .../template/SmithingTemplateTypeKeys.java | 16 - .../template/SmithingTemplateTypes.java | 20 - .../smithing/template/SmithingTemplates.java | 62 +- .../ItemUpgradeSmithingTemplate.java | 48 +- .../TrimPatternSmithingTemplate.java | 47 +- .../mixin/block/BeehiveBlockExtender.java | 3 +- .../block/DecoratedPotBlockExtender.java | 22 - .../mixin/block/entity/SherdsExtender.java | 74 +-- .../mixin/entity/LivingEntityExtender.java | 11 - .../task/RemoveOffHandItemTaskExtender.java | 16 +- .../entity/passive/GoatEntityExtender.java | 3 +- .../entity/player/PlayerEntityExtender.java | 24 - .../thrown/LingeringPotionEntityExtender.java | 22 + .../thrown/PotionEntityExtender.java | 36 - .../thrown/SplashPotionEntityExtender.java | 22 + .../mixin/item/AnimalArmorItemExtender.java | 35 - .../itematic/mixin/item/ItemExtender.java | 38 +- .../mixin/item/ItemStackExtender.java | 27 +- .../item/SmithingTemplateItemAccessor.java | 37 +- .../SmithingTransformRecipeExtender.java | 4 +- .../recipe/SmithingTrimRecipeExtender.java | 21 +- .../registry/BuiltinRegistriesExtender.java | 2 - .../registry/RegistryLoaderExtender.java | 3 - .../screen/LoomScreenHandlerExtender.java | 94 +-- .../itematic/registry/ItematicRegistries.java | 6 +- .../registry/ItematicRegistryKeys.java | 2 - .../itematic/sound/SoundEventKeys.java | 4 + .../itematic/util/IdentifierUtil.java | 15 - .../net/errorcraft/itematic/util/Util.java | 11 +- .../itematic/world/action/ActionTypeKeys.java | 1 - .../itematic/world/action/ActionTypes.java | 1 - .../actions/OpenBookFromItemAction.java | 47 -- src/main/resources/fabric.mod.json | 3 - src/main/resources/itematic.mixins.json | 4 +- 143 files changed, 1520 insertions(+), 1421 deletions(-) delete mode 100644 src/datagen/java/net/errorcraft/itematic/data/server/registry/SmithingTemplateProvider.java delete mode 100644 src/main/generated/data/minecraft/smithing_template/bolt_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/coast_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/dune_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/eye_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/flow_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/host_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/netherite_upgrade.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/raiser_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/rib_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/sentry_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/shaper_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/silence_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/snout_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/spire_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/tide_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/vex_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/ward_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/wayfinder_pattern.json delete mode 100644 src/main/generated/data/minecraft/smithing_template/wild_pattern.json delete mode 100644 src/main/java/net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess.java delete mode 100644 src/main/java/net/errorcraft/itematic/block/ComposterBlockUtil.java rename src/main/java/net/errorcraft/itematic/{component/AttributeModifiersComponentUtil.java => item/AttributeModifiers.java} (81%) create mode 100644 src/main/java/net/errorcraft/itematic/item/Tooltips.java create mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/AttackBlockingItemComponent.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateProviderItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/TrimMaterialProviderItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/item/composting/CompostChances.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateType.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypeKeys.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypes.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/LingeringPotionEntityExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/PotionEntityExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/SplashPotionEntityExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/item/AnimalArmorItemExtender.java delete mode 100644 src/main/java/net/errorcraft/itematic/util/IdentifierUtil.java delete mode 100644 src/main/java/net/errorcraft/itematic/world/action/actions/OpenBookFromItemAction.java diff --git a/gradle.properties b/gradle.properties index c8db22f6..33e64957 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w03a - yarn_mappings=25w03a+build.3 + minecraft_version=25w04a + yarn_mappings=25w04a+build.10 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.115.0+1.21.5 + fabric_version=0.115.1+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/ingame/SmithingScreenExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/ingame/SmithingScreenExtender.java index 2c5d00de..ddc61d1b 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/ingame/SmithingScreenExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/ingame/SmithingScreenExtender.java @@ -6,7 +6,7 @@ import com.llamalad7.mixinextras.sugar.Share; import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.errorcraft.itematic.item.component.components.SmithingTemplateItemComponent; +import net.errorcraft.itematic.item.component.components.SmithingTemplateProviderItemComponent; import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; import net.minecraft.client.gui.screen.ingame.ForgingScreen; import net.minecraft.client.gui.screen.ingame.SmithingScreen; @@ -16,7 +16,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.SmithingTemplateItem; -import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.screen.SmithingScreenHandler; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -44,9 +43,8 @@ public SmithingScreenExtender(SmithingScreenHandler handler, PlayerInventory pla private void storeSmithingTemplate(CallbackInfo info, @Share("smithingTemplate") LocalRef> smithingTemplate) { smithingTemplate.set(this.handler.getSlot(0) .getStack() - .itematic$getBehavior(ItemComponentTypes.SMITHING_TEMPLATE) - .map(SmithingTemplateItemComponent::template) - .map(RegistryEntry::value) + .itematic$getBehavior(ItemComponentTypes.SMITHING_TEMPLATE_PROVIDER) + .map(SmithingTemplateProviderItemComponent::template) ); } @@ -97,9 +95,8 @@ private Object checkPresenceEquipmentBehavior(ItemStack instance, ComponentType< ) ) private boolean instanceOfSmithingTemplateItemUseItemComponentCheck(Object reference, Class clazz, @Local(ordinal = 0) ItemStack itemStack, @Share("smithingTemplate") LocalRef smithingTemplate) { - Optional optionalSmithingTemplate = itemStack.itematic$getBehavior(ItemComponentTypes.SMITHING_TEMPLATE) - .map(SmithingTemplateItemComponent::template) - .map(RegistryEntry::value); + Optional optionalSmithingTemplate = itemStack.itematic$getBehavior(ItemComponentTypes.SMITHING_TEMPLATE_PROVIDER) + .map(SmithingTemplateProviderItemComponent::template); optionalSmithingTemplate.ifPresent(smithingTemplate::set); return optionalSmithingTemplate.isPresent(); } diff --git a/src/datagen/java/net/errorcraft/itematic/data/ItematicData.java b/src/datagen/java/net/errorcraft/itematic/data/ItematicData.java index 0abd3367..5dfc3abb 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/ItematicData.java +++ b/src/datagen/java/net/errorcraft/itematic/data/ItematicData.java @@ -29,7 +29,6 @@ public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { pack.addProvider(TradeTagProvider::new); pack.addProvider(ActionProvider::new); pack.addProvider(ActionTagProvider::new); - pack.addProvider(SmithingTemplateProvider::new); pack.addProvider(ModifiedRecipeProvider::new); pack.addProvider(PotionTagProvider::new); pack.addProvider(DispenseBehaviorProvider::new); diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/registry/SmithingTemplateProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/registry/SmithingTemplateProvider.java deleted file mode 100644 index c7fcc658..00000000 --- a/src/datagen/java/net/errorcraft/itematic/data/server/registry/SmithingTemplateProvider.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.errorcraft.itematic.data.server.registry; - -import net.errorcraft.itematic.registry.ItematicRegistryKeys; -import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; -import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider; -import net.minecraft.registry.RegistryWrapper; - -import java.util.concurrent.CompletableFuture; - -public class SmithingTemplateProvider extends FabricDynamicRegistryProvider { - public SmithingTemplateProvider(FabricDataOutput output, CompletableFuture registriesFuture) { - super(output, registriesFuture); - } - - @Override - protected void configure(RegistryWrapper.WrapperLookup registries, Entries entries) { - DynamicRegistryProviderUtil.addAll(entries, registries.getOrThrow(ItematicRegistryKeys.SMITHING_TEMPLATE)); - } - - @Override - public String getName() { - return "Smithing Templates"; - } -} diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java index bb35ec47..b2092de5 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/block/WaterCauldronBlockTestSuite.java @@ -33,7 +33,7 @@ public void usingColoredWolfArmorOnWaterCauldronClearsColor(TestContext context) PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL); ServerWorld world = context.getWorld(); ItemStack wolfArmor = world.itematic$createStack(ItemKeys.WOLF_ARMOR); - wolfArmor.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(0xffffff, true)); + wolfArmor.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(0xffffff)); player.setStackInHand(Hand.MAIN_HAND, wolfArmor); world.spawnEntity(player); context.useBlock(WATER_CAULDRON_POSITION, player); diff --git a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java index 73525ce4..4ad97366 100644 --- a/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java +++ b/src/gametest/java/net/errorcraft/itematic/gametest/item/component/ThrowableItemComponentTestSuite.java @@ -106,7 +106,7 @@ public void throwingSplashPotionSpawnsPotionAtEyePosition(TestContext context) { result.isAccepted(), () -> "Expected Splash Potion usage to be successful" ); - context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); + context.expectEntityAt(EntityType.SPLASH_POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } @@ -124,7 +124,7 @@ public void throwingLingeringPotionSpawnsPotionAtEyePosition(TestContext context result.isAccepted(), () -> "Expected Lingering Potion usage to be successful" ); - context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); + context.expectEntityAt(EntityType.LINGERING_POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); }); } diff --git a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java index 91879d2c..c936ae8c 100644 --- a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java +++ b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/structure/StructureTemplateManagerExtender.java @@ -15,7 +15,7 @@ @Mixin(StructureTemplateManager.class) public class StructureTemplateManagerExtender { @Unique - private static final String STRUCTURE_OUTPUT_DIR = System.getProperty("itematic.gametest.structure-output-directory"); + private static final String STRUCTURE_OUTPUT_DIRECTORY = System.getProperty("itematic.gametest.structure-output-directory"); @ModifyExpressionValue( method = "getTemplatePath", @@ -26,8 +26,8 @@ public class StructureTemplateManagerExtender { ) ) private Path useCustomStructureOutputDirectory(Path original) { - if (STRUCTURE_OUTPUT_DIR != null) { - return Paths.get(STRUCTURE_OUTPUT_DIR); + if (STRUCTURE_OUTPUT_DIRECTORY != null) { + return Paths.get(STRUCTURE_OUTPUT_DIRECTORY); } return original; diff --git a/src/main/generated/data/minecraft/item/amethyst_shard.json b/src/main/generated/data/minecraft/item/amethyst_shard.json index 4a8fb6e5..880abb5d 100644 --- a/src/main/generated/data/minecraft/item/amethyst_shard.json +++ b/src/main/generated/data/minecraft/item/amethyst_shard.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:amethyst" }, "display": { "model": "minecraft:amethyst_shard", diff --git a/src/main/generated/data/minecraft/item/bolt_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/bolt_armor_trim_smithing_template.json index 036b90e6..ba3878f0 100644 --- a/src/main/generated/data/minecraft/item/bolt_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/bolt_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:bolt_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:bolt_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.bolt_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/coast_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/coast_armor_trim_smithing_template.json index dd1311a9..1b3ae632 100644 --- a/src/main/generated/data/minecraft/item/coast_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/coast_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:coast_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:coast_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.coast_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/copper_ingot.json b/src/main/generated/data/minecraft/item/copper_ingot.json index 7ec814f8..a0bcf420 100644 --- a/src/main/generated/data/minecraft/item/copper_ingot.json +++ b/src/main/generated/data/minecraft/item/copper_ingot.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:copper" }, "display": { "model": "minecraft:copper_ingot", diff --git a/src/main/generated/data/minecraft/item/diamond.json b/src/main/generated/data/minecraft/item/diamond.json index aa2da596..91c005ee 100644 --- a/src/main/generated/data/minecraft/item/diamond.json +++ b/src/main/generated/data/minecraft/item/diamond.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:diamond" }, "display": { "model": "minecraft:diamond", diff --git a/src/main/generated/data/minecraft/item/diamond_axe.json b/src/main/generated/data/minecraft/item/diamond_axe.json index 5fd5b500..25002d63 100644 --- a/src/main/generated/data/minecraft/item/diamond_axe.json +++ b/src/main/generated/data/minecraft/item/diamond_axe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/diamond_horse_armor.json b/src/main/generated/data/minecraft/item/diamond_horse_armor.json index f1df3ed4..8f204e45 100644 --- a/src/main/generated/data/minecraft/item/diamond_horse_armor.json +++ b/src/main/generated/data/minecraft/item/diamond_horse_armor.json @@ -20,9 +20,10 @@ "behavior": "minecraft:equip_entity" }, "minecraft:equipment": { - "allowed_entities": "minecraft:horse", + "allowed_entities": "#minecraft:can_wear_horse_armor", "asset_id": "minecraft:diamond", - "equip_sound": "minecraft:item.armor.equip_diamond", + "damage_on_hurt": false, + "equip_sound": "minecraft:entity.horse.armor", "slot": "body" }, "minecraft:stackable": 1 diff --git a/src/main/generated/data/minecraft/item/dune_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/dune_armor_trim_smithing_template.json index 8ce6e7cf..c9ded6d1 100644 --- a/src/main/generated/data/minecraft/item/dune_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/dune_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:dune_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:dune_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.dune_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/emerald.json b/src/main/generated/data/minecraft/item/emerald.json index 608b1a43..b402638c 100644 --- a/src/main/generated/data/minecraft/item/emerald.json +++ b/src/main/generated/data/minecraft/item/emerald.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:emerald" }, "display": { "model": "minecraft:emerald", diff --git a/src/main/generated/data/minecraft/item/eye_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/eye_armor_trim_smithing_template.json index 900617ce..040d3476 100644 --- a/src/main/generated/data/minecraft/item/eye_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/eye_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:eye_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:eye_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.eye_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/flow_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/flow_armor_trim_smithing_template.json index 5cb452f1..c8a9c246 100644 --- a/src/main/generated/data/minecraft/item/flow_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/flow_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:flow_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:flow_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.flow_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/goat_horn.json b/src/main/generated/data/minecraft/item/goat_horn.json index dfcf263f..40d4bf2a 100644 --- a/src/main/generated/data/minecraft/item/goat_horn.json +++ b/src/main/generated/data/minecraft/item/goat_horn.json @@ -1,7 +1,7 @@ { "behavior": { "minecraft:playable": { - "instruments": "minecraft:goat_horns" + "default_instrument": "minecraft:ponder_goat_horn" }, "minecraft:stackable": 1, "minecraft:useable": { diff --git a/src/main/generated/data/minecraft/item/gold_ingot.json b/src/main/generated/data/minecraft/item/gold_ingot.json index c9ef1f53..e69ea2bd 100644 --- a/src/main/generated/data/minecraft/item/gold_ingot.json +++ b/src/main/generated/data/minecraft/item/gold_ingot.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:gold" }, "display": { "model": "minecraft:gold_ingot", diff --git a/src/main/generated/data/minecraft/item/golden_axe.json b/src/main/generated/data/minecraft/item/golden_axe.json index 06d72ac6..38714af8 100644 --- a/src/main/generated/data/minecraft/item/golden_axe.json +++ b/src/main/generated/data/minecraft/item/golden_axe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.25, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/golden_horse_armor.json b/src/main/generated/data/minecraft/item/golden_horse_armor.json index 385eff2c..d5297ad8 100644 --- a/src/main/generated/data/minecraft/item/golden_horse_armor.json +++ b/src/main/generated/data/minecraft/item/golden_horse_armor.json @@ -13,9 +13,10 @@ "behavior": "minecraft:equip_entity" }, "minecraft:equipment": { - "allowed_entities": "minecraft:horse", + "allowed_entities": "#minecraft:can_wear_horse_armor", "asset_id": "minecraft:gold", - "equip_sound": "minecraft:item.armor.equip_gold", + "damage_on_hurt": false, + "equip_sound": "minecraft:entity.horse.armor", "slot": "body" }, "minecraft:stackable": 1 diff --git a/src/main/generated/data/minecraft/item/host_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/host_armor_trim_smithing_template.json index a73b60fa..0245f3b7 100644 --- a/src/main/generated/data/minecraft/item/host_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/host_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:host_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:host_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.host_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/iron_axe.json b/src/main/generated/data/minecraft/item/iron_axe.json index c9e248fa..d522a059 100644 --- a/src/main/generated/data/minecraft/item/iron_axe.json +++ b/src/main/generated/data/minecraft/item/iron_axe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.225, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/iron_horse_armor.json b/src/main/generated/data/minecraft/item/iron_horse_armor.json index c8623c76..eea89d8a 100644 --- a/src/main/generated/data/minecraft/item/iron_horse_armor.json +++ b/src/main/generated/data/minecraft/item/iron_horse_armor.json @@ -13,9 +13,10 @@ "behavior": "minecraft:equip_entity" }, "minecraft:equipment": { - "allowed_entities": "minecraft:horse", + "allowed_entities": "#minecraft:can_wear_horse_armor", "asset_id": "minecraft:iron", - "equip_sound": "minecraft:item.armor.equip_iron", + "damage_on_hurt": false, + "equip_sound": "minecraft:entity.horse.armor", "slot": "body" }, "minecraft:stackable": 1 diff --git a/src/main/generated/data/minecraft/item/iron_ingot.json b/src/main/generated/data/minecraft/item/iron_ingot.json index 15767c6b..3ec26816 100644 --- a/src/main/generated/data/minecraft/item/iron_ingot.json +++ b/src/main/generated/data/minecraft/item/iron_ingot.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:iron" }, "display": { "model": "minecraft:iron_ingot", diff --git a/src/main/generated/data/minecraft/item/lapis_lazuli.json b/src/main/generated/data/minecraft/item/lapis_lazuli.json index 373d3737..690b0ad8 100644 --- a/src/main/generated/data/minecraft/item/lapis_lazuli.json +++ b/src/main/generated/data/minecraft/item/lapis_lazuli.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:lapis" }, "display": { "model": "minecraft:lapis_lazuli", diff --git a/src/main/generated/data/minecraft/item/leaf_litter.json b/src/main/generated/data/minecraft/item/leaf_litter.json index fe257ef4..b6b67c72 100644 --- a/src/main/generated/data/minecraft/item/leaf_litter.json +++ b/src/main/generated/data/minecraft/item/leaf_litter.json @@ -3,6 +3,9 @@ "minecraft:block": { "block": "minecraft:leaf_litter" }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, "minecraft:fuel": { "ticks": 100 }, diff --git a/src/main/generated/data/minecraft/item/leather_horse_armor.json b/src/main/generated/data/minecraft/item/leather_horse_armor.json index ad67976f..84ee190a 100644 --- a/src/main/generated/data/minecraft/item/leather_horse_armor.json +++ b/src/main/generated/data/minecraft/item/leather_horse_armor.json @@ -16,9 +16,10 @@ "default_color": -6265536 }, "minecraft:equipment": { - "allowed_entities": "minecraft:horse", + "allowed_entities": "#minecraft:can_wear_horse_armor", "asset_id": "minecraft:leather", - "equip_sound": "minecraft:item.armor.equip_leather", + "damage_on_hurt": false, + "equip_sound": "minecraft:entity.horse.armor", "slot": "body" }, "minecraft:stackable": 1 diff --git a/src/main/generated/data/minecraft/item/lingering_potion.json b/src/main/generated/data/minecraft/item/lingering_potion.json index 769d8c21..4cb97b82 100644 --- a/src/main/generated/data/minecraft/item/lingering_potion.json +++ b/src/main/generated/data/minecraft/item/lingering_potion.json @@ -7,7 +7,7 @@ "duration_multiplier": 0.25 }, "minecraft:projectile": { - "entity": "minecraft:potion" + "entity": "minecraft:lingering_potion" }, "minecraft:stackable": 1, "minecraft:throwable": { diff --git a/src/main/generated/data/minecraft/item/netherite_axe.json b/src/main/generated/data/minecraft/item/netherite_axe.json index 989f439c..27c1ef6a 100644 --- a/src/main/generated/data/minecraft/item/netherite_axe.json +++ b/src/main/generated/data/minecraft/item/netherite_axe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.25, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/netherite_ingot.json b/src/main/generated/data/minecraft/item/netherite_ingot.json index 23cb38ff..585b261a 100644 --- a/src/main/generated/data/minecraft/item/netherite_ingot.json +++ b/src/main/generated/data/minecraft/item/netherite_ingot.json @@ -3,7 +3,8 @@ "minecraft:immune_to_damage": { "damage": "minecraft:is_fire" }, - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:netherite" }, "display": { "model": "minecraft:netherite_ingot", diff --git a/src/main/generated/data/minecraft/item/netherite_upgrade_smithing_template.json b/src/main/generated/data/minecraft/item/netherite_upgrade_smithing_template.json index ac2874c4..222e0324 100644 --- a/src/main/generated/data/minecraft/item/netherite_upgrade_smithing_template.json +++ b/src/main/generated/data/minecraft/item/netherite_upgrade_smithing_template.json @@ -1,13 +1,42 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:netherite_upgrade" - }, + "minecraft:smithing_template_provider": "minecraft:item_upgrade", "minecraft:stackable": 64 }, "display": { "model": "minecraft:netherite_upgrade_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "translate": "smithing_template.minecraft.netherite_upgrade.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "translate": "smithing_template.minecraft.netherite_upgrade.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.netherite_upgrade_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/quartz.json b/src/main/generated/data/minecraft/item/quartz.json index 5b2dccf6..098371db 100644 --- a/src/main/generated/data/minecraft/item/quartz.json +++ b/src/main/generated/data/minecraft/item/quartz.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:quartz" }, "display": { "model": "minecraft:quartz", diff --git a/src/main/generated/data/minecraft/item/raiser_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/raiser_armor_trim_smithing_template.json index 28303a03..73c4c4cf 100644 --- a/src/main/generated/data/minecraft/item/raiser_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/raiser_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:raiser_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:raiser_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.raiser_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/redstone.json b/src/main/generated/data/minecraft/item/redstone.json index ae531cec..5adbc879 100644 --- a/src/main/generated/data/minecraft/item/redstone.json +++ b/src/main/generated/data/minecraft/item/redstone.json @@ -3,7 +3,8 @@ "minecraft:block": { "block": "minecraft:redstone_wire" }, - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:redstone" }, "display": { "model": "minecraft:redstone", diff --git a/src/main/generated/data/minecraft/item/resin_brick.json b/src/main/generated/data/minecraft/item/resin_brick.json index eab3d615..7d3c88e9 100644 --- a/src/main/generated/data/minecraft/item/resin_brick.json +++ b/src/main/generated/data/minecraft/item/resin_brick.json @@ -1,6 +1,7 @@ { "behavior": { - "minecraft:stackable": 64 + "minecraft:stackable": 64, + "minecraft:trim_material_provider": "minecraft:resin" }, "display": { "model": "minecraft:resin_brick", diff --git a/src/main/generated/data/minecraft/item/rib_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/rib_armor_trim_smithing_template.json index 53a66840..94ea495d 100644 --- a/src/main/generated/data/minecraft/item/rib_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/rib_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:rib_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:rib_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.rib_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/sentry_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/sentry_armor_trim_smithing_template.json index ec8605aa..98d28da8 100644 --- a/src/main/generated/data/minecraft/item/sentry_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/sentry_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:sentry_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:sentry_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.sentry_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/shaper_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/shaper_armor_trim_smithing_template.json index 79f22f63..79ea43bd 100644 --- a/src/main/generated/data/minecraft/item/shaper_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/shaper_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:shaper_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:shaper_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.shaper_armor_trim_smithing_template" } } \ 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 7ead730e..015c0fc1 100644 --- a/src/main/generated/data/minecraft/item/shield.json +++ b/src/main/generated/data/minecraft/item/shield.json @@ -1,5 +1,15 @@ { "behavior": { + "minecraft:attack_blocking": { + "block_delay_seconds": 0.25, + "block_sound": "minecraft:item.shield.block", + "disabled_sound": "minecraft:item.shield.break", + "item_damage": { + "base": 1.0, + "factor": 1.0, + "threshold": 3.0 + } + }, "minecraft:banner_pattern_holder": {}, "minecraft:damageable": { "durability": 336 diff --git a/src/main/generated/data/minecraft/item/silence_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/silence_armor_trim_smithing_template.json index 2bcc7b87..9eabffeb 100644 --- a/src/main/generated/data/minecraft/item/silence_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/silence_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:silence_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:silence_armor_trim_smithing_template", "rarity": "epic", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.silence_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/snout_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/snout_armor_trim_smithing_template.json index 798daa88..7782c944 100644 --- a/src/main/generated/data/minecraft/item/snout_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/snout_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:snout_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:snout_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.snout_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/spire_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/spire_armor_trim_smithing_template.json index ca61d85e..6a1610f5 100644 --- a/src/main/generated/data/minecraft/item/spire_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/spire_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:spire_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:spire_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.spire_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/splash_potion.json b/src/main/generated/data/minecraft/item/splash_potion.json index f443bba8..77b15f63 100644 --- a/src/main/generated/data/minecraft/item/splash_potion.json +++ b/src/main/generated/data/minecraft/item/splash_potion.json @@ -7,7 +7,7 @@ "duration_multiplier": 1.0 }, "minecraft:projectile": { - "entity": "minecraft:potion" + "entity": "minecraft:splash_potion" }, "minecraft:stackable": 1, "minecraft:throwable": { diff --git a/src/main/generated/data/minecraft/item/stone_axe.json b/src/main/generated/data/minecraft/item/stone_axe.json index 631e6d46..0c13e0a2 100644 --- a/src/main/generated/data/minecraft/item/stone_axe.json +++ b/src/main/generated/data/minecraft/item/stone_axe.json @@ -29,7 +29,7 @@ "rules": [] }, "attack_speed": 0.2, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/tide_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/tide_armor_trim_smithing_template.json index 27eb4824..481da6be 100644 --- a/src/main/generated/data/minecraft/item/tide_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/tide_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:tide_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:tide_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.tide_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/vex_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/vex_armor_trim_smithing_template.json index 81937df6..0c9d7fcc 100644 --- a/src/main/generated/data/minecraft/item/vex_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/vex_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:vex_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:vex_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.vex_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/ward_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/ward_armor_trim_smithing_template.json index 6f1473f2..cac3eeab 100644 --- a/src/main/generated/data/minecraft/item/ward_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/ward_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:ward_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:ward_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.ward_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wayfinder_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/wayfinder_armor_trim_smithing_template.json index 93eb3e84..46959ca0 100644 --- a/src/main/generated/data/minecraft/item/wayfinder_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/wayfinder_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:wayfinder_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:wayfinder_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.wayfinder_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wild_armor_trim_smithing_template.json b/src/main/generated/data/minecraft/item/wild_armor_trim_smithing_template.json index bb1d6dff..49e1c496 100644 --- a/src/main/generated/data/minecraft/item/wild_armor_trim_smithing_template.json +++ b/src/main/generated/data/minecraft/item/wild_armor_trim_smithing_template.json @@ -1,13 +1,44 @@ { "behavior": { - "minecraft:smithing_template": { - "template": "minecraft:wild_pattern" - }, + "minecraft:smithing_template_provider": "minecraft:trim_pattern", "minecraft:stackable": 64 }, "display": { "model": "minecraft:wild_armor_trim_smithing_template", "rarity": "uncommon", + "tooltip": [ + { + "color": "gray", + "translate": "item.minecraft.smithing_template" + }, + "", + { + "color": "gray", + "translate": "item.minecraft.smithing_template.applies_to" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.applies_to" + } + ], + "text": " " + }, + { + "color": "gray", + "translate": "item.minecraft.smithing_template.ingredients" + }, + { + "extra": [ + { + "color": "blue", + "translate": "item.minecraft.smithing_template.armor_trim.ingredients" + } + ], + "text": " " + } + ], "translation_key": "item.minecraft.wild_armor_trim_smithing_template" } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/wolf_armor.json b/src/main/generated/data/minecraft/item/wolf_armor.json index 52087b9a..7896dadc 100644 --- a/src/main/generated/data/minecraft/item/wolf_armor.json +++ b/src/main/generated/data/minecraft/item/wolf_armor.json @@ -22,6 +22,9 @@ "equip_sound": "minecraft:item.armor.equip_wolf", "slot": "body" }, + "minecraft:repairable": { + "items": "#minecraft:repairs_wolf_armor" + }, "minecraft:stackable": 1 }, "display": { diff --git a/src/main/generated/data/minecraft/item/wooden_axe.json b/src/main/generated/data/minecraft/item/wooden_axe.json index c8f30db9..00367c30 100644 --- a/src/main/generated/data/minecraft/item/wooden_axe.json +++ b/src/main/generated/data/minecraft/item/wooden_axe.json @@ -32,7 +32,7 @@ "rules": [] }, "attack_speed": 0.2, - "can_disable_blocking": true, + "disable_blocking_for_seconds": 5.0, "item_damage_per_attack": 2 } }, diff --git a/src/main/generated/data/minecraft/item/written_book.json b/src/main/generated/data/minecraft/item/written_book.json index 2d0582a4..5cd3f0dd 100644 --- a/src/main/generated/data/minecraft/item/written_book.json +++ b/src/main/generated/data/minecraft/item/written_book.json @@ -7,30 +7,5 @@ "glint": true, "model": "minecraft:written_book", "translation_key": "item.minecraft.written_book" - }, - "events": { - "minecraft:use": { - "action": { - "type": "minecraft:sequence", - "handler": "minecraft:passing", - "entries": [ - { - "action": { - "type": "minecraft:open_book_from_item" - } - }, - { - "action": { - "type": "minecraft:increment_stat", - "entity": "this", - "stat": { - "type": "minecraft:used", - "entry": "minecraft:written_book" - } - } - } - ] - } - } } } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json b/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json index a752fb5b..297661bd 100644 --- a/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json +++ b/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json @@ -125,11 +125,15 @@ "pattern": "minecraft:border" } ], - "minecraft:hide_additional_tooltip": {}, "minecraft:item_name": { "translate": "block.minecraft.ominous_banner" }, - "minecraft:rarity": "uncommon" + "minecraft:rarity": "uncommon", + "minecraft:tooltip_display": { + "hidden_components": [ + "minecraft:banner_patterns" + ] + } }, "item": "minecraft:white_banner" }, diff --git a/src/main/generated/data/minecraft/smithing_template/bolt_pattern.json b/src/main/generated/data/minecraft/smithing_template/bolt_pattern.json deleted file mode 100644 index c84566c5..00000000 --- a/src/main/generated/data/minecraft/smithing_template/bolt_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:bolt" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/coast_pattern.json b/src/main/generated/data/minecraft/smithing_template/coast_pattern.json deleted file mode 100644 index c49267d3..00000000 --- a/src/main/generated/data/minecraft/smithing_template/coast_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:coast" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/dune_pattern.json b/src/main/generated/data/minecraft/smithing_template/dune_pattern.json deleted file mode 100644 index 7287317f..00000000 --- a/src/main/generated/data/minecraft/smithing_template/dune_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:dune" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/eye_pattern.json b/src/main/generated/data/minecraft/smithing_template/eye_pattern.json deleted file mode 100644 index 5a22b7d2..00000000 --- a/src/main/generated/data/minecraft/smithing_template/eye_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:eye" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/flow_pattern.json b/src/main/generated/data/minecraft/smithing_template/flow_pattern.json deleted file mode 100644 index 295c5fd8..00000000 --- a/src/main/generated/data/minecraft/smithing_template/flow_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:flow" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/host_pattern.json b/src/main/generated/data/minecraft/smithing_template/host_pattern.json deleted file mode 100644 index ca389985..00000000 --- a/src/main/generated/data/minecraft/smithing_template/host_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:host" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/netherite_upgrade.json b/src/main/generated/data/minecraft/smithing_template/netherite_upgrade.json deleted file mode 100644 index 8db7808d..00000000 --- a/src/main/generated/data/minecraft/smithing_template/netherite_upgrade.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "minecraft:item_upgrade", - "item": "minecraft:netherite_ingot", - "translation_key_id": "minecraft:netherite_upgrade" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/raiser_pattern.json b/src/main/generated/data/minecraft/smithing_template/raiser_pattern.json deleted file mode 100644 index 98b84c5c..00000000 --- a/src/main/generated/data/minecraft/smithing_template/raiser_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:raiser" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/rib_pattern.json b/src/main/generated/data/minecraft/smithing_template/rib_pattern.json deleted file mode 100644 index de1c54f3..00000000 --- a/src/main/generated/data/minecraft/smithing_template/rib_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:rib" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/sentry_pattern.json b/src/main/generated/data/minecraft/smithing_template/sentry_pattern.json deleted file mode 100644 index 46a3af1d..00000000 --- a/src/main/generated/data/minecraft/smithing_template/sentry_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:sentry" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/shaper_pattern.json b/src/main/generated/data/minecraft/smithing_template/shaper_pattern.json deleted file mode 100644 index 22ae1f5f..00000000 --- a/src/main/generated/data/minecraft/smithing_template/shaper_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:shaper" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/silence_pattern.json b/src/main/generated/data/minecraft/smithing_template/silence_pattern.json deleted file mode 100644 index 982699dc..00000000 --- a/src/main/generated/data/minecraft/smithing_template/silence_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:silence" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/snout_pattern.json b/src/main/generated/data/minecraft/smithing_template/snout_pattern.json deleted file mode 100644 index 96e2b521..00000000 --- a/src/main/generated/data/minecraft/smithing_template/snout_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:snout" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/spire_pattern.json b/src/main/generated/data/minecraft/smithing_template/spire_pattern.json deleted file mode 100644 index 9f2dea98..00000000 --- a/src/main/generated/data/minecraft/smithing_template/spire_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:spire" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/tide_pattern.json b/src/main/generated/data/minecraft/smithing_template/tide_pattern.json deleted file mode 100644 index a1c8ca2f..00000000 --- a/src/main/generated/data/minecraft/smithing_template/tide_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:tide" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/vex_pattern.json b/src/main/generated/data/minecraft/smithing_template/vex_pattern.json deleted file mode 100644 index 3003d1f4..00000000 --- a/src/main/generated/data/minecraft/smithing_template/vex_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:vex" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/ward_pattern.json b/src/main/generated/data/minecraft/smithing_template/ward_pattern.json deleted file mode 100644 index be3b8cef..00000000 --- a/src/main/generated/data/minecraft/smithing_template/ward_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:ward" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/wayfinder_pattern.json b/src/main/generated/data/minecraft/smithing_template/wayfinder_pattern.json deleted file mode 100644 index a72c487c..00000000 --- a/src/main/generated/data/minecraft/smithing_template/wayfinder_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:wayfinder" -} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/smithing_template/wild_pattern.json b/src/main/generated/data/minecraft/smithing_template/wild_pattern.json deleted file mode 100644 index 8c7659bc..00000000 --- a/src/main/generated/data/minecraft/smithing_template/wild_pattern.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:trim_pattern", - "trim_pattern": "minecraft:wild" -} \ No newline at end of file diff --git a/src/main/java/net/errorcraft/itematic/Itematic.java b/src/main/java/net/errorcraft/itematic/Itematic.java index 2118d8bf..50335570 100644 --- a/src/main/java/net/errorcraft/itematic/Itematic.java +++ b/src/main/java/net/errorcraft/itematic/Itematic.java @@ -6,7 +6,7 @@ import net.errorcraft.itematic.item.holder.rule.ItemHolderRuleTypes; import net.errorcraft.itematic.item.placement.block.picker.BlockPickerTypes; import net.errorcraft.itematic.item.shooter.method.ShooterMethodTypes; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateTypes; +import net.errorcraft.itematic.item.smithing.template.SmithingTemplates; import net.errorcraft.itematic.item.use.provider.IntegerProviderTypes; import net.errorcraft.itematic.loot.function.ItematicItemModifierTypes; import net.errorcraft.itematic.loot.predicate.ItematicPredicateTypes; @@ -32,7 +32,7 @@ public void onInitialize() { SequenceHandlerTypes.init(); ItematicPredicateTypes.init(); ItematicContextParameters.init(); - SmithingTemplateTypes.init(); + SmithingTemplates.init(); BlockPickerTypes.init(); ItematicItemModifierTypes.init(); TradeModifierTypes.init(); diff --git a/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java b/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java index ab31ab0f..fb43459f 100644 --- a/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java @@ -18,7 +18,4 @@ public interface SherdsAccess { default List> itematic$entries(RegistryWrapper.WrapperLookup lookup) { return null; } - default List> itematic$entriesForwards(RegistryWrapper.WrapperLookup lookup) { - return null; - } } diff --git a/src/main/java/net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess.java b/src/main/java/net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess.java deleted file mode 100644 index 2bd8853e..00000000 --- a/src/main/java/net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.errorcraft.itematic.access.item; - -import net.minecraft.entity.EntityType; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.sound.SoundEvent; - -public interface AnimalArmorItemTypeAccess { - default RegistryEntry itematic$breakSound() { - return null; - } - default RegistryEntryList> itematic$allowedEntities() { - return null; - } -} 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 5d8511f2..3c6d953c 100644 --- a/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/item/ItemAccess.java @@ -9,11 +9,15 @@ import net.errorcraft.itematic.world.action.context.ActionContext; import net.minecraft.component.type.AttributeModifiersComponent; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.text.Text; import net.minecraft.util.Hand; import net.minecraft.world.World; import java.util.Optional; +import java.util.function.Consumer; public interface ItemAccess { default ItemDisplay itematic$display() { @@ -44,6 +48,7 @@ public interface ItemAccess { default boolean itematic$hasEventListener(ItemEvent event) { return false; } + default void itematic$addTooltip(ItemStack stack, Item.TooltipContext context, Consumer tooltip, TooltipType type) {} default boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { return true; } diff --git a/src/main/java/net/errorcraft/itematic/block/ComposterBlockUtil.java b/src/main/java/net/errorcraft/itematic/block/ComposterBlockUtil.java deleted file mode 100644 index 0af5252d..00000000 --- a/src/main/java/net/errorcraft/itematic/block/ComposterBlockUtil.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.errorcraft.itematic.block; - -public class ComposterBlockUtil { - public static final float SMALL_CHANCE_TO_COMPOST = 0.3f; - public static final float HALF_CHANCE_TO_COMPOST = 0.5f; - public static final float BIG_CHANCE_TO_COMPOST = 0.65f; - public static final float ALMOST_GUARANTEED_TO_COMPOST = 0.85f; - public static final float GUARANTEED_TO_COMPOST = 1.0f; - - private ComposterBlockUtil() {} -} diff --git a/src/main/java/net/errorcraft/itematic/entity/EntityTypeKeys.java b/src/main/java/net/errorcraft/itematic/entity/EntityTypeKeys.java index 2b736dda..c38c7f4b 100644 --- a/src/main/java/net/errorcraft/itematic/entity/EntityTypeKeys.java +++ b/src/main/java/net/errorcraft/itematic/entity/EntityTypeKeys.java @@ -66,6 +66,7 @@ public class EntityTypeKeys { public static final RegistryKey> ITEM_FRAME = of("item_frame"); public static final RegistryKey> JUNGLE_BOAT = of("jungle_boat"); public static final RegistryKey> JUNGLE_CHEST_BOAT = of("jungle_chest_boat"); + public static final RegistryKey> LINGERING_POTION = of("lingering_potion"); public static final RegistryKey> LLAMA = of("llama"); public static final RegistryKey> MAGMA_CUBE = of("magma_cube"); public static final RegistryKey> MANGROVE_BOAT = of("mangrove_boat"); @@ -87,7 +88,6 @@ public class EntityTypeKeys { public static final RegistryKey> PIGLIN_BRUTE = of("piglin_brute"); public static final RegistryKey> PILLAGER = of("pillager"); public static final RegistryKey> POLAR_BEAR = of("polar_bear"); - public static final RegistryKey> POTION = of("potion"); public static final RegistryKey> PUFFERFISH = of("pufferfish"); public static final RegistryKey> RABBIT = of("rabbit"); public static final RegistryKey> RAVAGER = of("ravager"); @@ -104,6 +104,7 @@ public class EntityTypeKeys { public static final RegistryKey> SNOW_GOLEM = of("snow_golem"); public static final RegistryKey> SPECTRAL_ARROW = of("spectral_arrow"); public static final RegistryKey> SPIDER = of("spider"); + public static final RegistryKey> SPLASH_POTION = of("splash_potion"); public static final RegistryKey> SPRUCE_BOAT = of("spruce_boat"); public static final RegistryKey> SPRUCE_CHEST_BOAT = of("spruce_chest_boat"); public static final RegistryKey> SQUID = of("squid"); diff --git a/src/main/java/net/errorcraft/itematic/component/AttributeModifiersComponentUtil.java b/src/main/java/net/errorcraft/itematic/item/AttributeModifiers.java similarity index 81% rename from src/main/java/net/errorcraft/itematic/component/AttributeModifiersComponentUtil.java rename to src/main/java/net/errorcraft/itematic/item/AttributeModifiers.java index f7d41952..f91d9504 100644 --- a/src/main/java/net/errorcraft/itematic/component/AttributeModifiersComponentUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/AttributeModifiers.java @@ -1,6 +1,5 @@ -package net.errorcraft.itematic.component; +package net.errorcraft.itematic.item; -import com.mojang.serialization.Codec; import net.minecraft.component.type.AttributeModifierSlot; import net.minecraft.component.type.AttributeModifiersComponent; import net.minecraft.entity.attribute.EntityAttributeModifier; @@ -9,13 +8,8 @@ import net.minecraft.item.equipment.EquipmentType; import net.minecraft.util.Identifier; -public class AttributeModifiersComponentUtil { - public static final Codec LIST_CODEC = AttributeModifiersComponent.Entry.CODEC.listOf().xmap( - entries -> new AttributeModifiersComponent(entries, true), - AttributeModifiersComponent::modifiers - ); - - private AttributeModifiersComponentUtil() {} +public class AttributeModifiers { + private AttributeModifiers() {} public static AttributeModifiersComponent armor(ArmorMaterial material, EquipmentType type) { Identifier attributeId = Identifier.ofVanilla("armor." + type.getName()); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemDisplay.java b/src/main/java/net/errorcraft/itematic/item/ItemDisplay.java index 33fd27af..1b59b1c9 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemDisplay.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemDisplay.java @@ -4,7 +4,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.component.ItematicDataComponentTypes; import net.errorcraft.itematic.mixin.item.ItemAccessor; -import net.errorcraft.itematic.util.IdentifierUtil; import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.item.Item; @@ -12,7 +11,6 @@ import net.minecraft.registry.RegistryKeyedValue; import net.minecraft.text.Text; import net.minecraft.text.TextCodecs; -import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; @@ -81,14 +79,11 @@ public Builder rarity(Rarity rarity) { return this; } - public Builder tooltip(RegistryKey name) { - return this.tooltip(Text.translatable(IdentifierUtil.createTranslationKey(name, "item", "desc")).formatted(Formatting.GRAY)); - } - public Builder tooltip(Text... lines) { if (this.tooltip == null) { this.tooltip = new ArrayList<>(); } + this.tooltip.addAll(List.of(lines)); return this; } diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index b918673d..e839d1ad 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -3,14 +3,13 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.block.BlockKeys; -import net.errorcraft.itematic.block.ComposterBlockUtil; -import net.errorcraft.itematic.component.AttributeModifiersComponentUtil; import net.errorcraft.itematic.component.type.ItemDamageRulesDataComponent; import net.errorcraft.itematic.entity.EntityTypeKeys; import net.errorcraft.itematic.entity.effect.StatusEffectKeys; import net.errorcraft.itematic.fluid.FluidKeys; import net.errorcraft.itematic.item.component.ItemComponentSet; import net.errorcraft.itematic.item.component.components.*; +import net.errorcraft.itematic.item.composting.CompostChances; import net.errorcraft.itematic.item.dispense.behavior.DispenseBehavior; import net.errorcraft.itematic.item.dispense.behavior.DispenseBehaviors; import net.errorcraft.itematic.item.event.ItemEventMap; @@ -18,7 +17,6 @@ import net.errorcraft.itematic.item.fuel.FuelTimes; import net.errorcraft.itematic.item.shooter.method.methods.ChargeableShooterMethod; 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.loot.condition.LocationCheckLootConditionUtil; import net.errorcraft.itematic.loot.predicate.SideCheckPredicate; @@ -56,6 +54,8 @@ import net.minecraft.item.equipment.ArmorMaterials; import net.minecraft.item.equipment.EquipmentAssetKeys; import net.minecraft.item.equipment.EquipmentType; +import net.minecraft.item.equipment.trim.ArmorTrimMaterial; +import net.minecraft.item.equipment.trim.ArmorTrimMaterials; import net.minecraft.loot.condition.*; import net.minecraft.loot.context.LootContext; import net.minecraft.particle.ParticleTypes; @@ -73,7 +73,6 @@ import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; -import net.minecraft.stat.Stats; import net.minecraft.state.property.Properties; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; @@ -83,12 +82,13 @@ import net.minecraft.world.event.GameEvent; import java.util.List; +import java.util.Optional; public class ItemUtil { public static final int UNSTACKABLE_MAX_STACK_SIZE = 1; public static final Codec CODEC = RecordCodecBuilder.create((instance) -> instance.group( ItemDisplay.CODEC.fieldOf("display").forGetter(Item::itematic$display), - AttributeModifiersComponentUtil.LIST_CODEC.optionalFieldOf("attribute_modifiers", AttributeModifiersComponent.DEFAULT).forGetter(Item::itematic$attributeModifiers), + AttributeModifiersComponent.CODEC.optionalFieldOf("attribute_modifiers", AttributeModifiersComponent.DEFAULT).forGetter(Item::itematic$attributeModifiers), ItemComponentSet.CODEC.optionalFieldOf("behavior", ItemComponentSet.EMPTY).forGetter(Item::itematic$behavior), ItemEventMap.CODEC.optionalFieldOf("events", ItemEventMap.EMPTY).forGetter(Item::itematic$events) ).apply(instance, ItemUtil::create)); @@ -136,12 +136,13 @@ private static class Bootstrapper { private final RegistryEntryLookup soundEvents; private final RegistryEntryLookup fluids; private final RegistryEntryLookup actions; - private final RegistryEntryLookup smithingTemplates; private final RegistryEntryLookup decoratedPotPatterns; private final RegistryEntryLookup statusEffects; private final RegistryEntryLookup potions; private final RegistryEntryLookup enchantments; private final RegistryEntryLookup jukeboxSongs; + private final RegistryEntryLookup instruments; + private final RegistryEntryLookup trimMaterials; private Bootstrapper(Registerable registerable) { this.registerable = registerable; @@ -152,12 +153,13 @@ private Bootstrapper(Registerable registerable) { this.soundEvents = registerable.getRegistryLookup(RegistryKeys.SOUND_EVENT); this.fluids = registerable.getRegistryLookup(RegistryKeys.FLUID); this.actions = registerable.getRegistryLookup(ItematicRegistryKeys.ACTION); - this.smithingTemplates = registerable.getRegistryLookup(ItematicRegistryKeys.SMITHING_TEMPLATE); this.decoratedPotPatterns = registerable.getRegistryLookup(RegistryKeys.DECORATED_POT_PATTERN); this.statusEffects = registerable.getRegistryLookup(RegistryKeys.STATUS_EFFECT); this.potions = registerable.getRegistryLookup(RegistryKeys.POTION); this.enchantments = registerable.getRegistryLookup(RegistryKeys.ENCHANTMENT); this.jukeboxSongs = registerable.getRegistryLookup(RegistryKeys.JUKEBOX_SONG); + this.instruments = registerable.getRegistryLookup(RegistryKeys.INSTRUMENT); + this.trimMaterials = registerable.getRegistryLookup(RegistryKeys.TRIM_MATERIAL); } private void bootstrap() { @@ -176,6 +178,7 @@ private void bootstrap() { this.bootstrapBanners(); this.bootstrapDecoratedPotPatterns(); this.bootstrapImmuneToDamage(); + this.bootstrapTrimMaterialProviders(); this.bootstrapMiscellaneous(); } @@ -263,7 +266,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.APPLE) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.MELON_SLICE, create( @@ -273,7 +276,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.MELON_SLICE) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.DRIED_KELP, create( @@ -283,7 +286,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.DRIED_KELP) .food(FoodComponents.DRIED_KELP) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.CARROT, create( @@ -294,7 +297,7 @@ private void bootstrapFood() { .food(FoodComponents.CARROT) .build()) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CARROTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.POTATO, create( @@ -305,7 +308,7 @@ private void bootstrapFood() { .food(FoodComponents.POTATO) .build()) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.POTATOES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.BAKED_POTATO, create( @@ -315,7 +318,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.BAKED_POTATO) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.CHORUS_FRUIT, create( @@ -337,7 +340,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.BEETROOT) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.SWEET_BERRIES, create( @@ -348,7 +351,7 @@ private void bootstrapFood() { .food(FoodComponents.SWEET_BERRIES) .build()) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SWEET_BERRY_BUSH))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.GLOW_BERRIES, create( @@ -359,7 +362,7 @@ private void bootstrapFood() { .food(FoodComponents.GLOW_BERRIES) .build()) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CAVE_VINES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.BREAD, create( @@ -369,7 +372,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.BREAD) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.COOKIE, create( @@ -379,7 +382,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.COOKIE) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.PORKCHOP, create( @@ -691,7 +694,7 @@ private void bootstrapFood() { .with(ConsumableItemComponent.builder(ConsumableComponents.FOOD) .food(FoodComponents.PUMPKIN_PIE) .build()) - .with(CompostableItemComponent.of(ComposterBlockUtil.GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.GUARANTEED)) .build() )); this.registerable.register(ItemKeys.HONEY_BOTTLE, create( @@ -5103,13 +5106,6 @@ private void bootstrapShulkerBoxes() { } private void bootstrapItemNameBlocks() { - this.registerable.register(ItemKeys.REDSTONE, create( - ItemDisplay.Builder.forItem(ItemKeys.REDSTONE).build(), - ItemComponentSet.builder() - .with(StackableItemComponent.of(64)) - .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.REDSTONE_WIRE))) - .build() - )); this.registerable.register(ItemKeys.STRING, create( ItemDisplay.Builder.forItem(ItemKeys.STRING).build(), ItemComponentSet.builder() @@ -5475,7 +5471,7 @@ private void bootstrapToolsAndWeapons() { .with(ToolItemComponent.builder(2) .preventCreativeDestruction() .build()) - .with(WeaponItemComponent.of(1, false, TridentItem.ATTACK_DAMAGE, 0.275d)) + .with(WeaponItemComponent.of(1, 0.0f, TridentItem.ATTACK_DAMAGE, 0.275d)) .with(ThrowableItemComponent.trident(TridentItem.THROW_SPEED, 0.0f, TridentItem.MIN_DRAW_DURATION)) .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.TRIDENT))) .with(EnchantableItemComponent.of(1)) @@ -6388,7 +6384,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.OAK_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.SPRUCE_LEAVES, create( @@ -6396,7 +6392,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SPRUCE_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.BIRCH_LEAVES, create( @@ -6404,7 +6400,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BIRCH_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.JUNGLE_LEAVES, create( @@ -6412,7 +6408,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.JUNGLE_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.ACACIA_LEAVES, create( @@ -6420,7 +6416,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.ACACIA_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.CHERRY_LEAVES, create( @@ -6428,7 +6424,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CHERRY_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.DARK_OAK_LEAVES, create( @@ -6436,7 +6432,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.DARK_OAK_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PALE_OAK_LEAVES, create( @@ -6444,7 +6440,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PALE_OAK_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.MANGROVE_LEAVES, create( @@ -6452,7 +6448,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MANGROVE_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.AZALEA_LEAVES, create( @@ -6460,7 +6456,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.AZALEA_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.OAK_SAPLING, create( @@ -6468,7 +6464,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.OAK_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6480,7 +6476,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SPRUCE_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6492,7 +6488,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BIRCH_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6504,7 +6500,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.JUNGLE_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6516,7 +6512,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.ACACIA_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6528,7 +6524,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CHERRY_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6540,7 +6536,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.DARK_OAK_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6552,7 +6548,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PALE_OAK_SAPLING))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6564,7 +6560,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MANGROVE_PROPAGULE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -6576,7 +6572,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SHORT_GRASS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.KELP, create( @@ -6584,7 +6580,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.KELP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.MOSS_CARPET, create( @@ -6592,7 +6588,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MOSS_CARPET))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PALE_MOSS_CARPET, create( @@ -6600,7 +6596,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PALE_MOSS_CARPET))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PINK_PETALS, create( @@ -6608,7 +6604,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PINK_PETALS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.HANGING_ROOTS, create( @@ -6616,7 +6612,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.HANGING_ROOTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.SMALL_DRIPLEAF, create( @@ -6624,7 +6620,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SMALL_DRIPLEAF))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.WHEAT_SEEDS, create( @@ -6632,7 +6628,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WHEAT))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PUMPKIN_SEEDS, create( @@ -6640,7 +6636,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PUMPKIN_STEM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.MELON_SEEDS, create( @@ -6648,7 +6644,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MELON_STEM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.TORCHFLOWER_SEEDS, create( @@ -6656,7 +6652,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.TORCHFLOWER_CROP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PITCHER_POD, create( @@ -6664,7 +6660,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PITCHER_CROP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.BEETROOT_SEEDS, create( @@ -6672,7 +6668,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BEETROOTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.MANGROVE_ROOTS, create( @@ -6680,7 +6676,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MANGROVE_ROOTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .with(FuelItemComponent.of(FuelTimes.WOOD)) .build() )); @@ -6689,7 +6685,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SEAGRASS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.PALE_HANGING_MOSS, create( @@ -6697,7 +6693,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PALE_HANGING_MOSS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.WILDFLOWERS, create( @@ -6705,7 +6701,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WILDFLOWERS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.SMALL_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); this.registerable.register(ItemKeys.FLOWERING_AZALEA_LEAVES, create( @@ -6713,7 +6709,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.FLOWERING_AZALEA_LEAVES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.NETHER_SPROUTS, create( @@ -6721,7 +6717,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.NETHER_SPROUTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.WEEPING_VINES, create( @@ -6729,7 +6725,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WEEPING_VINES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.TWISTING_VINES, create( @@ -6737,7 +6733,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.TWISTING_VINES))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.SUGAR_CANE, create( @@ -6745,7 +6741,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SUGAR_CANE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.VINE, create( @@ -6753,7 +6749,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.VINE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.GLOW_LICHEN, create( @@ -6761,7 +6757,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.GLOW_LICHEN))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.TALL_GRASS, create( @@ -6769,7 +6765,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.TALL_GRASS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build() )); this.registerable.register(ItemKeys.CACTUS, create( @@ -6777,7 +6773,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CACTUS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_CACTUS)) @@ -6788,7 +6784,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.DRIED_KELP_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.HALF_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.FIFTY_FIFTY)) .with(FuelItemComponent.of(FuelTimes.DRIED_KELP_BLOCK)) .build() )); @@ -6797,7 +6793,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.FERN))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_FERN)) @@ -6808,7 +6804,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LILY_PAD), BlockItemComponent.Pass.FLUID)) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.NETHER_WART, create( @@ -6816,7 +6812,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.NETHER_WART))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.COCOA_BEANS, create( @@ -6824,7 +6820,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.COCOA))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.BIG_DRIPLEAF, create( @@ -6832,7 +6828,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BIG_DRIPLEAF))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.PUMPKIN, create( @@ -6840,7 +6836,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PUMPKIN))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.CARVED_PUMPKIN, create( @@ -6848,7 +6844,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CARVED_PUMPKIN))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.HEAD) .swappable(false) .cameraOverlay(Identifier.ofVanilla("misc/pumpkinblur")) @@ -6861,7 +6857,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MELON))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.SEA_PICKLE, create( @@ -6869,14 +6865,14 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SEA_PICKLE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.WHEAT, create( ItemDisplay.Builder.forItem(ItemKeys.WHEAT).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.DANDELION, create( @@ -6884,7 +6880,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.DANDELION))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.SATURATION), 140) )) @@ -6898,7 +6894,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.OPEN_EYEBLOSSOM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.BLINDNESS), 140) )) @@ -6912,7 +6908,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CLOSED_EYEBLOSSOM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.NAUSEA), 140) )) @@ -6926,7 +6922,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.POPPY))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.NIGHT_VISION), 100) )) @@ -6940,7 +6936,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BLUE_ORCHID))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.SATURATION), 140) )) @@ -6954,7 +6950,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.ALLIUM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.FIRE_RESISTANCE), 80) )) @@ -6968,7 +6964,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.AZURE_BLUET))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.BLINDNESS), 160) )) @@ -6982,7 +6978,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.RED_TULIP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.WEAKNESS), 180) )) @@ -6996,7 +6992,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.ORANGE_TULIP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.WEAKNESS), 180) )) @@ -7010,7 +7006,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WHITE_TULIP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.WEAKNESS), 180) )) @@ -7024,7 +7020,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PINK_TULIP))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.WEAKNESS), 180) )) @@ -7038,7 +7034,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.OXEYE_DAISY))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.REGENERATION), 160) )) @@ -7052,7 +7048,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CORNFLOWER))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.JUMP_BOOST), 120) )) @@ -7066,7 +7062,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LILY_OF_THE_VALLEY))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.POISON), 240) )) @@ -7080,7 +7076,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WITHER_ROSE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.WITHER), 160) )) @@ -7094,7 +7090,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.AZALEA))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -7106,7 +7102,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SUNFLOWER))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.LILAC, create( @@ -7114,7 +7110,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LILAC))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.ROSE_BUSH, create( @@ -7122,7 +7118,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.ROSE_BUSH))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.PEONY, create( @@ -7130,7 +7126,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PEONY))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.LARGE_FERN, create( @@ -7138,7 +7134,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LARGE_FERN))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.SPORE_BLOSSOM, create( @@ -7146,7 +7142,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SPORE_BLOSSOM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.BROWN_MUSHROOM, create( @@ -7154,7 +7150,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BROWN_MUSHROOM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_BROWN_MUSHROOM)) @@ -7165,7 +7161,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.RED_MUSHROOM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_RED_MUSHROOM)) @@ -7176,7 +7172,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CRIMSON_FUNGUS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_CRIMSON_FUNGUS)) @@ -7187,7 +7183,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WARPED_FUNGUS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_WARPED_FUNGUS)) @@ -7198,7 +7194,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CRIMSON_ROOTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_CRIMSON_ROOTS)) @@ -7209,7 +7205,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WARPED_ROOTS))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, Actions.potBlock(this.blocks, BlockKeys.POTTED_WARPED_ROOTS)) @@ -7220,7 +7216,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MOSS_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.PALE_MOSS_BLOCK, create( @@ -7228,7 +7224,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PALE_MOSS_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.MUSHROOM_STEM, create( @@ -7236,7 +7232,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.MUSHROOM_STEM))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.SHROOMLIGHT, create( @@ -7244,7 +7240,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SHROOMLIGHT))) - .with(CompostableItemComponent.of(ComposterBlockUtil.BIG_CHANCE_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.BIG)) .build() )); this.registerable.register(ItemKeys.NETHER_WART_BLOCK, create( @@ -7252,7 +7248,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.NETHER_WART_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.WARPED_WART_BLOCK, create( @@ -7260,7 +7256,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WARPED_WART_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.HAY_BLOCK, create( @@ -7268,7 +7264,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.HAY_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.FLOWERING_AZALEA, create( @@ -7276,7 +7272,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.FLOWERING_AZALEA))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .with(FuelItemComponent.of(FuelTimes.PLANT)) .build(), ItemEventMap.builder() @@ -7288,7 +7284,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.TORCHFLOWER))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .with(SuspiciousEffectIngredientItemComponent.of( new SuspiciousStewEffectsComponent.StewEffect(this.statusEffects.getOrThrow(StatusEffectKeys.NIGHT_VISION), 100) )) @@ -7302,7 +7298,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.PITCHER_PLANT))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.BROWN_MUSHROOM_BLOCK, create( @@ -7310,7 +7306,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BROWN_MUSHROOM_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.RED_MUSHROOM_BLOCK, create( @@ -7318,7 +7314,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.RED_MUSHROOM_BLOCK))) - .with(CompostableItemComponent.of(ComposterBlockUtil.ALMOST_GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.ALMOST_GUARANTEED)) .build() )); this.registerable.register(ItemKeys.CAKE, create( @@ -7326,7 +7322,7 @@ private void bootstrapCompostables() { ItemComponentSet.builder() .with(StackableItemComponent.of(1)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CAKE))) - .with(CompostableItemComponent.of(ComposterBlockUtil.GUARANTEED_TO_COMPOST)) + .with(CompostableItemComponent.of(CompostChances.GUARANTEED)) .build() )); } @@ -7363,12 +7359,22 @@ private void bootstrapEquipment() { .with(UseableItemComponent.builder() .useIndefinitely() .animation(UseAction.BLOCK) - .build()) + .build() + ) .with(DamageableItemComponent.of(336)) + .with(AttackBlockingItemComponent.of(new BlocksAttacksComponent( + 0.25f, + 1.0f, + List.of(BlocksAttacksComponent.DamageReduction.DEFAULT), + new BlocksAttacksComponent.ItemDamage(3.0f, 1.0f, 1.0f), + Optional.of(this.soundEvents.getOrThrow(SoundEventKeys.SHIELD_BLOCK)), + Optional.of(this.soundEvents.getOrThrow(SoundEventKeys.SHIELD_BREAK)) + ))) .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.OFFHAND) .equipSound(this.soundEvents.getOrThrow(SoundEventKeys.ARMOR_EQUIP_GENERIC)) .swappable(false) - .build())) + .build() + )) .with(RepairableItemComponent.of(this.items.getOrThrow(ItemTags.WOODEN_TOOL_MATERIALS))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .with(BannerPatternHolderItemComponent.of()) @@ -7379,9 +7385,9 @@ private void bootstrapEquipment() { private void bootstrapArmor() { this.registerable.register(ItemKeys.LEATHER_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.LEATHER_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.LEATHER, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.LEATHER, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.LEATHER, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.LEATHER, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.LEATHER)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_LEATHER_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7390,9 +7396,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.LEATHER_CHESTPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.LEATHER_CHESTPLATE).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.LEATHER, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.LEATHER, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.LEATHER, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.LEATHER, EquipmentType.CHESTPLATE)) .with(EnchantableItemComponent.of(ArmorMaterials.LEATHER)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_LEATHER_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7401,9 +7407,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.LEATHER_LEGGINGS, create( ItemDisplay.Builder.forItem(ItemKeys.LEATHER_LEGGINGS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.LEATHER, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.LEATHER, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.LEATHER, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.LEATHER, EquipmentType.LEGGINGS)) .with(EnchantableItemComponent.of(ArmorMaterials.LEATHER)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_LEATHER_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7412,9 +7418,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.LEATHER_BOOTS, create( ItemDisplay.Builder.forItem(ItemKeys.LEATHER_BOOTS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.LEATHER, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.LEATHER, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.LEATHER, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.LEATHER, EquipmentType.BOOTS)) .with(EnchantableItemComponent.of(ArmorMaterials.LEATHER)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_LEATHER_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7425,9 +7431,9 @@ private void bootstrapArmor() { ItemDisplay.Builder.forItem(ItemKeys.CHAINMAIL_HELMET) .rarity(Rarity.UNCOMMON) .build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.CHAIN, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.CHAIN, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.CHAIN, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.CHAIN, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.CHAIN)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_CHAINMAIL_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7437,9 +7443,9 @@ private void bootstrapArmor() { ItemDisplay.Builder.forItem(ItemKeys.CHAINMAIL_CHESTPLATE) .rarity(Rarity.UNCOMMON) .build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.CHAIN, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.CHAIN, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.CHAIN, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.CHAIN, EquipmentType.CHESTPLATE)) .with(EnchantableItemComponent.of(ArmorMaterials.CHAIN)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_CHAINMAIL_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7449,9 +7455,9 @@ private void bootstrapArmor() { ItemDisplay.Builder.forItem(ItemKeys.CHAINMAIL_LEGGINGS) .rarity(Rarity.UNCOMMON) .build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.CHAIN, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.CHAIN, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.CHAIN, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.CHAIN, EquipmentType.LEGGINGS)) .with(EnchantableItemComponent.of(ArmorMaterials.CHAIN)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_CHAINMAIL_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7461,9 +7467,9 @@ private void bootstrapArmor() { ItemDisplay.Builder.forItem(ItemKeys.CHAINMAIL_BOOTS) .rarity(Rarity.UNCOMMON) .build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.CHAIN, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.CHAIN, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.CHAIN, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.CHAIN, EquipmentType.BOOTS)) .with(EnchantableItemComponent.of(ArmorMaterials.CHAIN)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_CHAINMAIL_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7471,9 +7477,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.IRON_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.IRON_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.IRON, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.IRON, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.IRON, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.IRON, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.IRON)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_IRON_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7481,9 +7487,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.IRON_CHESTPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.IRON_CHESTPLATE).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.IRON, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.IRON, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.IRON, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.IRON, EquipmentType.CHESTPLATE)) .with(EnchantableItemComponent.of(ArmorMaterials.IRON)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_IRON_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7491,9 +7497,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.IRON_LEGGINGS, create( ItemDisplay.Builder.forItem(ItemKeys.IRON_LEGGINGS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.IRON, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.IRON, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.IRON, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.IRON, EquipmentType.LEGGINGS)) .with(EnchantableItemComponent.of(ArmorMaterials.IRON)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_IRON_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7501,9 +7507,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.IRON_BOOTS, create( ItemDisplay.Builder.forItem(ItemKeys.IRON_BOOTS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.IRON, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.IRON, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.IRON, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.IRON, EquipmentType.BOOTS)) .with(EnchantableItemComponent.of(ArmorMaterials.IRON)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_IRON_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7511,9 +7517,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.DIAMOND_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.DIAMOND, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.DIAMOND, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.DIAMOND, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.DIAMOND, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.DIAMOND)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_DIAMOND_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7521,9 +7527,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.DIAMOND_CHESTPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND_CHESTPLATE).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.DIAMOND, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.DIAMOND, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.DIAMOND, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.DIAMOND, EquipmentType.CHESTPLATE)) .with(EnchantableItemComponent.of(ArmorMaterials.DIAMOND)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_DIAMOND_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7531,9 +7537,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.DIAMOND_LEGGINGS, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND_LEGGINGS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.DIAMOND, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.DIAMOND, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.DIAMOND, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.DIAMOND, EquipmentType.LEGGINGS)) .with(EnchantableItemComponent.of(ArmorMaterials.DIAMOND)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_DIAMOND_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7541,9 +7547,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.DIAMOND_BOOTS, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND_BOOTS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.DIAMOND, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.DIAMOND, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.DIAMOND, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.DIAMOND, EquipmentType.BOOTS)) .with(EnchantableItemComponent.of(ArmorMaterials.DIAMOND)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_DIAMOND_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7551,9 +7557,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.GOLDEN_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.GOLDEN_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.GOLD, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.GOLD, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.GOLD, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.GOLD, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.GOLD)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_GOLDEN_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7561,9 +7567,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.GOLDEN_CHESTPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.GOLDEN_CHESTPLATE).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.GOLD, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.GOLD, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.GOLD, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.GOLD, EquipmentType.CHESTPLATE)) .with(EnchantableItemComponent.of(ArmorMaterials.GOLD)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_GOLDEN_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7571,9 +7577,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.GOLDEN_LEGGINGS, create( ItemDisplay.Builder.forItem(ItemKeys.GOLDEN_LEGGINGS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.GOLD, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.GOLD, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.GOLD, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.GOLD, EquipmentType.LEGGINGS)) .with(EnchantableItemComponent.of(ArmorMaterials.GOLD)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_GOLDEN_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7581,9 +7587,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.GOLDEN_BOOTS, create( ItemDisplay.Builder.forItem(ItemKeys.GOLDEN_BOOTS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.GOLD, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.GOLD, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.GOLD, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.GOLD, EquipmentType.BOOTS)) .with(EnchantableItemComponent.of(ArmorMaterials.GOLD)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_GOLDEN_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7591,9 +7597,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.NETHERITE_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.NETHERITE_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.NETHERITE, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.NETHERITE, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.NETHERITE, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.NETHERITE, EquipmentType.HELMET)) .with(ImmuneToDamageItemComponent.of(DamageTypeTags.IS_FIRE)) .with(EnchantableItemComponent.of(ArmorMaterials.NETHERITE)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_NETHERITE_ARMOR))) @@ -7602,9 +7608,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.NETHERITE_CHESTPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.NETHERITE_CHESTPLATE).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.NETHERITE, EquipmentType.CHESTPLATE), + AttributeModifiers.armor(ArmorMaterials.NETHERITE, EquipmentType.CHESTPLATE), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.NETHERITE, EquipmentType.CHESTPLATE)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.NETHERITE, EquipmentType.CHESTPLATE)) .with(ImmuneToDamageItemComponent.of(DamageTypeTags.IS_FIRE)) .with(EnchantableItemComponent.of(ArmorMaterials.NETHERITE)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_NETHERITE_ARMOR))) @@ -7613,9 +7619,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.NETHERITE_LEGGINGS, create( ItemDisplay.Builder.forItem(ItemKeys.NETHERITE_LEGGINGS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.NETHERITE, EquipmentType.LEGGINGS), + AttributeModifiers.armor(ArmorMaterials.NETHERITE, EquipmentType.LEGGINGS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.NETHERITE, EquipmentType.LEGGINGS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.NETHERITE, EquipmentType.LEGGINGS)) .with(ImmuneToDamageItemComponent.of(DamageTypeTags.IS_FIRE)) .with(EnchantableItemComponent.of(ArmorMaterials.NETHERITE)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_NETHERITE_ARMOR))) @@ -7624,9 +7630,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.NETHERITE_BOOTS, create( ItemDisplay.Builder.forItem(ItemKeys.NETHERITE_BOOTS).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.NETHERITE, EquipmentType.BOOTS), + AttributeModifiers.armor(ArmorMaterials.NETHERITE, EquipmentType.BOOTS), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.NETHERITE, EquipmentType.BOOTS)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.NETHERITE, EquipmentType.BOOTS)) .with(ImmuneToDamageItemComponent.of(DamageTypeTags.IS_FIRE)) .with(EnchantableItemComponent.of(ArmorMaterials.NETHERITE)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_NETHERITE_ARMOR))) @@ -7635,9 +7641,9 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.TURTLE_HELMET, create( ItemDisplay.Builder.forItem(ItemKeys.TURTLE_HELMET).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.TURTLE_SCUTE, EquipmentType.HELMET), + AttributeModifiers.armor(ArmorMaterials.TURTLE_SCUTE, EquipmentType.HELMET), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.TURTLE_SCUTE, EquipmentType.HELMET)) + .with(EquipmentItemComponent.forArmor(ArmorMaterials.TURTLE_SCUTE, EquipmentType.HELMET)) .with(EnchantableItemComponent.of(ArmorMaterials.TURTLE_SCUTE)) .with(RepairableItemComponent.of(this.items.getOrThrow(ItematicItemTags.REPAIRS_TURTLE_ARMOR))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) @@ -7645,42 +7651,61 @@ private void bootstrapArmor() { )); this.registerable.register(ItemKeys.LEATHER_HORSE_ARMOR, create( ItemDisplay.Builder.forItem(ItemKeys.LEATHER_HORSE_ARMOR).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.LEATHER, EquipmentType.BODY), + AttributeModifiers.armor(ArmorMaterials.LEATHER, EquipmentType.BODY), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.LEATHER, EquipmentType.BODY, AnimalArmorItem.Type.EQUESTRIAN)) + .with(StackableItemComponent.of(1)) + .with(EquipmentItemComponent.ofHorseArmor(ArmorMaterials.LEATHER, this.soundEvents, this.entityTypes)) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .with(DyeableItemComponent.of()) .build() )); this.registerable.register(ItemKeys.IRON_HORSE_ARMOR, create( ItemDisplay.Builder.forItem(ItemKeys.IRON_HORSE_ARMOR).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.IRON, EquipmentType.BODY), + AttributeModifiers.armor(ArmorMaterials.IRON, EquipmentType.BODY), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.IRON, EquipmentType.BODY, AnimalArmorItem.Type.EQUESTRIAN)) + .with(StackableItemComponent.of(1)) + .with(EquipmentItemComponent.ofHorseArmor(ArmorMaterials.IRON, this.soundEvents, this.entityTypes)) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); this.registerable.register(ItemKeys.GOLDEN_HORSE_ARMOR, create( ItemDisplay.Builder.forItem(ItemKeys.GOLDEN_HORSE_ARMOR).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.GOLD, EquipmentType.BODY), + AttributeModifiers.armor(ArmorMaterials.GOLD, EquipmentType.BODY), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.GOLD, EquipmentType.BODY, AnimalArmorItem.Type.EQUESTRIAN)) + .with(StackableItemComponent.of(1)) + .with(EquipmentItemComponent.ofHorseArmor(ArmorMaterials.GOLD, this.soundEvents, this.entityTypes)) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); this.registerable.register(ItemKeys.DIAMOND_HORSE_ARMOR, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND_HORSE_ARMOR).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.DIAMOND, EquipmentType.BODY), + AttributeModifiers.armor(ArmorMaterials.DIAMOND, EquipmentType.BODY), ItemComponentSet.builder() - .with(EquipmentItemComponent.from(ArmorMaterials.DIAMOND, EquipmentType.BODY, AnimalArmorItem.Type.EQUESTRIAN)) + .with(StackableItemComponent.of(1)) + .with(EquipmentItemComponent.ofHorseArmor(ArmorMaterials.DIAMOND, this.soundEvents, this.entityTypes)) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); this.registerable.register(ItemKeys.WOLF_ARMOR, create( ItemDisplay.Builder.forItem(ItemKeys.WOLF_ARMOR).build(), - AttributeModifiersComponentUtil.armor(ArmorMaterials.ARMADILLO_SCUTE, EquipmentType.BODY), + AttributeModifiers.armor(ArmorMaterials.ARMADILLO_SCUTE, EquipmentType.BODY), ItemComponentSet.builder() - .with(EquipmentItemComponent.fromDamageable(ArmorMaterials.ARMADILLO_SCUTE, EquipmentType.BODY, AnimalArmorItem.Type.CANINE)) + .with(StackableItemComponent.of(1)) + .with(DamageableItemComponent.of( + EquipmentType.BODY.getMaxDamage(ArmorMaterials.ARMADILLO_SCUTE.durability()), + this.soundEvents.getOrThrow(SoundEventKeys.WOLF_ARMOR_BREAK) + )) + .with(RepairableItemComponent.of( + this.items.getOrThrow(ArmorMaterials.ARMADILLO_SCUTE.repairIngredient()) + )) + .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.BODY) + .equipSound(ArmorMaterials.ARMADILLO_SCUTE.equipSound()) + .model(ArmorMaterials.ARMADILLO_SCUTE.assetId()) + .allowedEntities(RegistryEntryList.of( + this.entityTypes.getOrThrow(EntityTypeKeys.WOLF) + )) + .build() + )) .with(DyeableItemComponent.of(0x000000)) .build() )); @@ -7693,7 +7718,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.SKELETON_SKULL), this.blocks.getOrThrow(BlockKeys.SKELETON_WALL_SKULL), this.dispenseBehaviors @@ -7706,7 +7731,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.WITHER_SKELETON_SKULL), this.blocks.getOrThrow(BlockKeys.WITHER_SKELETON_WALL_SKULL), this.dispenseBehaviors @@ -7719,7 +7744,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.PLAYER_HEAD), this.blocks.getOrThrow(BlockKeys.PLAYER_WALL_HEAD), this.dispenseBehaviors @@ -7732,7 +7757,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.ZOMBIE_HEAD), this.blocks.getOrThrow(BlockKeys.ZOMBIE_WALL_HEAD), this.dispenseBehaviors @@ -7745,7 +7770,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.CREEPER_HEAD), this.blocks.getOrThrow(BlockKeys.CREEPER_WALL_HEAD), this.dispenseBehaviors @@ -7758,7 +7783,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.DRAGON_HEAD), this.blocks.getOrThrow(BlockKeys.DRAGON_WALL_HEAD), this.dispenseBehaviors @@ -7771,7 +7796,7 @@ private void bootstrapSkulls() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(EquipmentItemComponent.skull( + .with(EquipmentItemComponent.forSkull( this.blocks.getOrThrow(BlockKeys.PIGLIN_HEAD), this.blocks.getOrThrow(BlockKeys.PIGLIN_WALL_HEAD), this.dispenseBehaviors @@ -9485,6 +9510,7 @@ private void bootstrapFuel() { .with(StackableItemComponent.of(64)) .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LEAF_LITTER))) .with(FuelItemComponent.of(FuelTimes.PLANT)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); } @@ -9623,7 +9649,7 @@ private void bootstrapProjectiles() { .with(StackableItemComponent.of(1)) .with(PotionHolderItemComponent.of(1.0f)) .with(ThrowableItemComponent.of(0.5f, -20.0f)) - .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.POTION))) + .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.SPLASH_POTION))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SHOOT_BOTTLE))) .build() )); @@ -9650,7 +9676,7 @@ private void bootstrapProjectiles() { .with(StackableItemComponent.of(1)) .with(PotionHolderItemComponent.of(0.25f)) .with(ThrowableItemComponent.of(0.5f, -20.0f)) - .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.POTION))) + .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.LINGERING_POTION))) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SHOOT_BOTTLE))) .build() )); @@ -9928,7 +9954,7 @@ private void bootstrapRecords() { this.registerable.register(ItemKeys.DISC_FRAGMENT_5, create( ItemDisplay.Builder.forItem(ItemKeys.DISC_FRAGMENT_5) .rarity(Rarity.UNCOMMON) - .tooltip(ItemKeys.DISC_FRAGMENT_5) + .tooltip(Tooltips.description(ItemKeys.DISC_FRAGMENT_5)) .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) @@ -10005,153 +10031,191 @@ private void bootstrapSmithingTemplates() { this.registerable.register(ItemKeys.NETHERITE_UPGRADE_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.NETHERITE_UPGRADE_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingUpgrade(Identifier.ofVanilla("netherite_upgrade"))) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.NETHERITE_UPGRADE))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.ITEM_UPGRADE)) .build() )); this.registerable.register(ItemKeys.SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.SENTRY_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.DUNE_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.DUNE_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.DUNE_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.COAST_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.COAST_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.COAST_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.WILD_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.WILD_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.WILD_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.WARD_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.WARD_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.WARD_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.EYE_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.EYE_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.EYE_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.VEX_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.VEX_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.VEX_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.TIDE_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.TIDE_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.TIDE_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.SNOUT_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.RIB_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.RIB_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.RIB_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.SPIRE_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.WAYFINDER_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.SHAPER_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.EPIC) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.SILENCE_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.RAISER_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.RAISER_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.RAISER_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.HOST_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.HOST_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.HOST_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.FLOW_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.FLOW_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.FLOW_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); this.registerable.register(ItemKeys.BOLT_ARMOR_TRIM_SMITHING_TEMPLATE, create( ItemDisplay.Builder.forItem(ItemKeys.BOLT_ARMOR_TRIM_SMITHING_TEMPLATE) .rarity(Rarity.UNCOMMON) + .tooltip(Tooltips.smithingTrimPattern()) .build(), ItemComponentSet.builder() - .with(SmithingTemplateItemComponent.of(this.smithingTemplates.getOrThrow(SmithingTemplates.BOLT_PATTERN))) + .with(StackableItemComponent.of(64)) + .with(SmithingTemplateProviderItemComponent.of(SmithingTemplates.TRIM_PATTERN)) .build() )); } @@ -10599,6 +10663,7 @@ private void bootstrapImmuneToDamage() { ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .with(ImmuneToDamageItemComponent.of(DamageTypeTags.IS_FIRE)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.NETHERITE))) .build() )); this.registerable.register(ItemKeys.NETHERITE_SCRAP, create( @@ -10620,98 +10685,124 @@ private void bootstrapImmuneToDamage() { )); } - private void bootstrapMiscellaneous() { - this.registerable.register(ItemKeys.AIR, create( - ItemDisplay.Builder.forBlock(ItemKeys.AIR).build() - )); - this.registerable.register(ItemKeys.SADDLE, create( - ItemDisplay.Builder.forItem(ItemKeys.SADDLE).build(), - ItemComponentSet.builder() - .with(StackableItemComponent.of(1)) - .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.SADDLE) - .equipSound(SoundEvents.ENTITY_HORSE_SADDLE) - .model(EquipmentAssetKeys.SADDLE) - .allowedEntities(this.entityTypes.getOrThrow(EntityTypeTags.CAN_EQUIP_SADDLE)) - .equipOnInteract(true) - .build() - )) - .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) - .build() - )); - this.registerable.register(ItemKeys.TURTLE_SCUTE, create( - ItemDisplay.Builder.forItem(ItemKeys.TURTLE_SCUTE).build(), - ItemComponentSet.builder() - .with(StackableItemComponent.of(64)) - .build() - )); - this.registerable.register(ItemKeys.ARMADILLO_SCUTE, create( - ItemDisplay.Builder.forItem(ItemKeys.ARMADILLO_SCUTE).build(), + private void bootstrapTrimMaterialProviders() { + this.registerable.register(ItemKeys.REDSTONE, create( + ItemDisplay.Builder.forItem(ItemKeys.REDSTONE).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.REDSTONE_WIRE))) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.REDSTONE))) .build() )); this.registerable.register(ItemKeys.DIAMOND, create( ItemDisplay.Builder.forItem(ItemKeys.DIAMOND).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.DIAMOND))) .build() )); this.registerable.register(ItemKeys.EMERALD, create( ItemDisplay.Builder.forItem(ItemKeys.EMERALD).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.EMERALD))) .build() )); this.registerable.register(ItemKeys.LAPIS_LAZULI, create( ItemDisplay.Builder.forItem(ItemKeys.LAPIS_LAZULI).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.LAPIS))) .build() )); this.registerable.register(ItemKeys.QUARTZ, create( ItemDisplay.Builder.forItem(ItemKeys.QUARTZ).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.QUARTZ))) .build() )); this.registerable.register(ItemKeys.AMETHYST_SHARD, create( ItemDisplay.Builder.forItem(ItemKeys.AMETHYST_SHARD).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.AMETHYST))) .build() )); - this.registerable.register(ItemKeys.RAW_IRON, create( - ItemDisplay.Builder.forItem(ItemKeys.RAW_IRON).build(), + this.registerable.register(ItemKeys.IRON_INGOT, create( + ItemDisplay.Builder.forItem(ItemKeys.IRON_INGOT).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.IRON))) .build() )); - this.registerable.register(ItemKeys.IRON_INGOT, create( - ItemDisplay.Builder.forItem(ItemKeys.IRON_INGOT).build(), + this.registerable.register(ItemKeys.COPPER_INGOT, create( + ItemDisplay.Builder.forItem(ItemKeys.COPPER_INGOT).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.COPPER))) .build() )); - this.registerable.register(ItemKeys.RAW_COPPER, create( - ItemDisplay.Builder.forItem(ItemKeys.RAW_COPPER).build(), + this.registerable.register(ItemKeys.GOLD_INGOT, create( + ItemDisplay.Builder.forItem(ItemKeys.GOLD_INGOT).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.GOLD))) .build() )); - this.registerable.register(ItemKeys.COPPER_INGOT, create( - ItemDisplay.Builder.forItem(ItemKeys.COPPER_INGOT).build(), + this.registerable.register(ItemKeys.RESIN_BRICK, create( + ItemDisplay.Builder.forItem(ItemKeys.RESIN_BRICK).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) + .with(TrimMaterialProviderItemComponent.of(this.trimMaterials.getOrThrow(ArmorTrimMaterials.RESIN))) .build() )); - this.registerable.register(ItemKeys.RAW_GOLD, create( - ItemDisplay.Builder.forItem(ItemKeys.RAW_GOLD).build(), + } + + private void bootstrapMiscellaneous() { + this.registerable.register(ItemKeys.AIR, create( + ItemDisplay.Builder.forBlock(ItemKeys.AIR).build() + )); + this.registerable.register(ItemKeys.SADDLE, create( + ItemDisplay.Builder.forItem(ItemKeys.SADDLE).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(1)) + .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.SADDLE) + .equipSound(SoundEvents.ENTITY_HORSE_SADDLE) + .model(EquipmentAssetKeys.SADDLE) + .allowedEntities(this.entityTypes.getOrThrow(EntityTypeTags.CAN_EQUIP_SADDLE)) + .equipOnInteract(true) + .build() + )) + .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) + .build() + )); + this.registerable.register(ItemKeys.TURTLE_SCUTE, create( + ItemDisplay.Builder.forItem(ItemKeys.TURTLE_SCUTE).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .build() )); - this.registerable.register(ItemKeys.GOLD_INGOT, create( - ItemDisplay.Builder.forItem(ItemKeys.GOLD_INGOT).build(), + this.registerable.register(ItemKeys.ARMADILLO_SCUTE, create( + ItemDisplay.Builder.forItem(ItemKeys.ARMADILLO_SCUTE).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .build() + )); + this.registerable.register(ItemKeys.RAW_IRON, create( + ItemDisplay.Builder.forItem(ItemKeys.RAW_IRON).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .build() + )); + this.registerable.register(ItemKeys.RAW_COPPER, create( + ItemDisplay.Builder.forItem(ItemKeys.RAW_COPPER).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .build() + )); + this.registerable.register(ItemKeys.RAW_GOLD, create( + ItemDisplay.Builder.forItem(ItemKeys.RAW_GOLD).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) .build() @@ -11098,16 +11189,6 @@ private void bootstrapMiscellaneous() { ItemComponentSet.builder() .with(StackableItemComponent.of(16)) .with(TextHolderItemComponent.INSTANCE) - .build(), - ItemEventMap.builder() - .add(ItemEvents.USE, ActionEntry.of( - PassingSequenceHandler.builder() - .add(OpenBookFromItemAction.INSTANCE) - .add(IncrementStatAction.of( - LootContext.EntityTarget.THIS, - Stats.USED.itematic$getOrCreateStat(this.items.getOrThrow(ItemKeys.WRITTEN_BOOK)) - )) - )) .build() )); this.registerable.register(ItemKeys.MAP, create( @@ -11140,12 +11221,6 @@ private void bootstrapMiscellaneous() { .with(StackableItemComponent.of(64)) .build() )); - this.registerable.register(ItemKeys.RESIN_BRICK, create( - ItemDisplay.Builder.forItem(ItemKeys.RESIN_BRICK).build(), - ItemComponentSet.builder() - .with(StackableItemComponent.of(64)) - .build() - )); this.registerable.register(ItemKeys.PRISMARINE_SHARD, create( ItemDisplay.Builder.forItem(ItemKeys.PRISMARINE_SHARD).build(), ItemComponentSet.builder() @@ -11287,7 +11362,7 @@ private void bootstrapMiscellaneous() { .build(), ItemComponentSet.builder() .with(StackableItemComponent.of(1)) - .with(PlayableItemComponent.of(InstrumentTags.GOAT_HORNS)) + .with(PlayableItemComponent.of(this.instruments.getOrThrow(Instruments.PONDER_GOAT_HORN))) .build() )); this.registerable.register(ItemKeys.HONEYCOMB, create( diff --git a/src/main/java/net/errorcraft/itematic/item/Tooltips.java b/src/main/java/net/errorcraft/itematic/item/Tooltips.java new file mode 100644 index 00000000..4fc7d770 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/Tooltips.java @@ -0,0 +1,44 @@ +package net.errorcraft.itematic.item; + +import net.errorcraft.itematic.mixin.item.SmithingTemplateItemAccessor; +import net.errorcraft.itematic.util.Util; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKey; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +public class Tooltips { + private Tooltips() {} + + public static Text description(RegistryKey item) { + return Text.translatable(Util.descriptionKey("item", item.getValue(), "desc")) + .formatted(Formatting.GRAY); + } + + public static Text[] smithingUpgrade(Identifier upgradeName) { + return smithing( + Text.translatable(Util.descriptionKey("smithing_template", upgradeName, "applies_to")), + Text.translatable(Util.descriptionKey("smithing_template", upgradeName, "ingredients")) + ); + } + + public static Text[] smithingTrimPattern() { + return smithing( + SmithingTemplateItemAccessor.trimPatternAppliesToLabel(), + SmithingTemplateItemAccessor.trimPatternIngredients() + ); + } + + private static Text[] smithing(Text appliesTo, Text ingredients) { + return new Text[] { + SmithingTemplateItemAccessor.smithingTemplateTitle(), + ScreenTexts.EMPTY, + SmithingTemplateItemAccessor.appliesToTitle(), + ScreenTexts.space().append(appliesTo), + SmithingTemplateItemAccessor.ingredientsTitle(), + ScreenTexts.space().append(ingredients) + }; + } +} 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 4aa28ebf..f7b2b006 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java @@ -21,8 +21,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import java.util.List; import java.util.Set; +import java.util.function.Consumer; public interface ItemComponent> { SetMapCodec, ItemComponent> SET_MAP_CODEC = SetMapCodec.ofRegistry(ItematicRegistries.ITEM_COMPONENT_TYPE, ItemComponentType::codec, ItemComponent::codec, ItemComponent::type); @@ -72,5 +72,5 @@ default void onCraft(ItemStack stack, World world) {} default void addComponents(ComponentMap.Builder builder) {} - default void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) {} + default void appendTooltip(ItemStack stack, Item.TooltipContext context, Consumer builder, TooltipType type) {} } 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 bd651543..9e9778b3 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -36,7 +36,7 @@ public class ItemComponentTypes { public static final ItemComponentType STEERING = register("steering", new ItemComponentType<>(SteeringItemComponent.CODEC)); public static final ItemComponentType POINTABLE = register("pointable", new ItemComponentType<>(PointableItemComponent.CODEC)); public static final ItemComponentType PREVENT_USE_WHEN_USED_ON_TARGET = register("prevent_use_when_used_on_target", new ItemComponentType<>(PreventUseWhenUsedOnTargetItemComponent.CODEC)); - public static final ItemComponentType SMITHING_TEMPLATE = register("smithing_template", new ItemComponentType<>(SmithingTemplateItemComponent.CODEC)); + public static final ItemComponentType SMITHING_TEMPLATE_PROVIDER = register("smithing_template_provider", new ItemComponentType<>(SmithingTemplateProviderItemComponent.CODEC)); public static final ItemComponentType BANNER_PATTERN = register("banner_pattern", new ItemComponentType<>(BannerPatternItemComponent.CODEC)); public static final ItemComponentType BANNER_PATTERN_HOLDER = register("banner_pattern_holder", new ItemComponentType<>(BannerPatternHolderItemComponent.CODEC)); public static final ItemComponentType WRITABLE = register("writable", new ItemComponentType<>(WritableItemComponent.CODEC)); @@ -56,6 +56,8 @@ public class ItemComponentTypes { public static final ItemComponentType STACKABLE = register("stackable", new ItemComponentType<>(StackableItemComponent.CODEC)); public static final ItemComponentType OMINOUS_EFFECT_PROVIDER = register("ominous_effect_provider", new ItemComponentType<>(OminousEffectProviderItemComponent.CODEC)); public static final ItemComponentType GLIDER = register("glider", new ItemComponentType<>(GliderItemComponent.CODEC)); + public static final ItemComponentType ATTACK_BLOCKING = register("attack_blocking", new ItemComponentType<>(AttackBlockingItemComponent.CODEC)); + public static final ItemComponentType TRIM_MATERIAL_PROVIDER = register("trim_material_provider", new ItemComponentType<>(TrimMaterialProviderItemComponent.CODEC)); private ItemComponentTypes() {} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/AttackBlockingItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/AttackBlockingItemComponent.java new file mode 100644 index 00000000..33d9e2ad --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/component/components/AttackBlockingItemComponent.java @@ -0,0 +1,35 @@ +package net.errorcraft.itematic.item.component.components; + +import com.mojang.serialization.Codec; +import net.errorcraft.itematic.item.component.ItemComponent; +import net.errorcraft.itematic.item.component.ItemComponentType; +import net.errorcraft.itematic.item.component.ItemComponentTypes; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.BlocksAttacksComponent; + +public record AttackBlockingItemComponent(BlocksAttacksComponent blocksAttacks) implements ItemComponent { + public static final Codec CODEC = BlocksAttacksComponent.CODEC.xmap( + AttackBlockingItemComponent::new, + AttackBlockingItemComponent::blocksAttacks + ); + + public static AttackBlockingItemComponent of(BlocksAttacksComponent blocksAttacks) { + return new AttackBlockingItemComponent(blocksAttacks); + } + + @Override + public ItemComponentType type() { + return ItemComponentTypes.ATTACK_BLOCKING; + } + + @Override + public Codec codec() { + return CODEC; + } + + @Override + public void addComponents(ComponentMap.Builder builder) { + builder.add(DataComponentTypes.BLOCKS_ATTACKS, this.blocksAttacks); + } +} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java index bbed680d..aea42558 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java @@ -8,14 +8,9 @@ import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.BannerPatternsComponent; -import net.minecraft.item.BannerItem; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.util.DyeColor; -import java.util.List; import java.util.Optional; public record BannerPatternHolderItemComponent(Optional color) implements ItemComponent { @@ -38,11 +33,6 @@ public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.BANNER_PATTERNS, BannerPatternsComponent.DEFAULT); } - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - BannerItem.appendBannerTooltip(stack, tooltip); - } - public boolean modifiable() { return this.color.isPresent(); } @@ -51,10 +41,12 @@ public Optional translationKey(ItemStack stack, String baseTranslationKe if (this.modifiable()) { return Optional.empty(); } + DyeColor baseColor = stack.get(DataComponentTypes.BASE_COLOR); if (baseColor == null) { return Optional.empty(); } + return Optional.of(baseTranslationKey + "." + baseColor.getName()); } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternItemComponent.java index 63192597..ee51bdcb 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternItemComponent.java @@ -6,6 +6,8 @@ import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.minecraft.block.entity.BannerPattern; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.DataComponentTypes; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.TagKey; @@ -30,4 +32,9 @@ public ItemComponentType type() { public Codec codec() { return CODEC; } + + @Override + public void addComponents(ComponentMap.Builder builder) { + builder.add(DataComponentTypes.PROVIDES_BANNER_PATTERNS, this.patterns); + } } 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 74b81fef..6939165a 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 @@ -20,13 +20,10 @@ import net.minecraft.component.type.ContainerComponent; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsage; import net.minecraft.item.ItemUsageContext; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.text.Text; import net.minecraft.util.Hand; import net.minecraft.util.StringIdentifiable; import net.minecraft.util.hit.BlockHitResult; @@ -35,7 +32,6 @@ import net.minecraft.world.RaycastContext; import net.minecraft.world.World; -import java.util.List; import java.util.Set; public record BlockItemComponent(BlockPicker block, boolean operatorOnly, Set passes) implements ItemComponent { @@ -104,11 +100,6 @@ public void addComponents(ComponentMap.Builder builder) { this.block.defaultBlock().value().itematic$addComponents(builder); } - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - this.block.defaultBlock().value().appendTooltip(stack, context, tooltip, type); - } - public boolean canBeNested() { return !(this.block.defaultBlock().value() instanceof ShulkerBoxBlock); } 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 a2f6cd15..cf091938 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 @@ -43,7 +43,6 @@ public static DamageableItemComponent ofPreserved(int durability) { } public static ItemComponent[] sword(RegistryEntryLookup blocks, ToolMaterial material, RegistryEntryList repairItems) { - double attackDamage = 4.0d + material.attackDamageBonus(); return new ItemComponent[] { StackableItemComponent.of(1), DamageableItemComponent.of(material.durability()), @@ -54,8 +53,8 @@ public static ItemComponent[] sword(RegistryEntryLookup blocks, ToolMa .build(), WeaponItemComponent.of( 1, - false, - attackDamage, + 0.0f, + 4.0d + material.attackDamageBonus(), 0.4d ), EnchantableItemComponent.of(material), @@ -64,36 +63,30 @@ public static ItemComponent[] sword(RegistryEntryLookup blocks, ToolMa } public static ItemComponent[] shovel(RegistryEntryLookup blocks, ToolMaterial material, RegistryEntryList repairItems) { - return tool(blocks, material, false, 2.5d, 0.25d, BlockTags.SHOVEL_MINEABLE, repairItems); + return tool(blocks, material, 0.0f, 2.5d, 0.25d, BlockTags.SHOVEL_MINEABLE, repairItems); } public static ItemComponent[] pickaxe(RegistryEntryLookup blocks, ToolMaterial material, RegistryEntryList repairItems) { - return tool(blocks, material, false, 2.0d, 0.3d, BlockTags.PICKAXE_MINEABLE, repairItems); + return tool(blocks, material, 0.0f, 2.0d, 0.3d, BlockTags.PICKAXE_MINEABLE, repairItems); } public static ItemComponent[] axe(RegistryEntryLookup blocks, ToolMaterial material, double attackDamage, double attackSpeed, RegistryEntryList repairItems) { - return tool(blocks, material, true, attackDamage, attackSpeed, BlockTags.AXE_MINEABLE, repairItems); + return tool(blocks, material, 5.0f, attackDamage, attackSpeed, BlockTags.AXE_MINEABLE, repairItems); } public static ItemComponent[] hoe(RegistryEntryLookup blocks, ToolMaterial material, double attackDamage, double attackSpeed, RegistryEntryList repairItems) { - return tool(blocks, material, false, attackDamage, attackSpeed, BlockTags.HOE_MINEABLE, repairItems); + return tool(blocks, material, 0.0f, attackDamage, attackSpeed, BlockTags.HOE_MINEABLE, repairItems); } - @Override - public ItemComponentType type() { - return ItemComponentTypes.DAMAGEABLE; - } - - private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMaterial material, boolean canDisableBlocking, double attackDamage, double attackSpeed, TagKey mineableBlocks, RegistryEntryList repairItems) { - double realAttackDamage = attackDamage + material.attackDamageBonus(); + private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMaterial material, float disableBlockingForSeconds, double baseAttackDamage, double attackSpeed, TagKey mineableBlocks, RegistryEntryList repairItems) { return new ItemComponent[] { StackableItemComponent.of(1), DamageableItemComponent.of(material.durability()), ToolItemComponent.of(blocks, material, mineableBlocks), WeaponItemComponent.of( 2, - canDisableBlocking, - realAttackDamage, + disableBlockingForSeconds, + baseAttackDamage + material.attackDamageBonus(), attackSpeed ), EnchantableItemComponent.of(material), @@ -101,6 +94,11 @@ private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMa }; } + @Override + public ItemComponentType type() { + return ItemComponentTypes.DAMAGEABLE; + } + @Override public Codec codec() { return CODEC; @@ -110,6 +108,7 @@ public Codec codec() { public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.MAX_DAMAGE, this.durability); builder.add(DataComponentTypes.DAMAGE, 0); + this.breakSound.ifPresent(breakSound -> builder.add(DataComponentTypes.BREAK_SOUND, breakSound)); } public int maximumDamage(ItemStack stack) { 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 afd9c881..31846fb4 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 @@ -42,8 +42,8 @@ import net.minecraft.world.RaycastContext; import net.minecraft.world.World; -import java.util.List; import java.util.Set; +import java.util.function.Consumer; public record EntityItemComponent(RegistryEntry> entity, boolean allowItemData, Set passes) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( @@ -113,18 +113,18 @@ public ItemResult useOnBlock(ItemUsageContext context, ItemStackExchanger stackE } @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { + public void appendTooltip(ItemStack stack, Item.TooltipContext context, Consumer builder, TooltipType type) { if (this.entity.value() != EntityType.PAINTING) { return; } RegistryEntry paintingVariant = stack.get(DataComponentTypes.PAINTING_VARIANT); if (paintingVariant != null) { - paintingVariant.value().title().ifPresent(tooltip::add); - paintingVariant.value().author().ifPresent(tooltip::add); - tooltip.add(Text.translatable("painting.dimensions", paintingVariant.value().width(), paintingVariant.value().height())); + paintingVariant.value().title().ifPresent(builder); + paintingVariant.value().author().ifPresent(builder); + builder.accept(Text.translatable("painting.dimensions", paintingVariant.value().width(), paintingVariant.value().height())); } else if (type.isCreative()) { - tooltip.add(RANDOM_TEXT); + builder.accept(RANDOM_TEXT); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/EquipmentItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/EquipmentItemComponent.java index f070f2e8..ed61870c 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/EquipmentItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/EquipmentItemComponent.java @@ -8,6 +8,7 @@ import net.errorcraft.itematic.item.dispense.behavior.DispenseBehavior; import net.errorcraft.itematic.item.dispense.behavior.DispenseBehaviors; import net.errorcraft.itematic.item.event.ItemEvents; +import net.errorcraft.itematic.sound.SoundEventKeys; import net.errorcraft.itematic.util.context.ItematicContextParameters; import net.errorcraft.itematic.world.action.context.ActionContext; import net.errorcraft.itematic.world.action.context.ItemStackExchanger; @@ -16,16 +17,18 @@ import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.EquippableComponent; import net.minecraft.component.type.FireworkExplosionComponent; +import net.minecraft.entity.EntityType; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.AnimalArmorItem; import net.minecraft.item.ItemStack; import net.minecraft.item.equipment.ArmorMaterial; import net.minecraft.item.equipment.EquipmentType; import net.minecraft.loot.context.LootContextParameters; import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.tag.EntityTypeTags; import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundEvent; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.math.Direction; @@ -38,16 +41,17 @@ public static EquipmentItemComponent of(EquippableComponent equippable) { return new EquipmentItemComponent(equippable); } - private static EquipmentItemComponent of(ArmorMaterial material, EquipmentType type, AnimalArmorItem.Type animalType) { - return new EquipmentItemComponent(EquippableComponent.builder(type.getEquipmentSlot()) - .swappable(true) - .equipSound(material.equipSound()) + public static EquipmentItemComponent ofHorseArmor(ArmorMaterial material, RegistryEntryLookup soundEvents, RegistryEntryLookup> entityTypes) { + return of(EquippableComponent.builder(EquipmentSlot.BODY) + .equipSound(soundEvents.getOrThrow(SoundEventKeys.HORSE_ARMOR)) .model(material.assetId()) - .allowedEntities(animalType.itematic$allowedEntities()) - .build()); + .allowedEntities(entityTypes.getOrThrow(EntityTypeTags.CAN_WEAR_HORSE_ARMOR)) + .damageOnHurt(false) + .build() + ); } - public static ItemComponent[] from(ArmorMaterial material, EquipmentType type) { + public static ItemComponent[] forArmor(ArmorMaterial material, EquipmentType type) { return new ItemComponent[] { StackableItemComponent.of(1), of(EquippableComponent.builder(type.getEquipmentSlot()) @@ -59,22 +63,7 @@ public static ItemComponent[] from(ArmorMaterial material, EquipmentType type }; } - public static ItemComponent[] from(ArmorMaterial material, EquipmentType type, AnimalArmorItem.Type animalType) { - return new ItemComponent[] { - StackableItemComponent.of(1), - of(material, type, animalType) - }; - } - - public static ItemComponent[] fromDamageable(ArmorMaterial material, EquipmentType type, AnimalArmorItem.Type animalType) { - return new ItemComponent[] { - StackableItemComponent.of(1), - DamageableItemComponent.of(type.getMaxDamage(material.durability()), animalType.itematic$breakSound()), - of(material, type, animalType) - }; - } - - public static ItemComponent[] skull(RegistryEntry attachedBlock, RegistryEntry otherBlock, RegistryEntryLookup dispenseBehaviors) { + public static ItemComponent[] forSkull(RegistryEntry attachedBlock, RegistryEntry otherBlock, RegistryEntryLookup dispenseBehaviors) { return new ItemComponent[] { BlockItemComponent.attachedToSide(attachedBlock, otherBlock, Direction.DOWN), new EquipmentItemComponent(EquippableComponent.builder(EquipmentSlot.HEAD) diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/FireworkExplosionHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/FireworkExplosionHolderItemComponent.java index a24cd312..b601b22a 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/FireworkExplosionHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/FireworkExplosionHolderItemComponent.java @@ -7,12 +7,6 @@ import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.FireworkExplosionComponent; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; - -import java.util.List; public record FireworkExplosionHolderItemComponent() implements ItemComponent { public static final FireworkExplosionHolderItemComponent INSTANCE = new FireworkExplosionHolderItemComponent(); @@ -32,12 +26,4 @@ public Codec codec() { public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.FIREWORK_EXPLOSION, FireworkExplosionComponent.DEFAULT); } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - FireworkExplosionComponent explosion = stack.get(DataComponentTypes.FIREWORK_EXPLOSION); - if (explosion != null) { - explosion.appendTooltip(context, tooltip::add, type); - } - } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/FireworkItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/FireworkItemComponent.java index cb1919fe..c062f77d 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/FireworkItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/FireworkItemComponent.java @@ -12,12 +12,9 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.FireworkRocketEntity; import net.minecraft.item.FireworkRocketItem; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.stat.Stats; -import net.minecraft.text.Text; import net.minecraft.util.Hand; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; @@ -76,14 +73,6 @@ public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.FIREWORKS, DEFAULT_DATA_COMPONENT); } - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - FireworksComponent fireworks = stack.get(DataComponentTypes.FIREWORKS); - if (fireworks != null) { - fireworks.appendTooltip(context, tooltip::add, type); - } - } - private static FireworkRocketEntity createFireworkEntity(World world, ItemStack stack, ItemUsageContext context) { Direction direction = context.getSide(); Vec3d position = context.getHitPos().add( diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java index b31cd038..393ff626 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java @@ -12,12 +12,8 @@ import net.minecraft.item.FilledMapItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.world.World; -import java.util.List; - public record MapHolderItemComponent() implements ItemComponent { public static final MapHolderItemComponent INSTANCE = new MapHolderItemComponent(); public static final Codec CODEC = Codec.unit(INSTANCE); @@ -48,9 +44,4 @@ public void inventoryTick(ItemStack stack, World world, Entity holder, int slot, public void onCraft(ItemStack stack, World world) { DUMMY.onCraft(stack, world); } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - DUMMY.appendTooltip(stack, context, tooltip, type); - } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/OminousEffectProviderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/OminousEffectProviderItemComponent.java index 5f5b9a3b..2ee15b4a 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/OminousEffectProviderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/OminousEffectProviderItemComponent.java @@ -8,14 +8,9 @@ import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.OminousBottleAmplifierComponent; import net.minecraft.entity.LivingEntity; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.world.World; -import java.util.List; - public class OminousEffectProviderItemComponent implements ItemComponent { public static final OminousEffectProviderItemComponent INSTANCE = new OminousEffectProviderItemComponent(); public static final Codec CODEC = Codec.unit(INSTANCE); @@ -39,12 +34,4 @@ public void finishUsing(World world, LivingEntity user, ItemStack stack, int use ominousAmplifier.onConsume(world, user, stack, null); } } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - OminousBottleAmplifierComponent ominousAmplifier = stack.get(DataComponentTypes.OMINOUS_BOTTLE_AMPLIFIER); - if (ominousAmplifier != null) { - ominousAmplifier.appendTooltip(context, tooltip::add, type); - } - } } 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 5c084953..2cf14d5c 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 @@ -10,43 +10,36 @@ import net.errorcraft.itematic.mixin.item.GoatHornItemAccessor; import net.errorcraft.itematic.world.action.context.ItemStackExchanger; import net.minecraft.SharedConstants; +import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.InstrumentComponent; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Instrument; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.consume.UseAction; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.registry.tag.TagKey; +import net.minecraft.registry.entry.RegistryFixedCodec; import net.minecraft.stat.Stats; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; -import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; -import java.util.List; import java.util.Optional; -import java.util.stream.Stream; -public record PlayableItemComponent(TagKey instruments) implements ItemComponent { +public record PlayableItemComponent(RegistryEntry defaultInstrument) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - TagKey.unprefixedCodec(RegistryKeys.INSTRUMENT).fieldOf("instruments").forGetter(PlayableItemComponent::instruments) + RegistryFixedCodec.of(RegistryKeys.INSTRUMENT).fieldOf("default_instrument").forGetter(PlayableItemComponent::defaultInstrument) ).apply(instance, PlayableItemComponent::new)); - public static ItemComponent[] of(TagKey instruments) { + public static ItemComponent[] of(RegistryEntry defaultInstrument) { return new ItemComponent[] { UseableItemComponent.builder() .useFor(PlayableIntegerProvider.INSTANCE) .animation(UseAction.TOOT_HORN) .build(), - new PlayableItemComponent(instruments) + new PlayableItemComponent(defaultInstrument) }; } @@ -73,27 +66,16 @@ public ItemResult use(World world, PlayerEntity user, Hand hand, ItemStack stack } @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - RegistryWrapper.WrapperLookup lookup = context.getRegistryLookup(); - if (lookup == null) { - return; - } - - this.instrument(stack, lookup) - .flatMap(RegistryEntry::getKey) - .map(RegistryKey::getValue) - .ifPresent(id -> tooltip.add(Text.translatable(Util.createTranslationKey("instrument", id)).formatted(Formatting.GRAY))); + public void addComponents(ComponentMap.Builder builder) { + builder.add(DataComponentTypes.INSTRUMENT, new InstrumentComponent(this.defaultInstrument)); } - public Optional> instrument(ItemStack stack, RegistryWrapper.WrapperLookup lookup) { - RegistryEntry instrument = stack.get(DataComponentTypes.INSTRUMENT); - if (instrument != null) { - return Optional.of(instrument); + public Optional> instrument(ItemStack stack, RegistryWrapper.WrapperLookup lookup) { + InstrumentComponent instrument = stack.get(DataComponentTypes.INSTRUMENT); + if (instrument == null) { + return Optional.empty(); } - return lookup.getOrThrow(RegistryKeys.INSTRUMENT) - .getOptional(this.instruments) - .map(RegistryEntryList::stream) - .flatMap(Stream::findFirst); + return instrument.getInstrument(lookup); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java index bcd34972..724f5ef4 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java @@ -33,6 +33,6 @@ public Codec codec() { @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.JUKEBOX_PLAYABLE, new JukeboxPlayableComponent(new RegistryPair<>(this.song), true)); + builder.add(DataComponentTypes.JUKEBOX_PLAYABLE, new JukeboxPlayableComponent(new RegistryPair<>(this.song))); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java index 1656e09e..f04a51f1 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java @@ -10,20 +10,19 @@ import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.PotionContentsComponent; import net.minecraft.entity.LivingEntity; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.util.dynamic.Codecs; import net.minecraft.world.World; -import java.util.List; - public record PotionHolderItemComponent(float durationMultiplier) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codecs.POSITIVE_FLOAT.fieldOf("duration_multiplier").forGetter(PotionHolderItemComponent::durationMultiplier) ).apply(instance, PotionHolderItemComponent::new)); + public static PotionHolderItemComponent of(float durationMultiplier) { + return new PotionHolderItemComponent(durationMultiplier); + } + @Override public ItemComponentType type() { return ItemComponentTypes.POTION_HOLDER; @@ -48,22 +47,10 @@ public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.POTION_DURATION_SCALE, this.durationMultiplier); } - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - PotionContentsComponent potionContents = stack.get(DataComponentTypes.POTION_CONTENTS); - if (potionContents != null) { - potionContents.buildTooltip(tooltip::add, this.durationMultiplier, context.getUpdateTickRate()); - } - } - public String translationKey(ItemStack stack, String baseTranslationKey) { return stack.getOrDefault(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT) .potion() .map(potion -> baseTranslationKey + ".effect." + potion.value().getBaseName()) .orElseGet(() -> baseTranslationKey + ".effect.empty"); } - - public static PotionHolderItemComponent of(float durationMultiplier) { - return new PotionHolderItemComponent(durationMultiplier); - } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateItemComponent.java deleted file mode 100644 index 57b0c536..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateItemComponent.java +++ /dev/null @@ -1,58 +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.errorcraft.itematic.item.smithing.template.SmithingTemplate; -import net.errorcraft.itematic.mixin.item.SmithingTemplateItemAccessor; -import net.errorcraft.itematic.registry.ItematicRegistryKeys; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryFixedCodec; -import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - -import java.util.List; - -public record SmithingTemplateItemComponent(RegistryEntry template) implements ItemComponent { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryFixedCodec.of(ItematicRegistryKeys.SMITHING_TEMPLATE).fieldOf("template").forGetter(SmithingTemplateItemComponent::template) - ).apply(instance, SmithingTemplateItemComponent::new)); - private static final Formatting DESCRIPTION_FORMATTING = SmithingTemplateItemAccessor.getDescriptionFormatting(); - private static final Text SMITHING_TEMPLATE_TEXT = SmithingTemplateItemAccessor.getSmithingTemplateText(); - private static final Text APPLIES_TO_TEXT = SmithingTemplateItemAccessor.getAppliesToText(); - private static final Text INGREDIENTS_TEXT = SmithingTemplateItemAccessor.getIngredientsText(); - - public static ItemComponent[] of(RegistryEntry template) { - return new ItemComponent[] { - StackableItemComponent.of(64), - new SmithingTemplateItemComponent(template) - }; - } - - @Override - public ItemComponentType type() { - return ItemComponentTypes.SMITHING_TEMPLATE; - } - - @Override - public Codec codec() { - return CODEC; - } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - SmithingTemplate template = this.template.value(); - tooltip.add(SMITHING_TEMPLATE_TEXT); - tooltip.add(ScreenTexts.EMPTY); - tooltip.add(APPLIES_TO_TEXT); - tooltip.add(ScreenTexts.space().append(template.appliesToText().formatted(DESCRIPTION_FORMATTING))); - tooltip.add(INGREDIENTS_TEXT); - tooltip.add(ScreenTexts.space().append(template.ingredientsText().formatted(DESCRIPTION_FORMATTING))); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateProviderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateProviderItemComponent.java new file mode 100644 index 00000000..2b0ca189 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/component/components/SmithingTemplateProviderItemComponent.java @@ -0,0 +1,28 @@ +package net.errorcraft.itematic.item.component.components; + +import com.mojang.serialization.Codec; +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.smithing.template.SmithingTemplate; + +public record SmithingTemplateProviderItemComponent(SmithingTemplate template) implements ItemComponent { + public static final Codec CODEC = SmithingTemplate.CODEC.xmap( + SmithingTemplateProviderItemComponent::new, + SmithingTemplateProviderItemComponent::template + ); + + public static SmithingTemplateProviderItemComponent of(SmithingTemplate template) { + return new SmithingTemplateProviderItemComponent(template); + } + + @Override + public ItemComponentType type() { + return ItemComponentTypes.SMITHING_TEMPLATE_PROVIDER; + } + + @Override + public Codec codec() { + return CODEC; + } +} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/TextHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/TextHolderItemComponent.java index 52a84c7f..88eb4b21 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/TextHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/TextHolderItemComponent.java @@ -1,24 +1,23 @@ package net.errorcraft.itematic.item.component.components; import com.mojang.serialization.Codec; +import net.errorcraft.itematic.item.ItemResult; import net.errorcraft.itematic.item.component.ItemComponent; import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.WrittenBookContentComponent; -import net.minecraft.item.Item; +import net.errorcraft.itematic.world.action.context.ItemStackExchanger; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.StringHelper; +import net.minecraft.stat.Stats; +import net.minecraft.util.Hand; +import net.minecraft.world.World; -import java.util.List; - -public record TextHolderItemComponent() implements ItemComponent { +public class TextHolderItemComponent implements ItemComponent { public static final TextHolderItemComponent INSTANCE = new TextHolderItemComponent(); public static final Codec CODEC = Codec.unit(INSTANCE); + private TextHolderItemComponent() {} + @Override public ItemComponentType type() { return ItemComponentTypes.TEXT_HOLDER; @@ -30,14 +29,9 @@ public Codec codec() { } @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - WrittenBookContentComponent writtenBookContent = stack.get(DataComponentTypes.WRITTEN_BOOK_CONTENT); - if (writtenBookContent == null) { - return; - } - if (!StringHelper.isBlank(writtenBookContent.author())) { - tooltip.add(Text.translatable("book.byAuthor", writtenBookContent.author()).formatted(Formatting.GRAY)); - } - tooltip.add(Text.translatable("book.generation." + writtenBookContent.generation()).formatted(Formatting.GRAY)); + public ItemResult use(World world, PlayerEntity user, Hand hand, ItemStack stack, ItemStackExchanger stackExchanger) { + user.useBook(stack, hand); + user.incrementStat(Stats.USED.itematic$getOrCreateStat(stack.getRegistryEntry())); + return ItemResult.SUCCEED; } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/TrimMaterialProviderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/TrimMaterialProviderItemComponent.java new file mode 100644 index 00000000..686520bf --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/component/components/TrimMaterialProviderItemComponent.java @@ -0,0 +1,37 @@ +package net.errorcraft.itematic.item.component.components; + +import com.mojang.serialization.Codec; +import net.errorcraft.itematic.item.component.ItemComponent; +import net.errorcraft.itematic.item.component.ItemComponentType; +import net.errorcraft.itematic.item.component.ItemComponentTypes; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ProvidesTrimMaterialComponent; +import net.minecraft.item.equipment.trim.ArmorTrimMaterial; +import net.minecraft.registry.entry.RegistryEntry; + +public record TrimMaterialProviderItemComponent(RegistryEntry trimMaterial) implements ItemComponent { + public static final Codec CODEC = ArmorTrimMaterial.ENTRY_CODEC.xmap( + TrimMaterialProviderItemComponent::new, + TrimMaterialProviderItemComponent::trimMaterial + ); + + public static TrimMaterialProviderItemComponent of(RegistryEntry trimMaterial) { + return new TrimMaterialProviderItemComponent(trimMaterial); + } + + @Override + public ItemComponentType type() { + return ItemComponentTypes.TRIM_MATERIAL_PROVIDER; + } + + @Override + public Codec codec() { + return CODEC; + } + + @Override + public void addComponents(ComponentMap.Builder builder) { + builder.add(DataComponentTypes.PROVIDES_TRIM_MATERIAL, new ProvidesTrimMaterialComponent(this.trimMaterial)); + } +} 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 6ac74f19..b8747b8a 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 @@ -14,37 +14,32 @@ import net.errorcraft.itematic.world.action.context.ItemStackExchanger; import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.AttributeModifiersComponent; import net.minecraft.component.type.WeaponComponent; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.MaceItem; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.loot.context.LootContextParameters; import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.dynamic.Codecs; import java.util.List; -public record WeaponItemComponent(int itemDamagePerAttack, boolean canDisableBlocking, boolean maySmash, WeaponAttackDamageDataComponent attackDamage, double attackSpeed) implements ItemComponent { +public record WeaponItemComponent(int itemDamagePerAttack, float disableBlockingForSeconds, boolean maySmash, WeaponAttackDamageDataComponent attackDamage, double attackSpeed) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codecs.NON_NEGATIVE_INT.optionalFieldOf("item_damage_per_attack", 1).forGetter(WeaponItemComponent::itemDamagePerAttack), - Codec.BOOL.optionalFieldOf("can_disable_blocking", false).forGetter(WeaponItemComponent::canDisableBlocking), + Codecs.NON_NEGATIVE_FLOAT.optionalFieldOf("disable_blocking_for_seconds", 0.0f).forGetter(WeaponItemComponent::disableBlockingForSeconds), Codec.BOOL.optionalFieldOf("may_smash", false).forGetter(WeaponItemComponent::maySmash), WeaponAttackDamageDataComponent.CODEC.fieldOf("attack_damage").forGetter(WeaponItemComponent::attackDamage), ItematicCodecs.NON_NEGATIVE_DOUBLE.fieldOf("attack_speed").forGetter(WeaponItemComponent::attackSpeed) ).apply(instance, WeaponItemComponent::new)); private static final MaceItem DUMMY = new MaceItem(new Item.Settings()); - public static WeaponItemComponent of(int damagePerHit, boolean canDisableBlocking, double attackDamage, double attackSpeed) { + public static WeaponItemComponent of(int damagePerHit, float disableBlockingForSeconds, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, - canDisableBlocking, + disableBlockingForSeconds, false, new WeaponAttackDamageDataComponent(List.of(), attackDamage), attackSpeed @@ -54,7 +49,7 @@ public static WeaponItemComponent of(int damagePerHit, boolean canDisableBlockin public static WeaponItemComponent ofSmashing(int damagePerHit, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, - false, + 0.0f, true, new WeaponAttackDamageDataComponent(List.of(), attackDamage), attackSpeed @@ -99,29 +94,8 @@ public void postHit(ItemStack stack, LivingEntity target, LivingEntity attacker, @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.WEAPON, new WeaponComponent(this.itemDamagePerAttack, this.canDisableBlocking)); + builder.add(DataComponentTypes.WEAPON, new WeaponComponent(this.itemDamagePerAttack, this.disableBlockingForSeconds)); builder.add(ItematicDataComponentTypes.WEAPON_ATTACK_DAMAGE, this.attackDamage); builder.add(ItematicDataComponentTypes.ATTACK_SPEED_MULTIPLIER, this.attackSpeed); } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - WeaponAttackDamageDataComponent weaponAttackDamage = stack.get(ItematicDataComponentTypes.WEAPON_ATTACK_DAMAGE); - if (weaponAttackDamage != null) { - tooltip.add( - Text.translatable( - "attribute.modifier.equals.0", - AttributeModifiersComponent.DECIMAL_FORMAT.format(weaponAttackDamage.defaultDamage()), - Text.translatable(EntityAttributes.ATTACK_DAMAGE.value().getTranslationKey()) - ).formatted(Formatting.DARK_GREEN) - ); - } - tooltip.add( - Text.translatable( - "attribute.modifier.equals.0", - AttributeModifiersComponent.DECIMAL_FORMAT.format(this.attackSpeed), - Text.translatable(EntityAttributes.ATTACK_SPEED.value().getTranslationKey()) - ).formatted(Formatting.DARK_GREEN) - ); - } } diff --git a/src/main/java/net/errorcraft/itematic/item/composting/CompostChances.java b/src/main/java/net/errorcraft/itematic/item/composting/CompostChances.java new file mode 100644 index 00000000..68c6b9af --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/composting/CompostChances.java @@ -0,0 +1,11 @@ +package net.errorcraft.itematic.item.composting; + +public class CompostChances { + public static final float SMALL = 0.3f; + public static final float FIFTY_FIFTY = 0.5f; + public static final float BIG = 0.65f; + public static final float ALMOST_GUARANTEED = 0.85f; + public static final float GUARANTEED = 1.0f; + + private CompostChances() {} +} diff --git a/src/main/java/net/errorcraft/itematic/item/group/entry/entries/InstrumentItemGroupEntry.java b/src/main/java/net/errorcraft/itematic/item/group/entry/entries/InstrumentItemGroupEntry.java index 8444456c..00f05f18 100644 --- a/src/main/java/net/errorcraft/itematic/item/group/entry/entries/InstrumentItemGroupEntry.java +++ b/src/main/java/net/errorcraft/itematic/item/group/entry/entries/InstrumentItemGroupEntry.java @@ -5,6 +5,7 @@ import net.errorcraft.itematic.item.group.entry.ItemGroupEntryType; import net.errorcraft.itematic.item.group.entry.PossiblyHiddenItemGroupEntry; import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.InstrumentComponent; import net.minecraft.item.Instrument; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; @@ -52,7 +53,7 @@ protected Collection createStacks(ItemGroup.DisplayContext context) { .stream() .map(instrument -> { ItemStack stack = new ItemStack(this.item); - stack.set(DataComponentTypes.INSTRUMENT, instrument); + stack.set(DataComponentTypes.INSTRUMENT, new InstrumentComponent(instrument)); return stack; }) .toList(); diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplate.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplate.java index bc87e381..7f2dc6b6 100644 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplate.java +++ b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplate.java @@ -2,19 +2,14 @@ import com.mojang.serialization.Codec; import net.errorcraft.itematic.registry.ItematicRegistries; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import java.util.List; public interface SmithingTemplate { - Codec CODEC = ItematicRegistries.SMITHING_TEMPLATE_TYPE.getCodec().dispatch(SmithingTemplate::type, SmithingTemplateType::codec); + Codec CODEC = ItematicRegistries.SMITHING_TEMPLATE.getCodec(); - SmithingTemplateType type(); - MutableText titleText(); - MutableText appliesToText(); - MutableText ingredientsText(); List emptyBaseSlotTextures(); List emptyAdditionsSlotTextures(); Text baseSlotDescription(); diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateType.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateType.java deleted file mode 100644 index 98f00973..00000000 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateType.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.errorcraft.itematic.item.smithing.template; - -import com.mojang.serialization.MapCodec; - -public record SmithingTemplateType(MapCodec codec) { -} diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypeKeys.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypeKeys.java deleted file mode 100644 index a5c57717..00000000 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypeKeys.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.errorcraft.itematic.item.smithing.template; - -import net.errorcraft.itematic.registry.ItematicRegistryKeys; -import net.minecraft.registry.RegistryKey; -import net.minecraft.util.Identifier; - -public class SmithingTemplateTypeKeys { - public static final RegistryKey> TRIM_PATTERN = of("trim_pattern"); - public static final RegistryKey> ITEM_UPGRADE = of("item_upgrade"); - - private SmithingTemplateTypeKeys() {} - - private static RegistryKey> of(String id) { - return RegistryKey.of(ItematicRegistryKeys.SMITHING_TEMPLATE_TYPE, Identifier.ofVanilla(id)); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypes.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypes.java deleted file mode 100644 index ce857861..00000000 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplateTypes.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.errorcraft.itematic.item.smithing.template; - -import net.errorcraft.itematic.item.smithing.template.templates.ItemUpgradeSmithingTemplate; -import net.errorcraft.itematic.item.smithing.template.templates.TrimPatternSmithingTemplate; -import net.errorcraft.itematic.registry.ItematicRegistries; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; - -public class SmithingTemplateTypes { - public static final SmithingTemplateType TRIM_PATTERN = register(SmithingTemplateTypeKeys.TRIM_PATTERN, new SmithingTemplateType<>(TrimPatternSmithingTemplate.CODEC)); - public static final SmithingTemplateType ITEM_UPGRADE = register(SmithingTemplateTypeKeys.ITEM_UPGRADE, new SmithingTemplateType<>(ItemUpgradeSmithingTemplate.CODEC)); - - private SmithingTemplateTypes() {} - - public static void init() {} - - private static SmithingTemplateType register(RegistryKey> id, SmithingTemplateType type) { - return Registry.register(ItematicRegistries.SMITHING_TEMPLATE_TYPE, id, type); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplates.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplates.java index f73dac69..c9e14fdf 100644 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplates.java +++ b/src/main/java/net/errorcraft/itematic/item/smithing/template/SmithingTemplates.java @@ -1,67 +1,19 @@ package net.errorcraft.itematic.item.smithing.template; -import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.item.smithing.template.templates.ItemUpgradeSmithingTemplate; import net.errorcraft.itematic.item.smithing.template.templates.TrimPatternSmithingTemplate; -import net.errorcraft.itematic.registry.ItematicRegistryKeys; -import net.minecraft.item.Item; -import net.minecraft.item.equipment.trim.ArmorTrimPattern; -import net.minecraft.item.equipment.trim.ArmorTrimPatterns; -import net.minecraft.registry.Registerable; -import net.minecraft.registry.RegistryEntryLookup; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.util.Identifier; +import net.errorcraft.itematic.registry.ItematicRegistries; +import net.minecraft.registry.Registry; public class SmithingTemplates { - public static final RegistryKey NETHERITE_UPGRADE = of("netherite_upgrade"); - public static final RegistryKey BOLT_PATTERN = of("bolt_pattern"); - public static final RegistryKey COAST_PATTERN = of("coast_pattern"); - public static final RegistryKey DUNE_PATTERN = of("dune_pattern"); - public static final RegistryKey EYE_PATTERN = of("eye_pattern"); - public static final RegistryKey FLOW_PATTERN = of("flow_pattern"); - public static final RegistryKey HOST_PATTERN = of("host_pattern"); - public static final RegistryKey RAISER_PATTERN = of("raiser_pattern"); - public static final RegistryKey RIB_PATTERN = of("rib_pattern"); - public static final RegistryKey SENTRY_PATTERN = of("sentry_pattern"); - public static final RegistryKey SHAPER_PATTERN = of("shaper_pattern"); - public static final RegistryKey SILENCE_PATTERN = of("silence_pattern"); - public static final RegistryKey SNOUT_PATTERN = of("snout_pattern"); - public static final RegistryKey SPIRE_PATTERN = of("spire_pattern"); - public static final RegistryKey TIDE_PATTERN = of("tide_pattern"); - public static final RegistryKey VEX_PATTERN = of("vex_pattern"); - public static final RegistryKey WARD_PATTERN = of("ward_pattern"); - public static final RegistryKey WAYFINDER_PATTERN = of("wayfinder_pattern"); - public static final RegistryKey WILD_PATTERN = of("wild_pattern"); + public static final SmithingTemplate TRIM_PATTERN = register("trim_pattern", new TrimPatternSmithingTemplate()); + public static final SmithingTemplate ITEM_UPGRADE = register("item_upgrade", new ItemUpgradeSmithingTemplate()); private SmithingTemplates() {} - public static void bootstrap(Registerable registerable) { - RegistryEntryLookup items = registerable.getRegistryLookup(RegistryKeys.ITEM); - RegistryEntryLookup trimPatterns = registerable.getRegistryLookup(RegistryKeys.TRIM_PATTERN); + public static void init() {} - registerable.register(NETHERITE_UPGRADE, new ItemUpgradeSmithingTemplate(items.getOrThrow(ItemKeys.NETHERITE_INGOT), Identifier.ofVanilla("netherite_upgrade"))); - registerable.register(BOLT_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.BOLT))); - registerable.register(COAST_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.COAST))); - registerable.register(DUNE_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.DUNE))); - registerable.register(EYE_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.EYE))); - registerable.register(FLOW_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.FLOW))); - registerable.register(HOST_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.HOST))); - registerable.register(RAISER_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.RAISER))); - registerable.register(RIB_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.RIB))); - registerable.register(SENTRY_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.SENTRY))); - registerable.register(SHAPER_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.SHAPER))); - registerable.register(SILENCE_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.SILENCE))); - registerable.register(SNOUT_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.SNOUT))); - registerable.register(SPIRE_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.SPIRE))); - registerable.register(TIDE_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.TIDE))); - registerable.register(VEX_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.VEX))); - registerable.register(WARD_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.WARD))); - registerable.register(WAYFINDER_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.WAYFINDER))); - registerable.register(WILD_PATTERN, new TrimPatternSmithingTemplate(trimPatterns.getOrThrow(ArmorTrimPatterns.WILD))); - } - - private static RegistryKey of(String id) { - return RegistryKey.of(ItematicRegistryKeys.SMITHING_TEMPLATE, Identifier.ofVanilla(id)); + private static SmithingTemplate register(String id, SmithingTemplate type) { + return Registry.register(ItematicRegistries.SMITHING_TEMPLATE, id, type); } } diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/ItemUpgradeSmithingTemplate.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/ItemUpgradeSmithingTemplate.java index 4201a67d..11c26a89 100644 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/ItemUpgradeSmithingTemplate.java +++ b/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/ItemUpgradeSmithingTemplate.java @@ -1,51 +1,17 @@ package net.errorcraft.itematic.item.smithing.template.templates; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateType; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateTypes; import net.errorcraft.itematic.mixin.item.SmithingTemplateItemAccessor; -import net.minecraft.item.Item; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryFixedCodec; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import net.minecraft.util.Util; import java.util.List; -public record ItemUpgradeSmithingTemplate(RegistryEntry item, Identifier translationKeyId) implements SmithingTemplate { - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - RegistryFixedCodec.of(RegistryKeys.ITEM).fieldOf("item").forGetter(ItemUpgradeSmithingTemplate::item), - Identifier.CODEC.fieldOf("translation_key_id").forGetter(ItemUpgradeSmithingTemplate::translationKeyId) - ).apply(instance, ItemUpgradeSmithingTemplate::new)); - private static final List EMPTY_BASE_SLOT_TEXTURES = SmithingTemplateItemAccessor.getItemUpgradeEmptyBaseSlotTextures(); - private static final List EMPTY_ADDITIONS_SLOT_TEXTURES = SmithingTemplateItemAccessor.getItemUpgradeEmptyAdditionsSlotTextures(); - private static final Text BASE_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.getItemUpgradeBaseSlotDescriptionText(); - private static final Text ADDITIONS_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.getItemUpgradeAdditionsSlotDescriptionText(); - - @Override - public SmithingTemplateType type() { - return SmithingTemplateTypes.ITEM_UPGRADE; - } - - @Override - public MutableText titleText() { - return Text.translatable(Util.createTranslationKey("upgrade", this.translationKeyId)); - } - - @Override - public MutableText appliesToText() { - return Text.translatable(this.createTranslationKey("applies_to")); - } - - @Override - public MutableText ingredientsText() { - return Text.translatable(this.createTranslationKey("ingredients")); - } +public class ItemUpgradeSmithingTemplate implements SmithingTemplate { + private static final List EMPTY_BASE_SLOT_TEXTURES = SmithingTemplateItemAccessor.itemUpgradeEmptyBaseSlotTextures(); + private static final List EMPTY_ADDITIONS_SLOT_TEXTURES = SmithingTemplateItemAccessor.itemUpgradeEmptyAdditionsSlotTextures(); + private static final Text BASE_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.itemUpgradeBaseSlotDescription(); + private static final Text ADDITIONS_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.itemUpgradeAdditionsSlotDescription(); @Override public List emptyBaseSlotTextures() { @@ -66,8 +32,4 @@ public Text baseSlotDescription() { public Text additionsSlotDescription() { return ADDITIONS_SLOT_DESCRIPTION; } - - private String createTranslationKey(String type) { - return Util.createTranslationKey("item", this.translationKeyId.withPath(id -> "smithing_template." + id + "." + type)); - } } diff --git a/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/TrimPatternSmithingTemplate.java b/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/TrimPatternSmithingTemplate.java index 80e1fad0..1d391e4e 100644 --- a/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/TrimPatternSmithingTemplate.java +++ b/src/main/java/net/errorcraft/itematic/item/smithing/template/templates/TrimPatternSmithingTemplate.java @@ -1,54 +1,17 @@ package net.errorcraft.itematic.item.smithing.template.templates; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateType; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateTypes; import net.errorcraft.itematic.mixin.item.SmithingTemplateItemAccessor; -import net.minecraft.item.equipment.trim.ArmorTrimPattern; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryFixedCodec; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import net.minecraft.util.Util; import java.util.List; -public record TrimPatternSmithingTemplate(RegistryEntry trimPattern) implements SmithingTemplate { - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - RegistryFixedCodec.of(RegistryKeys.TRIM_PATTERN).fieldOf("trim_pattern").forGetter(TrimPatternSmithingTemplate::trimPattern) - ).apply(instance, TrimPatternSmithingTemplate::new)); - private static final MutableText APPLIES_TO_TEXT = (MutableText) SmithingTemplateItemAccessor.getTrimPatternAppliesToText(); - private static final MutableText INGREDIENTS_TEXT = (MutableText) SmithingTemplateItemAccessor.getTrimPatternIngredientsText(); - private static final List EMPTY_BASE_SLOT_TEXTURES = SmithingTemplateItemAccessor.getTrimPatternEmptyBaseSlotTextures(); - private static final List EMPTY_ADDITIONS_SLOT_TEXTURES = SmithingTemplateItemAccessor.getTrimPatternEmptyAdditionsSlotTextures(); - private static final Text BASE_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.getTrimPatternBaseSlotDescriptionText(); - private static final Text ADDITIONS_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.getTrimPatternAdditionsSlotDescriptionText(); - - @Override - public SmithingTemplateType type() { - return SmithingTemplateTypes.TRIM_PATTERN; - } - - @Override - public MutableText titleText() { - Identifier id = this.trimPattern.getKey().map(RegistryKey::getValue).orElse(null); - return Text.translatable(Util.createTranslationKey("trim_pattern", id)); - } - - @Override - public MutableText appliesToText() { - return APPLIES_TO_TEXT; - } - - @Override - public MutableText ingredientsText() { - return INGREDIENTS_TEXT; - } +public class TrimPatternSmithingTemplate implements SmithingTemplate { + private static final List EMPTY_BASE_SLOT_TEXTURES = SmithingTemplateItemAccessor.trimPatternEmptyBaseSlotTextures(); + private static final List EMPTY_ADDITIONS_SLOT_TEXTURES = SmithingTemplateItemAccessor.trimPatternEmptyAdditionsSlotTextures(); + private static final Text BASE_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.trimPatternBaseSlotDescription(); + private static final Text ADDITIONS_SLOT_DESCRIPTION = SmithingTemplateItemAccessor.trimPatternAdditionsSlotDescription(); @Override public List emptyBaseSlotTextures() { diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/BeehiveBlockExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/BeehiveBlockExtender.java index a592d903..7f474865 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/BeehiveBlockExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/BeehiveBlockExtender.java @@ -6,6 +6,7 @@ import net.minecraft.block.BeehiveBlock; import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.BeesComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; @@ -93,6 +94,6 @@ private ItemStack newItemStackUseCreateStack(ItemConvertible item, World world) @Override public void itematic$addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.BEES, List.of()); + builder.add(DataComponentTypes.BEES, new BeesComponent(List.of())); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/DecoratedPotBlockExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/DecoratedPotBlockExtender.java index 1d563066..5a657ee8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/DecoratedPotBlockExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/DecoratedPotBlockExtender.java @@ -1,6 +1,5 @@ package net.errorcraft.itematic.mixin.block; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; import net.errorcraft.itematic.access.block.AbstractBlockAccess; import net.errorcraft.itematic.block.entity.SherdsUtil; @@ -13,9 +12,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.world.WorldView; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -26,24 +22,6 @@ @Mixin(DecoratedPotBlock.class) public class DecoratedPotBlockExtender implements AbstractBlockAccess { - @ModifyExpressionValue( - method = "appendTooltip", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/block/entity/Sherds;equals(Ljava/lang/Object;)Z" - ) - ) - private boolean defaultSherdsAlwaysTrue(boolean original, @Local(argsOnly = true) Item.TooltipContext context, @Local(argsOnly = true) List tooltip, @Local Sherds sherds) { - if (!original) { - tooltip.add(ScreenTexts.EMPTY); - for (RegistryEntry entry : sherds.itematic$entriesForwards(context.getRegistryLookup())) { - tooltip.add(new ItemStack(entry).getName().copyContentOnly().formatted(Formatting.GRAY)); - } - } - - return true; - } - @Redirect( method = "method_49815", at = @At( diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java index 84875f91..c83761b0 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java @@ -1,10 +1,12 @@ package net.errorcraft.itematic.mixin.block.entity; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.mojang.serialization.Codec; import net.errorcraft.itematic.access.block.entity.SherdsAccess; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.block.entity.Sherds; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtOps; import net.minecraft.network.RegistryByteBuf; @@ -13,10 +15,11 @@ import net.minecraft.registry.*; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryFixedCodec; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.dynamic.Codecs; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; @@ -24,6 +27,7 @@ import java.util.List; import java.util.Optional; +import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; @@ -125,40 +129,17 @@ private static Function>>> xmapFromShe return Sherds::itematic$optionalEntries; } - /** - * @author ErrorCraft - * @reason Uses a registry entry for data-driven items. - */ - @Overwrite - public Optional back() { - return this.back.map(RegistryEntry::value); - } - - /** - * @author ErrorCraft - * @reason Uses a registry entry for data-driven items. - */ - @Overwrite - public Optional left() { - return this.left.map(RegistryEntry::value); - } - - /** - * @author ErrorCraft - * @reason Uses a registry entry for data-driven items. - */ - @Overwrite - public Optional right() { - return this.right.map(RegistryEntry::value); - } - - /** - * @author ErrorCraft - * @reason Uses a registry entry for data-driven items. - */ - @Overwrite - public Optional front() { - return this.front.map(RegistryEntry::value); + @ModifyReturnValue( + method = { + "back", + "left", + "right", + "front" + }, + at = @At("TAIL") + ) + private Optional mapToItem(Optional> original) { + return original.map(RegistryEntry::value); } @Redirect( @@ -183,6 +164,21 @@ private static Optional> optionalUseValueFromList(T valu return sherds.get(index); } + @Redirect( + method = "appendTooltip", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/entity/Sherds;appendSherdTooltip(Ljava/util/function/Consumer;Ljava/util/Optional;)V" + ) + ) + private void appendSherdTooltipUseRegistryEntry(Consumer textConsumer, Optional> sherd) { + sherd.map(ItemStack::new) + .map(ItemStack::getName) + .map(Text::copyContentOnly) + .map(text -> text.formatted(Formatting.GRAY)) + .ifPresent(textConsumer); + } + @Override @SuppressWarnings("EqualsBetweenInconvertibleTypes") public NbtCompound itematic$toNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { @@ -206,12 +202,4 @@ private static Optional> optionalUseValueFromList(T valu .map(optional -> optional.orElse(items.getOrThrow(ItemKeys.BRICK))) .toList(); } - - @Override - public List> itematic$entriesForwards(RegistryWrapper.WrapperLookup lookup) { - RegistryWrapper.Impl items = lookup.getOrThrow(RegistryKeys.ITEM); - return Stream.of(this.front, this.left, this.right, this.back) - .map(optional -> optional.orElse(items.getOrThrow(ItemKeys.BRICK))) - .toList(); - } } 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 d22c3c80..ebb467c4 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/LivingEntityExtender.java @@ -31,7 +31,6 @@ import net.minecraft.loot.context.LootContextParameters; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.tag.ItemTags; import net.minecraft.server.world.ServerWorld; import net.minecraft.stat.Stat; import net.minecraft.stat.StatType; @@ -40,7 +39,6 @@ import net.minecraft.world.World; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -433,15 +431,6 @@ private int getItemUseTimeUseField(int original) { return this.itemUsedTicks; } - /** - * @author ErrorCraft - * @reason Uses an item tag check instead of an instanceof check. - */ - @Overwrite - public boolean disablesShield() { - return this.getMainHandStack().isIn(ItemTags.AXES); - } - @Override public boolean itematic$isHolding(RegistryKey key) { return this.isHolding(stack -> stack.itematic$isOf(key)); diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/RemoveOffHandItemTaskExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/RemoveOffHandItemTaskExtender.java index de5a0783..56eeb9e0 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/RemoveOffHandItemTaskExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/ai/brain/task/RemoveOffHandItemTaskExtender.java @@ -1,23 +1,23 @@ package net.errorcraft.itematic.mixin.entity.ai.brain.task; -import net.errorcraft.itematic.item.ItemKeys; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.minecraft.entity.ai.brain.task.RemoveOffHandItemTask; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; +import net.minecraft.entity.mob.PiglinEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(RemoveOffHandItemTask.class) public class RemoveOffHandItemTaskExtender { - @Redirect( + @ModifyExpressionValue( method = "method_47299", at = @At( value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" + target = "Lnet/minecraft/item/ItemStack;contains(Lnet/minecraft/component/ComponentType;)Z" ) ) - private static boolean isOfForShieldUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SHIELD); + private static boolean containsBlocksAttacksDataComponentAlsoCheckItemBehaviorComponent(boolean original, @Local(argsOnly = true) PiglinEntity piglin) { + return original && piglin.getOffHandStack().itematic$hasBehavior(ItemComponentTypes.ATTACK_BLOCKING); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/GoatEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/GoatEntityExtender.java index 45423203..511b6872 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/GoatEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/GoatEntityExtender.java @@ -3,6 +3,7 @@ import net.errorcraft.itematic.item.ItemKeys; import net.errorcraft.itematic.mixin.entity.mob.MobEntityExtender; import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.InstrumentComponent; import net.minecraft.entity.EntityType; import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.passive.GoatEntity; @@ -35,7 +36,7 @@ protected GoatEntityExtender(EntityType entityType, Worl private Function, ? extends ItemStack> getStackForInstrumentUseCreateStack(Function, ? extends ItemStack> mapper) { return instrument -> { ItemStack stack = this.getWorld().itematic$createStack(ItemKeys.GOAT_HORN); - stack.set(DataComponentTypes.INSTRUMENT, instrument); + stack.set(DataComponentTypes.INSTRUMENT, new InstrumentComponent(instrument)); return stack; }; } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java index a2a05ccc..85b38607 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java @@ -20,8 +20,6 @@ import net.minecraft.item.RangedWeaponItem; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.stat.Stat; -import net.minecraft.stat.StatType; import net.minecraft.util.Hand; import net.minecraft.world.World; import org.objectweb.asm.Opcodes; @@ -61,28 +59,6 @@ private boolean isEquippedForTurtleHelmetUseRegistryKeyCheck(PlayerEntity instan return this.isEquipped(ItemKeys.TURTLE_HELMET); } - @Redirect( - method = "damageShield", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForShieldUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.SHIELD); - } - - @Redirect( - method = "damageShield", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/stat/StatType;getOrCreateStat(Ljava/lang/Object;)Lnet/minecraft/stat/Stat;" - ) - ) - private Stat getOrCreateStatForActiveItemUseRegistryEntry(StatType instance, T key) { - return instance.itematic$getOrCreateStat(this.activeItemStack.getRegistryEntry()); - } - @Redirect( method = "attack", at = @At( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/LingeringPotionEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/LingeringPotionEntityExtender.java new file mode 100644 index 00000000..23b4a2cf --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/LingeringPotionEntityExtender.java @@ -0,0 +1,22 @@ +package net.errorcraft.itematic.mixin.entity.projectile.thrown; + +import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.projectile.thrown.LingeringPotionEntity; +import net.minecraft.entity.projectile.thrown.ThrownEntity; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(LingeringPotionEntity.class) +public abstract class LingeringPotionEntityExtender extends ThrownItemEntityExtender { + protected LingeringPotionEntityExtender(EntityType entityType, World world) { + super(entityType, world); + } + + @Override + protected RegistryKey getDefaultItemKey() { + return ItemKeys.LINGERING_POTION; + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/PotionEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/PotionEntityExtender.java deleted file mode 100644 index 8aef6fb3..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/PotionEntityExtender.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.errorcraft.itematic.mixin.entity.projectile.thrown; - -import net.errorcraft.itematic.item.ItemKeys; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.projectile.thrown.PotionEntity; -import net.minecraft.entity.projectile.thrown.ThrownItemEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.registry.RegistryKey; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(PotionEntity.class) -public abstract class PotionEntityExtender extends ThrownItemEntityExtender { - public PotionEntityExtender(EntityType entityType, World world) { - super(entityType, world); - } - - @Redirect( - method = "isLingering", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForLingeringPotionUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.LINGERING_POTION); - } - - @Override - protected RegistryKey getDefaultItemKey() { - return ItemKeys.SPLASH_POTION; - } -} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/SplashPotionEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/SplashPotionEntityExtender.java new file mode 100644 index 00000000..f3eb18ad --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/SplashPotionEntityExtender.java @@ -0,0 +1,22 @@ +package net.errorcraft.itematic.mixin.entity.projectile.thrown; + +import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.projectile.thrown.SplashPotionEntity; +import net.minecraft.entity.projectile.thrown.ThrownEntity; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKey; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(SplashPotionEntity.class) +public abstract class SplashPotionEntityExtender extends ThrownItemEntityExtender { + protected SplashPotionEntityExtender(EntityType entityType, World world) { + super(entityType, world); + } + + @Override + protected RegistryKey getDefaultItemKey() { + return ItemKeys.SPLASH_POTION; + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/AnimalArmorItemExtender.java b/src/main/java/net/errorcraft/itematic/mixin/item/AnimalArmorItemExtender.java deleted file mode 100644 index 9fe6b8a8..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/item/AnimalArmorItemExtender.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.errorcraft.itematic.mixin.item; - -import net.errorcraft.itematic.access.item.AnimalArmorItemTypeAccess; -import net.minecraft.entity.EntityType; -import net.minecraft.item.AnimalArmorItem; -import net.minecraft.registry.Registries; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.sound.SoundEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -public class AnimalArmorItemExtender { - @Mixin(AnimalArmorItem.Type.class) - public static class TypeExtender implements AnimalArmorItemTypeAccess { - @Shadow - @Final - SoundEvent breakSound; - - @Shadow - @Final - RegistryEntryList> allowedEntities; - - @Override - public RegistryEntry itematic$breakSound() { - return Registries.SOUND_EVENT.getEntry(this.breakSound); - } - - @Override - public RegistryEntryList> itematic$allowedEntities() { - return this.allowedEntities; - } - } -} 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 8b52883c..bec388f6 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java @@ -14,7 +14,6 @@ import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.BlockItemComponent; -import net.errorcraft.itematic.item.component.components.DamageableItemComponent; import net.errorcraft.itematic.item.event.ItemEvent; import net.errorcraft.itematic.item.event.ItemEventMap; import net.errorcraft.itematic.item.event.ItemEvents; @@ -51,8 +50,6 @@ import net.minecraft.registry.entry.RegistryFixedCodec; import net.minecraft.screen.slot.Slot; import net.minecraft.server.world.ServerWorld; -import net.minecraft.sound.SoundEvent; -import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; import net.minecraft.util.*; import net.minecraft.util.math.BlockPos; @@ -65,8 +62,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.List; import java.util.Optional; +import java.util.function.Consumer; @Mixin(Item.class) public abstract class ItemExtender implements ItemAccess, FabricItem { @@ -436,19 +433,6 @@ public void onCraft(ItemStack stack, World world, CallbackInfo info) { } } - /** - * @author ErrorCraft - * @reason Uses the ItemComponent implementation for data-driven items. - */ - @Overwrite - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - this.display.tooltip() - .ifPresent(tooltip::addAll); - for (ItemComponent component : this.itemComponents) { - component.appendTooltip(stack, context, tooltip, type); - } - } - @Inject( method = "canMine", at = @At("HEAD"), @@ -506,18 +490,6 @@ public boolean canBeNested() { .orElse(true); } - /** - * @author ErrorCraft - * @reason Uses the ItemComponent implementation for data-driven items. - */ - @Overwrite - public SoundEvent getBreakSound() { - return this.itematic$getBehavior(ItemComponentTypes.DAMAGEABLE) - .flatMap(DamageableItemComponent::breakSound) - .map(RegistryEntry::value) - .orElse(SoundEvents.ENTITY_ITEM_BREAK); - } - @Inject( method = "getUseAction", at = @At("HEAD"), @@ -677,6 +649,14 @@ private void checkTextHolderItemComponent(ItemStack stack, CallbackInfoReturnabl return this.events.hasListener(event); } + @Override + public void itematic$addTooltip(ItemStack stack, Item.TooltipContext context, Consumer builder, TooltipType type) { + this.display.tooltip().ifPresent(tooltip -> tooltip.forEach(builder)); + for (ItemComponent component : this.itemComponents) { + component.appendTooltip(stack, context, builder, type); + } + } + @Override public boolean itematic$mayStartUsing(World world, PlayerEntity user, Hand hand, ItemStack stack) { return this.itematic$getBehavior(ItemComponentTypes.FOOD) 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 cb5c5f3a..e9f147a2 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemStackExtender.java @@ -2,7 +2,6 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.errorcraft.itematic.access.item.ItemStackAccess; @@ -22,6 +21,7 @@ import net.fabricmc.fabric.api.item.v1.EnchantingContext; import net.fabricmc.fabric.api.item.v1.FabricItemStack; import net.minecraft.component.*; +import net.minecraft.component.type.TooltipDisplayComponent; import net.minecraft.component.type.WeaponComponent; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.Entity; @@ -61,7 +61,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.HashSet; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -511,19 +510,21 @@ private void checkEmptyStack(CallbackInfoReturnable info) { } } - @WrapWithCondition( - method = "getTooltip", + @Inject( + method = "appendTooltip", at = @At( value = "INVOKE", - target = "Lnet/minecraft/item/Item;appendTooltip(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/Item$TooltipContext;Ljava/util/List;Lnet/minecraft/item/tooltip/TooltipType;)V" + target = "Lnet/minecraft/item/Item;appendTooltip(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/Item$TooltipContext;Lnet/minecraft/component/type/TooltipDisplayComponent;Ljava/util/function/Consumer;Lnet/minecraft/item/tooltip/TooltipType;)V" ) ) - private boolean appendTooltipCheckRegistryEntry(Item instance, ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { - return this.entry != null; + private void addTooltipFromItem(Item.TooltipContext context, TooltipDisplayComponent displayComponent, PlayerEntity player, TooltipType type, Consumer textConsumer, CallbackInfo info) { + if (this.entry != null) { + this.entry.value().itematic$addTooltip((ItemStack) (Object) this, context, textConsumer, type); + } } @Redirect( - method = "getTooltip", + method = "appendTooltip", at = @At( value = "INVOKE", target = "Lnet/minecraft/registry/DefaultedRegistry;getId(Ljava/lang/Object;)Lnet/minecraft/util/Identifier;" @@ -573,7 +574,7 @@ private Object getWeaponDataComponentReturnNull(ItemStack instance, ComponentTyp ) private int limitDamageApplied(int original) { return this.itematic$getBehavior(ItemComponentTypes.DAMAGEABLE) - .map(c -> Math.min(c.maximumDamage((ItemStack)(Object) this) - this.getDamage(), original)) + .map(c -> Math.min(c.maximumDamage((ItemStack) (Object) this) - this.getDamage(), original)) .orElse(original); } @@ -646,7 +647,7 @@ private ActionResult.Success doNotModifyResultingItemStackIfNotUseable(ActionRes ) private void checkForUseableBehavior(LivingEntity user, ItemStack stack, CallbackInfoReturnable info) { if (!this.itematic$hasBehavior(ItemComponentTypes.USEABLE)) { - info.setReturnValue((ItemStack)(Object) this); + info.setReturnValue((ItemStack) (Object) this); } } @@ -673,7 +674,7 @@ private static void checkEmptyStack(ItemStack stack, CallbackInfoReturnable enchantment, EnchantingContext context) { // Use the original implementation again - return enchantment.value().isAcceptableItem((ItemStack)(Object) this); + return enchantment.value().isAcceptableItem((ItemStack) (Object) this); } @Override @@ -805,7 +806,7 @@ private void setFields(RegistryEntry entry) { this.entry = entry; if (entry.hasKeyAndValue()) { this.components = new MergedComponentMap(entry.value().getComponents()); - entry.value().postProcessComponents((ItemStack)(Object) this); + entry.value().postProcessComponents((ItemStack) (Object) this); } else { this.components = new MergedComponentMap(ComponentMap.EMPTY); } @@ -816,7 +817,7 @@ private void setFields(RegistryEntry entry, ComponentChanges changes) { this.entry = entry; if (entry.hasKeyAndValue()) { this.components = MergedComponentMap.create(entry.value().getComponents(), changes); - entry.value().postProcessComponents((ItemStack)(Object) this); + entry.value().postProcessComponents((ItemStack) (Object) this); } else { this.components = MergedComponentMap.create(ComponentMap.EMPTY, changes); } diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/SmithingTemplateItemAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/item/SmithingTemplateItemAccessor.java index c1e8d0d7..487420a9 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/SmithingTemplateItemAccessor.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/SmithingTemplateItemAccessor.java @@ -2,7 +2,6 @@ import net.minecraft.item.SmithingTemplateItem; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -12,78 +11,68 @@ @Mixin(SmithingTemplateItem.class) public interface SmithingTemplateItemAccessor { - @Accessor("TITLE_FORMATTING") - static Formatting getTitleFormatting() { - throw new AssertionError(); - } - - @Accessor("DESCRIPTION_FORMATTING") - static Formatting getDescriptionFormatting() { - throw new AssertionError(); - } - @Accessor("SMITHING_TEMPLATE_TEXT") - static Text getSmithingTemplateText() { + static Text smithingTemplateTitle() { throw new AssertionError(); } @Accessor("APPLIES_TO_TEXT") - static Text getAppliesToText() { + static Text appliesToTitle() { throw new AssertionError(); } @Accessor("ARMOR_TRIM_APPLIES_TO_TEXT") - static Text getTrimPatternAppliesToText() { + static Text trimPatternAppliesToLabel() { throw new AssertionError(); } @Accessor("INGREDIENTS_TEXT") - static Text getIngredientsText() { + static Text ingredientsTitle() { throw new AssertionError(); } @Accessor("ARMOR_TRIM_INGREDIENTS_TEXT") - static Text getTrimPatternIngredientsText() { + static Text trimPatternIngredients() { throw new AssertionError(); } @Accessor("ARMOR_TRIM_BASE_SLOT_DESCRIPTION_TEXT") - static Text getTrimPatternBaseSlotDescriptionText() { + static Text trimPatternBaseSlotDescription() { throw new AssertionError(); } @Accessor("ARMOR_TRIM_ADDITIONS_SLOT_DESCRIPTION_TEXT") - static Text getTrimPatternAdditionsSlotDescriptionText() { + static Text trimPatternAdditionsSlotDescription() { throw new AssertionError(); } @Accessor("NETHERITE_UPGRADE_BASE_SLOT_DESCRIPTION_TEXT") - static Text getItemUpgradeBaseSlotDescriptionText() { + static Text itemUpgradeBaseSlotDescription() { throw new AssertionError(); } @Accessor("NETHERITE_UPGRADE_ADDITIONS_SLOT_DESCRIPTION_TEXT") - static Text getItemUpgradeAdditionsSlotDescriptionText() { + static Text itemUpgradeAdditionsSlotDescription() { throw new AssertionError(); } @Invoker("getArmorTrimEmptyBaseSlotTextures") - static List getTrimPatternEmptyBaseSlotTextures() { + static List trimPatternEmptyBaseSlotTextures() { throw new AssertionError(); } @Invoker("getArmorTrimEmptyAdditionsSlotTextures") - static List getTrimPatternEmptyAdditionsSlotTextures() { + static List trimPatternEmptyAdditionsSlotTextures() { throw new AssertionError(); } @Invoker("getNetheriteUpgradeEmptyBaseSlotTextures") - static List getItemUpgradeEmptyBaseSlotTextures() { + static List itemUpgradeEmptyBaseSlotTextures() { throw new AssertionError(); } @Invoker("getNetheriteUpgradeEmptyAdditionsSlotTextures") - static List getItemUpgradeEmptyAdditionsSlotTextures() { + static List itemUpgradeEmptyAdditionsSlotTextures() { throw new AssertionError(); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java index e6d19e86..9ff0f309 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTransformRecipeExtender.java @@ -25,7 +25,7 @@ public class SmithingTransformRecipeExtender implements RecipeAccess { @Shadow @Final - Optional base; + Ingredient base; @Shadow @Final @@ -40,7 +40,7 @@ public class SmithingTransformRecipeExtender implements RecipeAccess { return List.of( new SmithingRecipeDisplay( Ingredient.toDisplay(this.template), - Ingredient.toDisplay(this.base), + this.base.toDisplay(), Ingredient.toDisplay(this.addition), this.result.createSlotDisplay(), new SlotDisplay.ItemSlotDisplay(items.getOrThrow(ItemKeys.SMITHING_TABLE)) diff --git a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTrimRecipeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTrimRecipeExtender.java index bd421559..9ef9acba 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTrimRecipeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/recipe/SmithingTrimRecipeExtender.java @@ -3,44 +3,49 @@ import net.errorcraft.itematic.access.recipe.RecipeAccess; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.item.Item; +import net.minecraft.item.equipment.trim.ArmorTrimPattern; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.SmithingTrimRecipe; import net.minecraft.recipe.display.RecipeDisplay; import net.minecraft.recipe.display.SlotDisplay; import net.minecraft.recipe.display.SmithingRecipeDisplay; import net.minecraft.registry.RegistryEntryLookup; +import net.minecraft.registry.entry.RegistryEntry; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.util.List; -import java.util.Optional; @Mixin(SmithingTrimRecipe.class) public class SmithingTrimRecipeExtender implements RecipeAccess { @Shadow @Final - Optional template; + Ingredient template; @Shadow @Final - Optional base; + Ingredient base; @Shadow @Final - Optional addition; + Ingredient addition; + + @Shadow + @Final + RegistryEntry pattern; @Override public List itematic$displays(RegistryEntryLookup items) { - SlotDisplay base = Ingredient.toDisplay(this.base); - SlotDisplay material = Ingredient.toDisplay(this.addition); - SlotDisplay pattern = Ingredient.toDisplay(this.template); + SlotDisplay base = this.base.toDisplay(); + SlotDisplay material = this.addition.toDisplay(); + SlotDisplay pattern = this.template.toDisplay(); return List.of( new SmithingRecipeDisplay( pattern, base, material, - new SlotDisplay.SmithingTrimSlotDisplay(base, material, pattern), + new SlotDisplay.SmithingTrimSlotDisplay(base, material, this.pattern), new SlotDisplay.ItemSlotDisplay(items.getOrThrow(ItemKeys.SMITHING_TABLE)) ) ); diff --git a/src/main/java/net/errorcraft/itematic/mixin/registry/BuiltinRegistriesExtender.java b/src/main/java/net/errorcraft/itematic/mixin/registry/BuiltinRegistriesExtender.java index 5f45de5f..ee2ddec8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/registry/BuiltinRegistriesExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/registry/BuiltinRegistriesExtender.java @@ -3,7 +3,6 @@ import net.errorcraft.itematic.item.ItemUtil; import net.errorcraft.itematic.item.dispense.behavior.DispenseBehaviors; import net.errorcraft.itematic.item.group.entry.provider.ItemGroupEntryProviders; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplates; import net.errorcraft.itematic.registry.ItematicRegistryKeys; import net.errorcraft.itematic.village.trade.Trades; import net.errorcraft.itematic.world.action.Actions; @@ -32,7 +31,6 @@ private static void initialiseCustomRegistries(CallbackInfo info) { .addRegistry(ItematicRegistryKeys.ITEM_GROUP_ENTRY_PROVIDER, ItemGroupEntryProviders::bootstrap) .addRegistry(ItematicRegistryKeys.TRADE, Trades::bootstrap) .addRegistry(ItematicRegistryKeys.ACTION, Actions::bootstrap) - .addRegistry(ItematicRegistryKeys.SMITHING_TEMPLATE, SmithingTemplates::bootstrap) .addRegistry(ItematicRegistryKeys.DISPENSE_BEHAVIOR, DispenseBehaviors::bootstrap); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/registry/RegistryLoaderExtender.java b/src/main/java/net/errorcraft/itematic/mixin/registry/RegistryLoaderExtender.java index 16adc0ee..d9a39374 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/registry/RegistryLoaderExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/registry/RegistryLoaderExtender.java @@ -7,7 +7,6 @@ import net.errorcraft.itematic.item.ItemUtil; import net.errorcraft.itematic.item.dispense.behavior.DispenseBehavior; import net.errorcraft.itematic.item.group.entry.provider.ItemGroupEntryProvider; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; import net.errorcraft.itematic.registry.ActionValidator; import net.errorcraft.itematic.registry.ItematicRegistryKeys; import net.errorcraft.itematic.village.trade.Trade; @@ -43,7 +42,6 @@ private static List> addCustomEntries(List> addCustomNetworkEntries(List clazz, ItemStack stack, @Share("bannerPatternItemComponent") LocalRef bannerPatternItemComponent) { - Optional optionalComponent = stack.itematic$getBehavior(ItemComponentTypes.BANNER_PATTERN); - optionalComponent.ifPresent(bannerPatternItemComponent::set); - return optionalComponent.isPresent(); - } - - @ModifyVariable( - method = "getPatternsFor", - at = @At("LOAD"), - ordinal = 0 - ) - private Item castToBannerPatternItemUseNull(Item instance) { - return null; - } - - @Redirect( - method = "getPatternsFor", + @ModifyExpressionValue( + method = "quickMove", at = @At( value = "INVOKE", - target = "Lnet/minecraft/item/BannerPatternItem;getPattern()Lnet/minecraft/registry/tag/TagKey;" - ) - ) - private TagKey getPatternUseItemComponent(BannerPatternItem instance, @Share("bannerPatternItemComponent") LocalRef bannerPatternItemComponent) { - return bannerPatternItemComponent.get().patterns(); - } - - @ModifyConstant( - method = "quickMove", - constant = @Constant( - classValue = BannerItem.class, - ordinal = 0 + target = "Lnet/minecraft/item/ItemStack;contains(Lnet/minecraft/component/ComponentType;)Z" ) ) - private boolean instanceOfBannerItemUseItemComponent(Object reference, Class clazz, @Local(ordinal = 1) ItemStack slotStack) { - return slotStack.itematic$getBehavior(ItemComponentTypes.BANNER_PATTERN_HOLDER) - .map(BannerPatternHolderItemComponent::modifiable) - .orElse(false); + private boolean containsProvidersBannerPatternsDataComponentAlsoCheckItemBehaviorComponent(boolean original, @Local(ordinal = 1) ItemStack slotStack) { + return original && slotStack.itematic$hasBehavior(ItemComponentTypes.BANNER_PATTERN_HOLDER); } @ModifyConstant( @@ -72,19 +41,10 @@ private boolean instanceOfBannerItemUseItemComponent(Object reference, Class clazz, @Local(ordinal = 1) ItemStack slotStack) { - return slotStack.itematic$hasBehavior(ItemComponentTypes.DYE); - } - - @ModifyConstant( - method = "quickMove", - constant = @Constant( - classValue = BannerPatternItem.class, - ordinal = 0 - ) - ) - private boolean instanceOfBannerPatternItemUseItemComponentCheck(Object reference, Class clazz, @Local(ordinal = 1) ItemStack slotStack) { - return slotStack.itematic$hasBehavior(ItemComponentTypes.BANNER_PATTERN); + private boolean instanceOfDyeItemUseItemComponentCheck(Object reference, Class clazz, @Local(ordinal = 1) ItemStack slotStack, @Share("dye") LocalRef dye) { + Optional optionalDye = slotStack.itematic$getBehavior(ItemComponentTypes.DYE); + optionalDye.ifPresent(dye::set); + return optionalDye.isPresent(); } @Redirect( @@ -105,10 +65,8 @@ private Item getItemUseNull(ItemStack instance) { target = "Lnet/minecraft/item/DyeItem;getColor()Lnet/minecraft/util/DyeColor;" ) ) - private DyeColor getColorUseItemComponent(DyeItem instance, @Local(ordinal = 1) ItemStack dyeStack) { - return dyeStack.itematic$getBehavior(ItemComponentTypes.DYE) - .map(DyeItemComponent::color) - .orElse(DyeColor.WHITE); + private DyeColor getColorUseItemComponent(DyeItem instance, @Share("dye") LocalRef dye) { + return dye.get().color(); } @Mixin(targets = "net/minecraft/screen/LoomScreenHandler$3") @@ -143,15 +101,15 @@ private boolean instanceOfDyeItemUseItemComponentCheck(Object reference, Class clazz, ItemStack stack) { - return stack.itematic$hasBehavior(ItemComponentTypes.BANNER_PATTERN); + private boolean containsProvidersBannerPatternsDataComponentAlsoCheckItemBehaviorComponent(boolean original, ItemStack stack) { + return original && stack.itematic$hasBehavior(ItemComponentTypes.BANNER_PATTERN_HOLDER); } } } diff --git a/src/main/java/net/errorcraft/itematic/registry/ItematicRegistries.java b/src/main/java/net/errorcraft/itematic/registry/ItematicRegistries.java index 74893c8c..5e9d8dcc 100644 --- a/src/main/java/net/errorcraft/itematic/registry/ItematicRegistries.java +++ b/src/main/java/net/errorcraft/itematic/registry/ItematicRegistries.java @@ -10,8 +10,8 @@ import net.errorcraft.itematic.item.placement.block.picker.BlockPickerTypes; import net.errorcraft.itematic.item.shooter.method.ShooterMethodType; import net.errorcraft.itematic.item.shooter.method.ShooterMethodTypes; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateType; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateTypes; +import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; +import net.errorcraft.itematic.item.smithing.template.SmithingTemplates; import net.errorcraft.itematic.item.use.provider.IntegerProviderType; import net.errorcraft.itematic.item.use.provider.IntegerProviderTypes; import net.errorcraft.itematic.mixin.registry.RegistriesAccessor; @@ -28,7 +28,7 @@ public class ItematicRegistries { public static final Registry ITEM_EVENT = RegistriesAccessor.create(ItematicRegistryKeys.ITEM_EVENT, r -> ItemEvents.USE); public static final Registry> ACTION_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.ACTION_TYPE, r -> ActionTypes.MODIFY_ITEM); public static final Registry> SEQUENCE_HANDLER_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.SEQUENCE_HANDLER_TYPE, r -> SequenceHandlerTypes.UNCHECKED); - public static final Registry> SMITHING_TEMPLATE_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.SMITHING_TEMPLATE_TYPE, r -> SmithingTemplateTypes.TRIM_PATTERN); + public static final Registry SMITHING_TEMPLATE = RegistriesAccessor.create(ItematicRegistryKeys.SMITHING_TEMPLATE, r -> SmithingTemplates.TRIM_PATTERN); public static final Registry> BLOCK_PICKER_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.BLOCK_PICKER_TYPE, r -> BlockPickerTypes.SIMPLE); public static final Registry> TRADE_MODIFIER_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.TRADE_MODIFIER_TYPE, r -> TradeModifierTypes.ENCHANT_WITH_LEVELS); public static final Registry> INTEGER_PROVIDER_TYPE = RegistriesAccessor.create(ItematicRegistryKeys.INTEGER_PROVIDER_TYPE, r -> IntegerProviderTypes.CONSTANT); diff --git a/src/main/java/net/errorcraft/itematic/registry/ItematicRegistryKeys.java b/src/main/java/net/errorcraft/itematic/registry/ItematicRegistryKeys.java index 2e1a9a3b..5bff8b39 100644 --- a/src/main/java/net/errorcraft/itematic/registry/ItematicRegistryKeys.java +++ b/src/main/java/net/errorcraft/itematic/registry/ItematicRegistryKeys.java @@ -8,7 +8,6 @@ import net.errorcraft.itematic.item.placement.block.picker.BlockPickerType; import net.errorcraft.itematic.item.shooter.method.ShooterMethodType; import net.errorcraft.itematic.item.smithing.template.SmithingTemplate; -import net.errorcraft.itematic.item.smithing.template.SmithingTemplateType; import net.errorcraft.itematic.item.use.provider.IntegerProviderType; import net.errorcraft.itematic.village.trade.Trade; import net.errorcraft.itematic.village.trade.modifier.TradeModifierType; @@ -28,7 +27,6 @@ public class ItematicRegistryKeys { public static final RegistryKey> TRADE = RegistryKey.ofRegistry(Identifier.ofVanilla("trade")); public static final RegistryKey> ACTION = RegistryKey.ofRegistry(Identifier.ofVanilla("action")); public static final RegistryKey>> SEQUENCE_HANDLER_TYPE = RegistryKey.ofRegistry(Identifier.ofVanilla("sequence_handler_type")); - public static final RegistryKey>> SMITHING_TEMPLATE_TYPE = RegistryKey.ofRegistry(Identifier.ofVanilla("smithing_template_type")); public static final RegistryKey> SMITHING_TEMPLATE = RegistryKey.ofRegistry(Identifier.ofVanilla("smithing_template")); public static final RegistryKey>> BLOCK_PICKER_TYPE = RegistryKey.ofRegistry(Identifier.ofVanilla("block_picker_type")); public static final RegistryKey>> TRADE_MODIFIER_TYPE = RegistryKey.ofRegistry(Identifier.ofVanilla("trade_modifier_type")); diff --git a/src/main/java/net/errorcraft/itematic/sound/SoundEventKeys.java b/src/main/java/net/errorcraft/itematic/sound/SoundEventKeys.java index c1bddd52..4d5fa397 100644 --- a/src/main/java/net/errorcraft/itematic/sound/SoundEventKeys.java +++ b/src/main/java/net/errorcraft/itematic/sound/SoundEventKeys.java @@ -27,6 +27,7 @@ public class SoundEventKeys { public static final RegistryKey GENERIC_SPLASH = of("entity.generic.splash"); public static final RegistryKey HOE_TILL = of("item.hoe.till"); public static final RegistryKey HONEY_BOTTLE_DRINK = of("item.honey_bottle.drink"); + public static final RegistryKey HORSE_ARMOR = of("entity.horse.armor"); public static final RegistryKey LODESTONE_COMPASS_LOCK = of("item.lodestone_compass.lock"); public static final RegistryKey MUSIC_DISC_5 = of("music_disc.5"); public static final RegistryKey MUSIC_DISC_11 = of("music_disc.11"); @@ -48,10 +49,13 @@ public class SoundEventKeys { public static final RegistryKey MUSIC_DISC_WAIT = of("music_disc.wait"); public static final RegistryKey MUSIC_DISC_WARD = of("music_disc.ward"); public static final RegistryKey OMINOUS_BOTTLE_DISPOSE = of("item.ominous_bottle.dispose"); + public static final RegistryKey SHIELD_BLOCK = of("item.shield.block"); + public static final RegistryKey SHIELD_BREAK = of("item.shield.break"); public static final RegistryKey SHOVEL_FLATTEN = of("item.shovel.flatten"); public static final RegistryKey SPYGLASS_USE = of("item.spyglass.use"); public static final RegistryKey SPYGLASS_STOP_USING = of("item.spyglass.stop_using"); public static final RegistryKey TNT_PRIMED = of("entity.tnt.primed"); + public static final RegistryKey WOLF_ARMOR_BREAK = of("item.wolf_armor.break"); private SoundEventKeys() {} diff --git a/src/main/java/net/errorcraft/itematic/util/IdentifierUtil.java b/src/main/java/net/errorcraft/itematic/util/IdentifierUtil.java deleted file mode 100644 index 6e196d97..00000000 --- a/src/main/java/net/errorcraft/itematic/util/IdentifierUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.errorcraft.itematic.util; - -import net.minecraft.registry.RegistryKey; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; - -public class IdentifierUtil { - public static String createTranslationKey(RegistryKey key, String prefix, String suffix) { - return createTranslationKey(key.getValue(), prefix, suffix); - } - - public static String createTranslationKey(Identifier id, String prefix, String suffix) { - return Util.createTranslationKey(prefix, id) + "." + suffix; - } -} diff --git a/src/main/java/net/errorcraft/itematic/util/Util.java b/src/main/java/net/errorcraft/itematic/util/Util.java index d5ef3c51..9bcd6d01 100644 --- a/src/main/java/net/errorcraft/itematic/util/Util.java +++ b/src/main/java/net/errorcraft/itematic/util/Util.java @@ -1,7 +1,6 @@ package net.errorcraft.itematic.util; -import net.minecraft.util.math.MathHelper; -import org.apache.commons.lang3.math.Fraction; +import net.minecraft.util.Identifier; import java.util.Arrays; import java.util.Objects; @@ -10,13 +9,13 @@ public class Util { private Util() {} + public static String descriptionKey(String prefix, Identifier id, String suffix) { + return net.minecraft.util.Util.createTranslationKey(prefix, id) + "." + suffix; + } + public static String stackTraceMessage(String message) { return Arrays.stream(Thread.currentThread().getStackTrace()) .map(Objects::toString) .collect(Collectors.joining("\n\t", message + "\nStack trace:\n\t", "")); } - - public static int multiplyFraction(Fraction fraction, int multiplier) { - return MathHelper.ceil(fraction.multiplyBy(Fraction.getFraction(multiplier, 1)).doubleValue()); - } } 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 7637ee05..ac50015d 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java @@ -28,7 +28,6 @@ public class ActionTypeKeys { public static final RegistryKey> DROP_ITEM_FROM_BLOCK = of("drop_item_from_block"); public static final RegistryKey> ATTACH_LEASHED_ENTITIES_ON_BLOCK = of("attach_leashed_entities_on_block"); public static final RegistryKey> SET_ENTITY_NAME_FROM_ITEM = of("set_entity_name_from_item"); - public static final RegistryKey> OPEN_BOOK_FROM_ITEM = of("open_book_from_item"); public static final RegistryKey> PLACE_BLOCK_FROM_ITEM = of("place_block_from_item"); public static final RegistryKey> MARK_BANNER_ON_ITEM = of("mark_banner_on_item"); public static final RegistryKey> TWIRL_PLAYER = of("twirl_player"); 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 9731220d..059f07e7 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java +++ b/src/main/java/net/errorcraft/itematic/world/action/ActionTypes.java @@ -29,7 +29,6 @@ public class ActionTypes { public static final ActionType DROP_ITEM_FROM_BLOCK = register(ActionTypeKeys.DROP_ITEM_FROM_BLOCK, new ActionType<>(DropItemFromBlockAction.CODEC)); public static final ActionType ATTACH_LEASHED_ENTITIES_ON_BLOCK = register(ActionTypeKeys.ATTACH_LEASHED_ENTITIES_ON_BLOCK, new ActionType<>(AttachLeashedEntitiesOnBlockAction.CODEC)); public static final ActionType SET_ENTITY_NAME_FROM_ITEM = register(ActionTypeKeys.SET_ENTITY_NAME_FROM_ITEM, new ActionType<>(SetEntityNameFromItemAction.CODEC)); - public static final ActionType OPEN_BOOK_FROM_ITEM = register(ActionTypeKeys.OPEN_BOOK_FROM_ITEM, new ActionType<>(OpenBookFromItemAction.CODEC)); public static final ActionType PLACE_BLOCK_FROM_ITEM = register(ActionTypeKeys.PLACE_BLOCK_FROM_ITEM, new ActionType<>(PlaceBlockFromItemAction.CODEC)); public static final ActionType MARK_BANNER_ON_ITEM = register(ActionTypeKeys.MARK_BANNER_ON_ITEM, new ActionType<>(MarkBannerOnItemAction.CODEC)); public static final ActionType TWIRL_PLAYER = register(ActionTypeKeys.TWIRL_PLAYER, new ActionType<>(TwirlPlayerAction.CODEC)); diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/OpenBookFromItemAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/OpenBookFromItemAction.java deleted file mode 100644 index 70565109..00000000 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/OpenBookFromItemAction.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.errorcraft.itematic.world.action.actions; - -import com.mojang.serialization.MapCodec; -import net.errorcraft.itematic.item.ItemStackUtil; -import net.errorcraft.itematic.util.context.ItematicContextParameters; -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.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.util.Hand; - -public class OpenBookFromItemAction implements Action { - public static final OpenBookFromItemAction INSTANCE = new OpenBookFromItemAction(); - public static final MapCodec CODEC = MapCodec.unit(INSTANCE); - - private OpenBookFromItemAction() {} - - @Override - public ActionType type() { - return ActionTypes.OPEN_BOOK_FROM_ITEM; - } - - @Override - public boolean execute(ActionContext context) { - Entity entity = context.get(LootContextParameters.THIS_ENTITY); - if (!(entity instanceof PlayerEntity player)) { - return false; - } - - ItemStack stack = context.get(LootContextParameters.TOOL); - if (ItemStackUtil.isNullOrEmpty(stack)) { - return false; - } - - Hand hand = context.get(ItematicContextParameters.HAND); - if (hand == null) { - return false; - } - - player.useBook(stack, hand); - return true; - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f192ff59..90104996 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -94,9 +94,6 @@ "net/minecraft/class_3611": [ "net/errorcraft/itematic/access/fluid/FluidAccess" ], - "net/minecraft/class_4059\u0024class_9076": [ - "net/errorcraft/itematic/access/item/AnimalArmorItemTypeAccess" - ], "net/minecraft/class_4538": [ "net/errorcraft/itematic/access/world/WorldViewAccess" ], diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 2f7915f5..480cb1a9 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -235,8 +235,9 @@ "entity.projectile.thrown.EggEntityExtender", "entity.projectile.thrown.EnderPearlEntityExtender", "entity.projectile.thrown.ExperienceBottleEntityExtender", - "entity.projectile.thrown.PotionEntityExtender", + "entity.projectile.thrown.LingeringPotionEntityExtender", "entity.projectile.thrown.SnowballEntityExtender", + "entity.projectile.thrown.SplashPotionEntityExtender", "entity.projectile.thrown.ThrownItemEntityExtender", "entity.raid.RaiderEntityExtender", "entity.raid.RaiderEntityExtender$PickUpBannerAsLeaderGoalExtender", @@ -254,7 +255,6 @@ "fluid.LavaFluidExtender", "fluid.WaterFluidExtender", "inventory.SimpleInventoryExtender", - "item.AnimalArmorItemExtender$TypeExtender", "item.BoneMealItemExtender", "item.BrushItemAccessor", "item.BrushItemExtender", From 3f8225fe6448f4f7fccc94b2759bbf847946757a Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Tue, 7 Apr 2026 02:31:38 +0200 Subject: [PATCH 04/12] Port to 25w05a --- gradle.properties | 6 +-- .../select/ChargeTypePropertyExtender.java | 23 ++++++++++ .../resources/itematic.client.mixins.json | 1 + .../data/server/tag/ItemTagProvider.java | 2 + .../generated/data/minecraft/item/bush.json | 15 ++++++ .../data/minecraft/item/firefly_bush.json | 15 ++++++ .../generated/data/minecraft/item/shield.json | 1 + .../tags/item/item_group/plants.json | 2 + .../access/block/entity/SherdsAccess.java | 4 -- .../errorcraft/itematic/block/BlockKeys.java | 2 + .../errorcraft/itematic/item/ItemKeys.java | 2 + .../errorcraft/itematic/item/ItemUtil.java | 21 ++++++++- .../DecoratedPotBlockEntityExtender.java | 18 ++++---- .../mixin/block/entity/SherdsExtender.java | 13 ------ ...oreboardCriterionArgumentTypeExtender.java | 25 ++++------ .../passive/MerchantEntityExtender.java | 16 ------- .../passive/MilkableEntitiesExtender.java | 7 ++- .../ScoreboardCriterionAccessor.java | 15 ++++++ .../ScoreboardCriterionExtender.java | 40 ++++++---------- .../scoreboard/ScoreboardStateExtender.java | 29 ------------ .../mixin/village/raid/RaidExtender.java | 7 +-- .../scoreboard/ScoreboardCriterionUtil.java | 40 +++++++++++++--- .../serialization/RegistryMapperCodec.java | 46 +++++++++++++++++++ src/main/resources/itematic.mixins.json | 2 +- 24 files changed, 221 insertions(+), 131 deletions(-) create mode 100644 src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java create mode 100644 src/main/generated/data/minecraft/item/bush.json create mode 100644 src/main/generated/data/minecraft/item/firefly_bush.json create mode 100644 src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionAccessor.java delete mode 100644 src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardStateExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/serialization/RegistryMapperCodec.java diff --git a/gradle.properties b/gradle.properties index 33e64957..f37330b6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w04a - yarn_mappings=25w04a+build.10 + minecraft_version=25w05a + yarn_mappings=25w05a+build.5 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.115.1+1.21.5 + fabric_version=0.115.2+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java new file mode 100644 index 00000000..5ef44b8d --- /dev/null +++ b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java @@ -0,0 +1,23 @@ +package net.errorcraft.itematic.mixin.client.render.item.property.select; + +import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.client.render.item.property.select.ChargeTypeProperty; +import net.minecraft.component.type.ChargedProjectilesComponent; +import net.minecraft.item.Item; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ChargeTypeProperty.class) +public class ChargeTypePropertyExtender { + @Redirect( + method = "getValue(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/entity/LivingEntity;ILnet/minecraft/item/ModelTransformationMode;)Lnet/minecraft/item/CrossbowItem$ChargeType;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/component/type/ChargedProjectilesComponent;contains(Lnet/minecraft/item/Item;)Z" + ) + ) + private boolean containsForFireworkRocketUseRegistryKeyCheck(ChargedProjectilesComponent instance, Item item) { + return instance.itematic$contains(ItemKeys.FIREWORK_ROCKET); + } +} diff --git a/src/client/resources/itematic.client.mixins.json b/src/client/resources/itematic.client.mixins.json index cba0235a..45d853dd 100644 --- a/src/client/resources/itematic.client.mixins.json +++ b/src/client/resources/itematic.client.mixins.json @@ -56,6 +56,7 @@ "render.entity.feature.WolfArmorFeatureRendererExtender", "render.entity.state.ItemStackEntityRenderStateExtender", "render.item.HeldItemRendererExtender", + "render.item.property.select.ChargeTypePropertyExtender", "tutorial.CraftPlanksTutorialStepHandlerExtender", "world.ClientWorldExtender", "world.WorldEventHandlerExtender" diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java index 0e8aa177..f6089743 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java +++ b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java @@ -930,6 +930,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.WARPED_FUNGUS) .add(ItemKeys.SHORT_GRASS) .add(ItemKeys.FERN) + .add(ItemKeys.BUSH) .add(ItemKeys.DEAD_BUSH) .add(ItemKeys.DANDELION) .add(ItemKeys.OPEN_EYEBLOSSOM) @@ -951,6 +952,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.WILDFLOWERS) .add(ItemKeys.LEAF_LITTER) .add(ItemKeys.SPORE_BLOSSOM) + .add(ItemKeys.FIREFLY_BUSH) .add(ItemKeys.BAMBOO) .add(ItemKeys.SUGAR_CANE) .add(ItemKeys.CACTUS) diff --git a/src/main/generated/data/minecraft/item/bush.json b/src/main/generated/data/minecraft/item/bush.json new file mode 100644 index 00000000..59ab4764 --- /dev/null +++ b/src/main/generated/data/minecraft/item/bush.json @@ -0,0 +1,15 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:bush" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:bush", + "translation_key": "block.minecraft.bush" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/firefly_bush.json b/src/main/generated/data/minecraft/item/firefly_bush.json new file mode 100644 index 00000000..2884e575 --- /dev/null +++ b/src/main/generated/data/minecraft/item/firefly_bush.json @@ -0,0 +1,15 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:firefly_bush" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:firefly_bush", + "translation_key": "block.minecraft.firefly_bush" + } +} \ 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 015c0fc1..89358302 100644 --- a/src/main/generated/data/minecraft/item/shield.json +++ b/src/main/generated/data/minecraft/item/shield.json @@ -3,6 +3,7 @@ "minecraft:attack_blocking": { "block_delay_seconds": 0.25, "block_sound": "minecraft:item.shield.block", + "bypassed_by": "#minecraft:bypasses_shield", "disabled_sound": "minecraft:item.shield.break", "item_damage": { "base": 1.0, diff --git a/src/main/generated/data/minecraft/tags/item/item_group/plants.json b/src/main/generated/data/minecraft/tags/item/item_group/plants.json index 78ce8d35..e491b150 100644 --- a/src/main/generated/data/minecraft/tags/item/item_group/plants.json +++ b/src/main/generated/data/minecraft/tags/item/item_group/plants.json @@ -8,6 +8,7 @@ "minecraft:warped_fungus", "minecraft:short_grass", "minecraft:fern", + "minecraft:bush", "minecraft:dead_bush", "minecraft:dandelion", "minecraft:open_eyeblossom", @@ -29,6 +30,7 @@ "minecraft:wildflowers", "minecraft:leaf_litter", "minecraft:spore_blossom", + "minecraft:firefly_bush", "minecraft:bamboo", "minecraft:sugar_cane", "minecraft:cactus", diff --git a/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java b/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java index fb43459f..bf9e86eb 100644 --- a/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java +++ b/src/main/java/net/errorcraft/itematic/access/block/entity/SherdsAccess.java @@ -1,7 +1,6 @@ package net.errorcraft.itematic.access.block.entity; import net.minecraft.item.Item; -import net.minecraft.nbt.NbtCompound; import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.entry.RegistryEntry; @@ -9,9 +8,6 @@ import java.util.Optional; public interface SherdsAccess { - default NbtCompound itematic$toNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { - return null; - } default List>> itematic$optionalEntries() { return null; } diff --git a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java index 665c39c3..8ae6a0ab 100644 --- a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java +++ b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java @@ -139,6 +139,7 @@ public class BlockKeys { public static final RegistryKey SHORT_GRASS = of("short_grass"); public static final RegistryKey FERN = of("fern"); public static final RegistryKey DEAD_BUSH = of("dead_bush"); + public static final RegistryKey BUSH = of("bush"); public static final RegistryKey SEAGRASS = of("seagrass"); public static final RegistryKey PISTON = of("piston"); public static final RegistryKey WHITE_WOOL = of("white_wool"); @@ -1064,6 +1065,7 @@ public class BlockKeys { public static final RegistryKey CLOSED_EYEBLOSSOM = of("closed_eyeblossom"); public static final RegistryKey POTTED_OPEN_EYEBLOSSOM = of("potted_open_eyeblossom"); public static final RegistryKey POTTED_CLOSED_EYEBLOSSOM = of("potted_closed_eyeblossom"); + public static final RegistryKey FIREFLY_BUSH = of("firefly_bush"); private BlockKeys() {} diff --git a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java index 79faf535..4f1e9044 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java @@ -210,9 +210,11 @@ public class ItemKeys { public static final RegistryKey COBWEB = register("cobweb"); public static final RegistryKey SHORT_GRASS = register("short_grass"); public static final RegistryKey FERN = register("fern"); + public static final RegistryKey BUSH = register("bush"); public static final RegistryKey AZALEA = register("azalea"); public static final RegistryKey FLOWERING_AZALEA = register("flowering_azalea"); public static final RegistryKey DEAD_BUSH = register("dead_bush"); + public static final RegistryKey FIREFLY_BUSH = register("firefly_bush"); public static final RegistryKey SEAGRASS = register("seagrass"); public static final RegistryKey SEA_PICKLE = register("sea_pickle"); public static final RegistryKey WHITE_WOOL = register("white_wool"); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index e839d1ad..9383ce99 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -6704,6 +6704,22 @@ private void bootstrapCompostables() { .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); + this.registerable.register(ItemKeys.BUSH, create( + ItemDisplay.Builder.forBlock(ItemKeys.BUSH).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.BUSH))) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); + this.registerable.register(ItemKeys.FIREFLY_BUSH, create( + ItemDisplay.Builder.forBlock(ItemKeys.FIREFLY_BUSH).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.FIREFLY_BUSH))) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); this.registerable.register(ItemKeys.FLOWERING_AZALEA_LEAVES, create( ItemDisplay.Builder.forBlock(ItemKeys.FLOWERING_AZALEA_LEAVES).build(), ItemComponentSet.builder() @@ -7365,8 +7381,11 @@ private void bootstrapEquipment() { .with(AttackBlockingItemComponent.of(new BlocksAttacksComponent( 0.25f, 1.0f, - List.of(BlocksAttacksComponent.DamageReduction.DEFAULT), + List.of( + new BlocksAttacksComponent.DamageReduction(90.0f, Optional.empty(), 0.0f, 1.0f) + ), new BlocksAttacksComponent.ItemDamage(3.0f, 1.0f, 1.0f), + Optional.of(DamageTypeTags.BYPASSES_SHIELD), Optional.of(this.soundEvents.getOrThrow(SoundEventKeys.SHIELD_BLOCK)), Optional.of(this.soundEvents.getOrThrow(SoundEventKeys.SHIELD_BREAK)) ))) diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/entity/DecoratedPotBlockEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/entity/DecoratedPotBlockEntityExtender.java index aa456c5e..42017525 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/entity/DecoratedPotBlockEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/entity/DecoratedPotBlockEntityExtender.java @@ -1,19 +1,21 @@ package net.errorcraft.itematic.mixin.block.entity; import com.llamalad7.mixinextras.sugar.Local; -import net.errorcraft.itematic.block.entity.SherdsUtil; +import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.DecoratedPotBlockEntity; -import net.minecraft.block.entity.Sherds; import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtOps; import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import java.util.Optional; + @Mixin(DecoratedPotBlockEntity.class) public class DecoratedPotBlockEntityExtender extends BlockEntity { public DecoratedPotBlockEntityExtender(BlockEntityType type, BlockPos pos, BlockState state) { @@ -24,21 +26,21 @@ public DecoratedPotBlockEntityExtender(BlockEntityType type, BlockPos pos, Bl method = "readNbt", at = @At( value = "INVOKE", - target = "Lnet/minecraft/block/entity/Sherds;fromNbt(Lnet/minecraft/nbt/NbtCompound;)Lnet/minecraft/block/entity/Sherds;" + target = "Lnet/minecraft/nbt/NbtCompound;get(Ljava/lang/String;Lcom/mojang/serialization/Codec;)Ljava/util/Optional;" ) ) - private Sherds fromNbtUseDynamicRegistry(NbtCompound nbt, @Local(argsOnly = true) RegistryWrapper.WrapperLookup lookup) { - return SherdsUtil.fromNbt(nbt, lookup); + private Optional getUseRegistryOps(NbtCompound instance, String key, Codec codec, @Local(argsOnly = true) RegistryWrapper.WrapperLookup lookup) { + return instance.get(key, codec, lookup.getOps(NbtOps.INSTANCE)); } @Redirect( method = "writeNbt", at = @At( value = "INVOKE", - target = "Lnet/minecraft/block/entity/Sherds;toNbt(Lnet/minecraft/nbt/NbtCompound;)Lnet/minecraft/nbt/NbtCompound;" + target = "Lnet/minecraft/nbt/NbtCompound;put(Ljava/lang/String;Lcom/mojang/serialization/Codec;Ljava/lang/Object;)V" ) ) - private NbtCompound toNbtUseDynamicRegistry(Sherds instance, NbtCompound nbt, @Local(argsOnly = true) RegistryWrapper.WrapperLookup lookup) { - return instance.itematic$toNbt(nbt, lookup); + private void putUseRegistryOps(NbtCompound instance, String key, Codec codec, T value, @Local(argsOnly = true) RegistryWrapper.WrapperLookup lookup) { + instance.put(key, codec, lookup.getOps(NbtOps.INSTANCE), value); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java index c83761b0..e13fdac6 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/entity/SherdsExtender.java @@ -7,8 +7,6 @@ import net.minecraft.block.entity.Sherds; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtOps; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; @@ -179,17 +177,6 @@ private void appendSherdTooltipUseRegistryEntry(Consumer textConsumer, Opt .ifPresent(textConsumer); } - @Override - @SuppressWarnings("EqualsBetweenInconvertibleTypes") - public NbtCompound itematic$toNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { - if (this.equals(DEFAULT)) { - return nbt; - } - - nbt.put("sherds", CODEC.encodeStart(lookup.getOps(NbtOps.INSTANCE), (Sherds)(Object) this).getOrThrow()); - return nbt; - } - @Override public List>> itematic$optionalEntries() { return List.of(this.back, this.left, this.right, this.front); diff --git a/src/main/java/net/errorcraft/itematic/mixin/command/argument/ScoreboardCriterionArgumentTypeExtender.java b/src/main/java/net/errorcraft/itematic/mixin/command/argument/ScoreboardCriterionArgumentTypeExtender.java index 8a6e4eef..afa88ffe 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/command/argument/ScoreboardCriterionArgumentTypeExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/command/argument/ScoreboardCriterionArgumentTypeExtender.java @@ -2,44 +2,39 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.brigadier.StringReader; +import com.mojang.serialization.JsonOps; import net.errorcraft.itematic.access.command.argument.ScoreboardCriterionArgumentTypeAccess; import net.errorcraft.itematic.scoreboard.ScoreboardCriterionUtil; import net.errorcraft.itematic.stat.StatUtil; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.argument.ScoreboardCriterionArgumentType; +import net.minecraft.registry.RegistryOps; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.scoreboard.ScoreboardCriterion; import net.minecraft.stat.StatType; 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.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Iterator; +import java.util.Optional; @Mixin(ScoreboardCriterionArgumentType.class) public class ScoreboardCriterionArgumentTypeExtender implements ScoreboardCriterionArgumentTypeAccess { @Unique private CommandRegistryAccess registryAccess; - @Inject( - method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/scoreboard/ScoreboardCriterion;", - at = @At("HEAD") - ) - private void setLookup(StringReader reader, CallbackInfoReturnable info) { - ScoreboardCriterionUtil.setLookup(this.registryAccess); - } - - @Inject( + @Redirect( method = "parse(Lcom/mojang/brigadier/StringReader;)Lnet/minecraft/scoreboard/ScoreboardCriterion;", - at = @At("RETURN") + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/scoreboard/ScoreboardCriterion;getOrCreateStatCriterion(Ljava/lang/String;)Ljava/util/Optional;" + ) ) - private void resetLookup(StringReader reader, CallbackInfoReturnable info) { - ScoreboardCriterionUtil.setLookup(null); + private Optional useDynamicRegistry(String name) { + return ScoreboardCriterionUtil.byName(name, RegistryOps.of(JsonOps.INSTANCE, this.registryAccess)); } @ModifyExpressionValue( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java index c26b8720..6c369c62 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java @@ -1,7 +1,6 @@ package net.errorcraft.itematic.mixin.entity.passive; import com.google.common.collect.Lists; -import com.mojang.serialization.DynamicOps; import net.errorcraft.itematic.mixin.entity.mob.MobEntityExtender; import net.errorcraft.itematic.util.context.ItematicContextTypes; import net.errorcraft.itematic.village.trade.Trade; @@ -11,8 +10,6 @@ import net.minecraft.loot.context.LootContext; import net.minecraft.loot.context.LootContextParameters; import net.minecraft.loot.context.LootWorldContext; -import net.minecraft.nbt.NbtElement; -import net.minecraft.registry.RegistryOps; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.server.world.ServerWorld; @@ -23,7 +20,6 @@ import org.spongepowered.asm.mixin.Shadow; 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.ArrayList; @@ -49,18 +45,6 @@ private void fillRecipesUseDynamicRegistry(MerchantEntity instance) { this.fillRecipesFromContext(); } - @ModifyArg( - method = "readCustomDataFromNbt", - at = @At( - value = "INVOKE", - target = "Lcom/mojang/serialization/Codec;parse(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;", - remap = false - ) - ) - private DynamicOps parseTradeOfferListUseCodec(DynamicOps ops) { - return RegistryOps.of(ops, this.getWorld().getRegistryManager()); - } - @Unique protected void fillRecipes(LootContext context) {} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MilkableEntitiesExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MilkableEntitiesExtender.java index 2e8a156b..88196289 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MilkableEntitiesExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MilkableEntitiesExtender.java @@ -2,8 +2,8 @@ import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.entity.EntityType; +import net.minecraft.entity.passive.AbstractCowEntity; import net.minecraft.entity.passive.AnimalEntity; -import net.minecraft.entity.passive.CowEntity; import net.minecraft.entity.passive.GoatEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -14,7 +14,10 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; -@Mixin({ CowEntity.class, GoatEntity.class }) +@Mixin({ + AbstractCowEntity.class, + GoatEntity.class +}) public abstract class MilkableEntitiesExtender extends AnimalEntity { protected MilkableEntitiesExtender(EntityType entityType, World world) { super(entityType, world); diff --git a/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionAccessor.java new file mode 100644 index 00000000..6484991e --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionAccessor.java @@ -0,0 +1,15 @@ +package net.errorcraft.itematic.mixin.scoreboard; + +import net.minecraft.scoreboard.ScoreboardCriterion; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(ScoreboardCriterion.class) +public interface ScoreboardCriterionAccessor { + @Accessor("CRITERIA") + static Map customCriteria() { + throw new AssertionError(); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionExtender.java b/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionExtender.java index abeb42e5..a5ea1bf8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardCriterionExtender.java @@ -1,24 +1,19 @@ package net.errorcraft.itematic.mixin.scoreboard; -import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.PrimitiveCodec; import net.errorcraft.itematic.access.scoreboard.ScoreboardCriterionAccess; import net.errorcraft.itematic.scoreboard.ScoreboardCriterionUtil; -import net.minecraft.registry.Registry; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.entry.RegistryEntry; +import net.errorcraft.itematic.serialization.RegistryMapperCodec; import net.minecraft.scoreboard.ScoreboardCriterion; -import net.minecraft.stat.Stat; -import net.minecraft.stat.StatType; -import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.Optional; import java.util.function.Function; @Mixin(ScoreboardCriterion.class) @@ -29,28 +24,19 @@ public class ScoreboardCriterionExtender implements ScoreboardCriterionAccess { private String name; @Redirect( - method = "getOrCreateStatCriterion(Lnet/minecraft/stat/StatType;Lnet/minecraft/util/Identifier;)Ljava/util/Optional;", + method = "", at = @At( value = "INVOKE", - target = "Lnet/minecraft/registry/Registry;getOptionalValue(Lnet/minecraft/util/Identifier;)Ljava/util/Optional;" + target = "Lcom/mojang/serialization/codecs/PrimitiveCodec;comapFlatMap(Ljava/util/function/Function;Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;", + remap = false ) ) - private static Optional> getOrEmptyUseDynamicRegistry(Registry instance, Identifier id) { - RegistryKey> key = instance.getKey(); - return ScoreboardCriterionUtil.lookup() - .getOrThrow(key) - .getOptional(RegistryKey.of(key, id)); - } - - @ModifyArg( - method = "getOrCreateStatCriterion(Lnet/minecraft/stat/StatType;Lnet/minecraft/util/Identifier;)Ljava/util/Optional;", - at = @At( - value = "INVOKE", - target = "Ljava/util/Optional;map(Ljava/util/function/Function;)Ljava/util/Optional;" - ) - ) - private static Function, ? extends Stat> mapToStatUseRegistryEntry(Function mapper, @Local(argsOnly = true) StatType statType) { - return statType::itematic$getOrCreateStat; + private static Codec useDynamicRegistry(PrimitiveCodec instance, Function> to, Function from) { + return RegistryMapperCodec.of( + instance, + ScoreboardCriterionUtil::byName, + ScoreboardCriterion::getName + ); } @Override diff --git a/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardStateExtender.java b/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardStateExtender.java deleted file mode 100644 index 7c1f5b99..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/scoreboard/ScoreboardStateExtender.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.errorcraft.itematic.mixin.scoreboard; - -import net.errorcraft.itematic.scoreboard.ScoreboardCriterionUtil; -import net.minecraft.nbt.NbtList; -import net.minecraft.registry.RegistryWrapper; -import net.minecraft.scoreboard.ScoreboardState; -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.callback.CallbackInfo; - -@Mixin(ScoreboardState.class) -public class ScoreboardStateExtender { - @Inject( - method = "readObjectivesNbt", - at = @At("HEAD") - ) - private void setLookup(NbtList nbt, RegistryWrapper.WrapperLookup registries, CallbackInfo info) { - ScoreboardCriterionUtil.setLookup(registries); - } - - @Inject( - method = "readObjectivesNbt", - at = @At("TAIL") - ) - private void resetLookup(NbtList nbt, RegistryWrapper.WrapperLookup registries, CallbackInfo info) { - ScoreboardCriterionUtil.setLookup(null); - } -} diff --git a/src/main/java/net/errorcraft/itematic/mixin/village/raid/RaidExtender.java b/src/main/java/net/errorcraft/itematic/mixin/village/raid/RaidExtender.java index ac2908d5..c9dc0bfa 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/village/raid/RaidExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/village/raid/RaidExtender.java @@ -6,9 +6,7 @@ import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; import net.minecraft.village.raid.Raid; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -17,9 +15,6 @@ @Mixin(Raid.class) public abstract class RaidExtender { - @Shadow - public abstract World getWorld(); - @Redirect( method = "createOminousBanner", at = @At( @@ -53,6 +48,6 @@ private static void checkEmptyStack(CallbackInfoReturnable info, @Loc ) ) private void createOminousBannerSetDataDrivenItemStack(int wave, RaiderEntity entity, CallbackInfo info) { - RaidUtil.createOminousBanner(this.getWorld()); + RaidUtil.createOminousBanner(entity.getWorld()); } } diff --git a/src/main/java/net/errorcraft/itematic/scoreboard/ScoreboardCriterionUtil.java b/src/main/java/net/errorcraft/itematic/scoreboard/ScoreboardCriterionUtil.java index 3d95a423..c44b7e6b 100644 --- a/src/main/java/net/errorcraft/itematic/scoreboard/ScoreboardCriterionUtil.java +++ b/src/main/java/net/errorcraft/itematic/scoreboard/ScoreboardCriterionUtil.java @@ -1,17 +1,45 @@ package net.errorcraft.itematic.scoreboard; -import net.minecraft.registry.RegistryWrapper; +import net.errorcraft.itematic.mixin.scoreboard.ScoreboardCriterionAccessor; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryOps; +import net.minecraft.scoreboard.ScoreboardCriterion; +import net.minecraft.stat.StatType; +import net.minecraft.util.Identifier; + +import java.util.Map; +import java.util.Optional; public class ScoreboardCriterionUtil { - private static RegistryWrapper.WrapperLookup lookup; + private static final Map CUSTOM_CRITERIA = ScoreboardCriterionAccessor.customCriteria(); private ScoreboardCriterionUtil() {} - public static RegistryWrapper.WrapperLookup lookup() { - return lookup; + public static Optional byName(String name, RegistryOps ops) { + ScoreboardCriterion customCriterion = CUSTOM_CRITERIA.get(name); + if (customCriterion != null) { + return Optional.of(customCriterion); + } + + int separatorIndex = name.indexOf(':'); + if (separatorIndex == -1) { + return Optional.empty(); + } + + return Registries.STAT_TYPE.getOptionalValue(Identifier.splitOn(name.substring(0, separatorIndex), '.')) + .flatMap(statType -> getStat( + statType, + Identifier.splitOn(name.substring(separatorIndex + 1), '.'), + ops + )); } - public static void setLookup(RegistryWrapper.WrapperLookup lookup) { - ScoreboardCriterionUtil.lookup = lookup; + private static Optional getStat(StatType statType, Identifier id, RegistryOps ops) { + RegistryKey> registryKey = statType.getRegistry().getKey(); + return ops.getEntryLookup(registryKey) + .flatMap(lookup -> lookup.getOptional(RegistryKey.of(registryKey, id))) + .map(statType::itematic$getOrCreateStat); } } diff --git a/src/main/java/net/errorcraft/itematic/serialization/RegistryMapperCodec.java b/src/main/java/net/errorcraft/itematic/serialization/RegistryMapperCodec.java new file mode 100644 index 00000000..d8c57263 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/serialization/RegistryMapperCodec.java @@ -0,0 +1,46 @@ +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.RegistryOps; + +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class RegistryMapperCodec implements Codec { + private final Codec fromCodec; + private final BiFunction, Optional> to; + private final Function from; + + private RegistryMapperCodec(Codec fromCodec, BiFunction, Optional> to, Function from) { + this.fromCodec = fromCodec; + this.to = to; + this.from = from; + } + + public static RegistryMapperCodec of(Codec fromCodec, BiFunction, Optional> to, Function from) { + return new RegistryMapperCodec<>(fromCodec, to, from); + } + + @Override + public DataResult> decode(DynamicOps ops, T input) { + if (!(ops instanceof RegistryOps registryOps)) { + return DataResult.error(() -> "Registries are inaccessible"); + } + + return this.fromCodec.decode(ops, input) + .map(Pair::getFirst) + .map(joined -> this.to.apply(joined, registryOps)) + .flatMap(result -> result.map(DataResult::success) + .orElseGet(() -> DataResult.error(() -> "Invalid name: " + input))) + .map(result -> Pair.of(result, input)); + } + + @Override + public DataResult encode(A input, DynamicOps ops, T prefix) { + return this.fromCodec.encode(this.from.apply(input), ops, prefix); + } +} diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 480cb1a9..fd90bbbb 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -350,8 +350,8 @@ "registry.entry.RegistryEntryExtender$ReferenceExtender", "registry.entry.RegistryEntryListExtender", "registry.entry.RegistryEntryListExtender$ListBackedExtender", + "scoreboard.ScoreboardCriterionAccessor", "scoreboard.ScoreboardCriterionExtender", - "scoreboard.ScoreboardStateExtender", "screen.AbstractFurnaceScreenHandlerExtender", "screen.AnvilScreenHandlerExtender", "screen.BrewingStandScreenHandlerAccessor", From edaf4abf575c45e8438758160ec52f3c9596f399 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Tue, 7 Apr 2026 21:38:51 +0200 Subject: [PATCH 05/12] Port to 25w06a --- gradle.properties | 6 +- .../data/server/tag/ItemTagProvider.java | 11 +- .../data/minecraft/item/blue_egg.json | 22 ++++ .../data/minecraft/item/brown_egg.json | 22 ++++ .../data/minecraft/item/cactus_flower.json | 15 +++ .../data/minecraft/item/compass.json | 39 ++++++- .../generated/data/minecraft/item/egg.json | 3 + .../data/minecraft/item/short_dry_grass.json | 18 +++ .../data/minecraft/item/tall_dry_grass.json | 18 +++ .../item_group_entry_provider/combat.json | 5 +- .../ingredients.json | 5 +- .../minecraft/tags/item/item_group/eggs.json | 7 ++ .../tags/item/item_group/plants.json | 7 +- .../errorcraft/itematic/block/BlockKeys.java | 3 + .../itematic/entity/EntitySpawner.java | 48 ++++++++ .../errorcraft/itematic/item/ItemKeys.java | 5 + .../errorcraft/itematic/item/ItemUtil.java | 107 +++++++++++++++++- .../itematic/item/ItematicItemTags.java | 1 + .../item/component/ItemComponent.java | 3 - .../item/component/ItemComponentTypes.java | 1 - .../components/MapHolderItemComponent.java | 12 +- .../components/PlayableSongItemComponent.java | 4 +- .../components/PointableItemComponent.java | 60 ---------- .../components/ProjectileItemComponent.java | 22 ++-- .../item/data/InventoryTickListener.java | 11 ++ .../provider/ItemGroupEntryProviders.java | 4 +- .../function/ItematicItemModifierTypes.java | 1 + .../loot/function/SplitItemModifier.java | 45 ++++++++ .../LodestoneTrackerComponentExtender.java | 27 +++++ .../type/MapIdComponentExtender.java | 32 ++++++ .../itematic/mixin/entity/EntityAccessor.java | 12 ++ .../entity/mob/ZombieEntityExtender.java | 15 +-- .../entity/player/PlayerEntityExtender.java | 2 +- .../projectile/thrown/EggEntityExtender.java | 31 +++++ .../itematic/mixin/item/ItemExtender.java | 34 ++---- .../action/actions/ModifyItemAction.java | 26 ++++- .../actions/SetItemPointerLocationAction.java | 29 ++--- .../world/action/context/ItemStackTarget.java | 34 ++++++ src/main/resources/itematic.mixins.json | 3 + 39 files changed, 592 insertions(+), 158 deletions(-) create mode 100644 src/main/generated/data/minecraft/item/blue_egg.json create mode 100644 src/main/generated/data/minecraft/item/brown_egg.json create mode 100644 src/main/generated/data/minecraft/item/cactus_flower.json create mode 100644 src/main/generated/data/minecraft/item/short_dry_grass.json create mode 100644 src/main/generated/data/minecraft/item/tall_dry_grass.json create mode 100644 src/main/generated/data/minecraft/tags/item/item_group/eggs.json create mode 100644 src/main/java/net/errorcraft/itematic/entity/EntitySpawner.java delete mode 100644 src/main/java/net/errorcraft/itematic/item/component/components/PointableItemComponent.java create mode 100644 src/main/java/net/errorcraft/itematic/item/data/InventoryTickListener.java create mode 100644 src/main/java/net/errorcraft/itematic/loot/function/SplitItemModifier.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/component/type/LodestoneTrackerComponentExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/component/type/MapIdComponentExtender.java create mode 100644 src/main/java/net/errorcraft/itematic/mixin/entity/EntityAccessor.java create mode 100644 src/main/java/net/errorcraft/itematic/world/action/context/ItemStackTarget.java diff --git a/gradle.properties b/gradle.properties index f37330b6..8c9f8702 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w05a - yarn_mappings=25w05a+build.5 + minecraft_version=25w06a + yarn_mappings=25w06a+build.7 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.115.2+1.21.5 + fabric_version=0.116.0+1.21.5 diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java index f6089743..8c2c9781 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java +++ b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java @@ -930,11 +930,10 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.WARPED_FUNGUS) .add(ItemKeys.SHORT_GRASS) .add(ItemKeys.FERN) + .add(ItemKeys.SHORT_DRY_GRASS) .add(ItemKeys.BUSH) .add(ItemKeys.DEAD_BUSH) .add(ItemKeys.DANDELION) - .add(ItemKeys.OPEN_EYEBLOSSOM) - .add(ItemKeys.CLOSED_EYEBLOSSOM) .add(ItemKeys.POPPY) .add(ItemKeys.BLUE_ORCHID) .add(ItemKeys.ALLIUM) @@ -947,6 +946,9 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.CORNFLOWER) .add(ItemKeys.LILY_OF_THE_VALLEY) .add(ItemKeys.TORCHFLOWER) + .add(ItemKeys.CACTUS_FLOWER) + .add(ItemKeys.CLOSED_EYEBLOSSOM) + .add(ItemKeys.OPEN_EYEBLOSSOM) .add(ItemKeys.WITHER_ROSE) .add(ItemKeys.PINK_PETALS) .add(ItemKeys.WILDFLOWERS) @@ -964,6 +966,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.VINE) .add(ItemKeys.TALL_GRASS) .add(ItemKeys.LARGE_FERN) + .add(ItemKeys.TALL_DRY_GRASS) .add(ItemKeys.SUNFLOWER) .add(ItemKeys.LILAC) .add(ItemKeys.ROSE_BUSH) @@ -1264,6 +1267,10 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(ItemKeys.IRON_HORSE_ARMOR) .add(ItemKeys.GOLDEN_HORSE_ARMOR) .add(ItemKeys.DIAMOND_HORSE_ARMOR); + this.getOrCreateTagBuilder(ItematicItemTags.EGGS) + .add(ItemKeys.EGG) + .add(ItemKeys.BROWN_EGG) + .add(ItemKeys.BLUE_EGG); this.getOrCreateTagBuilder(ItematicItemTags.FOOD) .add(ItemKeys.APPLE) .add(ItemKeys.GOLDEN_APPLE) diff --git a/src/main/generated/data/minecraft/item/blue_egg.json b/src/main/generated/data/minecraft/item/blue_egg.json new file mode 100644 index 00000000..dc86954e --- /dev/null +++ b/src/main/generated/data/minecraft/item/blue_egg.json @@ -0,0 +1,22 @@ +{ + "behavior": { + "minecraft:dispensable": { + "behavior": "minecraft:shoot_projectile" + }, + "minecraft:projectile": { + "components": { + "minecraft:chicken/variant": "minecraft:cold" + }, + "entity": "minecraft:egg" + }, + "minecraft:stackable": 16, + "minecraft:throwable": { + "angle_offset": 0.0, + "speed": 1.5 + } + }, + "display": { + "model": "minecraft:blue_egg", + "translation_key": "item.minecraft.blue_egg" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/brown_egg.json b/src/main/generated/data/minecraft/item/brown_egg.json new file mode 100644 index 00000000..863f38c5 --- /dev/null +++ b/src/main/generated/data/minecraft/item/brown_egg.json @@ -0,0 +1,22 @@ +{ + "behavior": { + "minecraft:dispensable": { + "behavior": "minecraft:shoot_projectile" + }, + "minecraft:projectile": { + "components": { + "minecraft:chicken/variant": "minecraft:warm" + }, + "entity": "minecraft:egg" + }, + "minecraft:stackable": 16, + "minecraft:throwable": { + "angle_offset": 0.0, + "speed": 1.5 + } + }, + "display": { + "model": "minecraft:brown_egg", + "translation_key": "item.minecraft.brown_egg" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/cactus_flower.json b/src/main/generated/data/minecraft/item/cactus_flower.json new file mode 100644 index 00000000..33e4afef --- /dev/null +++ b/src/main/generated/data/minecraft/item/cactus_flower.json @@ -0,0 +1,15 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:cactus_flower" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:cactus_flower", + "translation_key": "block.minecraft.cactus_flower" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/compass.json b/src/main/generated/data/minecraft/item/compass.json index ec17c66f..e57462bc 100644 --- a/src/main/generated/data/minecraft/item/compass.json +++ b/src/main/generated/data/minecraft/item/compass.json @@ -1,8 +1,5 @@ { "behavior": { - "minecraft:pointable": { - "lodestone_translation_key": "item.minecraft.lodestone_compass" - }, "minecraft:stackable": 64 }, "display": { @@ -15,10 +12,44 @@ "type": "minecraft:sequence", "handler": "minecraft:passing", "entries": [ + { + "action": { + "type": "minecraft:modify_item", + "item_modifier": { + "count": 1.0, + "function": "minecraft:split" + } + } + }, { "action": { "type": "minecraft:set_item_pointer_location", - "position": "interacted" + "position": "interacted", + "stack": "result" + } + }, + { + "action": { + "type": "minecraft:modify_item", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "function": "minecraft:set_name", + "name": { + "translate": "item.minecraft.lodestone_compass" + }, + "target": "item_name" + }, + { + "components": { + "minecraft:enchantment_glint_override": true + }, + "function": "minecraft:set_components" + } + ] + }, + "stack": "result" } }, { diff --git a/src/main/generated/data/minecraft/item/egg.json b/src/main/generated/data/minecraft/item/egg.json index 2754ce7a..a8e8f62f 100644 --- a/src/main/generated/data/minecraft/item/egg.json +++ b/src/main/generated/data/minecraft/item/egg.json @@ -4,6 +4,9 @@ "behavior": "minecraft:shoot_projectile" }, "minecraft:projectile": { + "components": { + "minecraft:chicken/variant": "minecraft:temperate" + }, "entity": "minecraft:egg" }, "minecraft:stackable": 16, diff --git a/src/main/generated/data/minecraft/item/short_dry_grass.json b/src/main/generated/data/minecraft/item/short_dry_grass.json new file mode 100644 index 00000000..079bf781 --- /dev/null +++ b/src/main/generated/data/minecraft/item/short_dry_grass.json @@ -0,0 +1,18 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:short_dry_grass" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:fuel": { + "ticks": 100 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:short_dry_grass", + "translation_key": "block.minecraft.short_dry_grass" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item/tall_dry_grass.json b/src/main/generated/data/minecraft/item/tall_dry_grass.json new file mode 100644 index 00000000..c500de0c --- /dev/null +++ b/src/main/generated/data/minecraft/item/tall_dry_grass.json @@ -0,0 +1,18 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:tall_dry_grass" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "minecraft:fuel": { + "ticks": 100 + }, + "minecraft:stackable": 64 + }, + "display": { + "model": "minecraft:tall_dry_grass", + "translation_key": "block.minecraft.tall_dry_grass" + } +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/item_group_entry_provider/combat.json b/src/main/generated/data/minecraft/item_group_entry_provider/combat.json index a9aaf1be..b336efa0 100644 --- a/src/main/generated/data/minecraft/item_group_entry_provider/combat.json +++ b/src/main/generated/data/minecraft/item_group_entry_provider/combat.json @@ -24,7 +24,10 @@ "minecraft:tnt", "minecraft:end_crystal", "minecraft:snowball", - "minecraft:egg", + { + "type": "tag", + "tag": "minecraft:item_group/eggs" + }, "minecraft:wind_charge", "minecraft:bow", "minecraft:crossbow", diff --git a/src/main/generated/data/minecraft/item_group_entry_provider/ingredients.json b/src/main/generated/data/minecraft/item_group_entry_provider/ingredients.json index c0fc01b9..980f60e1 100644 --- a/src/main/generated/data/minecraft/item_group_entry_provider/ingredients.json +++ b/src/main/generated/data/minecraft/item_group_entry_provider/ingredients.json @@ -27,7 +27,10 @@ "minecraft:string", "minecraft:feather", "minecraft:snowball", - "minecraft:egg", + { + "type": "tag", + "tag": "minecraft:item_group/eggs" + }, "minecraft:leather", "minecraft:rabbit_hide", "minecraft:honeycomb", diff --git a/src/main/generated/data/minecraft/tags/item/item_group/eggs.json b/src/main/generated/data/minecraft/tags/item/item_group/eggs.json new file mode 100644 index 00000000..b78a29d7 --- /dev/null +++ b/src/main/generated/data/minecraft/tags/item/item_group/eggs.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:egg", + "minecraft:brown_egg", + "minecraft:blue_egg" + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/item/item_group/plants.json b/src/main/generated/data/minecraft/tags/item/item_group/plants.json index e491b150..7a805ea8 100644 --- a/src/main/generated/data/minecraft/tags/item/item_group/plants.json +++ b/src/main/generated/data/minecraft/tags/item/item_group/plants.json @@ -8,11 +8,10 @@ "minecraft:warped_fungus", "minecraft:short_grass", "minecraft:fern", + "minecraft:short_dry_grass", "minecraft:bush", "minecraft:dead_bush", "minecraft:dandelion", - "minecraft:open_eyeblossom", - "minecraft:closed_eyeblossom", "minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", @@ -25,6 +24,9 @@ "minecraft:cornflower", "minecraft:lily_of_the_valley", "minecraft:torchflower", + "minecraft:cactus_flower", + "minecraft:closed_eyeblossom", + "minecraft:open_eyeblossom", "minecraft:wither_rose", "minecraft:pink_petals", "minecraft:wildflowers", @@ -42,6 +44,7 @@ "minecraft:vine", "minecraft:tall_grass", "minecraft:large_fern", + "minecraft:tall_dry_grass", "minecraft:sunflower", "minecraft:lilac", "minecraft:rose_bush", diff --git a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java index 8ae6a0ab..11038326 100644 --- a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java +++ b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java @@ -140,6 +140,8 @@ public class BlockKeys { public static final RegistryKey FERN = of("fern"); public static final RegistryKey DEAD_BUSH = of("dead_bush"); public static final RegistryKey BUSH = of("bush"); + public static final RegistryKey SHORT_DRY_GRASS = of("short_dry_grass"); + public static final RegistryKey TALL_DRY_GRASS = of("tall_dry_grass"); public static final RegistryKey SEAGRASS = of("seagrass"); public static final RegistryKey PISTON = of("piston"); public static final RegistryKey WHITE_WOOL = of("white_wool"); @@ -267,6 +269,7 @@ public class BlockKeys { public static final RegistryKey ICE = of("ice"); public static final RegistryKey SNOW_BLOCK = of("snow_block"); public static final RegistryKey CACTUS = of("cactus"); + public static final RegistryKey CACTUS_FLOWER = of("cactus_flower"); public static final RegistryKey CLAY = of("clay"); public static final RegistryKey SUGAR_CANE = of("sugar_cane"); public static final RegistryKey JUKEBOX = of("jukebox"); diff --git a/src/main/java/net/errorcraft/itematic/entity/EntitySpawner.java b/src/main/java/net/errorcraft/itematic/entity/EntitySpawner.java new file mode 100644 index 00000000..69879d64 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/entity/EntitySpawner.java @@ -0,0 +1,48 @@ +package net.errorcraft.itematic.entity; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.mixin.entity.EntityAccessor; +import net.errorcraft.itematic.world.action.context.ActionContext; +import net.minecraft.component.ComponentChanges; +import net.minecraft.component.ComponentMap; +import net.minecraft.component.MergedComponentMap; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnReason; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registries; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.util.math.BlockPos; + +public record EntitySpawner(RegistryEntry> entity, ComponentChanges components) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + Registries.ENTITY_TYPE.getEntryCodec().fieldOf("entity").forGetter(EntitySpawner::entity), + ComponentChanges.CODEC.optionalFieldOf("components", ComponentChanges.EMPTY).forGetter(EntitySpawner::components) + ).apply(instance, EntitySpawner::new)); + + public static EntitySpawner of(RegistryEntry> entity) { + return new EntitySpawner(entity, ComponentChanges.EMPTY); + } + + public static EntitySpawner of(RegistryEntry> entity, ComponentChanges components) { + return new EntitySpawner(entity, components); + } + + public Entity create(ActionContext context, BlockPos pos, SpawnReason reason) { + return this.entity.value().itematic$create( + context, + reason, + pos, + this::applyComponents, + false, + false + ); + } + + private void applyComponents(Entity entity, ItemStack stack) { + ((EntityAccessor) entity).itematic$copyComponentsFrom( + MergedComponentMap.create(ComponentMap.EMPTY, this.components) + ); + } +} diff --git a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java index 4f1e9044..aac3921c 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java @@ -215,6 +215,8 @@ public class ItemKeys { public static final RegistryKey FLOWERING_AZALEA = register("flowering_azalea"); public static final RegistryKey DEAD_BUSH = register("dead_bush"); public static final RegistryKey FIREFLY_BUSH = register("firefly_bush"); + public static final RegistryKey SHORT_DRY_GRASS = register("short_dry_grass"); + public static final RegistryKey TALL_DRY_GRASS = register("tall_dry_grass"); public static final RegistryKey SEAGRASS = register("seagrass"); public static final RegistryKey SEA_PICKLE = register("sea_pickle"); public static final RegistryKey WHITE_WOOL = register("white_wool"); @@ -333,6 +335,7 @@ public class ItemKeys { public static final RegistryKey ICE = register("ice"); public static final RegistryKey SNOW_BLOCK = register("snow_block"); public static final RegistryKey CACTUS = register("cactus"); + public static final RegistryKey CACTUS_FLOWER = register("cactus_flower"); public static final RegistryKey CLAY = register("clay"); public static final RegistryKey JUKEBOX = register("jukebox"); public static final RegistryKey OAK_FENCE = register("oak_fence"); @@ -971,6 +974,8 @@ public class ItemKeys { public static final RegistryKey BOOK = register("book"); public static final RegistryKey SLIME_BALL = register("slime_ball"); public static final RegistryKey EGG = register("egg"); + public static final RegistryKey BLUE_EGG = register("blue_egg"); + public static final RegistryKey BROWN_EGG = register("brown_egg"); public static final RegistryKey COMPASS = register("compass"); public static final RegistryKey RECOVERY_COMPASS = register("recovery_compass"); public static final RegistryKey BUNDLE = register("bundle"); diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index 9383ce99..c19763ae 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -19,6 +19,7 @@ import net.errorcraft.itematic.item.shooter.method.methods.DirectShooterMethod; import net.errorcraft.itematic.item.smithing.template.SmithingTemplates; import net.errorcraft.itematic.loot.condition.LocationCheckLootConditionUtil; +import net.errorcraft.itematic.loot.function.SplitItemModifier; import net.errorcraft.itematic.loot.predicate.SideCheckPredicate; import net.errorcraft.itematic.mixin.item.BrushItemAccessor; import net.errorcraft.itematic.mixin.item.CrossbowItemAccessor; @@ -29,6 +30,7 @@ import net.errorcraft.itematic.world.action.ActionEntry; import net.errorcraft.itematic.world.action.Actions; import net.errorcraft.itematic.world.action.actions.*; +import net.errorcraft.itematic.world.action.context.ItemStackTarget; import net.errorcraft.itematic.world.action.context.ItematicEntityTargets; import net.errorcraft.itematic.world.action.context.PositionTarget; import net.errorcraft.itematic.world.action.sequence.handler.handlers.FirstToPassRequirementsSequenceHandler; @@ -48,6 +50,8 @@ import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.passive.ChickenVariant; +import net.minecraft.entity.passive.ChickenVariants; import net.minecraft.fluid.Fluid; import net.minecraft.item.*; import net.minecraft.item.consume.UseAction; @@ -58,6 +62,8 @@ import net.minecraft.item.equipment.trim.ArmorTrimMaterials; import net.minecraft.loot.condition.*; import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.function.SetComponentsLootFunction; +import net.minecraft.loot.function.SetNameLootFunction; import net.minecraft.particle.ParticleTypes; import net.minecraft.potion.Potion; import net.minecraft.predicate.BlockPredicate; @@ -68,12 +74,14 @@ import net.minecraft.predicate.entity.LocationPredicate; import net.minecraft.predicate.item.*; import net.minecraft.registry.*; +import net.minecraft.registry.entry.LazyRegistryEntryReference; import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.registry.tag.*; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; @@ -143,6 +151,7 @@ private static class Bootstrapper { private final RegistryEntryLookup jukeboxSongs; private final RegistryEntryLookup instruments; private final RegistryEntryLookup trimMaterials; + private final RegistryEntryLookup chickenVariants; private Bootstrapper(Registerable registerable) { this.registerable = registerable; @@ -160,6 +169,7 @@ private Bootstrapper(Registerable registerable) { this.jukeboxSongs = registerable.getRegistryLookup(RegistryKeys.JUKEBOX_SONG); this.instruments = registerable.getRegistryLookup(RegistryKeys.INSTRUMENT); this.trimMaterials = registerable.getRegistryLookup(RegistryKeys.TRIM_MATERIAL); + this.chickenVariants = registerable.getRegistryLookup(RegistryKeys.CHICKEN_VARIANT); } private void bootstrap() { @@ -6720,6 +6730,14 @@ private void bootstrapCompostables() { .with(CompostableItemComponent.of(CompostChances.SMALL)) .build() )); + this.registerable.register(ItemKeys.CACTUS_FLOWER, create( + ItemDisplay.Builder.forBlock(ItemKeys.CACTUS_FLOWER).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.CACTUS_FLOWER))) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); this.registerable.register(ItemKeys.FLOWERING_AZALEA_LEAVES, create( ItemDisplay.Builder.forBlock(ItemKeys.FLOWERING_AZALEA_LEAVES).build(), ItemComponentSet.builder() @@ -9523,6 +9541,24 @@ private void bootstrapFuel() { .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.EQUIP_ENTITY))) .build() )); + this.registerable.register(ItemKeys.SHORT_DRY_GRASS, create( + ItemDisplay.Builder.forBlock(ItemKeys.SHORT_DRY_GRASS).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.SHORT_DRY_GRASS))) + .with(FuelItemComponent.of(FuelTimes.PLANT)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); + this.registerable.register(ItemKeys.TALL_DRY_GRASS, create( + ItemDisplay.Builder.forBlock(ItemKeys.TALL_DRY_GRASS).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.TALL_DRY_GRASS))) + .with(FuelItemComponent.of(FuelTimes.PLANT)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); this.registerable.register(ItemKeys.LEAF_LITTER, create( ItemDisplay.Builder.forBlock(ItemKeys.LEAF_LITTER).build(), ItemComponentSet.builder() @@ -9557,7 +9593,55 @@ private void bootstrapProjectiles() { ItemComponentSet.builder() .with(StackableItemComponent.of(16)) .with(ThrowableItemComponent.of(1.5f)) - .with(ProjectileItemComponent.of(this.entityTypes.getOrThrow(EntityTypeKeys.EGG))) + .with(ProjectileItemComponent.of( + this.entityTypes.getOrThrow(EntityTypeKeys.EGG), + ComponentChanges.builder() + .add( + DataComponentTypes.CHICKEN_VARIANT, + new LazyRegistryEntryReference<>( + this.chickenVariants.getOrThrow(ChickenVariants.TEMPERATE) + ) + ) + .build() + )) + .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SHOOT_PROJECTILE))) + .build() + )); + this.registerable.register(ItemKeys.BLUE_EGG, create( + ItemDisplay.Builder.forItem(ItemKeys.BLUE_EGG).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(16)) + .with(ThrowableItemComponent.of(1.5f)) + .with(ProjectileItemComponent.of( + this.entityTypes.getOrThrow(EntityTypeKeys.EGG), + ComponentChanges.builder() + .add( + DataComponentTypes.CHICKEN_VARIANT, + new LazyRegistryEntryReference<>( + this.chickenVariants.getOrThrow(ChickenVariants.COLD) + ) + ) + .build() + )) + .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SHOOT_PROJECTILE))) + .build() + )); + this.registerable.register(ItemKeys.BROWN_EGG, create( + ItemDisplay.Builder.forItem(ItemKeys.BROWN_EGG).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(16)) + .with(ThrowableItemComponent.of(1.5f)) + .with(ProjectileItemComponent.of( + this.entityTypes.getOrThrow(EntityTypeKeys.EGG), + ComponentChanges.builder() + .add( + DataComponentTypes.CHICKEN_VARIANT, + new LazyRegistryEntryReference<>( + this.chickenVariants.getOrThrow(ChickenVariants.WARM) + ) + ) + .build() + )) .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SHOOT_PROJECTILE))) .build() )); @@ -10880,7 +10964,6 @@ private void bootstrapMiscellaneous() { ItemDisplay.Builder.forItem(ItemKeys.COMPASS).build(), ItemComponentSet.builder() .with(StackableItemComponent.of(64)) - .with(PointableItemComponent.of(Util.createTranslationKey("item", Identifier.ofVanilla("lodestone_compass")))) .build(), ItemEventMap.builder() .add(ItemEvents.USE_ON_BLOCK, ActionEntry.of( @@ -10891,7 +10974,25 @@ private void bootstrapMiscellaneous() { .blocks(this.blocks, this.blocks.getOrThrow(BlockKeys.LODESTONE).value())) ), PassingSequenceHandler.builder() - .add(SetItemPointerLocationAction.of(PositionTarget.INTERACTED_POSITION)) + .add(ModifyItemAction.of( + ItemStackTarget.TOOL, + SplitItemModifier.builder(1) + )) + .add(SetItemPointerLocationAction.of( + ItemStackTarget.RESULT, + PositionTarget.INTERACTED_POSITION + )) + .add(ModifyItemAction.of( + ItemStackTarget.RESULT, + SetNameLootFunction.builder( + Text.translatable(Util.createTranslationKey("item", Identifier.ofVanilla("lodestone_compass"))), + SetNameLootFunction.Target.ITEM_NAME + ), + SetComponentsLootFunction.builder( + DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, + true + ) + )) .add(PlaySoundAction.of( PositionTarget.INTERACTED_POSITION, this.soundEvents.getOrThrow(SoundEventKeys.LODESTONE_COMPASS_LOCK), diff --git a/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java b/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java index b663a84c..c4ebe5ff 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java +++ b/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java @@ -139,6 +139,7 @@ public class ItematicItemTags { public static final TagKey AXES = of("item_group/axes"); public static final TagKey ARMOR = of("item_group/armor"); public static final TagKey HORSE_ARMOR = of("item_group/horse_armor"); + public static final TagKey EGGS = of("item_group/eggs"); public static final TagKey FOOD = of("item_group/food"); public static final TagKey DYES = of("item_group/dyes"); public static final TagKey BREWING_INGREDIENTS = of("item_group/brewing_ingredients"); 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 f7b2b006..f247a0e4 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponent.java @@ -7,7 +7,6 @@ import net.errorcraft.itematic.world.action.context.ItemStackExchanger; import net.minecraft.block.BlockState; import net.minecraft.component.ComponentMap; -import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -58,8 +57,6 @@ default boolean stopUsing(ItemStack stack, World world, LivingEntity user, int u default void finishUsing(World world, LivingEntity user, ItemStack stack, int usedTicks, ItemStackExchanger stackExchanger) {} - default void inventoryTick(ItemStack stack, World world, Entity holder, int slot, boolean selected) {} - default boolean clickOnSlot(ItemStack stack, Slot slot, ClickType clickType, PlayerEntity user) { return false; } 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 9e9778b3..361b852a 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -34,7 +34,6 @@ public class ItemComponentTypes { public static final ItemComponentType CONSUMABLE = register("consumable", new ItemComponentType<>(ConsumableItemComponent.CODEC)); public static final ItemComponentType POTION_HOLDER = register("potion_holder", new ItemComponentType<>(PotionHolderItemComponent.CODEC)); public static final ItemComponentType STEERING = register("steering", new ItemComponentType<>(SteeringItemComponent.CODEC)); - public static final ItemComponentType POINTABLE = register("pointable", new ItemComponentType<>(PointableItemComponent.CODEC)); public static final ItemComponentType PREVENT_USE_WHEN_USED_ON_TARGET = register("prevent_use_when_used_on_target", new ItemComponentType<>(PreventUseWhenUsedOnTargetItemComponent.CODEC)); public static final ItemComponentType SMITHING_TEMPLATE_PROVIDER = register("smithing_template_provider", new ItemComponentType<>(SmithingTemplateProviderItemComponent.CODEC)); public static final ItemComponentType BANNER_PATTERN = register("banner_pattern", new ItemComponentType<>(BannerPatternItemComponent.CODEC)); diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java index 393ff626..f3bbc166 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/MapHolderItemComponent.java @@ -8,16 +8,17 @@ import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.MapColorComponent; import net.minecraft.component.type.MapDecorationsComponent; -import net.minecraft.entity.Entity; import net.minecraft.item.FilledMapItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.world.World; -public record MapHolderItemComponent() implements ItemComponent { +public class MapHolderItemComponent implements ItemComponent { public static final MapHolderItemComponent INSTANCE = new MapHolderItemComponent(); public static final Codec CODEC = Codec.unit(INSTANCE); - private static final FilledMapItem DUMMY = new FilledMapItem(new Item.Settings()); + public static final FilledMapItem DUMMY = new FilledMapItem(new Item.Settings()); + + private MapHolderItemComponent() {} @Override public ItemComponentType type() { @@ -35,11 +36,6 @@ public void addComponents(ComponentMap.Builder builder) { builder.add(DataComponentTypes.MAP_DECORATIONS, MapDecorationsComponent.DEFAULT); } - @Override - public void inventoryTick(ItemStack stack, World world, Entity holder, int slot, boolean selected) { - DUMMY.inventoryTick(stack, world, holder, slot, selected); - } - @Override public void onCraft(ItemStack stack, World world) { DUMMY.onCraft(stack, world); diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java index 724f5ef4..19db9afd 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/PlayableSongItemComponent.java @@ -8,7 +8,7 @@ import net.minecraft.component.ComponentMap; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.JukeboxPlayableComponent; -import net.minecraft.registry.RegistryPair; +import net.minecraft.registry.entry.LazyRegistryEntryReference; import net.minecraft.registry.entry.RegistryEntry; public record PlayableSongItemComponent(RegistryEntry song) implements ItemComponent { @@ -33,6 +33,6 @@ public Codec codec() { @Override public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.JUKEBOX_PLAYABLE, new JukeboxPlayableComponent(new RegistryPair<>(this.song))); + builder.add(DataComponentTypes.JUKEBOX_PLAYABLE, new JukeboxPlayableComponent(new LazyRegistryEntryReference<>(this.song))); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/PointableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PointableItemComponent.java deleted file mode 100644 index ccf5d81b..00000000 --- a/src/main/java/net/errorcraft/itematic/item/component/components/PointableItemComponent.java +++ /dev/null @@ -1,60 +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.component.DataComponentTypes; -import net.minecraft.component.type.LodestoneTrackerComponent; -import net.minecraft.entity.Entity; -import net.minecraft.item.ItemStack; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.world.World; - -import java.util.Optional; - -public record PointableItemComponent(String lodestoneTranslationKey) implements ItemComponent { - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Codec.STRING.fieldOf("lodestone_translation_key").forGetter(PointableItemComponent::lodestoneTranslationKey) - ).apply(instance, PointableItemComponent::new)); - - public static PointableItemComponent of(String lodestoneTranslationKey) { - return new PointableItemComponent(lodestoneTranslationKey); - } - - @Override - public ItemComponentType type() { - return ItemComponentTypes.POINTABLE; - } - - @Override - public Codec codec() { - return CODEC; - } - - @Override - public void inventoryTick(ItemStack stack, World world, Entity holder, int slot, boolean selected) { - if (!(world instanceof ServerWorld serverWorld)) { - return; - } - - LodestoneTrackerComponent currentTracker = stack.get(DataComponentTypes.LODESTONE_TRACKER); - if (currentTracker == null) { - return; - } - - LodestoneTrackerComponent newTracker = currentTracker.forWorld(serverWorld); - if (newTracker != currentTracker) { - stack.set(DataComponentTypes.LODESTONE_TRACKER, newTracker); - } - } - - public Optional lodestoneTranslationKey(ItemStack stack) { - if (stack.contains(DataComponentTypes.LODESTONE_TRACKER)) { - return Optional.of(this.lodestoneTranslationKey); - } - - return Optional.empty(); - } -} diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/ProjectileItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/ProjectileItemComponent.java index 58070d92..99ce80a7 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/ProjectileItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/ProjectileItemComponent.java @@ -2,12 +2,14 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.entity.EntitySpawner; 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.util.context.ItematicContextParameters; import net.errorcraft.itematic.world.action.context.ActionContext; import net.errorcraft.itematic.world.action.context.PositionTarget; +import net.minecraft.component.ComponentChanges; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -19,7 +21,6 @@ import net.minecraft.entity.projectile.thrown.ThrownItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.registry.Registries; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; @@ -27,13 +28,17 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public record ProjectileItemComponent(RegistryEntry> entity) implements ItemComponent { +public record ProjectileItemComponent(EntitySpawner entity) implements ItemComponent { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - Registries.ENTITY_TYPE.getEntryCodec().fieldOf("entity").forGetter(ProjectileItemComponent::entity) + EntitySpawner.CODEC.forGetter(ProjectileItemComponent::entity) ).apply(instance, ProjectileItemComponent::new)); public static ProjectileItemComponent of(RegistryEntry> entity) { - return new ProjectileItemComponent(entity); + return new ProjectileItemComponent(EntitySpawner.of(entity)); + } + + public static ProjectileItemComponent of(RegistryEntry> entity, ComponentChanges components) { + return new ProjectileItemComponent(EntitySpawner.of(entity, components)); } @Override @@ -67,14 +72,7 @@ public Entity createEntity(ActionContext context, PositionTarget position, float return null; } - Entity entity = this.entity.value().itematic$create( - context, - SpawnReason.SPAWN_ITEM_USE, - BlockPos.ofFloored(pos), - null, - false, - false - ); + Entity entity = this.entity.create(context, BlockPos.ofFloored(pos), SpawnReason.SPAWN_ITEM_USE); if (entity == null) { return null; } diff --git a/src/main/java/net/errorcraft/itematic/item/data/InventoryTickListener.java b/src/main/java/net/errorcraft/itematic/item/data/InventoryTickListener.java new file mode 100644 index 00000000..71d4454a --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/item/data/InventoryTickListener.java @@ -0,0 +1,11 @@ +package net.errorcraft.itematic.item.data; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import org.jetbrains.annotations.Nullable; + +public interface InventoryTickListener { + void itematic$onInventoryTick(ServerWorld world, ItemStack stack, Entity owner, @Nullable EquipmentSlot slot); +} diff --git a/src/main/java/net/errorcraft/itematic/item/group/entry/provider/ItemGroupEntryProviders.java b/src/main/java/net/errorcraft/itematic/item/group/entry/provider/ItemGroupEntryProviders.java index 00a7786b..f2a34071 100644 --- a/src/main/java/net/errorcraft/itematic/item/group/entry/provider/ItemGroupEntryProviders.java +++ b/src/main/java/net/errorcraft/itematic/item/group/entry/provider/ItemGroupEntryProviders.java @@ -273,7 +273,7 @@ public static void bootstrap(Registerable registerable) .add(items.getOrThrow(ItemKeys.TNT)) .add(items.getOrThrow(ItemKeys.END_CRYSTAL)) .add(items.getOrThrow(ItemKeys.SNOWBALL)) - .add(items.getOrThrow(ItemKeys.EGG)) + .add(ItematicItemTags.EGGS) .add(items.getOrThrow(ItemKeys.WIND_CHARGE)) .add(items.getOrThrow(ItemKeys.BOW)) .add(items.getOrThrow(ItemKeys.CROSSBOW)) @@ -322,7 +322,7 @@ public static void bootstrap(Registerable registerable) .add(items.getOrThrow(ItemKeys.STRING)) .add(items.getOrThrow(ItemKeys.FEATHER)) .add(items.getOrThrow(ItemKeys.SNOWBALL)) - .add(items.getOrThrow(ItemKeys.EGG)) + .add(ItematicItemTags.EGGS) .add(items.getOrThrow(ItemKeys.LEATHER)) .add(items.getOrThrow(ItemKeys.RABBIT_HIDE)) .add(items.getOrThrow(ItemKeys.HONEYCOMB)) diff --git a/src/main/java/net/errorcraft/itematic/loot/function/ItematicItemModifierTypes.java b/src/main/java/net/errorcraft/itematic/loot/function/ItematicItemModifierTypes.java index 8dd42133..8d095f41 100644 --- a/src/main/java/net/errorcraft/itematic/loot/function/ItematicItemModifierTypes.java +++ b/src/main/java/net/errorcraft/itematic/loot/function/ItematicItemModifierTypes.java @@ -6,6 +6,7 @@ public class ItematicItemModifierTypes { public static final LootFunctionType DYE = LootFunctionTypesAccessor.register("dye", DyeItemModifier.CODEC); public static final LootFunctionType SET_RANDOM_POTION = LootFunctionTypesAccessor.register("set_random_potion", SetRandomPotionItemModifier.CODEC); + public static final LootFunctionType SPLIT = LootFunctionTypesAccessor.register("split", SplitItemModifier.CODEC); private ItematicItemModifierTypes() {} diff --git a/src/main/java/net/errorcraft/itematic/loot/function/SplitItemModifier.java b/src/main/java/net/errorcraft/itematic/loot/function/SplitItemModifier.java new file mode 100644 index 00000000..13591201 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/loot/function/SplitItemModifier.java @@ -0,0 +1,45 @@ +package net.errorcraft.itematic.loot.function; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.condition.LootCondition; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.function.ConditionalLootFunction; +import net.minecraft.loot.function.LootFunctionType; +import net.minecraft.loot.provider.number.ConstantLootNumberProvider; +import net.minecraft.loot.provider.number.LootNumberProvider; +import net.minecraft.loot.provider.number.LootNumberProviderTypes; + +import java.util.List; + +public class SplitItemModifier extends ConditionalLootFunction { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> addConditionsField(instance).and( + LootNumberProviderTypes.CODEC.fieldOf("count").forGetter(split -> split.count) + ).apply(instance, SplitItemModifier::new)); + + private final LootNumberProvider count; + + public SplitItemModifier(LootNumberProvider count) { + this(List.of(), count); + } + + public SplitItemModifier(List conditions, LootNumberProvider count) { + super(conditions); + this.count = count; + } + + public static Builder builder(int count) { + return builder(conditions -> new SplitItemModifier(ConstantLootNumberProvider.create(count))); + } + + @Override + public LootFunctionType getType() { + return ItematicItemModifierTypes.SPLIT; + } + + @Override + protected ItemStack process(ItemStack stack, LootContext context) { + return stack.split(this.count.nextInt(context)); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/component/type/LodestoneTrackerComponentExtender.java b/src/main/java/net/errorcraft/itematic/mixin/component/type/LodestoneTrackerComponentExtender.java new file mode 100644 index 00000000..17e29440 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/component/type/LodestoneTrackerComponentExtender.java @@ -0,0 +1,27 @@ +package net.errorcraft.itematic.mixin.component.type; + +import net.errorcraft.itematic.item.data.InventoryTickListener; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LodestoneTrackerComponent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(LodestoneTrackerComponent.class) +public abstract class LodestoneTrackerComponentExtender implements InventoryTickListener { + @Shadow + public abstract LodestoneTrackerComponent forWorld(ServerWorld world); + + @Override + @SuppressWarnings("ConstantValue") + public void itematic$onInventoryTick(ServerWorld world, ItemStack stack, Entity owner, @Nullable EquipmentSlot slot) { + LodestoneTrackerComponent newTracker = this.forWorld(world); + if ((Object) this != newTracker) { + stack.set(DataComponentTypes.LODESTONE_TRACKER, newTracker); + } + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/component/type/MapIdComponentExtender.java b/src/main/java/net/errorcraft/itematic/mixin/component/type/MapIdComponentExtender.java new file mode 100644 index 00000000..3f63f489 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/component/type/MapIdComponentExtender.java @@ -0,0 +1,32 @@ +package net.errorcraft.itematic.mixin.component.type; + +import net.errorcraft.itematic.item.component.components.MapHolderItemComponent; +import net.errorcraft.itematic.item.data.InventoryTickListener; +import net.minecraft.component.type.MapIdComponent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.map.MapState; +import net.minecraft.server.world.ServerWorld; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(MapIdComponent.class) +public class MapIdComponentExtender implements InventoryTickListener { + @Override + public void itematic$onInventoryTick(ServerWorld world, ItemStack stack, Entity owner, @Nullable EquipmentSlot slot) { + MapState mapState = world.getMapState((MapIdComponent)(Object) this); + if (mapState == null) { + return; + } + + if (owner instanceof PlayerEntity playerOwner) { + mapState.update(playerOwner, stack); + } + + if (!mapState.locked && slot != null && slot.getType() == EquipmentSlot.Type.HAND) { + MapHolderItemComponent.DUMMY.updateColors(world, owner, mapState); + } + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/EntityAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/entity/EntityAccessor.java new file mode 100644 index 00000000..a04f3cec --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/EntityAccessor.java @@ -0,0 +1,12 @@ +package net.errorcraft.itematic.mixin.entity; + +import net.minecraft.component.ComponentsAccess; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Entity.class) +public interface EntityAccessor { + @Invoker("copyComponentsFrom") + void itematic$copyComponentsFrom(ComponentsAccess from); +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/mob/ZombieEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/mob/ZombieEntityExtender.java index d39e7320..a89993cf 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/mob/ZombieEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/mob/ZombieEntityExtender.java @@ -14,6 +14,7 @@ import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -25,17 +26,6 @@ protected ZombieEntityExtender(EntityType entityType, W super(entityType, world); } - @Redirect( - method = "canPickupItem", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z" - ) - ) - private boolean isOfForEggUseRegistryKeyCheck(ItemStack instance, Item item) { - return instance.itematic$isOf(ItemKeys.EGG); - } - @ModifyExpressionValue( method = "initialize", at = @At( @@ -113,7 +103,8 @@ private ItemStack newItemStackForIronSwordUseCreateStack(ItemConvertible item) { slice = @Slice( from = @At( value = "FIELD", - target = "Lnet/minecraft/item/Items;IRON_SWORD:Lnet/minecraft/item/Item;" + target = "Lnet/minecraft/item/Items;IRON_SWORD:Lnet/minecraft/item/Item;", + opcode = Opcodes.GETSTATIC ) ) ) diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java index 85b38607..03ea4c7b 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/player/PlayerEntityExtender.java @@ -95,7 +95,7 @@ private void neverSetEmptyStack(PlayerEntity instance, Hand hand, ItemStack stac ) ) private double multiplyByAttackSpeedMultiplier(double original) { - return this.inventory.getMainHandStack().itematic$attackSpeedMultiplier() * original; + return this.getMainHandStack().itematic$attackSpeedMultiplier() * original; } @Redirect( diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/EggEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/EggEntityExtender.java index e874ce67..e5acd137 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/EggEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/thrown/EggEntityExtender.java @@ -1,20 +1,51 @@ package net.errorcraft.itematic.mixin.entity.projectile.thrown; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import net.errorcraft.itematic.item.ItemKeys; +import net.minecraft.component.ComponentsAccess; +import net.minecraft.component.DataComponentTypes; import net.minecraft.entity.EntityType; +import net.minecraft.entity.passive.ChickenVariant; import net.minecraft.entity.projectile.thrown.EggEntity; import net.minecraft.entity.projectile.thrown.ThrownItemEntity; import net.minecraft.item.Item; import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.LazyRegistryEntryReference; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; @Mixin(EggEntity.class) public abstract class EggEntityExtender extends ThrownItemEntityExtender { + @Unique + private LazyRegistryEntryReference chickenVariant; + public EggEntityExtender(EntityType entityType, World world) { super(entityType, world); } + @Override + protected void copyComponentsFrom(ComponentsAccess from) { + super.copyComponentsFrom(from); + this.chickenVariant = from.get(DataComponentTypes.CHICKEN_VARIANT); + } + + @ModifyExpressionValue( + method = "onCollision", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;" + ) + ) + private Object getChickenVariantPossiblyUseDefault(Object original) { + if (original != null) { + return original; + } + + return this.chickenVariant; + } + @Override protected RegistryKey getDefaultItemKey() { return ItemKeys.EGG; 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 bec388f6..fb0aed1d 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java @@ -14,6 +14,7 @@ import net.errorcraft.itematic.item.component.ItemComponentType; import net.errorcraft.itematic.item.component.ItemComponentTypes; import net.errorcraft.itematic.item.component.components.BlockItemComponent; +import net.errorcraft.itematic.item.data.InventoryTickListener; import net.errorcraft.itematic.item.event.ItemEvent; import net.errorcraft.itematic.item.event.ItemEventMap; import net.errorcraft.itematic.item.event.ItemEvents; @@ -383,15 +384,13 @@ public void finishUsingUseItemComponent(ItemStack stack, World world, LivingEnti info.setReturnValue(stackExchanger.result()); } - /** - * @author ErrorCraft - * @reason Uses the ItemComponent implementation for data-driven items. - */ - @Overwrite - public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) { - for (ItemComponent component : this.itemComponents) { - component.inventoryTick(stack, world, entity, slot, selected); - } + @Inject( + method = "inventoryTick", + at = @At("HEAD") + ) + public void callInventoryTickListeners(ItemStack stack, ServerWorld world, Entity entity, EquipmentSlot slot, CallbackInfo info) { + stack.streamAll(InventoryTickListener.class) + .forEach(inventoryTickListener -> inventoryTickListener.itematic$onInventoryTick(world, stack, entity, slot)); } /** @@ -468,17 +467,6 @@ private boolean isCorrectForDropsPassItemStack(ToolComponent instance, BlockStat return instance.itematic$isCorrectForDrops(stack, state); } - @Inject( - method = "hasGlint", - at = @At("HEAD"), - cancellable = true - ) - public void checkPointableItemComponent(ItemStack stack, CallbackInfoReturnable info) { - if (this.itematic$hasBehavior(ItemComponentTypes.POINTABLE) && stack.contains(DataComponentTypes.LODESTONE_TRACKER)) { - info.setReturnValue(true); - } - } - /** * @author ErrorCraft * @reason Uses the ItemComponent implementation for data-driven items. @@ -538,10 +526,8 @@ public final String getTranslationKey() { cancellable = true ) public void getName(ItemStack stack, CallbackInfoReturnable info) { - this.itematic$getBehavior(ItemComponentTypes.POINTABLE) - .flatMap(c -> c.lodestoneTranslationKey(stack)) - .or(() -> this.itematic$getBehavior(ItemComponentTypes.POTION_HOLDER) - .map(c -> c.translationKey(stack, this.display.translationKey()))) + this.itematic$getBehavior(ItemComponentTypes.POTION_HOLDER) + .map(c -> c.translationKey(stack, this.display.translationKey())) .or(() -> this.itematic$getBehavior(ItemComponentTypes.BANNER_PATTERN_HOLDER) .flatMap(c -> c.translationKey(stack, this.display.translationKey()))) .map(Text::translatable) diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/ModifyItemAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/ModifyItemAction.java index 32e2b286..b2450ef4 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/ModifyItemAction.java +++ b/src/main/java/net/errorcraft/itematic/world/action/actions/ModifyItemAction.java @@ -2,21 +2,39 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.item.ItemStackUtil; 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.ItemStackTarget; import net.minecraft.item.ItemStack; import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.loot.function.AndLootFunction; import net.minecraft.loot.function.LootFunction; import net.minecraft.loot.function.LootFunctionTypes; -public record ModifyItemAction(LootFunction itemModifier) implements Action { +import java.util.stream.Stream; + +public record ModifyItemAction(ItemStackTarget stack, LootFunction itemModifier) implements Action { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ItemStackTarget.CODEC.optionalFieldOf("stack", ItemStackTarget.TOOL).forGetter(ModifyItemAction::stack), LootFunctionTypes.CODEC.fieldOf("item_modifier").forGetter(ModifyItemAction::itemModifier) ).apply(instance, ModifyItemAction::new)); + public static ModifyItemAction of(ItemStackTarget stack, LootFunction.Builder itemModifier) { + return new ModifyItemAction(stack, itemModifier.build()); + } + + public static ModifyItemAction of(ItemStackTarget stack, LootFunction.Builder... itemModifiers) { + AndLootFunction itemModifier = AndLootFunction.create( + Stream.of(itemModifiers) + .map(LootFunction.Builder::build) + .toList() + ); + return new ModifyItemAction(stack, itemModifier); + } + @Override public ActionType type() { return ActionTypes.MODIFY_ITEM; @@ -24,8 +42,8 @@ public ActionType type() { @Override public boolean execute(ActionContext context) { - ItemStack stack = context.get(LootContextParameters.TOOL); - if (stack == null || stack.isEmpty()) { + ItemStack stack = this.stack.get(context); + if (ItemStackUtil.isNullOrEmpty(stack)) { return false; } diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/SetItemPointerLocationAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/SetItemPointerLocationAction.java index 8ea0b2cd..8aad98ea 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/SetItemPointerLocationAction.java +++ b/src/main/java/net/errorcraft/itematic/world/action/actions/SetItemPointerLocationAction.java @@ -2,26 +2,29 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.item.ItemStackUtil; 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.ItemStackTarget; import net.errorcraft.itematic.world.action.context.PositionTarget; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LodestoneTrackerComponent; import net.minecraft.item.ItemStack; -import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.GlobalPos; import java.util.Optional; -public record SetItemPointerLocationAction(PositionTarget position) implements Action { +public record SetItemPointerLocationAction(ItemStackTarget stack, PositionTarget position) implements Action { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ItemStackTarget.CODEC.optionalFieldOf("stack", ItemStackTarget.TOOL).forGetter(SetItemPointerLocationAction::stack), PositionTarget.CODEC.fieldOf("position").forGetter(SetItemPointerLocationAction::position) ).apply(instance, SetItemPointerLocationAction::new)); - public static SetItemPointerLocationAction of(PositionTarget position) { - return new SetItemPointerLocationAction(position); + public static SetItemPointerLocationAction of(ItemStackTarget stack, PositionTarget position) { + return new SetItemPointerLocationAction(stack, position); } @Override @@ -31,23 +34,23 @@ public ActionType type() { @Override public boolean execute(ActionContext context) { - ItemStack stack = context.get(LootContextParameters.TOOL); - if (stack == null || stack.isEmpty()) { + ItemStack stack = this.stack.get(context); + if (ItemStackUtil.isNullOrEmpty(stack)) { return false; } - ItemStack resultStack = stack.split(1); - resultStack.set( + BlockPos pos = context.get(this.position.parameter(), BlockPos::ofFloored); + if (pos == null) { + return false; + } + + stack.set( DataComponentTypes.LODESTONE_TRACKER, new LodestoneTrackerComponent( - Optional.of(GlobalPos.create( - context.world().getRegistryKey(), - context.getBlockPos(this.position.parameter()) - )), + Optional.of(GlobalPos.create(context.world().getRegistryKey(), pos)), true ) ); - context.exchangeStack(resultStack); return true; } } diff --git a/src/main/java/net/errorcraft/itematic/world/action/context/ItemStackTarget.java b/src/main/java/net/errorcraft/itematic/world/action/context/ItemStackTarget.java new file mode 100644 index 00000000..acdb58d1 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/world/action/context/ItemStackTarget.java @@ -0,0 +1,34 @@ +package net.errorcraft.itematic.world.action.context; + +import com.mojang.serialization.Codec; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.util.StringIdentifiable; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +public enum ItemStackTarget implements StringIdentifiable { + TOOL("tool", context -> context.get(LootContextParameters.TOOL)), + RESULT("result", ActionContext::resultStack); + + public static final Codec CODEC = StringIdentifiable.createCodec(ItemStackTarget::values); + + private final String name; + private final Function itemStackSupplier; + + ItemStackTarget(String name, Function itemStackSupplier) { + this.name = name; + this.itemStackSupplier = itemStackSupplier; + } + + @Override + public String asString() { + return this.name; + } + + @Nullable + public ItemStack get(ActionContext context) { + return this.itemStackSupplier.apply(context); + } +} diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index fd90bbbb..6c25a8f7 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -89,6 +89,8 @@ "component.type.ConsumableComponentExtender", "component.type.DyedColorComponentExtender", "component.type.EquippableComponentExtender", + "component.type.LodestoneTrackerComponentExtender", + "component.type.MapIdComponentExtender", "component.type.ToolComponentExtender", "component.type.ToolComponentExtender$RuleExtender", "datafixer.SchemasExtender", @@ -96,6 +98,7 @@ "enchantment.EnchantmentHelperExtender", "entity.BucketableExtender", "entity.CrossbowUserExtender", + "entity.EntityAccessor", "entity.EntityExtender", "entity.EntityTypeExtender", "entity.EntityTypeExtender$BuilderExtender", From ddfa7a4c850e3865303bd76218fe040ca04b6dce Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 03:54:56 +0200 Subject: [PATCH 06/12] Port to 25w07a --- gradle.properties | 6 +- .../render/item/HeldItemRendererExtender.java | 2 +- .../data/server/tag/TradeTagProvider.java | 122 +++++--- .../tags/trade/cartographer_apprentice.json | 8 +- .../tags/trade/cartographer_expert.json | 31 +- .../tags/trade/cartographer_journeyman.json | 3 +- .../tags/trade/cartographer_master.json | 3 +- .../tags/trade/cartographer_novice.json | 2 +- .../tags/trade/librarian_novice.json | 2 +- .../tags/trade/shepherd_apprentice.json | 32 +- .../tags/trade/wandering_trader_buying.json | 10 + .../tags/trade/wandering_trader_regular.json | 11 +- .../tags/trade/wandering_trader_special.json | 15 +- .../minecraft/trade/buy_baked_potato.json | 13 + .../trade/buy_fermented_spider_eye.json | 13 + .../data/minecraft/trade/buy_hay_block.json | 12 + .../data/minecraft/trade/buy_milk_bucket.json | 13 + .../trade/buy_paper_cartographer.json | 14 + ...uy_paper.json => buy_paper_librarian.json} | 0 .../minecraft/trade/buy_water_bottle.json | 16 + .../minecraft/trade/buy_water_bucket.json | 13 + .../data/minecraft/trade/sell_acacia_log.json | 13 + .../data/minecraft/trade/sell_birch_log.json | 13 + .../trade/sell_black_banner_cartographer.json | 24 ++ ...ool.json => sell_black_wool_shepherd.json} | 0 .../trade/sell_blue_banner_cartographer.json | 27 ++ ...wool.json => sell_blue_wool_shepherd.json} | 0 .../trade/sell_brown_banner_cartographer.json | 27 ++ ...ool.json => sell_brown_wool_shepherd.json} | 0 .../data/minecraft/trade/sell_cherry_log.json | 13 + .../trade/sell_cyan_banner_cartographer.json | 27 ++ ...wool.json => sell_cyan_wool_shepherd.json} | 0 .../minecraft/trade/sell_dark_oak_log.json | 13 + .../trade/sell_desert_village_map.json | 45 +++ ...chanted_iron_pickaxe_wandering_trader.json | 21 ++ .../minecraft/trade/sell_firefly_bush.json | 12 + .../trade/sell_gray_banner_cartographer.json | 24 ++ ...wool.json => sell_gray_wool_shepherd.json} | 0 .../trade/sell_green_banner_cartographer.json | 28 ++ ...ool.json => sell_green_wool_shepherd.json} | 0 .../data/minecraft/trade/sell_jungle_log.json | 13 + .../trade/sell_jungle_temple_map.json | 46 +++ .../sell_light_blue_banner_cartographer.json | 27 ++ ...son => sell_light_blue_wool_shepherd.json} | 0 ...son => sell_light_gray_wool_shepherd.json} | 0 .../trade/sell_lime_banner_cartographer.json | 27 ++ ...wool.json => sell_lime_wool_shepherd.json} | 0 .../trade/sell_long_invisibility_potion.json | 17 ++ .../sell_magenta_banner_cartographer.json | 24 ++ ...l.json => sell_magenta_wool_shepherd.json} | 0 .../minecraft/trade/sell_mangrove_log.json | 13 + .../minecraft/trade/sell_monument_map.json | 2 +- .../data/minecraft/trade/sell_oak_log.json | 13 + .../minecraft/trade/sell_open_eyeblossom.json | 12 + .../sell_orange_banner_cartographer.json | 27 ++ ...ol.json => sell_orange_wool_shepherd.json} | 0 .../trade/sell_pale_hanging_moss.json | 12 + .../minecraft/trade/sell_pale_moss_block.json | 13 + .../minecraft/trade/sell_pale_oak_log.json | 13 + .../trade/sell_pale_oak_sapling.json | 13 + .../trade/sell_pink_banner_cartographer.json | 27 ++ ...wool.json => sell_pink_wool_shepherd.json} | 0 .../trade/sell_plains_village_map.json | 47 +++ .../sell_purple_banner_cartographer.json | 27 ++ ...ol.json => sell_purple_wool_shepherd.json} | 0 .../trade/sell_red_banner_cartographer.json | 27 ++ ..._wool.json => sell_red_wool_shepherd.json} | 0 .../trade/sell_savanna_village_map.json | 46 +++ .../trade/sell_snowy_village_map.json | 45 +++ .../data/minecraft/trade/sell_spruce_log.json | 13 + .../minecraft/trade/sell_swamp_hut_map.json | 46 +++ .../trade/sell_taiga_village_map.json | 46 +++ .../minecraft/trade/sell_tall_dry_grass.json | 12 + .../trade/sell_trial_chamber_map.json | 32 ++ .../trade/sell_white_banner_cartographer.json | 27 ++ ...ool.json => sell_white_wool_shepherd.json} | 0 .../minecraft/trade/sell_wildflowers.json | 12 + .../sell_yellow_banner_cartographer.json | 27 ++ ...ol.json => sell_yellow_wool_shepherd.json} | 0 .../net/errorcraft/itematic/Itematic.java | 2 + .../BannerPatternHolderItemComponent.java | 2 +- .../passive/MerchantEntityExtender.java | 12 +- .../WanderingTraderEntityExtender.java | 3 +- .../FireworkRocketEntityExtender.java | 19 +- .../mixin/stat/ServerStatHandlerExtender.java | 62 ++-- .../mixin/village/VillagerDataExtender.java | 2 +- .../ItematicEntitySubPredicateTypes.java | 18 ++ .../entity/VillagerEntitySubPredicate.java | 38 +++ .../itematic/village/trade/Trade.java | 48 ++- .../itematic/village/trade/TradeTags.java | 5 +- .../itematic/village/trade/Trades.java | 273 ++++++++++++++---- 91 files changed, 1627 insertions(+), 191 deletions(-) create mode 100644 src/main/generated/data/minecraft/tags/trade/wandering_trader_buying.json create mode 100644 src/main/generated/data/minecraft/trade/buy_baked_potato.json create mode 100644 src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json create mode 100644 src/main/generated/data/minecraft/trade/buy_hay_block.json create mode 100644 src/main/generated/data/minecraft/trade/buy_milk_bucket.json create mode 100644 src/main/generated/data/minecraft/trade/buy_paper_cartographer.json rename src/main/generated/data/minecraft/trade/{buy_paper.json => buy_paper_librarian.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/buy_water_bottle.json create mode 100644 src/main/generated/data/minecraft/trade/buy_water_bucket.json create mode 100644 src/main/generated/data/minecraft/trade/sell_acacia_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_birch_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_black_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_black_wool.json => sell_black_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_blue_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_blue_wool.json => sell_blue_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_brown_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_brown_wool.json => sell_brown_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_cherry_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_cyan_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_cyan_wool.json => sell_cyan_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_dark_oak_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_desert_village_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_enchanted_iron_pickaxe_wandering_trader.json create mode 100644 src/main/generated/data/minecraft/trade/sell_firefly_bush.json create mode 100644 src/main/generated/data/minecraft/trade/sell_gray_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_gray_wool.json => sell_gray_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_green_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_green_wool.json => sell_green_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_jungle_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_jungle_temple_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_light_blue_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_light_blue_wool.json => sell_light_blue_wool_shepherd.json} (100%) rename src/main/generated/data/minecraft/trade/{sell_light_gray_wool.json => sell_light_gray_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_lime_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_lime_wool.json => sell_lime_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_long_invisibility_potion.json create mode 100644 src/main/generated/data/minecraft/trade/sell_magenta_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_magenta_wool.json => sell_magenta_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_mangrove_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_oak_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_open_eyeblossom.json create mode 100644 src/main/generated/data/minecraft/trade/sell_orange_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_orange_wool.json => sell_orange_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_pale_hanging_moss.json create mode 100644 src/main/generated/data/minecraft/trade/sell_pale_moss_block.json create mode 100644 src/main/generated/data/minecraft/trade/sell_pale_oak_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_pale_oak_sapling.json create mode 100644 src/main/generated/data/minecraft/trade/sell_pink_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_pink_wool.json => sell_pink_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_plains_village_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_purple_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_purple_wool.json => sell_purple_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_red_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_red_wool.json => sell_red_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_savanna_village_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_snowy_village_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_spruce_log.json create mode 100644 src/main/generated/data/minecraft/trade/sell_swamp_hut_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_taiga_village_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_tall_dry_grass.json create mode 100644 src/main/generated/data/minecraft/trade/sell_trial_chamber_map.json create mode 100644 src/main/generated/data/minecraft/trade/sell_white_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_white_wool.json => sell_white_wool_shepherd.json} (100%) create mode 100644 src/main/generated/data/minecraft/trade/sell_wildflowers.json create mode 100644 src/main/generated/data/minecraft/trade/sell_yellow_banner_cartographer.json rename src/main/generated/data/minecraft/trade/{sell_yellow_wool.json => sell_yellow_wool_shepherd.json} (100%) create mode 100644 src/main/java/net/errorcraft/itematic/predicate/entity/ItematicEntitySubPredicateTypes.java create mode 100644 src/main/java/net/errorcraft/itematic/predicate/entity/VillagerEntitySubPredicate.java diff --git a/gradle.properties b/gradle.properties index 8c9f8702..e927566f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w06a - yarn_mappings=25w06a+build.7 + minecraft_version=25w07a + yarn_mappings=25w07a+build.12 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.116.0+1.21.5 + fabric_version=0.117.3+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java index 8c196845..2960ef95 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java @@ -136,7 +136,7 @@ private int getUseTimeLeftForCrossbowUseNegatedUsedTicks(AbstractClientPlayerEnt slice = @Slice( from = @At( value = "INVOKE", - target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", ordinal = 0 ) ) diff --git a/src/datagen/java/net/errorcraft/itematic/data/server/tag/TradeTagProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/tag/TradeTagProvider.java index 23bd7670..1f25f09a 100644 --- a/src/datagen/java/net/errorcraft/itematic/data/server/tag/TradeTagProvider.java +++ b/src/datagen/java/net/errorcraft/itematic/data/server/tag/TradeTagProvider.java @@ -70,22 +70,22 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.BUY_BLACK_DYE) .add(Trades.BUY_LIGHT_BLUE_DYE) .add(Trades.BUY_LIME_DYE) - .add(Trades.SELL_WHITE_WOOL) - .add(Trades.SELL_ORANGE_WOOL) - .add(Trades.SELL_MAGENTA_WOOL) - .add(Trades.SELL_LIGHT_BLUE_WOOL) - .add(Trades.SELL_YELLOW_WOOL) - .add(Trades.SELL_LIME_WOOL) - .add(Trades.SELL_PINK_WOOL) - .add(Trades.SELL_GRAY_WOOL) - .add(Trades.SELL_LIGHT_GRAY_WOOL) - .add(Trades.SELL_CYAN_WOOL) - .add(Trades.SELL_PURPLE_WOOL) - .add(Trades.SELL_BLUE_WOOL) - .add(Trades.SELL_BROWN_WOOL) - .add(Trades.SELL_GREEN_WOOL) - .add(Trades.SELL_RED_WOOL) - .add(Trades.SELL_BLACK_WOOL) + .add(Trades.SELL_WHITE_WOOL_SHEPHERD) + .add(Trades.SELL_ORANGE_WOOL_SHEPHERD) + .add(Trades.SELL_MAGENTA_WOOL_SHEPHERD) + .add(Trades.SELL_LIGHT_BLUE_WOOL_SHEPHERD) + .add(Trades.SELL_YELLOW_WOOL_SHEPHERD) + .add(Trades.SELL_LIME_WOOL_SHEPHERD) + .add(Trades.SELL_PINK_WOOL_SHEPHERD) + .add(Trades.SELL_GRAY_WOOL_SHEPHERD) + .add(Trades.SELL_LIGHT_GRAY_WOOL_SHEPHERD) + .add(Trades.SELL_CYAN_WOOL_SHEPHERD) + .add(Trades.SELL_PURPLE_WOOL_SHEPHERD) + .add(Trades.SELL_BLUE_WOOL_SHEPHERD) + .add(Trades.SELL_BROWN_WOOL_SHEPHERD) + .add(Trades.SELL_GREEN_WOOL_SHEPHERD) + .add(Trades.SELL_RED_WOOL_SHEPHERD) + .add(Trades.SELL_BLACK_WOOL_SHEPHERD) .add(Trades.SELL_WHITE_CARPET) .add(Trades.SELL_ORANGE_CARPET) .add(Trades.SELL_MAGENTA_CARPET) @@ -167,7 +167,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.SELL_ENCHANTED_CROSSBOW) .add(Trades.SELL_TIPPED_ARROW); this.getOrCreateTagBuilder(TradeTags.LIBRARIAN_NOVICE) - .add(Trades.BUY_PAPER) + .add(Trades.BUY_PAPER_LIBRARIAN) .add(Trades.SELL_ENCHANTED_BOOK_NOVICE) .add(Trades.SELL_BOOKSHELF); this.getOrCreateTagBuilder(TradeTags.LIBRARIAN_APPRENTICE) @@ -186,34 +186,41 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { this.getOrCreateTagBuilder(TradeTags.LIBRARIAN_MASTER) .add(Trades.SELL_NAME_TAG); this.getOrCreateTagBuilder(TradeTags.CARTOGRAPHER_NOVICE) - .add(Trades.BUY_PAPER) + .add(Trades.BUY_PAPER_CARTOGRAPHER) .add(Trades.SELL_MAP); this.getOrCreateTagBuilder(TradeTags.CARTOGRAPHER_APPRENTICE) .add(Trades.BUY_GLASS_PANE) - .add(Trades.SELL_MONUMENT_MAP); + .add(Trades.SELL_TAIGA_VILLAGE_MAP) + .add(Trades.SELL_SWAMP_HUT_MAP) + .add(Trades.SELL_SNOWY_VILLAGE_MAP) + .add(Trades.SELL_SAVANNA_VILLAGE_MAP) + .add(Trades.SELL_PLAINS_VILLAGE_MAP) + .add(Trades.SELL_JUNGLE_TEMPLE_MAP) + .add(Trades.SELL_DESERT_VILLAGE_MAP); this.getOrCreateTagBuilder(TradeTags.CARTOGRAPHER_JOURNEYMAN) .add(Trades.BUY_COMPASS) - .add(Trades.SELL_MANSION_MAP); + .add(Trades.SELL_MONUMENT_MAP) + .add(Trades.SELL_TRIAL_CHAMBER_MAP); this.getOrCreateTagBuilder(TradeTags.CARTOGRAPHER_EXPERT) .add(Trades.SELL_ITEM_FRAME) - .add(Trades.SELL_WHITE_BANNER) - .add(Trades.SELL_BLUE_BANNER) - .add(Trades.SELL_LIGHT_BLUE_BANNER) - .add(Trades.SELL_RED_BANNER) - .add(Trades.SELL_PINK_BANNER) - .add(Trades.SELL_GREEN_BANNER) - .add(Trades.SELL_LIME_BANNER) - .add(Trades.SELL_GRAY_BANNER) - .add(Trades.SELL_BLACK_BANNER) - .add(Trades.SELL_PURPLE_BANNER) - .add(Trades.SELL_MAGENTA_BANNER) - .add(Trades.SELL_CYAN_BANNER) - .add(Trades.SELL_BROWN_BANNER) - .add(Trades.SELL_YELLOW_BANNER) - .add(Trades.SELL_ORANGE_BANNER) - .add(Trades.SELL_LIGHT_GRAY_BANNER); + .add(Trades.SELL_BLUE_BANNER_CARTOGRAPHER) + .add(Trades.SELL_WHITE_BANNER_CARTOGRAPHER) + .add(Trades.SELL_RED_BANNER_CARTOGRAPHER) + .add(Trades.SELL_GREEN_BANNER_CARTOGRAPHER) + .add(Trades.SELL_LIME_BANNER_CARTOGRAPHER) + .add(Trades.SELL_PURPLE_BANNER_CARTOGRAPHER) + .add(Trades.SELL_CYAN_BANNER_CARTOGRAPHER) + .add(Trades.SELL_YELLOW_BANNER_CARTOGRAPHER) + .add(Trades.SELL_ORANGE_BANNER_CARTOGRAPHER) + .add(Trades.SELL_BROWN_BANNER_CARTOGRAPHER) + .add(Trades.SELL_MAGENTA_BANNER_CARTOGRAPHER) + .add(Trades.SELL_LIGHT_BLUE_BANNER_CARTOGRAPHER) + .add(Trades.SELL_PINK_BANNER_CARTOGRAPHER) + .add(Trades.SELL_GRAY_BANNER_CARTOGRAPHER) + .add(Trades.SELL_BLACK_BANNER_CARTOGRAPHER); this.getOrCreateTagBuilder(TradeTags.CARTOGRAPHER_MASTER) - .add(Trades.SELL_GLOBE_BANNER_PATTERN); + .add(Trades.SELL_GLOBE_BANNER_PATTERN) + .add(Trades.SELL_MANSION_MAP); this.getOrCreateTagBuilder(TradeTags.CLERIC_NOVICE) .add(Trades.BUY_ROTTEN_FLESH) .add(Trades.SELL_REDSTONE); @@ -372,7 +379,32 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { this.getOrCreateTagBuilder(TradeTags.MASON_MASTER) .add(Trades.SELL_QUARTZ_PILLAR) .add(Trades.SELL_QUARTZ_BLOCK); + this.getOrCreateTagBuilder(TradeTags.WANDERING_TRADER_BUYING) + .add(Trades.BUY_WATER_BOTTLE) + .add(Trades.BUY_WATER_BUCKET) + .add(Trades.BUY_MILK_BUCKET) + .add(Trades.BUY_FERMENTED_SPIDER_EYE) + .add(Trades.BUY_BAKED_POTATO) + .add(Trades.BUY_HAY_BLOCK); + this.getOrCreateTagBuilder(TradeTags.WANDERING_TRADER_SPECIAL) + .add(Trades.SELL_PACKED_ICE) + .add(Trades.SELL_BLUE_ICE) + .add(Trades.SELL_GUNPOWDER) + .add(Trades.SELL_PODZOL) + .add(Trades.SELL_ACACIA_LOG) + .add(Trades.SELL_BIRCH_LOG) + .add(Trades.SELL_DARK_OAK_LOG) + .add(Trades.SELL_JUNGLE_LOG) + .add(Trades.SELL_OAK_LOG) + .add(Trades.SELL_SPRUCE_LOG) + .add(Trades.SELL_CHERRY_LOG) + .add(Trades.SELL_MANGROVE_LOG) + .add(Trades.SELL_PALE_OAK_LOG) + .add(Trades.SELL_ENCHANTED_IRON_PICKAXE_WANDERING_TRADER) + .add(Trades.SELL_LONG_INVISIBILITY_POTION); this.getOrCreateTagBuilder(TradeTags.WANDERING_TRADER_REGULAR) + .add(Trades.SELL_TROPICAL_FISH_BUCKET) + .add(Trades.SELL_PUFFERFISH_BUCKET) .add(Trades.SELL_SEA_PICKLE) .add(Trades.SELL_SLIME_BALL) .add(Trades.SELL_GLOWSTONE_WANDERING_TRADER) @@ -394,6 +426,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.SELL_OXEYE_DAISY) .add(Trades.SELL_CORNFLOWER) .add(Trades.SELL_LILY_OF_THE_VALLEY) + .add(Trades.SELL_OPEN_EYEBLOSSOM) .add(Trades.SELL_WHEAT_SEEDS) .add(Trades.SELL_BEETROOT_SEEDS) .add(Trades.SELL_PUMPKIN_SEEDS) @@ -405,6 +438,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.SELL_OAK_SAPLING) .add(Trades.SELL_SPRUCE_SAPLING) .add(Trades.SELL_CHERRY_SAPLING) + .add(Trades.SELL_PALE_OAK_SAPLING) .add(Trades.SELL_MANGROVE_PROPAGULE) .add(Trades.SELL_RED_DYE) .add(Trades.SELL_WHITE_DYE) @@ -428,6 +462,7 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.SELL_HORN_CORAL_BLOCK) .add(Trades.SELL_TUBE_CORAL_BLOCK) .add(Trades.SELL_VINE) + .add(Trades.SELL_PALE_HANGING_MOSS) .add(Trades.SELL_BROWN_MUSHROOM) .add(Trades.SELL_RED_MUSHROOM) .add(Trades.SELL_LILY_PAD) @@ -436,13 +471,10 @@ protected void configure(RegistryWrapper.WrapperLookup lookup) { .add(Trades.SELL_RED_SAND) .add(Trades.SELL_POINTED_DRIPSTONE) .add(Trades.SELL_ROOTED_DIRT) - .add(Trades.SELL_MOSS_BLOCK); - this.getOrCreateTagBuilder(TradeTags.WANDERING_TRADER_SPECIAL) - .add(Trades.SELL_TROPICAL_FISH_BUCKET) - .add(Trades.SELL_PUFFERFISH_BUCKET) - .add(Trades.SELL_PACKED_ICE) - .add(Trades.SELL_BLUE_ICE) - .add(Trades.SELL_GUNPOWDER) - .add(Trades.SELL_PODZOL); + .add(Trades.SELL_MOSS_BLOCK) + .add(Trades.SELL_PALE_MOSS_BLOCK) + .add(Trades.SELL_WILDFLOWERS) + .add(Trades.SELL_TALL_DRY_GRASS) + .add(Trades.SELL_FIREFLY_BUSH); } } diff --git a/src/main/generated/data/minecraft/tags/trade/cartographer_apprentice.json b/src/main/generated/data/minecraft/tags/trade/cartographer_apprentice.json index 881e7cfc..ea494db0 100644 --- a/src/main/generated/data/minecraft/tags/trade/cartographer_apprentice.json +++ b/src/main/generated/data/minecraft/tags/trade/cartographer_apprentice.json @@ -1,6 +1,12 @@ { "values": [ "minecraft:buy_glass_pane", - "minecraft:sell_monument_map" + "minecraft:sell_taiga_village_map", + "minecraft:sell_swamp_hut_map", + "minecraft:sell_snowy_village_map", + "minecraft:sell_savanna_village_map", + "minecraft:sell_plains_village_map", + "minecraft:sell_jungle_temple_map", + "minecraft:sell_desert_village_map" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/cartographer_expert.json b/src/main/generated/data/minecraft/tags/trade/cartographer_expert.json index 234b93cf..b7d9c6d9 100644 --- a/src/main/generated/data/minecraft/tags/trade/cartographer_expert.json +++ b/src/main/generated/data/minecraft/tags/trade/cartographer_expert.json @@ -1,21 +1,20 @@ { "values": [ "minecraft:sell_item_frame", - "minecraft:sell_white_banner", - "minecraft:sell_blue_banner", - "minecraft:sell_light_blue_banner", - "minecraft:sell_red_banner", - "minecraft:sell_pink_banner", - "minecraft:sell_green_banner", - "minecraft:sell_lime_banner", - "minecraft:sell_gray_banner", - "minecraft:sell_black_banner", - "minecraft:sell_purple_banner", - "minecraft:sell_magenta_banner", - "minecraft:sell_cyan_banner", - "minecraft:sell_brown_banner", - "minecraft:sell_yellow_banner", - "minecraft:sell_orange_banner", - "minecraft:sell_light_gray_banner" + "minecraft:sell_blue_banner_cartographer", + "minecraft:sell_white_banner_cartographer", + "minecraft:sell_red_banner_cartographer", + "minecraft:sell_green_banner_cartographer", + "minecraft:sell_lime_banner_cartographer", + "minecraft:sell_purple_banner_cartographer", + "minecraft:sell_cyan_banner_cartographer", + "minecraft:sell_yellow_banner_cartographer", + "minecraft:sell_orange_banner_cartographer", + "minecraft:sell_brown_banner_cartographer", + "minecraft:sell_magenta_banner_cartographer", + "minecraft:sell_light_blue_banner_cartographer", + "minecraft:sell_pink_banner_cartographer", + "minecraft:sell_gray_banner_cartographer", + "minecraft:sell_black_banner_cartographer" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/cartographer_journeyman.json b/src/main/generated/data/minecraft/tags/trade/cartographer_journeyman.json index 85a0bba7..6d60ce1b 100644 --- a/src/main/generated/data/minecraft/tags/trade/cartographer_journeyman.json +++ b/src/main/generated/data/minecraft/tags/trade/cartographer_journeyman.json @@ -1,6 +1,7 @@ { "values": [ "minecraft:buy_compass", - "minecraft:sell_mansion_map" + "minecraft:sell_monument_map", + "minecraft:sell_trial_chamber_map" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/cartographer_master.json b/src/main/generated/data/minecraft/tags/trade/cartographer_master.json index 9ee1bf94..adc15db0 100644 --- a/src/main/generated/data/minecraft/tags/trade/cartographer_master.json +++ b/src/main/generated/data/minecraft/tags/trade/cartographer_master.json @@ -1,5 +1,6 @@ { "values": [ - "minecraft:sell_globe_banner_pattern" + "minecraft:sell_globe_banner_pattern", + "minecraft:sell_mansion_map" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/cartographer_novice.json b/src/main/generated/data/minecraft/tags/trade/cartographer_novice.json index 76f94d49..26da7e36 100644 --- a/src/main/generated/data/minecraft/tags/trade/cartographer_novice.json +++ b/src/main/generated/data/minecraft/tags/trade/cartographer_novice.json @@ -1,6 +1,6 @@ { "values": [ - "minecraft:buy_paper", + "minecraft:buy_paper_cartographer", "minecraft:sell_map" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/librarian_novice.json b/src/main/generated/data/minecraft/tags/trade/librarian_novice.json index a8f47236..8bb10593 100644 --- a/src/main/generated/data/minecraft/tags/trade/librarian_novice.json +++ b/src/main/generated/data/minecraft/tags/trade/librarian_novice.json @@ -1,6 +1,6 @@ { "values": [ - "minecraft:buy_paper", + "minecraft:buy_paper_librarian", "minecraft:sell_enchanted_book_novice", "minecraft:sell_bookshelf" ] diff --git a/src/main/generated/data/minecraft/tags/trade/shepherd_apprentice.json b/src/main/generated/data/minecraft/tags/trade/shepherd_apprentice.json index 4f9f5932..3c54b69b 100644 --- a/src/main/generated/data/minecraft/tags/trade/shepherd_apprentice.json +++ b/src/main/generated/data/minecraft/tags/trade/shepherd_apprentice.json @@ -5,22 +5,22 @@ "minecraft:buy_black_dye", "minecraft:buy_light_blue_dye", "minecraft:buy_lime_dye", - "minecraft:sell_white_wool", - "minecraft:sell_orange_wool", - "minecraft:sell_magenta_wool", - "minecraft:sell_light_blue_wool", - "minecraft:sell_yellow_wool", - "minecraft:sell_lime_wool", - "minecraft:sell_pink_wool", - "minecraft:sell_gray_wool", - "minecraft:sell_light_gray_wool", - "minecraft:sell_cyan_wool", - "minecraft:sell_purple_wool", - "minecraft:sell_blue_wool", - "minecraft:sell_brown_wool", - "minecraft:sell_green_wool", - "minecraft:sell_red_wool", - "minecraft:sell_black_wool", + "minecraft:sell_white_wool_shepherd", + "minecraft:sell_orange_wool_shepherd", + "minecraft:sell_magenta_wool_shepherd", + "minecraft:sell_light_blue_wool_shepherd", + "minecraft:sell_yellow_wool_shepherd", + "minecraft:sell_lime_wool_shepherd", + "minecraft:sell_pink_wool_shepherd", + "minecraft:sell_gray_wool_shepherd", + "minecraft:sell_light_gray_wool_shepherd", + "minecraft:sell_cyan_wool_shepherd", + "minecraft:sell_purple_wool_shepherd", + "minecraft:sell_blue_wool_shepherd", + "minecraft:sell_brown_wool_shepherd", + "minecraft:sell_green_wool_shepherd", + "minecraft:sell_red_wool_shepherd", + "minecraft:sell_black_wool_shepherd", "minecraft:sell_white_carpet", "minecraft:sell_orange_carpet", "minecraft:sell_magenta_carpet", diff --git a/src/main/generated/data/minecraft/tags/trade/wandering_trader_buying.json b/src/main/generated/data/minecraft/tags/trade/wandering_trader_buying.json new file mode 100644 index 00000000..8d653f9e --- /dev/null +++ b/src/main/generated/data/minecraft/tags/trade/wandering_trader_buying.json @@ -0,0 +1,10 @@ +{ + "values": [ + "minecraft:buy_water_bottle", + "minecraft:buy_water_bucket", + "minecraft:buy_milk_bucket", + "minecraft:buy_fermented_spider_eye", + "minecraft:buy_baked_potato", + "minecraft:buy_hay_block" + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/wandering_trader_regular.json b/src/main/generated/data/minecraft/tags/trade/wandering_trader_regular.json index 88c3269a..cf07e7cb 100644 --- a/src/main/generated/data/minecraft/tags/trade/wandering_trader_regular.json +++ b/src/main/generated/data/minecraft/tags/trade/wandering_trader_regular.json @@ -1,5 +1,7 @@ { "values": [ + "minecraft:sell_tropical_fish_bucket", + "minecraft:sell_pufferfish_bucket", "minecraft:sell_sea_pickle", "minecraft:sell_slime_ball", "minecraft:sell_glowstone_wandering_trader", @@ -21,6 +23,7 @@ "minecraft:sell_oxeye_daisy", "minecraft:sell_cornflower", "minecraft:sell_lily_of_the_valley", + "minecraft:sell_open_eyeblossom", "minecraft:sell_wheat_seeds", "minecraft:sell_beetroot_seeds", "minecraft:sell_pumpkin_seeds", @@ -32,6 +35,7 @@ "minecraft:sell_oak_sapling", "minecraft:sell_spruce_sapling", "minecraft:sell_cherry_sapling", + "minecraft:sell_pale_oak_sapling", "minecraft:sell_mangrove_propagule", "minecraft:sell_red_dye", "minecraft:sell_white_dye", @@ -55,6 +59,7 @@ "minecraft:sell_horn_coral_block", "minecraft:sell_tube_coral_block", "minecraft:sell_vine", + "minecraft:sell_pale_hanging_moss", "minecraft:sell_brown_mushroom", "minecraft:sell_red_mushroom", "minecraft:sell_lily_pad", @@ -63,6 +68,10 @@ "minecraft:sell_red_sand", "minecraft:sell_pointed_dripstone", "minecraft:sell_rooted_dirt", - "minecraft:sell_moss_block" + "minecraft:sell_moss_block", + "minecraft:sell_pale_moss_block", + "minecraft:sell_wildflowers", + "minecraft:sell_tall_dry_grass", + "minecraft:sell_firefly_bush" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/tags/trade/wandering_trader_special.json b/src/main/generated/data/minecraft/tags/trade/wandering_trader_special.json index 88d01e51..dc712d47 100644 --- a/src/main/generated/data/minecraft/tags/trade/wandering_trader_special.json +++ b/src/main/generated/data/minecraft/tags/trade/wandering_trader_special.json @@ -1,10 +1,19 @@ { "values": [ - "minecraft:sell_tropical_fish_bucket", - "minecraft:sell_pufferfish_bucket", "minecraft:sell_packed_ice", "minecraft:sell_blue_ice", "minecraft:sell_gunpowder", - "minecraft:sell_podzol" + "minecraft:sell_podzol", + "minecraft:sell_acacia_log", + "minecraft:sell_birch_log", + "minecraft:sell_dark_oak_log", + "minecraft:sell_jungle_log", + "minecraft:sell_oak_log", + "minecraft:sell_spruce_log", + "minecraft:sell_cherry_log", + "minecraft:sell_mangrove_log", + "minecraft:sell_pale_oak_log", + "minecraft:sell_enchanted_iron_pickaxe_wandering_trader", + "minecraft:sell_long_invisibility_potion" ] } \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_baked_potato.json b/src/main/generated/data/minecraft/trade/buy_baked_potato.json new file mode 100644 index 00000000..928f325a --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_baked_potato.json @@ -0,0 +1,13 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "count": 4, + "item": "minecraft:baked_potato" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json b/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json new file mode 100644 index 00000000..01fc0133 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 3, + "item": "minecraft:emerald" + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:fermented_spider_eye" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_hay_block.json b/src/main/generated/data/minecraft/trade/buy_hay_block.json new file mode 100644 index 00000000..dbb1ab7f --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_hay_block.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:hay_block" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_milk_bucket.json b/src/main/generated/data/minecraft/trade/buy_milk_bucket.json new file mode 100644 index 00000000..0f0ed124 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_milk_bucket.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 2, + "item": "minecraft:emerald" + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:milk_bucket" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_paper_cartographer.json b/src/main/generated/data/minecraft/trade/buy_paper_cartographer.json new file mode 100644 index 00000000..e4f8366b --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_paper_cartographer.json @@ -0,0 +1,14 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 12, + "price_multiplier": 0.05, + "trade_experience": 2, + "wants": [ + { + "count": 24, + "item": "minecraft:paper" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_paper.json b/src/main/generated/data/minecraft/trade/buy_paper_librarian.json similarity index 100% rename from src/main/generated/data/minecraft/trade/buy_paper.json rename to src/main/generated/data/minecraft/trade/buy_paper_librarian.json diff --git a/src/main/generated/data/minecraft/trade/buy_water_bottle.json b/src/main/generated/data/minecraft/trade/buy_water_bottle.json new file mode 100644 index 00000000..f2ba65af --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_water_bottle.json @@ -0,0 +1,16 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 12, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:potion", + "item_modifier": { + "id": "minecraft:water", + "function": "minecraft:set_potion" + } + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/buy_water_bucket.json b/src/main/generated/data/minecraft/trade/buy_water_bucket.json new file mode 100644 index 00000000..5e7721d0 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_water_bucket.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 2, + "item": "minecraft:emerald" + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:water_bucket" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_acacia_log.json b/src/main/generated/data/minecraft/trade/sell_acacia_log.json new file mode 100644 index 00000000..89b2f8e3 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_acacia_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:acacia_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_birch_log.json b/src/main/generated/data/minecraft/trade/sell_birch_log.json new file mode 100644 index 00000000..649694c7 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_birch_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:birch_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_black_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_black_banner_cartographer.json new file mode 100644 index 00000000..eb23e6e4 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_black_banner_cartographer.json @@ -0,0 +1,24 @@ +{ + "gives": { + "item": "minecraft:black_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": "minecraft:swamp" + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_black_wool.json b/src/main/generated/data/minecraft/trade/sell_black_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_black_wool.json rename to src/main/generated/data/minecraft/trade/sell_black_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_blue_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_blue_banner_cartographer.json new file mode 100644 index 00000000..931c51c3 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_blue_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:blue_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:snow", + "minecraft:taiga" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_blue_wool.json b/src/main/generated/data/minecraft/trade/sell_blue_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_blue_wool.json rename to src/main/generated/data/minecraft/trade/sell_blue_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_brown_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_brown_banner_cartographer.json new file mode 100644 index 00000000..4b048d67 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_brown_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:brown_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:plains", + "minecraft:jungle" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_brown_wool.json b/src/main/generated/data/minecraft/trade/sell_brown_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_brown_wool.json rename to src/main/generated/data/minecraft/trade/sell_brown_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_cherry_log.json b/src/main/generated/data/minecraft/trade/sell_cherry_log.json new file mode 100644 index 00000000..83b42ed7 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_cherry_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:cherry_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_cyan_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_cyan_banner_cartographer.json new file mode 100644 index 00000000..da2d5204 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_cyan_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:cyan_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:desert", + "minecraft:snow" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_cyan_wool.json b/src/main/generated/data/minecraft/trade/sell_cyan_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_cyan_wool.json rename to src/main/generated/data/minecraft/trade/sell_cyan_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_dark_oak_log.json b/src/main/generated/data/minecraft/trade/sell_dark_oak_log.json new file mode 100644 index 00000000..7b74c0d7 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_dark_oak_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:dark_oak_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_desert_village_map.json b/src/main/generated/data/minecraft/trade/sell_desert_village_map.json new file mode 100644 index 00000000..28403692 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_desert_village_map.json @@ -0,0 +1,45 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:village_desert", + "destination": "minecraft:on_desert_village_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.village_desert" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:savanna", + "minecraft:jungle" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_enchanted_iron_pickaxe_wandering_trader.json b/src/main/generated/data/minecraft/trade/sell_enchanted_iron_pickaxe_wandering_trader.json new file mode 100644 index 00000000..723c5f3f --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_enchanted_iron_pickaxe_wandering_trader.json @@ -0,0 +1,21 @@ +{ + "gives": { + "item": "minecraft:iron_pickaxe" + }, + "max_uses": 1, + "price_multiplier": 0.2, + "trade_modifier": { + "type": "minecraft:enchant_with_levels", + "index": 0, + "level": { + "max": 19, + "min": 5 + } + }, + "wants": [ + { + "count": 3, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_firefly_bush.json b/src/main/generated/data/minecraft/trade/sell_firefly_bush.json new file mode 100644 index 00000000..e628045b --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_firefly_bush.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:firefly_bush" + }, + "max_uses": 5, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_gray_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_gray_banner_cartographer.json new file mode 100644 index 00000000..3ec71cb7 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_gray_banner_cartographer.json @@ -0,0 +1,24 @@ +{ + "gives": { + "item": "minecraft:gray_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": "minecraft:desert" + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_gray_wool.json b/src/main/generated/data/minecraft/trade/sell_gray_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_gray_wool.json rename to src/main/generated/data/minecraft/trade/sell_gray_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_green_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_green_banner_cartographer.json new file mode 100644 index 00000000..0e9bad2d --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_green_banner_cartographer.json @@ -0,0 +1,28 @@ +{ + "gives": { + "item": "minecraft:green_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:desert", + "minecraft:savanna", + "minecraft:jungle" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_green_wool.json b/src/main/generated/data/minecraft/trade/sell_green_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_green_wool.json rename to src/main/generated/data/minecraft/trade/sell_green_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_jungle_log.json b/src/main/generated/data/minecraft/trade/sell_jungle_log.json new file mode 100644 index 00000000..352fbc2b --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_jungle_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:jungle_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_jungle_temple_map.json b/src/main/generated/data/minecraft/trade/sell_jungle_temple_map.json new file mode 100644 index 00000000..3dd29f65 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_jungle_temple_map.json @@ -0,0 +1,46 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:jungle_temple", + "destination": "minecraft:on_jungle_explorer_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.explorer_jungle" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:swamp", + "minecraft:savanna", + "minecraft:desert" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_light_blue_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_light_blue_banner_cartographer.json new file mode 100644 index 00000000..6c243a06 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_light_blue_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:light_blue_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:snow", + "minecraft:swamp" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_light_blue_wool.json b/src/main/generated/data/minecraft/trade/sell_light_blue_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_light_blue_wool.json rename to src/main/generated/data/minecraft/trade/sell_light_blue_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_light_gray_wool.json b/src/main/generated/data/minecraft/trade/sell_light_gray_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_light_gray_wool.json rename to src/main/generated/data/minecraft/trade/sell_light_gray_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_lime_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_lime_banner_cartographer.json new file mode 100644 index 00000000..a11dd2ae --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_lime_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:lime_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:desert", + "minecraft:taiga" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_lime_wool.json b/src/main/generated/data/minecraft/trade/sell_lime_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_lime_wool.json rename to src/main/generated/data/minecraft/trade/sell_lime_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_long_invisibility_potion.json b/src/main/generated/data/minecraft/trade/sell_long_invisibility_potion.json new file mode 100644 index 00000000..072ec270 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_long_invisibility_potion.json @@ -0,0 +1,17 @@ +{ + "gives": { + "item": "minecraft:potion", + "item_modifier": { + "id": "minecraft:long_invisibility", + "function": "minecraft:set_potion" + } + }, + "max_uses": 1, + "price_multiplier": 0.05, + "wants": [ + { + "count": 5, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_magenta_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_magenta_banner_cartographer.json new file mode 100644 index 00000000..b9f74d83 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_magenta_banner_cartographer.json @@ -0,0 +1,24 @@ +{ + "gives": { + "item": "minecraft:magenta_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": "minecraft:savanna" + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_magenta_wool.json b/src/main/generated/data/minecraft/trade/sell_magenta_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_magenta_wool.json rename to src/main/generated/data/minecraft/trade/sell_magenta_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_mangrove_log.json b/src/main/generated/data/minecraft/trade/sell_mangrove_log.json new file mode 100644 index 00000000..10547e66 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_mangrove_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:mangrove_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_monument_map.json b/src/main/generated/data/minecraft/trade/sell_monument_map.json index 38dd2069..6697dd2a 100644 --- a/src/main/generated/data/minecraft/trade/sell_monument_map.json +++ b/src/main/generated/data/minecraft/trade/sell_monument_map.json @@ -22,7 +22,7 @@ }, "max_uses": 12, "price_multiplier": 0.05, - "trade_experience": 5, + "trade_experience": 10, "wants": [ { "count": 13, diff --git a/src/main/generated/data/minecraft/trade/sell_oak_log.json b/src/main/generated/data/minecraft/trade/sell_oak_log.json new file mode 100644 index 00000000..ea470ea1 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_oak_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:oak_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_open_eyeblossom.json b/src/main/generated/data/minecraft/trade/sell_open_eyeblossom.json new file mode 100644 index 00000000..da468b81 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_open_eyeblossom.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:open_eyeblossom" + }, + "max_uses": 7, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_orange_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_orange_banner_cartographer.json new file mode 100644 index 00000000..e5a8534b --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_orange_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:orange_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:savanna", + "minecraft:desert" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_orange_wool.json b/src/main/generated/data/minecraft/trade/sell_orange_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_orange_wool.json rename to src/main/generated/data/minecraft/trade/sell_orange_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_pale_hanging_moss.json b/src/main/generated/data/minecraft/trade/sell_pale_hanging_moss.json new file mode 100644 index 00000000..8f1f6e90 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_pale_hanging_moss.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:pale_hanging_moss" + }, + "max_uses": 12, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_pale_moss_block.json b/src/main/generated/data/minecraft/trade/sell_pale_moss_block.json new file mode 100644 index 00000000..5af3bd91 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_pale_moss_block.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 2, + "item": "minecraft:pale_moss_block" + }, + "max_uses": 5, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_pale_oak_log.json b/src/main/generated/data/minecraft/trade/sell_pale_oak_log.json new file mode 100644 index 00000000..a1b802b6 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_pale_oak_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:pale_oak_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_pale_oak_sapling.json b/src/main/generated/data/minecraft/trade/sell_pale_oak_sapling.json new file mode 100644 index 00000000..46abbd4b --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_pale_oak_sapling.json @@ -0,0 +1,13 @@ +{ + "gives": { + "item": "minecraft:pale_oak_sapling" + }, + "max_uses": 8, + "price_multiplier": 0.05, + "wants": [ + { + "count": 5, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_pink_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_pink_banner_cartographer.json new file mode 100644 index 00000000..b1628865 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_pink_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:pink_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:taiga", + "minecraft:plains" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_pink_wool.json b/src/main/generated/data/minecraft/trade/sell_pink_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_pink_wool.json rename to src/main/generated/data/minecraft/trade/sell_pink_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_plains_village_map.json b/src/main/generated/data/minecraft/trade/sell_plains_village_map.json new file mode 100644 index 00000000..5e5511d9 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_plains_village_map.json @@ -0,0 +1,47 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:village_plains", + "destination": "minecraft:on_plains_village_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.village_plains" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:taiga", + "minecraft:snow", + "minecraft:savanna", + "minecraft:desert" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_purple_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_purple_banner_cartographer.json new file mode 100644 index 00000000..ac2c02ea --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_purple_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:purple_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:taiga", + "minecraft:swamp" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_purple_wool.json b/src/main/generated/data/minecraft/trade/sell_purple_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_purple_wool.json rename to src/main/generated/data/minecraft/trade/sell_purple_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_red_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_red_banner_cartographer.json new file mode 100644 index 00000000..528f9234 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_red_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:red_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:snow", + "minecraft:savanna" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_red_wool.json b/src/main/generated/data/minecraft/trade/sell_red_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_red_wool.json rename to src/main/generated/data/minecraft/trade/sell_red_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_savanna_village_map.json b/src/main/generated/data/minecraft/trade/sell_savanna_village_map.json new file mode 100644 index 00000000..fce8d08a --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_savanna_village_map.json @@ -0,0 +1,46 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:village_savanna", + "destination": "minecraft:on_savanna_village_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.village_savanna" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:plains", + "minecraft:jungle", + "minecraft:desert" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_snowy_village_map.json b/src/main/generated/data/minecraft/trade/sell_snowy_village_map.json new file mode 100644 index 00000000..25a872e4 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_snowy_village_map.json @@ -0,0 +1,45 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:village_snowy", + "destination": "minecraft:on_snowy_village_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.village_snowy" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:taiga", + "minecraft:swamp" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_spruce_log.json b/src/main/generated/data/minecraft/trade/sell_spruce_log.json new file mode 100644 index 00000000..2ad47602 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_spruce_log.json @@ -0,0 +1,13 @@ +{ + "gives": { + "count": 8, + "item": "minecraft:spruce_log" + }, + "max_uses": 4, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_swamp_hut_map.json b/src/main/generated/data/minecraft/trade/sell_swamp_hut_map.json new file mode 100644 index 00000000..7fbce3ab --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_swamp_hut_map.json @@ -0,0 +1,46 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:swamp_hut", + "destination": "minecraft:on_swamp_explorer_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.explorer_swamp" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:taiga", + "minecraft:snow", + "minecraft:jungle" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_taiga_village_map.json b/src/main/generated/data/minecraft/trade/sell_taiga_village_map.json new file mode 100644 index 00000000..4d0739d7 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_taiga_village_map.json @@ -0,0 +1,46 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:village_taiga", + "destination": "minecraft:on_taiga_village_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.village_taiga" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:swamp", + "minecraft:snow", + "minecraft:plains" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 5, + "wants": [ + { + "count": 8, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_tall_dry_grass.json b/src/main/generated/data/minecraft/trade/sell_tall_dry_grass.json new file mode 100644 index 00000000..ec2a86cb --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_tall_dry_grass.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:tall_dry_grass" + }, + "max_uses": 5, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_trial_chamber_map.json b/src/main/generated/data/minecraft/trade/sell_trial_chamber_map.json new file mode 100644 index 00000000..8aaf8029 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_trial_chamber_map.json @@ -0,0 +1,32 @@ +{ + "gives": { + "item": "minecraft:map", + "item_modifier": { + "function": "minecraft:sequence", + "functions": [ + { + "decoration": "minecraft:trial_chambers", + "destination": "minecraft:on_trial_chambers_maps", + "function": "minecraft:exploration_map", + "search_radius": 100 + }, + { + "function": "minecraft:set_name", + "name": { + "translate": "filled_map.trial_chambers" + }, + "target": "item_name" + } + ] + } + }, + "max_uses": 12, + "price_multiplier": 0.05, + "trade_experience": 10, + "wants": [ + { + "count": 12, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_white_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_white_banner_cartographer.json new file mode 100644 index 00000000..1d0614c6 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_white_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:white_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:snow", + "minecraft:plains" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_white_wool.json b/src/main/generated/data/minecraft/trade/sell_white_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_white_wool.json rename to src/main/generated/data/minecraft/trade/sell_white_wool_shepherd.json diff --git a/src/main/generated/data/minecraft/trade/sell_wildflowers.json b/src/main/generated/data/minecraft/trade/sell_wildflowers.json new file mode 100644 index 00000000..2bdb1bea --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_wildflowers.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:wildflowers" + }, + "max_uses": 5, + "price_multiplier": 0.05, + "wants": [ + { + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_yellow_banner_cartographer.json b/src/main/generated/data/minecraft/trade/sell_yellow_banner_cartographer.json new file mode 100644 index 00000000..09a50a96 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/sell_yellow_banner_cartographer.json @@ -0,0 +1,27 @@ +{ + "gives": { + "item": "minecraft:yellow_banner" + }, + "max_uses": 12, + "merchant_predicate": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type_specific": { + "type": "minecraft:villager", + "variant": [ + "minecraft:plains", + "minecraft:jungle" + ] + } + } + }, + "price_multiplier": 0.05, + "trade_experience": 15, + "wants": [ + { + "count": 2, + "item": "minecraft:emerald" + } + ] +} \ No newline at end of file diff --git a/src/main/generated/data/minecraft/trade/sell_yellow_wool.json b/src/main/generated/data/minecraft/trade/sell_yellow_wool_shepherd.json similarity index 100% rename from src/main/generated/data/minecraft/trade/sell_yellow_wool.json rename to src/main/generated/data/minecraft/trade/sell_yellow_wool_shepherd.json diff --git a/src/main/java/net/errorcraft/itematic/Itematic.java b/src/main/java/net/errorcraft/itematic/Itematic.java index 50335570..52a2e04a 100644 --- a/src/main/java/net/errorcraft/itematic/Itematic.java +++ b/src/main/java/net/errorcraft/itematic/Itematic.java @@ -10,6 +10,7 @@ import net.errorcraft.itematic.item.use.provider.IntegerProviderTypes; import net.errorcraft.itematic.loot.function.ItematicItemModifierTypes; import net.errorcraft.itematic.loot.predicate.ItematicPredicateTypes; +import net.errorcraft.itematic.predicate.entity.ItematicEntitySubPredicateTypes; import net.errorcraft.itematic.recipe.ItematicRecipeSerializers; import net.errorcraft.itematic.recipe.ItematicRecipeTypes; import net.errorcraft.itematic.recipe.book.ItematicRecipeBookCategories; @@ -45,5 +46,6 @@ public void onInitialize() { ItematicRecipeBookCategories.init(); ItematicRecipeDisplaySerializers.init(); ItematicSlotDisplaySerializers.init(); + ItematicEntitySubPredicateTypes.init(); } } diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java index aea42558..a7550a1e 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/BannerPatternHolderItemComponent.java @@ -47,7 +47,7 @@ public Optional translationKey(ItemStack stack, String baseTranslationKe return Optional.empty(); } - return Optional.of(baseTranslationKey + "." + baseColor.getName()); + return Optional.of(baseTranslationKey + "." + baseColor.getId()); } public static BannerPatternHolderItemComponent of() { diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java index 6c369c62..51144f8a 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java @@ -67,9 +67,17 @@ protected void fillRecipesFromPool(RegistryEntryList.Named entries, int c int actualCount = Math.min(count, entries.size()); ArrayList> pool = Lists.newArrayList(entries); TradeOfferList recipeList = this.getOffers(); - for (int i = 0; i < actualCount; i++) { - TradeOffer tradeOffer = pool.remove(this.random.nextInt(pool.size())).value().createTradeOffer(context); + int addedTrades = 0; + while (addedTrades < actualCount && !pool.isEmpty()) { + TradeOffer tradeOffer = pool.remove(this.random.nextInt(pool.size())) + .value() + .createTradeOffer(context); + if (tradeOffer == null) { + continue; + } + recipeList.add(tradeOffer); + addedTrades++; } } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java index 46b95335..f5e769ec 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/WanderingTraderEntityExtender.java @@ -33,8 +33,9 @@ public abstract class WanderingTraderEntityExtender extends MerchantEntityExtender { @Unique private static final Object2IntMap> TRADE_TO_AMOUNT = Util.make(new Object2IntArrayMap<>(), trades -> { + trades.put(TradeTags.WANDERING_TRADER_BUYING, 2); + trades.put(TradeTags.WANDERING_TRADER_SPECIAL, 2); trades.put(TradeTags.WANDERING_TRADER_REGULAR, 5); - trades.put(TradeTags.WANDERING_TRADER_SPECIAL, 1); }); public WanderingTraderEntityExtender(EntityType entityType, World world) { diff --git a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/FireworkRocketEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/FireworkRocketEntityExtender.java index fe38a04e..e98f74b8 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/FireworkRocketEntityExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/entity/projectile/FireworkRocketEntityExtender.java @@ -12,8 +12,6 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.function.Supplier; - @Mixin(FireworkRocketEntity.class) public abstract class FireworkRocketEntityExtender extends ProjectileEntity { public FireworkRocketEntityExtender(EntityType entityType, World world) { @@ -31,9 +29,11 @@ private Item getHandPosOffsetUseRegistryEntry(Item item) { return this.getWorld().itematic$getItem(ItemKeys.FIREWORK_ROCKET).value(); } - @Redirect( - method = { "initDataTracker", "readCustomDataFromNbt" }, + method = { + "initDataTracker", + "readCustomDataFromNbt" + }, at = @At( value = "INVOKE", target = "Lnet/minecraft/entity/projectile/FireworkRocketEntity;getDefaultStack()Lnet/minecraft/item/ItemStack;" @@ -42,15 +42,4 @@ private Item getHandPosOffsetUseRegistryEntry(Item item) { private ItemStack newItemStackForFireworkRocketUseCreateStack() { return this.getWorld().itematic$createStack(ItemKeys.FIREWORK_ROCKET); } - - @ModifyArg( - method = "readCustomDataFromNbt", - at = @At( - value = "INVOKE", - target = "Ljava/util/Optional;orElseGet(Ljava/util/function/Supplier;)Ljava/lang/Object;" - ) - ) - private Supplier newItemStackSupplierForFireworkRocketUseCreateStack(Supplier supplier) { - return () -> this.getWorld().itematic$createStack(ItemKeys.FIREWORK_ROCKET); - } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/stat/ServerStatHandlerExtender.java b/src/main/java/net/errorcraft/itematic/mixin/stat/ServerStatHandlerExtender.java index 5b1cc960..947d71bb 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/stat/ServerStatHandlerExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/stat/ServerStatHandlerExtender.java @@ -1,13 +1,16 @@ package net.errorcraft.itematic.mixin.stat; import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import net.minecraft.registry.Registry; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.entry.RegistryFixedCodec; import net.minecraft.server.MinecraftServer; import net.minecraft.stat.ServerStatHandler; import net.minecraft.stat.Stat; import net.minecraft.stat.StatHandler; import net.minecraft.stat.StatType; -import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -15,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.Optional; import java.util.function.Function; @Mixin(ServerStatHandler.class) @@ -24,40 +26,64 @@ public class ServerStatHandlerExtender extends StatHandler { @Final private MinecraftServer server; + @Redirect( + method = "createCodec", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/registry/Registry;getCodec()Lcom/mojang/serialization/Codec;" + ) + ) + private static Codec> getCodecUseRegistryEntry(Registry instance) { + return RegistryFixedCodec.of(instance.getKey()); + } + @ModifyArg( - method = "createStat", + method = "createCodec", at = @At( value = "INVOKE", - target = "Ljava/util/Optional;flatMap(Ljava/util/function/Function;)Ljava/util/Optional;" + target = "Lcom/mojang/serialization/Codec;flatComapMap(Ljava/util/function/Function;Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;", + remap = false + ), + index = 0 + ) + private static Function, Stat> flatComapMapToUseRegistryEntry(Function> to, @Local(argsOnly = true) StatType statType) { + return statType::itematic$getOrCreateStat; + } + + @ModifyArg( + method = "method_67581", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/serialization/DataResult;success(Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;", + remap = false ) ) - private Function>> flatMapToEntryUseDynamicRegistry(Function> mapper, @Local(argsOnly = true) StatType type) { - return id -> this.server.getRegistryManager() - .getOrThrow(type.getRegistry().getKey()) - .getEntry(id); + @SuppressWarnings("unchecked") + private static T getValueUseRegistryEntry(T result, @Local(argsOnly = true) Stat stat) { + return (T) stat.itematic$entry(); } @ModifyArg( - method = "createStat", + method = "parse", at = @At( value = "INVOKE", - target = "Ljava/util/Optional;map(Ljava/util/function/Function;)Ljava/util/Optional;" + target = "Lcom/mojang/serialization/Dynamic;(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)V", + remap = false ) ) - private Function, Stat> mapToStatUseRegistryEntry(Function mapper, @Local(argsOnly = true) StatType type) { - return type::itematic$getOrCreateStat; + private DynamicOps useRegistryOps(DynamicOps ops) { + return this.server.getRegistryManager().getOps(ops); } - @Redirect( + @ModifyArg( method = "asString", at = @At( value = "INVOKE", - target = "Lnet/minecraft/stat/ServerStatHandler;getStatId(Lnet/minecraft/stat/Stat;)Lnet/minecraft/util/Identifier;" + target = "Lcom/mojang/serialization/Codec;encodeStart(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;", + remap = false ) ) - private Identifier getStatIdUseDynamicRegistry(Stat stat) { - return this.server.getRegistryManager() - .getOrThrow(stat.getType().getRegistry().getKey()) - .getId(stat.getValue()); + private DynamicOps encodeStartUseRegistryOps(DynamicOps ops) { + return this.server.getRegistryManager().getOps(ops); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java b/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java index 1d665b10..19477cbb 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java @@ -39,7 +39,7 @@ public class VillagerDataExtender implements VillagerDataAccess { return null; } - Identifier tag = Identifier.ofVanilla(this.profession.value().id() + "_" + this.levelName()); + Identifier tag = this.profession.getKey().orElseThrow().getValue().withPath(path -> path + "_" + this.levelName()); return TagKey.of(ItematicRegistryKeys.TRADE, tag); } diff --git a/src/main/java/net/errorcraft/itematic/predicate/entity/ItematicEntitySubPredicateTypes.java b/src/main/java/net/errorcraft/itematic/predicate/entity/ItematicEntitySubPredicateTypes.java new file mode 100644 index 00000000..2da7e163 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/predicate/entity/ItematicEntitySubPredicateTypes.java @@ -0,0 +1,18 @@ +package net.errorcraft.itematic.predicate.entity; + +import com.mojang.serialization.MapCodec; +import net.minecraft.predicate.entity.EntitySubPredicate; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; + +public class ItematicEntitySubPredicateTypes { + public static final MapCodec VILLAGER = register("villager", VillagerEntitySubPredicate.CODEC); + + private ItematicEntitySubPredicateTypes() {} + + public static void init() {} + + private static MapCodec register(String id, MapCodec codec) { + return Registry.register(Registries.ENTITY_SUB_PREDICATE_TYPE, id, codec); + } +} diff --git a/src/main/java/net/errorcraft/itematic/predicate/entity/VillagerEntitySubPredicate.java b/src/main/java/net/errorcraft/itematic/predicate/entity/VillagerEntitySubPredicate.java new file mode 100644 index 00000000..c5e260b0 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/predicate/entity/VillagerEntitySubPredicate.java @@ -0,0 +1,38 @@ +package net.errorcraft.itematic.predicate.entity; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.entity.Entity; +import net.minecraft.predicate.entity.EntitySubPredicate; +import net.minecraft.registry.RegistryCodecs; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntryList; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.village.VillagerDataContainer; +import net.minecraft.village.VillagerType; +import org.jetbrains.annotations.Nullable; + +public record VillagerEntitySubPredicate(RegistryEntryList variant) implements EntitySubPredicate { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + RegistryCodecs.entryList(RegistryKeys.VILLAGER_TYPE).fieldOf("variant").forGetter(VillagerEntitySubPredicate::variant) + ).apply(instance, VillagerEntitySubPredicate::new)); + + public static VillagerEntitySubPredicate of(RegistryEntryList variant) { + return new VillagerEntitySubPredicate(variant); + } + + @Override + public MapCodec getCodec() { + return CODEC; + } + + @Override + public boolean test(Entity entity, ServerWorld world, @Nullable Vec3d pos) { + if (entity instanceof VillagerDataContainer villagerDataContainer) { + return this.variant.contains(villagerDataContainer.getVillagerData().type()); + } + + return false; + } +} diff --git a/src/main/java/net/errorcraft/itematic/village/trade/Trade.java b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java index 17029b3d..ab82e420 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trade.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java @@ -9,6 +9,7 @@ import net.errorcraft.itematic.village.trade.modifier.TradeModifier; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.loot.condition.LootCondition; import net.minecraft.loot.context.LootContext; import net.minecraft.loot.function.LootFunction; import net.minecraft.loot.function.LootFunctionTypes; @@ -25,24 +26,34 @@ import java.util.List; import java.util.Optional; -public record Trade(List wants, Entry gives, int maxUses, int tradeExperience, float priceMultiplier, Optional> tradeModifier) { +public record Trade(List wants, Entry gives, int maxUses, int tradeExperience, float priceMultiplier, Optional> tradeModifier, Optional merchantPredicate) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Entry.CODEC.listOf(1, Trade.MAX_WANTED_ENTRIES).fieldOf("wants").forGetter(Trade::wants), Entry.CODEC.fieldOf("gives").forGetter(Trade::gives), Codecs.POSITIVE_INT.fieldOf("max_uses").forGetter(Trade::maxUses), Codec.INT.optionalFieldOf("trade_experience", 1).forGetter(Trade::tradeExperience), Codec.FLOAT.optionalFieldOf("price_multiplier", 0.0f).forGetter(Trade::priceMultiplier), - TradeModifier.CODEC.optionalFieldOf("trade_modifier").forGetter(Trade::tradeModifier) + TradeModifier.CODEC.optionalFieldOf("trade_modifier").forGetter(Trade::tradeModifier), + LootCondition.CODEC.optionalFieldOf("merchant_predicate").forGetter(Trade::merchantPredicate) ).apply(instance, Trade::new)); public static final Codec WANTED_INDEX_CODEC = ItematicCodecs.index(Trade.MAX_WANTED_ENTRIES); private static final int MAX_WANTED_ENTRIES = 2; public TradeOffer createTradeOffer(LootContext context) { + if (!this.test(context)) { + return null; + } + Input wants = this.createWantedStacks(context); TradedItem gives = this.createGivenStack(wants, context); return new TradeOffer(wants.getTradedItem(0).orElseThrow(), wants.getTradedItem(1), gives.itemStack(), this.maxUses, this.tradeExperience, this.priceMultiplier); } + private boolean test(LootContext context) { + return this.merchantPredicate.map(merchantPredicate -> merchantPredicate.test(context)) + .orElse(true); + } + private Input createWantedStacks(LootContext context) { List stacks = this.wants.stream().map(entry -> entry.createStack(context)).toList(); return new Input(stacks); @@ -63,14 +74,23 @@ public static Trade of(Entry firstBuy, Entry sell, int maxUses, int tradeExperie } public static Trade of(Entry firstBuy, Entry sell, int maxUses, int tradeExperience, float priceMultiplier) { - return of(List.of(firstBuy), sell, maxUses, tradeExperience, priceMultiplier, null); + return of(List.of(firstBuy), sell, maxUses, tradeExperience, priceMultiplier, null, null); } - public static Trade of(List wants, Entry gives, int maxUses, int tradeExperience, float priceMultiplier, TradeModifier tradeModifier) { + public static Trade of(List wants, Entry gives, int maxUses, int tradeExperience, float priceMultiplier, TradeModifier tradeModifier, LootCondition merchantPredicate) { if (wants.size() > MAX_WANTED_ENTRIES) { throw new IllegalArgumentException("Wanted entries must not be more than " + MAX_WANTED_ENTRIES); } - return new Trade(wants, gives, maxUses, tradeExperience, priceMultiplier, Optional.ofNullable(tradeModifier)); + + return new Trade( + wants, + gives, + maxUses, + tradeExperience, + priceMultiplier, + Optional.ofNullable(tradeModifier), + Optional.ofNullable(merchantPredicate) + ); } public static class Builder { @@ -80,19 +100,29 @@ public static class Builder { private int tradeExperience; private float priceMultiplier = TradeOffersAccessor.lowPriceMultiplier(); private TradeModifier tradeModifier; + private LootCondition merchantPredicate; public Builder(Entry gives) { this.gives = gives; } public Trade build() { - return Trade.of(this.wants, this.gives, this.maxUses, this.tradeExperience, this.priceMultiplier, this.tradeModifier); + return Trade.of( + this.wants, + this.gives, + this.maxUses, + this.tradeExperience, + this.priceMultiplier, + this.tradeModifier, + this.merchantPredicate + ); } public Builder wants(Entry entry) { if (this.wants.size() >= MAX_WANTED_ENTRIES) { throw new IllegalArgumentException("Tried to add more than " + MAX_WANTED_ENTRIES + " wanted entries"); } + this.wants.add(entry); return this; } @@ -116,6 +146,11 @@ public Builder priceMultiplier(float priceMultiplier) { this.priceMultiplier = priceMultiplier; return this; } + + public Builder merchantPredicate(LootCondition.Builder merchantPredicate) { + this.merchantPredicate = merchantPredicate.build(); + return this; + } } public static class Input { @@ -129,6 +164,7 @@ public Optional getTradedItem(int index) { if (index < 0 || index >= this.stacks.size()) { return Optional.empty(); } + ItemStack stack = this.stacks.get(index); return Optional.of(new TradedItem(stack.getRegistryEntry(), stack.getCount(), ComponentPredicate.of(stack.getComponents()))); } diff --git a/src/main/java/net/errorcraft/itematic/village/trade/TradeTags.java b/src/main/java/net/errorcraft/itematic/village/trade/TradeTags.java index a445a295..38cf2d5a 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/TradeTags.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/TradeTags.java @@ -70,10 +70,9 @@ public class TradeTags { public static final TagKey MASON_JOURNEYMAN = of("mason_journeyman"); public static final TagKey MASON_EXPERT = of("mason_expert"); public static final TagKey MASON_MASTER = of("mason_master"); - public static final TagKey WANDERING_TRADER_REGULAR = of("wandering_trader_regular"); + public static final TagKey WANDERING_TRADER_BUYING = of("wandering_trader_buying"); public static final TagKey WANDERING_TRADER_SPECIAL = of("wandering_trader_special"); - - + public static final TagKey WANDERING_TRADER_REGULAR = of("wandering_trader_regular"); private TradeTags() {} diff --git a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java index 4547c53a..7adeed96 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java @@ -5,7 +5,9 @@ import net.errorcraft.itematic.loot.function.DyeItemModifier; import net.errorcraft.itematic.loot.function.SetRandomPotionItemModifier; import net.errorcraft.itematic.mixin.village.TradeOffersAccessor; +import net.errorcraft.itematic.potion.PotionKeys; import net.errorcraft.itematic.potion.PotionTags; +import net.errorcraft.itematic.predicate.entity.VillagerEntitySubPredicate; import net.errorcraft.itematic.registry.ItematicRegistryKeys; import net.errorcraft.itematic.village.trade.modifier.modifiers.EnchantWithLevelsTradeModifier; import net.errorcraft.itematic.village.trade.modifier.modifiers.ItemFromTypeTradeModifier; @@ -15,16 +17,13 @@ import net.minecraft.item.Item; import net.minecraft.item.map.MapDecorationType; import net.minecraft.item.map.MapDecorationTypes; -import net.minecraft.loot.function.AndLootFunction; -import net.minecraft.loot.function.ExplorationMapLootFunction; -import net.minecraft.loot.function.SetNameLootFunction; -import net.minecraft.loot.function.SetStewEffectLootFunction; +import net.minecraft.loot.condition.EntityPropertiesLootCondition; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.function.*; import net.minecraft.loot.provider.number.ConstantLootNumberProvider; import net.minecraft.potion.Potion; -import net.minecraft.registry.Registerable; -import net.minecraft.registry.RegistryEntryLookup; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; +import net.minecraft.predicate.entity.EntityPredicate; +import net.minecraft.registry.*; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.registry.tag.EnchantmentTags; @@ -80,22 +79,22 @@ public class Trades { public static final RegistryKey BUY_BLACK_DYE = of("buy_black_dye"); public static final RegistryKey BUY_LIGHT_BLUE_DYE = of("buy_light_blue_dye"); public static final RegistryKey BUY_LIME_DYE = of("buy_lime_dye"); - public static final RegistryKey SELL_WHITE_WOOL = of("sell_white_wool"); - public static final RegistryKey SELL_ORANGE_WOOL = of("sell_orange_wool"); - public static final RegistryKey SELL_MAGENTA_WOOL = of("sell_magenta_wool"); - public static final RegistryKey SELL_LIGHT_BLUE_WOOL = of("sell_light_blue_wool"); - public static final RegistryKey SELL_YELLOW_WOOL = of("sell_yellow_wool"); - public static final RegistryKey SELL_LIME_WOOL = of("sell_lime_wool"); - public static final RegistryKey SELL_PINK_WOOL = of("sell_pink_wool"); - public static final RegistryKey SELL_GRAY_WOOL = of("sell_gray_wool"); - public static final RegistryKey SELL_LIGHT_GRAY_WOOL = of("sell_light_gray_wool"); - public static final RegistryKey SELL_CYAN_WOOL = of("sell_cyan_wool"); - public static final RegistryKey SELL_PURPLE_WOOL = of("sell_purple_wool"); - public static final RegistryKey SELL_BLUE_WOOL = of("sell_blue_wool"); - public static final RegistryKey SELL_BROWN_WOOL = of("sell_brown_wool"); - public static final RegistryKey SELL_GREEN_WOOL = of("sell_green_wool"); - public static final RegistryKey SELL_RED_WOOL = of("sell_red_wool"); - public static final RegistryKey SELL_BLACK_WOOL = of("sell_black_wool"); + public static final RegistryKey SELL_WHITE_WOOL_SHEPHERD = of("sell_white_wool_shepherd"); + public static final RegistryKey SELL_ORANGE_WOOL_SHEPHERD = of("sell_orange_wool_shepherd"); + public static final RegistryKey SELL_MAGENTA_WOOL_SHEPHERD = of("sell_magenta_wool_shepherd"); + public static final RegistryKey SELL_LIGHT_BLUE_WOOL_SHEPHERD = of("sell_light_blue_wool_shepherd"); + public static final RegistryKey SELL_YELLOW_WOOL_SHEPHERD = of("sell_yellow_wool_shepherd"); + public static final RegistryKey SELL_LIME_WOOL_SHEPHERD = of("sell_lime_wool_shepherd"); + public static final RegistryKey SELL_PINK_WOOL_SHEPHERD = of("sell_pink_wool_shepherd"); + public static final RegistryKey SELL_GRAY_WOOL_SHEPHERD = of("sell_gray_wool_shepherd"); + public static final RegistryKey SELL_LIGHT_GRAY_WOOL_SHEPHERD = of("sell_light_gray_wool_shepherd"); + public static final RegistryKey SELL_CYAN_WOOL_SHEPHERD = of("sell_cyan_wool_shepherd"); + public static final RegistryKey SELL_PURPLE_WOOL_SHEPHERD = of("sell_purple_wool_shepherd"); + public static final RegistryKey SELL_BLUE_WOOL_SHEPHERD = of("sell_blue_wool_shepherd"); + public static final RegistryKey SELL_BROWN_WOOL_SHEPHERD = of("sell_brown_wool_shepherd"); + public static final RegistryKey SELL_GREEN_WOOL_SHEPHERD = of("sell_green_wool_shepherd"); + public static final RegistryKey SELL_RED_WOOL_SHEPHERD = of("sell_red_wool_shepherd"); + public static final RegistryKey SELL_BLACK_WOOL_SHEPHERD = of("sell_black_wool_shepherd"); public static final RegistryKey SELL_WHITE_CARPET = of("sell_white_carpet"); public static final RegistryKey SELL_ORANGE_CARPET = of("sell_orange_carpet"); public static final RegistryKey SELL_MAGENTA_CARPET = of("sell_magenta_carpet"); @@ -168,7 +167,7 @@ public class Trades { public static final RegistryKey BUY_TRIPWIRE_HOOK = of("buy_tripwire_hook"); public static final RegistryKey SELL_ENCHANTED_CROSSBOW = of("sell_enchanted_crossbow"); public static final RegistryKey SELL_TIPPED_ARROW = of("sell_tipped_arrow"); - public static final RegistryKey BUY_PAPER = of("buy_paper"); + public static final RegistryKey BUY_PAPER_LIBRARIAN = of("buy_paper_librarian"); public static final RegistryKey SELL_ENCHANTED_BOOK_NOVICE = of("sell_enchanted_book_novice"); public static final RegistryKey SELL_BOOKSHELF = of("sell_bookshelf"); public static final RegistryKey BUY_BOOK = of("buy_book"); @@ -182,13 +181,37 @@ public class Trades { public static final RegistryKey SELL_CLOCK = of("sell_clock"); public static final RegistryKey SELL_COMPASS = of("sell_compass"); public static final RegistryKey SELL_NAME_TAG = of("sell_name_tag"); + public static final RegistryKey BUY_PAPER_CARTOGRAPHER = of("buy_paper_cartographer"); public static final RegistryKey SELL_MAP = of("sell_map"); public static final RegistryKey BUY_GLASS_PANE = of("buy_glass_pane"); - public static final RegistryKey SELL_MONUMENT_MAP = of("sell_monument_map"); + public static final RegistryKey SELL_TAIGA_VILLAGE_MAP = of("sell_taiga_village_map"); + public static final RegistryKey SELL_SWAMP_HUT_MAP = of("sell_swamp_hut_map"); + public static final RegistryKey SELL_SNOWY_VILLAGE_MAP = of("sell_snowy_village_map"); + public static final RegistryKey SELL_SAVANNA_VILLAGE_MAP = of("sell_savanna_village_map"); + public static final RegistryKey SELL_PLAINS_VILLAGE_MAP = of("sell_plains_village_map"); + public static final RegistryKey SELL_JUNGLE_TEMPLE_MAP = of("sell_jungle_temple_map"); + public static final RegistryKey SELL_DESERT_VILLAGE_MAP = of("sell_desert_village_map"); public static final RegistryKey BUY_COMPASS = of("buy_compass"); - public static final RegistryKey SELL_MANSION_MAP = of("sell_mansion_map"); + public static final RegistryKey SELL_MONUMENT_MAP = of("sell_monument_map"); + public static final RegistryKey SELL_TRIAL_CHAMBER_MAP = of("sell_trial_chamber_map"); public static final RegistryKey SELL_ITEM_FRAME = of("sell_item_frame"); + public static final RegistryKey SELL_BLUE_BANNER_CARTOGRAPHER = of("sell_blue_banner_cartographer"); + public static final RegistryKey SELL_WHITE_BANNER_CARTOGRAPHER = of("sell_white_banner_cartographer"); + public static final RegistryKey SELL_RED_BANNER_CARTOGRAPHER = of("sell_red_banner_cartographer"); + public static final RegistryKey SELL_GREEN_BANNER_CARTOGRAPHER = of("sell_green_banner_cartographer"); + public static final RegistryKey SELL_LIME_BANNER_CARTOGRAPHER = of("sell_lime_banner_cartographer"); + public static final RegistryKey SELL_PURPLE_BANNER_CARTOGRAPHER = of("sell_purple_banner_cartographer"); + public static final RegistryKey SELL_CYAN_BANNER_CARTOGRAPHER = of("sell_cyan_banner_cartographer"); + public static final RegistryKey SELL_YELLOW_BANNER_CARTOGRAPHER = of("sell_yellow_banner_cartographer"); + public static final RegistryKey SELL_ORANGE_BANNER_CARTOGRAPHER = of("sell_orange_banner_cartographer"); + public static final RegistryKey SELL_BROWN_BANNER_CARTOGRAPHER = of("sell_brown_banner_cartographer"); + public static final RegistryKey SELL_MAGENTA_BANNER_CARTOGRAPHER = of("sell_magenta_banner_cartographer"); + public static final RegistryKey SELL_LIGHT_BLUE_BANNER_CARTOGRAPHER = of("sell_light_blue_banner_cartographer"); + public static final RegistryKey SELL_PINK_BANNER_CARTOGRAPHER = of("sell_pink_banner_cartographer"); + public static final RegistryKey SELL_GRAY_BANNER_CARTOGRAPHER = of("sell_gray_banner_cartographer"); + public static final RegistryKey SELL_BLACK_BANNER_CARTOGRAPHER = of("sell_black_banner_cartographer"); public static final RegistryKey SELL_GLOBE_BANNER_PATTERN = of("sell_globe_banner_pattern"); + public static final RegistryKey SELL_MANSION_MAP = of("sell_mansion_map"); public static final RegistryKey BUY_ROTTEN_FLESH = of("buy_rotten_flesh"); public static final RegistryKey SELL_REDSTONE = of("sell_redstone"); public static final RegistryKey BUY_GOLD_INGOT = of("buy_gold_ingot"); @@ -300,6 +323,29 @@ public class Trades { public static final RegistryKey SELL_BROWN_GLAZED_TERRACOTTA = of("sell_brown_glazed_terracotta"); public static final RegistryKey SELL_QUARTZ_PILLAR = of("sell_quartz_pillar"); public static final RegistryKey SELL_QUARTZ_BLOCK = of("sell_quartz_block"); + public static final RegistryKey BUY_WATER_BOTTLE = of("buy_water_bottle"); + public static final RegistryKey BUY_WATER_BUCKET = of("buy_water_bucket"); + public static final RegistryKey BUY_MILK_BUCKET = of("buy_milk_bucket"); + public static final RegistryKey BUY_FERMENTED_SPIDER_EYE = of("buy_fermented_spider_eye"); + public static final RegistryKey BUY_BAKED_POTATO = of("buy_baked_potato"); + public static final RegistryKey BUY_HAY_BLOCK = of("buy_hay_block"); + public static final RegistryKey SELL_PACKED_ICE = of("sell_packed_ice"); + public static final RegistryKey SELL_BLUE_ICE = of("sell_blue_ice"); + public static final RegistryKey SELL_GUNPOWDER = of("sell_gunpowder"); + public static final RegistryKey SELL_PODZOL = of("sell_podzol"); + public static final RegistryKey SELL_ACACIA_LOG = of("sell_acacia_log"); + public static final RegistryKey SELL_BIRCH_LOG = of("sell_birch_log"); + public static final RegistryKey SELL_DARK_OAK_LOG = of("sell_dark_oak_log"); + public static final RegistryKey SELL_JUNGLE_LOG = of("sell_jungle_log"); + public static final RegistryKey SELL_OAK_LOG = of("sell_oak_log"); + public static final RegistryKey SELL_SPRUCE_LOG = of("sell_spruce_log"); + public static final RegistryKey SELL_CHERRY_LOG = of("sell_cherry_log"); + public static final RegistryKey SELL_MANGROVE_LOG = of("sell_mangrove_log"); + public static final RegistryKey SELL_PALE_OAK_LOG = of("sell_pale_oak_log"); + public static final RegistryKey SELL_ENCHANTED_IRON_PICKAXE_WANDERING_TRADER = of("sell_enchanted_iron_pickaxe_wandering_trader"); + public static final RegistryKey SELL_LONG_INVISIBILITY_POTION = of("sell_long_invisibility_potion"); + public static final RegistryKey SELL_TROPICAL_FISH_BUCKET = of("sell_tropical_fish_bucket"); + public static final RegistryKey SELL_PUFFERFISH_BUCKET = of("sell_pufferfish_bucket"); public static final RegistryKey SELL_SEA_PICKLE = of("sell_sea_pickle"); public static final RegistryKey SELL_SLIME_BALL = of("sell_slime_ball"); public static final RegistryKey SELL_GLOWSTONE_WANDERING_TRADER = of("sell_glowstone_wandering_trader"); @@ -321,6 +367,7 @@ public class Trades { public static final RegistryKey SELL_OXEYE_DAISY = of("sell_oxeye_daisy"); public static final RegistryKey SELL_CORNFLOWER = of("sell_cornflower"); public static final RegistryKey SELL_LILY_OF_THE_VALLEY = of("sell_lily_of_the_valley"); + public static final RegistryKey SELL_OPEN_EYEBLOSSOM = of("sell_open_eyeblossom"); public static final RegistryKey SELL_WHEAT_SEEDS = of("sell_wheat_seeds"); public static final RegistryKey SELL_BEETROOT_SEEDS = of("sell_beetroot_seeds"); public static final RegistryKey SELL_PUMPKIN_SEEDS = of("sell_pumpkin_seeds"); @@ -332,6 +379,7 @@ public class Trades { public static final RegistryKey SELL_OAK_SAPLING = of("sell_oak_sapling"); public static final RegistryKey SELL_SPRUCE_SAPLING = of("sell_spruce_sapling"); public static final RegistryKey SELL_CHERRY_SAPLING = of("sell_cherry_sapling"); + public static final RegistryKey SELL_PALE_OAK_SAPLING = of("sell_pale_oak_sapling"); public static final RegistryKey SELL_MANGROVE_PROPAGULE = of("sell_mangrove_propagule"); public static final RegistryKey SELL_RED_DYE = of("sell_red_dye"); public static final RegistryKey SELL_WHITE_DYE = of("sell_white_dye"); @@ -355,6 +403,7 @@ public class Trades { public static final RegistryKey SELL_HORN_CORAL_BLOCK = of("sell_horn_coral_block"); public static final RegistryKey SELL_TUBE_CORAL_BLOCK = of("sell_tube_coral_block"); public static final RegistryKey SELL_VINE = of("sell_vine"); + public static final RegistryKey SELL_PALE_HANGING_MOSS = of("sell_pale_hanging_moss"); public static final RegistryKey SELL_BROWN_MUSHROOM = of("sell_brown_mushroom"); public static final RegistryKey SELL_RED_MUSHROOM = of("sell_red_mushroom"); public static final RegistryKey SELL_LILY_PAD = of("sell_lily_pad"); @@ -364,12 +413,10 @@ public class Trades { public static final RegistryKey SELL_POINTED_DRIPSTONE = of("sell_pointed_dripstone"); public static final RegistryKey SELL_ROOTED_DIRT = of("sell_rooted_dirt"); public static final RegistryKey SELL_MOSS_BLOCK = of("sell_moss_block"); - public static final RegistryKey SELL_TROPICAL_FISH_BUCKET = of("sell_tropical_fish_bucket"); - public static final RegistryKey SELL_PUFFERFISH_BUCKET = of("sell_pufferfish_bucket"); - public static final RegistryKey SELL_PACKED_ICE = of("sell_packed_ice"); - public static final RegistryKey SELL_BLUE_ICE = of("sell_blue_ice"); - public static final RegistryKey SELL_GUNPOWDER = of("sell_gunpowder"); - public static final RegistryKey SELL_PODZOL = of("sell_podzol"); + public static final RegistryKey SELL_PALE_MOSS_BLOCK = of("sell_pale_moss_block"); + public static final RegistryKey SELL_WILDFLOWERS = of("sell_wildflowers"); + public static final RegistryKey SELL_TALL_DRY_GRASS = of("sell_tall_dry_grass"); + public static final RegistryKey SELL_FIREFLY_BUSH = of("sell_firefly_bush"); private Trades() {} @@ -429,22 +476,22 @@ public static void bootstrap(Registerable registerable) { registerable.register(BUY_BLACK_DYE, buy(items, items.getOrThrow(ItemKeys.BLACK_DYE), 12, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); registerable.register(BUY_LIGHT_BLUE_DYE, buy(items, items.getOrThrow(ItemKeys.LIGHT_BLUE_DYE), 12, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); registerable.register(BUY_LIME_DYE, buy(items, items.getOrThrow(ItemKeys.LIME_DYE), 12, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); - registerable.register(SELL_WHITE_WOOL, sell(items, items.getOrThrow(ItemKeys.WHITE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_ORANGE_WOOL, sell(items, items.getOrThrow(ItemKeys.ORANGE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_MAGENTA_WOOL, sell(items, items.getOrThrow(ItemKeys.MAGENTA_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_LIGHT_BLUE_WOOL, sell(items, items.getOrThrow(ItemKeys.LIGHT_BLUE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_YELLOW_WOOL, sell(items, items.getOrThrow(ItemKeys.YELLOW_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_LIME_WOOL, sell(items, items.getOrThrow(ItemKeys.LIME_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_PINK_WOOL, sell(items, items.getOrThrow(ItemKeys.PINK_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_GRAY_WOOL, sell(items, items.getOrThrow(ItemKeys.GRAY_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_LIGHT_GRAY_WOOL, sell(items, items.getOrThrow(ItemKeys.LIGHT_GRAY_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_CYAN_WOOL, sell(items, items.getOrThrow(ItemKeys.CYAN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_PURPLE_WOOL, sell(items, items.getOrThrow(ItemKeys.PURPLE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_BLUE_WOOL, sell(items, items.getOrThrow(ItemKeys.BLUE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_BROWN_WOOL, sell(items, items.getOrThrow(ItemKeys.BROWN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_GREEN_WOOL, sell(items, items.getOrThrow(ItemKeys.GREEN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_RED_WOOL, sell(items, items.getOrThrow(ItemKeys.RED_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); - registerable.register(SELL_BLACK_WOOL, sell(items, items.getOrThrow(ItemKeys.BLACK_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_WHITE_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.WHITE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_ORANGE_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.ORANGE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_MAGENTA_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.MAGENTA_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_LIGHT_BLUE_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.LIGHT_BLUE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_YELLOW_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.YELLOW_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_LIME_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.LIME_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_PINK_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.PINK_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_GRAY_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.GRAY_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_LIGHT_GRAY_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.LIGHT_GRAY_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_CYAN_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.CYAN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_PURPLE_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.PURPLE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_BLUE_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.BLUE_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_BROWN_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.BROWN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_GREEN_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.GREEN_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_RED_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.RED_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); + registerable.register(SELL_BLACK_WOOL_SHEPHERD, sell(items, items.getOrThrow(ItemKeys.BLACK_WOOL), 1, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); registerable.register(SELL_WHITE_CARPET, sell(items, items.getOrThrow(ItemKeys.WHITE_CARPET), 4, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); registerable.register(SELL_ORANGE_CARPET, sell(items, items.getOrThrow(ItemKeys.ORANGE_CARPET), 4, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); registerable.register(SELL_MAGENTA_CARPET, sell(items, items.getOrThrow(ItemKeys.MAGENTA_CARPET), 4, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), 1)); @@ -517,7 +564,7 @@ public static void bootstrap(Registerable registerable) { registerable.register(BUY_TRIPWIRE_HOOK, buy(items, items.getOrThrow(ItemKeys.TRIPWIRE_HOOK), 8, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.masterTradeExperience())); registerable.register(SELL_ENCHANTED_CROSSBOW, sellEnchantedItem(items, items.getOrThrow(ItemKeys.CROSSBOW), 15, 3)); registerable.register(SELL_TIPPED_ARROW, sellWithPotion(items, potions.getOrThrow(PotionTags.TRADEABLE), items.getOrThrow(ItemKeys.ARROW), items.getOrThrow(ItemKeys.TIPPED_ARROW), TradeOffersAccessor.masterTradeExperience())); - registerable.register(BUY_PAPER, buy(items, items.getOrThrow(ItemKeys.PAPER), 24, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); + registerable.register(BUY_PAPER_LIBRARIAN, buy(items, items.getOrThrow(ItemKeys.PAPER), 24, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); registerable.register(SELL_ENCHANTED_BOOK_NOVICE, sellEnchantedBook(items, TradeOffersAccessor.noviceSellTradeExperience(), enchantments.getOrThrow(EnchantmentTags.TRADEABLE))); registerable.register(SELL_BOOKSHELF, sell(items, items.getOrThrow(ItemKeys.BOOKSHELF), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 9)); registerable.register(BUY_BOOK, buy(items, items.getOrThrow(ItemKeys.BOOK), 4, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); @@ -531,13 +578,37 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_CLOCK, sell(items, items.getOrThrow(ItemKeys.CLOCK), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 5)); registerable.register(SELL_COMPASS, sell(items, items.getOrThrow(ItemKeys.COMPASS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 4)); registerable.register(SELL_NAME_TAG, sell(items, items.getOrThrow(ItemKeys.NAME_TAG), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.masterTradeExperience(), 20)); + registerable.register(BUY_PAPER_CARTOGRAPHER, buy(items, items.getOrThrow(ItemKeys.PAPER), 24, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); registerable.register(SELL_MAP, sell(items, items.getOrThrow(ItemKeys.MAP), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 7)); registerable.register(BUY_GLASS_PANE, buy(items, items.getOrThrow(ItemKeys.GLASS_PANE), 11, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); - registerable.register(SELL_MONUMENT_MAP, sellMap(items, 13, StructureTags.ON_OCEAN_EXPLORER_MAPS, "filled_map.monument", MapDecorationTypes.MONUMENT, TradeOffersAccessor.apprenticeSellTradeExperience())); + registerable.register(SELL_TAIGA_VILLAGE_MAP, sellMap(items, 8, StructureTags.ON_TAIGA_VILLAGE_MAPS, "filled_map.village_taiga", MapDecorationTypes.VILLAGE_TAIGA, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.SWAMP, VillagerType.SNOW, VillagerType.PLAINS)); + registerable.register(SELL_SWAMP_HUT_MAP, sellMap(items, 8, StructureTags.ON_SWAMP_EXPLORER_MAPS, "filled_map.explorer_swamp", MapDecorationTypes.SWAMP_HUT, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.TAIGA, VillagerType.SNOW, VillagerType.JUNGLE)); + registerable.register(SELL_SNOWY_VILLAGE_MAP, sellMap(items, 8, StructureTags.ON_SNOWY_VILLAGE_MAPS, "filled_map.village_snowy", MapDecorationTypes.VILLAGE_SNOWY, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.TAIGA, VillagerType.SWAMP)); + registerable.register(SELL_SAVANNA_VILLAGE_MAP, sellMap(items, 8, StructureTags.ON_SAVANNA_VILLAGE_MAPS, "filled_map.village_savanna", MapDecorationTypes.VILLAGE_SAVANNA, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.PLAINS, VillagerType.JUNGLE, VillagerType.DESERT)); + registerable.register(SELL_PLAINS_VILLAGE_MAP, sellMap(items, 8, StructureTags.ON_PLAINS_VILLAGE_MAPS, "filled_map.village_plains", MapDecorationTypes.VILLAGE_PLAINS, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.TAIGA, VillagerType.SNOW, VillagerType.SAVANNA, VillagerType.DESERT)); + registerable.register(SELL_JUNGLE_TEMPLE_MAP, sellMap(items, 8, StructureTags.ON_JUNGLE_EXPLORER_MAPS, "filled_map.explorer_jungle", MapDecorationTypes.JUNGLE_TEMPLE, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.SWAMP, VillagerType.SAVANNA, VillagerType.DESERT)); + registerable.register(SELL_DESERT_VILLAGE_MAP, sellMap(items, 8, StructureTags.ON_DESERT_VILLAGE_MAPS, "filled_map.village_desert", MapDecorationTypes.VILLAGE_DESERT, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeSellTradeExperience(), VillagerType.SAVANNA, VillagerType.JUNGLE)); registerable.register(BUY_COMPASS, buy(items, items.getOrThrow(ItemKeys.COMPASS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.journeymanBuyTradeExperience())); - registerable.register(SELL_MANSION_MAP, sellMap(items, 14, StructureTags.ON_WOODLAND_EXPLORER_MAPS, "filled_map.mansion", MapDecorationTypes.MANSION, TradeOffersAccessor.journeymanSellTradeExperience())); + registerable.register(SELL_MONUMENT_MAP, sellMap(items, 13, StructureTags.ON_OCEAN_EXPLORER_MAPS, "filled_map.monument", MapDecorationTypes.MONUMENT, TradeOffersAccessor.journeymanSellTradeExperience())); + registerable.register(SELL_TRIAL_CHAMBER_MAP, sellMap(items, 12, StructureTags.ON_TRIAL_CHAMBERS_MAPS, "filled_map.trial_chambers", MapDecorationTypes.TRIAL_CHAMBERS, TradeOffersAccessor.journeymanSellTradeExperience())); registerable.register(SELL_ITEM_FRAME, sell(items, items.getOrThrow(ItemKeys.ITEM_FRAME), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 7)); + registerable.register(SELL_BLUE_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.BLUE_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SNOW, VillagerType.TAIGA)); + registerable.register(SELL_WHITE_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.WHITE_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SNOW, VillagerType.PLAINS)); + registerable.register(SELL_RED_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.RED_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SNOW, VillagerType.SAVANNA)); + registerable.register(SELL_GREEN_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.GREEN_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.DESERT, VillagerType.SAVANNA, VillagerType.JUNGLE)); + registerable.register(SELL_LIME_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.LIME_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.DESERT, VillagerType.TAIGA)); + registerable.register(SELL_PURPLE_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.PURPLE_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.TAIGA, VillagerType.SWAMP)); + registerable.register(SELL_CYAN_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.CYAN_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.DESERT, VillagerType.SNOW)); + registerable.register(SELL_YELLOW_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.YELLOW_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.PLAINS, VillagerType.JUNGLE)); + registerable.register(SELL_ORANGE_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.ORANGE_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SAVANNA, VillagerType.DESERT)); + registerable.register(SELL_BROWN_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.BROWN_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.PLAINS, VillagerType.JUNGLE)); + registerable.register(SELL_MAGENTA_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.MAGENTA_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SAVANNA)); + registerable.register(SELL_LIGHT_BLUE_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.LIGHT_BLUE_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SNOW, VillagerType.SWAMP)); + registerable.register(SELL_PINK_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.PINK_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.TAIGA, VillagerType.PLAINS)); + registerable.register(SELL_GRAY_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.GRAY_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.DESERT)); + registerable.register(SELL_BLACK_BANNER_CARTOGRAPHER, sell(items, items.getOrThrow(ItemKeys.BLACK_BANNER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.expertSellTradeExperience(), 2, VillagerType.SWAMP)); registerable.register(SELL_GLOBE_BANNER_PATTERN, sell(items, items.getOrThrow(ItemKeys.GLOBE_BANNER_PATTERN), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.masterTradeExperience(), 8)); + registerable.register(SELL_MANSION_MAP, sellMap(items, 14, StructureTags.ON_WOODLAND_EXPLORER_MAPS, "filled_map.mansion", MapDecorationTypes.MANSION, TradeOffersAccessor.journeymanSellTradeExperience())); registerable.register(BUY_ROTTEN_FLESH, buy(items, items.getOrThrow(ItemKeys.ROTTEN_FLESH), 32, TradeOffersAccessor.commonMaxUses(), TradeOffersAccessor.noviceBuyTradeExperience())); registerable.register(SELL_REDSTONE, sell(items, items.getOrThrow(ItemKeys.REDSTONE), 2, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(BUY_GOLD_INGOT, buy(items, items.getOrThrow(ItemKeys.GOLD_INGOT), 3, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.apprenticeBuyTradeExperience())); @@ -670,6 +741,7 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_OXEYE_DAISY, sell(items, items.getOrThrow(ItemKeys.OXEYE_DAISY), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_CORNFLOWER, sell(items, items.getOrThrow(ItemKeys.CORNFLOWER), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_LILY_OF_THE_VALLEY, sell(items, items.getOrThrow(ItemKeys.LILY_OF_THE_VALLEY), 1, 7, TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_OPEN_EYEBLOSSOM, sell(items, items.getOrThrow(ItemKeys.OPEN_EYEBLOSSOM), 1, 7, TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_WHEAT_SEEDS, sell(items, items.getOrThrow(ItemKeys.WHEAT_SEEDS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_BEETROOT_SEEDS, sell(items, items.getOrThrow(ItemKeys.BEETROOT_SEEDS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_PUMPKIN_SEEDS, sell(items, items.getOrThrow(ItemKeys.PUMPKIN_SEEDS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); @@ -681,6 +753,7 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_OAK_SAPLING, sell(items, items.getOrThrow(ItemKeys.OAK_SAPLING), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 5)); registerable.register(SELL_SPRUCE_SAPLING, sell(items, items.getOrThrow(ItemKeys.SPRUCE_SAPLING), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 5)); registerable.register(SELL_CHERRY_SAPLING, sell(items, items.getOrThrow(ItemKeys.CHERRY_SAPLING), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 5)); + registerable.register(SELL_PALE_OAK_SAPLING, sell(items, items.getOrThrow(ItemKeys.PALE_OAK_SAPLING), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 5)); registerable.register(SELL_MANGROVE_PROPAGULE, sell(items, items.getOrThrow(ItemKeys.MANGROVE_PROPAGULE), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 5)); registerable.register(SELL_RED_DYE, sell(items, items.getOrThrow(ItemKeys.RED_DYE), 3, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_WHITE_DYE, sell(items, items.getOrThrow(ItemKeys.WHITE_DYE), 3, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); @@ -704,6 +777,7 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_HORN_CORAL_BLOCK, sell(items, items.getOrThrow(ItemKeys.HORN_CORAL_BLOCK), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 3)); registerable.register(SELL_TUBE_CORAL_BLOCK, sell(items, items.getOrThrow(ItemKeys.TUBE_CORAL_BLOCK), 1, 8, TradeOffersAccessor.noviceSellTradeExperience(), 3)); registerable.register(SELL_VINE, sell(items, items.getOrThrow(ItemKeys.VINE), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_PALE_HANGING_MOSS, sell(items, items.getOrThrow(ItemKeys.PALE_HANGING_MOSS), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_BROWN_MUSHROOM, sell(items, items.getOrThrow(ItemKeys.BROWN_MUSHROOM), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_RED_MUSHROOM, sell(items, items.getOrThrow(ItemKeys.RED_MUSHROOM), 1, TradeOffersAccessor.defaultMaxUses(), TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_LILY_PAD, sell(items, items.getOrThrow(ItemKeys.LILY_PAD), 2, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); @@ -713,12 +787,33 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_POINTED_DRIPSTONE, sell(items, items.getOrThrow(ItemKeys.POINTED_DRIPSTONE), 2, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_ROOTED_DIRT, sell(items, items.getOrThrow(ItemKeys.ROOTED_DIRT), 2, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_MOSS_BLOCK, sell(items, items.getOrThrow(ItemKeys.MOSS_BLOCK), 2, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_PALE_MOSS_BLOCK, sell(items, items.getOrThrow(ItemKeys.PALE_MOSS_BLOCK), 2, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_WILDFLOWERS, sell(items, items.getOrThrow(ItemKeys.WILDFLOWERS), 1, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_TALL_DRY_GRASS, sell(items, items.getOrThrow(ItemKeys.TALL_DRY_GRASS), 1, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); + registerable.register(SELL_FIREFLY_BUSH, sell(items, items.getOrThrow(ItemKeys.FIREFLY_BUSH), 1, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_TROPICAL_FISH_BUCKET, sell(items, items.getOrThrow(ItemKeys.TROPICAL_FISH_BUCKET), 1, 4, 1, 5)); registerable.register(SELL_PUFFERFISH_BUCKET, sell(items, items.getOrThrow(ItemKeys.PUFFERFISH_BUCKET), 1, 4, 1, 5)); + registerable.register(BUY_WATER_BOTTLE, buyWithPotion(items, potions.getOrThrow(PotionKeys.WATER), items.getOrThrow(ItemKeys.POTION), 1)); + registerable.register(BUY_WATER_BUCKET, buy(items, items.getOrThrow(ItemKeys.WATER_BUCKET), 1, 2, 1, 1)); + registerable.register(BUY_MILK_BUCKET, buy(items, items.getOrThrow(ItemKeys.MILK_BUCKET), 1, 2, 1, 1)); + registerable.register(BUY_FERMENTED_SPIDER_EYE, buy(items, items.getOrThrow(ItemKeys.FERMENTED_SPIDER_EYE), 1, 3, 1, 1)); + registerable.register(BUY_BAKED_POTATO, buy(items, items.getOrThrow(ItemKeys.BAKED_POTATO), 4, 1, 1, 1)); + registerable.register(BUY_HAY_BLOCK, buy(items, items.getOrThrow(ItemKeys.HAY_BLOCK), 1, 1, 1, 1)); registerable.register(SELL_PACKED_ICE, sell(items, items.getOrThrow(ItemKeys.PACKED_ICE), 1, 6, 1, 3)); registerable.register(SELL_BLUE_ICE, sell(items, items.getOrThrow(ItemKeys.BLUE_ICE), 1, 6, 1, 6)); registerable.register(SELL_GUNPOWDER, sell(items, items.getOrThrow(ItemKeys.GUNPOWDER), 1, 8, 1, 1)); registerable.register(SELL_PODZOL, sell(items, items.getOrThrow(ItemKeys.PODZOL), 3, 6, 1, 3)); + registerable.register(SELL_ACACIA_LOG, sell(items, items.getOrThrow(ItemKeys.ACACIA_LOG), 8, 4, 1, 1)); + registerable.register(SELL_BIRCH_LOG, sell(items, items.getOrThrow(ItemKeys.BIRCH_LOG), 8, 4, 1, 1)); + registerable.register(SELL_CHERRY_LOG, sell(items, items.getOrThrow(ItemKeys.CHERRY_LOG), 8, 4, 1, 1)); + registerable.register(SELL_MANGROVE_LOG, sell(items, items.getOrThrow(ItemKeys.MANGROVE_LOG), 8, 4, 1, 1)); + registerable.register(SELL_DARK_OAK_LOG, sell(items, items.getOrThrow(ItemKeys.DARK_OAK_LOG), 8, 4, 1, 1)); + registerable.register(SELL_JUNGLE_LOG, sell(items, items.getOrThrow(ItemKeys.JUNGLE_LOG), 8, 4, 1, 1)); + registerable.register(SELL_OAK_LOG, sell(items, items.getOrThrow(ItemKeys.OAK_LOG), 8, 4, 1, 1)); + registerable.register(SELL_SPRUCE_LOG, sell(items, items.getOrThrow(ItemKeys.SPRUCE_LOG), 8, 4, 1, 1)); + registerable.register(SELL_PALE_OAK_LOG, sell(items, items.getOrThrow(ItemKeys.PALE_OAK_LOG), 8, 4, 1, 1)); + registerable.register(SELL_ENCHANTED_IRON_PICKAXE_WANDERING_TRADER, sellEnchantedItem(items, items.getOrThrow(ItemKeys.IRON_PICKAXE), 1, 3, TradeOffersAccessor.highPriceMultiplier(), 1)); + registerable.register(SELL_LONG_INVISIBILITY_POTION, sellWithPotion(items, potions.getOrThrow(PotionKeys.LONG_INVISIBILITY), items.getOrThrow(ItemKeys.POTION), 1)); } private static Trade buy(RegistryEntryLookup items, RegistryEntry item, int count, int maxUses, int tradeExperience) { @@ -729,6 +824,14 @@ private static Trade buy(RegistryEntryLookup items, RegistryEntry it .build(); } + private static Trade buy(RegistryEntryLookup items, RegistryEntry item, int count, int givenAmount, int maxUses, int tradeExperience) { + return Trade.builder(Trade.Entry.ofEmerald(items, givenAmount)) + .wants(Trade.Entry.of(item, count)) + .maxUses(maxUses) + .tradeExperience(tradeExperience) + .build(); + } + private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry item, Map, RegistryEntry> types) { return Trade.builder(Trade.Entry.ofEmerald(items)) .wants(Trade.Entry.of(item)) @@ -737,6 +840,13 @@ private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry< .build(); } + private static Trade buyWithPotion(RegistryEntryLookup items, RegistryEntry potion, RegistryEntry item, int tradeExperience) { + return Trade.builder(Trade.Entry.ofEmerald(items)) + .wants(Trade.Entry.of(item, 1, SetPotionLootFunction.builder(potion).build())) + .tradeExperience(tradeExperience) + .build(); + } + private static Trade sell(RegistryEntryLookup items, RegistryEntry item, int count, int maxUses, int tradeExperience, int price) { return Trade.builder(Trade.Entry.of(item, count)) .wants(Trade.Entry.ofEmerald(items, price)) @@ -745,6 +855,24 @@ private static Trade sell(RegistryEntryLookup items, RegistryEntry i .build(); } + @SafeVarargs + private static Trade sell(RegistryEntryLookup items, RegistryEntry item, int count, int maxUses, int tradeExperience, int price, RegistryKey... types) { + return Trade.builder(Trade.Entry.of(item, count)) + .wants(Trade.Entry.ofEmerald(items, price)) + .maxUses(maxUses) + .tradeExperience(tradeExperience) + .merchantPredicate( + EntityPropertiesLootCondition.builder( + LootContext.EntityTarget.THIS, + EntityPredicate.Builder.create() + .typeSpecific(VillagerEntitySubPredicate.of( + RegistryEntryList.of(Registries.VILLAGER_TYPE::getOrThrow, types) + )) + ) + ) + .build(); + } + private static Trade sell(RegistryEntryLookup items, RegistryEntry item, int count, RegistryEntry processedItem, int processedCount, int maxUses, int tradeExperience, float priceMultiplier) { return Trade.builder(Trade.Entry.of(processedItem, processedCount)) .wants(Trade.Entry.ofEmerald(items)) @@ -770,9 +898,13 @@ private static Trade sellEnchantedItem(RegistryEntryLookup items, Registry } private static Trade sellEnchantedItem(RegistryEntryLookup items, RegistryEntry item, int tradeExperience, int basePrice, float priceMultiplier) { + return sellEnchantedItem(items, item, tradeExperience, basePrice, priceMultiplier, 3); + } + + private static Trade sellEnchantedItem(RegistryEntryLookup items, RegistryEntry item, int tradeExperience, int basePrice, float priceMultiplier, int maxUses) { return Trade.builder(Trade.Entry.of(item)) .wants(Trade.Entry.ofEmerald(items, basePrice)) - .maxUses(3) + .maxUses(maxUses) .tradeExperience(tradeExperience) .tradeModifier(EnchantWithLevelsTradeModifier.of(0, 5, 19)) .priceMultiplier(priceMultiplier) @@ -787,6 +919,14 @@ private static Trade sellWithPotion(RegistryEntryLookup items, RegistryEnt .build(); } + private static Trade sellWithPotion(RegistryEntryLookup items, RegistryEntry potion, RegistryEntry resultItem, int tradeExperience) { + return Trade.builder(Trade.Entry.of(resultItem, 1, SetPotionLootFunction.builder(potion).build())) + .wants(Trade.Entry.ofEmerald(items, 5)) + .tradeExperience(tradeExperience) + .maxUses(1) + .build(); + } + private static Trade sellDyedItem(RegistryEntryLookup items, RegistryEntry item, int price) { return sellDyedItem(items, item, price, 1); } @@ -814,6 +954,33 @@ private static Trade sellMap(RegistryEntryLookup items, int price, TagKey< .build(); } + @SafeVarargs + private static Trade sellMap(RegistryEntryLookup items, int price, TagKey structure, String name, RegistryEntry decoration, int maxUses, int experience, RegistryKey... types) { + AndLootFunction itemModifier = AndLootFunction.create(List.of( + ExplorationMapLootFunction.builder() + .withDestination(structure) + .withDecoration(decoration) + .searchRadius(100) + .build(), + SetNameLootFunction.builder(Text.translatable(name), SetNameLootFunction.Target.ITEM_NAME) + .build() + )); + return Trade.builder(Trade.Entry.of(items.getOrThrow(ItemKeys.MAP), 1, itemModifier)) + .wants(Trade.Entry.ofEmerald(items, price)) + .maxUses(maxUses) + .tradeExperience(experience) + .merchantPredicate( + EntityPropertiesLootCondition.builder( + LootContext.EntityTarget.THIS, + EntityPredicate.Builder.create() + .typeSpecific(VillagerEntitySubPredicate.of( + RegistryEntryList.of(Registries.VILLAGER_TYPE::getOrThrow, types) + )) + ) + ) + .build(); + } + private static Trade sellEnchantedBook(RegistryEntryLookup items, int tradeExperience, RegistryEntryList enchantments) { return Trade.builder(Trade.Entry.of(items.getOrThrow(ItemKeys.BOOK))) .wants(Trade.Entry.ofEmerald(items, 2)) From 94035bf7057b9a1befd6f009a6b9a429986f1b87 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 04:35:48 +0200 Subject: [PATCH 07/12] Port to 25w08a --- gradle.properties | 6 +++--- .../render/item/HeldItemRendererExtender.java | 2 +- .../select/ChargeTypePropertyExtender.java | 2 +- .../data/minecraft/trade/buy_baked_potato.json | 2 +- .../trade/buy_fermented_spider_eye.json | 2 +- .../data/minecraft/trade/buy_hay_block.json | 2 +- .../data/minecraft/trade/buy_milk_bucket.json | 2 +- .../data/minecraft/trade/buy_water_bottle.json | 2 +- .../data/minecraft/trade/buy_water_bucket.json | 2 +- .../itematic/village/trade/Trades.java | 17 +++++++++-------- 10 files changed, 20 insertions(+), 19 deletions(-) diff --git a/gradle.properties b/gradle.properties index e927566f..7e0d2398 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w07a - yarn_mappings=25w07a+build.12 + minecraft_version=25w08a + yarn_mappings=25w08a+build.6 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.117.3+1.21.5 + fabric_version=0.118.0+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java index 2960ef95..52048f3b 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/HeldItemRendererExtender.java @@ -136,7 +136,7 @@ private int getUseTimeLeftForCrossbowUseNegatedUsedTicks(AbstractClientPlayerEnt slice = @Slice( from = @At( value = "INVOKE", - target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", + target = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemDisplayContext;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", ordinal = 0 ) ) diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java index 5ef44b8d..897d5b6a 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/render/item/property/select/ChargeTypePropertyExtender.java @@ -11,7 +11,7 @@ @Mixin(ChargeTypeProperty.class) public class ChargeTypePropertyExtender { @Redirect( - method = "getValue(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/entity/LivingEntity;ILnet/minecraft/item/ModelTransformationMode;)Lnet/minecraft/item/CrossbowItem$ChargeType;", + method = "getValue(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/entity/LivingEntity;ILnet/minecraft/item/ItemDisplayContext;)Lnet/minecraft/item/CrossbowItem$ChargeType;", at = @At( value = "INVOKE", target = "Lnet/minecraft/component/type/ChargedProjectilesComponent;contains(Lnet/minecraft/item/Item;)Z" diff --git a/src/main/generated/data/minecraft/trade/buy_baked_potato.json b/src/main/generated/data/minecraft/trade/buy_baked_potato.json index 928f325a..4b55f3fa 100644 --- a/src/main/generated/data/minecraft/trade/buy_baked_potato.json +++ b/src/main/generated/data/minecraft/trade/buy_baked_potato.json @@ -2,7 +2,7 @@ "gives": { "item": "minecraft:emerald" }, - "max_uses": 1, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json b/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json index 01fc0133..f44fd873 100644 --- a/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json +++ b/src/main/generated/data/minecraft/trade/buy_fermented_spider_eye.json @@ -3,7 +3,7 @@ "count": 3, "item": "minecraft:emerald" }, - "max_uses": 1, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/generated/data/minecraft/trade/buy_hay_block.json b/src/main/generated/data/minecraft/trade/buy_hay_block.json index dbb1ab7f..7fe903e9 100644 --- a/src/main/generated/data/minecraft/trade/buy_hay_block.json +++ b/src/main/generated/data/minecraft/trade/buy_hay_block.json @@ -2,7 +2,7 @@ "gives": { "item": "minecraft:emerald" }, - "max_uses": 1, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/generated/data/minecraft/trade/buy_milk_bucket.json b/src/main/generated/data/minecraft/trade/buy_milk_bucket.json index 0f0ed124..4286b833 100644 --- a/src/main/generated/data/minecraft/trade/buy_milk_bucket.json +++ b/src/main/generated/data/minecraft/trade/buy_milk_bucket.json @@ -3,7 +3,7 @@ "count": 2, "item": "minecraft:emerald" }, - "max_uses": 1, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/generated/data/minecraft/trade/buy_water_bottle.json b/src/main/generated/data/minecraft/trade/buy_water_bottle.json index f2ba65af..e6ffa50f 100644 --- a/src/main/generated/data/minecraft/trade/buy_water_bottle.json +++ b/src/main/generated/data/minecraft/trade/buy_water_bottle.json @@ -2,7 +2,7 @@ "gives": { "item": "minecraft:emerald" }, - "max_uses": 12, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/generated/data/minecraft/trade/buy_water_bucket.json b/src/main/generated/data/minecraft/trade/buy_water_bucket.json index 5e7721d0..ddc32491 100644 --- a/src/main/generated/data/minecraft/trade/buy_water_bucket.json +++ b/src/main/generated/data/minecraft/trade/buy_water_bucket.json @@ -3,7 +3,7 @@ "count": 2, "item": "minecraft:emerald" }, - "max_uses": 1, + "max_uses": 2, "price_multiplier": 0.05, "wants": [ { diff --git a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java index 7adeed96..2dbb6aa8 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trades.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trades.java @@ -793,12 +793,12 @@ public static void bootstrap(Registerable registerable) { registerable.register(SELL_FIREFLY_BUSH, sell(items, items.getOrThrow(ItemKeys.FIREFLY_BUSH), 1, 5, TradeOffersAccessor.noviceSellTradeExperience(), 1)); registerable.register(SELL_TROPICAL_FISH_BUCKET, sell(items, items.getOrThrow(ItemKeys.TROPICAL_FISH_BUCKET), 1, 4, 1, 5)); registerable.register(SELL_PUFFERFISH_BUCKET, sell(items, items.getOrThrow(ItemKeys.PUFFERFISH_BUCKET), 1, 4, 1, 5)); - registerable.register(BUY_WATER_BOTTLE, buyWithPotion(items, potions.getOrThrow(PotionKeys.WATER), items.getOrThrow(ItemKeys.POTION), 1)); - registerable.register(BUY_WATER_BUCKET, buy(items, items.getOrThrow(ItemKeys.WATER_BUCKET), 1, 2, 1, 1)); - registerable.register(BUY_MILK_BUCKET, buy(items, items.getOrThrow(ItemKeys.MILK_BUCKET), 1, 2, 1, 1)); - registerable.register(BUY_FERMENTED_SPIDER_EYE, buy(items, items.getOrThrow(ItemKeys.FERMENTED_SPIDER_EYE), 1, 3, 1, 1)); - registerable.register(BUY_BAKED_POTATO, buy(items, items.getOrThrow(ItemKeys.BAKED_POTATO), 4, 1, 1, 1)); - registerable.register(BUY_HAY_BLOCK, buy(items, items.getOrThrow(ItemKeys.HAY_BLOCK), 1, 1, 1, 1)); + registerable.register(BUY_WATER_BOTTLE, buyWithPotion(items, potions.getOrThrow(PotionKeys.WATER), items.getOrThrow(ItemKeys.POTION))); + registerable.register(BUY_WATER_BUCKET, buy(items, items.getOrThrow(ItemKeys.WATER_BUCKET), 1, 2, 2, 1)); + registerable.register(BUY_MILK_BUCKET, buy(items, items.getOrThrow(ItemKeys.MILK_BUCKET), 1, 2, 2, 1)); + registerable.register(BUY_FERMENTED_SPIDER_EYE, buy(items, items.getOrThrow(ItemKeys.FERMENTED_SPIDER_EYE), 1, 3, 2, 1)); + registerable.register(BUY_BAKED_POTATO, buy(items, items.getOrThrow(ItemKeys.BAKED_POTATO), 4, 1, 2, 1)); + registerable.register(BUY_HAY_BLOCK, buy(items, items.getOrThrow(ItemKeys.HAY_BLOCK), 1, 1, 2, 1)); registerable.register(SELL_PACKED_ICE, sell(items, items.getOrThrow(ItemKeys.PACKED_ICE), 1, 6, 1, 3)); registerable.register(SELL_BLUE_ICE, sell(items, items.getOrThrow(ItemKeys.BLUE_ICE), 1, 6, 1, 6)); registerable.register(SELL_GUNPOWDER, sell(items, items.getOrThrow(ItemKeys.GUNPOWDER), 1, 8, 1, 1)); @@ -840,10 +840,11 @@ private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry< .build(); } - private static Trade buyWithPotion(RegistryEntryLookup items, RegistryEntry potion, RegistryEntry item, int tradeExperience) { + private static Trade buyWithPotion(RegistryEntryLookup items, RegistryEntry potion, RegistryEntry item) { return Trade.builder(Trade.Entry.ofEmerald(items)) .wants(Trade.Entry.of(item, 1, SetPotionLootFunction.builder(potion).build())) - .tradeExperience(tradeExperience) + .maxUses(2) + .tradeExperience(1) .build(); } From b37f5a37170f574d26df796847a97a68e89313f7 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 15:46:26 +0200 Subject: [PATCH 08/12] Port to 25w10a --- gradle.properties | 6 +-- ...electionScreenGameModeSelectionAccess.java | 11 ----- .../screen/GameModeSwitcherScreenAccess.java | 15 ++++++ ...va => GameModeSwitcherScreenExtender.java} | 47 +++++++++++-------- .../resources/itematic.client.mixins.json | 4 +- .../errorcraft/itematic/item/ItemUtil.java | 41 +++++++++++----- .../mixin/block/TntBlockAccessor.java | 17 +++++++ .../mixin/block/TntBlockExtender.java | 4 +- .../predicate/item/ItemPredicateUtil.java | 11 ++--- .../itematic/village/trade/Trade.java | 6 +-- .../EnchantWithLevelsTradeModifier.java | 4 +- .../modifiers/ItemFromTypeTradeModifier.java | 4 +- .../SingleEnchantmentTradeModifier.java | 4 +- .../world/action/actions/PrimeTntAction.java | 24 +++++++--- src/main/resources/fabric.mod.json | 3 -- src/main/resources/itematic.classtweaker | 3 +- src/main/resources/itematic.mixins.json | 1 + 17 files changed, 127 insertions(+), 78 deletions(-) delete mode 100644 src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSelectionScreenGameModeSelectionAccess.java create mode 100644 src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSwitcherScreenAccess.java rename src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/{GameModeSelectionScreenExtender.java => GameModeSwitcherScreenExtender.java} (66%) create mode 100644 src/main/java/net/errorcraft/itematic/mixin/block/TntBlockAccessor.java diff --git a/gradle.properties b/gradle.properties index 7e0d2398..f2d9fcbd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w08a - yarn_mappings=25w08a+build.6 + minecraft_version=25w10a + yarn_mappings=25w10a+build.9 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.118.0+1.21.5 + fabric_version=0.118.5+1.21.5 diff --git a/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSelectionScreenGameModeSelectionAccess.java b/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSelectionScreenGameModeSelectionAccess.java deleted file mode 100644 index a5a02c6f..00000000 --- a/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSelectionScreenGameModeSelectionAccess.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.errorcraft.itematic.access.client.gui.screen; - -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.registry.Registry; - -public interface GameModeSelectionScreenGameModeSelectionAccess { - default ItemStack itematic$icon(Registry registry) { - return ItemStack.EMPTY; - } -} diff --git a/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSwitcherScreenAccess.java b/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSwitcherScreenAccess.java new file mode 100644 index 00000000..3d0b218a --- /dev/null +++ b/src/client/java/net/errorcraft/itematic/access/client/gui/screen/GameModeSwitcherScreenAccess.java @@ -0,0 +1,15 @@ +package net.errorcraft.itematic.access.client.gui.screen; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; + +public interface GameModeSwitcherScreenAccess { + interface GameModeSelectionAccess { + default ItemStack itematic$icon(Registry registry) { + return ItemStack.EMPTY; + } + default void itematic$setIcon(RegistryKey item) {} + } +} diff --git a/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSelectionScreenExtender.java b/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSwitcherScreenExtender.java similarity index 66% rename from src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSelectionScreenExtender.java rename to src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSwitcherScreenExtender.java index 41f2183b..52617d07 100644 --- a/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSelectionScreenExtender.java +++ b/src/client/java/net/errorcraft/itematic/mixin/client/gui/screen/GameModeSwitcherScreenExtender.java @@ -1,11 +1,11 @@ package net.errorcraft.itematic.mixin.client.gui.screen; -import net.errorcraft.itematic.access.client.gui.screen.GameModeSelectionScreenGameModeSelectionAccess; +import net.errorcraft.itematic.access.client.gui.screen.GameModeSwitcherScreenAccess; import net.errorcraft.itematic.item.ItemKeys; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.GameModeSelectionScreen; +import net.minecraft.client.gui.screen.GameModeSwitcherScreen; import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemStack; @@ -20,52 +20,53 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -public class GameModeSelectionScreenExtender { - @Mixin(GameModeSelectionScreen.ButtonWidget.class) +public class GameModeSwitcherScreenExtender { + @Mixin(GameModeSwitcherScreen.ButtonWidget.class) public static class ButtonWidgetExtender { @Redirect( method = "renderWidget", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection;renderIcon(Lnet/minecraft/client/gui/DrawContext;II)V" + target = "Lnet/minecraft/client/gui/screen/GameModeSwitcherScreen$GameModeSelection;renderIcon(Lnet/minecraft/client/gui/DrawContext;II)V" ) ) - private void renderIconUseRegistryEntry(GameModeSelectionScreen.GameModeSelection instance, DrawContext context, int x, int y) { + private void renderIconUseRegistryEntry(GameModeSwitcherScreen.GameModeSelection instance, DrawContext context, int x, int y) { World world = MinecraftClient.getInstance().world; if (world == null) { return; } + ItemStack stack = instance.itematic$icon(world.getRegistryManager().getOrThrow(RegistryKeys.ITEM)); context.drawItem(stack, x, y); } } - @Mixin(GameModeSelectionScreen.GameModeSelection.class) - public static class GameModeSelectionExtender implements GameModeSelectionScreenGameModeSelectionAccess { - @Final + @Mixin(GameModeSwitcherScreen.GameModeSelection.class) + public static class GameModeSelectionExtender implements GameModeSwitcherScreenAccess.GameModeSelectionAccess { @Shadow - public static GameModeSelectionScreen.GameModeSelection CREATIVE; - @Final - @Shadow - public static GameModeSelectionScreen.GameModeSelection SURVIVAL; + public static GameModeSwitcherScreen.GameModeSelection CREATIVE; - @Final @Shadow - public static GameModeSelectionScreen.GameModeSelection ADVENTURE; + @Final + public static GameModeSwitcherScreen.GameModeSelection SURVIVAL; + @Shadow @Final + public static GameModeSwitcherScreen.GameModeSelection ADVENTURE; + @Shadow - public static GameModeSelectionScreen.GameModeSelection SPECTATOR; + @Final + public static GameModeSwitcherScreen.GameModeSelection SPECTATOR; @Unique private RegistryKey icon; static { - ((GameModeSelectionExtender)(Object) CREATIVE).icon = ItemKeys.GRASS_BLOCK; - ((GameModeSelectionExtender)(Object) SURVIVAL).icon = ItemKeys.IRON_SWORD; - ((GameModeSelectionExtender)(Object) ADVENTURE).icon = ItemKeys.MAP; - ((GameModeSelectionExtender)(Object) SPECTATOR).icon = ItemKeys.ENDER_EYE; + CREATIVE.itematic$setIcon(ItemKeys.GRASS_BLOCK); + SURVIVAL.itematic$setIcon(ItemKeys.IRON_SWORD); + ADVENTURE.itematic$setIcon(ItemKeys.MAP); + SPECTATOR.itematic$setIcon(ItemKeys.ENDER_EYE); } @Redirect( @@ -84,9 +85,15 @@ private static ItemStack newItemStackReturnEmptyStack(ItemConvertible item) { if (this.icon == null) { return ItemStack.EMPTY; } + return registry.getOptional(this.icon) .map(ItemStack::new) .orElse(ItemStack.EMPTY); } + + @Override + public void itematic$setIcon(RegistryKey icon) { + this.icon = icon; + } } } diff --git a/src/client/resources/itematic.client.mixins.json b/src/client/resources/itematic.client.mixins.json index 45d853dd..87426a16 100644 --- a/src/client/resources/itematic.client.mixins.json +++ b/src/client/resources/itematic.client.mixins.json @@ -12,8 +12,8 @@ "gui.screen.CustomizeFlatLevelScreenExtender", "gui.screen.CustomizeFlatLevelScreenExtender$SuperflatLayersListWidgetExtender", "gui.screen.CustomizeFlatLevelScreenExtender$SuperflatLayersListWidgetExtender$SuperflatLayerEntryExtender", - "gui.screen.GameModeSelectionScreenExtender$ButtonWidgetExtender", - "gui.screen.GameModeSelectionScreenExtender$GameModeSelectionExtender", + "gui.screen.GameModeSwitcherScreenExtender$ButtonWidgetExtender", + "gui.screen.GameModeSwitcherScreenExtender$GameModeSelectionExtender", "gui.screen.StatsScreenAccessor$ItemStatsListWidgetAccessor$EntryAccessor", "gui.screen.StatsScreenExtender", "gui.screen.StatsScreenExtender$ItemStatsListWidgetExtender", diff --git a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java index c19763ae..64611afa 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemUtil.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemUtil.java @@ -70,6 +70,8 @@ import net.minecraft.predicate.FluidPredicate; import net.minecraft.predicate.NumberRange; import net.minecraft.predicate.StatePredicate; +import net.minecraft.predicate.component.ComponentPredicateTypes; +import net.minecraft.predicate.component.ComponentsPredicate; import net.minecraft.predicate.entity.EntityPredicate; import net.minecraft.predicate.entity.LocationPredicate; import net.minecraft.predicate.item.*; @@ -228,11 +230,15 @@ private void bootstrapConsumables() { .block(BlockPredicate.Builder.create() .tag(this.blocks, BlockTags.CONVERTABLE_TO_MUD)) ), - MatchToolLootCondition.builder( - ItemPredicate.Builder.create() - .subPredicate(ItemSubPredicateTypes.POTION_CONTENTS, new PotionContentsPredicate(RegistryEntryList.of( - this.potions.getOrThrow(PotionKeys.WATER) - ))) + MatchToolLootCondition.builder(ItemPredicate.Builder.create() + .components(ComponentsPredicate.Builder.create() + .partial( + ComponentPredicateTypes.POTION_CONTENTS, + new PotionContentsPredicate(RegistryEntryList.of( + this.potions.getOrThrow(PotionKeys.WATER) + )) + ).build() + ) ) ), UncheckedSequenceHandler.builder() @@ -5495,11 +5501,16 @@ private void bootstrapToolsAndWeapons() { .itematic$usedItemAtLeast(TridentItem.MIN_DRAW_DURATION) .itematic$inWaterOrRain(true) ), - MatchToolLootCondition.builder( - ItemPredicate.Builder.create() - .subPredicate(ItemSubPredicateTypes.ENCHANTMENTS, EnchantmentsPredicate.enchantments(List.of( - new EnchantmentPredicate(this.enchantments.getOrThrow(Enchantments.RIPTIDE), NumberRange.IntRange.ANY) - )))) + MatchToolLootCondition.builder(ItemPredicate.Builder.create() + .components(ComponentsPredicate.Builder.create() + .partial( + ComponentPredicateTypes.ENCHANTMENTS, + EnchantmentsPredicate.enchantments(List.of( + new EnchantmentPredicate(this.enchantments.getOrThrow(Enchantments.RIPTIDE), NumberRange.IntRange.ANY) + )) + ).build() + ) + ) ), PassingSequenceHandler.builder() .add(TwirlPlayerAction.INSTANCE) @@ -7372,9 +7383,13 @@ private void bootstrapEquipment() { .with(StackableItemComponent.of(1)) .with(DamageableItemComponent.ofPreserved(432)) .with(GliderItemComponent.of(ItemPredicate.Builder.create() - .subPredicate(ItemSubPredicateTypes.DAMAGE, DamagePredicate.durability( - NumberRange.IntRange.atLeast(2))) - .build())) + .components(ComponentsPredicate.Builder.create() + .partial( + ComponentPredicateTypes.DAMAGE, + DamagePredicate.durability(NumberRange.IntRange.atLeast(2)) + ).build() + ).build() + )) .with(EquipmentItemComponent.of(EquippableComponent.builder(EquipmentSlot.CHEST) .swappable(true) .equipSound(this.soundEvents.getOrThrow(SoundEventKeys.ARMOR_EQUIP_ELYTRA)) diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockAccessor.java new file mode 100644 index 00000000..64087af2 --- /dev/null +++ b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockAccessor.java @@ -0,0 +1,17 @@ +package net.errorcraft.itematic.mixin.block; + +import net.minecraft.block.TntBlock; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(TntBlock.class) +public interface TntBlockAccessor { + @Invoker("primeTnt") + static boolean primeTnt(World world, BlockPos pos, @Nullable LivingEntity igniter) { + throw new AssertionError(); + } +} diff --git a/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java index b42c889d..83530a33 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/block/TntBlockExtender.java @@ -36,7 +36,7 @@ private boolean isOfForFlintAndSteelUseRegistryKeyCheck(ItemStack instance, Item } @ModifyExpressionValue( - method = "primeTnt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/LivingEntity;)V", + method = "primeTnt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/LivingEntity;)Z", at = @At( value = "NEW", target = "(Lnet/minecraft/world/World;DDDLnet/minecraft/entity/LivingEntity;)Lnet/minecraft/entity/TntEntity;" @@ -48,7 +48,7 @@ private static TntEntity setBlockState(TntEntity original, World world, BlockPos } @Redirect( - method = "primeTnt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/LivingEntity;)V", + method = "primeTnt(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/LivingEntity;)Z", at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;playSound(Lnet/minecraft/entity/Entity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V" diff --git a/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateUtil.java b/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateUtil.java index af08407e..a030b460 100644 --- a/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateUtil.java +++ b/src/main/java/net/errorcraft/itematic/predicate/item/ItemPredicateUtil.java @@ -6,30 +6,27 @@ import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; -import net.minecraft.predicate.ComponentPredicate; import net.minecraft.predicate.NumberRange; +import net.minecraft.predicate.component.ComponentsPredicate; import net.minecraft.predicate.item.ItemPredicate; -import net.minecraft.predicate.item.ItemSubPredicate; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntryList; -import java.util.Map; import java.util.Optional; public class ItemPredicateUtil { public static final PacketCodec PACKET_CODEC = PacketCodec.tuple( PacketCodecs.optional(PacketCodecs.registryEntryList(RegistryKeys.ITEM)), ItemPredicate::items, NumberRangeUtil.INTEGER_RANGE_PACKET_CODEC, ItemPredicate::count, - ComponentPredicate.PACKET_CODEC, ItemPredicate::components, - PacketCodecs.registryCodec(ItemSubPredicate.PREDICATES_MAP_CODEC), ItemPredicate::subPredicates, + ComponentsPredicate.PACKET_CODEC, ItemPredicate::components, ItemPredicateExtraFields.PACKET_CODEC, itemPredicate -> ((ItemPredicateAccess)(Object) itemPredicate).itematic$extraFields(), ItemPredicateUtil::create ); private ItemPredicateUtil() {} - private static ItemPredicate create(Optional> items, NumberRange.IntRange count, ComponentPredicate components, Map, ItemSubPredicate> subPredicates, ItemPredicateExtraFields extraFields) { - ItemPredicate predicate = new ItemPredicate(items, count, components, subPredicates); + private static ItemPredicate create(Optional> items, NumberRange.IntRange count, ComponentsPredicate components, ItemPredicateExtraFields extraFields) { + ItemPredicate predicate = new ItemPredicate(items, count, components); ((ItemPredicateAccess)(Object) predicate).itematic$setExtraFields(extraFields); return predicate; } diff --git a/src/main/java/net/errorcraft/itematic/village/trade/Trade.java b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java index ab82e420..b9047d4b 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trade.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java @@ -13,7 +13,7 @@ import net.minecraft.loot.context.LootContext; import net.minecraft.loot.function.LootFunction; import net.minecraft.loot.function.LootFunctionTypes; -import net.minecraft.predicate.ComponentPredicate; +import net.minecraft.predicate.component.ComponentMapPredicate; import net.minecraft.registry.RegistryEntryLookup; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; @@ -62,7 +62,7 @@ private Input createWantedStacks(LootContext context) { private TradedItem createGivenStack(Input wants, LootContext context) { ItemStack gives = this.gives.createStack(context); return this.tradeModifier.flatMap(tradeModifier -> tradeModifier.apply(wants, gives, context)) - .orElseGet(() -> new TradedItem(gives.getRegistryEntry(), gives.getCount(), ComponentPredicate.of(gives.getComponents()))); + .orElseGet(() -> new TradedItem(gives.getRegistryEntry(), gives.getCount(), ComponentMapPredicate.of(gives.getComponents()))); } public static Builder builder(Entry gives) { @@ -166,7 +166,7 @@ public Optional getTradedItem(int index) { } ItemStack stack = this.stacks.get(index); - return Optional.of(new TradedItem(stack.getRegistryEntry(), stack.getCount(), ComponentPredicate.of(stack.getComponents()))); + return Optional.of(new TradedItem(stack.getRegistryEntry(), stack.getCount(), ComponentMapPredicate.of(stack.getComponents()))); } public ItemStack getStack(int index) { diff --git a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/EnchantWithLevelsTradeModifier.java b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/EnchantWithLevelsTradeModifier.java index b20f8622..a1b1b777 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/EnchantWithLevelsTradeModifier.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/EnchantWithLevelsTradeModifier.java @@ -12,7 +12,7 @@ import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.item.ItemStack; import net.minecraft.loot.context.LootContext; -import net.minecraft.predicate.ComponentPredicate; +import net.minecraft.predicate.component.ComponentMapPredicate; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntryList; @@ -47,6 +47,6 @@ public Optional apply(Trade.Input wants, ItemStack gives, LootContex .getOptional(EnchantmentTags.ON_TRADED_EQUIPMENT); ItemStack givesActual = EnchantmentHelper.enchant(random, gives, level, registryManager, enchantments); wants.getStack(this.index).itematic$tryIncrement(level); - return Optional.of(new TradedItem(givesActual.getRegistryEntry(), givesActual.getCount(), ComponentPredicate.of(givesActual.getComponents()))); + return Optional.of(new TradedItem(givesActual.getRegistryEntry(), givesActual.getCount(), ComponentMapPredicate.of(givesActual.getComponents()))); } } diff --git a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java index d0da8dc9..d283654b 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/ItemFromTypeTradeModifier.java @@ -11,7 +11,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.loot.context.LootContext; import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.predicate.ComponentPredicate; +import net.minecraft.predicate.component.ComponentMapPredicate; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; @@ -49,6 +49,6 @@ public Optional apply(Trade.Input wants, ItemStack gives, LootContex } ItemStack givesActual = gives.itematic$copyWithItem(this.types.get(type)); - return Optional.of(new TradedItem(givesActual.getRegistryEntry(), givesActual.getCount(), ComponentPredicate.of(givesActual.getComponents()))); + return Optional.of(new TradedItem(givesActual.getRegistryEntry(), givesActual.getCount(), ComponentMapPredicate.of(givesActual.getComponents()))); } } diff --git a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/SingleEnchantmentTradeModifier.java b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/SingleEnchantmentTradeModifier.java index 60d5abfb..c55fe090 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/SingleEnchantmentTradeModifier.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/modifier/modifiers/SingleEnchantmentTradeModifier.java @@ -11,7 +11,7 @@ import net.minecraft.enchantment.Enchantment; import net.minecraft.item.ItemStack; import net.minecraft.loot.context.LootContext; -import net.minecraft.predicate.ComponentPredicate; +import net.minecraft.predicate.component.ComponentMapPredicate; import net.minecraft.registry.RegistryCodecs; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; @@ -47,7 +47,7 @@ public Optional apply(Trade.Input wants, ItemStack gives, LootContex Random random = context.getRandom(); this.enchantments.getRandom(random) .ifPresent(entry -> this.apply(wants.getStack(this.index), gives, random, entry)); - return Optional.of(new TradedItem(gives.getRegistryEntry(), gives.getCount(), ComponentPredicate.of(gives.getComponents()))); + return Optional.of(new TradedItem(gives.getRegistryEntry(), gives.getCount(), ComponentMapPredicate.of(gives.getComponents()))); } private void apply(ItemStack wants, ItemStack gives, Random random, RegistryEntry enchantment) { diff --git a/src/main/java/net/errorcraft/itematic/world/action/actions/PrimeTntAction.java b/src/main/java/net/errorcraft/itematic/world/action/actions/PrimeTntAction.java index 46066a78..2e828d5c 100644 --- a/src/main/java/net/errorcraft/itematic/world/action/actions/PrimeTntAction.java +++ b/src/main/java/net/errorcraft/itematic/world/action/actions/PrimeTntAction.java @@ -2,15 +2,18 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.errorcraft.itematic.mixin.block.TntBlockAccessor; 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.PositionTarget; -import net.minecraft.block.TntBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.loot.context.LootContextParameters; import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; +import net.minecraft.world.GameRules; public record PrimeTntAction(PositionTarget position) implements Action { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( @@ -28,15 +31,22 @@ public ActionType type() { @Override public boolean execute(ActionContext context) { - Vec3d pos = context.get(this.position.parameter()); + BlockPos pos = context.get(this.position.parameter(), BlockPos::ofFloored); if (pos == null) { return false; } ServerWorld world = context.world(); - BlockPos blockPos = BlockPos.ofFloored(pos); - TntBlock.primeTnt(world, blockPos); - world.removeBlock(blockPos, false); - return true; + PlayerEntity player = context.get(LootContextParameters.THIS_ENTITY, PlayerEntity.class); + if (TntBlockAccessor.primeTnt(world, pos, player)) { + world.removeBlock(pos, false); + return true; + } + + if (player != null && !world.getGameRules().getBoolean(GameRules.TNT_EXPLODES)) { + player.sendMessage(Text.translatable("block.minecraft.tnt.disabled"), true); + } + + return false; } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 90104996..38cc8e64 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -97,9 +97,6 @@ "net/minecraft/class_4538": [ "net/errorcraft/itematic/access/world/WorldViewAccess" ], - "net/minecraft/class_5289\u0024class_5290": [ - "net/errorcraft/itematic/access/client/gui/screen/GameModeSelectionScreenGameModeSelectionAccess" - ], "net/minecraft/class_6880": [ "net/errorcraft/itematic/access/registry/entry/RegistryEntryAccess" ], diff --git a/src/main/resources/itematic.classtweaker b/src/main/resources/itematic.classtweaker index 65206267..d2fd35f6 100644 --- a/src/main/resources/itematic.classtweaker +++ b/src/main/resources/itematic.classtweaker @@ -2,7 +2,7 @@ classTweaker v1 named accessible class net/minecraft/registry/Registries$Initializer accessible class net/minecraft/entity/passive/OcelotEntity$OcelotTemptGoal -accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection +accessible class net/minecraft/client/gui/screen/GameModeSwitcherScreen$GameModeSelection accessible class net/minecraft/client/gui/screen/StatsScreen$ItemStatsListWidget accessible class net/minecraft/client/gui/screen/StatsScreen$ItemStatsListWidget$Entry accessible class net/minecraft/client/gui/screen/world/CustomizeFlatLevelScreen$SuperflatLayersListWidget @@ -21,3 +21,4 @@ inject-interface net/minecraft/entity/EntityType$Builder net/errorcraft/it inject-interface net/minecraft/block/entity/BlockEntity net/errorcraft/itematic/access/block/entity/BlockEntityAccess inject-interface net/minecraft/village/VillagerData net/errorcraft/itematic/access/village/VillagerDataAccess inject-interface net/minecraft/village/VillagerProfession net/errorcraft/itematic/access/village/VillagerProfessionAccess +inject-interface net/minecraft/client/gui/screen/GameModeSwitcherScreen$GameModeSelection net/errorcraft/itematic/access/client/gui/screen/GameModeSwitcherScreenAccess$GameModeSelectionAccess diff --git a/src/main/resources/itematic.mixins.json b/src/main/resources/itematic.mixins.json index 6c25a8f7..a342f1e6 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -55,6 +55,7 @@ "block.StemBlockExtender", "block.SweetBerryBushBlockExtender", "block.TallSeagrassBlockExtender", + "block.TntBlockAccessor", "block.TntBlockExtender", "block.TorchflowerBlockExtender", "block.TripwireBlockExtender", From 49615b1c62dff9ae265107dbe4c7cd7d4b649b26 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 22:16:30 +0200 Subject: [PATCH 09/12] Port to 1.21.5 pre-release 1 --- gradle.properties | 6 +++--- .../mixin/network/state/PlayStateFactoriesExtender.java | 3 ++- .../itematic/screen/BrewingStandMenuDelegate.java | 9 +++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/gradle.properties b/gradle.properties index f2d9fcbd..58b99362 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=25w10a - yarn_mappings=25w10a+build.9 + minecraft_version=1.21.5-pre1 + yarn_mappings=1.21.5-pre1+build.2 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.118.5+1.21.5 + fabric_version=0.118.6+1.21.5 diff --git a/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java b/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java index 14f74efc..ae339e18 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java @@ -6,6 +6,7 @@ import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.listener.ClientPlayPacketListener; import net.minecraft.network.state.PlayStateFactories; +import net.minecraft.util.Unit; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,7 +18,7 @@ public class PlayStateFactoriesExtender { method = "method_55958", at = @At("TAIL") ) - private static void registerCustomS2CPackets(NetworkStateBuilder builder, CallbackInfo info) { + private static void registerCustomS2CPackets(NetworkStateBuilder builder, CallbackInfo info) { builder.add(ItematicPlayPackets.TWIRL, TwirlS2CPacket.CODEC); } } diff --git a/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java index 4f22c9f1..3e5b3b71 100644 --- a/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java +++ b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java @@ -4,6 +4,7 @@ import net.errorcraft.itematic.recipe.book.ItematicRecipeBookTypes; import net.errorcraft.itematic.recipe.brewing.BrewingRecipe; import net.errorcraft.itematic.recipe.input.BrewingRecipeInput; +import net.minecraft.class_10938; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -138,13 +139,13 @@ public void setPreviousTrackedSlot(int slot, ItemStack stack) { } @Override - public void setPreviousTrackedSlotMutable(int slot, ItemStack stack) { - this.delegate.setPreviousTrackedSlotMutable(slot, stack); + public void setPreviousTrackedSlotMutable(int slot, class_10938 hash) { + this.delegate.setPreviousTrackedSlotMutable(slot, hash); } @Override - public void setPreviousCursorStack(ItemStack stack) { - this.delegate.setPreviousCursorStack(stack); + public void setPreviousCursorStack(class_10938 cursorStackHash) { + this.delegate.setPreviousCursorStack(cursorStackHash); } @Override From 75927b708753f788415ac24393a1ee7976ca4998 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 22:29:17 +0200 Subject: [PATCH 10/12] Port to 1.21.5 pre-release 2 --- gradle.properties | 6 +++--- .../network/state/PlayStateFactoriesExtender.java | 2 +- .../itematic/screen/BrewingStandMenuDelegate.java | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gradle.properties b/gradle.properties index 58b99362..a1ce2a4a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.21.5-pre1 - yarn_mappings=1.21.5-pre1+build.2 + minecraft_version=1.21.5-pre2 + yarn_mappings=1.21.5-pre2+build.6 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.118.6+1.21.5 + fabric_version=0.119.0+1.21.5 diff --git a/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java b/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java index ae339e18..be48acfd 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/network/state/PlayStateFactoriesExtender.java @@ -2,9 +2,9 @@ import net.errorcraft.itematic.network.packet.ItematicPlayPackets; import net.errorcraft.itematic.network.packet.s2c.play.TwirlS2CPacket; -import net.minecraft.network.NetworkStateBuilder; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.state.NetworkStateBuilder; import net.minecraft.network.state.PlayStateFactories; import net.minecraft.util.Unit; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java index 3e5b3b71..8c492742 100644 --- a/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java +++ b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java @@ -4,7 +4,6 @@ import net.errorcraft.itematic.recipe.book.ItematicRecipeBookTypes; import net.errorcraft.itematic.recipe.brewing.BrewingRecipe; import net.errorcraft.itematic.recipe.input.BrewingRecipeInput; -import net.minecraft.class_10938; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -17,6 +16,7 @@ import net.minecraft.screen.*; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.screen.sync.ItemStackHash; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.collection.DefaultedList; @@ -134,18 +134,18 @@ public void updateToClient() { } @Override - public void setPreviousTrackedSlot(int slot, ItemStack stack) { - this.delegate.setPreviousTrackedSlot(slot, stack); + public void setReceivedStack(int slot, ItemStack stack) { + this.delegate.setReceivedStack(slot, stack); } @Override - public void setPreviousTrackedSlotMutable(int slot, class_10938 hash) { - this.delegate.setPreviousTrackedSlotMutable(slot, hash); + public void setReceivedHash(int slot, ItemStackHash hash) { + this.delegate.setReceivedHash(slot, hash); } @Override - public void setPreviousCursorStack(class_10938 cursorStackHash) { - this.delegate.setPreviousCursorStack(cursorStackHash); + public void setReceivedCursorHash(ItemStackHash cursorStackHash) { + this.delegate.setReceivedCursorHash(cursorStackHash); } @Override From 0b02a3513b60bc96d3c7d0e856281d12f7c8b4a9 Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 22:44:15 +0200 Subject: [PATCH 11/12] Port to 1.21.5 pre-release 3 --- gradle.properties | 6 +++--- .../item/component/components/MappableItemComponent.java | 7 ++++--- .../itematic/mixin/item/FilledMapItemAccessor.java | 3 ++- .../loot/function/ExplorationMapLootFunctionExtender.java | 6 +++--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index a1ce2a4a..eb9c34e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.21.5-pre2 - yarn_mappings=1.21.5-pre2+build.6 + minecraft_version=1.21.5-pre3 + yarn_mappings=1.21.5-pre3+build.2 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.119.0+1.21.5 + fabric_version=0.119.2+1.21.5 diff --git a/src/main/java/net/errorcraft/itematic/item/component/components/MappableItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/MappableItemComponent.java index 14b9db35..f164a6a7 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/components/MappableItemComponent.java +++ b/src/main/java/net/errorcraft/itematic/item/component/components/MappableItemComponent.java @@ -16,6 +16,7 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryFixedCodec; +import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvents; import net.minecraft.stat.Stats; import net.minecraft.util.Hand; @@ -42,19 +43,19 @@ public Codec codec() { @Override public ItemResult use(World world, PlayerEntity user, Hand hand, ItemStack stack, ItemStackExchanger stackExchanger) { - if (world.isClient()) { + if (!(world instanceof ServerWorld serverWorld)) { return ItemResult.SUCCEED; } user.incrementStat(Stats.USED.itematic$getOrCreateStat(stack.getRegistryEntry())); world.playSoundFromEntity(null, user, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, user.getSoundCategory(), 1.0f, 1.0f); - ItemStack resultStack = this.createStack(world, user.getBlockX(), user.getBlockZ(), 0, true, false); + ItemStack resultStack = this.createStack(serverWorld, user.getBlockX(), user.getBlockZ(), 0, true, false); stack.decrementUnlessCreative(1, user); stackExchanger.exchange(resultStack); return ItemResult.CONSUME; } - public ItemStack createStack(World world, int x, int z, int scale, boolean showIcons, boolean unlimitedTracking) { + public ItemStack createStack(ServerWorld world, int x, int z, int scale, boolean showIcons, boolean unlimitedTracking) { ItemStack resultStack = new ItemStack(this.transformsInto); MapIdComponent mapId = FilledMapItemAccessor.allocateMapId(world, x, z, scale, showIcons, unlimitedTracking, world.getRegistryKey()); resultStack.set(DataComponentTypes.MAP_ID, mapId); diff --git a/src/main/java/net/errorcraft/itematic/mixin/item/FilledMapItemAccessor.java b/src/main/java/net/errorcraft/itematic/mixin/item/FilledMapItemAccessor.java index 21919f0c..3ff31434 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/item/FilledMapItemAccessor.java +++ b/src/main/java/net/errorcraft/itematic/mixin/item/FilledMapItemAccessor.java @@ -3,6 +3,7 @@ import net.minecraft.component.type.MapIdComponent; import net.minecraft.item.FilledMapItem; import net.minecraft.registry.RegistryKey; +import net.minecraft.server.world.ServerWorld; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @@ -10,7 +11,7 @@ @Mixin(FilledMapItem.class) public interface FilledMapItemAccessor { @Invoker("allocateMapId") - static MapIdComponent allocateMapId(World world, int x, int z, int scale, boolean showIcons, boolean unlimitedTracking, RegistryKey dimension) { + static MapIdComponent allocateMapId(ServerWorld world, int x, int z, int scale, boolean showIcons, boolean unlimitedTracking, RegistryKey dimension) { throw new AssertionError(); } } diff --git a/src/main/java/net/errorcraft/itematic/mixin/loot/function/ExplorationMapLootFunctionExtender.java b/src/main/java/net/errorcraft/itematic/mixin/loot/function/ExplorationMapLootFunctionExtender.java index a41cd670..1b4f44b7 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/loot/function/ExplorationMapLootFunctionExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/loot/function/ExplorationMapLootFunctionExtender.java @@ -7,7 +7,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.loot.function.ExplorationMapLootFunction; -import net.minecraft.world.World; +import net.minecraft.server.world.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -33,10 +33,10 @@ private boolean isOfForMapUseItemComponentCheck(ItemStack instance, Item item, @ method = "process", at = @At( value = "INVOKE", - target = "Lnet/minecraft/item/FilledMapItem;createMap(Lnet/minecraft/world/World;IIBZZ)Lnet/minecraft/item/ItemStack;" + target = "Lnet/minecraft/item/FilledMapItem;createMap(Lnet/minecraft/server/world/ServerWorld;IIBZZ)Lnet/minecraft/item/ItemStack;" ) ) - private ItemStack createMapUseItemComponent(World world, int x, int z, byte scale, boolean showIcons, boolean unlimitedTracking, @Share("mappableItemComponent") LocalRef mappableItemComponent) { + private ItemStack createMapUseItemComponent(ServerWorld world, int x, int z, byte scale, boolean showIcons, boolean unlimitedTracking, @Share("mappableItemComponent") LocalRef mappableItemComponent) { return mappableItemComponent.get().createStack(world, x, z, scale, showIcons, unlimitedTracking); } } From d0ea8dc27fd98837d89357072f6352a57e751c1f Mon Sep 17 00:00:00 2001 From: ErrorCraft Date: Wed, 8 Apr 2026 23:27:58 +0200 Subject: [PATCH 12/12] Update to 1.21.5 --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index eb9c34e5..8ced8aab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.21.5-pre3 - yarn_mappings=1.21.5-pre3+build.2 + minecraft_version=1.21.5 + yarn_mappings=1.21.5+build.1 loader_version=0.18.4 # Mod Properties @@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx1G archives_base_name = itematic # Dependencies - fabric_version=0.119.2+1.21.5 + fabric_version=0.128.2+1.21.5