Class BlockCapability<T,C>

java.lang.Object
net.neoforged.neoforge.capabilities.BaseCapability<T,C>
net.neoforged.neoforge.capabilities.BlockCapability<T,C>
Type Parameters:
T - type of queried objects
C - type of the additional context

public final class BlockCapability<T,C> extends BaseCapability<T,C>
A BlockCapability gives flexible access to objects of type T located in the world.

Querying a block capability

To get an object of type T, use ILevelExtension.getCapability(BlockCapability, BlockPos, Object). For example, to query an item handler in the world, from a specific side:


 Level level = ...;
 BlockPos pos = ...;
 Direction side = ...;

 IItemHandler maybeHandler = level.getCapability(Capabilities.ItemHandler.BLOCK, pos, side);
 if (maybeHandler != null) {
     // Use maybeHandler
 }
 

For repeated queries at a specific position, use BlockCapabilityCache to improve performance.

Providing a capability for a block entity

To provide objects of type T, register providers to RegisterCapabilitiesEvent. For example:


 modBus.addListener(RegisterCapabilitiesEvent.class, event -> {
     event.registerBlockEntity(
         Capabilities.ItemHandler.BLOCK, // capability to register for
         MY_BLOCK_ENTITY_TYPE,
         (myBlockEntity, side) -> <return the IItemHandler for myBlockEntity and side>);
 });
 

If a previously returned capability is not valid anymore, or if a new capability is available, ILevelExtension.invalidateCapabilities(BlockPos) MUST be called to notify the caches (see below).

Providing a capability for a plain block

For blocks without a block entity, we use registerBlock instead:

 modBus.addListener(RegisterCapabilitiesEvent.class, event -> {
     event.registerBlock(
         Capabilities.ItemHandler.BLOCK, // capability to register for
         (level, pos, state, be, side) -> <return the IItemHandler>,
         // blocks to register for
         MY_ITEM_HANDLER_BLOCK, MY_OTHER_ITEM_HANDLER_BLOCK);
 });
 

Plain blocks must invalidate their capabilities whenever they change, including on placement and removal. For example:


 public class MyBlock extends Block {
     ļ¼ Override
     public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
         // Invalidate capabilities on block placement or block state change
         level.invalidateCapabilities(pos);
     }

     ļ¼ Override
     public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
         super.onRemove(state, level, pos, newState, movedByPiston);
         // Invalidate capabilities on block removal or block state change
         level.invalidateCapabilities(pos);
     }
 }