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) |
| + | { |
| + | if (event.getState().is(Tags.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.getUseItem().getItem().is(Tags.Items.SHEARS)) // check if the player is holding shears |
| + | { |
| + | ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone to the player! |
| + | } |
| + | } |
| + | } |
| + | </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.BreakEvent event) |
| + | { |
| + | Entity entity = event.getEntity(); |
| + | if (entity != null) // check if the entity is null |
| + | { |
| + | Block block = event.getState().getBlock(); // get the block that was placed |
| + | if (entity instanceof PlayerEntity && block.is(Blocks.FROSTED_ICE)) |
| + | { |
| + | event.setCanceled(true); // cancel the placing |
| + | event.getWorld().setBlock(event.getPos(), Blocks.COBBLESTONE.defaultBlockState(), 3); // set cobble instead |
| + | } |
| + | } |
| + | } |
| + | </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.BreakEvent event) |
| + | { |
| + | BlockPos eventPos = event.getPos(); |
| + | for (Direction direction : event.getNotifiedSides()) // cycle through notified directions |
| + | { |
| + | BlockPos pos = eventPos.relative(direction); // move to the direction given |
| + | double x = pos.getX() + 0.5D; // move to center of the block |
| + | double y = pos.getY() + 0.5D; |
| + | double z = pos.getZ() + 0.5D; |
| + | // add particle |
| + | event.getWorld().addParticle(ParticleTypes.CLOUD, x, y, z, 0.0D, 0.0D, 0.0D); |
| + | } |
| + | } |
| + | </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 onNeighborNotify(final BlockEvent.BreakEvent event) |
| + | { |
| + | if (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 onBreak(final BlockEvent.BreakEvent event) |
| + | { |
| + | BlockState newState = event.getNewState(); |
| + | if (newState.is(Blocks.FIRE)) |
| + | { |
| + | event.setCanceled(true); // prevent fire placing from lava |
| + | } |
| + | else if (newState.is(Blocks.COBBLESTONE) && event.getWorld().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) |
| + | { |
| + | 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 (event.getWorld().getRandom().nextFloat() > 0.2F) // take a 4/5 chance |
| + | { |
| + | event.setResult(Event.Result.DENY); // make bamboo grow less often |
| + | } |
| + | } |
| + | } |
| + | </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) |
| + | { |
| + | if (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). |
| + | |
| + | == 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. |
| + | |
| + | Example usage: |
| + | <syntaxhighlight lang="java"> |
| + | public void event(final BlockEvent.BlockToolInteractEvent event) |
| + | { |
| + | if (event.getFinalState().is(Blocks.FARMLAND) && event.getHeldItemStack().getItem() == Items.NETHERITE_HOE) |
| + | { |
| + | event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // change the final state under certain conditions |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | Some ideas for using this: |
| + | * Setting your custom farmland block during tilling |
| + | * Adding stripped wood behavior for other blocks |
| + | * Disable path creation |