diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index 28aeb7ce..28f75288 100755 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -6,8 +6,9 @@ import eu.crushedpixel.replaymod.events.*; import eu.crushedpixel.replaymod.localization.LocalizedResourcePack; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.reflection.MCPNames; -import eu.crushedpixel.replaymod.registry.ReplayFileAppender; import eu.crushedpixel.replaymod.registry.KeybindRegistry; +import eu.crushedpixel.replaymod.registry.ReplayFileAppender; +import eu.crushedpixel.replaymod.registry.UploadedFileHandler; import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer; import eu.crushedpixel.replaymod.replay.ReplaySender; import eu.crushedpixel.replaymod.settings.ReplaySettings; @@ -36,7 +37,7 @@ public class ReplayMod { //TODO: Show the player whether he has already uploaded a replay - //TODO: Hinting to the b/v key feature (help page) + //TODO: help page //TODO: Add "Miscellaneous" Replay Category @@ -47,7 +48,6 @@ public class ReplayMod { //Rain isn't working //Incompatible with Shaders Mod // - // public static final String MODID = "replaymod"; public static final String VERSION = "0.0.1"; @@ -63,6 +63,7 @@ public class ReplayMod { public static ReplaySender replaySender; public static int TP_DISTANCE_LIMIT = 128; public static ReplayFileAppender replayFileAppender; + public static UploadedFileHandler uploadedFileHandler; private static Field defaultResourcePacksField; static { @@ -83,6 +84,8 @@ public class ReplayMod { config = new Configuration(event.getSuggestedConfigurationFile()); config.load(); + uploadedFileHandler = new UploadedFileHandler(event.getModConfigurationDirectory()); + replaySettings = new ReplaySettings(); replaySettings.readValues(); @@ -146,7 +149,7 @@ public class ReplayMod { JOptionPane.showMessageDialog(null, "It seems like you didn't donate, so you can't use the Replay Mod yet."); FMLCommonHandler.instance().exitJava(0, false); } - */ + */ } private void removeTmcprFiles() { diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/FileUploader.java b/src/main/java/eu/crushedpixel/replaymod/api/client/FileUploader.java index 38818b6c..2f737948 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/client/FileUploader.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/FileUploader.java @@ -1,6 +1,7 @@ package eu.crushedpixel.replaymod.api.client; import com.google.gson.Gson; +import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.api.client.holders.ApiError; import eu.crushedpixel.replaymod.api.client.holders.Category; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; @@ -31,106 +32,115 @@ public class FileUploader { private GuiUploadFile parent; public void uploadFile(GuiUploadFile gui, String auth, String filename, List tags, File file, Category category) throws IOException, ApiException, RuntimeException { - parent = gui; - gui.onStartUploading(); - filesize = 0; - - if(uploading) throw new RuntimeException("FileUploader is already uploading"); - uploading = true; - - String postData = "?auth=" + auth + "&category=" + category.getId(); - - if(tags.size() > 0) { - postData += "&tags="; - for(String tag : tags) { - postData += tag; - if(!tag.equals(tags.get(tags.size() - 1))) { - postData += ","; - } - } - } - - postData += "&name=" + URLEncoder.encode(filename, "UTF-8"); - System.out.println(postData); - - String url = "http://ReplayMod.com/api/upload_file" + postData; - HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); - con.setUseCaches(false); - con.setDoOutput(true); - con.setRequestMethod("POST"); - con.setChunkedStreamingMode(1024); - con.setRequestProperty("Connection", "Keep-Alive"); - con.setRequestProperty("Cache-Control", "no-cache"); - con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + this.boundary); - - HashMap params = new HashMap(); - params.put("auth", auth); - params.put("name", filename); - params.put("category", category.getId() + ""); - - DataOutputStream request = new DataOutputStream(con.getOutputStream()); - - request.writeBytes(this.twoHyphens + this.boundary + this.crlf); - request.writeBytes("Content-Disposition: form-data; name=\"" + this.attachmentName + "\";filename=\"" + this.attachmentFileName + "\"" + this.crlf); - request.writeBytes(this.crlf); - - byte[] buf = new byte[1024]; - FileInputStream fis = new FileInputStream(file); - filesize = fis.getChannel().size(); - current = 0; - int len; - while((len = fis.read(buf)) != -1) { - request.write(buf); - current += len; - if(cancel) { - uploading = false; - current = 0; - cancel = false; - parent.onFinishUploading(false, I18n.format("replaymod.gui.upload.canceled")); - fis.close(); - return; - } - } - fis.close(); - - request.writeBytes(this.crlf); - request.writeBytes(this.twoHyphens + this.boundary + this.twoHyphens + this.crlf); - - request.flush(); - request.close(); - boolean success = false; - int responseCode = con.getResponseCode(); - InputStream is; - if(responseCode == 200) { - success = true; - is = con.getInputStream(); - } else { - is = con.getErrorStream(); - } - String info = null; - if(is != null) { - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - info = null; - if(responseCode != 200) { - String json = ""; - while(r.ready()) { - json += r.readLine(); + try { + parent = gui; + gui.onStartUploading(); + filesize = 0; + + if(uploading) throw new RuntimeException("FileUploader is already uploading"); + uploading = true; + + String postData = "?auth=" + auth + "&category=" + category.getId(); + + if(tags.size() > 0) { + postData += "&tags="; + for(String tag : tags) { + postData += tag; + if(!tag.equals(tags.get(tags.size() - 1))) { + postData += ","; + } } - ApiError error = gson.fromJson(json, ApiError.class); - info = error.getTranslatedDesc(); - System.out.println(info); } + + postData += "&name=" + URLEncoder.encode(filename, "UTF-8"); + System.out.println(postData); + + String url = "http://ReplayMod.com/api/upload_file" + postData; + HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); + con.setUseCaches(false); + con.setDoOutput(true); + con.setRequestMethod("POST"); + con.setChunkedStreamingMode(1024); + con.setRequestProperty("Connection", "Keep-Alive"); + con.setRequestProperty("Cache-Control", "no-cache"); + con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + this.boundary); + + HashMap params = new HashMap(); + params.put("auth", auth); + params.put("name", filename); + params.put("category", category.getId() + ""); + + DataOutputStream request = new DataOutputStream(con.getOutputStream()); + + request.writeBytes(this.twoHyphens + this.boundary + this.crlf); + request.writeBytes("Content-Disposition: form-data; name=\"" + this.attachmentName + "\";filename=\"" + this.attachmentFileName + "\"" + this.crlf); + request.writeBytes(this.crlf); + + byte[] buf = new byte[1024]; + FileInputStream fis = new FileInputStream(file); + filesize = fis.getChannel().size(); + current = 0; + int len; + while((len = fis.read(buf)) != -1) { + request.write(buf); + current += len; + if(cancel) { + uploading = false; + current = 0; + cancel = false; + parent.onFinishUploading(false, I18n.format("replaymod.gui.upload.canceled")); + fis.close(); + return; + } + } + fis.close(); + + request.writeBytes(this.crlf); + request.writeBytes(this.twoHyphens + this.boundary + this.twoHyphens + this.crlf); + + request.flush(); + request.close(); + + success = false; + int responseCode = con.getResponseCode(); + InputStream is; + if(responseCode == 200) { + success = true; + is = con.getInputStream(); + } else { + is = con.getErrorStream(); + } + + if(is != null) { + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + info = null; + if(responseCode != 200) { + String json = ""; + while(r.ready()) { + json += r.readLine(); + } + ApiError error = gson.fromJson(json, ApiError.class); + info = error.getTranslatedDesc(); + System.out.println(info); + } + } + con.disconnect(); + + if(info == null) info = I18n.format("replaymod.gui.unknownerror"); + + ReplayMod.uploadedFileHandler.markAsUploaded(file); + + success = true; + } catch(Exception e) { + success = false; + } finally { + parent.onFinishUploading(success, info); + + uploading = false; } - con.disconnect(); - - if(info == null) info = I18n.format("replaymod.gui.unknownerror"); - - parent.onFinishUploading(success, info); - - uploading = false; } public float getUploadProgress() { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java index a1414339..9e5f43a5 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java @@ -2,6 +2,7 @@ package eu.crushedpixel.replaymod.gui.replayviewer; import com.google.gson.Gson; import com.mojang.realmsclient.util.Pair; +import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.api.client.holders.FileInfo; import eu.crushedpixel.replaymod.gui.GuiReplaySettings; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; @@ -11,6 +12,7 @@ import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.recording.ReplayMetaData; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.ImageUtils; +import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; @@ -166,7 +168,18 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { this.drawDefaultBackground(); this.replayGuiList.drawScreen(mouseX, mouseY, partialTicks); this.drawCenteredString(this.fontRendererObj, I18n.format("replaymod.gui.replayviewer"), this.width / 2, 20, 16777215); + super.drawScreen(mouseX, mouseY, partialTicks); + + if(uploadButton.isMouseOver() && !uploadButton.enabled && loadButton.enabled) { + if(!AuthenticationHandler.isAuthenticated()) { + Point mouse = MouseUtils.getMousePos(); + drawCenteredString(mc.fontRendererObj, I18n.format("replaymod.gui.viewer.noauth"), (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); + } else if(currentFileUploaded) { + Point mouse = MouseUtils.getMousePos(); + drawCenteredString(mc.fontRendererObj, I18n.format("replaymod.gui.viewer.alreadyuploaded"), (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); + } + } } @Override @@ -243,12 +256,15 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { } } + private boolean currentFileUploaded = false; + public void setButtonsEnabled(boolean b) { loadButton.enabled = b; if(!b || !AuthenticationHandler.isAuthenticated()) { uploadButton.enabled = false; } else { - uploadButton.enabled = true; + currentFileUploaded = ReplayMod.uploadedFileHandler.isUploaded(replayFileList.get(replayGuiList.selected).first().first()); + uploadButton.enabled = !currentFileUploaded; } renameButton.enabled = b; diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/UploadedFileHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/UploadedFileHandler.java new file mode 100644 index 00000000..5f63fe59 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/registry/UploadedFileHandler.java @@ -0,0 +1,55 @@ +package eu.crushedpixel.replaymod.registry; + +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class UploadedFileHandler { + + private Configuration configuration; + + public UploadedFileHandler(File confDir) { + try { + File confFile = new File(confDir, "uploaded"); + confFile.createNewFile(); + configuration = new Configuration(confFile); + configuration.load(); + + Property uploaded = configuration.get("uploaded", "hashes", new String[0]); + + configuration.save(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void markAsUploaded(File file) throws IOException { + String checksum = String.valueOf(FileUtils.checksumCRC32(file)); + List hashes = new ArrayList(Arrays.asList(configuration.get("uploaded", + "hashes", new String[0]).getStringList())); + configuration.removeCategory(configuration.getCategory("uploaded")); + + hashes.add(checksum); + + configuration.get("uploaded", "hashes", hashes.toArray(new String[hashes.size()])); + configuration.save(); + } + + public boolean isUploaded(File file) { + try { + String checksum = String.valueOf(FileUtils.checksumCRC32(file)); + List hashes = new ArrayList(Arrays.asList(configuration.get("uploaded", + "hashes", new String[0]).getStringList())); + return hashes.contains(checksum); + } catch(Exception e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java index ca4e4632..37daa94d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java @@ -22,22 +22,22 @@ public class ReplaySettings { Configuration config = ReplayMod.config; for(RecordingOptions o : RecordingOptions.values()) { - Property p = getConfigSetting(ReplayMod.instance.config, o.name(), o.getValue(), "recording", false); + Property p = getConfigSetting(config, o.name(), o.getValue(), "recording", false); o.setValue(getValueObject(p)); } for(ReplayOptions o : ReplayOptions.values()) { - Property p = getConfigSetting(ReplayMod.instance.config, o.name(), o.getValue(), "replay", false); + Property p = getConfigSetting(config, o.name(), o.getValue(), "replay", false); o.setValue(getValueObject(p)); } for(RenderOptions o : RenderOptions.values()) { - Property p = getConfigSetting(ReplayMod.instance.config, o.name(), o.getValue(), "render", false); + Property p = getConfigSetting(config, o.name(), o.getValue(), "render", false); o.setValue(getValueObject(p)); } for(AdvancedOptions o : AdvancedOptions.values()) { - Property p = getConfigSetting(ReplayMod.instance.config, o.name(), o.getValue(), "advanced", true); + Property p = getConfigSetting(config, o.name(), o.getValue(), "advanced", true); o.setValue(getValueObject(p)); } diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index a0dba963..e073d5f5 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -93,6 +93,8 @@ replaymod.gui.login.connectionerror=Could not connect to ReplayMod.com replaymod.gui.viewer.rename.title=Rename Replay replaymod.gui.viewer.rename.name=Replay Name replaymod.gui.viewer.replayfolder=Open Replay Folder... +replaymod.gui.viewer.noauth=Log in to upload a Replay +replaymod.gui.viewer.alreadyuploaded=This Replay has already been uploaded replaymod.gui.viewer.delete.linea=Are you sure you want to delete this replay?