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 injectDeduplicationPass(Stream 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); - } - } -} -*/