Interface ApiLookupMap<L>

Type Parameters:
L - The type of the lookup implementation, similar to the existing BlockApiLookup.
All Superinterfaces:
Iterable<L>

@NonExtendable public interface ApiLookupMap<L> extends 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 use ApiLookupMap 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) + ".");
         }
     }
 }
 
  • Method Details

    • create

      static <L> ApiLookupMap<L> create(ApiLookupMap.LookupFactory<L> lookupFactory)
      Create a new instance.
      Parameters:
      lookupFactory - The factory that is used to create API lookup instances.
    • getLookup

      L getLookup(net.minecraft.util.Identifier lookupId, Class<?> apiClass, Class<?> contextClass)
      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 another apiClass or another contextClass was already registered with the same identifier.
      NullPointerException - If one of the arguments is null.