mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 00:37:52 +00:00
Add use context and simulate flag to getToolModifiedState, enabled HOE_TILL action. (#8557)
This commit is contained in:
1 parent
94ce098056
commit
7d79f0d581
12 files changed
+268
-74
No files matched your search
@@ -11,7 +11,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
public class ToolAction
|
||||
public final class ToolAction
|
||||
{
|
||||
private static final Map<String, ToolAction> actions = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ToolActions
|
||||
public static final ToolAction SHOVEL_DIG = ToolAction.get("shovel_dig");
|
||||
|
||||
/**
|
||||
* Exposed by shovels to allow querying tool behaviours
|
||||
* Exposed by hoes to allow querying tool behaviours
|
||||
*/
|
||||
public static final ToolAction HOE_DIG = ToolAction.get("hoe_dig");
|
||||
|
||||
@@ -90,10 +90,10 @@ public class ToolActions
|
||||
*/
|
||||
public static final ToolAction SHEARS_DISARM = ToolAction.get("shears_disarm");
|
||||
|
||||
///**
|
||||
// * Passed onto {@link IForgeBlock#getToolModifiedState} when a hoe wants to turn dirt into soil
|
||||
// */
|
||||
// TODO: public static final ToolAction HOE_TILL = ToolAction.get("till");
|
||||
/**
|
||||
* Passed onto {@link IForgeBlock#getToolModifiedState} when a hoe wants to turn dirt into soil
|
||||
*/
|
||||
public static final ToolAction HOE_TILL = ToolAction.get("till");
|
||||
|
||||
/**
|
||||
* A tool action corresponding to the 'block' action of shields.
|
||||
@@ -102,7 +102,7 @@ public class ToolActions
|
||||
|
||||
// Default actions supported by each tool type
|
||||
public static final Set<ToolAction> DEFAULT_AXE_ACTIONS = of(AXE_DIG, AXE_STRIP, AXE_SCRAPE, AXE_WAX_OFF);
|
||||
public static final Set<ToolAction> DEFAULT_HOE_ACTIONS = of(HOE_DIG /* TODO: , HOE_TILL */);
|
||||
public static final Set<ToolAction> DEFAULT_HOE_ACTIONS = of(HOE_DIG, HOE_TILL);
|
||||
public static final Set<ToolAction> DEFAULT_SHOVEL_ACTIONS = of(SHOVEL_DIG, SHOVEL_FLATTEN);
|
||||
public static final Set<ToolAction> DEFAULT_PICKAXE_ACTIONS = of(PICKAXE_DIG);
|
||||
public static final Set<ToolAction> DEFAULT_SWORD_ACTIONS = of(SWORD_DIG, SWORD_SWEEP);
|
||||
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.FishingHook;
|
||||
import net.minecraft.world.entity.projectile.WitherSkull;
|
||||
import net.minecraft.world.item.*;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
@@ -662,9 +663,48 @@ public interface IForgeBlock
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state that this block should transform into when right clicked by a tool.
|
||||
* For example: Used to determine if an axe can strip, a shovel can path, or a hoe can till.
|
||||
* Return null if vanilla behavior should be disabled.
|
||||
* Returns the state that this block should transform into when right-clicked by a tool.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip},
|
||||
* {@link ToolActions#SHOVEL_FLATTEN a shovel can path}, or {@link ToolActions#HOE_TILL a hoe can till}.
|
||||
* Returns {@code null} if nothing should happen.
|
||||
*
|
||||
* @param state The current state
|
||||
* @param context The use on context that the action was performed in
|
||||
* @param toolAction The action being performed by the tool
|
||||
* @param simulate If {@code true}, no actions that modify the world in any way should be performed. If {@code false}, the world may be modified.
|
||||
* @return The resulting state after the action has been performed
|
||||
*/
|
||||
@Nullable
|
||||
default BlockState getToolModifiedState(BlockState state, UseOnContext context, ToolAction toolAction, boolean simulate)
|
||||
{
|
||||
BlockState toolModifiedState = getToolModifiedState(state, context.getLevel(), context.getClickedPos(),
|
||||
context.getPlayer(), context.getItemInHand(), toolAction);
|
||||
|
||||
if (toolModifiedState == null && ToolActions.HOE_TILL == toolAction && context.getItemInHand().canPerformAction(ToolActions.HOE_TILL))
|
||||
{
|
||||
// Logic copied from HoeItem#TILLABLES; needs to be kept in sync during updating
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.ROOTED_DIRT)
|
||||
{
|
||||
if (!simulate && !context.getLevel().isClientSide)
|
||||
{
|
||||
Block.popResourceFromFace(context.getLevel(), context.getClickedPos(), context.getClickedFace(), new ItemStack(Items.HANGING_ROOTS));
|
||||
}
|
||||
return Blocks.DIRT.defaultBlockState();
|
||||
} else if ((block == Blocks.GRASS_BLOCK || block == Blocks.DIRT_PATH || block == Blocks.DIRT || block == Blocks.COARSE_DIRT) &&
|
||||
context.getLevel().getBlockState(context.getClickedPos().above()).isAir())
|
||||
{
|
||||
return block == Blocks.COARSE_DIRT ? Blocks.DIRT.defaultBlockState() : Blocks.FARMLAND.defaultBlockState();
|
||||
}
|
||||
}
|
||||
|
||||
return toolModifiedState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state that this block should transform into when right-clicked by a tool.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip} or {@link ToolActions#SHOVEL_FLATTEN a shovel can path}.
|
||||
* Returns {@code null} if nothing should happen.
|
||||
*
|
||||
* @param state The current state
|
||||
* @param level The level
|
||||
@@ -673,18 +713,20 @@ public interface IForgeBlock
|
||||
* @param stack The stack being used by the player
|
||||
* @param toolAction The action being performed by the tool
|
||||
* @return The resulting state after the action has been performed
|
||||
* @deprecated Override and use {@link #getToolModifiedState(BlockState, UseOnContext, ToolAction, boolean)} instead
|
||||
*/
|
||||
@Nullable
|
||||
// TODO 1.19: Remove this and move the default impl to the newer method in 1.19. Has to stay here to preserve behavior of overrides on this method.
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
default BlockState getToolModifiedState(BlockState state, Level level, BlockPos pos, Player player, ItemStack stack, ToolAction toolAction)
|
||||
{
|
||||
if (!stack.canPerformAction(toolAction)) return null;
|
||||
if (ToolActions.AXE_STRIP.equals(toolAction)) return AxeItem.getAxeStrippingState(state);
|
||||
else if(ToolActions.AXE_SCRAPE.equals(toolAction)) return WeatheringCopper.getPrevious(state).orElse(null);
|
||||
else if(ToolActions.AXE_WAX_OFF.equals(toolAction)) return Optional.ofNullable(HoneycombItem.WAX_OFF_BY_BLOCK.get().get(state.getBlock())).map((p_150694_) -> {
|
||||
if (ToolActions.AXE_STRIP == toolAction) return AxeItem.getAxeStrippingState(state);
|
||||
else if(ToolActions.AXE_SCRAPE == toolAction) return WeatheringCopper.getPrevious(state).orElse(null);
|
||||
else if(ToolActions.AXE_WAX_OFF == toolAction) return Optional.ofNullable(HoneycombItem.WAX_OFF_BY_BLOCK.get().get(state.getBlock())).map((p_150694_) -> {
|
||||
return p_150694_.withPropertiesOf(state);
|
||||
}).orElse(null);
|
||||
//else if(ToolActions.HOE_TILL.equals(toolAction)) return HoeItem.getHoeTillingState(state); //TODO HoeItem bork
|
||||
else if (ToolActions.SHOVEL_FLATTEN.equals(toolAction)) return ShovelItem.getShovelPathingState(state);
|
||||
else if (ToolActions.SHOVEL_FLATTEN == toolAction) return ShovelItem.getShovelPathingState(state);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.FishingHook;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
@@ -37,6 +38,7 @@ import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.common.ToolAction;
|
||||
import net.minecraftforge.common.ToolActions;
|
||||
|
||||
public interface IForgeBlockState
|
||||
{
|
||||
@@ -603,9 +605,27 @@ public interface IForgeBlockState
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state that this block should transform into when right clicked by a tool.
|
||||
* For example: Used to determine if an axe can strip, a shovel can path, or a hoe can till.
|
||||
* Return null if vanilla behavior should be disabled.
|
||||
* Returns the state that this block should transform into when right-clicked by a tool.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip},
|
||||
* {@link ToolActions#SHOVEL_FLATTEN a shovel can path}, or {@link ToolActions#HOE_TILL a hoe can till}.
|
||||
* Returns {@code null} if nothing should happen.
|
||||
*
|
||||
* @param context The use on context that the action was performed in
|
||||
* @param toolAction The action being performed by the tool
|
||||
* @param simulate If {@code true}, no actions that modify the world in any way should be performed. If {@code false}, the world may be modified.
|
||||
* @return The resulting state after the action has been performed
|
||||
*/
|
||||
@Nullable
|
||||
default BlockState getToolModifiedState(UseOnContext context, ToolAction toolAction, boolean simulate)
|
||||
{
|
||||
BlockState eventState = net.minecraftforge.event.ForgeEventFactory.onToolUse(self(), context, toolAction, simulate);
|
||||
return eventState != self() ? eventState : self().getBlock().getToolModifiedState(self(), context, toolAction, simulate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state that this block should transform into when right-clicked by a tool.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip} or {@link ToolActions#SHOVEL_FLATTEN a shovel can path}.
|
||||
* Returns {@code null} if nothing should happen.
|
||||
*
|
||||
* @param level The level
|
||||
* @param pos The block position in level
|
||||
@@ -613,8 +633,11 @@ public interface IForgeBlockState
|
||||
* @param stack The stack being used by the player
|
||||
* @param toolAction The tool type to be considered when performing the action
|
||||
* @return The resulting state after the action has been performed
|
||||
* @deprecated Use {@link #getToolModifiedState(UseOnContext, ToolAction, boolean)} instead
|
||||
*/
|
||||
@Nullable
|
||||
// TODO 1.19: Remove
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
default BlockState getToolModifiedState(Level level, BlockPos pos, Player player, ItemStack stack, ToolAction toolAction)
|
||||
{
|
||||
BlockState eventState = net.minecraftforge.event.ForgeEventFactory.onToolUse(self(), level, pos, player, stack, toolAction);
|
||||
|
||||
@@ -125,6 +125,7 @@ import net.minecraftforge.event.entity.player.UseHoeEvent;
|
||||
import net.minecraftforge.event.furnace.FurnaceFuelBurnTimeEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.BlockToolInteractEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.BlockToolModificationEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.CreateFluidSourceEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.EntityMultiPlaceEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
|
||||
@@ -345,8 +346,8 @@ public class ForgeEventFactory
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? "" : event.getMessage();
|
||||
}
|
||||
|
||||
//TODO: 1.17 Remove
|
||||
@Deprecated
|
||||
//TODO 1.19: Remove
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
public static int onHoeUse(UseOnContext context)
|
||||
{
|
||||
UseHoeEvent event = new UseHoeEvent(context);
|
||||
@@ -360,6 +361,21 @@ public class ForgeEventFactory
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BlockState onToolUse(BlockState originalState, UseOnContext context, ToolAction toolAction, boolean simulate)
|
||||
{
|
||||
// TODO 1.19: Remove ternary and just use BlockToolModificationEvent constructor with simulate parameter passed in
|
||||
BlockToolModificationEvent event = simulate
|
||||
? new BlockToolModificationEvent(originalState, context, toolAction, true)
|
||||
: new BlockToolInteractEvent(originalState, context, toolAction);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getFinalState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onToolUse(BlockState, UseOnContext, ToolAction, boolean)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
// TODO 1.19: Remove
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
public static BlockState onToolUse(BlockState originalState, Level level, BlockPos pos, Player player, ItemStack stack, ToolAction toolAction)
|
||||
{
|
||||
BlockToolInteractEvent event = new BlockToolInteractEvent(level, pos, originalState, player, stack, toolAction);
|
||||
|
||||
@@ -19,12 +19,11 @@ import javax.annotation.Nonnull;
|
||||
* and damage the hoe.
|
||||
*
|
||||
* setResult(ALLOW) is the same as the old setHandled();
|
||||
*
|
||||
* TODO: 1.17 Remove
|
||||
*/
|
||||
@Cancelable
|
||||
@HasResult
|
||||
@Deprecated
|
||||
// TODO 1.19: Remove
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
public class UseHoeEvent extends PlayerEvent
|
||||
{
|
||||
private final UseOnContext context;;
|
||||
|
||||
@@ -8,6 +8,7 @@ package net.minecraftforge.event.world;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.portal.PortalShape;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
@@ -22,6 +23,7 @@ import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.ToolAction;
|
||||
import net.minecraftforge.common.ToolActions;
|
||||
import net.minecraftforge.common.util.BlockSnapshot;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
@@ -415,65 +417,159 @@ public class BlockEvent extends Event
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when when this block is right clicked by a tool to change its state.
|
||||
* For example: Used to determine if an axe can strip or a shovel can path.
|
||||
* For hoes, see {@code net.minecraft.world.item.HoeItem#TILLABLES} and
|
||||
* {@link net.minecraftforge.event.entity.player.UseHoeEvent}.
|
||||
*
|
||||
* Fired when a block is right-clicked by a tool to change its state.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip},
|
||||
* {@link ToolActions#SHOVEL_FLATTEN a shovel can path}, or {@link ToolActions#HOE_TILL a hoe can till}.
|
||||
* <p>
|
||||
* This deprecated subclass event is <i>only</i> fired when {@link #isSimulated()} is false.
|
||||
* To receive simulated events, use {@link BlockToolModificationEvent}.
|
||||
* <p>
|
||||
* This event is {@link Cancelable}. If canceled, this will prevent the tool
|
||||
* from changing the block's state.
|
||||
*
|
||||
* @deprecated Use {@link BlockToolModificationEvent} and put world-modifying actions behind <code>if (!event.isSimulated())</code>.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class BlockToolInteractEvent extends BlockEvent
|
||||
@Deprecated(forRemoval = true, since = "1.18.2")
|
||||
public static class BlockToolInteractEvent extends BlockToolModificationEvent
|
||||
{
|
||||
|
||||
private final Player player;
|
||||
private final ItemStack stack;
|
||||
private final ToolAction toolAction;
|
||||
private BlockState state;
|
||||
|
||||
public BlockToolInteractEvent(BlockState originalState, @Nonnull UseOnContext context, ToolAction toolAction)
|
||||
{
|
||||
super(originalState, context, toolAction, false);
|
||||
this.player = context.getPlayer();
|
||||
this.stack = context.getItemInHand();
|
||||
}
|
||||
|
||||
public BlockToolInteractEvent(LevelAccessor world, BlockPos pos, BlockState originalState, Player player, ItemStack stack, ToolAction toolAction)
|
||||
{
|
||||
super(world, pos, originalState);
|
||||
super(world, pos, originalState, toolAction);
|
||||
this.player = player;
|
||||
this.stack = stack;
|
||||
this.state = originalState;
|
||||
this.toolAction = toolAction;
|
||||
}
|
||||
|
||||
/**Gets the player using the tool.*/
|
||||
public Player getPlayer()
|
||||
{
|
||||
return player;
|
||||
}
|
||||
|
||||
/**Gets the tool being used.*/
|
||||
public ItemStack getHeldItemStack()
|
||||
{
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**Gets the action being performed.*/
|
||||
public ToolAction getToolAction()
|
||||
{
|
||||
return toolAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transformed state after tool use.
|
||||
* If not set, will return the original state.
|
||||
* This will be bypassed if canceled returning null instead.
|
||||
* */
|
||||
public void setFinalState(BlockState finalState)
|
||||
* @return the player using the tool, never null
|
||||
*/
|
||||
@Nonnull
|
||||
public Player getPlayer()
|
||||
{
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public ItemStack getHeldItemStack()
|
||||
{
|
||||
return this.stack;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a block is right-clicked by a tool to change its state.
|
||||
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip},
|
||||
* {@link ToolActions#SHOVEL_FLATTEN a shovel can path}, or {@link ToolActions#HOE_TILL a hoe can till}.
|
||||
* <p>
|
||||
* Care must be taken to ensure world-modifying events are only performed if {@link #isSimulated()} returns {@code true}.
|
||||
* <p>
|
||||
* This event is {@link Cancelable}. If canceled, this will prevent the tool
|
||||
* from changing the block's state.
|
||||
*/
|
||||
public static class BlockToolModificationEvent extends BlockEvent
|
||||
{
|
||||
private final UseOnContext context;
|
||||
private final ToolAction toolAction;
|
||||
private final boolean simulate;
|
||||
private BlockState state;
|
||||
|
||||
public BlockToolModificationEvent(BlockState originalState, @Nonnull UseOnContext context, ToolAction toolAction, boolean simulate)
|
||||
{
|
||||
super(context.getLevel(), context.getClickedPos(), originalState);
|
||||
this.context = context;
|
||||
this.state = originalState;
|
||||
this.toolAction = toolAction;
|
||||
this.simulate = simulate;
|
||||
}
|
||||
|
||||
// TODO 1.19: Remove
|
||||
BlockToolModificationEvent(LevelAccessor level, BlockPos pos, BlockState originalState, ToolAction toolAction)
|
||||
{
|
||||
super(level, pos, originalState);
|
||||
this.context = null;
|
||||
this.state = originalState;
|
||||
this.toolAction = toolAction;
|
||||
this.simulate = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the player using the tool.
|
||||
* May be null based on what was provided by {@link #getContext() the use on context}.
|
||||
*/
|
||||
@Nullable
|
||||
public Player getPlayer()
|
||||
{
|
||||
return this.context.getPlayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tool being used
|
||||
*/
|
||||
public ItemStack getHeldItemStack()
|
||||
{
|
||||
return this.context.getItemInHand();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the action being performed
|
||||
*/
|
||||
public ToolAction getToolAction()
|
||||
{
|
||||
return this.toolAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this event should not perform any actions that modify the world.
|
||||
* If {@code false}, then world-modifying actions can be performed.
|
||||
*
|
||||
* @return {@code true} if this event should not perform any actions that modify the world.
|
||||
* If {@code false}, then world-modifying actions can be performed.
|
||||
*/
|
||||
public boolean isSimulated()
|
||||
{
|
||||
return this.simulate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nullable use on context that this event was performed in.
|
||||
* Starting in 1.19, this will never be null.
|
||||
*
|
||||
* @return the nullable use on context that this event was performed in
|
||||
*/
|
||||
// TODO 1.19: Remove nullable annotation and add non-null annotation
|
||||
@Nullable
|
||||
public UseOnContext getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state to transform the block into after tool use.
|
||||
*
|
||||
* @param finalState the state to transform the block into after tool use
|
||||
* @see #getFinalState()
|
||||
*/
|
||||
public void setFinalState(@Nullable BlockState finalState)
|
||||
{
|
||||
this.state = finalState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transformed state after tool use.
|
||||
* If setFinalState not called, will return the original state.
|
||||
* This will be bypassed if canceled returning null instead.
|
||||
* */
|
||||
* Returns the state to transform the block into after tool use.
|
||||
* If {@link #setFinalState(BlockState)} is not called, this will return the original state.
|
||||
* If {@link #isCanceled()} is {@code true}, this value will be ignored and the tool action will be canceled.
|
||||
*
|
||||
* @return the state to transform the block into after tool use
|
||||
*/
|
||||
public BlockState getFinalState()
|
||||
{
|
||||
return state;
|
||||
|
||||
Reference in new issue
Block a user