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 fee1b16f..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.4 - yarn_mappings=1.21.4+build.8 + 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.4+1.21.4 + fabric_version=0.128.2+1.21.5 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b95..d997cfc6 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ 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/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/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/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/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/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..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;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/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 new file mode 100644 index 00000000..897d5b6a --- /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/ItemDisplayContext;)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 d07ca01a..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", @@ -40,7 +40,6 @@ "gui.tooltip.TooltipComponentExtender", "network.AbstractClientPlayerEntityExtender", "network.ClientPlayerEntityExtender", - "network.ClientPlayerInteractionManagerExtender", "network.ClientPlayNetworkHandlerExtender", "option.HotbarStorageEntryExtender", "particle.CrackParticleExtender$SlimeballFactoryExtender", @@ -54,10 +53,10 @@ "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", + "render.item.property.select.ChargeTypePropertyExtender", "tutorial.CraftPlanksTutorialStepHandlerExtender", "world.ClientWorldExtender", "world.WorldEventHandlerExtender" 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/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java b/src/datagen/java/net/errorcraft/itematic/data/server/tag/ItemTagProvider.java index dee2d04c..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,10 +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) @@ -946,9 +946,15 @@ 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) + .add(ItemKeys.LEAF_LITTER) .add(ItemKeys.SPORE_BLOSSOM) + .add(ItemKeys.FIREFLY_BUSH) .add(ItemKeys.BAMBOO) .add(ItemKeys.SUGAR_CANE) .add(ItemKeys.CACTUS) @@ -960,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) @@ -1260,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) @@ -1390,9 +1401,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/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/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..b2092de5 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)); + 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 6c5790d1..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,35 +1,33 @@ package net.errorcraft.itematic.gametest.item.component; -import net.errorcraft.itematic.component.ItematicDataComponentTypes; +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.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(world.itematic$createStack(ItemKeys.POTION), Potions.LEAPING); - player.setStackInHand(Hand.MAIN_HAND, stack); + ItemStack potion = PotionContentsComponentUtil.setPotion( + world.itematic$createStack(ItemKeys.POTION), + Potions.LEAPING + ); + 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( - TestUtil.getDataComponent(stack, ItematicDataComponentTypes.USE_DURATION).ticks(stack, 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..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 @@ -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"); - context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); + ActionResult result = splashPotion.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Splash Potion usage to be successful" + ); + context.expectEntityAt(EntityType.SPLASH_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"); - context.expectEntityAt(EntityType.POTION, SPAWN_POSITION.add(0, (int)player.getStandingEyeHeight(), 0)); + ActionResult result = lingeringPotion.use(world, player, Hand.MAIN_HAND); + Assert.isTrue( + context, + result.isAccepted(), + () -> "Expected Lingering Potion usage to be successful" + ); + context.expectEntityAt(EntityType.LINGERING_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 bd4b8bc2..ad498e73 100644 --- a/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java +++ b/src/gametest/java/net/errorcraft/itematic/mixin/gametest/TestContextExtender.java @@ -2,21 +2,37 @@ 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.util.math.Vec3d; +import net.minecraft.world.GameMode; 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; @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 setPlayerData(PlayerEntity original, GameMode gameMode) { + original.setPosition(this.getAbsolute(Vec3d.ZERO)); + gameMode.setAbilities(original.getAbilities()); + return original; + } + @ModifyReturnValue( method = "createMockCreativeServerPlayerInWorld", at = @At("TAIL") 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..c936ae8c --- /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_DIRECTORY = 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_DIRECTORY != null) { + return Paths.get(STRUCTURE_OUTPUT_DIRECTORY); + } + + 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 00000000..47ef87c2 Binary files /dev/null and b/src/gametest/resources/data/itematic/structure/item.brush.platform.nbt differ 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 00000000..09b27d21 Binary files /dev/null and b/src/gametest/resources/data/itematic/structure/item.brush.platform.short_grass.nbt differ diff --git a/src/gametest/resources/data/itematic/structure/item.brush.platform.suspicious_sand.nbt b/src/gametest/resources/data/itematic/structure/item.brush.platform.suspicious_sand.nbt new file mode 100644 index 00000000..fe705978 Binary files /dev/null and b/src/gametest/resources/data/itematic/structure/item.brush.platform.suspicious_sand.nbt differ 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/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/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/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/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/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/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/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/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/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 c704e4ac..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,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 2d1cca75..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_hit": 2 + "item_damage_per_attack": 2 } }, "display": { 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/diamond_pickaxe.json b/src/main/generated/data/minecraft/item/diamond_pickaxe.json index 0e2a1e0f..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_hit": 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 6878e057..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_hit": 2 + "item_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/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/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/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/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/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 e1feb855..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,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 7b0a13ee..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_hit": 2 + "item_damage_per_attack": 2 } }, "display": { 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/golden_pickaxe.json b/src/main/generated/data/minecraft/item/golden_pickaxe.json index f9e06186..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_hit": 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 b496c65f..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_hit": 2 + "item_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/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 0b7da415..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,8 @@ "rules": [] }, "attack_speed": 0.225, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 45981982..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_hit": 2 + "item_damage_per_attack": 2 } }, "display": { 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/iron_pickaxe.json b/src/main/generated/data/minecraft/item/iron_pickaxe.json index 8e29e465..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_hit": 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 e8870512..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_hit": 2 + "item_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/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 new file mode 100644 index 00000000..b6b67c72 --- /dev/null +++ b/src/main/generated/data/minecraft/item/leaf_litter.json @@ -0,0 +1,18 @@ +{ + "behavior": { + "minecraft:block": { + "block": "minecraft:leaf_litter" + }, + "minecraft:compostable": { + "level_increase_chance": 0.3 + }, + "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/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/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..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,8 @@ "rules": [] }, "attack_speed": 0.25, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 3c53188a..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_hit": 2 + "item_damage_per_attack": 2 } }, "display": { 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_pickaxe.json b/src/main/generated/data/minecraft/item/netherite_pickaxe.json index 648220e6..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_hit": 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 bff386d9..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_hit": 2 + "item_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/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/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/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/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/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..89358302 100644 --- a/src/main/generated/data/minecraft/item/shield.json +++ b/src/main/generated/data/minecraft/item/shield.json @@ -1,5 +1,16 @@ { "behavior": { + "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, + "factor": 1.0, + "threshold": 3.0 + } + }, "minecraft:banner_pattern_holder": {}, "minecraft:damageable": { "durability": 336 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/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 9c0ca595..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,8 @@ "rules": [] }, "attack_speed": 0.2, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 6a3916bc..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_hit": 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 1387786d..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_hit": 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 2120a114..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_hit": 2 + "item_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/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/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/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/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/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/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 68077771..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,8 @@ "rules": [] }, "attack_speed": 0.2, - "damage_per_hit": 2 + "disable_blocking_for_seconds": 5.0, + "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 d8d36a08..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_hit": 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 011de7bf..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_hit": 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 8f11fc3a..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_hit": 2 + "item_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/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/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/functional_blocks.json b/src/main/generated/data/minecraft/item_group_entry_provider/functional_blocks.json index 140e3e88..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,9 +125,15 @@ "pattern": "minecraft:border" } ], - "minecraft:hide_additional_tooltip": {}, - "minecraft:item_name": "{\"translate\":\"block.minecraft.ominous_banner\"}", - "minecraft:rarity": "uncommon" + "minecraft:item_name": { + "translate": "block.minecraft.ominous_banner" + }, + "minecraft:rarity": "uncommon", + "minecraft:tooltip_display": { + "hidden_components": [ + "minecraft:banner_patterns" + ] + } }, "item": "minecraft:white_banner" }, 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/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/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 a13f080e..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,10 +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", @@ -24,9 +24,15 @@ "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", + "minecraft:leaf_litter", "minecraft:spore_blossom", + "minecraft:firefly_bush", "minecraft:bamboo", "minecraft:sugar_cane", "minecraft:cactus", @@ -38,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/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/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..4b55f3fa --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_baked_potato.json @@ -0,0 +1,13 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 2, + "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..f44fd873 --- /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": 2, + "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..7fe903e9 --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_hay_block.json @@ -0,0 +1,12 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 2, + "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..4286b833 --- /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": 2, + "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..e6ffa50f --- /dev/null +++ b/src/main/generated/data/minecraft/trade/buy_water_bottle.json @@ -0,0 +1,16 @@ +{ + "gives": { + "item": "minecraft:emerald" + }, + "max_uses": 2, + "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..ddc32491 --- /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": 2, + "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 2118d8bf..52a2e04a 100644 --- a/src/main/java/net/errorcraft/itematic/Itematic.java +++ b/src/main/java/net/errorcraft/itematic/Itematic.java @@ -6,10 +6,11 @@ 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; +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; @@ -32,7 +33,7 @@ public void onInitialize() { SequenceHandlerTypes.init(); ItematicPredicateTypes.init(); ItematicContextParameters.init(); - SmithingTemplateTypes.init(); + SmithingTemplates.init(); BlockPickerTypes.init(); ItematicItemModifierTypes.init(); TradeModifierTypes.init(); @@ -45,5 +46,6 @@ public void onInitialize() { ItematicRecipeBookCategories.init(); ItematicRecipeDisplaySerializers.init(); ItematicSlotDisplaySerializers.init(); + ItematicEntitySubPredicateTypes.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..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,16 +8,10 @@ import java.util.Optional; public interface SherdsAccess { - default NbtCompound itematic$toNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup lookup) { - return null; - } default List>> itematic$optionalEntries() { return null; } 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/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/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/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..11038326 100644 --- a/src/main/java/net/errorcraft/itematic/block/BlockKeys.java +++ b/src/main/java/net/errorcraft/itematic/block/BlockKeys.java @@ -139,6 +139,9 @@ 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 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"); @@ -266,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"); @@ -1012,6 +1016,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"); @@ -1062,6 +1068,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/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/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/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/ItemKeys.java b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java index 8020c448..aac3921c 100644 --- a/src/main/java/net/errorcraft/itematic/item/ItemKeys.java +++ b/src/main/java/net/errorcraft/itematic/item/ItemKeys.java @@ -210,9 +210,13 @@ 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 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"); @@ -261,6 +265,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"); @@ -329,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"); @@ -967,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 d775207e..64611afa 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,9 +17,9 @@ 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.function.SplitItemModifier; import net.errorcraft.itematic.loot.predicate.SideCheckPredicate; import net.errorcraft.itematic.mixin.item.BrushItemAccessor; import net.errorcraft.itematic.mixin.item.CrossbowItemAccessor; @@ -31,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; @@ -50,30 +50,40 @@ 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; 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.loot.function.SetComponentsLootFunction; +import net.minecraft.loot.function.SetNameLootFunction; import net.minecraft.particle.ParticleTypes; import net.minecraft.potion.Potion; import net.minecraft.predicate.BlockPredicate; 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.*; 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.stat.Stats; +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; @@ -82,12 +92,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)); @@ -135,12 +146,14 @@ 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 final RegistryEntryLookup chickenVariants; private Bootstrapper(Registerable registerable) { this.registerable = registerable; @@ -151,12 +164,14 @@ 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); + this.chickenVariants = registerable.getRegistryLookup(RegistryKeys.CHICKEN_VARIANT); } private void bootstrap() { @@ -175,6 +190,7 @@ private void bootstrap() { this.bootstrapBanners(); this.bootstrapDecoratedPotPatterns(); this.bootstrapImmuneToDamage(); + this.bootstrapTrimMaterialProviders(); this.bootstrapMiscellaneous(); } @@ -199,7 +215,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(), @@ -215,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() @@ -263,7 +282,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 +292,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 +302,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 +313,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 +324,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 +334,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 +356,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 +367,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 +378,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 +388,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 +398,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 +710,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 +5122,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() @@ -5473,8 +5485,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, 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)) @@ -5488,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) @@ -5557,7 +5575,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) @@ -6387,7 +6405,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( @@ -6395,7 +6413,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( @@ -6403,7 +6421,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( @@ -6411,7 +6429,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( @@ -6419,7 +6437,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( @@ -6427,7 +6445,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( @@ -6435,7 +6453,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( @@ -6443,7 +6461,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( @@ -6451,7 +6469,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( @@ -6459,7 +6477,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( @@ -6467,7 +6485,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() @@ -6479,7 +6497,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() @@ -6491,7 +6509,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() @@ -6503,7 +6521,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() @@ -6515,7 +6533,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() @@ -6527,7 +6545,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() @@ -6539,7 +6557,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() @@ -6551,7 +6569,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() @@ -6563,7 +6581,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() @@ -6575,7 +6593,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( @@ -6583,7 +6601,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( @@ -6591,7 +6609,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( @@ -6599,7 +6617,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( @@ -6607,7 +6625,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( @@ -6615,7 +6633,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( @@ -6623,7 +6641,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( @@ -6631,7 +6649,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( @@ -6639,7 +6657,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( @@ -6647,7 +6665,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( @@ -6655,7 +6673,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( @@ -6663,7 +6681,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( @@ -6671,7 +6689,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( @@ -6679,7 +6697,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() )); @@ -6688,7 +6706,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( @@ -6696,7 +6714,39 @@ 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( + ItemDisplay.Builder.forBlock(ItemKeys.WILDFLOWERS).build(), + ItemComponentSet.builder() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.WILDFLOWERS))) + .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.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( @@ -6704,7 +6754,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( @@ -6712,7 +6762,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( @@ -6720,7 +6770,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( @@ -6728,7 +6778,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( @@ -6736,7 +6786,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( @@ -6744,7 +6794,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( @@ -6752,7 +6802,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( @@ -6760,7 +6810,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( @@ -6768,7 +6818,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)) @@ -6779,7 +6829,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() )); @@ -6788,7 +6838,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)) @@ -6799,7 +6849,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( @@ -6807,7 +6857,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( @@ -6815,7 +6865,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( @@ -6823,7 +6873,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( @@ -6831,7 +6881,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( @@ -6839,7 +6889,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")) @@ -6852,7 +6902,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( @@ -6860,14 +6910,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( @@ -6875,7 +6925,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) )) @@ -6889,7 +6939,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) )) @@ -6903,7 +6953,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) )) @@ -6917,7 +6967,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) )) @@ -6931,7 +6981,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) )) @@ -6945,7 +6995,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) )) @@ -6959,7 +7009,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) )) @@ -6973,7 +7023,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) )) @@ -6987,7 +7037,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) )) @@ -7001,7 +7051,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) )) @@ -7015,7 +7065,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) )) @@ -7029,7 +7079,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) )) @@ -7043,7 +7093,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) )) @@ -7057,7 +7107,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) )) @@ -7071,7 +7121,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) )) @@ -7085,7 +7135,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() @@ -7097,7 +7147,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( @@ -7105,7 +7155,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( @@ -7113,7 +7163,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( @@ -7121,7 +7171,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( @@ -7129,7 +7179,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( @@ -7137,7 +7187,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( @@ -7145,7 +7195,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)) @@ -7156,7 +7206,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)) @@ -7167,7 +7217,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)) @@ -7178,7 +7228,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)) @@ -7189,7 +7239,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)) @@ -7200,7 +7250,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)) @@ -7211,7 +7261,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( @@ -7219,7 +7269,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( @@ -7227,7 +7277,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( @@ -7235,7 +7285,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( @@ -7243,7 +7293,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( @@ -7251,7 +7301,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( @@ -7259,7 +7309,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( @@ -7267,7 +7317,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() @@ -7279,7 +7329,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) )) @@ -7293,7 +7343,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( @@ -7301,7 +7351,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( @@ -7309,7 +7359,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( @@ -7317,7 +7367,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() )); } @@ -7333,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)) @@ -7354,12 +7408,25 @@ 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( + 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)) + ))) .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()) @@ -7370,9 +7437,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))) @@ -7381,9 +7448,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))) @@ -7392,9 +7459,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))) @@ -7403,9 +7470,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))) @@ -7416,9 +7483,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))) @@ -7428,9 +7495,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))) @@ -7440,9 +7507,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))) @@ -7452,9 +7519,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))) @@ -7462,9 +7529,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))) @@ -7472,9 +7539,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))) @@ -7482,9 +7549,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))) @@ -7492,9 +7559,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))) @@ -7502,9 +7569,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))) @@ -7512,9 +7579,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))) @@ -7522,9 +7589,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))) @@ -7532,9 +7599,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))) @@ -7542,9 +7609,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))) @@ -7552,9 +7619,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))) @@ -7562,9 +7629,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))) @@ -7572,9 +7639,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))) @@ -7582,9 +7649,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))) @@ -7593,9 +7660,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))) @@ -7604,9 +7671,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))) @@ -7615,9 +7682,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))) @@ -7626,9 +7693,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))) @@ -7636,42 +7703,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() )); @@ -7684,7 +7770,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 @@ -7697,7 +7783,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 @@ -7710,7 +7796,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 @@ -7723,7 +7809,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 @@ -7736,7 +7822,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 @@ -7749,7 +7835,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 @@ -7762,7 +7848,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 @@ -9470,6 +9556,33 @@ 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() + .with(StackableItemComponent.of(64)) + .with(BlockItemComponent.of(this.blocks.getOrThrow(BlockKeys.LEAF_LITTER))) + .with(FuelItemComponent.of(FuelTimes.PLANT)) + .with(CompostableItemComponent.of(CompostChances.SMALL)) + .build() + )); } private void bootstrapProjectiles() { @@ -9495,7 +9608,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() )); @@ -9606,7 +9767,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() )); @@ -9633,7 +9794,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() )); @@ -9911,7 +10072,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)) @@ -9988,153 +10149,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() )); } @@ -10582,6 +10781,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( @@ -10603,92 +10803,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(SaddleItemComponent.INSTANCE) - .with(DispensableItemComponent.of(this.dispenseBehaviors.getOrThrow(DispenseBehaviors.SADDLE))) - .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() @@ -10747,7 +10979,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( @@ -10758,7 +10989,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), @@ -11075,16 +11324,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( @@ -11117,12 +11356,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() @@ -11264,7 +11497,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/ItematicItemTags.java b/src/main/java/net/errorcraft/itematic/item/ItematicItemTags.java index ae56727b..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"); @@ -149,7 +150,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/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 798ad585..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; @@ -21,8 +20,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); @@ -43,8 +42,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) { @@ -59,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; } @@ -73,5 +69,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 ad24c21d..361b852a 100644 --- a/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java +++ b/src/main/java/net/errorcraft/itematic/item/component/ItemComponentTypes.java @@ -32,13 +32,10 @@ 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)); - 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)); @@ -58,6 +55,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..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 @@ -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,11 +41,13 @@ 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()); + + return Optional.of(baseTranslationKey + "." + baseColor.getId()); } public static BannerPatternHolderItemComponent of() { 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 55034de6..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,17 +43,18 @@ 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()), 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, - attackDamage, + 0.0f, + 4.0d + material.attackDamageBonus(), 0.4d ), EnchantableItemComponent.of(material), @@ -62,35 +63,30 @@ 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, 0.0f, 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, 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, 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, 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, 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, - realAttackDamage, + disableBlockingForSeconds, + baseAttackDamage + material.attackDamageBonus(), attackSpeed ), EnchantableItemComponent.of(material), @@ -98,6 +94,11 @@ private static ItemComponent[] tool(RegistryEntryLookup blocks, ToolMa }; } + @Override + public ItemComponentType type() { + return ItemComponentTypes.DAMAGEABLE; + } + @Override public Codec codec() { return CODEC; @@ -107,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/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/EntityItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/EntityItemComponent.java index f321ced2..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 @@ -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; @@ -44,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( @@ -115,33 +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; } - RegistryWrapper.WrapperLookup lookup = context.getRegistryLookup(); - if (lookup == null) { - return; - } - - NbtComponent entityData = stack.getOrDefault(DataComponentTypes.ENTITY_DATA, NbtComponent.DEFAULT); - if (!entityData.isEmpty()) { - entityData.get(lookup.getOps(NbtOps.INSTANCE), PaintingEntity.VARIANT_MAP_CODEC).result().ifPresentOrElse( - variant -> { - 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()) { - tooltip.add(RANDOM_TEXT); + RegistryEntry paintingVariant = stack.get(DataComponentTypes.PAINTING_VARIANT); + if (paintingVariant != null) { + 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()) { + 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..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,20 +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.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.world.World; -import java.util.List; - -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() { @@ -39,18 +36,8 @@ 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); } - - @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/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/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..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), true)); + 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/PotionHolderItemComponent.java b/src/main/java/net/errorcraft/itematic/item/component/components/PotionHolderItemComponent.java index c9fe7e8e..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 @@ -5,22 +5,24 @@ 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.item.Item; +import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; import net.minecraft.util.dynamic.Codecs; - -import java.util.List; +import net.minecraft.world.World; 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; @@ -32,26 +34,23 @@ public Codec codec() { } @Override - public void addComponents(ComponentMap.Builder builder) { - builder.add(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT); - } - - @Override - public void appendTooltip(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipType type) { + public void finishUsing(World world, LivingEntity user, ItemStack stack, int usedTicks, ItemStackExchanger stackExchanger) { PotionContentsComponent potionContents = stack.get(DataComponentTypes.POTION_CONTENTS); if (potionContents != null) { - potionContents.buildTooltip(tooltip::add, this.durationMultiplier, context.getUpdateTickRate()); + 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); + } + 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/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/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/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/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/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/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 882a0857..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 @@ -13,46 +13,46 @@ 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.type.AttributeModifiersComponent; +import net.minecraft.component.DataComponentTypes; +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 damagePerHit, WeaponAttackDamageDataComponent attackDamage, double attackSpeed, boolean maySmash) 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("damage_per_hit", 1).forGetter(WeaponItemComponent::damagePerHit), + Codecs.NON_NEGATIVE_INT.optionalFieldOf("item_damage_per_attack", 1).forGetter(WeaponItemComponent::itemDamagePerAttack), + 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), - 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, float disableBlockingForSeconds, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, + disableBlockingForSeconds, + false, new WeaponAttackDamageDataComponent(List.of(), attackDamage), - attackSpeed, - false + attackSpeed ); } public static WeaponItemComponent ofSmashing(int damagePerHit, double attackDamage, double attackSpeed) { return new WeaponItemComponent( damagePerHit, + 0.0f, + true, new WeaponAttackDamageDataComponent(List.of(), attackDamage), - attackSpeed, - true + attackSpeed ); } @@ -67,16 +67,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,34 +86,16 @@ 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.itemDamagePerAttack(), context); + } } @Override public void addComponents(ComponentMap.Builder builder) { + 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/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/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/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/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/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/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/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/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/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/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/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/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/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 a1f3b685..83530a33 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; @@ -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,11 +48,11 @@ 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/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/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 84875f91..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 @@ -1,22 +1,23 @@ 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.nbt.NbtCompound; -import net.minecraft.nbt.NbtOps; +import net.minecraft.item.ItemStack; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.codec.PacketCodecs; 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 +25,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 +127,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,15 +162,19 @@ private static Optional> optionalUseValueFromList(T valu return sherds.get(index); } - @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; + @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 @@ -206,12 +189,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/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/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/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/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/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/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/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/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/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/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/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/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/passive/MerchantEntityExtender.java b/src/main/java/net/errorcraft/itematic/mixin/entity/passive/MerchantEntityExtender.java index c26b8720..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 @@ -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) {} @@ -83,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/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/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..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 @@ -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; @@ -32,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) { @@ -61,7 +63,8 @@ private ItemStack newItemStackForPotionUseCreateStack(Item item, RegistryEntry

Stat getOrCreateStatForActiveItemUseRegistryEntry(StatType instance, T key) { - return instance.itematic$getOrCreateStat(this.activeItemStack.getRegistryEntry()); - } - @Redirect( method = "attack", at = @At( @@ -119,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/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/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/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/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/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/item/ItemExtender.java b/src/main/java/net/errorcraft/itematic/mixin/item/ItemExtender.java index 24dfd3bd..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,7 +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.component.components.DamageableItemComponent; +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; @@ -51,8 +51,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 +63,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 { @@ -257,11 +255,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 +275,6 @@ public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attack } tryUpdateItemStack(attacker, Hand.MAIN_HAND, stack, stackExchanger); - return result; } /** @@ -388,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)); } /** @@ -438,28 +432,15 @@ 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"), cancellable = true ) - private void useDebugStickItemComponent(BlockState state, World world, BlockPos pos, PlayerEntity miner, CallbackInfoReturnable 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); }); } @@ -486,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. @@ -508,18 +478,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"), @@ -568,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) @@ -679,6 +635,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 cced66df..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,14 +2,12 @@ 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; 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 +20,9 @@ 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.TooltipDisplayComponent; +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; @@ -66,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; @@ -237,12 +231,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", @@ -292,7 +297,7 @@ private Item getItemGetItemFieldUseRegistryEntryToPreventNullPointerException(It } @Redirect( - method = "copy", + method = "copy()Lnet/minecraft/item/ItemStack;", at = @At( value = "NEW", target = "(Lnet/minecraft/item/ItemConvertible;ILnet/minecraft/component/MergedComponentMap;)Lnet/minecraft/item/ItemStack;" @@ -505,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;" @@ -550,15 +557,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( @@ -567,7 +574,7 @@ private void postMineUseRegistryEntryNullCheck(World world, BlockState state, Bl ) 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); } @@ -640,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); } } @@ -667,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 @@ -776,19 +783,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) { @@ -812,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); } @@ -823,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/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); } } 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..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,10 +2,11 @@ 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; 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/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..9ff0f309 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; @@ -28,7 +25,7 @@ public class SmithingTransformRecipeExtender implements RecipeAccess { @Shadow @Final - Optional base; + Ingredient base; @Shadow @Final @@ -36,27 +33,16 @@ 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) { return List.of( new SmithingRecipeDisplay( Ingredient.toDisplay(this.template), - Ingredient.toDisplay(this.base), + this.base.toDisplay(), 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/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/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/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 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/screen/HorseScreenHandlerExtender.java b/src/main/java/net/errorcraft/itematic/mixin/screen/HorseScreenHandlerExtender.java deleted file mode 100644 index f6f5f562..00000000 --- a/src/main/java/net/errorcraft/itematic/mixin/screen/HorseScreenHandlerExtender.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.errorcraft.itematic.mixin.screen; - -import net.errorcraft.itematic.item.ItemKeys; -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; - -public class HorseScreenHandlerExtender { - @Mixin(targets = "net/minecraft/screen/HorseScreenHandler$1") - public static class SaddleSlotExtender { - @Redirect( - method = "canInsert", - 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/screen/LoomScreenHandlerExtender.java b/src/main/java/net/errorcraft/itematic/mixin/screen/LoomScreenHandlerExtender.java index 629894ae..1f71e941 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/screen/LoomScreenHandlerExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/screen/LoomScreenHandlerExtender.java @@ -1,68 +1,37 @@ package net.errorcraft.itematic.mixin.screen; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; 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.BannerPatternHolderItemComponent; -import net.errorcraft.itematic.item.component.components.BannerPatternItemComponent; import net.errorcraft.itematic.item.component.components.DyeItemComponent; -import net.minecraft.block.entity.BannerPattern; -import net.minecraft.item.*; -import net.minecraft.registry.tag.TagKey; +import net.minecraft.item.BannerItem; +import net.minecraft.item.DyeItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.screen.LoomScreenHandler; import net.minecraft.util.DyeColor; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Redirect; import java.util.Optional; @Mixin(LoomScreenHandler.class) public class LoomScreenHandlerExtender { - @ModifyConstant( - method = "getPatternsFor", - constant = @Constant( - classValue = BannerPatternItem.class, - ordinal = 0 - ) - ) - private boolean instanceOfBannerPatternItemUseItemComponent(Object reference, Class 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/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/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 cc936855..19477cbb 100644 --- a/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java +++ b/src/main/java/net/errorcraft/itematic/mixin/village/VillagerDataExtender.java @@ -3,6 +3,7 @@ import net.errorcraft.itematic.access.village.VillagerDataAccess; import net.errorcraft.itematic.registry.ItematicRegistryKeys; import net.errorcraft.itematic.village.trade.Trade; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -18,7 +19,7 @@ public class VillagerDataExtender implements VillagerDataAccess { @Shadow @Final - private VillagerProfession profession; + private 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 = 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/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/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/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/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/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/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/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/screen/BrewingStandMenuDelegate.java b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java index 4f22c9f1..8c492742 100644 --- a/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java +++ b/src/main/java/net/errorcraft/itematic/screen/BrewingStandMenuDelegate.java @@ -16,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; @@ -133,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, ItemStack stack) { - this.delegate.setPreviousTrackedSlotMutable(slot, stack); + public void setReceivedHash(int slot, ItemStackHash hash) { + this.delegate.setReceivedHash(slot, hash); } @Override - public void setPreviousCursorStack(ItemStack stack) { - this.delegate.setPreviousCursorStack(stack); + public void setReceivedCursorHash(ItemStackHash cursorStackHash) { + this.delegate.setReceivedCursorHash(cursorStackHash); } @Override 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/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/village/trade/Trade.java b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java index 17029b3d..b9047d4b 100644 --- a/src/main/java/net/errorcraft/itematic/village/trade/Trade.java +++ b/src/main/java/net/errorcraft/itematic/village/trade/Trade.java @@ -9,10 +9,11 @@ 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; -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; @@ -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); @@ -51,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) { @@ -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,8 +164,9 @@ 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()))); + 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/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 a4433d63..2dbb6aa8 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() {} @@ -378,6 +425,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 +458,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())); @@ -428,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)); @@ -516,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())); @@ -530,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())); @@ -669,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)); @@ -680,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)); @@ -703,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)); @@ -712,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))); + 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)); 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) { @@ -728,7 +824,15 @@ private static Trade buy(RegistryEntryLookup items, RegistryEntry it .build(); } - private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry item, Map> types) { + 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)) .tradeExperience(TradeOffersAccessor.masterTradeExperience()) @@ -736,6 +840,14 @@ private static Trade buyFromType(RegistryEntryLookup items, RegistryEntry< .build(); } + 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())) + .maxUses(2) + .tradeExperience(1) + .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)) @@ -744,6 +856,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)) @@ -769,9 +899,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) @@ -786,6 +920,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); } @@ -813,6 +955,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)) 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 df0faf6b..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; @@ -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,11 +42,13 @@ 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()))); + 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/ActionTypeKeys.java b/src/main/java/net/errorcraft/itematic/world/action/ActionTypeKeys.java index ebca8365..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"); @@ -40,7 +39,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..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)); @@ -41,7 +40,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/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/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/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/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/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/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/fabric.mod.json b/src/main/resources/fabric.mod.json index 7f18687c..38cc8e64 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -94,21 +94,9 @@ "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" - ], "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 5955614d..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 @@ -19,3 +19,6 @@ 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 +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 71ef2423..a342f1e6 100644 --- a/src/main/resources/itematic.mixins.json +++ b/src/main/resources/itematic.mixins.json @@ -50,10 +50,12 @@ "block.PumpkinBlockExtender", "block.RespawnAnchorBlockExtender", "block.ScaffoldingBlockExtender", + "block.SegmentedExtender", "block.ShulkerBoxBlockExtender", "block.StemBlockExtender", "block.SweetBerryBushBlockExtender", "block.TallSeagrassBlockExtender", + "block.TntBlockAccessor", "block.TntBlockExtender", "block.TorchflowerBlockExtender", "block.TripwireBlockExtender", @@ -88,12 +90,16 @@ "component.type.ConsumableComponentExtender", "component.type.DyedColorComponentExtender", "component.type.EquippableComponentExtender", + "component.type.LodestoneTrackerComponentExtender", + "component.type.MapIdComponentExtender", "component.type.ToolComponentExtender", "component.type.ToolComponentExtender$RuleExtender", "datafixer.SchemasExtender", + "enchantment.EnchantmentHelperAccessor", "enchantment.EnchantmentHelperExtender", "entity.BucketableExtender", "entity.CrossbowUserExtender", + "entity.EntityAccessor", "entity.EntityExtender", "entity.EntityTypeExtender", "entity.EntityTypeExtender$BuilderExtender", @@ -131,6 +137,7 @@ "entity.mob.BlazeEntityExtender", "entity.mob.BoggedEntityExtender", "entity.mob.CaveSpiderEntityExtender", + "entity.mob.CreakingEntityExtender", "entity.mob.CreeperEntityExtender", "entity.mob.DrownedEntityExtender", "entity.mob.DrownedEntityExtender$TridentAttackGoalExtender", @@ -174,7 +181,6 @@ "entity.passive.AbstractDonkeyEntityExtender", "entity.passive.AbstractDonkeyEntityExtender$StackReferenceExtender", "entity.passive.AbstractHorseEntityExtender", - "entity.passive.AbstractHorseEntityExtender$SaddleStackReferenceExtender", "entity.passive.AllayEntityExtender", "entity.passive.ArmadilloEntityExtender", "entity.passive.AxolotlEntityExtender", @@ -233,8 +239,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", @@ -252,7 +259,6 @@ "fluid.LavaFluidExtender", "fluid.WaterFluidExtender", "inventory.SimpleInventoryExtender", - "item.AnimalArmorItemExtender$TypeExtender", "item.BoneMealItemExtender", "item.BrushItemAccessor", "item.BrushItemExtender", @@ -309,7 +315,6 @@ "recipe.ArmorDyeRecipeExtender", "recipe.BannerDuplicateRecipeExtender", "recipe.BlastingRecipeExtender", - "recipe.BookCloningRecipeExtender", "recipe.CampfireCookingRecipeExtender", "recipe.CraftingDecoratedPotRecipeExtender", "recipe.FireworkRocketRecipeExtender", @@ -334,6 +339,7 @@ "recipe.StonecuttingRecipeExtender", "recipe.TippedArrowRecipeExtender", "recipe.TransmuteRecipeExtender", + "recipe.TransmuteRecipeResultExtender", "recipe.book.RecipeBookOptionsExtender", "recipe.display.SlotDisplayExtender$AnyFuelSlotDisplayExtender", "recipe.display.SlotDisplayExtender$ItemSlotDisplayExtender", @@ -348,8 +354,8 @@ "registry.entry.RegistryEntryExtender$ReferenceExtender", "registry.entry.RegistryEntryListExtender", "registry.entry.RegistryEntryListExtender$ListBackedExtender", + "scoreboard.ScoreboardCriterionAccessor", "scoreboard.ScoreboardCriterionExtender", - "scoreboard.ScoreboardStateExtender", "screen.AbstractFurnaceScreenHandlerExtender", "screen.AnvilScreenHandlerExtender", "screen.BrewingStandScreenHandlerAccessor", @@ -362,7 +368,6 @@ "screen.EnchantmentScreenHandlerExtender$LapisLazuliSlotExtender", "screen.GrindstoneScreenHandlerExtender", "screen.GrindstoneScreenHandlerExtender$EnchantedItemSlotExtender", - "screen.HorseScreenHandlerExtender$SaddleSlotExtender", "screen.LoomScreenHandlerExtender", "screen.LoomScreenHandlerExtender$BannerPatternSlotExtender", "screen.LoomScreenHandlerExtender$BannerSlotExtender", @@ -370,7 +375,6 @@ "screen.ScreenHandlerTypeAccessor", "screen.ScreenHandlerTypeExtender", "screen.slot.FurnaceFuelSlotExtender", - "server.ServerPlayerInteractionManagerExtender", "server.command.ScoreboardCommandExtender", "server.network.ServerPlayNetworkHandlerExtender", "sound.SoundCategoryExtender",