BlockApiLookup

public interface BlockApiLookup<A, C>

An object that allows retrieving APIs from blocks in a world. Instances of this interface can be obtained through get.

When trying to find an API, the block or block entity at that position will be queried if it exists. If it doesn't exist, or if it returns {@code null}, the fallback providers will be queried in order.

Note: If you are going to query APIs a lot, consider using BlockApiCache, it may drastically improve performance.

Usage ExampleLet us pretend we have the following interface that we would like to attach to some blocks depending on the direction.
{@code * public interface FluidContainer { * boolean containsFluids(); // return true if not empty * }}
Let us first create a static {@code BlockApiLookup} instance that will manage the registration and the query.
{@code * public final class MyApi { * public static final BlockApiLookupFLUID_CONTAINER = BlockApiLookup.get(new Identifier("mymod:fluid_container"), FluidContainer.class, Direction.class);
 * }}
Using that, we can query instances of {@code FluidContainer}:
{@code * FluidContainer container = MyApi.FLUID_CONTAINER.find(world, pos, direction); * if (container != null) { * // Do something with the container * if (container.containsFluids()) { * System.out.println("It contains fluids!"); * } * }}
For the query to return a useful result, functions that provide an API for a block or a block entity must be registered.
{@code * // If the block entity directly implements the interface, registerSelf can be used. * public class ContainerBlockEntity implements FluidContainer { * // ... * } * BlockEntityTypeCONTAINER_BLOCK_ENTITY_TYPE;
 * MyApi.FLUID_CONTAINER.registerSelf(CONTAINER_BLOCK_ENTITY_TYPE);
 *
 * // For more complicated block entity logic, registerForBlockEntities can be used.
 * // For example, let's provide a stored field, and only when the direction is UP:
 * public class MyBlockEntity {
 *     public final FluidContainer upContainer;
 *     // ...
 * }
 * MyApi.FLUID_CONTAINER.registerForBlockEntities((blockEntity, direction) -> {
 *     if (direction == Direction.UP) { // only expose from the top
 *         // return a field
 *         return ((MyBlockEntity) blockEntity).upContainer;
 *     } else {
 *         return null;
 *     }
 * }, BLOCK_ENTITY_TYPE_1, BLOCK_ENTITY_TYPE_2);
 *
 * // Without a block entity, registerForBlocks can be used.
 * MyApi.FLUID_CONTAINER.registerForBlocks((world, pos, state, blockEntity, direction) -> {
 *     // return a FluidContainer for your block, or null if there is none
 * }, BLOCK_INSTANCE, ANOTHER_BLOCK_INSTANCE); // register as many blocks as you want
 *
 * // Block entity fallback, for example to interface with another mod's FluidInventory.
 * MyApi.FLUID_CONTAINER.registerFallback((world, pos, state, blockEntity, direction) -> {
 *     if (blockEntity instanceof FluidInventory) {
 *         // return wrapper
 *     }
 *     return null;
 * });
 *
 * // General fallback, to interface with anything, for example another BlockApiLookup.
 * MyApi.FLUID_CONTAINER.registerFallback((world, pos, state, blockEntity, direction) -> {
 *     // return something if available, or null
 * });}
Improving performanceWhen performing queries every tick, it is recommended to use BlockApiCache<A, C> instead of directly querying the {@code BlockApiLookup}.
{@code * // 1) create and store an instance * BlockApiCachecache = BlockApiCache.create(MyApi.FLUID_CONTAINER, serverWorld, pos);
 *
 * // 2) use it later, the block entity instance will be cached among other things
 * FluidContainer container = cache.find(direction);
 * if (container != null) {
 *     // ...
 * }
 *
 * // 2bis) if the caller is able to cache the block state as well, for example by listening to neighbor updates,
 * //       that will further improve performance.
 * FluidContainer container = cache.find(direction, cachedBlockState);
 * if (container != null) {
 *     // ...
 * }
 *
 * // no need to destroy the cache, the garbage collector will take care of it}
Generic context typesNote that {@code FluidContainer} and {@code Direction} were completely arbitrary in this example. We can define any {@code BlockApiLookup<A, C>}, where {@code A} is the type of the queried API, and {@code C} is the type of the additional context (the direction parameter in the previous example). If no context is necessary, {@code Void} should be used, and {@code null} instances should be passed.

Parameters

<A>

The type of the API.

<C>

The type of the additional context object.

Types

BlockApiProvider
Link copied to clipboard
public interface BlockApiProvider<A, C>
BlockEntityApiProvider
Link copied to clipboard
public interface BlockEntityApiProvider<A, C>

Functions

apiClass
Link copied to clipboard
abstract Class<AapiClass()
Return the API class of this lookup.
contextClass
Link copied to clipboard
abstract Class<CcontextClass()
Return the context class of this lookup.
find
Link copied to clipboard
@Nullable()
A find(World world, BlockPos pos, C context)
Attempt to retrieve an API from a block in the world.
@Nullable()
abstract A find(World world, BlockPos pos, @Nullable() BlockState state, @Nullable() BlockEntity blockEntity, C context)
Attempt to retrieve an API from a block in the world.
get
Link copied to clipboard
static BlockApiLookup<A, Cget<A, C>(Identifier lookupId, Class<A> apiClass, Class<C> contextClass)
Retrieve the BlockApiLookup associated with an identifier, or create it if it didn't exist yet.
registerFallback
Link copied to clipboard
abstract void registerFallback(BlockApiLookup.BlockApiProvider<A, C> fallbackProvider)
Expose the API for all queries: the provider will be invoked if no object was found using the block or block entity providers.This may have a big performance impact on all queries, use cautiously.
registerForBlockEntities
Link copied to clipboard
abstract void registerForBlockEntities(BlockApiLookup.BlockEntityApiProvider<A, C> provider, Array<BlockEntityType<? extends Object>> blockEntityTypes)
Expose the API for instances of the passed block entity types.
registerForBlocks
Link copied to clipboard
abstract void registerForBlocks(BlockApiLookup.BlockApiProvider<A, C> provider, Array<Block> blocks)
Expose the API for the passed blocks.
registerSelf
Link copied to clipboard
abstract void registerSelf(Array<BlockEntityType<? extends Object>> blockEntityTypes)
Expose the API for the passed block entities directly implementing it.

Inheritors

BlockApiLookupImpl
Link copied to clipboard

Sources

jvm source
Link copied to clipboard