Deduplicate ingredient item values using reference equality of components
This is necessary to work around Neo's changes to Holder.Reference equality Related: #577
This commit is contained in:
parent
2f25bb4bae
commit
1501fe29e6
|
|
@ -0,0 +1,18 @@
|
|||
package org.embeddedt.modernfix.neoforge.mixin.perf.ingredient_item_deduplication;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import net.minecraft.core.component.DataComponentMap;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.component.PatchedDataComponentMap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(PatchedDataComponentMap.class)
|
||||
public interface PatchedDataComponentMapAccessor {
|
||||
@Accessor("prototype")
|
||||
DataComponentMap mfix$getPrototype();
|
||||
@Accessor("patch")
|
||||
Reference2ObjectMap<DataComponentType<?>, Optional<?>> mfix$getPatch();
|
||||
}
|
||||
|
|
@ -2,8 +2,11 @@ package org.embeddedt.modernfix.neoforge.recipe;
|
|||
|
||||
import it.unimi.dsi.fastutil.Hash;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.ItemStackLinkedSet;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.embeddedt.modernfix.neoforge.mixin.perf.ingredient_item_deduplication.PatchedDataComponentMapAccessor;
|
||||
|
||||
/**
|
||||
* @author embeddedt (original inspiration from Uncandango's AllTheLeaks mod)
|
||||
|
|
@ -15,9 +18,54 @@ public class IngredientValueDeduplicator {
|
|||
return o == null ? 0 : ItemStackLinkedSet.TYPE_AND_TAG.hashCode(o.item());
|
||||
}
|
||||
|
||||
private boolean areComponentsSame(ItemStack a, ItemStack b) {
|
||||
// Compare using stricter logic than vanilla: require the prototype maps to be identity-equal, and require
|
||||
// the values in the patch to also be identity-equal. This works around Neo allowing Holder.Reference objects
|
||||
// made with the server & client registries to be considered equal.
|
||||
if (a.getComponents() instanceof PatchedDataComponentMapAccessor aComps && b.getComponents() instanceof PatchedDataComponentMapAccessor bComps) {
|
||||
if (aComps.mfix$getPrototype() != bComps.mfix$getPrototype()) {
|
||||
return false;
|
||||
}
|
||||
var aPatch = aComps.mfix$getPatch();
|
||||
var bPatch = bComps.mfix$getPatch();
|
||||
if (aPatch != bPatch) {
|
||||
if (aPatch.size() != bPatch.size()) {
|
||||
return false;
|
||||
}
|
||||
for (var entry : Reference2ObjectMaps.fastIterable(aPatch)) {
|
||||
var value = bPatch.get(entry.getKey());
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
if (value.isPresent() != entry.getValue().isPresent()) {
|
||||
return false;
|
||||
} else if (value.isPresent() && value.get() != entry.getValue().get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return a.getComponents() == b.getComponents();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean areStacksSame(ItemStack a, ItemStack b) {
|
||||
if (!a.is(b.getItem())) {
|
||||
return false;
|
||||
}
|
||||
if (a.isEmpty() != b.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (!areComponentsSame(a, b)) {
|
||||
return false;
|
||||
}
|
||||
return a.getCount() == b.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Ingredient.ItemValue a, Ingredient.ItemValue b) {
|
||||
return a == b || a != null && b != null && ItemStackLinkedSet.TYPE_AND_TAG.equals(a.item(), b.item()) && a.item().getCount() == b.item().getCount();
|
||||
return a == b || a != null && b != null && areStacksSame(a.item(), b.item());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user