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 28, 2024
1 parent 43cec0a commit ed498cd
Show file tree
Hide file tree
Showing 7 changed files with 200 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
Expand Up @@ -2,10 +2,14 @@

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 mezz.jei.library.ingredients.itemStacks.NormalizedTypedItemStack;
import mezz.jei.library.ingredients.itemStacks.TypedItemStack;
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 +32,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.normalize(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 +81,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 +128,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 +142,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,34 @@
package mezz.jei.library.ingredients.itemStacks;

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.world.item.Item;
import net.minecraft.world.item.ItemStack;

import java.util.Optional;

record NormalizedTypedItem(Holder<Item> itemHolder) implements ITypedIngredient<ItemStack> {
@Override
public ItemStack getIngredient() {
return new ItemStack(itemHolder);
}

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

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

@Override
public String toString() {
return "SimpleItemStack{" +
"itemHolder=" + itemHolder +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package mezz.jei.library.ingredients.itemStacks;

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> normalize(ITypedIngredient<ItemStack> typedIngredient) {
switch (typedIngredient) {
case NormalizedTypedItemStack normalized -> {
return normalized;
}
case NormalizedTypedItem normalized -> {
return normalized;
}
case TypedItemStack typedItemStack -> {
return create(typedItemStack.itemHolder(), typedItemStack.dataComponentPatch());
}
default -> {
ItemStack itemStack = typedIngredient.getIngredient();
return create(itemStack.getItemHolder(), itemStack.getComponentsPatch());
}
}
}

public static ITypedIngredient<ItemStack> create(Holder<Item> itemHolder, DataComponentPatch dataComponentPatch) {
if (dataComponentPatch.isEmpty()) {
return new NormalizedTypedItem(itemHolder);
}
return new NormalizedTypedItemStack(itemHolder, dataComponentPatch);
}

public static ITypedIngredient<ItemStack> create(ItemStack itemStack) {
return create(
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 "NormalizedTypedItemStack{" +
"itemHolder=" + itemHolder +
", dataComponentPatch=" + dataComponentPatch +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package mezz.jei.library.ingredients.itemStacks;

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 "TypedItemStack{" +
"itemHolder=" + itemHolder +
", dataComponentPatch=" + dataComponentPatch +
", count=" + count +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package mezz.jei.library.ingredients.itemStacks;

import net.minecraft.MethodsReturnNonnullByDefault;

import javax.annotation.ParametersAreNonnullByDefault;

0 comments on commit ed498cd

Please sign in to comment.