Skip to content

Commit

Permalink
Optimize getting subtypes for typed ItemStacks
Browse files Browse the repository at this point in the history
  • Loading branch information
mezz committed Oct 2, 2024
1 parent 93ddf24 commit 6712a3c
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 12 deletions.
11 changes: 11 additions & 0 deletions Common/src/main/java/mezz/jei/common/util/StackHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.helpers.IStackHelper;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.ingredients.subtypes.ISubtypeManager;
import mezz.jei.api.ingredients.subtypes.UidContext;
import net.minecraft.core.registries.Registries;
Expand Down Expand Up @@ -50,6 +51,16 @@ public Object getUidForStack(ItemStack stack, UidContext context) {
return item;
}

@Override
public Object getUidForStack(ITypedIngredient<ItemStack> typedIngredient, UidContext context) {
Item item = typedIngredient.getBaseIngredient(VanillaTypes.ITEM_STACK);
Object subtypeData = subtypeManager.getSubtypeData(VanillaTypes.ITEM_STACK, typedIngredient, context);
if (subtypeData != null) {
return List.of(item, subtypeData);
}
return item;
}

@SuppressWarnings("removal")
@Override
public String getUniqueIdentifierForStack(ItemStack stack, UidContext context) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package mezz.jei.api.helpers;

import mezz.jei.api.ingredients.ITypedIngredient;
import org.jetbrains.annotations.Nullable;

