From 0fc966244917cec6cab3232a156944713e5dc3ae Mon Sep 17 00:00:00 2001 From: Marius Metzger Date: Mon, 2 Feb 2015 13:41:39 +0100 Subject: [PATCH] Fixed some serious memory issues with the Replay Manager, which now only loads the required thumbnails. --- .../replaymod/entities/CameraEntity.java | 10 ++- .../replaymod/events/GuiEventHandler.java | 3 +- .../gui/replaymanager/GuiReplayListEntry.java | 84 +++++++++++-------- .../replaymanager/GuiReplayListExtended.java | 19 ++--- .../gui/replaymanager/GuiReplayManager.java | 17 ++-- .../gui/replaymanager/ResourceHelper.java | 7 +- 6 files changed, 84 insertions(+), 56 deletions(-) diff --git a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java index 587d5ea2..a6316f80 100644 --- a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java +++ b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java @@ -37,10 +37,14 @@ public class CameraEntity extends EntityPlayer { mc.thePlayer.rotationPitch = mc.getRenderViewEntity().rotationPitch; mc.thePlayer.rotationYaw = mc.getRenderViewEntity().rotationYaw; + mc.thePlayer.posX = mc.getRenderViewEntity().posX; + mc.thePlayer.posY = mc.getRenderViewEntity().posY; + mc.thePlayer.posZ = mc.getRenderViewEntity().posZ; + //removes water/suffocation/shadow overlays in screen - mc.thePlayer.posX = 0; - mc.thePlayer.posY = 500; - mc.thePlayer.posZ = 0; + //mc.thePlayer.posX = 0; + //mc.thePlayer.posY = 500; + //mc.thePlayer.posZ = 0; } if(direction == null || motion < 0.1) { diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java index 2f35351f..bd10de96 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java @@ -51,6 +51,8 @@ public class GuiEventHandler { @SubscribeEvent public void onGui(GuiOpenEvent event) { + if(!(event.gui instanceof GuiReplayManager || event.gui instanceof GuiUploadFile)) ResourceHelper.freeAllResources(); + if(event.gui instanceof GuiMainMenu) { if(ReplayMod.firstMainMenu) { ReplayMod.firstMainMenu = false; @@ -71,7 +73,6 @@ public class GuiEventHandler { event.gui = new GuiReplaySaving(event.gui); return; } - if(!(event.gui instanceof GuiReplayManager || event.gui instanceof GuiUploadFile)) ResourceHelper.freeResources(); if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) { if(ReplayHandler.replayActive()) { event.setCanceled(true); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListEntry.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListEntry.java index 6827538d..35db84ac 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListEntry.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListEntry.java @@ -1,22 +1,21 @@ package eu.crushedpixel.replaymod.gui.replaymanager; import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.zip.ZipInputStream; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import javax.imageio.ImageIO; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiListExtended.IGuiListEntry; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.util.ResourceLocation; import eu.crushedpixel.replaymod.recording.ReplayMetaData; @@ -29,9 +28,10 @@ public class GuiReplayListEntry implements IGuiListEntry { private ReplayMetaData metaData; private String fileName; - private final ResourceLocation textureResource; + private ResourceLocation textureResource; private DynamicTexture dynTex = null; + private File imageFile; private BufferedImage image = null; public ReplayMetaData getMetaData() { @@ -52,46 +52,60 @@ public class GuiReplayListEntry implements IGuiListEntry { private GuiReplayListExtended parent; - public GuiReplayListEntry(GuiReplayListExtended parent, String fileName, ReplayMetaData metaData, BufferedImage image) { + public GuiReplayListEntry(GuiReplayListExtended parent, String fileName, ReplayMetaData metaData, File imageFile) { this.metaData = metaData; this.fileName = fileName; this.parent = parent; - this.textureResource = new ResourceLocation("thumbs/"+fileName); dynTex = null; - this.image = image; + this.imageFile = imageFile; } + boolean registered = false; + @Override public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected) { - minecraft.fontRendererObj.drawString(fileName, x + 3, y + 1, 16777215); + try { + minecraft.fontRendererObj.drawString(fileName, x + 3, y + 1, 16777215); + + if(y < -slotHeight || y > parent.height) { + if(registered) { + registered = false; + ResourceHelper.freeResource(textureResource); + textureResource = null; + image = null; + dynTex = null; + } + return; + } else { + if(!registered) { + textureResource = new ResourceLocation("thumbs/"+fileName); + image = ImageIO.read(imageFile); + dynTex = new DynamicTexture(image); + minecraft.getTextureManager().loadTexture(textureResource, dynTex); + dynTex.updateDynamicTexture(); + ResourceHelper.registerResource(textureResource); + registered = true; + } - //Draw thumbnail - if(image != null) { - if(dynTex == null) { - dynTex = new DynamicTexture(image); - minecraft.getTextureManager().loadTexture(textureResource, dynTex); - dynTex.updateDynamicTexture(); - ResourceHelper.registerResource(textureResource); - } - - minecraft.getTextureManager().bindTexture(textureResource); //Will be freed by the ResourceHelper - Gui.drawScaledCustomSizeModalRect(x-60, y, 0, 0, 1280, 720, 57, 32, 1280, 720); + minecraft.getTextureManager().bindTexture(textureResource); + Gui.drawScaledCustomSizeModalRect(x-60, y, 0, 0, 1280, 720, 57, 32, 1280, 720); + } + + List list = new ArrayList(); + list.add(metaData.getServerName()+" ("+dateFormat.format(new Date(metaData.getDate()))+")"); + + list.add(String.format("%02dm%02ds", + TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration()), + TimeUnit.MILLISECONDS.toSeconds(metaData.getDuration()) - + TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration())) + )); + + for (int l1 = 0; l1 < Math.min(list.size(), 2); ++l1) { + minecraft.fontRendererObj.drawString((String)list.get(l1), x + 3, y + 12 + minecraft.fontRendererObj.FONT_HEIGHT * l1, 8421504); + } + } catch(Exception e) { + e.printStackTrace(); } - - List list = new ArrayList(); - list.add(metaData.getServerName()+" ("+dateFormat.format(new Date(metaData.getDate()))+")"); - - list.add(String.format("%02dm%02ds", - TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration()), - TimeUnit.MILLISECONDS.toSeconds(metaData.getDuration()) - - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(metaData.getDuration())) - )); - - for (int l1 = 0; l1 < Math.min(list.size(), 2); ++l1) { - minecraft.fontRendererObj.drawString((String)list.get(l1), x + 3, y + 12 + minecraft.fontRendererObj.FONT_HEIGHT * l1, 8421504); - } - - } @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListExtended.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListExtended.java index d642f6c6..b3ae5f86 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListExtended.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayListExtended.java @@ -1,20 +1,19 @@ package eu.crushedpixel.replaymod.gui.replaymanager; -import java.awt.image.BufferedImage; +import java.io.File; import java.util.ArrayList; import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiListExtended; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.util.MathHelper; + import org.lwjgl.input.Mouse; import eu.crushedpixel.replaymod.recording.ReplayMetaData; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiListExtended; -import net.minecraft.client.gui.ServerListEntryLanScan; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.resources.ResourcePackListEntry; -import net.minecraft.util.MathHelper; public class GuiReplayListExtended extends GuiListExtended { @@ -90,7 +89,7 @@ public class GuiReplayListExtended extends GuiListExtended { entries = new ArrayList(); } - public void addEntry(String fileName, ReplayMetaData metaData, BufferedImage image) { + public void addEntry(String fileName, ReplayMetaData metaData, File image) { entries.add(new GuiReplayListEntry(this, fileName, metaData, image)); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayManager.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayManager.java index eb915ed9..828953dc 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayManager.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/GuiReplayManager.java @@ -55,7 +55,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback { private String hoveringText; private boolean initialized; private GuiReplayListExtended replayGuiList; - private List, BufferedImage>> replayFileList = new ArrayList, BufferedImage>>(); + private List, File>> replayFileList = new ArrayList, File>>(); private GuiButton loadButton, uploadButton, folderButton, renameButton, deleteButton, cancelButton, settingsButton; private static Gson gson = new Gson(); @@ -73,7 +73,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback { private void reloadFiles() { replayGuiList.clearEntries(); - replayFileList = new ArrayList, BufferedImage>>(); + replayFileList = new ArrayList, File>>(); File folder = new File("./replay_recordings/"); folder.mkdirs(); @@ -100,6 +100,11 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback { if(img == null) { img = ImageIO.read(MCPNames.class.getClassLoader().getResourceAsStream("default_thumb.jpg")); } + + File tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath()), "jpg"); + tmp.deleteOnExit(); + + ImageIO.write(img, "jpg", tmp); InputStream is = archive.getInputStream(metadata); BufferedReader br = new BufferedReader(new InputStreamReader(is)); @@ -108,7 +113,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback { ReplayMetaData metaData = gson.fromJson(json, ReplayMetaData.class); - replayFileList.add(Pair.of(Pair.of(file, metaData), img)); + replayFileList.add(Pair.of(Pair.of(file, metaData), tmp)); archive.close(); } catch(Exception e) { @@ -119,15 +124,15 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback { Collections.sort(replayFileList, new FileAgeComparator()); - for(Pair, BufferedImage> p : replayFileList) { + for(Pair, File> p : replayFileList) { replayGuiList.addEntry(FilenameUtils.getBaseName(p.first().first().getName()), p.first().second(), p.second()); } } - public class FileAgeComparator implements Comparator, BufferedImage>> { + public class FileAgeComparator implements Comparator, File>> { @Override - public int compare(Pair, BufferedImage> o1, Pair, BufferedImage> o2) { + public int compare(Pair, File> o1, Pair, File> o2) { try { return (int)(new Date(o2.first().second().getDate()).compareTo(new Date(o1.first().second().getDate()))); } catch(Exception e) { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/ResourceHelper.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/ResourceHelper.java index b4d2cd8e..2e27fd99 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/ResourceHelper.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaymanager/ResourceHelper.java @@ -14,7 +14,12 @@ public class ResourceHelper { openResources.add(loc); } - public static void freeResources() { + public static void freeResource(ResourceLocation loc) { + Minecraft.getMinecraft().getTextureManager().deleteTexture(loc); + openResources.remove(loc); + } + + public static void freeAllResources() { for(ResourceLocation loc : openResources) { Minecraft.getMinecraft().getTextureManager().deleteTexture(loc); }