Views
Actions
Difference between revisions of "Events/BlockEvent"
EERussianguy (talk | contribs) |
EERussianguy (talk | contribs) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 14: | Line 14: | ||
public void onBlockBreak(final BlockEvent.BreakEvent event) | 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 | 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 | event.setExpToDrop(10); // change the amount of experience we'll be dropping | ||
PlayerEntity player = event.getPlayer(); | PlayerEntity player = event.getPlayer(); | ||
− | if (player. | + | if (player.getMainHandItem().getItem().equals(Items.DIAMOND_SHOVEL)) // check what we're holding |
{ | { | ||
− | ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone | + | ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.BONE)); // give a bone |
} | } | ||
} | } | ||
Line 46: | Line 47: | ||
public void onEntityPlace(final BlockEvent.EntityPlaceEvent event) | public void onEntityPlace(final BlockEvent.EntityPlaceEvent event) | ||
{ | { | ||
− | + | IWorld world = event.getWorld(); | |
− | if (!world.isClientSide() && | + | if (!world.isClientSide() && event.getEntity() instanceof EndermanEntity) |
{ | { | ||
− | + | event.setCanceled(true); // prevent enderman placement | |
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
} | } | ||
Line 81: | Line 77: | ||
public void onNeighborNotify(final BlockEvent.NeighborNotifyEvent event) | public void onNeighborNotify(final BlockEvent.NeighborNotifyEvent event) | ||
{ | { | ||
− | if ( | + | IWorld world = event.getWorld(); |
+ | if (world.isClientSide()) return; | ||
BlockPos eventPos = event.getPos(); | 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 | |
+ | } | ||
+ | } | ||
} | } | ||
} | } | ||
Line 106: | Line 105: | ||
public void onFluidSourceCreate(final BlockEvent.CreateFluidSourceEvent event) | public void onFluidSourceCreate(final BlockEvent.CreateFluidSourceEvent event) | ||
{ | { | ||
+ | IWorldReader world = event.getWorld(); | ||
if (!world.isClientSide() && event.getPos().getY() > 100) | if (!world.isClientSide() && event.getPos().getY() > 100) | ||
{ | { | ||
Line 128: | Line 128: | ||
public void onFluidPlace(final BlockEvent.FluidPlaceBlockEvent event) | public void onFluidPlace(final BlockEvent.FluidPlaceBlockEvent event) | ||
{ | { | ||
+ | IWorld world = event.getWorld(); | ||
if (world.isClientSide()) return; | if (world.isClientSide()) return; | ||
BlockState newState = event.getNewState(); | BlockState newState = event.getNewState(); | ||
− | + | if (newState.is(Blocks.COBBLESTONE) && world.dayTime() > 14000L) | |
− | |||
− | |||
− | |||
− | |||
{ | { | ||
event.setNewState(Blocks.ANDESITE.defaultBlockState()); // change the block if done during nighttime. | event.setNewState(Blocks.ANDESITE.defaultBlockState()); // change the block if done during nighttime. | ||
Line 157: | Line 154: | ||
public void onCropGrowPre(final BlockEvent.CropGrowEvent.Pre event) | public void onCropGrowPre(final BlockEvent.CropGrowEvent.Pre event) | ||
{ | { | ||
+ | IWorld world = event.getWorld(); | ||
if (world.isClientSide()) return; | if (world.isClientSide()) return; | ||
BlockState state = event.getState(); | BlockState state = event.getState(); | ||
Line 165: | Line 163: | ||
else if (state.is(Blocks.BAMBOO)) | else if (state.is(Blocks.BAMBOO)) | ||
{ | { | ||
− | if ( | + | if (world.getRandom().nextFloat() > 0.2F) // take a 4/5 chance |
{ | { | ||
event.setResult(Event.Result.DENY); // make bamboo grow less often | 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 | ||
} | } | ||
} | } | ||
Line 189: | Line 200: | ||
public void onTrample(final BlockEvent.FarmlandTrampleEvent event) | public void onTrample(final BlockEvent.FarmlandTrampleEvent event) | ||
{ | { | ||
+ | IWorld world = event.getWorld(); | ||
if (!world.isClientSide() && event.getFallDistance() < 10.0F) | if (!world.isClientSide() && event.getFallDistance() < 10.0F) | ||
{ | { | ||
Line 202: | Line 214: | ||
This is mostly used for preventing portal spawning in certain dimensions (even the overworld). | 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 == | == BlockToolInteractEvent == | ||
Line 208: | Line 228: | ||
<code>setFinalState()</code>: Set what you want the result to be. | <code>setFinalState()</code>: Set what you want the result to be. | ||
− | <code>getFinalState()</code>: Returns what it will be changed to. | + | <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: | Example usage: | ||
Line 214: | Line 234: | ||
public void onToolInteract(final BlockEvent.BlockToolInteractEvent event) | public void onToolInteract(final BlockEvent.BlockToolInteractEvent event) | ||
{ | { | ||
− | if (!world.isClientSide( | + | IWorld world = event.getWorld(); |
+ | if (!world.isClientSide() && event.getHeldItemStack().getItem() == Items.NETHERITE_HOE) | ||
{ | { | ||
− | event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // | + | event.setFinalState(Blocks.NETHERRACK.defaultBlockState()); // set the block to netherrack |
+ | // note that this happens for any right click on a block, not just dirt | ||
} | } | ||
} | } |
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