diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java index d7374343..d5ddb999 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java @@ -79,4 +79,5 @@ public class GuiConstants { public static final int PLAYER_OVERVIEW_HIDE_ALL = 1010; public static final int PLAYER_OVERVIEW_SHOW_ALL = 0101; + public static final int PLAYER_OVERVIEW_REMEMBER = -10; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java index 83aecf3d..d1f02132 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java @@ -3,8 +3,11 @@ package eu.crushedpixel.replaymod.gui; import com.mojang.realmsclient.util.Pair; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.api.mojang.SkinDownloader; +import eu.crushedpixel.replaymod.holders.PlayerVisibility; import eu.crushedpixel.replaymod.registry.PlayerHandler; import eu.crushedpixel.replaymod.replay.ReplayHandler; +import eu.crushedpixel.replaymod.utils.ReplayFile; +import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; @@ -18,9 +21,11 @@ import net.minecraft.entity.player.EnumPlayerModelParts; import net.minecraft.potion.Potion; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.client.config.GuiCheckBox; +import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import java.awt.*; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -29,11 +34,14 @@ import java.util.List; public class GuiPlayerOverview extends GuiScreen { + public static boolean defaultSave = false; + private List> players; private List checkBoxes; private List loadedPlayers = new ArrayList(); private GuiCheckBox hideAllBox, showAllBox; + private GuiCheckBox rememberHidden; private boolean initialized = false; @@ -112,8 +120,8 @@ public class GuiPlayerOverview extends GuiScreen { } int k2 = (int) (this.width * 0.3); - if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= 60 && mouseY <= lowerBound) { - int off = mouseY - 60; + if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) { + int off = mouseY - upperBound; int p = (off / 21) + upperPlayer; ReplayHandler.spectateEntity(players.get(p).first()); mc.displayGuiScreen(null); @@ -175,14 +183,19 @@ public class GuiPlayerOverview extends GuiScreen { if(!initialized) { hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false); showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true); + rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave); } hideAllBox.xPosition = (int)(this.width*0.7)-5; showAllBox.xPosition = (int)(this.width*0.7)-20; hideAllBox.yPosition = showAllBox.yPosition = 45; + rememberHidden.xPosition = (int)(this.width*0.3); + rememberHidden.yPosition = 45; + buttonList.add(hideAllBox); buttonList.add(showAllBox); + buttonList.add(rememberHidden); initialized = true; } @@ -207,12 +220,13 @@ public class GuiPlayerOverview extends GuiScreen { PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked()); } + private static final int upperBound = 65; + @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB()); int k2 = (int)(this.width * 0.3); - int l2 = 60; - int l3 = l2; + int l2 = upperBound; drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680); @@ -275,8 +289,8 @@ public class GuiPlayerOverview extends GuiScreen { float posPerc = ((float) upperPlayer) / playerCount; int barY = (int) (posPerc * (height - 32 - 32)); - drawRect(k2 - 18, l3 - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB()); - drawRect(k2 - 16, l3+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB()); + drawRect(k2 - 18, upperBound - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB()); + drawRect(k2 - 16, upperBound+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB()); } int i = 0; @@ -288,6 +302,7 @@ public class GuiPlayerOverview extends GuiScreen { hideAllBox.drawButton(mc, mouseX, mouseY); showAllBox.drawButton(mc, mouseX, mouseY); + rememberHidden.drawButton(mc, mouseX, mouseY); if(hideAllBox.isMouseOver()) { drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.hideall"), mouseX, mouseY+5, Color.WHITE.getRGB()); @@ -297,9 +312,42 @@ public class GuiPlayerOverview extends GuiScreen { drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.showall"), mouseX, mouseY+5, Color.WHITE.getRGB()); } + if(rememberHidden.isMouseOver()) { + drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.remembersettings.description"), mouseX, mouseY+5, Color.WHITE.getRGB()); + } + + //this is necessary to reset the GL parameters for further GUI rendering drawRect(0, 0, 0, 0, Color.LIGHT_GRAY.getRGB()); } + private PlayerVisibility getVisibilityInstance() { + return new PlayerVisibility(PlayerHandler.getHiddenPlayers()); + } + + + private void saveOnQuit() { + if(rememberHidden.isChecked()) { + try { + File f = File.createTempFile(ReplayFile.ENTRY_VISIBILITY, "json"); + ReplayFileIO.writePlayerVisibilityToFile(getVisibilityInstance(), f); + ReplayMod.replayFileAppender.registerModifiedFile(f, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); + System.out.println("here"); + } catch(Exception e) { + e.printStackTrace(); + } + } else { + ReplayMod.replayFileAppender.registerModifiedFile(null, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); + } + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + if(keyCode == Keyboard.KEY_ESCAPE) { + saveOnQuit(); + super.keyTyped(typedChar, keyCode); + } + } + private class PlayerComparator implements Comparator { @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java b/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java new file mode 100644 index 00000000..6c46f23d --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java @@ -0,0 +1,17 @@ +package eu.crushedpixel.replaymod.holders; + +import java.util.List; + +public class PlayerVisibility { + + public PlayerVisibility(List hidden) { + this.hidden = hidden.toArray(new Integer[hidden.size()]); + } + + private Integer[] hidden; + + public Integer[] getHiddenPlayers() { + return hidden; + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java index c7d0cb6c..6bd71295 100755 --- a/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java @@ -3,9 +3,9 @@ package eu.crushedpixel.replaymod.registry; import com.google.common.base.Predicate; import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.gui.GuiPlayerOverview; +import eu.crushedpixel.replaymod.holders.PlayerVisibility; import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.Minecraft; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import java.util.ArrayList; @@ -39,6 +39,18 @@ public class PlayerHandler { else hidePlayer(player); } + public static void loadPlayerVisibilityConfiguration(PlayerVisibility visibility) { + resetHiddenPlayers(); + if(visibility != null) { + GuiPlayerOverview.defaultSave = true; + for(int i : visibility.getHiddenPlayers()) { + hidden.add(i); + } + } else { + GuiPlayerOverview.defaultSave = false; + } + } + public static List getHiddenPlayers() { return hidden; } @@ -48,12 +60,7 @@ public class PlayerHandler { } public static void resetHiddenPlayers() { - for(int i : hidden) { - Entity ent = mc.theWorld.getEntityByID(i); - if(ent != null) { - ent.setInvisible(false); - } - } + hidden = new ArrayList(); } public static void openPlayerOverview() { diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java b/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java index e3590029..eb2ac086 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java @@ -43,7 +43,11 @@ public class ReplayFileAppender extends Thread { if(mv != null) { if(mv.getRight().canWrite()) { try { - ReplayFileIO.addFileToZip(mv.getRight(), mv.getLeft().getLeft(), mv.getLeft().getRight()); + if(mv.getLeft().getLeft() == null) { + ReplayFileIO.removeFileFromZip(mv.getRight(), mv.getLeft().getRight()); + } else { + ReplayFileIO.addFileToZip(mv.getRight(), mv.getLeft().getLeft(), mv.getLeft().getRight()); + } } catch(Exception e) { e.printStackTrace(); filesToMove.add(mv); diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index bff21fe7..9fe67ca8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -52,12 +52,12 @@ public class ReplayHandler { keyframeRepository = repo; if(write) { try { - File tempFile = File.createTempFile("paths", "json"); + File tempFile = File.createTempFile(ReplayFile.ENTRY_PATHS, "json"); tempFile.deleteOnExit(); ReplayFileIO.writeKeyframeRegistryToFile(repo, tempFile); - ReplayMod.replayFileAppender.registerModifiedFile(tempFile, "paths", getReplayFile()); + ReplayMod.replayFileAppender.registerModifiedFile(tempFile, ReplayFile.ENTRY_PATHS, getReplayFile()); } catch(Exception e) { e.printStackTrace(); } @@ -344,7 +344,8 @@ public class ReplayHandler { KeyframeSet[] paths = currentReplayFile.paths().get(); ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false); - PlayerHandler.resetHiddenPlayers(); + PlayerVisibility visibility = currentReplayFile.visibility().get(); + PlayerHandler.loadPlayerVisibilityConfiguration(visibility); ReplayMod.replaySender = new ReplaySender(currentReplayFile, true); channel.pipeline().addFirst(ReplayMod.replaySender); diff --git a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java index d6bceeee..ec73310d 100644 --- a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java +++ b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java @@ -3,6 +3,7 @@ package eu.crushedpixel.replaymod.utils; import com.google.common.base.Supplier; import com.google.gson.Gson; import eu.crushedpixel.replaymod.holders.KeyframeSet; +import eu.crushedpixel.replaymod.holders.PlayerVisibility; import eu.crushedpixel.replaymod.recording.ReplayMetaData; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; @@ -20,6 +21,7 @@ public class ReplayFile extends ZipFile { public static final String ENTRY_METADATA = "metaData" + JSON_FILE_EXTENSION; public static final String ENTRY_PATHS = "paths"; public static final String ENTRY_THUMB = "thumb"; + public static final String ENTRY_VISIBILITY = "visibility"; private final File file; @@ -71,6 +73,10 @@ public class ReplayFile extends ZipFile { return getEntry(ENTRY_PATHS); } + public ZipArchiveEntry visibilityEntry() { + return getEntry(ENTRY_VISIBILITY); + } + public Supplier paths() { return new Supplier() { @Override @@ -89,6 +95,24 @@ public class ReplayFile extends ZipFile { }; } + public Supplier visibility() { + return new Supplier() { + @Override + public PlayerVisibility get() { + try { + ZipArchiveEntry entry = visibilityEntry(); + if (entry == null) { + return null; + } + BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(entry))); + return new Gson().fromJson(reader, PlayerVisibility.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + } + public ZipArchiveEntry thumbEntry() { return getEntry(ENTRY_THUMB); } diff --git a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java index 1405818d..b8f35519 100755 --- a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java +++ b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java @@ -4,6 +4,7 @@ import com.google.gson.Gson; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.holders.KeyframeSet; import eu.crushedpixel.replaymod.holders.PacketData; +import eu.crushedpixel.replaymod.holders.PlayerVisibility; import eu.crushedpixel.replaymod.recording.PacketSerializer; import eu.crushedpixel.replaymod.recording.ReplayMetaData; import io.netty.buffer.ByteBuf; @@ -291,11 +292,20 @@ public class ReplayFileIO { Files.write(file.toPath(), json.getBytes()); } - public static KeyframeSet[] getKeyframeRegistryFromFile(File file) throws Exception { - return gson.fromJson(Files.readAllLines(file.toPath()).get(0), KeyframeSet[].class); + public static void writePlayerVisibilityToFile(PlayerVisibility visibility, File file) throws IOException { + file.mkdirs(); + file.createNewFile(); + + String json = gson.toJson(visibility); + Files.write(file.toPath(), json.getBytes()); } public static void addFileToZip(File zipFile, File toAdd, String fileName) throws IOException { + if(toAdd == null) { + removeFileFromZip(zipFile, fileName); + return; + } + // get a temp file File tempFile = File.createTempFile(zipFile.getName(), null, zipFile.getParentFile()); // delete it, otherwise you cannot rename your existing zip to it. @@ -347,4 +357,39 @@ public class ReplayFileIO { toAdd.delete(); } + + public static void removeFileFromZip(File zipFile, String toRemove) throws IOException { + // get a temp file + File tempFile = File.createTempFile(zipFile.getName(), null, zipFile.getParentFile()); + // delete it, otherwise you cannot rename your existing zip to it. + + byte[] buf = new byte[1024]; + + ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile)); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile)); + + ZipEntry entry = zin.getNextEntry(); + while(entry != null) { + String name = entry.getName(); + boolean isFile = name.equalsIgnoreCase(toRemove); + if(!isFile) { + // Add ZIP entry to output stream. + out.putNextEntry(new ZipEntry(name)); + // Transfer bytes from the ZIP file to the output file + int len; + while((len = zin.read(buf)) > 0) { + out.write(buf, 0, len); + } + } + entry = zin.getNextEntry(); + } + // Close the streams + zin.close(); + + // Complete the ZIP file + out.close(); + + zipFile.delete(); + tempFile.renameTo(zipFile); + } } diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index d387a240..c4c1958e 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -168,6 +168,8 @@ replaymod.gui.playeroverview.visible=Visible replaymod.gui.playeroverview.hideall=Hide all replaymod.gui.playeroverview.showall=Show all replaymod.gui.playeroverview.spectate=Spectate Player +replaymod.gui.playeroverview.remembersettings=Remember Hidden Players +replaymod.gui.playeroverview.remembersettings.description=Saves Player Visibility in Replay File #Replay Mod Settings GUI replaymod.gui.settings.title=Replay Mod Settings