Skip to content

Commit

Permalink
Optimize storage of ItemStacks
Browse files Browse the repository at this point in the history
  • Loading branch information
mezz committed Aug 27, 2024
1 parent 3c6efef commit bfc890b
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ default String getUid() {
*/
default Optional<T> castIngredient(@Nullable Object ingredient) {
Class<? extends T> ingredientClass = getIngredientClass();
return Optional.ofNullable(ingredient)
.filter(ingredientClass::isInstance)
.map(ingredientClass::cast);
if (ingredientClass.isInstance(ingredient)) {
return Optional.of(ingredientClass.cast(ingredient));
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,10 @@ public <V> Optional<ITypedIngredient<V>> createTypedIngredient(IIngredientType<V

@Override
public <V> ITypedIngredient<V> normalizeTypedIngredient(ITypedIngredient<V> typedIngredient) {
ErrorUtil.checkNotNull(typedIngredient, "typedIngredient");
IIngredientType<V> type = typedIngredient.getType();
IIngredientHelper<V> ingredientHelper = getIngredientHelper(type);
V ingredient = typedIngredient.getIngredient();
V normalized = ingredientHelper.normalizeIngredient(ingredient);
return TypedIngredient.createUnvalidated(type, normalized);
return TypedIngredient.normalize(typedIngredient, ingredientHelper);
}

@SuppressWarnings("removal")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mezz.jei.library.ingredients;

import com.google.common.base.MoreObjects;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

import java.util.Optional;

public record NormalizedTypedItemStack(
Holder<Item> itemHolder,
DataComponentPatch dataComponentPatch
) implements ITypedIngredient<ItemStack> {
public static ITypedIngredient<ItemStack> create(ITypedIngredient<ItemStack> typedIngredient) {
if (typedIngredient instanceof NormalizedTypedItemStack normalizedTypedItemStack) {
return normalizedTypedItemStack;
} else if (typedIngredient instanceof TypedItemStack typedItemStack) {
return new NormalizedTypedItemStack(typedItemStack.itemHolder(), typedItemStack.dataComponentPatch());
}
ItemStack itemStack = typedIngredient.getIngredient();
return new NormalizedTypedItemStack(itemStack.getItemHolder(), itemStack.getComponentsPatch());
}

public static ITypedIngredient<ItemStack> create(ItemStack itemStack) {
return new NormalizedTypedItemStack(itemStack.getItemHolder(), itemStack.getComponentsPatch());
}

@Override
public ItemStack getIngredient() {
return new ItemStack(itemHolder, 1, dataComponentPatch);
}

@Override
public Optional<ItemStack> getItemStack() {
return Optional.of(getIngredient());
}

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

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("type", getType().getUid())
.add("ingredient", getIngredient())
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientHelper;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.world.item.ItemStack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
Expand All @@ -28,8 +30,31 @@ private static <T> void checkParameters(IIngredientType<T> ingredientType, T ing
}
}

public static <T> ITypedIngredient<T> normalize(ITypedIngredient<T> typedIngredient, IIngredientHelper<T> ingredientHelper) {
IIngredientType<T> type = typedIngredient.getType();

if (type == VanillaTypes.ITEM_STACK) {
@SuppressWarnings("unchecked")
ITypedIngredient<ItemStack> cast = (ITypedIngredient<ItemStack>) typedIngredient;
ITypedIngredient<ItemStack> normalized = NormalizedTypedItemStack.create(cast);
@SuppressWarnings("unchecked")
ITypedIngredient<T> castNormalized = (ITypedIngredient<T>) normalized;
return castNormalized;
}

T ingredient = typedIngredient.getIngredient();
T normalized = ingredientHelper.normalizeIngredient(ingredient);
return createUnvalidated(type, normalized);
}

public static <T> ITypedIngredient<T> createUnvalidated(IIngredientType<T> ingredientType, T ingredient) {
checkParameters(ingredientType, ingredient);
if (ingredientType == VanillaTypes.ITEM_STACK) {
ITypedIngredient<ItemStack> typedIngredient = TypedItemStack.create((ItemStack) ingredient);
@SuppressWarnings("unchecked")
ITypedIngredient<T> castIngredient = (ITypedIngredient<T>) typedIngredient;
return castIngredient;
}

return new TypedIngredient<>(ingredientType, ingredient);
}

Expand All @@ -54,7 +79,6 @@ public static <T> Optional<ITypedIngredient<T>> createAndFilterInvalid(
if (ingredient == null) {
return Optional.empty();
}
checkParameters(ingredientType, ingredient);

IIngredientHelper<T> ingredientHelper = ingredientManager.getIngredientHelper(ingredientType);
return createAndFilterInvalid(ingredientHelper, ingredientType, ingredient, normalize);
Expand Down Expand Up @@ -102,7 +126,7 @@ public static <T> Optional<ITypedIngredient<T>> createAndFilterInvalid(
throw new IllegalArgumentException("Crashed when checking if ingredient is valid. Ingredient Info: " + ingredientInfo, e);
}

TypedIngredient<T> typedIngredient = new TypedIngredient<>(ingredientType, ingredient);
ITypedIngredient<T> typedIngredient = createUnvalidated(ingredientType, ingredient);
return Optional.of(typedIngredient);
}

Expand All @@ -116,6 +140,7 @@ public static <T> Optional<ITypedIngredient<T>> deepCopy(IIngredientManager ingr
private final T ingredient;

private TypedIngredient(IIngredientType<T> ingredientType, T ingredient) {
checkParameters(ingredientType, ingredient);
this.ingredientType = ingredientType;
this.ingredient = ingredient;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package mezz.jei.library.ingredients;

import com.google.common.base.MoreObjects;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

import java.util.Optional;

public record TypedItemStack(
Holder<Item> itemHolder,
DataComponentPatch dataComponentPatch,
int count
) implements ITypedIngredient<ItemStack> {
public static ITypedIngredient<ItemStack> create(ItemStack ingredient) {
if (ingredient.getCount() == 1) {
return NormalizedTypedItemStack.create(ingredient);
}
return new TypedItemStack(
ingredient.getItemHolder(),
ingredient.getComponentsPatch(),
ingredient.getCount()
);
}

@Override
public ItemStack getIngredient() {
return new ItemStack(itemHolder, count, dataComponentPatch);
}

@Override
public Optional<ItemStack> getItemStack() {
return Optional.of(getIngredient());
}

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

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("type", getType().getUid())
.add("ingredient", getIngredient())
.toString();
}
}

0 comments on commit bfc890b

Please sign in to comment.