Fixes shearing leads for custom shears (interacting with entity & leash knot) (#10706)

This commit is contained in:
cech12 authored and GitHub committed 2025-11-19 17:39:39 -08:00
1 parent fae5c92daf
commit e75f0b67fe
5 files changed
+141 -1

No files matched your search

@@ -238,7 +238,12 @@
p_409579_.addFreshEntity(itementity);
return itementity;
}
@@ -2127,7 +_,7 @@
@@ -2123,11 +_,11 @@
}
ItemStack itemstack = p_19978_.getItemInHand(p_19979_);
- if (itemstack.is(Items.SHEARS) && this.shearOffAllLeashConnections(p_19978_)) {
+ if (itemstack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.shearOffAllLeashConnections(p_19978_)) {
itemstack.hurtAndBreak(1, p_19978_, p_19979_);
return InteractionResult.SUCCESS;
} else if (this instanceof Mob mob
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
+++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
@@ -72,7 +_,7 @@
if (this.level().isClientSide) {
return InteractionResult.SUCCESS;
} else {
- if (p_31842_.getItemInHand(p_31843_).is(Items.SHEARS)) {
+ if (p_31842_.getItemInHand(p_31843_).canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST)) {
InteractionResult interactionresult = super.interact(p_31842_, p_31843_);
if (interactionresult instanceof InteractionResult.Success interactionresult$success && interactionresult$success.wasItemInteraction()) {
return interactionresult;
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:shears_behavior/custom_shears_unleash_entity",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:shears_behavior/custom_shears_unleash_knot",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}
@@ -0,0 +1,110 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.debug.gameplay.item;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.common.ToolAction;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.gametest.GameTest;
import net.minecraftforge.gametest.GameTestNamespace;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import net.minecraftforge.test.BaseTestMod;
@Mod(ShearsBehaviorTest.MOD_ID)
@GameTestNamespace("forge")
public class ShearsBehaviorTest extends BaseTestMod {
public static final String MOD_ID = "shears_behavior";
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
private static final RegistryObject<Item> CUSTOM_SHEARS_HARVEST_ITEM = ITEMS.register("custom_shears_harvest_item", () -> new ShearsHarvestItem(
new Item.Properties().stacksTo(1).setId(ITEMS.key("custom_shears_harvest_item"))
));
public ShearsBehaviorTest(FMLJavaModLoadingContext context) {
super(context, false, true);
this.testItem(lookup -> CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance());
}
@GameTest
public static void custom_shears_unleash_entity(GameTestHelper helper) {
helper.makeFloor();
// setup: fence + knot + leash cow
var fencePos = new BlockPos(1, 1, 1);
var cowPos = new BlockPos(0, 1, 1);
helper.setBlock(fencePos, Blocks.OAK_FENCE);
var cow = helper.spawnWithNoFreeWill(EntityType.COW, cowPos);
var knot = LeashFenceKnotEntity.getOrCreateKnot(helper.getLevel(), helper.absolutePos(fencePos));
cow.setLeashedTo(knot, true);
helper.assertTrue(cow.isLeashed(), "Cow should start leashed");
// act: interact with cow using custom shears
var player = helper.makeMockPlayer(GameType.SURVIVAL);
var shears = CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance();
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
var result = player.interactOn(cow, InteractionHand.MAIN_HAND);
// assert
helper.assertTrue(result.consumesAction(), "Using custom shears on leashed cow should result in consume action");
helper.assertTrue(!cow.isLeashed(), "Cow should be unleashed by custom shears");
helper.assertItemEntityPresent(Items.LEAD);
helper.succeed();
}
@GameTest
public static void custom_shears_unleash_knot(GameTestHelper helper) {
helper.makeFloor();
// setup: fence + knot + leash cow
var fencePos = new BlockPos(1, 1, 1);
var cowPos = new BlockPos(0, 1, 1);
helper.setBlock(fencePos, Blocks.OAK_FENCE);
var cow = helper.spawnWithNoFreeWill(EntityType.COW, cowPos);
var knot = LeashFenceKnotEntity.getOrCreateKnot(helper.getLevel(), helper.absolutePos(fencePos));
cow.setLeashedTo(knot, true);
helper.assertTrue(cow.isLeashed(), "Cow should start leashed");
// act: interact with knot using custom shears
var player = helper.makeMockPlayer(GameType.SURVIVAL);
var shears = CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance();
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
var result = player.interactOn(knot, InteractionHand.MAIN_HAND);
// assert
helper.assertTrue(result.consumesAction(), "Using custom shears on leash knot should result in consume action");
helper.assertTrue(!cow.isLeashed(), "Cow should be unleashed by sheared knot");
helper.assertItemEntityPresent(Items.LEAD);
helper.succeed();
}
private static final class ShearsHarvestItem extends Item {
ShearsHarvestItem(Item.Properties properties) {
super(properties);
}
@Override
public boolean canPerformAction(ItemStack stack, ToolAction action) {
return action == ToolActions.SHEARS_HARVEST;
}
}
}