From 03d07a9621f5d07f4e8341cfddafc1a27ea769b6 Mon Sep 17 00:00:00 2001 From: Jonathing Date: Tue, 18 Feb 2025 16:38:04 -0500 Subject: [PATCH] Fix damageItem's game test not using onBreak callback correctly (#10452) --- .../gameplay/item/PreventItemDamageTest.java | 70 +++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/src/test/java/net/minecraftforge/debug/gameplay/item/PreventItemDamageTest.java b/src/test/java/net/minecraftforge/debug/gameplay/item/PreventItemDamageTest.java index 307be56a9c..e3db38fb18 100644 --- a/src/test/java/net/minecraftforge/debug/gameplay/item/PreventItemDamageTest.java +++ b/src/test/java/net/minecraftforge/debug/gameplay/item/PreventItemDamageTest.java @@ -11,6 +11,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.gametest.framework.GameTest; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageTypes; @@ -28,7 +29,9 @@ import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.test.BaseTestMod; +import org.jetbrains.annotations.Nullable; +import java.util.Objects; import java.util.function.Consumer; @Mod(PreventItemDamageTest.MOD_ID) @@ -37,10 +40,12 @@ public class PreventItemDamageTest extends BaseTestMod { static final String MOD_ID = "prevent_item_damage"; private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID); - private static final RegistryObject FAKE_SHIELD = ITEMS.register("fake_shield", FakeShieldItem::new); + private static final RegistryObject FAKE_SHIELD = ITEMS.register("fake_shield", () -> new FakeShieldItem(true)); + private static final RegistryObject FAKE_UNBREAKING_SHIELD = ITEMS.register("fake_unbreaking_shield", () -> new FakeShieldItem(false)); public PreventItemDamageTest() { this.testItem(() -> FAKE_SHIELD.get().getDefaultInstance()); + this.testItem(() -> FAKE_UNBREAKING_SHIELD.get().getDefaultInstance()); } @GameTest(template = "forge:empty3x3x3") @@ -50,6 +55,56 @@ public class PreventItemDamageTest extends BaseTestMod { // setup player var player = helper.makeMockPlayer(GameType.SURVIVAL); + // setup shield + var shield = FAKE_UNBREAKING_SHIELD.get().getDefaultInstance(); + + // setup events + var firedLivingEntityUseItem = helper.boolFlag("fired LivingEntityUseItemEvent"); + helper.addEventListener(event -> { + if (event.getEntity() != player) return; + + if (event.getItem() != shield) + helper.fail("Player is using an item, but it's not the fake shield! Check the game test impl."); + + // Artificially pass 5 seconds from start of the shield + // This is because the first 5 ticks, the player is still vulnerable + firedLivingEntityUseItem.set(true); + event.setDuration(event.getDuration() - 100); + }); + + // start using shield + player.setItemInHand(InteractionHand.MAIN_HAND, shield); + player.startUsingItem(InteractionHand.MAIN_HAND); + int initialDamage = shield.getDamageValue(); + + // setup enemy + var enemy = helper.spawnWithNoFreeWill(EntityType.HUSK, new BlockPos(2, 0, 2)); + player.lookAt(EntityAnchorArgument.Anchor.EYES, enemy.position()); + + // hit the player + var attack = helper.registryLookup(Registries.DAMAGE_TYPE).getOrThrow(DamageTypes.MOB_ATTACK); + var damage = new DamageSource(attack, enemy) { + @Override + public boolean scalesWithDifficulty() { + return false; + } + }; + player.hurt(damage, 5.0F); + + // ok, run the tests + firedLivingEntityUseItem.assertEquals(true); + helper.assertValueEqual(initialDamage + 1, shield.getDamageValue(), "shield damage value", "Fake shield did not take precisely 1 damage! Check IForgeItem#damageItem."); + helper.assertValueEqual(player.getItemInHand(InteractionHand.MAIN_HAND), shield, "player shield", "Fake shield was removed from player's hand! Check Player#hurtCurrentlyUsedShield."); + helper.succeed(); + } + + @GameTest(template = "forge:empty3x3x3") + public static void player_fake_shield_breaks(GameTestHelper helper) { + helper.makeFloor(); + + // setup player + var player = helper.makeMockPlayer(GameType.SURVIVAL); + // setup shield var shield = FAKE_SHIELD.get().getDefaultInstance(); @@ -79,7 +134,6 @@ public class PreventItemDamageTest extends BaseTestMod { // start using shield player.setItemInHand(InteractionHand.MAIN_HAND, shield); player.startUsingItem(InteractionHand.MAIN_HAND); - int initialDamage = shield.getDamageValue(); // setup enemy var enemy = helper.spawnWithNoFreeWill(EntityType.HUSK, new BlockPos(2, 0, 2)); @@ -98,8 +152,7 @@ public class PreventItemDamageTest extends BaseTestMod { // ok, run the tests firedLivingEntityUseItem.assertEquals(true); firedPlayerDestroyItem.assertEquals(true); - helper.assertValueEqual(initialDamage + 1, shield.getDamageValue(), "shield damage value", "Fake shield did not take precisely 1 damage! Check IForgeItem#damageItem."); - helper.assertValueEqual(player.getItemInHand(InteractionHand.MAIN_HAND), shield, "player shield", "Fake shield was removed from player's hand! Check Player#hurtCurrentlyUsedShield."); + helper.assertFalse(shield.isEmpty(), () -> "Fake shield called onBreak callback, but was set to empty! Check FakeShieldItem or IForgeItem#damageItem."); helper.succeed(); } @@ -133,13 +186,18 @@ public class PreventItemDamageTest extends BaseTestMod { } private static final class FakeShieldItem extends ShieldItem { - public FakeShieldItem() { + private final boolean breakOnDamage; + + public FakeShieldItem(boolean breakOnDamage) { super(new Item.Properties().durability(10)); + this.breakOnDamage = breakOnDamage; } @Override public int damageItem(ItemStack stack, int amount, T entity, Consumer onBroken) { - onBroken.accept(entity); + if (this.breakOnDamage) { + onBroken.accept(entity); + } return 1; } }