mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-21 03:10:54 -04:00
Add id getter to ApiLookups and expose the BE in BlockApiCache (#1866)
* Add id getter to ApiLookups and expose the BE in BlockApiCache * identifier() -> getIdentifier(), and add some query methods to BlockApiCache * getId
This commit is contained in:
parent
252fd7d614
commit
17be577f67
11 changed files with 134 additions and 18 deletions
fabric-api-lookup-api-v1/src
main/java/net/fabricmc/fabric
api/lookup/v1
block
custom
entity
item
impl/lookup
testmod/java/net/fabricmc/fabric/test/lookup
|
@ -22,6 +22,7 @@ import org.jetbrains.annotations.ApiStatus;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
|
@ -64,6 +65,30 @@ public interface BlockApiCache<A, C> {
|
|||
@Nullable
|
||||
A find(@Nullable BlockState state, C context);
|
||||
|
||||
/**
|
||||
* Return the block entity at the target position of this lookup.
|
||||
*
|
||||
* <p>This is the most efficient way to query the block entity at the target position repeatedly:
|
||||
* unless the block entity has been loaded or unloaded since the last query, the result will be cached.
|
||||
*/
|
||||
@Nullable
|
||||
BlockEntity getBlockEntity();
|
||||
|
||||
/**
|
||||
* Return the lookup this cache is bound to.
|
||||
*/
|
||||
BlockApiLookup<A, C> getLookup();
|
||||
|
||||
/**
|
||||
* Return the world this cache is bound to.
|
||||
*/
|
||||
ServerWorld getWorld();
|
||||
|
||||
/**
|
||||
* Return the position this cache is bound to.
|
||||
*/
|
||||
BlockPos getPos();
|
||||
|
||||
/**
|
||||
* Create a new instance bound to the passed {@link ServerWorld} and position, and querying the same API as the passed lookup.
|
||||
*/
|
||||
|
|
|
@ -236,6 +236,11 @@ public interface BlockApiLookup<A, C> {
|
|||
*/
|
||||
void registerFallback(BlockApiProvider<A, C> fallbackProvider);
|
||||
|
||||
/**
|
||||
* Return the identifier of this lookup.
|
||||
*/
|
||||
Identifier getId();
|
||||
|
||||
/**
|
||||
* Return the API class of this lookup.
|
||||
*/
|
||||
|
|
|
@ -62,8 +62,9 @@ import net.fabricmc.fabric.impl.lookup.custom.ApiLookupMapImpl;
|
|||
* return (ItemStackApiLookup<A, C>) LOOKUPS.getLookup(lookupId, apiClass, contextClass);
|
||||
* }
|
||||
*
|
||||
* private ItemStackApiLookupImpl(Class<?> apiClass, Class<?> contextClass) {
|
||||
* // We don't use these classes, so nothing to do here.
|
||||
* private ItemStackApiLookupImpl(Identifier id, Class<?> apiClass, Class<?> contextClass) {
|
||||
* // We don't use these parameters, so nothing to do here.
|
||||
* // In practice, these parameters should be stored and exposed with identifier(), apiClass() and contextClass() getter functions.
|
||||
* }
|
||||
* // We will use an ApiProviderMap to store the providers.
|
||||
* private final ApiProviderMap<Item, ItemStackApiProvider<A, C>> providerMap = ApiProviderMap.create();
|
||||
|
@ -97,12 +98,12 @@ public interface ApiLookupMap<L> extends Iterable<L> {
|
|||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param lookupFactory The factory that is used to create API lookup instances.
|
||||
* @param lookupConstructor The constructor that is used to create API lookup instances.
|
||||
*/
|
||||
static <L> ApiLookupMap<L> create(LookupFactory<L> lookupFactory) {
|
||||
Objects.requireNonNull(lookupFactory, "Lookup factory may not be null.");
|
||||
static <L> ApiLookupMap<L> create(LookupConstructor<L> lookupConstructor) {
|
||||
Objects.requireNonNull(lookupConstructor, "Lookup factory may not be null.");
|
||||
|
||||
return new ApiLookupMapImpl<>(lookupFactory);
|
||||
return new ApiLookupMapImpl<>(lookupConstructor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,6 +118,33 @@ public interface ApiLookupMap<L> extends Iterable<L> {
|
|||
*/
|
||||
L getLookup(Identifier lookupId, Class<?> apiClass, Class<?> contextClass);
|
||||
|
||||
@FunctionalInterface
|
||||
interface LookupConstructor<L> {
|
||||
/**
|
||||
* Create a new API lookup implementation.
|
||||
*
|
||||
* @param identifier The identifier of this lookup.
|
||||
* @param apiClass The API class passed to {@link #getLookup}.
|
||||
* @param contextClass The context class passed to {@link #getLookup}.
|
||||
*/
|
||||
L get(Identifier identifier, Class<?> apiClass, Class<?> contextClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param lookupFactory The factory that is used to create API lookup instances.
|
||||
* @deprecated {@link LookupConstructor} should be used instead of lookup factory, to expose the identifier.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
static <L> ApiLookupMap<L> create(LookupFactory<L> lookupFactory) {
|
||||
return create((id, apiClass, contextClass) -> lookupFactory.get(apiClass, contextClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated {@link LookupConstructor} should be used instead as it also passes the identifier.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
interface LookupFactory<L> {
|
||||
/**
|
||||
* Create a new API lookup implementation.
|
||||
|
|
|
@ -146,6 +146,11 @@ public interface EntityApiLookup<A, C> {
|
|||
*/
|
||||
void registerFallback(EntityApiProvider<A, C> fallbackProvider);
|
||||
|
||||
/**
|
||||
* Return the identifier of this lookup.
|
||||
*/
|
||||
Identifier getId();
|
||||
|
||||
/**
|
||||
* Returns the API class of this lookup.
|
||||
*/
|
||||
|
|
|
@ -145,6 +145,11 @@ public interface ItemApiLookup<A, C> {
|
|||
*/
|
||||
void registerFallback(ItemApiProvider<A, C> fallbackProvider);
|
||||
|
||||
/**
|
||||
* Return the identifier of this lookup.
|
||||
*/
|
||||
Identifier getId();
|
||||
|
||||
/**
|
||||
* Return the API class of this lookup.
|
||||
*/
|
||||
|
|
|
@ -61,11 +61,8 @@ public final class BlockApiCacheImpl<A, C> implements BlockApiCache<A, C> {
|
|||
@Nullable
|
||||
@Override
|
||||
public A find(@Nullable BlockState state, C context) {
|
||||
// Get block entity
|
||||
if (!blockEntityCacheValid) {
|
||||
cachedBlockEntity = world.getBlockEntity(pos);
|
||||
blockEntityCacheValid = true;
|
||||
}
|
||||
// Update block entity cache
|
||||
getBlockEntity();
|
||||
|
||||
// Get block state
|
||||
if (state == null) {
|
||||
|
@ -105,6 +102,32 @@ public final class BlockApiCacheImpl<A, C> implements BlockApiCache<A, C> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockEntity getBlockEntity() {
|
||||
if (!blockEntityCacheValid) {
|
||||
cachedBlockEntity = world.getBlockEntity(pos);
|
||||
blockEntityCacheValid = true;
|
||||
}
|
||||
|
||||
return cachedBlockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockApiLookupImpl<A, C> getLookup() {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
static {
|
||||
ServerBlockEntityEvents.BLOCK_ENTITY_LOAD.register((blockEntity, world) -> {
|
||||
((ServerWorldCache) world).fabric_invalidateCache(blockEntity.getPos());
|
||||
|
|
|
@ -47,13 +47,15 @@ public final class BlockApiLookupImpl<A, C> implements BlockApiLookup<A, C> {
|
|||
return (BlockApiLookup<A, C>) LOOKUPS.getLookup(lookupId, apiClass, contextClass);
|
||||
}
|
||||
|
||||
private final Identifier identifier;
|
||||
private final Class<A> apiClass;
|
||||
private final Class<C> contextClass;
|
||||
private final ApiProviderMap<Block, BlockApiProvider<A, C>> providerMap = ApiProviderMap.create();
|
||||
private final List<BlockApiProvider<A, C>> fallbackProviders = new CopyOnWriteArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private BlockApiLookupImpl(Class<?> apiClass, Class<?> contextClass) {
|
||||
private BlockApiLookupImpl(Identifier identifier, Class<?> apiClass, Class<?> contextClass) {
|
||||
this.identifier = identifier;
|
||||
this.apiClass = (Class<A>) apiClass;
|
||||
this.contextClass = (Class<C>) contextClass;
|
||||
}
|
||||
|
@ -174,6 +176,11 @@ public final class BlockApiLookupImpl<A, C> implements BlockApiLookup<A, C> {
|
|||
fallbackProviders.add(fallbackProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<A> apiClass() {
|
||||
return apiClass;
|
||||
|
|
|
@ -28,10 +28,10 @@ import net.fabricmc.fabric.api.lookup.v1.custom.ApiLookupMap;
|
|||
|
||||
public final class ApiLookupMapImpl<L> implements ApiLookupMap<L> {
|
||||
private final Map<Identifier, StoredLookup<L>> lookups = new HashMap<>();
|
||||
private final LookupFactory<L> lookupFactory;
|
||||
private final LookupConstructor<L> lookupConstructor;
|
||||
|
||||
public ApiLookupMapImpl(LookupFactory<L> lookupFactory) {
|
||||
this.lookupFactory = lookupFactory;
|
||||
public ApiLookupMapImpl(LookupConstructor<L> lookupConstructor) {
|
||||
this.lookupConstructor = lookupConstructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,7 +40,7 @@ public final class ApiLookupMapImpl<L> implements ApiLookupMap<L> {
|
|||
Objects.requireNonNull(apiClass, "API class may not be null.");
|
||||
Objects.requireNonNull(contextClass, "Context class may not be null.");
|
||||
|
||||
StoredLookup<L> storedLookup = lookups.computeIfAbsent(lookupId, id -> new StoredLookup<>(lookupFactory.get(apiClass, contextClass), apiClass, contextClass));
|
||||
StoredLookup<L> storedLookup = lookups.computeIfAbsent(lookupId, id -> new StoredLookup<>(lookupConstructor.get(id, apiClass, contextClass), apiClass, contextClass));
|
||||
|
||||
if (storedLookup.apiClass == apiClass && storedLookup.contextClass == contextClass) {
|
||||
return storedLookup.lookup;
|
||||
|
|
|
@ -46,12 +46,14 @@ public class EntityApiLookupImpl<A, C> implements EntityApiLookup<A, C> {
|
|||
private static final Map<Class<?>, Set<EntityType<?>>> REGISTERED_SELVES = new HashMap<>();
|
||||
private static boolean checkEntityLookup = true;
|
||||
|
||||
private final Identifier identifier;
|
||||
private final Class<A> apiClass;
|
||||
private final Class<C> contextClass;
|
||||
private final ApiProviderMap<EntityType<?>, EntityApiProvider<A, C>> providerMap = ApiProviderMap.create();
|
||||
private final List<EntityApiProvider<A, C>> fallbackProviders = new CopyOnWriteArrayList<>();
|
||||
|
||||
private EntityApiLookupImpl(Class<A> apiClass, Class<C> contextClass) {
|
||||
private EntityApiLookupImpl(Identifier identifier, Class<A> apiClass, Class<C> contextClass) {
|
||||
this.identifier = identifier;
|
||||
this.apiClass = apiClass;
|
||||
this.contextClass = contextClass;
|
||||
}
|
||||
|
@ -153,6 +155,11 @@ public class EntityApiLookupImpl<A, C> implements EntityApiLookup<A, C> {
|
|||
fallbackProviders.add(fallbackProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<A> apiClass() {
|
||||
return apiClass;
|
||||
|
|
|
@ -43,13 +43,15 @@ public class ItemApiLookupImpl<A, C> implements ItemApiLookup<A, C> {
|
|||
return (ItemApiLookup<A, C>) LOOKUPS.getLookup(lookupId, apiClass, contextClass);
|
||||
}
|
||||
|
||||
private final Identifier identifier;
|
||||
private final Class<A> apiClass;
|
||||
private final Class<C> contextClass;
|
||||
private final ApiProviderMap<Item, ItemApiProvider<A, C>> providerMap = ApiProviderMap.create();
|
||||
private final List<ItemApiProvider<A, C>> fallbackProviders = new CopyOnWriteArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ItemApiLookupImpl(Class<?> apiClass, Class<?> contextClass) {
|
||||
private ItemApiLookupImpl(Identifier identifier, Class<?> apiClass, Class<?> contextClass) {
|
||||
this.identifier = identifier;
|
||||
this.apiClass = (Class<A>) apiClass;
|
||||
this.contextClass = (Class<C>) contextClass;
|
||||
}
|
||||
|
@ -124,6 +126,11 @@ public class ItemApiLookupImpl<A, C> implements ItemApiLookup<A, C> {
|
|||
fallbackProviders.add(fallbackProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<A> apiClass() {
|
||||
return apiClass;
|
||||
|
|
|
@ -97,6 +97,10 @@ public class FabricApiLookupTest implements ModInitializer {
|
|||
wrongInsertable.registerFallback((world, pos, state, be, nocontext) -> null);
|
||||
}, "The registry should have prevented creation of another instance with different classes, but same id.");
|
||||
|
||||
if (!insertable2.getId().equals(new Identifier("testmod:item_insertable"))) {
|
||||
throw new AssertionError("Incorrect identifier was returned.");
|
||||
}
|
||||
|
||||
if (insertable2.apiClass() != ItemInsertable.class) {
|
||||
throw new AssertionError("Incorrect API class was returned.");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue