Merge remote-tracking branch 'origin/1.20' into 1.21.1
This commit is contained in:
parent
7ac2c5fa68
commit
69f08abe8c
|
|
@ -8,6 +8,8 @@ import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.ItemStackLinkedSet;
|
import net.minecraft.world.item.ItemStackLinkedSet;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.neoforged.neoforge.common.crafting.ICustomIngredient;
|
import net.neoforged.neoforge.common.crafting.ICustomIngredient;
|
||||||
|
import org.embeddedt.modernfix.neoforge.recipe.ExtendedIngredient;
|
||||||
|
import org.embeddedt.modernfix.neoforge.recipe.IngredientItemStacksSoftReference;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
@ -22,7 +24,7 @@ import java.util.ArrayList;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Mixin(value = Ingredient.class, priority = 700)
|
@Mixin(value = Ingredient.class, priority = 700)
|
||||||
public abstract class IngredientMixin {
|
public abstract class IngredientMixin implements ExtendedIngredient {
|
||||||
@Shadow @Final
|
@Shadow @Final
|
||||||
private Ingredient.Value[] values;
|
private Ingredient.Value[] values;
|
||||||
|
|
||||||
|
|
@ -39,6 +41,8 @@ public abstract class IngredientMixin {
|
||||||
return !this.isCustom();
|
return !this.isCustom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private volatile IngredientItemStacksSoftReference mfix$cachedItemStacks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author embeddedt
|
* @author embeddedt
|
||||||
* @reason tag ingredients can be tested without iterating over all items
|
* @reason tag ingredients can be tested without iterating over all items
|
||||||
|
|
@ -109,9 +113,8 @@ public abstract class IngredientMixin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author embeddedt
|
* @author embeddedt
|
||||||
* @reason remove caching of the item stacks, it won't deduplicate anything with tags (since each Ingredient
|
* @reason Change caching of item stacks to use a soft reference, which allows the GC to evict the array under
|
||||||
* instance would make new item stacks anyway, and storing them permanently takes up a lot of memory).
|
* memory pressure/when it hasn't been used.
|
||||||
* We implement an optimized version of some functions that avoids needing to call this entirely.
|
|
||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public ItemStack[] getItems() {
|
public ItemStack[] getItems() {
|
||||||
|
|
@ -124,6 +127,19 @@ public abstract class IngredientMixin {
|
||||||
this.itemStacks = this.customIngredient.getItems().collect(Collectors.toCollection(ItemStackLinkedSet::createTypeAndComponentsSet)).toArray(ItemStack[]::new);
|
this.itemStacks = this.customIngredient.getItems().collect(Collectors.toCollection(ItemStackLinkedSet::createTypeAndComponentsSet)).toArray(ItemStack[]::new);
|
||||||
return this.itemStacks;
|
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
|
// Fast path for case with one item
|
||||||
if (this.values.length == 1) {
|
if (this.values.length == 1) {
|
||||||
if (this.values[0] instanceof Ingredient.ItemValue itemValue) {
|
if (this.values[0] instanceof Ingredient.ItemValue itemValue) {
|
||||||
|
|
@ -150,4 +166,9 @@ public abstract class IngredientMixin {
|
||||||
}
|
}
|
||||||
return itemList.toArray(ItemStack[]::new);
|
return itemList.toArray(ItemStack[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mfix$clearReference() {
|
||||||
|
this.mfix$cachedItemStacks = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.embeddedt.modernfix.neoforge.recipe;
|
||||||
|
|
||||||
|
public interface ExtendedIngredient {
|
||||||
|
void mfix$clearReference();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.embeddedt.modernfix.neoforge.recipe;
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
|
||||||
|
public class IngredientItemStacksSoftReference extends SoftReference<ItemStack[]> {
|
||||||
|
private final Ingredient ingredient;
|
||||||
|
|
||||||
|
private static final ReferenceQueue<ItemStack[]> QUEUE = new ReferenceQueue<>();
|
||||||
|
private static final Thread DISCARD_THREAD = new Thread(IngredientItemStacksSoftReference::clearReferences, "Ingredient reference clearing thread");
|
||||||
|
|
||||||
|
static {
|
||||||
|
DISCARD_THREAD.setPriority(Thread.NORM_PRIORITY + 2);
|
||||||
|
DISCARD_THREAD.setDaemon(true);
|
||||||
|
DISCARD_THREAD.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IngredientItemStacksSoftReference(Ingredient ingredient, ItemStack[] stacks) {
|
||||||
|
super(stacks, QUEUE);
|
||||||
|
this.ingredient = ingredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void clearReferences() {
|
||||||
|
while (true) {
|
||||||
|
Reference<? extends ItemStack[]> ref;
|
||||||
|
try {
|
||||||
|
ref = QUEUE.remove();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ref instanceof IngredientItemStacksSoftReference ingRef && (Object)ingRef.ingredient instanceof ExtendedIngredient extIng) {
|
||||||
|
// Null out the reference to the SoftReference object, to allow the SoftReference itself to be garbage collected.
|
||||||
|
extIng.mfix$clearReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user