Fix damageItem's game test not using onBreak callback correctly (#10452)

This commit is contained in:
Jonathing authored and GitHub committed 2025-02-18 13:38:04 -08:00
1 parent 90dc29b1ef
commit 03d07a9621
1 file changed
+64 -6
@@ -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<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
private static final RegistryObject<FakeShieldItem> FAKE_SHIELD = ITEMS.register("fake_shield", FakeShieldItem::new);
private static final RegistryObject<FakeShieldItem> FAKE_SHIELD = ITEMS.register("fake_shield", () -> new FakeShieldItem(true));
private static final RegistryObject<FakeShieldItem> 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.<LivingEntityUseItemEvent.Start>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 <T extends LivingEntity> int damageItem(ItemStack stack, int amount, T entity, Consumer<T> onBroken) {
onBroken.accept(entity);
if (this.breakOnDamage) {
onBroken.accept(entity);
}
return 1;
}
}