import mezz.jei.api.ingredients.subtypes.UidContext;
Expand All @@ -20,6 +21,14 @@ public interface IStackHelper {
*/
Object getUidForStack(ItemStack stack, UidContext context);

/**
* Gets the unique identifier for a stack, ignoring NBT on items without subtypes, and uses the {@link ISubtypeManager}.
* If two unique identifiers are equal, then the items can be considered equivalent.
*
* @since 19.19.4
*/
Object getUidForStack(ITypedIngredient<ItemStack> stack, UidContext context);

/**
* Similar to ItemStack.areItemStacksEqual but ignores NBT on items without subtypes, and uses the {@link ISubtypeManager}
* @since 7.3.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ default Object getUid(V ingredient, UidContext context) {
return getUniqueId(ingredient, context);
}


/**
* Unique ID for use in comparing and looking up ingredients.
*
* Returns an {@link Object} so that UID creation can be optimized.
* Make sure the returned value implements {@link Object#equals} and {@link Object#hashCode}.
*
* Replaces {@link #getUniqueId(Object, UidContext)}.
*
* @since 19.19.4
*/
default Object getUid(ITypedIngredient<V> typedIngredient, UidContext context) {
return getUniqueId(typedIngredient.getIngredient(), context);
}

/**
* Unique ID for use in grouping ingredients together.
* This is used for hiding groups of ingredients together at once.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ default <V> Optional<V> getIngredient(IIngredientType<V> ingredientType) {
return ingredientType.castIngredient(getIngredient());
}

/**
* @return the ingredient's base ingredient. (For example, an ItemStack's base ingredient is the Item)
*
* @see IIngredientTypeWithSubtypes#getBase
*
* @since 19.19.4
*/
default <B> B getBaseIngredient(IIngredientTypeWithSubtypes<B, T> ingredientType) {
return ingredientType.getBase(getIngredient());
}

/**
* @return the ItemStack wrapped by this instance, only this holds an ItemStack ingredient.
* This is useful when handling a wildcard generic instance of `ITypedIngredient<?>`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.registration.ISubtypeRegistration;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -32,6 +33,15 @@ default Object getSubtypeData(ItemStack ingredient, UidContext context) {
@Nullable
<T> Object getSubtypeData(IIngredientTypeWithSubtypes<?, T> ingredientType, T ingredient, UidContext context);

/**
* Get the data from a typed ingredient that is relevant to comparing and telling subtypes apart.
* Returns null if the typed ingredient has no information used for subtypes.
*
* @since 19.19.4
*/
@Nullable
<B, T> Object getSubtypeData(IIngredientTypeWithSubtypes<B, T> ingredientType, ITypedIngredient<T> typedIngredient, UidContext context);

/**
* Get the data from an ItemStack that is relevant to comparing and telling subtypes apart.
* Returns {@link IIngredientSubtypeInterpreter#NONE} if the ItemStack has no information used for subtypes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ protected TypedItemStack getNormalized() {
return NormalizedTypedItemStack.create(itemHolder, dataComponentPatch);
}

@Override
protected Item getItem() {
return itemHolder.value();
}

@Override
public String toString() {
return "TypedItemStack{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public TypedItemStack getNormalized() {
return this;
}

@Override
protected Item getItem() {
return itemHolder.value();
}

@Override
public String toString() {
return "SimpleItemStack{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ public TypedItemStack getNormalized() {
return this;
}

@Override
protected Item getItem() {
return itemHolder.value();
}

@Override
public String toString() {
return "NormalizedTypedItemStack{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import com.google.common.cache.LoadingCache;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes;
import mezz.jei.api.ingredients.ITypedIngredient;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

import java.time.Duration;
Expand Down Expand Up @@ -53,11 +55,20 @@ public final Optional<ItemStack> getItemStack() {
return Optional.of(getIngredient());
}

@Override
public final <B> B getBaseIngredient(IIngredientTypeWithSubtypes<B, ItemStack> ingredientType) {
Item item = getItem();
Class<? extends B> ingredientBaseClass = ingredientType.getIngredientBaseClass();
return ingredientBaseClass.cast(item);
}

@Override
public final IIngredientType<ItemStack> getType() {
return VanillaTypes.ITEM_STACK;
}

protected abstract Item getItem();

protected abstract TypedItemStack getNormalized();

protected abstract ItemStack createItemStackUncached();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes;
import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter;
import org.jetbrains.annotations.Nullable;

import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Optional;

public class SubtypeInterpreters {
private final Map<Object, ISubtypeInterpreter<?>> map;
Expand Down Expand Up @@ -41,12 +41,18 @@ public <B, I> boolean addInterpreter(IIngredientTypeWithSubtypes<B, I> type, B b
return true;
}

public <B, I> Optional<ISubtypeInterpreter<I>> get(IIngredientTypeWithSubtypes<B, I> type, I ingredient) {
@Nullable
public <B, I> ISubtypeInterpreter<I> get(IIngredientTypeWithSubtypes<B, I> type, I ingredient) {
B base = type.getBase(ingredient);
ISubtypeInterpreter<?> interpreter = map.get(base);
return getFromBase(type, base);
}

@Nullable
public <B, I> ISubtypeInterpreter<I> getFromBase(@SuppressWarnings("unused") IIngredientTypeWithSubtypes<B, I> type, B ingredientBase) {
ISubtypeInterpreter<?> interpreter = map.get(ingredientBase);
@SuppressWarnings("unchecked")
ISubtypeInterpreter<I> cast = (ISubtypeInterpreter<I>) interpreter;
return Optional.ofNullable(cast);
return cast;
}

public <B, T> boolean contains(IIngredientTypeWithSubtypes<B, T> type, T ingredient) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package mezz.jei.library.ingredients.subtypes;

import mezz.jei.api.ingredients.IIngredientTypeWithSubtypes;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter;
import mezz.jei.api.ingredients.subtypes.ISubtypeManager;
import mezz.jei.api.ingredients.subtypes.UidContext;
import mezz.jei.common.util.ErrorUtil;
Expand All @@ -20,9 +22,26 @@ public <T> Object getSubtypeData(IIngredientTypeWithSubtypes<?, T> ingredientTyp
ErrorUtil.checkNotNull(ingredient, "ingredient");
ErrorUtil.checkNotNull(context, "type");

return interpreters.get(ingredientType, ingredient)
.map(subtypeInterpreter -> subtypeInterpreter.getSubtypeData(ingredient, context))
.orElse(null);
ISubtypeInterpreter<T> interpreter = interpreters.get(ingredientType, ingredient);
if (interpreter == null) {
return null;
}
return interpreter.getSubtypeData(ingredient, context);
}

@Override
public @Nullable <B, T> Object getSubtypeData(IIngredientTypeWithSubtypes<B, T> ingredientType, ITypedIngredient<T> typedIngredient, UidContext context) {
ErrorUtil.checkNotNull(ingredientType, "ingredientType");
ErrorUtil.checkNotNull(typedIngredient, "typedIngredient");
ErrorUtil.checkNotNull(context, "type");

B ingredientBase = typedIngredient.getBaseIngredient(ingredientType);
ISubtypeInterpreter<T> interpreter = interpreters.getFromBase(ingredientType, ingredientBase);
if (interpreter == null) {
return null;
}
T ingredient = typedIngredient.getIngredient();
return interpreter.getSubtypeData(ingredient, context);
}

@SuppressWarnings({"removal", "deprecation"})
Expand All @@ -32,9 +51,11 @@ public <T> String getSubtypeInfo(IIngredientTypeWithSubtypes<?, T> ingredientTyp
ErrorUtil.checkNotNull(ingredient, "ingredient");
ErrorUtil.checkNotNull(context, "context");

return interpreters.get(ingredientType, ingredient)
.map(subtypeInterpreter -> subtypeInterpreter.getLegacyStringSubtypeInfo(ingredient, context))
.orElse(mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter.NONE);
ISubtypeInterpreter<T> interpreter = interpreters.get(ingredientType, ingredient);
if (interpreter == null) {
return mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter.NONE;
}
return interpreter.getLegacyStringSubtypeInfo(ingredient, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import mezz.jei.api.helpers.IColorHelper;
import mezz.jei.api.ingredients.IIngredientHelper;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.ingredients.subtypes.UidContext;
import mezz.jei.common.Internal;
import mezz.jei.common.config.IClientConfig;
Expand Down Expand Up @@ -74,6 +75,13 @@ public Object getUid(ItemStack ingredient, UidContext context) {
return stackHelper.getUidForStack(ingredient, context);
}

@Override
public Object getUid(ITypedIngredient<ItemStack> typedIngredient, UidContext context) {
ErrorUtil.checkNotNull(typedIngredient, "typedIngredient");
ErrorUtil.checkNotNull(context, "type");
return stackHelper.getUidForStack(typedIngredient, context);
}

@Override
public Object getGroupingUid(ItemStack ingredient) {
return ingredient.getItem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,6 @@ public void compact() {
private <T> Object getIngredientUid(ITypedIngredient<T> typedIngredient) {
IIngredientType<T> type = typedIngredient.getType();
IIngredientHelper<T> ingredientHelper = ingredientManager.getIngredientHelper(type);
return ingredientHelper.getUid(typedIngredient.getIngredient(), UidContext.Recipe);
return ingredientHelper.getUid(typedIngredient, UidContext.Recipe);
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ modrinthId=u6dRKJwZ
jUnitVersion=5.8.2

# Version
specificationVersion=19.19.3
specificationVersion=19.19.4

0 comments on commit 6712a3c

Please sign in to comment.