Interface ApiLookupMap<L>
- Type Parameters:
L
- The type of the lookup implementation, similar to the existingBlockApiLookup
.
- All Superinterfaces:
Iterable<L>
A a map meant to be used as the backing storage for custom
ApiLookup
instances,
to implement a custom equivalent of BlockApiLookup#get
.
Usage Example
We will be implementing the following simplified version of an API lookup interface for item stacks to illustrate how to useApiLookupMap
and ApiProviderMap
.
public interface ItemStackApiLookup<A, C> {
static <A, C> ItemStackApiLookup<A, C> get(Identifier lookupId, Class<A> apiClass, Class<C> contextClass) {
return ItemStackApiLookupImpl.get(lookupId, apiClass, contextClass);
}
// Find an API instance.
@Nullable
A find(ItemStack stack, C context);
// Expose the API for some item.
void register(ItemStackApiProvider<A, C> provider, Item item);
interface ItemStackApiProvider<A, C> {
// Return an API instance if available, or null otherwise.
@Nullable
A find(ItemStack stack, C context);
}
}
All the implementation can fit in a single class:
public class ItemStackApiLookupImpl<A, C> implements ItemStackApiLookup<A, C> {
// Management of lookup instances is handled by ApiLookupMap.
private static final ApiLookupMap<ItemStackApiLookup<?, ?>> LOOKUPS = ApiLookupMap.create(ItemStackApiLookupImpl::new);
// We have to perform an unchecked cast to convert <?, ?> back to <A, C>.
@SuppressWarnings("unchecked")
public static <A, C> ItemStackApiLookup<A, C> get(Identifier lookupId, Class<A> apiClass, Class<C> contextClass) {
// Null checks are already handled by ApiLookupMap#get.
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.
}
// We will use an ApiProviderMap to store the providers.
private final ApiProviderMap<Item, ItemStackApiProvider<A, C>> providerMap = ApiProviderMap.create();
@Nullable
public A find(ItemStack stack, C context) {
ItemStackApiProvider<A, C> provider = providerMap.get(stack.getItem());
if (provider == null) {
return null;
} else {
return provider.find(stack, context);
}
}
public void register(ItemStackApiProvider provider, Item item) {
// Let's add a few null checks just in case.
Objects.requireNonNull(provider, "ItemStackApiProvider may not be null.");
Objects.requireNonNull(item, "Item may not be null.");
// Register the provider, or warn if it is already registered
if (providerMap.putIfAbsent(item, provider) != null) {
// Emit a warning printing the item ID to help users debug more easily.
LogManager.getLogger("The name of your mod").warn("Encountered duplicate API provider registration for item " + Registry.ITEM.getId(item) + ".");
}
}
}
-
Nested Class Summary
-
Method Summary
Modifier and TypeMethodDescriptionstatic <L> ApiLookupMap<L>
create(ApiLookupMap.LookupFactory<L> lookupFactory)
Create a new instance.Retrieve the API lookup associated with an identifier.Methods inherited from interface java.lang.Iterable
forEach, iterator, spliterator
-
Method Details
-
create
Create a new instance.- Parameters:
lookupFactory
- The factory that is used to create API lookup instances.
-
getLookup
Retrieve the API lookup associated with an identifier.- Parameters:
lookupId
- The unique identifier of the lookup.apiClass
- The class of the queried API.contextClass
- The class of the queried additional context.- Returns:
- The unique lookup with the passed lookupId.
- Throws:
IllegalArgumentException
- If anotherapiClass
or anothercontextClass
was already registered with the same identifier.NullPointerException
- If one of the arguments is null.
-