Skip to content

Instantly share code, notes, and snippets.

@Commoble
Created December 28, 2020 20:51
Show Gist options
  • Save Commoble/6d0be224b46a1f9064e6e3d6b14a55b7 to your computer and use it in GitHub Desktop.
Save Commoble/6d0be224b46a1f9064e6e3d6b14a55b7 to your computer and use it in GitHub Desktop.
Minecraft Forge 1.16.4: onBlockPlacedBy, updatePostPlacement, neighborChanged, onNeighborChange and observedNeighborChange
package commoble.gists;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
/**
* Example block class documenting the differences between different block-update event methods.
* Some argument names have been changed from the defaults to make their purpose clearer.
*/
public class NeighborNoticingBlock extends Block
{
public NeighborNoticingBlock(Properties properties)
{
super(properties);
}
/**
* Called by BlockItem::tryPlace after a player or other entity uses a BlockItem to place a block.
* Endermen do *not* invoke this when placing blocks, though they do fire an EntityPlaceEvent.
* This occurs *after* all setBlockState code runs, including updating of neighbors, placing the block entity,
* and transferring block entity data from the itemstack to the block entity, if any.
* @param world The world the block was placed into
* @param pos The position the block was placed at
* @param the final and actual state that ended up in the world after all other processing
* @param placer The entity that placed the block
* @param stack The ItemStack that was used to place the block
*/
@Override
public void onBlockPlacedBy(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack)
{
// does nothing by default
super.onBlockPlacedBy(world, pos, state, placer, stack);
}
/**
* This one is a bit tricky, as it's used in numerous places for slightly different purposes.
* The gist of it is that, given a blockstate for this block that either exists or is about to be placed,
* and a blockstate for an adjacent block, that already exists in the world,
* we *transform* the blockstate for this block that should be used, given the adjacent block.
*
* When a block is about to be placed into the world, this is called *before* the block is placed,
* (iteratively calling the method with the six adjacent neighbors as arguments),
* to determine the state that should be set.
*
* *After* a block is placed into the world (during markAndNotifyBlock, at the end of setBlockState),
* this is called on the neighbors of the placed block (using the placed block as the arguments)
* to determine if those neighboring blocks should be updated.
*
* Fences are a good example of this -- when you place a fence block, the state that gets placed is going to depend
* on which adjacent block the fence is going to be "connecting" to.
* Likewise, when we place a block next to to a fence, this gets called on the existing fence blockstate to determine
* the new state of the fence block.
*
* This method should probably be used in a purely functional manner and just return
* the new blockstate without making world changes, as the calling context may not be intending
* to be making any world changes.
*
* @param thisState The untransformed state of this block
* @param directionToNeighbor The side of this block that faces the neighbor we're looking at
* @param neighborState The state of the neighbor block we're looking at
* @param world The world this and the other blockstate are in
* @param thisPos The position of this block
* @param neighborPos The position of the neighbor block
* @return The new state of this block (can return thisState if no changes should be made)
*/
@Override
@Deprecated
public BlockState updatePostPlacement(BlockState thisState, Direction directionToNeighbor, BlockState neighborState, IWorld world, BlockPos thisPos, BlockPos neighborPos)
{
// returns thisState by default
return super.updatePostPlacement(thisState, directionToNeighbor, neighborState, world, thisPos, neighborPos);
}
/**
* This is invoked from many places, but it generally indicates that a neighboring block has changed
* and this block should react in the manner in which it is accustomed.
*
* The two main places this is called from:
*
* A) when something invokes world.notifyNeighborsOfStateChange on a block position,
* which fires the NeighborNotifyEvent forge event and invokes neighborChanged on the six adjacent blocks if the event is not cancelled.
* Lots of things invoke world.notifyNeighborsOfStateChange, but it's primarily invoked by the setting of a blockstate.
* Some tile entities like chests invoke this after their data changes as well
*
* B) When something invokes world.updateComparatorOutputLevel on a block,
* the world checks the six adjacent blocks,
* invokes neighborChanged on that adjacent block (forge block hook, see below),
* and if *that* adjacent block is also a normal cube,
* and if the block on the *far* side of the adjacent block returns true for the getWeakChanges forge hook,
* then neighborChanged is invoked for the block on the *far* side of the adjacent block
*
* Several blocks invoke this directly (typically to cause neighbor updates on blocks on specific sides instead of every side)
*
* @param thisState The existing state of this block in the world
* @param world The world this block is in
* @param thisPos The position of this block in the world
* @param fromBlock The neighboring block instance that changed
* @param fromPos The position of the neighboring block instance that changed
* @param isMoving Indicates that the changed neighbor state was set with flag 64 IS_MOVING
* (to indicate that the new blockstate was pushed there from somewhere else),
*/
@Override
@Deprecated
public void neighborChanged(BlockState thisState, World world, BlockPos thisPos, Block fromBlock, BlockPos fromPos, boolean isMoving)
{
// does nothing by default
// (an alleged "debug packet sender" method is invoked, but this invocation does nothing)
// (likely either legacy code or it has been stripped out by mojang's build process)
super.neighborChanged(thisState, world, thisPos, fromBlock, fromPos, isMoving);
}
/**
* This is a forge hook from IForgeBlock.
* When a block invokes updateComparatorOutputLevel, onNeighborChange is invoked on its six neighbors.
* The intended use of this appears to be that neighborChanged is to be used for listening to blockstate changes,
* while onNeighborChange is to be used for listening to TE data changes.
* @param thisState This block's state in the world
* @param world The world this block is in
* @param thisPos The position of this block in the world
* @param neighborPos The position of the neighbor block that changed
*/
@Override
public void onNeighborChange(BlockState thisState, IWorldReader world, BlockPos thisPos, BlockPos neighborPos)
{
// does nothing by default
super.onNeighborChange(thisState, world, thisPos, neighborPos);
}
/**
* This is a forge hook from IForgeBlock.
* Not actually called from anywhere, seems to be a dead forge patch that got lost in some minecraft update.
*/
@Override
public void observedNeighborChange(BlockState observerState, World world, BlockPos observerPos, Block changedBlock, BlockPos changedBlockPos)
{
// does nothing by default
super.observedNeighborChange(observerState, world, observerPos, changedBlock, changedBlockPos);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment