diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/faster_ingredients/IngredientMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/faster_ingredients/IngredientMixin.java
deleted file mode 100644
index 0408ab4c..00000000
--- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/faster_ingredients/IngredientMixin.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package org.embeddedt.modernfix.neoforge.mixin.perf.faster_ingredients;
-
-/* FIXME: Ingredient rework
-import it.unimi.dsi.fastutil.ints.IntArrayList;
-import it.unimi.dsi.fastutil.ints.IntComparators;
-import it.unimi.dsi.fastutil.ints.IntList;
-import net.minecraft.core.registries.BuiltInRegistries;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemStackLinkedSet;
-import net.minecraft.world.item.crafting.Ingredient;
-import net.neoforged.neoforge.common.crafting.ICustomIngredient;
-import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker;
-import org.embeddedt.modernfix.neoforge.recipe.ExtendedIngredient;
-import org.embeddedt.modernfix.neoforge.recipe.IngredientItemStacksSoftReference;
-import org.jetbrains.annotations.Nullable;
-import org.spongepowered.asm.mixin.Final;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Overwrite;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.Unique;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-
-import java.util.ArrayList;
-import java.util.stream.Collectors;
-
-@Mixin(value = Ingredient.class, priority = 700)
-public abstract class IngredientMixin implements ExtendedIngredient {
- @Shadow @Final
- private Ingredient.Value[] values;
-
- @Shadow private @Nullable IntList stackingIds;
-
- @Shadow @Nullable private ItemStack[] itemStacks;
-
- @Shadow public abstract boolean isCustom();
-
- @Shadow private ICustomIngredient customIngredient;
-
- @Unique
- private boolean isVanilla() {
- return !this.isCustom();
- }
-
- private volatile IngredientItemStacksSoftReference mfix$cachedItemStacks;
-
- /**
- * Minecraft's server resource loading process has a design flaw in that tags are loaded, recipes are loaded,
- * then tags are bound to the server registries. This results in recipe modification mods like KubeJS/CraftTweaker
- * not being able to use Ingredient.test reliably as the TagValue will not find any contents for the given tag.
- * To work around this issue these mods track tag context themselves and then patch TagValue.getItems to use it
- * during the resource reload process. We often bypass Value.getItems, so we must disable that bypass
- * whenever a server reload is in progress.
- *
- * An alternative fix would be to bind tags ourselves when the recipe manager reload begins, before control is
- * handed to these mods. However, it's unclear if there would be any negative side effects from binding tags early
- * like this. Moreover, this fix would only work if the mod-provided patches to getItems read exactly what the
- * registry would normally contain, rather than a modified version.
- *
- * Note: this is a separate problem from the issue where clients may receive recipes before tags in 1.21.
- *
- private boolean mfix$areTagsAvailable() {
- return !MinecraftServerReloadTracker.isReloadActive();
- }
-
- /**
- * @author embeddedt
- * @reason tag ingredients can be tested without iterating over all items
- *
- @Inject(method = "test(Lnet/minecraft/world/item/ItemStack;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true)
- private void modernfix$fasterTagIngredientTest(ItemStack stack, CallbackInfoReturnable cir) {
- if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
- cir.setReturnValue(stack.getItemHolder().is(tagValue.tag()));
- }
- }
-
- /**
- * @author embeddedt
- * @reason exploding the stack list is unnecessary
- *
- @Inject(method = "hasNoItems", at = @At("HEAD"), cancellable = true, remap = false)
- public void hasNoItems(CallbackInfoReturnable cir) {
- if (this.isVanilla()) {
- cir.setReturnValue(!this.containsItems());
- }
- }
-
- @Unique
- private boolean isEmptyTagStack(ItemStack item) {
- return item.getItem() == net.minecraft.world.item.Items.BARRIER && item.getHoverName() instanceof net.minecraft.network.chat.MutableComponent hoverName && hoverName.getString().startsWith("Empty Tag: ");
- }
-
- @Unique
- private boolean containsItems() {
- for (Ingredient.Value value : this.values) {
- if (value instanceof Ingredient.ItemValue) {
- return true;
- } else if (value instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
- var holderSetOpt = BuiltInRegistries.ITEM.getTag(tagValue.tag());
- if (holderSetOpt.isPresent() && holderSetOpt.get().size() > 0) {
- return true;
- }
- } else {
- var items = value.getItems();
- if (items.isEmpty() || isEmptyTagStack(items.iterator().next())) {
- // Doesn't have items
- continue;
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * @author embeddedt
- * @reason tag ingredients can be converted to stacking IDs without expanding into stacks, since stacking only
- * goes by item ID
- *
- @Inject(method = "getStackingIds", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true)
- private void modernfix$fasterTagIngredientStacking(CallbackInfoReturnable cir) {
- if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
- var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag());
- if (!tag.isPresent() || tag.get().size() == 0) {
- return;
- }
- var list = new IntArrayList(tag.get().stream().mapToInt(h -> BuiltInRegistries.ITEM.getId(h.value())).toArray());
- list.sort(IntComparators.NATURAL_COMPARATOR);
- this.stackingIds = list;
- cir.setReturnValue(list);
- }
- }
-
- /**
- * @author embeddedt
- * @reason Change caching of item stacks to use a soft reference, which allows the GC to evict the array under
- * memory pressure/when it hasn't been used.
- *
- @Overwrite
- public ItemStack[] getItems() {
- // For compatibility if mods explicitly force a set of item stacks to be used
- if (this.itemStacks != null) {
- return this.itemStacks;
- }
- if (this.customIngredient != null) {
- // We probably have to cache this as mods won't make it fast if they expect Neo to cache it
- this.itemStacks = this.customIngredient.getItems().collect(Collectors.toCollection(ItemStackLinkedSet::createTypeAndComponentsSet)).toArray(ItemStack[]::new);
- return this.itemStacks;
- }
- var cache = this.mfix$cachedItemStacks;
- if (cache != null) {
- var stacks = cache.get();
- if (stacks != null) {
- return stacks;
- }
- }
- ItemStack[] result = computeItemsArray();
- this.mfix$cachedItemStacks = new IngredientItemStacksSoftReference((Ingredient)(Object)this, result);
- return result;
- }
-
- private ItemStack[] computeItemsArray() {
- // Fast path for case with one item
- if (this.values.length == 1) {
- if (this.values[0] instanceof Ingredient.ItemValue itemValue) {
- return new ItemStack[] { itemValue.item() };
- } else if (this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
- var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag());
- if (tag.isPresent() && tag.get().size() > 0) {
- var holderSet = tag.get();
- ItemStack[] result = new ItemStack[holderSet.size()];
- for (int i = 0; i < result.length; i++) {
- result[i] = new ItemStack(holderSet.get(i));
- }
- return result;
- }
- }
- }
- ArrayList itemList = new ArrayList<>(2);
- for (var value : this.values) {
- var collection = value.getItems();
- itemList.ensureCapacity(collection.size() + itemList.size());
- for (var item : collection) {
- itemList.add(item);
- }
- }
- return itemList.toArray(ItemStack[]::new);
- }
-
- @Override
- public void mfix$clearReference() {
- this.mfix$cachedItemStacks = null;
- }
-}
-*/
\ No newline at end of file
diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java
deleted file mode 100644
index 18e71b5d..00000000
--- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.embeddedt.modernfix.neoforge.mixin.perf.ingredient_item_deduplication;
-
-/* FIXME: Ingredient rework
-import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.crafting.Ingredient;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-
-@Mixin(Ingredient.ItemValue.class)
-public class IngredientItemValueMixin {
- /**
- * @author embeddedt
- * @reason Defensively copy the item so that the deduplication is not visible to most mods (unless they introspect
- * the item held within this object directly). This is necessary since some mods edit the returned stack.
- /
- @ModifyExpressionValue(method = "getItems", at = @At(value = "FIELD", target = "Lnet/minecraft/world/item/crafting/Ingredient$ItemValue;item:Lnet/minecraft/world/item/ItemStack;"))
- private ItemStack mfix$defensiveCopy(ItemStack original) {
- return original.copy();
- }
-}
-*/
diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientMixin.java
deleted file mode 100644
index 82ffd056..00000000
--- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/ingredient_item_deduplication/IngredientMixin.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.embeddedt.modernfix.neoforge.mixin.perf.ingredient_item_deduplication;
-
-/* FIXME: Ingredient rework
-import net.minecraft.world.item.crafting.Ingredient;
-import org.embeddedt.modernfix.neoforge.recipe.IngredientValueDeduplicator;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.ModifyVariable;
-
-import java.util.stream.Stream;
-
-@Mixin(Ingredient.class)
-public class IngredientMixin {
- @ModifyVariable(method = "(Ljava/util/stream/Stream;)V", at = @At("HEAD"), argsOnly = true, ordinal = 0)
- private static Stream extends Ingredient.Value> injectDeduplicationPass(Stream extends Ingredient.Value> stream) {
- return stream.map(IngredientValueDeduplicator::deduplicate);
- }
-}
-*/
\ No newline at end of file
diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/ConnectionMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/ConnectionMixin.java
deleted file mode 100644
index d4afdd55..00000000
--- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/ConnectionMixin.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.embeddedt.modernfix.neoforge.mixin.perf.smart_ingredient_sync;
-
-import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
-import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
-import net.minecraft.network.Connection;
-import net.minecraft.network.ConnectionProtocol;
-import net.minecraft.network.PacketSendListener;
-import net.minecraft.network.protocol.Packet;
-import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
-import net.neoforged.neoforge.network.registration.NetworkRegistry;
-import org.embeddedt.modernfix.neoforge.packet.SmartIngredientSyncPayload;
-import org.spongepowered.asm.mixin.Mixin;
-
-@Mixin(Connection.class)
-public class ConnectionMixin {
- /**
- * @author embeddedt
- * @reason Provide context to the ingredient serializer about whether the enhanced sync protocol is supported.
- */
- @WrapMethod(method = "doSendPacket")
- private void modernfix$checkClientPresence(Packet> packet, PacketSendListener sendListener, boolean flush, Operation original) {
- if (packet instanceof ClientboundUpdateRecipesPacket && NetworkRegistry.hasChannel((Connection)(Object)this, ConnectionProtocol.PLAY, SmartIngredientSyncPayload.TYPE.id())) {
- SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(true);
- try {
- original.call(packet, sendListener, flush);
- } finally {
- SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(false);
- }
- } else {
- original.call(packet, sendListener, flush);
- }
- }
-}
diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/IngredientMixin.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/IngredientMixin.java
deleted file mode 100644
index 2b7483fa..00000000
--- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/smart_ingredient_sync/IngredientMixin.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.embeddedt.modernfix.neoforge.mixin.perf.smart_ingredient_sync;
-
-/* FIXME: Ingredient rework
-import net.minecraft.core.registries.BuiltInRegistries;
-import net.minecraft.core.registries.Registries;
-import net.minecraft.network.RegistryFriendlyByteBuf;
-import net.minecraft.tags.TagKey;
-import net.minecraft.world.item.crafting.Ingredient;
-import org.embeddedt.modernfix.neoforge.packet.SmartIngredientSyncPayload;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-
-@Mixin(targets = {"net/minecraft/world/item/crafting/Ingredient$1"})
-public abstract class IngredientMixin {
-
- @Inject(method = "encode(Lnet/minecraft/network/RegistryFriendlyByteBuf;Lnet/minecraft/world/item/crafting/Ingredient;)V",
- at = @At(value = "FIELD", target = "Lnet/minecraft/world/item/ItemStack;LIST_STREAM_CODEC:Lnet/minecraft/network/codec/StreamCodec;"),
- cancellable = true)
- private void checkForVanillaTagIngredient(RegistryFriendlyByteBuf buf, Ingredient ingredient, CallbackInfo ci) {
- if (!SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.get() || ingredient.isCustom()) {
- return;
- }
- Ingredient.Value[] values = ingredient.getValues();
- if (values.length == 1 && values[0] instanceof Ingredient.TagValue tagValue) {
- var optionalHolderSet = BuiltInRegistries.ITEM.getTag(tagValue.tag());
- if (optionalHolderSet.isEmpty()) {
- // Use default serialization logic for tags that do not exist
- return;
- }
-
- // Encode this as our tag ingredient type instead of using vanilla's flattening logic.
- ci.cancel();
- buf.writeVarInt(-2);
- buf.writeResourceLocation(tagValue.tag().location());
- }
- }
-
- @Inject(method = "decode(Lnet/minecraft/network/RegistryFriendlyByteBuf;)Lnet/minecraft/world/item/crafting/Ingredient;",
- at = @At(value = "HEAD"),
- cancellable = true, remap = false)
- private void decodeSmartIngredient(RegistryFriendlyByteBuf buf, CallbackInfoReturnable cir) {
- int readerIndex = buf.readerIndex();
- var sizeId = buf.readVarInt();
- if (sizeId == -2) {
- // Probably our ingredient
- var tagKey = TagKey.create(Registries.ITEM, buf.readResourceLocation());
- cir.setReturnValue(Ingredient.of(tagKey));
- } else {
- buf.readerIndex(readerIndex);
- }
- }
-}
-*/