diff --git a/src/main/java/noppes/npcs/client/Client.java b/src/main/java/noppes/npcs/client/Client.java index ec8dc6884..5247e7bed 100644 --- a/src/main/java/noppes/npcs/client/Client.java +++ b/src/main/java/noppes/npcs/client/Client.java @@ -21,7 +21,6 @@ public class Client { public static HashMap customOverlays = new HashMap<>(); public static HashMap> skinOverlays = new HashMap<>(); public static HashMap playerAnimations = new HashMap<>(); - private static HashMap imageDataCache = new HashMap<>(); public static void sendData(final EnumPacketServer enu, final Object... obs) { ByteBuf buffer = Unpooled.buffer(); @@ -33,12 +32,4 @@ public class Client { e.printStackTrace(); } } - - public static ImageData getImageData(String directory) { - if (!imageDataCache.containsKey(directory)) { - ImageData downloadData = new ImageData(directory); - imageDataCache.put(directory, downloadData); - } - return imageDataCache.get(directory); - } } diff --git a/src/main/java/noppes/npcs/client/ClientCache.java b/src/main/java/noppes/npcs/client/ClientCache.java new file mode 100644 index 000000000..43fb33bd7 --- /dev/null +++ b/src/main/java/noppes/npcs/client/ClientCache.java @@ -0,0 +1,16 @@ +package noppes.npcs.client; + +import noppes.npcs.client.renderer.customitem.ImageData; +import noppes.npcs.util.CacheHashMap; + +public class ClientCache { + private static final CacheHashMap> imageDataCache = new CacheHashMap<>(10*1000); + + public static ImageData getImageData(String directory) { + if (!imageDataCache.containsKey(directory)) { + ImageData imageData = new ImageData(directory); + imageDataCache.put(directory, new CacheHashMap.CachedObject<>(imageData)); + } + return imageDataCache.get(directory).getObject(); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiButton.java b/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiButton.java index 29b918291..f5bb21fb9 100644 --- a/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiButton.java +++ b/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiButton.java @@ -15,6 +15,7 @@ import net.minecraft.client.resources.IResource; import net.minecraft.util.ResourceLocation; import noppes.npcs.api.gui.ICustomGuiComponent; import noppes.npcs.client.Client; +import noppes.npcs.client.ClientCache; import noppes.npcs.client.ImageDownloadAlt; import noppes.npcs.client.gui.custom.GuiCustom; import noppes.npcs.client.gui.custom.interfaces.IClickListener; @@ -62,7 +63,7 @@ public class CustomGuiButton extends GuiButton implements IClickListener { this.textureY = textureY; this.label = buttonText; if (texture != null && !texture.isEmpty()) { - this.imageData = Client.getImageData(texture); + this.imageData = ClientCache.getImageData(texture); } } diff --git a/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiTexturedRect.java b/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiTexturedRect.java index 241a6e2f5..af16d4907 100644 --- a/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiTexturedRect.java +++ b/src/main/java/noppes/npcs/client/gui/custom/components/CustomGuiTexturedRect.java @@ -14,6 +14,7 @@ import net.minecraft.client.resources.IResource; import net.minecraft.util.ResourceLocation; import noppes.npcs.api.gui.ICustomGuiComponent; import noppes.npcs.client.Client; +import noppes.npcs.client.ClientCache; import noppes.npcs.client.ImageDownloadAlt; import noppes.npcs.client.gui.custom.GuiCustom; import noppes.npcs.client.gui.custom.interfaces.IGuiComponent; @@ -61,7 +62,7 @@ public class CustomGuiTexturedRect extends Gui implements IGuiComponent { this.textureX = textureX; this.textureY = textureY; if (texture != null && !texture.isEmpty()) { - this.imageData = Client.getImageData(texture); + this.imageData = ClientCache.getImageData(texture); } } diff --git a/src/main/java/noppes/npcs/client/renderer/customitem/CustomItemRenderer.java b/src/main/java/noppes/npcs/client/renderer/customitem/CustomItemRenderer.java index ec0e670d2..d831fb727 100644 --- a/src/main/java/noppes/npcs/client/renderer/customitem/CustomItemRenderer.java +++ b/src/main/java/noppes/npcs/client/renderer/customitem/CustomItemRenderer.java @@ -14,6 +14,7 @@ import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.IItemRenderer; import noppes.npcs.client.Client; +import noppes.npcs.client.ClientCache; import noppes.npcs.items.ItemScripted; import noppes.npcs.scripted.item.ScriptCustomItem; import org.lwjgl.opengl.GL11; @@ -49,7 +50,7 @@ public class CustomItemRenderer implements IItemRenderer { public void renderItem(ItemRenderType type, ItemStack itemStack, Object... data) { ScriptCustomItem scriptCustomItem = ItemScripted.GetWrapper(itemStack); - BufferedImage bufferedImage = Client.getImageData(scriptCustomItem.texture).getBufferedImage(); + BufferedImage bufferedImage = ClientCache.getImageData(scriptCustomItem.texture).getBufferedImage(); if (bufferedImage != null && (scriptCustomItem.width != bufferedImage.getWidth() || scriptCustomItem.height != bufferedImage.getHeight())) { scriptCustomItem.width = bufferedImage.getWidth(); scriptCustomItem.height = bufferedImage.getHeight(); @@ -136,7 +137,7 @@ public class CustomItemRenderer implements IItemRenderer { int pass = 0; GL11.glPushMatrix(); - Client.getImageData(scriptCustomItem.texture).bindTexture(); + ClientCache.getImageData(scriptCustomItem.texture).bindTexture(); Tessellator tessellator = Tessellator.instance; @@ -191,7 +192,7 @@ public class CustomItemRenderer implements IItemRenderer { // Makes items offset when in 3D, like when in 2D, looks much better. Considered a vanilla bug... GL11.glTranslatef(0f, 0f, f9 + f10); - ImageData imageData = Client.getImageData(scriptCustomItem.texture); + ImageData imageData = ClientCache.getImageData(scriptCustomItem.texture); ItemRenderer.renderItemIn2D(tessellator, f15, f4, f14, f5, imageData.getTotalWidth(), imageData.getTotalHeight(), f9); if (itemStack.hasEffect(pass)) @@ -291,7 +292,7 @@ public class CustomItemRenderer implements IItemRenderer { GL11.glDisable(GL11.GL_LIGHTING); //Forge: Make sure that render states are reset, a renderEffect can derp them up. GL11.glEnable(GL11.GL_ALPHA_TEST); - Client.getImageData(scriptCustomItem.texture).bindTexture(); + ClientCache.getImageData(scriptCustomItem.texture).bindTexture(); renderCustomItemSlot(0,0,16,16, itemRed, itemGreen, itemBlue); GL11.glEnable(GL11.GL_LIGHTING); @@ -366,7 +367,7 @@ public class CustomItemRenderer implements IItemRenderer { TextureManager texturemanager = mc.getTextureManager(); int par3 = 0; - Client.getImageData(scriptCustomItem.texture).bindTexture(); + ClientCache.getImageData(scriptCustomItem.texture).bindTexture(); Tessellator tessellator = Tessellator.instance; IIcon icon = entityLivingBase.getItemIcon(itemStack, par3); @@ -421,7 +422,7 @@ public class CustomItemRenderer implements IItemRenderer { public static void renderCustomItemIn2D(ItemStack itemStack, Tessellator p_78439_0_, float p_78439_1_, float p_78439_2_, float p_78439_3_, float p_78439_4_, float p_78439_7_) { - ImageData imageData = Client.getImageData(ItemScripted.GetWrapper(itemStack).texture); + ImageData imageData = ClientCache.getImageData(ItemScripted.GetWrapper(itemStack).texture); int width = imageData.getTotalWidth(); int height = imageData.getTotalHeight(); diff --git a/src/main/java/noppes/npcs/util/CacheHashMap.java b/src/main/java/noppes/npcs/util/CacheHashMap.java new file mode 100644 index 000000000..fae933a7e --- /dev/null +++ b/src/main/java/noppes/npcs/util/CacheHashMap.java @@ -0,0 +1,56 @@ +package noppes.npcs.util; + +import java.util.*; + +public class CacheHashMap> extends HashMap { + private final long maxCacheTime; + + public CacheHashMap(long maxCacheTime) { + this.maxCacheTime = maxCacheTime; + } + + @Override + public V get(Object key) { + synchronized (this) { + List keysToRemove = new ArrayList<>(); + for (Map.Entry entry : this.entrySet()) { + if (!Objects.equals(key,entry.getKey())) { + long timeDiff = entry.getValue().timeSinceAccessed(); + if (timeDiff > this.maxCacheTime) { + keysToRemove.add(entry.getKey()); + } + } + } + for (K k : keysToRemove) { + this.remove(k); + } + } + + V object = super.get(key); + object.updateTimeAccessed(); + + return object; + } + + public static class CachedObject { + private long lastTimeAccessed; + private final T object; + + public CachedObject(T object) { + this.object = object; + this.lastTimeAccessed = System.currentTimeMillis(); + } + + public long timeSinceAccessed() { + return System.currentTimeMillis() - this.lastTimeAccessed; + } + + public void updateTimeAccessed() { + this.lastTimeAccessed = System.currentTimeMillis(); + } + + public T getObject() { + return this.object; + } + } +}