New IForgeBlock#getToolModifiedState hook allow better control over tools interacting with blocks. (#7176)

This commit is contained in:
ChampionAsh5357 2020-08-03 19:49:26 -04:00 committed by GitHub
parent 97a2b9a448
commit 0984777c98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 214 additions and 4 deletions

View file

@ -9,3 +9,29 @@
}
public float func_150893_a(ItemStack p_150893_1_, BlockState p_150893_2_) {
@@ -34,12 +34,12 @@
World world = p_195939_1_.func_195991_k();
BlockPos blockpos = p_195939_1_.func_195995_a();
BlockState blockstate = world.func_180495_p(blockpos);
- Block block = field_203176_a.get(blockstate.func_177230_c());
+ BlockState block = blockstate.getToolModifiedState(world, blockpos, p_195939_1_.func_195999_j(), p_195939_1_.func_195996_i(), net.minecraftforge.common.ToolType.AXE);
if (block != null) {
PlayerEntity playerentity = p_195939_1_.func_195999_j();
world.func_184133_a(playerentity, blockpos, SoundEvents.field_203255_y, SoundCategory.BLOCKS, 1.0F, 1.0F);
if (!world.field_72995_K) {
- world.func_180501_a(blockpos, block.func_176223_P().func_206870_a(RotatedPillarBlock.field_176298_M, blockstate.func_177229_b(RotatedPillarBlock.field_176298_M)), 11);
+ world.func_180501_a(blockpos, block, 11);
if (playerentity != null) {
p_195939_1_.func_195996_i().func_222118_a(1, playerentity, (p_220040_1_) -> {
p_220040_1_.func_213334_d(p_195939_1_.func_221531_n());
@@ -52,4 +52,10 @@
return ActionResultType.PASS;
}
}
+
+ @javax.annotation.Nullable
+ public static BlockState getAxeStrippingState(BlockState originalState) {
+ Block block = field_203176_a.get(originalState.func_177230_c());
+ return block != null ? block.func_176223_P().func_206870_a(RotatedPillarBlock.field_176298_M, originalState.func_177229_b(RotatedPillarBlock.field_176298_M)) : null;
+ }
}

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/item/HoeItem.java
+++ b/net/minecraft/item/HoeItem.java
@@ -21,13 +21,15 @@
@@ -21,14 +21,16 @@
protected static final Map<Block, BlockState> field_195973_b = Maps.newHashMap(ImmutableMap.of(Blocks.field_196658_i, Blocks.field_150458_ak.func_176223_P(), Blocks.field_185774_da, Blocks.field_150458_ak.func_176223_P(), Blocks.field_150346_d, Blocks.field_150458_ak.func_176223_P(), Blocks.field_196660_k, Blocks.field_150346_d.func_176223_P()));
public HoeItem(IItemTier p_i231595_1_, int p_i231595_2_, float p_i231595_3_, Item.Properties p_i231595_4_) {
@ -12,9 +12,21 @@
World world = p_195939_1_.func_195991_k();
BlockPos blockpos = p_195939_1_.func_195995_a();
- if (p_195939_1_.func_196000_l() != Direction.DOWN && world.func_180495_p(blockpos.func_177984_a()).func_196958_f()) {
- BlockState blockstate = field_195973_b.get(world.func_180495_p(blockpos).func_177230_c());
+ int hook = net.minecraftforge.event.ForgeEventFactory.onHoeUse(p_195939_1_);
+ if (hook != 0) return hook > 0 ? ActionResultType.SUCCESS : ActionResultType.FAIL;
+ if (p_195939_1_.func_196000_l() != Direction.DOWN && world.func_175623_d(blockpos.func_177984_a())) {
BlockState blockstate = field_195973_b.get(world.func_180495_p(blockpos).func_177230_c());
+ BlockState blockstate = world.func_180495_p(blockpos).getToolModifiedState(world, blockpos, p_195939_1_.func_195999_j(), p_195939_1_.func_195996_i(), net.minecraftforge.common.ToolType.HOE);
if (blockstate != null) {
PlayerEntity playerentity = p_195939_1_.func_195999_j();
world.func_184133_a(playerentity, blockpos, SoundEvents.field_187693_cj, SoundCategory.BLOCKS, 1.0F, 1.0F);
@@ -47,4 +49,9 @@
return ActionResultType.PASS;
}
+
+ @javax.annotation.Nullable
+ public static BlockState getHoeTillingState(BlockState originalState) {
+ return field_195973_b.get(originalState.func_177230_c());
+ }
}

View file

@ -9,12 +9,25 @@
}
public boolean func_150897_b(BlockState p_150897_1_) {
@@ -39,7 +39,7 @@
@@ -37,9 +37,9 @@
return ActionResultType.PASS;
} else {
PlayerEntity playerentity = p_195939_1_.func_195999_j();
BlockState blockstate1 = field_195955_e.get(blockstate.func_177230_c());
- BlockState blockstate1 = field_195955_e.get(blockstate.func_177230_c());
+ BlockState blockstate1 = blockstate.getToolModifiedState(world, blockpos, playerentity, p_195939_1_.func_195996_i(), net.minecraftforge.common.ToolType.SHOVEL);
BlockState blockstate2 = null;
- if (blockstate1 != null && world.func_180495_p(blockpos.func_177984_a()).func_196958_f()) {
+ if (blockstate1 != null && world.func_175623_d(blockpos.func_177984_a())) {
world.func_184133_a(playerentity, blockpos, SoundEvents.field_187771_eN, SoundCategory.BLOCKS, 1.0F, 1.0F);
blockstate2 = blockstate1;
} else if (blockstate.func_177230_c() instanceof CampfireBlock && blockstate.func_177229_b(CampfireBlock.field_220101_b)) {
@@ -67,4 +67,9 @@
}
}
}
+
+ @javax.annotation.Nullable
+ public static BlockState getShovelPathingState(BlockState originalState) {
+ return field_195955_e.get(originalState.func_177230_c());
+ }
}

View file

@ -42,8 +42,11 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.WitherSkullEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.potion.Effects;
import net.minecraft.item.AxeItem;
import net.minecraft.item.DyeColor;
import net.minecraft.item.HoeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ShovelItem;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.state.Property;
import net.minecraft.state.properties.BedPart;
@ -887,4 +890,24 @@ public interface IForgeBlock
{
return state.getBlock() instanceof BreakableBlock || state.getBlock() instanceof LeavesBlock;
}
/**
* 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.
*
* @param state The current state
* @param world The world
* @param pos The block position in world
* @param player The player clicking the block
* @param stack The stack being used by the player
* @return The resulting state after the action has been performed
*/
@Nullable
default BlockState getToolModifiedState(BlockState state, World world, BlockPos pos, PlayerEntity player, ItemStack stack, ToolType toolType)
{
if (toolType == ToolType.AXE) return AxeItem.getAxeStrippingState(state);
else if(toolType == ToolType.HOE) return HoeItem.getHoeTillingState(state);
else return toolType == ToolType.SHOVEL ? ShovelItem.getShovelPathingState(state) : null;
}
}

View file

@ -778,4 +778,23 @@ public interface IForgeBlockState
{
return getBlockState().getBlock().shouldDisplayFluidOverlay(getBlockState(), world, pos, fluidState);
}
/**
* 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.
*
* @param world The world
* @param pos The block position in world
* @param player The player clicking the block
* @param stack The stack being used by the player
* @param toolTypes The tool types to be considered when performing the action
* @return The resulting state after the action has been performed
*/
@Nullable
default BlockState getToolModifiedState(World world, BlockPos pos, PlayerEntity player, ItemStack stack, ToolType toolType)
{
BlockState eventState = net.minecraftforge.event.ForgeEventFactory.onToolUse(getBlockState(), world, pos, player, stack, toolType);
return eventState != getBlockState() ? eventState : getBlockState().getBlock().getToolModifiedState(getBlockState(), world, pos, player, stack, toolType);
}
}

View file

@ -88,6 +88,7 @@ import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.RenderBlockOverlayEvent;
import net.minecraftforge.client.event.RenderBlockOverlayEvent.OverlayType;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.ToolType;
import net.minecraftforge.common.capabilities.CapabilityDispatcher;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.BlockSnapshot;
@ -126,6 +127,7 @@ import net.minecraftforge.event.entity.player.SleepingTimeCheckEvent;
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.CreateFluidSourceEvent;
import net.minecraftforge.event.world.BlockEvent.EntityMultiPlaceEvent;
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
@ -348,6 +350,8 @@ public class ForgeEventFactory
return MinecraftForge.EVENT_BUS.post(event) ? "" : event.getMessage();
}
//TODO: 1.17 Remove
@Deprecated
public static int onHoeUse(ItemUseContext context)
{
UseHoeEvent event = new UseHoeEvent(context);
@ -359,6 +363,13 @@ public class ForgeEventFactory
}
return 0;
}
@Nullable
public static BlockState onToolUse(BlockState originalState, World world, BlockPos pos, PlayerEntity player, ItemStack stack, ToolType toolType)
{
BlockToolInteractEvent event = new BlockToolInteractEvent(world, pos, originalState, player, stack, toolType);
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getFinalState();
}
public static int onApplyBonemeal(@Nonnull PlayerEntity player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull ItemStack stack)
{

View file

@ -33,9 +33,12 @@ import javax.annotation.Nonnull;
* and damage the hoe.
*
* setResult(ALLOW) is the same as the old setHandled();
*
* TODO: 1.17 Remove
*/
@Cancelable
@HasResult
@Deprecated
public class UseHoeEvent extends PlayerEvent
{
private final ItemUseContext context;;

View file

@ -35,6 +35,7 @@ import net.minecraft.util.Direction;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.ToolType;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
@ -444,4 +445,68 @@ public class BlockEvent extends Event
return size;
}
}
/**
* 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, a shovel can path, or a hoe can till.
*
* This event is {@link Cancelable}. If canceled, this will prevent the tool
* from changing the block's state.
*/
@Cancelable
public static class BlockToolInteractEvent extends BlockEvent
{
private final PlayerEntity player;
private final ItemStack stack;
private final ToolType toolType;
private BlockState state;
public BlockToolInteractEvent(IWorld world, BlockPos pos, BlockState originalState, PlayerEntity player, ItemStack stack, ToolType toolType)
{
super(world, pos, originalState);
this.player = player;
this.stack = stack;
this.state = originalState;
this.toolType = toolType;
}
/**Gets the player using the tool.*/
public PlayerEntity getPlayer()
{
return player;
}
/**Gets the tool being used.*/
public ItemStack getHeldItemStack()
{
return stack;
}
/**Gets the current type of the tool being compared against.*/
public ToolType getToolType()
{
return toolType;
}
/**
* 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)
{
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.
* */
public BlockState getFinalState()
{
return state;
}
}
}

