Difference between revisions of "Events/BlockEvent"

From Forge Community Wiki
(create page)
 
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
The variations of <code>BlockEvent</code> let modders intercept interactions between the player and blocks in the world. All of these events have in common the following: the <code>World</code> the action was taken in, and the <code>BlockPos</code> and <code>BlockState</code> that's being modified.<br /><br />== BreakEvent ==<br />This event is fired before a block is broken by a player. Predictably, cancelling this event prevents the block from getting broken. Modders have two extra variables to play with:<br /><br /><code>getExpToDrop()</code>: Returns how much experience ought to drop when the block is broken. Will be zero if the event is currently canceled.<br /><br /><code>setExpToDrop()</code>: Sets the experience that's going to drop manually.<br /><br /><code>getPlayer()</code>: Gets the player that's doing the action.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onBlockBreak(final BlockEvent.BreakEvent event)<br /> {<br /> if (event.getState().is(Tags.Blocks.SAND)) // use the base event to get the state and see what it is<br /> {<br /> event.setExpToDrop(10); // change the amount of experience we'll be dropping<br /> PlayerEntity player = event.getPlayer();<br /> if (player.getUseItem().getItem().is(Tags.Items.SHEARS)) // check if the player is holding shears<br /> {<br /> ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone to the player!<br /> }<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this event:<br />* Stopping players from breaking a block<br />* Changing the XP drop of a vanilla block<br />* Modify the behavior of a tool<br /><br />== EntityPlaceEvent ==<br />This event is called when a block is placed.<br /><br /><code>getEntity()</code>: This is the entity placing the block. Note that this might not be a player! It can be null. This means you should null check the entity. By default, Forge adds this in three places: players placing blocks, endermen placing their held block, as well as ice placed by the Frost Walker enchantment.<br /><br /><code>getBlockSnapshot()</code>: Gets the snapshot of what's about to be placed. A <code>BlockSnapshot</code> is just an object containing the dimension, position, NBT, and state of a block, along with some other info. Typically, this isn't necessary.<br /><br /><code>getPlacedBlock()</code> The <code>BlockState</code> to be placed.<br /><br /><code>getPlacedAgainst()</code> The <code>BlockState</code> that was clicked in order to place the block. Imagine planting a flower on some dirt. The dirt would be the state here.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onEntityPlace(final BlockEvent.BreakEvent event)<br /> {<br /> Entity entity = event.getEntity();<br /> if (entity != null) // check if the entity is null<br /> {<br /> Block block = event.getState().getBlock(); // get the block that was placed<br /> if (entity instanceof PlayerEntity && block.is(Blocks.FROSTED_ICE))<br /> {<br /> event.setCanceled(true); // cancel the placing<br /> event.getWorld().setBlock(event.getPos(), Blocks.COBBLESTONE.defaultBlockState(), 3); // set cobble instead<br /> }<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this event:<br />* (See above) Changing how frost walker works based on certain conditions<br />* Preventing a block from being placed<br />* Changing the player's inventory when a block is placed<br />* Cause another block to be placed instead of another<br /><br />== EntityMultiPlaceEvent ==<br />This is the same as above except it's fired when a block causes another block to be replaced. A great example is beds, where placing one half of the bed causes another half to be placed.<br /><br /><code>getReplacedBlockSnapshots()</code>: Everything is the same as before, except we now have a list of snapshots. How sweet.<br /><br />== NeighborNotifyEvent ==<br />This event is fired when a block tells its neighbors to update themselves. This happens all the time, typically with redstone blocks like tripwires or repeaters.<br /><br /><code>getNotifiedSides()</code>: A set of <code>Direction</code> values that were updated during the event. Sometimes, blocks will choose to exclude a side from being updated, but most often this will be all six directions.<br /><br /><code>getForceRedstoneUpdate()</code> This is a little funky. There's an option when blocks are set to force a redstone update. If that happened, this will be true. You typically won't need this.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onNeighborNotify(final BlockEvent.BreakEvent event)<br /> {<br /> BlockPos eventPos = event.getPos();<br /> for (Direction direction : event.getNotifiedSides()) // cycle through notified directions<br /> {<br /> BlockPos pos = eventPos.relative(direction); // move to the direction given<br /> double x = pos.getX() + 0.5D; // move to center of the block<br /> double y = pos.getY() + 0.5D;<br /> double z = pos.getZ() + 0.5D;<br /> // add particle<br /> event.getWorld().addParticle(ParticleTypes.CLOUD, x, y, z, 0.0D, 0.0D, 0.0D);<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this event:<br />* Adding blocks that interact with redstone<br />* Making a block update detector block<br /><br />== CreateFluidSourceEvent ==<br />This event controls creation of fluid sources. This is different than cancellable events, because it has a <code>Result</code>. Setting it to <code>ALLOW</code> causes a source block to created, even if that's not normally what would happen. Setting it to <code>DENY</code> always prevents source creation.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onNeighborNotify(final BlockEvent.BreakEvent event)<br /> {<br /> if (event.getPos().getY() > 100)<br /> {<br /> event.setResult(Event.Result.DENY); // prevent source creation above y = 100<br /> }<br /> }<br /></syntaxhighlight><br /><br />== FluidPlaceBlockEvent ==<br />This event fires when fluids place blocks. Examples of this happening are: basalt, stone, cobblestone, obsidian, and fire (think lava pools). You can cancel this event to prevent placement.<br /><br /><code>getLiquidPos()</code> This is the liquid's position. For cases like cobble generation, this is the same as the original <code>getPos()</code>. But for placing fire, this won't be the same.<br /><br /><code>getNewState()</code> Gets the state to be placed.<br /><br /><code>setNewState()</code> Sets the state to be placed.<br /><br /><code>getOriginalState()</code> What the block was before this event.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onBreak(final BlockEvent.BreakEvent event)<br /> {<br /> BlockState newState = event.getNewState();<br /> if (newState.is(Blocks.FIRE))<br /> {<br /> event.setCanceled(true); // prevent fire placing from lava<br /> }<br /> else if (newState.is(Blocks.COBBLESTONE) && event.getWorld().dayTime() > 14000L)<br /> {<br /> event.setNewState(Blocks.ANDESITE.defaultBlockState()); // change the block if done during nighttime.<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this event:<br />* Changing behavior of cobble generators<br />* Preventing cobble generators<br />* Adding more aggressive effects during fire spreading from lava<br /><br />== CropGrowEvent ==<br />These events are fired during crop growth. The <code>Pre</code> event is fired before. It's fired when vanilla blocks try to 'grow' during random ticks (think cacti getting taller). Setting <code>DEFAULT</code> as the result will cause no change. Setting <code>ALLOW</code> forces growth. Setting <code>DENY</code> prevents growth.<br /><br />The <code>Post</code> event is fired after growth.<br /><br /><code>getOriginalState</code> Get the state before growth happened.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onCropGrowPre(final BlockEvent.CropGrowEvent.Pre event)<br /> {<br /> BlockState state = event.getState();<br /> if (state.is(Blocks.WHEAT))<br /> {<br /> event.setResult(Event.Result.DENY); // prevent wheat from growing<br /> }<br /> else if (state.is(Blocks.BAMBOO))<br /> {<br /> if (event.getWorld().getRandom().nextFloat() > 0.2F) // take a 4/5 chance<br /> {<br /> event.setResult(Event.Result.DENY); // make bamboo grow less often<br /> }<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this event:<br />* Changing growth rate of crops<br />* Preventing crop growth under certain conditions<br />* Spawning an entity when something grows<br /><br />== FarmlandTrampleEvent ==<br />This event is fired when farmland gets trampled. You can cancel it to prevent trampling.<br /><br /><code>getEntity()</code> The entity that trampled<br /><br /><code>getFallDistance()</code> How far that entity fell<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void onTrample(final BlockEvent.FarmlandTrampleEvent event)<br /> {<br /> if (event.getFallDistance() < 10.0F)<br /> {<br /> event.setCanceled(true); // change conditions for trampling<br /> }<br /> }<br /></syntaxhighlight><br /><br />== PortalSpawnEvent ==<br />This event is fired when a nether portal is created.<br /><br /><code>getPortalSize()</code> returns a <code>PortalSize</code> object, basically only useful for determining if the portal is going to be valid or not.<br /><br />This is mostly used for preventing portal spawning in certain dimensions (even the overworld).<br /><br />== BlockToolInteractEvent ==<br />This event is fired on right click tool events, such as path creation, wood stripping, and farmland tilling. You have access to the player, the <code>ItemStack</code> they're holding, and the <code>ToolType</code> they have.<br /><br /><code>setFinalState()</code>: Set what you want the result to be.<br /><br /><code>getFinalState()</code>: Returns what it will be changed to.<br /><br />Example usage:<br /><syntaxhighlight lang="java"><br />public void event(final BlockEvent.BlockToolInteractEvent event)<br /> {<br /> if (event.getFinalState().is(Blocks.FARMLAND) && event.getHeldItemStack().getItem() == Items.NETHERITE_HOE)<br /> {<br /> event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // change the final state under certain conditions<br /> }<br /> }<br /></syntaxhighlight><br /><br />Some ideas for using this:<br />* Setting your custom farmland block during tilling<br />* Adding stripped wood behavior for other blocks<br />* Disable path creation
+
The variations of <code>BlockEvent</code> let modders intercept interactions between the player and blocks in the world. All of these events have in common the following: the <code>World</code> the action was taken in, and the <code>BlockPos</code> and <code>BlockState</code> that's being modified.
 +
 
 +
