diff --git a/src/main/java/com/buuz135/replication/Replication.java b/src/main/java/com/buuz135/replication/Replication.java index 0ab654a..387f2f1 100644 --- a/src/main/java/com/buuz135/replication/Replication.java +++ b/src/main/java/com/buuz135/replication/Replication.java @@ -6,6 +6,7 @@ import com.buuz135.replication.block.*; import com.buuz135.replication.block.tile.MatterPipeBlockEntity; import com.buuz135.replication.block.tile.ReplicationMachine; +import com.buuz135.replication.calculation.ItemVariants; import com.buuz135.replication.calculation.ReplicationCalculation; import com.buuz135.replication.client.ClientEvents; import com.buuz135.replication.container.ReplicationTerminalContainer; @@ -210,6 +211,7 @@ protected void initModules() { } }).subscribe(); + ItemVariants.init(); ReplicationCalculation.init(); if (ModList.get().isLoaded("guideme")) { diff --git a/src/main/java/com/buuz135/replication/api/CollectItemVariantsEvent.java b/src/main/java/com/buuz135/replication/api/CollectItemVariantsEvent.java new file mode 100644 index 0000000..9cbe2f0 --- /dev/null +++ b/src/main/java/com/buuz135/replication/api/CollectItemVariantsEvent.java @@ -0,0 +1,19 @@ +package com.buuz135.replication.api; + +import net.minecraft.world.item.Item; +import net.neoforged.bus.api.Event; +import net.neoforged.fml.event.IModBusEvent; + +import java.util.function.BiConsumer; + +public class CollectItemVariantsEvent extends Event implements IModBusEvent { + private final BiConsumer consumer; + + public CollectItemVariantsEvent(BiConsumer consumer) { + this.consumer = consumer; + } + + public void add(Item item, IItemVariantProvider provider) { + consumer.accept(item, provider); + } +} diff --git a/src/main/java/com/buuz135/replication/api/IItemVariantProvider.java b/src/main/java/com/buuz135/replication/api/IItemVariantProvider.java new file mode 100644 index 0000000..e9f6ec1 --- /dev/null +++ b/src/main/java/com/buuz135/replication/api/IItemVariantProvider.java @@ -0,0 +1,17 @@ +package com.buuz135.replication.api; + +import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistryAccess; +import net.minecraft.world.item.ItemStack; + +import java.util.Set; + +public interface IItemVariantProvider { + // Get name of variant + String getVariantKey(ItemStack stack); + + // Do not mutate stack. + ItemStack normalize(ItemStack stack); + + Set getVariants(HolderLookup.Provider registries); +} diff --git a/src/main/java/com/buuz135/replication/block/tile/IdentificationChamberBlockEntity.java b/src/main/java/com/buuz135/replication/block/tile/IdentificationChamberBlockEntity.java index f0f4356..92e52b1 100644 --- a/src/main/java/com/buuz135/replication/block/tile/IdentificationChamberBlockEntity.java +++ b/src/main/java/com/buuz135/replication/block/tile/IdentificationChamberBlockEntity.java @@ -5,6 +5,7 @@ import com.buuz135.replication.ReplicationRegistry; import com.buuz135.replication.api.pattern.IMatterPatternHolder; import com.buuz135.replication.api.pattern.IMatterPatternModifier; +import com.buuz135.replication.calculation.ItemVariants; import com.buuz135.replication.calculation.ReplicationCalculation; import com.buuz135.replication.client.gui.addons.IdentificationChamberAddon; import com.buuz135.replication.util.InvUtil; @@ -28,7 +29,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; - public class IdentificationChamberBlockEntity extends ReplicationMachine{ @@ -130,7 +130,7 @@ private IMatterPatternModifier.ModifierAction executeProgress(IMatterPattern this.getInput().getStackInSlot(0).shrink(1); syncObject(this.input); } else { - returnedValue = patternModifier.addPattern(this.level, stack, input.getItem().getDefaultInstance(), (float) ReplicationConfig.IdentificationChamber.IDENTIFICATION_PROGRESS); + returnedValue = patternModifier.addPattern(this.level, stack, ItemVariants.normalize(input).stack(), (float) ReplicationConfig.IdentificationChamber.IDENTIFICATION_PROGRESS); } if (returnedValue.getPattern() != null && returnedValue.getPattern().getCompletion() >= 1) { this.getInput().getStackInSlot(0).shrink(1); diff --git a/src/main/java/com/buuz135/replication/block/tile/ReplicatorBlockEntity.java b/src/main/java/com/buuz135/replication/block/tile/ReplicatorBlockEntity.java index fdaa00a..86c55bf 100644 --- a/src/main/java/com/buuz135/replication/block/tile/ReplicatorBlockEntity.java +++ b/src/main/java/com/buuz135/replication/block/tile/ReplicatorBlockEntity.java @@ -5,6 +5,7 @@ import com.buuz135.replication.api.task.IReplicationTask; import com.buuz135.replication.api.task.ReplicationTask; import com.buuz135.replication.block.ReplicatorBlock; +import com.buuz135.replication.calculation.ItemVariants; import com.buuz135.replication.calculation.ReplicationCalculation; import com.buuz135.replication.client.gui.addons.ReplicatorCraftingAddon; import com.buuz135.replication.client.gui.addons.ReplicatorMotorAddon; @@ -106,7 +107,7 @@ public ReplicatorBlockEntity(BasicTileBlock base, BlockEn @Override public void setFilter(int slot, ItemStack stack) { - super.setFilter(slot, stack.getItem().getDefaultInstance()); + super.setFilter(slot, ItemVariants.normalize(stack).stack()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/buuz135/replication/calculation/ItemVariant.java b/src/main/java/com/buuz135/replication/calculation/ItemVariant.java new file mode 100644 index 0000000..9558439 --- /dev/null +++ b/src/main/java/com/buuz135/replication/calculation/ItemVariant.java @@ -0,0 +1,17 @@ +package com.buuz135.replication.calculation; + +import net.minecraft.world.item.ItemStack; + +// Needed to ensure hashCode is valid for storing in maps. +public record ItemVariant(ItemStack stack) { + @Override + public int hashCode() { + return ItemStack.hashItemAndComponents(stack); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ItemVariant(ItemStack otherStack))) return false; + return ItemStack.isSameItemSameComponents(stack, otherStack); + } +} diff --git a/src/main/java/com/buuz135/replication/calculation/ItemVariants.java b/src/main/java/com/buuz135/replication/calculation/ItemVariants.java new file mode 100644 index 0000000..7b26a5a --- /dev/null +++ b/src/main/java/com/buuz135/replication/calculation/ItemVariants.java @@ -0,0 +1,53 @@ +package com.buuz135.replication.calculation; + +import com.buuz135.replication.api.CollectItemVariantsEvent; +import com.buuz135.replication.api.IItemVariantProvider; +import com.hrznstudio.titanium.event.handler.EventManager; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.neoforged.fml.ModLoader; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +// TODO: Should cache results. +public class ItemVariants { + private static final Map providers = new HashMap<>(); + + public static void init() { + EventManager.mod(FMLCommonSetupEvent.class).process(commonSetupEvent -> { + var event = new CollectItemVariantsEvent(providers::put); + ModLoader.postEvent(event); + }).subscribe(); + } + + public static String getName(ItemVariant variant) { + if (providers.containsKey(variant.stack().getItem())) { + return BuiltInRegistries.ITEM.getKey(variant.stack().getItem()).toString() + + providers.get(variant.stack().getItem()).getVariantKey(variant.stack()); + } + + return BuiltInRegistries.ITEM.getKey(variant.stack().getItem()).toString(); + } + + public static ItemVariant normalize(ItemStack stack) { + if (providers.containsKey(stack.getItem())) { + return new ItemVariant(providers.get(stack.getItem()).normalize(stack)); + } + + return new ItemVariant(stack.getItem().getDefaultInstance()); + } + + public static Set getVariants(Item item, HolderLookup.Provider registries) { + if (providers.containsKey(item)) { + return providers.get(item).getVariants(registries).stream().map(ItemVariant::new).collect(Collectors.toSet()); + } + + return Set.of(new ItemVariant(item.getDefaultInstance())); + } +} diff --git a/src/main/java/com/buuz135/replication/calculation/ReplicationCalculation.java b/src/main/java/com/buuz135/replication/calculation/ReplicationCalculation.java index 1fde52d..8d47051 100644 --- a/src/main/java/com/buuz135/replication/calculation/ReplicationCalculation.java +++ b/src/main/java/com/buuz135/replication/calculation/ReplicationCalculation.java @@ -34,9 +34,9 @@ public class ReplicationCalculation { public static final Logger CALCULATOR_LOG = LogManager.getLogger("Replication Calculator"); - public static HashMap SORTED_CALCULATION_REFERENCE = new HashMap(); + public static HashMap SORTED_CALCULATION_REFERENCE = new HashMap(); public static Set> DEFAULT_MATTER_RECIPE = new HashSet<>(); - public static HashMap DEFAULT_MATTER_COMPOUND = new HashMap(); + public static HashMap DEFAULT_MATTER_COMPOUND = new HashMap(); private static CompoundTag cachedSyncTag = new CompoundTag(); public static MatterCalculationStatus STATUS = MatterCalculationStatus.NOT_CALCULATED; @@ -57,10 +57,6 @@ public static void init() { private static HashMap INGREDIENT_CACHE = new HashMap<>(); - public static String getNameFromStack(ItemStack stack) { - return BuiltInRegistries.ITEM.getKey(stack.getItem()).toString(); - } - public static void organizeRecipes(RecipeManager recipeManager, RegistryAccess registryAccess) { STATUS = MatterCalculationStatus.NOT_CALCULATED; CALCULATOR_LOG.info("Sorting recipes"); @@ -73,15 +69,17 @@ public static void organizeRecipes(RecipeManager recipeManager, RegistryAccess r //SORTING RECIPES - SORTED_CALCULATION_REFERENCE = new HashMap(); + SORTED_CALCULATION_REFERENCE = new HashMap(); time = System.currentTimeMillis(); for (RecipeHolder craftingRecipe : recipeManager.getAllRecipesFor(RecipeType.CRAFTING)) { var result = craftingRecipe.value().getResultItem(registryAccess); - SORTED_CALCULATION_REFERENCE.computeIfAbsent(result.getItem(), string -> new CalculationReference(result, new HashSet<>())).getReferences().add(new RecipeReference(craftingRecipe.id(), result, new ArrayList<>(craftingRecipe.value().getIngredients()))); + var resultVariant = ItemVariants.normalize(result); + SORTED_CALCULATION_REFERENCE.computeIfAbsent(resultVariant, string -> new CalculationReference(resultVariant, new HashSet<>())).getReferences().add(new RecipeReference(craftingRecipe.id(), result, new ArrayList<>(craftingRecipe.value().getIngredients()))); } for (RecipeHolder craftingRecipe : recipeManager.getAllRecipesFor(RecipeType.SMELTING)) { var result = craftingRecipe.value().getResultItem(registryAccess); - SORTED_CALCULATION_REFERENCE.computeIfAbsent(result.getItem(), string -> new CalculationReference(result, new HashSet<>())).getReferences().add(new RecipeReference(craftingRecipe.id(), result, new ArrayList<>(craftingRecipe.value().getIngredients()))); + var resultVariant = ItemVariants.normalize(result); + SORTED_CALCULATION_REFERENCE.computeIfAbsent(resultVariant, string -> new CalculationReference(resultVariant, new HashSet<>())).getReferences().add(new RecipeReference(craftingRecipe.id(), result, new ArrayList<>(craftingRecipe.value().getIngredients()))); } CALCULATOR_LOG.info("Sorted " + SORTED_CALCULATION_REFERENCE.size() + " Recipes in " + (System.currentTimeMillis() - time) + "ms"); } @@ -99,7 +97,7 @@ public static void calculateRecipes(RegistryAccess registryAccess) { } compound.add(matterValue); } - DEFAULT_MATTER_COMPOUND.put(item.getItem(), compound); + DEFAULT_MATTER_COMPOUND.put(ItemVariants.normalize(item), compound); } } CALCULATOR_LOG.info("Loaded default values in " + (System.currentTimeMillis() - time) + "ms"); @@ -128,23 +126,27 @@ public static void calculateRecipes(RegistryAccess registryAccess) { CALCULATOR_LOG.info("Progress " + checkedAmount + " of " + totalAmount + " items"); timeTracker = System.currentTimeMillis(); } - try { - var stack = item.getDefaultInstance(); - if (stack.isEmpty()) continue; - //if (InvUtil.hasExtraComponents(stack)) continue; - var rl = getNameFromStack(stack); - if (!DEFAULT_MATTER_COMPOUND.containsKey(stack.getItem()) && !SORTED_CALCULATION_REFERENCE.containsKey(stack.getItem())) { - continue; - } - var compound = getMatterCompound(stack, 0, new HashSet<>(), new HashSet<>(), false); - // CALCULATOR_LOG.info("---------------------------------------------"); - if (compound != null && !compound.getValues().isEmpty()) { - if (false) CALCULATOR_LOG.info(item + " -> " + compound.toString()); - tempTag.put(rl, compound.serializeNBT(registryAccess)); - ++amount; + + Set variants = ItemVariants.getVariants(item, registryAccess); + for (ItemVariant variant : variants) { + try { + var stack = variant.stack(); + if (stack.isEmpty()) continue; + //if (InvUtil.hasExtraComponents(stack)) continue; + if (!DEFAULT_MATTER_COMPOUND.containsKey(variant) && !SORTED_CALCULATION_REFERENCE.containsKey(variant)) { + continue; + } + var compound = getMatterCompound(variant, 0, new HashSet<>(), new HashSet<>(), false); + // CALCULATOR_LOG.info("---------------------------------------------"); + if (compound != null && !compound.getValues().isEmpty()) { + if (false) CALCULATOR_LOG.info(item + " -> " + compound.toString()); + tempTag.put(ItemVariants.getName(variant), compound.serializeNBT(registryAccess)); + ++amount; + } + } catch (Exception e) { + // TODO: Could we add more handy information? + CALCULATOR_LOG.info("Failed to calculate a variant of " + item, e); } - } catch (Exception e) { - CALCULATOR_LOG.info("Failed to calculate " + item, e); } } CALCULATOR_LOG.info("Resolved " + amount + " values in " + (System.currentTimeMillis() - time) + "ms"); @@ -162,21 +164,21 @@ public static void calculateRecipes(RegistryAccess registryAccess) { @Nullable public static MatterCompound getMatterCompound(ItemStack stack) { - return getMatterCompound(stack, 0, new HashSet<>(), new HashSet<>(), false); + return getMatterCompound(ItemVariants.normalize(stack), 0, new HashSet<>(), new HashSet<>(), false); } - private static MatterCompound getMatterCompound(ItemStack item, int depth, Set visitedRecipes, Set visitedCalculations, boolean printDebug) { + private static MatterCompound getMatterCompound(ItemVariant variant, int depth, Set visitedRecipes, Set visitedCalculations, boolean printDebug) { MatterCompound result = null; //GET FROM DEFAULT VALUES - result = getMatterCompound(item, depth, visitedRecipes, visitedCalculations, printDebug, result); + result = getMatterCompound(variant, depth, visitedRecipes, visitedCalculations, printDebug, result); return result; } - private static MatterCompound getMatterCompound(ItemStack item, int depth, Set visitedRecipes, Set visitedCalculations, boolean printDebug, MatterCompound result) { - var defaultValue = getDefaultValue(item); + private static MatterCompound getMatterCompound(ItemVariant variant, int depth, Set visitedRecipes, Set visitedCalculations, boolean printDebug, MatterCompound result) { + var defaultValue = getDefaultValue(variant); if (defaultValue != null) { if (printDebug) - CALCULATOR_LOG.info(repeatChar(' ', depth + 1) + "\\" + repeatChar('_', depth + 1) + "Found default value for " + item.toString()); + CALCULATOR_LOG.info(repeatChar(' ', depth + 1) + "\\" + repeatChar('_', depth + 1) + "Found default value for " + variant.stack().toString()); if (result == null) { result = defaultValue; } else { @@ -185,11 +187,11 @@ private static MatterCompound getMatterCompound(ItemStack item, int depth, Set references; - private final ItemStack stack; + private final ItemVariant variant; private final Item name; private boolean resolved = false; private MatterCompound cached; - public CalculationReference(ItemStack stack, Set references) { + public CalculationReference(ItemVariant variant, Set references) { this.references = references; - this.stack = stack; - this.name = stack.getItem(); + this.variant = variant; + this.name = variant.stack().getItem(); } public MatterCompound resolve(int depth, Set visitedRecipes, Set visitedCalculations, boolean printDebug) { @@ -287,14 +289,14 @@ public MatterCompound resolve(int depth, Set visitedRecipes, Set v } visitedCalculations.add(name); if (references.size() == 0) { - CALCULATOR_LOG.info(repeatChar(' ', depth + 1) + "\\" + repeatChar('_', depth + 1) + "FOUND NO RECIPES FOR " + stack.toString()); + CALCULATOR_LOG.info(repeatChar(' ', depth + 1) + "\\" + repeatChar('_', depth + 1) + "FOUND NO RECIPES FOR " + variant.stack().toString()); } if (resolved) { if (printDebug) CALCULATOR_LOG.info(repeatChar(' ', depth + 1) + "\\" + repeatChar('_', depth + 1) + "RESOLVED_" + (cached == null ? null : cached.toString())); return cached; } - MatterCompound result = getDefaultValue(stack); + MatterCompound result = getDefaultValue(variant); if (result != null) { resolved = true; this.cached = result; diff --git a/src/main/java/com/buuz135/replication/calculation/client/ClientReplicationCalculation.java b/src/main/java/com/buuz135/replication/calculation/client/ClientReplicationCalculation.java index c215107..10bfd8f 100644 --- a/src/main/java/com/buuz135/replication/calculation/client/ClientReplicationCalculation.java +++ b/src/main/java/com/buuz135/replication/calculation/client/ClientReplicationCalculation.java @@ -1,5 +1,6 @@ package com.buuz135.replication.calculation.client; +import com.buuz135.replication.calculation.ItemVariants; import com.buuz135.replication.calculation.MatterCompound; import com.buuz135.replication.calculation.ReplicationCalculation; import net.minecraft.core.HolderLookup; @@ -16,8 +17,9 @@ public class ClientReplicationCalculation { @Nullable public static MatterCompound getMatterCompound(ItemStack stack) { - if (DEFAULT_MATTER_COMPOUND.containsKey(ReplicationCalculation.getNameFromStack(stack))){ - return DEFAULT_MATTER_COMPOUND.get(ReplicationCalculation.getNameFromStack(stack)); + String name = ItemVariants.getName(ItemVariants.normalize(stack)); + if (DEFAULT_MATTER_COMPOUND.containsKey(name)) { + return DEFAULT_MATTER_COMPOUND.get(name); } return null; } diff --git a/src/main/java/com/buuz135/replication/item/MemoryChipItem.java b/src/main/java/com/buuz135/replication/item/MemoryChipItem.java index 4ffccdd..ff554fe 100644 --- a/src/main/java/com/buuz135/replication/item/MemoryChipItem.java +++ b/src/main/java/com/buuz135/replication/item/MemoryChipItem.java @@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; @@ -106,7 +107,7 @@ public void addTooltipDetails(@Nullable BasicItem.Key key, ItemStack stack, List for (MatterPattern pattern : patterns) { if (pattern.getStack().isEmpty()) continue; var component = Component.literal(" - ").setStyle(Style.EMPTY.withColor(Mth.color(114/255f, 229/255f, 103/255f))) - .append(Component.translatable(pattern.getStack().getDescriptionId()).withStyle(pattern.getCompletion() >= 1 ? ChatFormatting.GOLD : ChatFormatting.WHITE)); + .append(MutableComponent.create(pattern.getStack().getDisplayName().getContents()).withStyle(pattern.getCompletion() >= 1 ? ChatFormatting.GOLD : ChatFormatting.WHITE)); if (pattern.getCompletion() < 1){ component.append(Component.literal(" " + new DecimalFormat("##.## %").format(pattern.getCompletion())).withStyle(Style.EMPTY.withColor(Mth.color(242/255f, 82/255f, 82/255f)))); }