View file

@ -0,0 +1,36 @@
package net.minecraftforge.debug.block;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.BlockEvent.BlockToolInteractEvent;
import net.minecraftforge.fml.common.Mod;
@Mod("tool_interact_test")
public class ToolInteractTest
{
private static final Logger LOGGER = LogManager.getLogger();
public ToolInteractTest()
{
MinecraftForge.EVENT_BUS.addListener(this::onToolInteraction);
}
private void onToolInteraction(final BlockToolInteractEvent event)
{
//Test 1: No Changes, just test if event is called. State and Final State should be the same
LOGGER.info("BlockState {} is modified to {} at position {} by {} with {}", event.getState(), event.getFinalState(), event.getPos(), event.getPlayer(), event.getHeldItemStack());
//Test 2: Canceling, nothing in game should change
/*event.setCanceled(true);
LOGGER.info("Event has been canceled: {}", event.isCanceled());
*/
//Test 3: Altering
/*event.setFinalState(Blocks.ACACIA_FENCE.getDefaultState());
LOGGER.info("BlockState {} is modified to {} at position {} by {} with {}", event.getState(), event.getFinalState(), event.getPos(), event.getPlayer(), event.getHeldItemStack());
*/
}
}

View file

@ -76,5 +76,7 @@ license="LGPL v2.1"
modId="player_name_event_test"
[[mods]]
modId="modded_overworld_biomes_test"
[[mods]]
modId="tool_interact_test"
[[mods]]
modId="custom_elytra_test"