Fix pattern cache (#3010)

* Fix pattern cache

* Address review comments
This commit is contained in:
Anton Bulakh
2021-06-12 17:58:35 +03:00
committed by GitHub
parent 01911e2650
commit f596531798
3 changed files with 45 additions and 29 deletions

View File

@@ -2,7 +2,7 @@ package com.refinedmods.refinedstorage.apiimpl.storage.tracker;
import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker;
import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.util.ItemStackKey;
import com.refinedmods.refinedstorage.util.StackUtils; import com.refinedmods.refinedstorage.util.StackUtils;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -17,7 +17,7 @@ public class ItemStorageTracker implements IStorageTracker<ItemStack> {
private static final String NBT_NAME = "Name"; private static final String NBT_NAME = "Name";
private static final String NBT_TIME = "Time"; private static final String NBT_TIME = "Time";
private final Map<Key, StorageTrackerEntry> changes = new HashMap<>(); private final Map<ItemStackKey, StorageTrackerEntry> changes = new HashMap<>();
private final Runnable listener; private final Runnable listener;
public ItemStorageTracker(Runnable listener) { public ItemStorageTracker(Runnable listener) {
@@ -26,14 +26,14 @@ public class ItemStorageTracker implements IStorageTracker<ItemStack> {
@Override @Override
public void changed(PlayerEntity player, ItemStack stack) { public void changed(PlayerEntity player, ItemStack stack) {
changes.put(new Key(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString())); changes.put(new ItemStackKey(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString()));
listener.run(); listener.run();
} }
@Override @Override
public StorageTrackerEntry get(ItemStack stack) { public StorageTrackerEntry get(ItemStack stack) {
return changes.get(new Key(stack)); return changes.get(new ItemStackKey(stack));
} }
public void readFromNbt(ListNBT list) { public void readFromNbt(ListNBT list) {
@@ -43,7 +43,7 @@ public class ItemStorageTracker implements IStorageTracker<ItemStack> {
ItemStack stack = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK)); ItemStack stack = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK));
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
changes.put(new Key(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME))); changes.put(new ItemStackKey(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME)));
} }
} }
} }
@@ -51,34 +51,16 @@ public class ItemStorageTracker implements IStorageTracker<ItemStack> {
public ListNBT serializeNbt() { public ListNBT serializeNbt() {
ListNBT list = new ListNBT(); ListNBT list = new ListNBT();
for (Map.Entry<Key, StorageTrackerEntry> entry : changes.entrySet()) { for (Map.Entry<ItemStackKey, StorageTrackerEntry> entry : changes.entrySet()) {
CompoundNBT tag = new CompoundNBT(); CompoundNBT tag = new CompoundNBT();
tag.putLong(NBT_TIME, entry.getValue().getTime()); tag.putLong(NBT_TIME, entry.getValue().getTime());
tag.putString(NBT_NAME, entry.getValue().getName()); tag.putString(NBT_NAME, entry.getValue().getName());
tag.put(NBT_STACK, StackUtils.serializeStackToNbt(entry.getKey().stack)); tag.put(NBT_STACK, StackUtils.serializeStackToNbt(entry.getKey().getStack()));
list.add(tag); list.add(tag);
} }
return list; return list;
} }
private static class Key {
private final ItemStack stack;
public Key(ItemStack stack) {
this.stack = stack;
}
@Override
public boolean equals(Object other) {
return other instanceof Key && API.instance().getComparer().isEqualNoQuantity(stack, ((Key) other).stack);
}
@Override
public int hashCode() {
return API.instance().getItemStackHashCode(stack);
}
}
} }

View File

@@ -10,6 +10,7 @@ import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPattern;
import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPatternFactory; import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPatternFactory;
import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.render.Styles;
import com.refinedmods.refinedstorage.render.tesr.PatternItemStackTileRenderer; import com.refinedmods.refinedstorage.render.tesr.PatternItemStackTileRenderer;
import com.refinedmods.refinedstorage.util.ItemStackKey;
import com.refinedmods.refinedstorage.util.RenderUtils; import com.refinedmods.refinedstorage.util.RenderUtils;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
@@ -35,7 +36,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class PatternItem extends Item implements ICraftingPatternProvider { public class PatternItem extends Item implements ICraftingPatternProvider {
private static final Map<ItemStack, ICraftingPattern> CACHE = new HashMap<>(); private static final Map<ItemStackKey, ICraftingPattern> CACHE = new HashMap<>();
private static final String NBT_VERSION = "Version"; private static final String NBT_VERSION = "Version";
private static final String NBT_INPUT_SLOT = "Input_%d"; private static final String NBT_INPUT_SLOT = "Input_%d";
@@ -53,11 +54,18 @@ public class PatternItem extends Item implements ICraftingPatternProvider {
} }
public static ICraftingPattern fromCache(World world, ItemStack stack) { public static ICraftingPattern fromCache(World world, ItemStack stack) {
if (!CACHE.containsKey(stack)) { ICraftingPattern pattern = CACHE.computeIfAbsent(
CACHE.put(stack, CraftingPatternFactory.INSTANCE.create(world, null, stack)); new ItemStackKey(stack),
s -> CraftingPatternFactory.INSTANCE.create(world, null, s.getStack())
);
// A number that is not too crazy but hopefully is not normally reachable,
// just reset the cache to keep its size limited so this is not a memory leak
if (CACHE.size() > 16384) {
CACHE.clear();
} }
return CACHE.get(stack); return pattern;
} }
@Override @Override

View File

@@ -0,0 +1,26 @@
package com.refinedmods.refinedstorage.util;
import com.refinedmods.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
public final class ItemStackKey {
private final ItemStack stack;
public ItemStackKey(ItemStack stack) {
this.stack = stack;
}
public ItemStack getStack() {
return stack;
}
@Override
public boolean equals(Object other) {
return other instanceof ItemStackKey && API.instance().getComparer().isEqualNoQuantity(stack, ((ItemStackKey) other).stack);
}
@Override
public int hashCode() {
return API.instance().getItemStackHashCode(stack);
}
}