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.crafting.Ingredient;
|
||||
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.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
@ -22,7 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(value = Ingredient.class, priority = 700)
|
||||
public abstract class IngredientMixin {
|
||||
public abstract class IngredientMixin implements ExtendedIngredient {
|
||||
@Shadow @Final
|
||||
private Ingredient.Value[] values;
|
||||
|
||||
|
|
@ -39,6 +41,8 @@ public abstract class IngredientMixin {
|
|||
return !this.isCustom();
|
||||
}
|
||||
|
||||
private volatile IngredientItemStacksSoftReference mfix$cachedItemStacks;
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason tag ingredients can be tested without iterating over all items
|
||||
|
|
@ -109,9 +113,8 @@ public abstract class IngredientMixin {
|
|||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason remove caching of the item stacks, it won't deduplicate anything with tags (since each Ingredient
|
||||
* instance would make new item stacks anyway, and storing them permanently takes up a lot of memory).
|
||||
* We implement an optimized version of some functions that avoids needing to call this entirely.
|
||||
* @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() {
|
||||
|
|
@ -124,6 +127,19 @@ public abstract class IngredientMixin {
|
|||
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) {
|
||||
|
|
@ -150,4 +166,9 @@ public abstract class IngredientMixin {
|
|||
}
|
||||
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