Clean up and restructure the replay sender
Add a ReplayFile class for easy reading of replay files
This commit is contained in:
@@ -13,6 +13,7 @@ import eu.crushedpixel.replaymod.registry.UploadedFileHandler;
|
|||||||
import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer;
|
import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer;
|
||||||
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
||||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
@@ -158,7 +159,7 @@ public class ReplayMod {
|
|||||||
File folder = ReplayFileIO.getReplayFolder();
|
File folder = ReplayFileIO.getReplayFolder();
|
||||||
|
|
||||||
for(File f : folder.listFiles()) {
|
for(File f : folder.listFiles()) {
|
||||||
if(("." + FilenameUtils.getExtension(f.getAbsolutePath())).equals(ConnectionEventHandler.TEMP_FILE_EXTENSION)) {
|
if(("." + FilenameUtils.getExtension(f.getAbsolutePath())).equals(ReplayFile.TEMP_FILE_EXTENSION)) {
|
||||||
f.delete();
|
f.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import eu.crushedpixel.replaymod.api.client.holders.Category;
|
|||||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||||
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
|
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
|
||||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
||||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
|
||||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||||
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ResourceHelper;
|
import eu.crushedpixel.replaymod.utils.ResourceHelper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Gui;
|
import net.minecraft.client.gui.Gui;
|
||||||
@@ -20,8 +20,6 @@ import net.minecraft.client.gui.GuiTextField;
|
|||||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||||
import net.minecraft.client.resources.I18n;
|
import net.minecraft.client.resources.I18n;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -30,7 +28,8 @@ import org.lwjgl.input.Keyboard;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -64,30 +63,17 @@ public class GuiUploadFile extends GuiScreen {
|
|||||||
boolean correctFile = false;
|
boolean correctFile = false;
|
||||||
this.replayFile = file;
|
this.replayFile = file;
|
||||||
|
|
||||||
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ConnectionEventHandler.ZIP_FILE_EXTENSION)) {
|
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ReplayFile.ZIP_FILE_EXTENSION)) {
|
||||||
ZipFile archive = null;
|
ReplayFile archive = null;
|
||||||
try {
|
try {
|
||||||
archive = new ZipFile(file);
|
archive = new ReplayFile(file);
|
||||||
ZipArchiveEntry recfile = archive.getEntry("recording" + ConnectionEventHandler.TEMP_FILE_EXTENSION);
|
|
||||||
ZipArchiveEntry metadata = archive.getEntry("metaData" + ConnectionEventHandler.JSON_FILE_EXTENSION);
|
|
||||||
|
|
||||||
ZipArchiveEntry image = archive.getEntry("thumb");
|
metaData = archive.metadata().get();
|
||||||
BufferedImage img = null;
|
BufferedImage img = archive.thumb().get();
|
||||||
if(image != null) {
|
if(img != null) {
|
||||||
InputStream is = archive.getInputStream(image);
|
thumb = ImageUtils.scaleImage(img, new Dimension(1280, 720));
|
||||||
is.skip(7);
|
|
||||||
BufferedImage bimg = ImageIO.read(is);
|
|
||||||
if(bimg != null) {
|
|
||||||
thumb = ImageUtils.scaleImage(bimg, new Dimension(1280, 720));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream is = archive.getInputStream(metadata);
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
|
||||||
String json = br.readLine();
|
|
||||||
|
|
||||||
metaData = gson.fromJson(json, ReplayMetaData.class);
|
|
||||||
|
|
||||||
archive.close();
|
archive.close();
|
||||||
correctFile = true;
|
correctFile = true;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.crushedpixel.replaymod.gui.replayviewer;
|
package eu.crushedpixel.replaymod.gui.replayviewer;
|
||||||
|
|
||||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import net.minecraft.client.gui.GuiButton;
|
import net.minecraft.client.gui.GuiButton;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
@@ -48,7 +48,7 @@ public class GuiRenameReplay extends GuiScreen {
|
|||||||
} else if(button.id == 0) {
|
} else if(button.id == 0) {
|
||||||
File folder = ReplayFileIO.getReplayFolder();
|
File folder = ReplayFileIO.getReplayFolder();
|
||||||
|
|
||||||
File initRenamed = new File(folder, this.field_146583_f.getText().trim() + ConnectionEventHandler.ZIP_FILE_EXTENSION.replaceAll("[^a-zA-Z0-9\\.\\-]", "_"));
|
File initRenamed = new File(folder, (this.field_146583_f.getText().trim() + ReplayFile.ZIP_FILE_EXTENSION).replaceAll("[^a-zA-Z0-9\\.\\-]", "_"));
|
||||||
File renamed = initRenamed;
|
File renamed = initRenamed;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
while(renamed.isFile()) {
|
while(renamed.isFile()) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package eu.crushedpixel.replaymod.gui.replayviewer;
|
package eu.crushedpixel.replaymod.gui.replayviewer;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.mojang.realmsclient.util.Pair;
|
import com.mojang.realmsclient.util.Pair;
|
||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
import eu.crushedpixel.replaymod.api.client.holders.FileInfo;
|
import eu.crushedpixel.replaymod.api.client.holders.FileInfo;
|
||||||
@@ -8,11 +7,11 @@ import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
|
|||||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
||||||
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
||||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
||||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
|
||||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||||
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
||||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import net.minecraft.client.gui.GuiButton;
|
import net.minecraft.client.gui.GuiButton;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
@@ -20,8 +19,6 @@ import net.minecraft.client.gui.GuiYesNo;
|
|||||||
import net.minecraft.client.gui.GuiYesNoCallback;
|
import net.minecraft.client.gui.GuiYesNoCallback;
|
||||||
import net.minecraft.client.resources.I18n;
|
import net.minecraft.client.resources.I18n;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.lwjgl.Sys;
|
import org.lwjgl.Sys;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
@@ -29,7 +26,8 @@ import org.lwjgl.input.Keyboard;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,7 +41,6 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
|||||||
private static final int DELETE_BUTTON_ID = 9005;
|
private static final int DELETE_BUTTON_ID = 9005;
|
||||||
private static final int SETTINGS_BUTTON_ID = 9006;
|
private static final int SETTINGS_BUTTON_ID = 9006;
|
||||||
private static final int CANCEL_BUTTON_ID = 9007;
|
private static final int CANCEL_BUTTON_ID = 9007;
|
||||||
private static Gson gson = new Gson();
|
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
private GuiReplayListExtended replayGuiList;
|
private GuiReplayListExtended replayGuiList;
|
||||||
private List<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>();
|
private List<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>();
|
||||||
@@ -65,39 +62,21 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
|||||||
|
|
||||||
for(File file : ReplayFileIO.getAllReplayFiles()) {
|
for(File file : ReplayFileIO.getAllReplayFiles()) {
|
||||||
try {
|
try {
|
||||||
ZipFile archive = new ZipFile(file);
|
ReplayFile replayFile = new ReplayFile(file);
|
||||||
ZipArchiveEntry metadata = archive.getEntry("metaData" + ConnectionEventHandler.JSON_FILE_EXTENSION);
|
ReplayMetaData metaData = replayFile.metadata().get();
|
||||||
|
BufferedImage img = replayFile.thumb().get();
|
||||||
ZipArchiveEntry image = archive.getEntry("thumb");
|
|
||||||
BufferedImage img = null;
|
|
||||||
if(image != null) {
|
|
||||||
InputStream is = archive.getInputStream(image);
|
|
||||||
is.skip(7);
|
|
||||||
BufferedImage bimg = ImageIO.read(is);
|
|
||||||
if(bimg != null) {
|
|
||||||
img = ImageUtils.scaleImage(bimg, new Dimension(1280, 720));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File tmp = null;
|
File tmp = null;
|
||||||
if(img != null) {
|
if(img != null) {
|
||||||
|
img = ImageUtils.scaleImage(img, new Dimension(1280, 720));
|
||||||
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath()), "jpg");
|
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath()), "jpg");
|
||||||
tmp.deleteOnExit();
|
tmp.deleteOnExit();
|
||||||
|
|
||||||
ImageIO.write(img, "jpg", tmp);
|
ImageIO.write(img, "jpg", tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream is = archive.getInputStream(metadata);
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
|
||||||
|
|
||||||
String json = br.readLine();
|
|
||||||
|
|
||||||
ReplayMetaData metaData = gson.fromJson(json, ReplayMetaData.class);
|
|
||||||
|
|
||||||
replayFileList.add(Pair.of(Pair.of(file, metaData), tmp));
|
replayFileList.add(Pair.of(Pair.of(file, metaData), tmp));
|
||||||
|
replayFile.close();
|
||||||
archive.close();
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package eu.crushedpixel.replaymod.recording;
|
|||||||
|
|
||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType;
|
import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
@@ -26,9 +27,6 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
public class ConnectionEventHandler {
|
public class ConnectionEventHandler {
|
||||||
|
|
||||||
public static final String TEMP_FILE_EXTENSION = ".tmcpr";
|
|
||||||
public static final String JSON_FILE_EXTENSION = ".json";
|
|
||||||
public static final String ZIP_FILE_EXTENSION = ".mcpr";
|
|
||||||
private static final String decoderKey = "decoder";
|
private static final String decoderKey = "decoder";
|
||||||
private static final String packetHandlerKey = "packet_handler";
|
private static final String packetHandlerKey = "packet_handler";
|
||||||
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
||||||
@@ -92,7 +90,7 @@ public class ConnectionEventHandler {
|
|||||||
File folder = ReplayFileIO.getReplayFolder();
|
File folder = ReplayFileIO.getReplayFolder();
|
||||||
|
|
||||||
fileName = sdf.format(Calendar.getInstance().getTime());
|
fileName = sdf.format(Calendar.getInstance().getTime());
|
||||||
currentFile = new File(folder, fileName + TEMP_FILE_EXTENSION);
|
currentFile = new File(folder, fileName + ReplayFile.TEMP_FILE_EXTENSION);
|
||||||
|
|
||||||
currentFile.createNewFile();
|
currentFile.createNewFile();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package eu.crushedpixel.replaymod.recording;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import eu.crushedpixel.replaymod.gui.GuiReplaySaving;
|
import eu.crushedpixel.replaymod.gui.GuiReplaySaving;
|
||||||
import eu.crushedpixel.replaymod.holders.PacketData;
|
import eu.crushedpixel.replaymod.holders.PacketData;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
@@ -134,7 +135,7 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
File folder = ReplayFileIO.getReplayFolder();
|
File folder = ReplayFileIO.getReplayFolder();
|
||||||
|
|
||||||
File archive = new File(folder, name + ConnectionEventHandler.ZIP_FILE_EXTENSION);
|
File archive = new File(folder, name + ReplayFile.ZIP_FILE_EXTENSION);
|
||||||
archive.createNewFile();
|
archive.createNewFile();
|
||||||
|
|
||||||
ReplayFileIO.writeReplayFile(archive, file, metaData);
|
ReplayFileIO.writeReplayFile(archive, file, metaData);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.mojang.authlib.GameProfile;
|
|||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||||
import eu.crushedpixel.replaymod.holders.*;
|
import eu.crushedpixel.replaymod.holders.*;
|
||||||
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
@@ -14,6 +15,7 @@ import net.minecraft.network.NetworkManager;
|
|||||||
import net.minecraft.network.play.INetHandlerPlayClient;
|
import net.minecraft.network.play.INetHandlerPlayClient;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ReplayHandler {
|
public class ReplayHandler {
|
||||||
@@ -36,6 +38,11 @@ public class ReplayHandler {
|
|||||||
|
|
||||||
private static KeyframeSet[] keyframeRepository = new KeyframeSet[]{};
|
private static KeyframeSet[] keyframeRepository = new KeyframeSet[]{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file currently being played.
|
||||||
|
*/
|
||||||
|
private static ReplayFile currentReplayFile;
|
||||||
|
|
||||||
public static KeyframeSet[] getKeyframeRepository() {
|
public static KeyframeSet[] getKeyframeRepository() {
|
||||||
return keyframeRepository;
|
return keyframeRepository;
|
||||||
}
|
}
|
||||||
@@ -49,7 +56,7 @@ public class ReplayHandler {
|
|||||||
|
|
||||||
ReplayFileIO.writeKeyframeRegistryToFile(repo, tempFile);
|
ReplayFileIO.writeKeyframeRegistryToFile(repo, tempFile);
|
||||||
|
|
||||||
ReplayMod.replayFileAppender.registerModifiedFile(tempFile, "paths", ReplayMod.replaySender.getReplayFile());
|
ReplayMod.replayFileAppender.registerModifiedFile(tempFile, "paths", getReplayFile());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -325,13 +332,23 @@ public class ReplayHandler {
|
|||||||
|
|
||||||
channel = new OpenEmbeddedChannel(networkManager);
|
channel = new OpenEmbeddedChannel(networkManager);
|
||||||
|
|
||||||
ReplayMod.replaySender = new ReplaySender(file, networkManager);
|
// Open replay
|
||||||
|
try {
|
||||||
|
currentReplayFile = new ReplayFile(file);
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyframeSet[] paths = currentReplayFile.paths().get();
|
||||||
|
ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false);
|
||||||
|
|
||||||
|
ReplayMod.replaySender = new ReplaySender(currentReplayFile, true);
|
||||||
channel.pipeline().addFirst(ReplayMod.replaySender);
|
channel.pipeline().addFirst(ReplayMod.replaySender);
|
||||||
channel.pipeline().fireChannelActive();
|
channel.pipeline().fireChannelActive();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ReplayMod.overlay.resetUI(true);
|
ReplayMod.overlay.resetUI(true);
|
||||||
} catch(Exception e) {}
|
} catch(Exception e) {} // TODO proper handling
|
||||||
|
|
||||||
//Load lighting and trigger update
|
//Load lighting and trigger update
|
||||||
ReplayMod.replaySettings.setLightingEnabled(ReplayMod.replaySettings.isLightingEnabled());
|
ReplayMod.replaySettings.setLightingEnabled(ReplayMod.replaySettings.isLightingEnabled());
|
||||||
@@ -374,6 +391,15 @@ public class ReplayHandler {
|
|||||||
ReplayMod.replaySender.terminateReplay();
|
ReplayMod.replaySender.terminateReplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentReplayFile != null) {
|
||||||
|
try {
|
||||||
|
currentReplayFile.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
currentReplayFile = null;
|
||||||
|
}
|
||||||
|
|
||||||
resetKeyframes();
|
resetKeyframes();
|
||||||
|
|
||||||
inReplay = false;
|
inReplay = false;
|
||||||
@@ -400,10 +426,7 @@ public class ReplayHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static File getReplayFile() {
|
public static File getReplayFile() {
|
||||||
if(ReplayMod.replaySender != null) {
|
return currentReplayFile == null ? null : currentReplayFile.getFile();
|
||||||
return ReplayMod.replaySender.getReplayFile();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TimeKeyframe getFirstTimeKeyframe() {
|
public static TimeKeyframe getFirstTimeKeyframe() {
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ public class ReplayProcess {
|
|||||||
calculated = false;
|
calculated = false;
|
||||||
requestFinish = false;
|
requestFinish = false;
|
||||||
|
|
||||||
ReplayMod.replaySender.resetToleratedTimeStamp();
|
|
||||||
|
|
||||||
blocked = deepBlock = false;
|
blocked = deepBlock = false;
|
||||||
|
|
||||||
startRealTime = System.currentTimeMillis();
|
startRealTime = System.currentTimeMillis();
|
||||||
@@ -97,6 +95,7 @@ public class ReplayProcess {
|
|||||||
|
|
||||||
ReplayHandler.sortKeyframes();
|
ReplayHandler.sortKeyframes();
|
||||||
ReplayHandler.setInPath(true);
|
ReplayHandler.setInPath(true);
|
||||||
|
ReplayMod.replaySender.setAsyncMode(false);
|
||||||
|
|
||||||
//gets first Timestamp and sets Replay Time to it
|
//gets first Timestamp and sets Replay Time to it
|
||||||
TimeKeyframe tf = ReplayHandler.getFirstTimeKeyframe();
|
TimeKeyframe tf = ReplayHandler.getFirstTimeKeyframe();
|
||||||
@@ -105,7 +104,7 @@ public class ReplayProcess {
|
|||||||
if(ts < ReplayMod.replaySender.currentTimeStamp()) {
|
if(ts < ReplayMod.replaySender.currentTimeStamp()) {
|
||||||
mc.displayGuiScreen(null);
|
mc.displayGuiScreen(null);
|
||||||
}
|
}
|
||||||
ReplayMod.replaySender.jumpToTime(ts);
|
ReplayMod.replaySender.sendPacketsTill(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION);
|
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION);
|
||||||
@@ -132,6 +131,7 @@ public class ReplayProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReplayHandler.setInPath(false);
|
ReplayHandler.setInPath(false);
|
||||||
|
ReplayMod.replaySender.setAsyncMode(true);
|
||||||
|
|
||||||
ReplayMod.replaySender.stopHurrying();
|
ReplayMod.replaySender.stopHurrying();
|
||||||
|
|
||||||
@@ -357,8 +357,8 @@ public class ReplayProcess {
|
|||||||
lastRenderPartialTicks = MCTimerHandler.getRenderTicks();
|
lastRenderPartialTicks = MCTimerHandler.getRenderTicks();
|
||||||
lastTicks = MCTimerHandler.getTicks();
|
lastTicks = MCTimerHandler.getTicks();
|
||||||
|
|
||||||
if(curTimestamp != null && curTimestamp != ReplayMod.replaySender.getDesiredTimestamp())
|
if(curTimestamp != null)
|
||||||
ReplayMod.replaySender.jumpToTime(curTimestamp);
|
ReplayMod.replaySender.sendPacketsTill(curTimestamp);
|
||||||
|
|
||||||
//splinePos = (index of last entry + add) / total entries
|
//splinePos = (index of last entry + add) / total entries
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
117
src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java
Normal file
117
src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
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.recording.ReplayMetaData;
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class ReplayFile extends ZipFile {
|
||||||
|
|
||||||
|
public static final String TEMP_FILE_EXTENSION = ".tmcpr";
|
||||||
|
public static final String JSON_FILE_EXTENSION = ".json";
|
||||||
|
public static final String ZIP_FILE_EXTENSION = ".mcpr";
|
||||||
|
public static final String ENTRY_RECORDING = "recording" + TEMP_FILE_EXTENSION;
|
||||||
|
public static final String ENTRY_METADATA = "metaData" + JSON_FILE_EXTENSION;
|
||||||
|
public static final String ENTRY_PATHS = "paths";
|
||||||
|
public static final String ENTRY_THUMB = "thumb";
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public ReplayFile(File f) throws IOException {
|
||||||
|
super(f);
|
||||||
|
this.file = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZipArchiveEntry recordingEntry() {
|
||||||
|
return getEntry(ENTRY_RECORDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<InputStream> recording() {
|
||||||
|
return new Supplier<InputStream>() {
|
||||||
|
@Override
|
||||||
|
public InputStream get() {
|
||||||
|
try {
|
||||||
|
return getInputStream(recordingEntry());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZipArchiveEntry metadataEntry() {
|
||||||
|
return getEntry(ENTRY_METADATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<ReplayMetaData> metadata() {
|
||||||
|
return new Supplier<ReplayMetaData>() {
|
||||||
|
@Override
|
||||||
|
public ReplayMetaData get() {
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(metadataEntry())));
|
||||||
|
return new Gson().fromJson(reader, ReplayMetaData.class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZipArchiveEntry pathsEntry() {
|
||||||
|
return getEntry(ENTRY_PATHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<KeyframeSet[]> paths() {
|
||||||
|
return new Supplier<KeyframeSet[]>() {
|
||||||
|
@Override
|
||||||
|
public KeyframeSet[] get() {
|
||||||
|
try {
|
||||||
|
ZipArchiveEntry entry = pathsEntry();
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(entry)));
|
||||||
|
return new Gson().fromJson(reader, KeyframeSet[].class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZipArchiveEntry thumbEntry() {
|
||||||
|
return getEntry(ENTRY_THUMB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<BufferedImage> thumb() {
|
||||||
|
return new Supplier<BufferedImage>() {
|
||||||
|
@Override
|
||||||
|
public BufferedImage get() {
|
||||||
|
try {
|
||||||
|
ZipArchiveEntry entry = thumbEntry();
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InputStream is = getInputStream(entry);
|
||||||
|
int i = 7;
|
||||||
|
while (i > 0) {
|
||||||
|
i -= is.skip(i); // Security through obscurity \o/
|
||||||
|
}
|
||||||
|
return ImageIO.read(is);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package eu.crushedpixel.replaymod.utils;
|
package eu.crushedpixel.replaymod.utils;
|
||||||
|
|
||||||
import akka.japi.Pair;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
import eu.crushedpixel.replaymod.holders.KeyframeSet;
|
import eu.crushedpixel.replaymod.holders.KeyframeSet;
|
||||||
import eu.crushedpixel.replaymod.holders.PacketData;
|
import eu.crushedpixel.replaymod.holders.PacketData;
|
||||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
|
||||||
import eu.crushedpixel.replaymod.recording.PacketSerializer;
|
import eu.crushedpixel.replaymod.recording.PacketSerializer;
|
||||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
@@ -16,8 +14,6 @@ import net.minecraft.network.Packet;
|
|||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.network.play.server.S01PacketJoinGame;
|
import net.minecraft.network.play.server.S01PacketJoinGame;
|
||||||
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
|
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -54,28 +50,13 @@ public class ReplayFileIO {
|
|||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<File>();
|
||||||
File folder = getReplayFolder();
|
File folder = getReplayFolder();
|
||||||
for(File file : folder.listFiles()) {
|
for(File file : folder.listFiles()) {
|
||||||
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(
|
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ReplayFile.ZIP_FILE_EXTENSION)) {
|
||||||
ConnectionEventHandler.ZIP_FILE_EXTENSION)) {
|
|
||||||
files.add(file);
|
files.add(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataInputStream getMetaDataInputStream(File replayFile) throws IOException {
|
|
||||||
ZipFile archive = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
archive = new ZipFile(replayFile);
|
|
||||||
ZipArchiveEntry tmcpr = archive.getEntry("metaData" +
|
|
||||||
ConnectionEventHandler.JSON_FILE_EXTENSION);
|
|
||||||
|
|
||||||
return new DataInputStream(archive.getInputStream(tmcpr));
|
|
||||||
} catch(IOException e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeReplayFile(File replayFile, File tempFile, ReplayMetaData metaData) throws IOException {
|
public static void writeReplayFile(File replayFile, File tempFile, ReplayMetaData metaData) throws IOException {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
|
|
||||||
@@ -88,13 +69,13 @@ public class ReplayFileIO {
|
|||||||
|
|
||||||
String json = new Gson().toJson(metaData);
|
String json = new Gson().toJson(metaData);
|
||||||
|
|
||||||
zos.putNextEntry(new ZipEntry("metaData.json"));
|
zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_METADATA));
|
||||||
PrintWriter pw = new PrintWriter(zos);
|
PrintWriter pw = new PrintWriter(zos);
|
||||||
pw.write(json);
|
pw.write(json);
|
||||||
pw.flush();
|
pw.flush();
|
||||||
zos.closeEntry();
|
zos.closeEntry();
|
||||||
|
|
||||||
zos.putNextEntry(new ZipEntry("recording" + ConnectionEventHandler.TEMP_FILE_EXTENSION));
|
zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_RECORDING));
|
||||||
FileInputStream fis = new FileInputStream(tempFile);
|
FileInputStream fis = new FileInputStream(tempFile);
|
||||||
int len;
|
int len;
|
||||||
while((len = fis.read(buffer)) > 0) {
|
while((len = fis.read(buffer)) > 0) {
|
||||||
@@ -107,26 +88,13 @@ public class ReplayFileIO {
|
|||||||
zos.close();
|
zos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Pair<Long, DataInputStream> getTempFileInputStream(File replayFile) throws Exception {
|
|
||||||
ZipFile archive = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
archive = new ZipFile(replayFile);
|
|
||||||
ZipArchiveEntry tmcpr = archive.getEntry("recording" +
|
|
||||||
ConnectionEventHandler.TEMP_FILE_EXTENSION);
|
|
||||||
long size = tmcpr.getSize();
|
|
||||||
|
|
||||||
return new Pair<Long, DataInputStream>(size, new DataInputStream(archive.getInputStream(tmcpr)));
|
|
||||||
} catch(Exception e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ReplayMetaData getMetaData(File replayFile) throws IOException {
|
public static ReplayMetaData getMetaData(File replayFile) throws IOException {
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(getMetaDataInputStream(replayFile)));
|
ReplayFile file = new ReplayFile(replayFile);
|
||||||
String json = br.readLine();
|
try {
|
||||||
|
return file.metadata().get();
|
||||||
return new Gson().fromJson(json, ReplayMetaData.class);
|
} finally {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,12 +106,13 @@ public class ReplayFileIO {
|
|||||||
if(replayFile == lastReplayFile) {
|
if(replayFile == lastReplayFile) {
|
||||||
return lastContainsJoinPacket;
|
return lastContainsJoinPacket;
|
||||||
}
|
}
|
||||||
|
ReplayFile file = null;
|
||||||
|
|
||||||
lastReplayFile = replayFile;
|
lastReplayFile = replayFile;
|
||||||
lastContainsJoinPacket = false;
|
lastContainsJoinPacket = false;
|
||||||
try {
|
try {
|
||||||
Pair<Long, DataInputStream> pair = getTempFileInputStream(replayFile);
|
file = new ReplayFile(replayFile);
|
||||||
dis = pair.second();
|
dis = new DataInputStream(file.recording().get());
|
||||||
PacketData pd = readPacketData(dis);
|
PacketData pd = readPacketData(dis);
|
||||||
while(dis.available() > 0) {
|
while(dis.available() > 0) {
|
||||||
Packet p = deserializePacket(pd.getByteArray());
|
Packet p = deserializePacket(pd.getByteArray());
|
||||||
@@ -163,8 +132,10 @@ public class ReplayFileIO {
|
|||||||
if(dis != null) {
|
if(dis != null) {
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
if (file != null) {
|
||||||
}
|
file.close();
|
||||||
|
}
|
||||||
|
} catch(Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -238,6 +209,7 @@ public class ReplayFileIO {
|
|||||||
|
|
||||||
RandomAccessFile raf = null;
|
RandomAccessFile raf = null;
|
||||||
DataInputStream dis = null;
|
DataInputStream dis = null;
|
||||||
|
ReplayFile file = null;
|
||||||
|
|
||||||
boolean bounds = false;
|
boolean bounds = false;
|
||||||
int lower = 0, upper = 0;
|
int lower = 0, upper = 0;
|
||||||
@@ -255,10 +227,10 @@ public class ReplayFileIO {
|
|||||||
outputFile.createNewFile();
|
outputFile.createNewFile();
|
||||||
}
|
}
|
||||||
raf = new RandomAccessFile(outputFile, "rw");
|
raf = new RandomAccessFile(outputFile, "rw");
|
||||||
|
file = new ReplayFile(replayFile);
|
||||||
|
|
||||||
Pair<Long, DataInputStream> pair = getTempFileInputStream(replayFile);
|
dis = new DataInputStream(file.recording().get());
|
||||||
dis = pair.second();
|
long fileLength = file.recordingEntry().getSize();
|
||||||
long fileLength = pair.first();
|
|
||||||
|
|
||||||
raf.setLength(fileLength);
|
raf.setLength(fileLength);
|
||||||
|
|
||||||
@@ -300,8 +272,10 @@ public class ReplayFileIO {
|
|||||||
if(dis != null) {
|
if(dis != null) {
|
||||||
dis.close();
|
dis.close();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
if(file != null) {
|
||||||
}
|
file.close();
|
||||||
|
}
|
||||||
|
} catch(Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user