Trait BlockPart
pub trait BlockPart:
Send
+ Sync
+ 'static {
Show 42 methods
// Provided methods
fn neighbor_changed(
&self,
level: &mut dyn LevelTicksHost,
event: &mut NeighborChangedEvent,
) { ... }
fn random_tick(
&self,
level: &mut dyn LevelWriteHost,
event: &mut RandomTickEvent,
) -> Flow { ... }
fn tick_block(
&self,
level: &mut dyn LevelWriteHost,
event: &mut TickBlockEvent,
) -> Flow { ... }
fn update_shape(
&self,
level: &mut dyn LevelTicksHost,
event: &mut UpdateShapeEvent,
) -> Option<BlockState> { ... }
fn block_signal(&self, level: &dyn LevelHost, event: &mut BlockSignalEvent) { ... }
fn is_signal_source(
&self,
level: &dyn LevelHost,
event: &mut IsSignalSourceEvent,
) { ... }
fn has_analog_output(
&self,
level: &dyn LevelHost,
event: &mut HasAnalogOutputEvent,
) { ... }
fn analog_output(
&self,
level: &dyn LevelHost,
event: &mut AnalogOutputEvent,
) { ... }
fn can_survive(
&self,
level: &dyn LevelHost,
event: &mut CanSurviveEvent,
) -> Option<bool> { ... }
fn may_place_on(
&self,
level: &dyn LevelHost,
event: &mut MayPlaceOnEvent,
) -> Option<bool> { ... }
fn is_valid_bonemeal_target(
&self,
level: LevelSide<'_>,
event: &mut IsValidBonemealTargetEvent,
) -> Option<bool> { ... }
fn is_bonemeal_success(
&self,
level: &mut dyn LevelRandomHost,
event: &mut IsBonemealSuccessEvent,
) { ... }
fn perform_bonemeal(
&self,
level: &mut dyn LevelWriteHost,
event: &mut PerformBonemealEvent,
) { ... }
fn state_for_placement(
&self,
level: &dyn LevelHost,
event: &mut StateForPlacementEvent<'_>,
) -> Option<Option<BlockState>> { ... }
fn fire_odds(
&self,
level: &dyn LevelHost,
event: &mut FireOddsEvent,
) -> Option<(i32, i32)> { ... }
fn smoke_source(
&self,
level: &dyn LevelHost,
event: &mut SmokeSourceEvent,
) -> Option<bool> { ... }
fn affect_neighbors_after_removal(
&self,
level: &dyn LevelHost,
event: &mut AffectNeighborsAfterRemovalEvent<'_>,
) { ... }
fn block_jump_factor(
&self,
context: &dyn LoopContext,
event: &mut BlockJumpFactorEvent,
) { ... }
fn block_speed_factor(
&self,
context: &dyn LoopContext,
event: &mut BlockSpeedFactorEvent,
) { ... }
fn fall_on(
&self,
level: &mut dyn LevelRandomHost,
event: &mut FallOnEvent<'_>,
) { ... }
fn bounce_on(
&self,
level: &mut dyn LevelRandomHost,
event: &mut BounceOnEvent<'_>,
) { ... }
fn block_render_visibility(
&self,
host: &dyn ClientHost,
event: &mut BlockRenderVisibilityEvent,
) { ... }
fn use_item_on(
&self,
host: &mut dyn ServerHost,
event: &mut UseItemOnEvent<'_>,
) -> Option<InteractionResult> { ... }
fn use_without_item(
&self,
host: &mut dyn ServerHost,
event: &mut UseWithoutItemEvent<'_>,
) -> Option<InteractionResult> { ... }
fn can_harvest_block(
&self,
host: HostSide<'_>,
event: &mut CanHarvestBlockEvent,
) { ... }
fn can_sustain_plant(
&self,
level: &dyn LevelHost,
event: &mut CanSustainPlantEvent,
) -> Option<bool> { ... }
fn clone_item_stack(
&self,
host: &dyn Host,
event: &mut CloneItemStackEvent<'_>,
) -> Option<ItemStack> { ... }
fn connects_to(&self, level: &dyn LevelHost, event: &mut ConnectsToEvent) { ... }
fn contents_changed(
&self,
host: &mut dyn ServerHost,
event: &mut ContentsChangedEvent,
) { ... }
fn dispense_method(
&self,
host: &mut dyn ServerHost,
event: &mut DispenseMethodEvent<'_>,
) -> Option<(Option<ItemStack>, i32)> { ... }
fn entity_inside(
&self,
host: &mut dyn ServerHost,
event: &mut EntityInsideEvent,
) { ... }
fn exp_drop(
&self,
level: &dyn LevelHost,
event: &mut ExpDropEvent<'_>,
) -> Option<i32> { ... }
fn is_ladder(&self, context: &dyn LoopContext, event: &mut IsLadderEvent) { ... }
fn is_pathfindable(&self, host: &dyn Host, event: &mut IsPathfindableEvent) { ... }
fn item_after_vertical_collision(
&self,
host: HostSide<'_>,
event: &mut ItemAfterVerticalCollisionEvent<'_>,
) -> Flow { ... }
fn minecart_pass(
&self,
host: &mut dyn ServerHost,
event: &mut MinecartPassEvent,
) { ... }
fn on_block_exploded(
&self,
host: &mut dyn ServerHost,
event: &mut OnBlockExplodedEvent<'_>,
) { ... }
fn on_neighbor_change(
&self,
level: &dyn LevelHost,
event: &mut OnNeighborChangeEvent,
) { ... }
fn remove_block(
&self,
level: &dyn LevelHost,
event: &mut RemoveBlockEvent,
) -> Option<BlockState> { ... }
fn should_check_weak_power(
&self,
level: &dyn LevelHost,
event: &mut ShouldCheckWeakPowerEvent,
) { ... }
fn should_redstone_wire_connect_to(
&self,
level: &dyn LevelHost,
event: &mut ShouldRedstoneWireConnectToEvent,
) { ... }
fn weak_changes(&self, level: &dyn LevelHost, event: &mut WeakChangesEvent) { ... }
}Expand description
A block’s part: code attached through Registrar to one block, a mod’s own or vanilla’s.
Its methods are the scoped hooks’, asked only for the blocks it is attached to: a scoped
hook has no Hooks method. They may run on the window’s thread or the server thread.
Annotate each part trait implementation with horizon_part to derive its subscriptions.
Provided Methods§
fn neighbor_changed(
&self,
level: &mut dyn LevelTicksHost,
event: &mut NeighborChangedEvent,
)
fn neighbor_changed( &self, level: &mut dyn LevelTicksHost, event: &mut NeighborChangedEvent, )
An authoritative server is about to deliver neighborChanged.
State and block IDs are valid in this level’s registries for this call.
The host is the level with its ticks, as vanilla’s neighborChanged gets the
level: a part may read its inputs (signal, has_neighbor_signal) and
schedule its tick here, as a diode does (DiodeBlock.checkTickOnNeighbor).
Side: server.
fn random_tick(
&self,
level: &mut dyn LevelWriteHost,
event: &mut RandomTickEvent,
) -> Flow
fn random_tick( &self, level: &mut dyn LevelWriteHost, event: &mut RandomTickEvent, ) -> Flow
An authoritative server’s ServerLevel.tickChunk is about to
random-tick the block state at pos (BlockState.randomTick):
only blocks that tick randomly, a mod’s as its vanilla template block
does. Bone meal’s random ticks (StemBlock.performBonemeal) don’t
fire it. Change the block with native_set_block_property and set
handled to skip the block’s own random tick (a mod crop growing its
own way); a block changed without handled takes its own random tick
as it is now, if it still ticks randomly. Lava’s fluid random tick
runs either way.
Side: server.
Return Flow::Cancel to take it: this sets handled, and later parts are skipped.
fn tick_block(
&self,
level: &mut dyn LevelWriteHost,
event: &mut TickBlockEvent,
) -> Flow
fn tick_block( &self, level: &mut dyn LevelWriteHost, event: &mut TickBlockEvent, ) -> Flow
An authoritative server’s ServerLevel.tickBlock is about to run a
due scheduled tick of the block state at pos (BlockState.tick):
the block is still the one the tick was scheduled for. Change the
block with native_set_block_property and set handled to skip the
block’s own tick; a block changed without handled takes its own
tick as it is now, if it is still the tick’s block.
Side: server.
Return Flow::Cancel to take it: this sets handled, and later parts are skipped.
fn update_shape(
&self,
level: &mut dyn LevelTicksHost,
event: &mut UpdateShapeEvent,
) -> Option<BlockState>
fn update_shape( &self, level: &mut dyn LevelTicksHost, event: &mut UpdateShapeEvent, ) -> Option<BlockState>
An authoritative server is about to compute the state the block
state at pos takes now that its neighbour in direction is
neighbour (BlockBehaviour.updateShape). state may not be in the
world yet (a piston landing it): decide from state, not from the
block at pos. Answer only for your own blocks: put the new state in
new (state keeps the block as it is; air breaks it, with its drops,
on a neighbour update) and the block’s own updateShape doesn’t run,
nor the ticks it would schedule. The level is read-only, as vanilla’s
LevelReader; ticks go through native_schedule_block_tick and
native_schedule_fluid_tick with ticks (ScheduledTickAccess). It
runs often, at least six times per setBlock that updates shapes
(more for redstone wire’s diagonals and knock-on updates): keep it
short.
Side: server.
Return Some to set new; the first part returning Some wins.
fn block_signal(&self, level: &dyn LevelHost, event: &mut BlockSignalEvent)
fn block_signal(&self, level: &dyn LevelHost, event: &mut BlockSignalEvent)
The redstone signal the block state at pos gives on its face, the
side that touches the block reading it: BlockState.getDirectSignal
when direct (what passes through a block it touches, as a lever’s
does), else getSignal. signal holds vanilla’s answer: change it when
the block is yours (0 to 15; anything else is clamped). Asked very often,
from inside the level’s update, so answer from your own state: check the
block first, and don’t read or change the world here. When the answer
changes, and once the block is placed, call
level.update_neighbors(host, pos, state, NeighbourUpdate::Neighbours). Authoritative
servers only.
Side: server.
fn is_signal_source(
&self,
level: &dyn LevelHost,
event: &mut IsSignalSourceEvent,
)
fn is_signal_source( &self, level: &dyn LevelHost, event: &mut IsSignalSourceEvent, )
BlockState.isSignalSource: set source for a block of yours that
gives a signal, so redstone wire beside it connects to it. Authoritative
servers only.
Side: server.
fn has_analog_output(
&self,
level: &dyn LevelHost,
event: &mut HasAnalogOutputEvent,
)
fn has_analog_output( &self, level: &dyn LevelHost, event: &mut HasAnalogOutputEvent, )
BlockState.hasAnalogOutputSignal: set output for a block of yours
that comparators read (how full or far along it is, as a composter’s
level), so they ask native_analog_output. Asked from inside the
level’s update: answer from state alone. Authoritative servers only.
Side: server.
Every part gets event.output in order and may add, change or remove output.
fn analog_output(&self, level: &dyn LevelHost, event: &mut AnalogOutputEvent)
fn analog_output(&self, level: &dyn LevelHost, event: &mut AnalogOutputEvent)
BlockState.getAnalogOutputSignal: the signal a comparator reads from
the block state at pos, face the side that touches the comparator
(or the conductor in front of it). output holds vanilla’s answer:
change it when the block is yours (0 to 15; anything else is clamped).
Asked only for blocks native_has_analog_output answered for, from
inside the level’s update: don’t change the world here. When the
answer changes without the block’s state changing, call
level.update_neighbors(host, pos, state, NeighbourUpdate::OutputSignal); a change of
state through
native_set_block or native_set_block_property (neighbour updates
on) tells the comparators itself, as vanilla’s Level.setBlock does.
Authoritative servers only.
Side: server.
Every part gets event.output in order and may add, change or remove output.
fn can_survive(
&self,
level: &dyn LevelHost,
event: &mut CanSurviveEvent,
) -> Option<bool>
fn can_survive( &self, level: &dyn LevelHost, event: &mut CanSurviveEvent, ) -> Option<bool>
On an authoritative server, BlockState.canSurvive for state at
pos (BlockBehaviour.canSurvive), before the block answers it: as
it is placed (BlockItem.canPlace), from a shape update of a block
whose template checks it (a plant, a torch, a sign: false breaks the
block with its drops), and wherever else vanilla asks. state may not
be in the world yet, so decide from state. Answer only for your own
blocks: Some(false) refuses the spot, Some(true) allows it, and
the block’s own rule doesn’t run. The level is read-only. Asked on
every shape update of such a block: keep it short.
Side: server.
Return Some to set survives; the first part returning Some wins.
fn may_place_on(
&self,
level: &dyn LevelHost,
event: &mut MayPlaceOnEvent,
) -> Option<bool>
fn may_place_on( &self, level: &dyn LevelHost, event: &mut MayPlaceOnEvent, ) -> Option<bool>
On an authoritative server, VegetationBlock.mayPlaceOn for the
plant state on ground at ground_pos, before the plant answers
it: the blocks a mod plant (one whose template is a vanilla plant,
such as a crop) can stand on. Its template’s canSurvive asks it, so
the plant is refused there and pops off when its ground changes to
one it can’t stand on. Answer only for your own blocks. The level is
read-only.
Side: server.
Return Some to set may; the first part returning Some wins.
fn is_valid_bonemeal_target(
&self,
level: LevelSide<'_>,
event: &mut IsValidBonemealTargetEvent,
) -> Option<bool>
fn is_valid_bonemeal_target( &self, level: LevelSide<'_>, event: &mut IsValidBonemealTargetEvent, ) -> Option<bool>
A block nothing in Horizon knows a BonemealableBlock for is about to
take bone meal: vanilla’s BonemealableBlock.isValidBonemealTarget,
state the block’s own state at pos. Answer valid for your own
blocks: the meal is used up on one as vanilla uses it up (the growth
particles and the sound follow, whether or not the roll below grows
it), from a player’s BoneMealItem.useOn, from a dispenser and, on a
crop (a villager bonemeals only a CropBlock), from a villager. Asked
on both sides, as vanilla asks it on both, so a client predicts the
use with your answer: say no where you can only grow on a server
(match LevelSide). Some(false) refuses the meal, even on a block
whose template takes it (vanilla’s growCrop then keeps the meal);
left None, the block keeps the BonemealableBlock its template gives
it, or takes no bone meal.
Side: both.
Return Some to set valid; the first part returning Some wins.
fn is_bonemeal_success(
&self,
level: &mut dyn LevelRandomHost,
event: &mut IsBonemealSuccessEvent,
)
fn is_bonemeal_success( &self, level: &mut dyn LevelRandomHost, event: &mut IsBonemealSuccessEvent, )
BonemealableBlock.isBonemealSuccess for a block that answered
native_is_valid_bonemeal_target, after it did: set success to grow
it this time. Vanilla draws the level’s random here
(isBonemealSuccess(Level, RandomSource, BlockPos, BlockState)), so
draw from native_level_random to keep vanilla’s order.
Authoritative servers only.
Side: server.
Every part gets event.success in order and may add, change or remove success.
fn perform_bonemeal(
&self,
level: &mut dyn LevelWriteHost,
event: &mut PerformBonemealEvent,
)
fn perform_bonemeal( &self, level: &mut dyn LevelWriteHost, event: &mut PerformBonemealEvent, )
BonemealableBlock.performBonemeal for a block that answered
native_is_valid_bonemeal_target and whose native_is_bonemeal_success
said yes: grow it here, state its state at pos. The meal is used up
either way. Change the block with the level’s
native_set_block_property, and schedule with native_schedule_block_tick
(ticks is the hook’s). Authoritative servers only.
Side: server.
fn state_for_placement(
&self,
level: &dyn LevelHost,
event: &mut StateForPlacementEvent<'_>,
) -> Option<Option<BlockState>>
fn state_for_placement( &self, level: &dyn LevelHost, event: &mut StateForPlacementEvent<'_>, ) -> Option<Option<BlockState>>
A block is about to take the state it is placed in
(Block.getStateForPlacement(BlockPlaceContext)), state the block’s
own default state. Answer only for your blocks: put the state you want
in answer as Some(Some(state)) — a state of that block, as vanilla
sets properties on its own defaultBlockState (another block’s is
ignored) — or refuse the placement with Some(None): the block goes
nowhere and the stack is kept, as vanilla’s null. Left empty, the
block’s own placement runs. context is
vanilla’s BlockPlaceContext (the clicked face, the placer’s rotation,
the clicked position, whether the clicked block is being replaced, the
item in hand) and fluid the fluid in the position the block would go
in, which a waterlogged block reads. Build the state from state with
native_state_with_property, and know whether state is yours with
native_state_block. It is asked for every placer that goes
through vanilla’s placement (a player’s BlockItem.place, a
dispenser’s DirectionalPlaceContext), and the answer still takes its
survival and entity obstruction checks. A trait mod returns
Some(Some(state)) to choose a state, Some(None) to refuse, or
None to leave the answer to the next mod or vanilla. Changes to the event’s fluid
copy are mod-provided data forwarded to later Parts, never consumed by the engine.
Authoritative servers only.
Side: server.
Return Some to set answer; the first part returning Some wins.
fn fire_odds(
&self,
level: &dyn LevelHost,
event: &mut FireOddsEvent,
) -> Option<(i32, i32)>
fn fire_odds( &self, level: &dyn LevelHost, event: &mut FireOddsEvent, ) -> Option<(i32, i32)>
On an authoritative server, how fire treats the block state
(FireBlock.setFlammable(block, igniteOdds, burnOdds)): put
(ignite, burn) in odds for your own blocks, and vanilla’s table
isn’t read. Ignite odds above zero let fire stand beside the block and
spread into the air around it (planks 5, wool 30, leaves 30); burn odds
are how fast fire destroys it (planks 20, wool 60, leaves 60). (0, 0)
never burns; keep both within vanilla’s 0 to 100. A waterlogged state
never burns and isn’t asked. Answer only for your own blocks and leave
odds empty otherwise; the level is read-only. Asked hundreds of times
per fire tick: keep it short.
Side: server.
Return Some to set odds; the first part returning Some wins.
fn smoke_source(
&self,
level: &dyn LevelHost,
event: &mut SmokeSourceEvent,
) -> Option<bool>
fn smoke_source( &self, level: &dyn LevelHost, event: &mut SmokeSourceEvent, ) -> Option<bool>
On an authoritative server, CampfireBlock.isSmokeSource for the
block state under a campfire, as the campfire is placed or the block
under it changes: Some(true) for your own blocks makes the campfire a
signal fire whose smoke rises higher, as over a hay bale. The level is
read-only.
Side: server.
Return Some to set smoke; the first part returning Some wins.
fn affect_neighbors_after_removal(
&self,
level: &dyn LevelHost,
event: &mut AffectNeighborsAfterRemovalEvent<'_>,
)
fn affect_neighbors_after_removal( &self, level: &dyn LevelHost, event: &mut AffectNeighborsAfterRemovalEvent<'_>, )
Block.affectNeighborsAfterRemoval for a mod’s block: an authoritative server removed the
block state from pos (moved: a piston pushed it) and has run its template class’s own
updates. Push onto updates the neighbour updates it wants, in order: OutputSignal
(updateNeighbourForOutputSignal), Neighbours (updateNeighborsAt) and
NeighboursExcept(direction) (updateNeighborsAtExceptFromFacing); the level runs each
at once, as the block’s own override would. Answered from inside the level’s write: it
reads, and cannot write blocks or spawn entities.
Side: server.
Every part gets event.updates in order and may add, change or remove updates.
fn block_jump_factor(
&self,
context: &dyn LoopContext,
event: &mut BlockJumpFactorEvent,
)
fn block_jump_factor( &self, context: &dyn LoopContext, event: &mut BlockJumpFactorEvent, )
The jump factor of a block state this part is attached to (Block.getJumpFactor, which Entity.getBlockJumpFactor reads for the player, the cube, the panda, the rabbit and every other living jumper) is being read; vanilla’s values are 0.5 for honey and 1.0 for the rest. A part may change factor (event.factor). The entity reads the block at its feet and, when that gives 1.0, the block below it, so a changed factor takes part in that choice exactly as the block’s own would. It runs for each read, on both sides and on the client’s replayed ticks, so register the mod on both and keep the listener a pure function of its inputs. It is given the loop context of the side that ticks the entity, and takes no Host. NeoForge’s counterpart Block.getJumpFactor() is a method of the block, with no bus event, so this is a part method only; a mod reacting to its own blocks uses this part. Diverges from upstream: new hook.
Side: both.
fn block_speed_factor(
&self,
context: &dyn LoopContext,
event: &mut BlockSpeedFactorEvent,
)
fn block_speed_factor( &self, context: &dyn LoopContext, event: &mut BlockSpeedFactorEvent, )
The speed factor of a block state this part is attached to (Block.getSpeedFactor, which Entity.getBlockSpeedFactor reads for the player, mobs, boats and minecarts where vanilla reads it) is being read; vanilla’s values are 0.4 for honey and soul sand and 1.0 for the rest. A part may change factor (event.factor). The entity reads the block at its feet and, when that is not water or a bubble column and gives 1.0, the block below it, so a changed factor takes part in that choice exactly as the block’s own would. It runs for each read, on both sides and on the client’s replayed ticks, so register the mod on both and keep the listener a pure function of its inputs. It is given the loop context of the side that ticks the entity, and takes no Host. NeoForge’s counterpart Block.getSpeedFactor() is a method of the block, with no bus event, so this is a part method only; a mod reacting to its own blocks uses this part. Diverges from upstream: new hook.
Side: both.
fn fall_on(&self, level: &mut dyn LevelRandomHost, event: &mut FallOnEvent<'_>)
fn fall_on(&self, level: &mut dyn LevelRandomHost, event: &mut FallOnEvent<'_>)
An entity landed on a block state this part is attached to (Block.fallOn), after falling event.distance blocks. event.damage is the fall damage the entity calculated, before hurt handling and the fall sounds: change it, and zero prevents both. An entity that cannot be hurt by the fall (creative, fall immune) is told with zero damage and keeps its immunity, and a cancelled fall still lands. It runs inside the entity’s move, on the level random host: it reads blocks and draws the level’s random in vanilla’s order, and cannot write. A write the override makes (farmland turning to dirt, a turtle egg breaking) is asked with event.request(LandingWrite::SetBlock(state)) or LandingWrite::DestroyBlock { drop } and lands at the block the entity landed on once the entity’s batch has ticked, in the order asked, if the block is still the state it landed on. SetBlock takes an API BlockState. The complete requested batch is checked before queuing: an invalid key or ordinal refuses all writes and sibling outputs from that callback, including damage. The original landed-state guard is checked once per batch, not between its ordered writes. Players, mobs and dropped items land here (an item as an EntityRef of kind minecraft:item, with zero damage: items take none); projectiles and the other entities do not yet.
Side: server.
Every part gets event.damage in order and may add, change or remove damage.
fn bounce_on(
&self,
level: &mut dyn LevelRandomHost,
event: &mut BounceOnEvent<'_>,
)
fn bounce_on( &self, level: &mut dyn LevelRandomHost, event: &mut BounceOnEvent<'_>, )
An entity bounced off a block state this part is attached to (Block.bounceOn), after falling event.fall_distance blocks. It fires only when the entity bounced, just before vanilla sets its movement. event.movement is the movement the bounce leaves it (x, y, z): change it to change what the entity keeps. It runs inside the entity’s move, on the level random host: it reads blocks and draws the level’s random in vanilla’s order, but writes nothing. Players and mobs bounce here; dropped items and the other entities do not yet.
Side: server.
Every part gets event.movement in order and may add, change or remove movement.
fn block_render_visibility(
&self,
host: &dyn ClientHost,
event: &mut BlockRenderVisibilityEvent,
)
fn block_render_visibility( &self, host: &dyn ClientHost, event: &mut BlockRenderVisibilityEvent, )
Hides a block state from the mesher: set event.hidden and the state draws nothing, as if its blocks were air. Its neighbours’ faces toward it show, it no longer hides what is behind it, and its fluid layer and block entity are not drawn; light, collision and the server are untouched. The answer depends on the state alone and is resolved at mesh time, never per frame: the game asks once for every state when the client joins a world, and again for every state each time a mod calls ClientHost::refresh_render_visibility (a toggle, an ore scanner). Attach the part to vanilla blocks with block_part_tag. With no mod answering, the mesher pays nothing.
Side: client.
Every part gets event.hidden in order and may add, change or remove hidden.
fn use_item_on(
&self,
host: &mut dyn ServerHost,
event: &mut UseItemOnEvent<'_>,
) -> Option<InteractionResult>
fn use_item_on( &self, host: &mut dyn ServerHost, event: &mut UseItemOnEvent<'_>, ) -> Option<InteractionResult>
BlockBehaviour.useItemOn: the block’s own behaviour, with the
held item, on the server for each player. An answer replaces the
template’s behaviour; TryWithEmptyHand tries useWithoutItem on
the main hand, and Pass goes on to the item’s useOn.
Side: server.
Return Some to set answer; the first part returning Some wins.
fn use_without_item(
&self,
host: &mut dyn ServerHost,
event: &mut UseWithoutItemEvent<'_>,
) -> Option<InteractionResult>
fn use_without_item( &self, host: &mut dyn ServerHost, event: &mut UseWithoutItemEvent<'_>, ) -> Option<InteractionResult>
BlockBehaviour.useWithoutItem: the captured state’s empty-hand method,
after useItemOn asks for it, on the server and main hand only.
Side: server.
Return Some to set answer; the first part returning Some wins.
fn can_harvest_block(
&self,
host: HostSide<'_>,
event: &mut CanHarvestBlockEvent,
)
fn can_harvest_block( &self, host: HostSide<'_>, event: &mut CanHarvestBlockEvent, )
Whether the player player’s tool harvests the block state at pos
(IBlockExtension.canHarvestBlock, what Player.hasCorrectToolForDrops asks of the block).
can_harvest starts with vanilla’s answer: false for a block that needs a tool the player’s
held item is not, true otherwise. Set it for your own block; false breaks the block and drops
nothing, and the dig is slowed as vanilla slows a wrong tool. The part answers first and the
global player_harvest_check hears the result, so a mod reacting to every block still has the
last word. Asked wherever the harvest rule is: the dig’s progress (both sides, so a client
predicts it), the break and a door’s break.
Side: both.
Every part gets event.can_harvest in order and may add, change or remove can_harvest.
fn can_sustain_plant(
&self,
level: &dyn LevelHost,
event: &mut CanSustainPlantEvent,
) -> Option<bool>
fn can_sustain_plant( &self, level: &dyn LevelHost, event: &mut CanSustainPlantEvent, ) -> Option<bool>
On an authoritative server, IBlockExtension.canSustainPlant for the soil ground at
ground_pos and the plant state above it, asked before the plant answers its own
mayPlaceOn (may_place_on) wherever vanilla’s plant rule reads its ground: when the plant is
placed, from its shape update and wherever else vanilla asks. Some(true) lets the plant
stand there, Some(false) refuses it (a planted one pops off when its ground changes to this block),
and left None the plant’s own may_place_on answers, as vanilla’s does. Answer only for
your own soil. The level is read-only. Runs on every shape update of a plant over a part’s
block: keep it short.
Side: server.
Return Some to set sustains; the first part returning Some wins.
fn clone_item_stack(
&self,
host: &dyn Host,
event: &mut CloneItemStackEvent<'_>,
) -> Option<ItemStack>
fn clone_item_stack( &self, host: &dyn Host, event: &mut CloneItemStackEvent<'_>, ) -> Option<ItemStack>
BlockBehaviour.getCloneItemStack, asked by
ServerGamePacketListenerImpl.handlePickItemFromBlock. include_data
is true for a creative player picking with Ctrl. Leave stack unset to
keep the game’s item. Creative breaking, such as a beehive’s
playerWillDestroy, does not ask this query. Server-side.
Side: server.
Return Some to set stack; the first part returning Some wins.
fn connects_to(&self, level: &dyn LevelHost, event: &mut ConnectsToEvent)
fn connects_to(&self, level: &dyn LevelHost, event: &mut ConnectsToEvent)
Whether a fence, wall, or iron bars or pane of yours connects a side:
set connected to say whether the block state at pos connects toward
neighbour, the state beside it, direction pointing from the block to
that neighbour and face_solid whether the neighbour’s face toward the
block is sturdy. kind names vanilla’s rule, and connected holds its
answer: ConnectionKind::Fence is FenceBlock.connectsTo (a solid face, a
fence of the same kind or a gate across the arm), Wall is
WallBlock.connectsTo (a wall, a solid face, iron bars or a pane, or a
gate across the side; a connected side is still low or tall from the
block above) and Bars is IronBarsBlock.attachsTo for iron bars and
glass panes (a solid face, bars or a pane, or a wall; vanilla’s rule
ignores direction). Change it, to false as well as to true, when the
block is your own. Asked whenever the block settles its shape toward a
side or is placed, inside the level’s update: answer from the arguments
without touching the world. Only the block’s own part is asked, so
vanilla blocks cost nothing. Authoritative servers only. Contract version
2: version 1 was fence_connects_to, for fences alone and without
kind. Diverges from upstream: new hook.
Side: server.
Every part gets event.connected in order and may add, change or remove connected.
fn contents_changed(
&self,
host: &mut dyn ServerHost,
event: &mut ContentsChangedEvent,
)
fn contents_changed( &self, host: &mut dyn ServerHost, event: &mut ContentsChangedEvent, )
A server-only, non-cancellable backing-block storage notice at Container.setChanged / BlockEntity.setChanged, after the write and before existing dirty/comparator updates. The event carries LevelRef, BlockPos and BlockState. Native After::Changed transactions notify each backing block once at the root commit, never on abort or simulation; explicit set_changed invalidates even equal contents. Nested writes to the block whose notice is active still apply but do not re-enter its notice; writes to another block notify normally. Double containers notify each backing component, not the other half merely refreshed for comparators. Vehicle/menu placeholder coordinates are excluded. Replaces the Create port positional contents_changed mixin for depot, package and schematic storage; there is no matching NeoForge bus event. Side: server.
fn dispense_method(
&self,
host: &mut dyn ServerHost,
event: &mut DispenseMethodEvent<'_>,
) -> Option<(Option<ItemStack>, i32)>
fn dispense_method( &self, host: &mut dyn ServerHost, event: &mut DispenseMethodEvent<'_>, ) -> Option<(Option<ItemStack>, i32)>
DispenserBlock.getDispenseMethod, before the item’s dispense_item:
the block the dispenser faces chooses what the dispense does, for any
item, including vanilla items, on the authoritative server (not
droppers). state is the block at pos moved by facing (air
included), and the part is asked only for that block. An answer wins:
no item part is asked and vanilla’s behaviour
doesn’t run. The answer is dispense_item’s: a remainder of None
empties the slot, Some(stack) replaces it (the hook owns
consumption: no extra item is removed afterwards), and event is the
level event played with the smoke: 1000 the click, 1001 the fail sound,
or 0 for nothing at all. Leave answer None and dispense_item decides,
as it did before.
Side: server.
Return Some to set answer; the first part returning Some wins.
fn entity_inside(
&self,
host: &mut dyn ServerHost,
event: &mut EntityInsideEvent,
)
fn entity_inside( &self, host: &mut dyn ServerHost, event: &mut EntityInsideEvent, )
An entity is inside a block state this part is attached to (Block.entityInside). event.precise is Entity.checkInsideBlocks’ flag: the entity moved nearly a block, or its box at the target touches the block. Fires for mobs, projectiles, dropped items and players on the server, once per entity and block per move, after the entity-kind batch (or the player’s turn) has ticked, not mid-sweep; a contact whose entity is gone or whose block changed is dropped. Vanilla’s InsideBlockEffectApplier is not exposed.
Side: server.
fn exp_drop(
&self,
level: &dyn LevelHost,
event: &mut ExpDropEvent<'_>,
) -> Option<i32>
fn exp_drop( &self, level: &dyn LevelHost, event: &mut ExpDropEvent<'_>, ) -> Option<i32>
Experience before enchantments (IBlockExtension.getExpDrop). First answer
replaces vanilla sampling; the global break_block event may override it.
Answers are clamped to 0..=32767. A panic unwinds before the answer is applied.
Side: server.
Return Some to set experience; the first part returning Some wins.
fn is_ladder(&self, context: &dyn LoopContext, event: &mut IsLadderEvent)
fn is_ladder(&self, context: &dyn LoopContext, event: &mut IsLadderEvent)
Whether a living entity climbs the block state this part is attached to (IBlockExtension.isLadder, which LivingEntity.onClimbable asks of the block the entity stands in). entity is the climber’s id and pos the block it stands in; state is that block’s state. ladder starts with vanilla’s answer, whether the block is in #minecraft:climbable, and a part may set either value: true makes the block climbable as a ladder is, false refuses it though the tag lists it. A gliding entity (isFallFlying) in a #minecraft:can_glide_through block, a spectator and a player who is flying are never asked, as vanilla never climbs for them, and an open trapdoor over a ladder climbs as before. Read for the player, the mobs, and the climbing a mod reads through LivingRef::is_climbing. It fires on both sides and on the client’s replayed ticks, so register the mod on both and keep the listener a pure function of its inputs. It is given the loop context of the side that ticks the entity, and takes no Host. With no part attached to the state, the owning game checks the hook subscription and prepared API block key before any event conversion, so the cost is one table lookup. Armor stands never ask it. Diverges from upstream: new hook.
Side: both.
fn is_pathfindable(&self, host: &dyn Host, event: &mut IsPathfindableEvent)
fn is_pathfindable(&self, host: &dyn Host, event: &mut IsPathfindableEvent)
Changes whether a path of a PathComputationType (Land, Water or Air) may go through a block state. event.pathfindable starts with the block’s own answer. The answer depends on the state and the type alone: the game asks once per state and type when parts resolve, at world load and on every /reload, so path finding and spawning read the stored answer and a part cannot answer from a position, level or time.
Side: server.
Every part gets event.pathfindable in order and may add, change or remove pathfindable.
fn item_after_vertical_collision(
&self,
host: HostSide<'_>,
event: &mut ItemAfterVerticalCollisionEvent<'_>,
) -> Flow
fn item_after_vertical_collision( &self, host: HostSide<'_>, event: &mut ItemAfterVerticalCollisionEvent<'_>, ) -> Flow
native_item_after_vertical_collision lends a dropped item’s active stack after vertical collision response, before block effects, merging and pickup. The block is the one selected by the legacy on-position query. client identifies prediction. Set discard (trait Flow::Cancel) or set the stack to None to consume the item without loot or pickup. A movement skipped by the normal item tick sends no notification. Bundles need “hooks”: @API:item_after_vertical_collision@.
Side: both.
Return Flow::Cancel to take it: this sets discard, and later parts are skipped.
fn minecart_pass(
&self,
host: &mut dyn ServerHost,
event: &mut MinecartPassEvent,
)
fn minecart_pass( &self, host: &mut dyn ServerHost, event: &mut MinecartPassEvent, )
A minecart passed over a rail block state this part is attached to (the moment AbstractMinecart calls activateMinecart on an activator rail, for every rail; Forge’s IBaseRailExtension.onMinecartPass, which NeoForge 26.3 no longer has, so this hook has no counterpart). event.entity is the cart, event.pos the rail. With the old minecart physics it fires once per tick the cart is on a rail; with minecart_improvements once per track iteration, so a fast cart can pass several times in a tick. It fires after the cart’s batch has ticked, not mid-move, so a write the part makes (a velocity change through the cart handle) lands on the stored cart, and a pass whose cart is gone or whose rail changed is dropped. Only a rail state a part listens for is recorded; with no such part nothing is kept. Diverges from upstream: new hook.
Side: server.
fn on_block_exploded(
&self,
host: &mut dyn ServerHost,
event: &mut OnBlockExplodedEvent<'_>,
)
fn on_block_exploded( &self, host: &mut dyn ServerHost, event: &mut OnBlockExplodedEvent<'_>, )
An explosion destroys this block, before removal and while its live block entity is readable. Writes are allowed; the engine still replaces the cell with air afterwards, including a replacement written by the part. Side: server.
fn on_neighbor_change(
&self,
level: &dyn LevelHost,
event: &mut OnNeighborChangeEvent,
)
fn on_neighbor_change( &self, level: &dyn LevelHost, event: &mut OnNeighborChangeEvent, )
A neighbouring block entity changed, was created or removed. Vanilla comparator processing runs first. Side: server.
fn remove_block(
&self,
level: &dyn LevelHost,
event: &mut RemoveBlockEvent,
) -> Option<BlockState>
fn remove_block( &self, level: &dyn LevelHost, event: &mut RemoveBlockEvent, ) -> Option<BlockState>
Choose the state left by removing your block. Return a state in answer
to replace vanilla’s fluid block (air when dry), or leave it unanswered.
Only the removed block’s Part is asked, on the authoritative server.
The replacement must be a registered block state; an invalid answer is
refused with a diagnostic and vanilla’s replacement is written instead.
The normal setBlock effects and flags 3 (+64 when moved by a piston)
apply to the written state. The level is read-only during this call.
Side: server.
Return Some to set answer; the first part returning Some wins.
fn should_check_weak_power(
&self,
level: &dyn LevelHost,
event: &mut ShouldCheckWeakPowerEvent,
)
fn should_check_weak_power( &self, level: &dyn LevelHost, event: &mut ShouldCheckWeakPowerEvent, )
IBlockExtension.shouldCheckWeakPower: set check to decide whether
indirect power is read through this block. check starts with vanilla’s
conductor answer. direction is the input side of the block being powered,
opposite the queried block’s output side. Authoritative servers only.
Side: server.
Every part gets event.check in order and may add, change or remove check.
fn should_redstone_wire_connect_to(
&self,
level: &dyn LevelHost,
event: &mut ShouldRedstoneWireConnectToEvent,
)
fn should_redstone_wire_connect_to( &self, level: &dyn LevelHost, event: &mut ShouldRedstoneWireConnectToEvent, )
BlockBehaviour.shouldRedstoneWireConnectTo: set connected to say
whether redstone wire connects to the block state at pos.
direction points from the wire toward the neighbouring block, or is
None when the wire asks about the block above or below. connected holds vanilla’s answer: change
it when the block is yours. Asked whenever wire settles its shape:
answer from state and pos without touching the world. When the
answer changes, and once the wire is placed, update its neighbours
(level.update_neighbors). Authoritative servers only.
Side: server.
Every part gets event.connected in order and may add, change or remove connected.
fn weak_changes(&self, level: &dyn LevelHost, event: &mut WeakChangesEvent)
fn weak_changes(&self, level: &dyn LevelHost, event: &mut WeakChangesEvent)
Whether this block receives block entity changes through an adjacent conductor. Starts false. Side: server.
Every part gets event.receive in order and may add, change or remove receive.
Trait Implementations§
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".