== BreakEvent ==
 +
This event is fired before a block is broken by a player. Predictably, cancelling this event prevents the block from getting broken. Modders have two extra variables to play with:
 +
 
 +
<code>getExpToDrop()</code>: Returns how much experience ought to drop when the block is broken. Will be zero if the event is currently canceled.
 +
 
 +
<code>setExpToDrop()</code>: Sets the experience that's going to drop manually.
 +
 
 +
<code>getPlayer()</code>: Gets the player that's doing the action.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onBlockBreak(final BlockEvent.BreakEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (!world.isClientSide() && event.getState().is(Blocks.SAND)) // use the base event to get the state and see what it is
 +
        {
 +
            event.setExpToDrop(10); // change the amount of experience we'll be dropping
 +
            PlayerEntity player = event.getPlayer();
 +
            if (player.getMainHandItem().getItem().equals(Items.DIAMOND_SHOVEL)) // check what we're holding
 +
            {
 +
                ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone
 +
            }
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this event:
 +
* Stopping players from breaking a block
 +
* Changing the XP drop of a vanilla block
 +
* Modify the behavior of a tool
 +
 
 +
== EntityPlaceEvent ==
 +
This event is called when a block is placed.
 +
 
 +
<code>getEntity()</code>: This is the entity placing the block. Note that this might not be a player! It can be null. This means you should null check the entity. By default, Forge adds this in three places: players placing blocks, endermen placing their held block, as well as ice placed by the Frost Walker enchantment.
 +
 
 +
<code>getBlockSnapshot()</code>: Gets the snapshot of what's about to be placed. A <code>BlockSnapshot</code> is just an object containing the dimension, position, NBT, and state of a block, along with some other info. Typically, this isn't necessary.
 +
 
 +
<code>getPlacedBlock()</code> The <code>BlockState</code> to be placed.
 +
 
 +
<code>getPlacedAgainst()</code> The <code>BlockState</code> that was clicked in order to place the block. Imagine planting a flower on some dirt. The dirt would be the state here.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onEntityPlace(final BlockEvent.EntityPlaceEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (!world.isClientSide() && event.getEntity() instanceof EndermanEntity)
 +
        {
 +
            event.setCanceled(true); // prevent enderman placement
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this event:
 +
* (See above) Changing how frost walker works based on certain conditions
 +
* Preventing a block from being placed
 +
* Changing the player's inventory when a block is placed
 +
* Cause another block to be placed instead of another
 +
 
 +
== EntityMultiPlaceEvent ==
 +
This is the same as above except it's fired when a block causes another block to be replaced. A great example is beds, where placing one half of the bed causes another half to be placed.
 +
 
 +
<code>getReplacedBlockSnapshots()</code>: Everything is the same as before, except we now have a list of snapshots. How sweet.
 +
 
 +
== NeighborNotifyEvent ==
 +
This event is fired when a block tells its neighbors to update themselves. This happens all the time, typically with redstone blocks like tripwires or repeaters.
 +
 
 +
<code>getNotifiedSides()</code>: A set of <code>Direction</code> values that were updated during the event. Sometimes, blocks will choose to exclude a side from being updated, but most often this will be all six directions.
 +
 
 +
<code>getForceRedstoneUpdate()</code> This is a little funky. There's an option when blocks are set to force a redstone update. If that happened, this will be true. You typically won't need this.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onNeighborNotify(final BlockEvent.NeighborNotifyEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (world.isClientSide()) return;
 +
        BlockPos eventPos = event.getPos();
 +
        if (event.getState().is(Blocks.REDSTONE_WIRE)) // only do it for redstone
 +
        {
 +
            for (Direction direction : event.getNotifiedSides()) // cycle through notified directions
 +
            {
 +
                BlockPos pos = eventPos.relative(direction); // move to that spot
 +
                if (world.isEmptyBlock(pos))
 +
                {
 +
                    world.setBlock(pos, Blocks.GLOWSTONE.defaultBlockState(), 3); // place glowstone
 +
                }
 +
            }
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this event:
 +
* Adding blocks that interact with redstone
 +
* Making a block update detector block
 +
 
 +
==CreateFluidSourceEvent==
 +
This event controls creation of fluid sources. This is different than cancellable events, because it has a <code>Result</code>. Setting it to <code>ALLOW</code> causes a source block to created, even if that's not normally what would happen. Setting it to <code>DENY</code> always prevents source creation.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onFluidSourceCreate(final BlockEvent.CreateFluidSourceEvent event)
 +
    {
 +
        IWorldReader world = event.getWorld();
 +
        if (!world.isClientSide() && event.getPos().getY() > 100)
 +
        {
 +
            event.setResult(Event.Result.DENY); // prevent source creation above y = 100
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
== FluidPlaceBlockEvent ==
 +
This event fires when fluids place blocks. Examples of this happening are: basalt, stone, cobblestone, obsidian, and fire (think lava pools). You can cancel this event to prevent placement.
 +
 
 +
<code>getLiquidPos()</code> This is the liquid's position. For cases like cobble generation, this is the same as the original <code>getPos()</code>. But for placing fire, this won't be the same.
 +
 
 +
<code>getNewState()</code> Gets the state to be placed.
 +
 
 +
<code>setNewState()</code> Sets the state to be placed.
 +
 
 +
<code>getOriginalState()</code> What the block was before this event.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onFluidPlace(final BlockEvent.FluidPlaceBlockEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (world.isClientSide()) return;
 +
        BlockState newState = event.getNewState();
 +
        if (newState.is(Blocks.COBBLESTONE) && world.dayTime() > 14000L)
 +
        {
 +
            event.setNewState(Blocks.ANDESITE.defaultBlockState()); // change the block if done during nighttime.
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this event:
 +
* Changing behavior of cobble generators
 +
* Preventing cobble generators
 +
* Adding more aggressive effects during fire spreading from lava
 +
 
 +
== CropGrowEvent ==
 +
These events are fired during crop growth. The <code>Pre</code> event is fired before. It's fired when vanilla blocks try to  'grow' during random ticks (think cacti getting taller). Setting <code>DEFAULT</code> as the result will cause no change. Setting <code>ALLOW</code> forces growth. Setting <code>DENY</code> prevents growth.
 +
 
 +
The <code>Post</code> event is fired after growth.
 +
 
 +
<code>getOriginalState()</code> Get the state before growth happened.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onCropGrowPre(final BlockEvent.CropGrowEvent.Pre event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (world.isClientSide()) return;
 +
        BlockState state = event.getState();
 +
        if (state.is(Blocks.WHEAT))
 +
        {
 +
            event.setResult(Event.Result.DENY); // prevent wheat from growing
 +
        }
 +
        else if (state.is(Blocks.BAMBOO))
 +
        {
 +
            if (world.getRandom().nextFloat() > 0.2F) // take a 4/5 chance
 +
            {
 +
                event.setResult(Event.Result.DENY); // make bamboo grow less often
 +
            }
 +
        }
 +
    }
 +
 
 +
public void onCropsGrowPost(final BlockEvent.CropGrowEvent.Post event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (!world.isClientSide() && event.getState().is(Blocks.WHEAT)) // check wheat
 +
        {
 +
            BlockState newState = event.getState();
 +
            if (newState.is(Blocks.WHEAT)) // defensive check to make sure we can do this
 +
            {
 +
                world.setBlock(event.getPos(), newState.setValue(CropsBlock.AGE, 7), 3); // set max growth wheat
 +
            }
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this event:
 +
* Changing growth rate of crops
 +
* Preventing crop growth under certain conditions
 +
* Spawning an entity when something grows
 +
 
 +
== FarmlandTrampleEvent ==
 +
This event is fired when farmland gets trampled. You can cancel it to prevent trampling.
 +
 
 +
<code>getEntity()</code> The entity that trampled
 +
 
 +
<code>getFallDistance()</code> How far that entity fell
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onTrample(final BlockEvent.FarmlandTrampleEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (!world.isClientSide() && event.getFallDistance() < 10.0F)
 +
        {
 +
            event.setCanceled(true); // change conditions for trampling
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
== PortalSpawnEvent ==
 +
This event is fired when a nether portal is created.
 +
 
 +
<code>getPortalSize()</code> returns a <code>PortalSize</code> object, basically only useful for determining if the portal is going to be valid or not.
 +
 
 +
This is mostly used for preventing portal spawning in certain dimensions (even the overworld).
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onPortalLight(final BlockEvent.PortalSpawnEvent event)
 +
    {
 +
        event.setCanceled(true);
 +
    }
 +
</syntaxhighlight>
 +
 
 +
== BlockToolInteractEvent ==
 +
This event is fired on right click tool events, such as path creation, wood stripping, and farmland tilling. You have access to the player, the <code>ItemStack</code> they're holding, and the <code>ToolType</code> they have.
 +
 
 +
<code>setFinalState()</code>: Set what you want the result to be.
 +
 
 +
<code>getFinalState()</code>: Returns what it will be changed to. This will normally just return whatever the original block is unless you or another modder has set it. It can't check, for example, if something *will* turn into farmland in the future.
 +
 
 +
Example usage:
 +
<syntaxhighlight lang="java">
 +
public void onToolInteract(final BlockEvent.BlockToolInteractEvent event)
 +
    {
 +
        IWorld world = event.getWorld();
 +
        if (!world.isClientSide() && event.getHeldItemStack().getItem() == Items.NETHERITE_HOE)
 +
        {
 +
            event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // set the block to netherrack
 +
            // note that this happens for any right click on a block, not just dirt
 +
        }
 +
    }
 +
</syntaxhighlight>
 +
 
 +
Some ideas for using this:
 +
* Setting your custom farmland block during tilling
 +
* Adding stripped wood behavior for other blocks
 +
* Disable path creation

Latest revision as of 18:46, 20 April 2021

The variations of BlockEvent let modders intercept interactions between the player and blocks in the world. All of these events have in common the following: the World the action was taken in, and the BlockPos and BlockState that's being modified.

BreakEvent

This event is fired before a block is broken by a player. Predictably, cancelling this event prevents the block from getting broken. Modders have two extra variables to play with:

getExpToDrop(): Returns how much experience ought to drop when the block is broken. Will be zero if the event is currently canceled.

setExpToDrop(): Sets the experience that's going to drop manually.

getPlayer(): Gets the player that's doing the action.

Example usage:

public void onBlockBreak(final BlockEvent.BreakEvent event)
    {
        IWorld world = event.getWorld();
        if (!world.isClientSide() && event.getState().is(Blocks.SAND)) // use the base event to get the state and see what it is
        {
            event.setExpToDrop(10); // change the amount of experience we'll be dropping
            PlayerEntity player = event.getPlayer();
            if (player.getMainHandItem().getItem().equals(Items.DIAMOND_SHOVEL)) // check what we're holding
            {
                ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone
            }
        }
    }

Some ideas for using this event:

  • Stopping players from breaking a block
  • Changing the XP drop of a vanilla block
  • Modify the behavior of a tool

EntityPlaceEvent

This event is called when a block is placed.

getEntity(): This is the entity placing the block. Note that this might not be a player! It can be null. This means you should null check the entity. By default, Forge adds this in three places: players placing blocks, endermen placing their held block, as well as ice placed by the Frost Walker enchantment.

getBlockSnapshot(): Gets the snapshot of what's about to be placed. A BlockSnapshot is just an object containing the dimension, position, NBT, and state of a block, along with some other info. Typically, this isn't necessary.

getPlacedBlock() The BlockState to be placed.

getPlacedAgainst() The BlockState that was clicked in order to place the block. Imagine planting a flower on some dirt. The dirt would be the state here.

Example usage:

public void onEntityPlace(final BlockEvent.EntityPlaceEvent event)
    {
        IWorld world = event.getWorld();
        if (!world.isClientSide() && event.getEntity() instanceof EndermanEntity)
        {
            event.setCanceled(true); // prevent enderman placement
        }
    }

Some ideas for using this event:

  • (See above) Changing how frost walker works based on certain conditions
  • Preventing a block from being placed
  • Changing the player's inventory when a block is placed
  • Cause another block to be placed instead of another

EntityMultiPlaceEvent

This is the same as above except it's fired when a block causes another block to be replaced. A great example is beds, where placing one half of the bed causes another half to be placed.

getReplacedBlockSnapshots(): Everything is the same as before, except we now have a list of snapshots. How sweet.

NeighborNotifyEvent

This event is fired when a block tells its neighbors to update themselves. This happens all the time, typically with redstone blocks like tripwires or repeaters.

getNotifiedSides(): A set of Direction values that were updated during the event. Sometimes, blocks will choose to exclude a side from being updated, but most often this will be all six directions.

getForceRedstoneUpdate() This is a little funky. There's an option when blocks are set to force a redstone update. If that happened, this will be true. You typically won't need this.

Example usage:

public void onNeighborNotify(final BlockEvent.NeighborNotifyEvent event)
    {
        IWorld world = event.getWorld();
        if (world.isClientSide()) return;
        BlockPos eventPos = event.getPos();
        if (event.getState().is(Blocks.REDSTONE_WIRE)) // only do it for redstone
        {
            for (Direction direction : event.getNotifiedSides()) // cycle through notified directions
            {
                BlockPos pos = eventPos.relative(direction); // move to that spot
                if (world.isEmptyBlock(pos))
                {
                    world.setBlock(pos, Blocks.GLOWSTONE.defaultBlockState(), 3); // place glowstone
                }
            }
        }
    }

Some ideas for using this event:

  • Adding blocks that interact with redstone
  • Making a block update detector block

CreateFluidSourceEvent

This event controls creation of fluid sources. This is different than cancellable events, because it has a Result. Setting it to ALLOW causes a source block to created, even if that's not normally what would happen. Setting it to DENY always prevents source creation.

Example usage:

public void onFluidSourceCreate(final BlockEvent.CreateFluidSourceEvent event)
    {
        IWorldReader world = event.getWorld();
        if (!world.isClientSide() && event.getPos().getY() > 100)
        {
            event.setResult(Event.Result.DENY); // prevent source creation above y = 100
        }
    }

FluidPlaceBlockEvent

This event fires when fluids place blocks. Examples of this happening are: basalt, stone, cobblestone, obsidian, and fire (think lava pools). You can cancel this event to prevent placement.

getLiquidPos() This is the liquid's position. For cases like cobble generation, this is the same as the original getPos(). But for placing fire, this won't be the same.

getNewState() Gets the state to be placed.

setNewState() Sets the state to be placed.

getOriginalState() What the block was before this event.

Example usage:

public void onFluidPlace(final BlockEvent.FluidPlaceBlockEvent event)
    {
        IWorld world = event.getWorld();
        if (world.isClientSide()) return;
        BlockState newState = event.getNewState();
        if (newState.is(Blocks.COBBLESTONE) && world.dayTime() > 14000L)
        {
            event.setNewState(Blocks.ANDESITE.defaultBlockState()); // change the block if done during nighttime.
        }
    }

Some ideas for using this event:

  • Changing behavior of cobble generators
  • Preventing cobble generators
  • Adding more aggressive effects during fire spreading from lava

CropGrowEvent

These events are fired during crop growth. The Pre event is fired before. It's fired when vanilla blocks try to 'grow' during random ticks (think cacti getting taller). Setting DEFAULT as the result will cause no change. Setting ALLOW forces growth. Setting DENY prevents growth.

The Post event is fired after growth.

getOriginalState() Get the state before growth happened.

Example usage:

public void onCropGrowPre(final BlockEvent.CropGrowEvent.Pre event)
    {
        IWorld world = event.getWorld();
        if (world.isClientSide()) return;
        BlockState state = event.getState();
        if (state.is(Blocks.WHEAT))
        {
            event.setResult(Event.Result.DENY); // prevent wheat from growing
        }
        else if (state.is(Blocks.BAMBOO))
        {
            if (world.getRandom().nextFloat() > 0.2F) // take a 4/5 chance
            {
                event.setResult(Event.Result.DENY); // make bamboo grow less often
            }
        }
    }

public void onCropsGrowPost(final BlockEvent.CropGrowEvent.Post event)
    {
        IWorld world = event.getWorld();
        if (!world.isClientSide() && event.getState().is(Blocks.WHEAT)) // check wheat
        {
            BlockState newState = event.getState();
            if (newState.is(Blocks.WHEAT)) // defensive check to make sure we can do this
            {
                world.setBlock(event.getPos(), newState.setValue(CropsBlock.AGE, 7), 3); // set max growth wheat
            }
        }
    }

Some ideas for using this event:

  • Changing growth rate of crops
  • Preventing crop growth under certain conditions
  • Spawning an entity when something grows

FarmlandTrampleEvent

This event is fired when farmland gets trampled. You can cancel it to prevent trampling.

getEntity() The entity that trampled

getFallDistance() How far that entity fell

Example usage:

public void onTrample(final BlockEvent.FarmlandTrampleEvent event)
    {
        IWorld world = event.getWorld();
        if (!world.isClientSide() && event.getFallDistance() < 10.0F)
        {
            event.setCanceled(true); // change conditions for trampling
        }
    }

PortalSpawnEvent

This event is fired when a nether portal is created.

getPortalSize() returns a PortalSize object, basically only useful for determining if the portal is going to be valid or not.

This is mostly used for preventing portal spawning in certain dimensions (even the overworld).

Example usage:

public void onPortalLight(final BlockEvent.PortalSpawnEvent event)
    {
        event.setCanceled(true);
    }

BlockToolInteractEvent

This event is fired on right click tool events, such as path creation, wood stripping, and farmland tilling. You have access to the player, the ItemStack they're holding, and the ToolType they have.

setFinalState(): Set what you want the result to be.

getFinalState(): Returns what it will be changed to. This will normally just return whatever the original block is unless you or another modder has set it. It can't check, for example, if something *will* turn into farmland in the future.

Example usage:

public void onToolInteract(final BlockEvent.BlockToolInteractEvent event)
    {
        IWorld world = event.getWorld();
        if (!world.isClientSide() && event.getHeldItemStack().getItem() == Items.NETHERITE_HOE)
        {
            event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // set the block to netherrack
            // note that this happens for any right click on a block, not just dirt
        }
    }

Some ideas for using this:

  • Setting your custom farmland block during tilling
  • Adding stripped wood behavior for other blocks
  • Disable path creation