From 238df18b4c6521377e08ec2fc560dee4ad762add Mon Sep 17 00:00:00 2001 From: MCPfannkuchenYT Date: Sat, 16 Oct 2021 00:14:00 +0200 Subject: [PATCH 01/12] Fix the direction the player is facing, when loading a state --- .../playerloading/SavestatePlayerLoadingPacketHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/playerloading/SavestatePlayerLoadingPacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/playerloading/SavestatePlayerLoadingPacketHandler.java index a7467e0c..0ca90e7d 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/playerloading/SavestatePlayerLoadingPacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/playerloading/SavestatePlayerLoadingPacketHandler.java @@ -1,5 +1,6 @@ package de.scribble.lp.tasmod.savestates.server.playerloading; +import de.pfannekuchen.tasmod.events.CameraInterpolationEvents; import de.scribble.lp.tasmod.savestates.server.chunkloading.SavestatesChunkControl; import net.minecraft.client.Minecraft; import net.minecraft.nbt.NBTTagCompound; @@ -61,6 +62,10 @@ private void workaround(SavestatePlayerLoadingPacket message) { GameType type=GameType.getByID(gamemode); Minecraft.getMinecraft().playerController.setGameType(type); + //TAS#?? Player rotation does not change when loading a savestate + CameraInterpolationEvents.rotationPitch=player.rotationPitch; + CameraInterpolationEvents.rotationYaw=player.rotationYaw+180f; + SavestatesChunkControl.keepPlayerInLoadedEntityList(player); SavestatePlayerLoading.wasLoading = true; } From 4df64af53e2137d9a28462eaae8fa6f5089c3037 Mon Sep 17 00:00:00 2001 From: Scribble Date: Tue, 19 Oct 2021 23:59:38 +0200 Subject: [PATCH 02/12] Fixes #117 adding support for keybinds on mouse buttons --- .../de/scribble/lp/tasmod/virtual/VirtualInput.java | 2 +- .../scribble/lp/tasmod/virtual/VirtualKeybindings.java | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java index 37ee1bfd..d4099dd7 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java @@ -264,7 +264,7 @@ public VirtualMouse getNextMouse() { public void updateNextMouse(int keycode, boolean keystate, int scrollwheel, int cursorX, int cursorY, boolean filter) { - if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode)) { + if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode-100)) { return; } boolean flag = true; diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java index bf17fe53..7c7f349e 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java @@ -5,6 +5,7 @@ import java.util.List; import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; import com.google.common.collect.Maps; @@ -47,7 +48,14 @@ public static void increaseCooldowntimer() { public static boolean isKeyDown(KeyBinding keybind) { int keycode=keybind.getKeyCode(); - boolean down = isKeyCodeAlwaysBlocked(keycode) ? Keyboard.isKeyDown(keycode) : ClientProxy.virtual.willKeyBeDown(keycode); + + boolean down=false; + + if(isKeyCodeAlwaysBlocked(keycode)) { + down=keycode>=0 ? Keyboard.isKeyDown(keycode) : Mouse.isButtonDown(keycode+100); + }else { + down=ClientProxy.virtual.willKeyBeDown(keycode); + } if (down) { if (cooldownHashMap.containsKey(keybind)) { From b0a4782fed467470955bda687f66275c457be76e Mon Sep 17 00:00:00 2001 From: Scribble Date: Sat, 23 Oct 2021 00:00:54 +0200 Subject: [PATCH 03/12] Fixing multiple keybinding presses in certain circumstances --- .../lp/tasmod/events/KeybindingEvents.java | 1 - .../lp/tasmod/virtual/VirtualInput.java | 53 ++++++++++-------- .../lp/tasmod/virtual/VirtualKeybindings.java | 54 +++++++++---------- 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/events/KeybindingEvents.java b/src/main/java/de/scribble/lp/tasmod/events/KeybindingEvents.java index e2575c9a..1180ed08 100644 --- a/src/main/java/de/scribble/lp/tasmod/events/KeybindingEvents.java +++ b/src/main/java/de/scribble/lp/tasmod/events/KeybindingEvents.java @@ -19,7 +19,6 @@ public class KeybindingEvents { public static void fireKeybindingsEvent() { - VirtualKeybindings.increaseCooldowntimer(); if (VirtualKeybindings.isKeyDownExceptTextfield(ClientProxy.savestateSaveKey)) { diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java index d4099dd7..50dcdbef 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java @@ -179,7 +179,6 @@ public void clearNextKeyboard() { public boolean isKeyDown(int keycode) { if (keycode >= 0) return currentKeyboard.get(keycode).isKeyDown(); - else return currentMouse.get(keycode).isKeyDown(); } @@ -197,7 +196,6 @@ public boolean isKeyDown(String keyname) { public boolean willKeyBeDown(int keycode) { if (keycode >= 0) return nextKeyboard.get(keycode).isKeyDown(); - else return nextMouse.get(keycode).isKeyDown(); } @@ -264,7 +262,7 @@ public VirtualMouse getNextMouse() { public void updateNextMouse(int keycode, boolean keystate, int scrollwheel, int cursorX, int cursorY, boolean filter) { - if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode-100)) { + if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode - 100)) { return; } boolean flag = true; @@ -427,34 +425,37 @@ public void setContainer(InputContainer container) { public void loadSavestate(InputContainer savestatecontainer) { if (this.container.isPlayingback()) { - preloadInput(this.container, savestatecontainer.size() - 1); // Preloading from the current container and from the second to last index of + preloadInput(this.container, savestatecontainer.size() - 1); // Preloading from the current container and from the second to last index of // the savestatecontainer. Since this is executed during playback, // we will only load the position of the savestate container and not replace the // container itself - this.container.setIndex(savestatecontainer.size()); // Set the "playback" index of the current container to the latest index of the - // savestatecontainer. Meaning this index will be played next + this.container.setIndex(savestatecontainer.size()); // Set the "playback" index of the current container to the latest index of the + // savestatecontainer. Meaning this index will be played next } else if (this.container.isRecording()) { - String start = savestatecontainer.getStartLocation(); // TODO Another start location thing to keep in mind - preloadInput(savestatecontainer, savestatecontainer.size() - 1); // Preload the input of the savestate + String start = savestatecontainer.getStartLocation(); // TODO Another start location thing to keep in mind + preloadInput(savestatecontainer, savestatecontainer.size() - 1); // Preload the input of the savestate - nextKeyboard = new VirtualKeyboard(); // Unpress the nextKeyboard and mouse to get rid of the preloaded inputs in the + nextKeyboard = new VirtualKeyboard(); // Unpress the nextKeyboard and mouse to get rid of the preloaded inputs in the // next keyboard. Note that these inputs are still loaded in the current // keyboard nextMouse = new VirtualMouse(); savestatecontainer.setIndex(savestatecontainer.size()); savestatecontainer.setTASState(TASstate.RECORDING); - savestatecontainer.setStartLocation(start); //TODO Another one - this.container = savestatecontainer; //Replace the current container with the savestated container + savestatecontainer.setStartLocation(start); // TODO Another one + this.container = savestatecontainer; // Replace the current container with the savestated container } } /** - * Preloads the specified index from, the container to {@link #nextMouse} and {@link #nextKeyboard} + * Preloads the specified index from, the container to {@link #nextMouse} and + * {@link #nextKeyboard} + * * @param container The container from which the inputs should be pre loaded - * @param index The index of the container from which the inputs should be loaded + * @param index The index of the container from which the inputs should be + * loaded */ private void preloadInput(InputContainer container, int index) { TickInputContainer tickcontainer = container.get(index); @@ -464,7 +465,8 @@ private void preloadInput(InputContainer container, int index) { nextKeyboard = tickcontainer.getKeyboard().clone(); nextMouse = tickcontainer.getMouse().clone(); - ((AccessorRunStuff) Minecraft.getMinecraft()).runTickKeyboardAccessor(); // Letting mouse and keyboard tick once to load inputs into the "currentKeyboard" + ((AccessorRunStuff) Minecraft.getMinecraft()).runTickKeyboardAccessor(); // Letting mouse and keyboard tick once to load inputs into the + // "currentKeyboard" ((AccessorRunStuff) Minecraft.getMinecraft()).runTickMouseAccessor(); } else { TASmod.logger.warn("Can't preload inputs, specified inputs are null!"); @@ -490,25 +492,30 @@ public InputEvent(int tick, List keyboardevent, List *
- * Container and input events differ in that input events are the events that get accepted by Minecraft in the runTickKeyboard.
- * The container however stores the current inputs and can calculate the corresponding input events from that, but it does it only when you are playing back or recording.
+ * Container and input events differ in that input events are the events that + * get accepted by Minecraft in the runTickKeyboard.
+ * The container however stores the current inputs and can calculate the + * corresponding input events from that, but it does it only when you are + * playing back or recording.
*
- * This however runs through the {@link VirtualInput#container} and generates the input events on for debug purposes. + * This however runs through the {@link VirtualInput#container} and generates + * the input events on for debug purposes. + * * @return */ public List getAllInputEvents() { - + List main = new ArrayList<>(); - + for (int i = 0; i < container.size(); i++) { - + TickInputContainer tick = container.get(i); TickInputContainer nextTick = container.get(i + 1); - + if (nextTick == null) { - nextTick = new TickInputContainer(i + 1); //Fills the last tick in the container with an empty TickInputContainer + nextTick = new TickInputContainer(i + 1); // Fills the last tick in the container with an empty TickInputContainer } - + VirtualKeyboard keyboard = tick.getKeyboard(); List keyboardEventsList = keyboard.getDifference(nextTick.getKeyboard()); diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java index 7c7f349e..8774d41f 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java @@ -19,65 +19,63 @@ /** * Applies special rules to vanilla keybindings.
*
- * Using {@link #isKeyDown(KeyBinding)}, the registered keybindings will work inside of gui screens
+ * Using {@link #isKeyDown(KeyBinding)}, the registered keybindings will work + * inside of gui screens
*
- * {@link #isKeyDownExceptTextfield(KeyBinding)} does the same, but excludes textfields, certain guiscreens, and the keybinding options
+ * {@link #isKeyDownExceptTextfield(KeyBinding)} does the same, but excludes + * textfields, certain guiscreens, and the keybinding options
*
- * Keybindings registered with {@link #registerBlockedKeyBinding(KeyBinding)} will not be recorded during a recording or pressed in a playback + * Keybindings registered with {@link #registerBlockedKeyBinding(KeyBinding)} + * will not be recorded during a recording or pressed in a playback * * @author ScribbleLP * */ public class VirtualKeybindings { private static Minecraft mc = Minecraft.getMinecraft(); - private static long cooldown = 20; + private static long cooldown = 50*10; private static HashMap cooldownHashMap = Maps.newHashMap(); private static List blockedKeys = new ArrayList<>(); - private static long cooldowntimer = 0; public static boolean focused = false; - public static void increaseCooldowntimer() { - cooldowntimer++; - } /** * Checks whether the keycode is pressed, regardless of any gui screens + * * @param keybind * @return */ public static boolean isKeyDown(KeyBinding keybind) { - - int keycode=keybind.getKeyCode(); - - boolean down=false; - - if(isKeyCodeAlwaysBlocked(keycode)) { - down=keycode>=0 ? Keyboard.isKeyDown(keycode) : Mouse.isButtonDown(keycode+100); - }else { - down=ClientProxy.virtual.willKeyBeDown(keycode); + + int keycode = keybind.getKeyCode(); + + boolean down = false; + + if (isKeyCodeAlwaysBlocked(keycode)) { + down = keycode >= 0 ? Keyboard.isKeyDown(keycode) : Mouse.isButtonDown(keycode + 100); + } else { + down = ClientProxy.virtual.willKeyBeDown(keycode); } - + if (down) { if (cooldownHashMap.containsKey(keybind)) { - if (cooldown <= cooldowntimer - (long) cooldownHashMap.get(keybind)) { - cooldownHashMap.put(keybind, cooldowntimer); - cooldown=Minecraft.getDebugFPS()/3; + if (cooldown <= Minecraft.getSystemTime() - (long) cooldownHashMap.get(keybind)) { + cooldownHashMap.put(keybind, Minecraft.getSystemTime()); return true; } return false; } else { - cooldownHashMap.put(keybind, cooldowntimer); - cooldown=Minecraft.getDebugFPS()/3; + cooldownHashMap.put(keybind, Minecraft.getSystemTime()); return true; } } return false; } - + /** * Checks whether the key is down, but stops when certain conditions apply * - * @param keybind + * @param keybind * @return */ public static boolean isKeyDownExceptTextfield(KeyBinding keybind) { @@ -89,14 +87,16 @@ public static boolean isKeyDownExceptTextfield(KeyBinding keybind) { /** * Registers keybindings that should not be recorded or played back in a TAS + * * @param keybind */ public static void registerBlockedKeyBinding(KeyBinding keybind) { blockedKeys.add(keybind); } - + /** * Checks whether the keycode should not be recorded or played back in a TAS + * * @param keycode to block * @return Whether it should be blocked */ @@ -107,5 +107,5 @@ public static boolean isKeyCodeAlwaysBlocked(int keycode) { } return false; } - + } From 04e87b845cb83a9f5c04e66f1c409e2085646086 Mon Sep 17 00:00:00 2001 From: Scribble Date: Wed, 13 Oct 2021 23:39:13 +0200 Subject: [PATCH 04/12] Make SavestateHandler not static anymore -Added a way to map savestate folders to an index, although that is not fully implemented -Added a current index that stores the number of which savestate to load/create next -Added serialization for that currentIndex in .minecraft/saves//tasmod/savestate.data (Maybe with more information to store in the future?) -Fixed a crash when opening the SavestateSavingScreen --- .../java/de/scribble/lp/tasmod/TASmod.java | 5 + .../server/GuiSavestateSavingScreen.java | 7 +- .../server/LoadstatePacketHandler.java | 3 +- .../savestates/server/SavestateHandler.java | 145 ++++++++++++++---- .../server/SavestatePacketHandler.java | 3 +- 5 files changed, 134 insertions(+), 29 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/TASmod.java b/src/main/java/de/scribble/lp/tasmod/TASmod.java index ac6b2a22..14120520 100644 --- a/src/main/java/de/scribble/lp/tasmod/TASmod.java +++ b/src/main/java/de/scribble/lp/tasmod/TASmod.java @@ -15,6 +15,7 @@ import de.scribble.lp.tasmod.commands.recording.CommandRecord; import de.scribble.lp.tasmod.commands.savetas.CommandSaveTAS; import de.scribble.lp.tasmod.commands.tutorial.CommandPlaybacktutorial; +import de.scribble.lp.tasmod.savestates.server.SavestateHandler; import de.scribble.lp.tasmod.savestates.server.SavestateTrackerFile; import de.scribble.lp.tasmod.tickratechanger.CommandTickrate; import de.scribble.lp.tasmod.util.ModIncompatibleException; @@ -53,6 +54,8 @@ public class TASmod { public static final Logger logger = LogManager.getLogger("TASMod"); public static ContainerStateServer containerStateServer; + + public static SavestateHandler savestateHandler; @EventHandler public void preInit(FMLPreInitializationEvent ev) throws Exception { @@ -107,6 +110,8 @@ public void serverStart(FMLServerStartingEvent ev) { } catch (IOException e) { e.printStackTrace(); } + + savestateHandler=new SavestateHandler(ev.getServer()); } public static TASmod getInstance() { diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/GuiSavestateSavingScreen.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/GuiSavestateSavingScreen.java index 035b637e..fd21c174 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/GuiSavestateSavingScreen.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/GuiSavestateSavingScreen.java @@ -7,7 +7,12 @@ public class GuiSavestateSavingScreen extends GuiScreen{ - + @Override + public void initGui() { + this.mc=Minecraft.getMinecraft(); + super.initGui(); + } + @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.drawDefaultBackground(); diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java index daed6f0c..dfae6e84 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java @@ -1,5 +1,6 @@ package de.scribble.lp.tasmod.savestates.server; +import de.scribble.lp.tasmod.TASmod; import de.scribble.lp.tasmod.savestates.server.chunkloading.SavestatesChunkControl; import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException; import net.minecraft.client.Minecraft; @@ -22,7 +23,7 @@ public IMessage onMessage(LoadstatePacket message, MessageContext ctx) { return; } try { - SavestateHandler.loadState(); + TASmod.savestateHandler.loadState(); } catch (LoadstateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getMessage())); diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index 306392fe..30e1093a 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -3,6 +3,12 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; import org.apache.commons.io.FileUtils; @@ -16,10 +22,12 @@ import de.scribble.lp.tasmod.savestates.server.motion.ClientMotionServer; import de.scribble.lp.tasmod.savestates.server.playerloading.SavestatePlayerLoading; import de.scribble.lp.tasmod.tickratechanger.TickrateChangerServer; +import de.scribble.lp.tasmod.util.FileThread; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.PlayerList; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.WorldServer; @@ -37,11 +45,18 @@ * */ public class SavestateHandler { - private static MinecraftServer server=TASmod.getServerInstance(); - private static File savestateDirectory; + private MinecraftServer server; + private File savestateDirectory; public static SavestateState state=SavestateState.NONE; + public SavestateHandler(MinecraftServer server) { + this.server=server; + createSavestateDirectory(); + refreshSavestateMap(); + loadCurrentIndex(); + } + /** * Creates a copy of the currently played world and saves it in .minecraft/saves/savestates/worldname
* Called in {@link SavestatePacketHandler}
@@ -51,7 +66,7 @@ public class SavestateHandler { * @throws SavestateException * @throws IOException */ - public static void saveState(int savestateIndex) throws SavestateException, IOException { + public void saveState(int savestateIndex) throws SavestateException, IOException { if(state==SavestateState.SAVING) { throw new SavestateException("A savestating operation is already being carried out"); } @@ -64,6 +79,9 @@ public static void saveState(int savestateIndex) throws SavestateException, IOEx //Create a directory just in case createSavestateDirectory(); + increaseCurrentIndex(); + saveCurrentIndex(); + //Enable tickrate 0 TickrateChangerServer.changeServerTickrate(0); TickrateChangerServer.changeClientTickrate(0); @@ -109,20 +127,6 @@ public static void saveState(int savestateIndex) throws SavestateException, IOEx state=SavestateState.NONE; } - private static String nextSaveName(String worldname, int index) { - File[] listofFiles=savestateDirectory.listFiles(new FileFilter() { - - @Override - public boolean accept(File pathname) { - return pathname.getName().startsWith(worldname); - } - - }); - if(index<0) { - } - return ""; - } - /** * Searches through the savestate folder to look for the next possible savestate foldername
* Savestate equivalent to {@link SavestateHandler#getLatestSavestateLocation(String)} @@ -131,7 +135,7 @@ public boolean accept(File pathname) { * @throws SavestateException if the found savestates count is greater or equal than 300 */ @Deprecated - private static File getNextSaveFolderLocation(String worldname) throws SavestateException { + private File getNextSaveFolderLocation(String worldname) throws SavestateException { int i = 1; int limit=300; File targetsavefolder=null; @@ -156,7 +160,7 @@ private static File getNextSaveFolderLocation(String worldname) throws Savestate * @return The correct name of the next savestate */ @Deprecated - private static String nameWhenSaving(String worldname) { + private String nameWhenSaving(String worldname) { int i = 1; int limit=300; File targetsavefolder=null; @@ -183,7 +187,7 @@ private static String nameWhenSaving(String worldname) { * @throws LoadstateException * @throws IOException */ - public static void loadState() throws LoadstateException, IOException { + public void loadState() throws LoadstateException, IOException { if(state==SavestateState.SAVING) { throw new LoadstateException("A savestating operation is already being carried out"); } @@ -269,7 +273,7 @@ public static void loadState() throws LoadstateException, IOException { * @return targetsavefolder * @throws LoadstateException if there is no savestate or more than 300 savestates */ - private static File getLatestSavestateLocation(String worldname) throws LoadstateException { + private File getLatestSavestateLocation(String worldname) throws LoadstateException { int i=1; int limit=300; @@ -297,13 +301,13 @@ private static File getLatestSavestateLocation(String worldname) throws Loadstat * @param worldname the name of the world currently on the server * @return The correct name of the next loadstate */ - private static String nameWhenLoading(String worldname) throws LoadstateException { + private String nameWhenLoading(String worldname) throws LoadstateException { int i=1; int limit=300; String name=""; File targetsavefolder=null; while(i<=300) { - targetsavefolder = new File(savestateDirectory,worldname+"-Savestate"+Integer.toString(i)); + targetsavefolder = new File(savestateDirectory, worldname+"-Savestate"+Integer.toString(i)); if (!targetsavefolder.exists()) { if(i-1==0) { throw new LoadstateException("Couldn't find any savestates"); @@ -323,7 +327,7 @@ private static String nameWhenLoading(String worldname) throws LoadstateExceptio /** * Creates the savestate directory in case the user deletes it between savestates */ - private static void createSavestateDirectory() { + private void createSavestateDirectory() { if(!server.isDedicatedServer()) { savestateDirectory=new File(server.getDataDirectory()+File.separator+"saves"+File.separator+"savestates"+File.separator); }else { @@ -334,12 +338,100 @@ private static void createSavestateDirectory() { } } + private Map savestateMap=new HashMap(); + + private int nextFreeIndex=0; + + private int currentIndex; + + public void refreshSavestateMap() { + savestateMap.clear(); + File[] files=savestateDirectory.listFiles(new FileFilter() { + + @Override + public boolean accept(File pathname) { + return pathname.getName().startsWith(server.getFolderName()+"-Savestate"); + } + }); + int index=0; + for(File file:files) { + try { + index=Integer.parseInt(file.getName().substring(file.getName().length()-1)); + } catch (NumberFormatException e) { + TASmod.logger.warn(String.format("Could not process the savestate %s", e.getMessage())); + } + savestateMap.put(index, file); + } + nextFreeIndex=index+1; + } + + public void saveCurrentIndex() { + File tasmodDir=new File(savestateDirectory, "../"+server.getFolderName()+"/tasmod/"); + if(!tasmodDir.exists()) { + tasmodDir.mkdir(); + } + File savestateDat=new File(tasmodDir, "savestate.data"); + List lines=new ArrayList(); + lines.add("currentIndex="+currentIndex); + try { + FileUtils.writeLines(savestateDat, lines); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void loadCurrentIndex() { + int index = -1; + List lines = new ArrayList(); + File tasmodDir = new File(savestateDirectory, "../" + server.getFolderName() + "/tasmod/"); + if (!tasmodDir.exists()) { + tasmodDir.mkdir(); + } + File savestateDat = new File(tasmodDir, "savestate.data"); + try { + lines = FileUtils.readLines(savestateDat, StandardCharsets.UTF_8); + } catch (IOException e) { + TASmod.logger.warn("No savestate.data file found in current world folder, ignoring it"); + } + if (!lines.isEmpty()) { + for (String line : lines) { + if (line.startsWith("currentIndex=")) { + try { + index = Integer.parseInt(line.split("=")[1]); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + } + setCurrentIndex(index);; + } + + private void setCurrentIndex(int index) { + if(index<0) { + currentIndex=nextFreeIndex-1; + }else { + currentIndex=index; + } + TASmod.logger.info("Setting the savestate index to {}", currentIndex); + } + + public void increaseCurrentIndex() { + setCurrentIndex(currentIndex+1); + } + + private String getSavestateNameWithIndex(int index) { + return server.getFolderName()+File.separator+"Savestate"+index; + } + /** * Event, that gets executed after a loadstate operation was carried out, get's called on the server side */ public static void playerLoadSavestateEventServer() { - EntityPlayerMP player=server.getPlayerList().getPlayers().get(0); - NBTTagCompound nbttagcompound = server.getPlayerList().getPlayerNBT(player); + PlayerList playerList=TASmod.getServerInstance().getPlayerList(); + EntityPlayerMP player=playerList.getPlayers().get(0); + NBTTagCompound nbttagcompound = playerList.getPlayerNBT(player); + //TODO Make this multiplayer compatible ffs SavestatePlayerLoading.reattachEntityToPlayer(nbttagcompound, player.getServerWorld(), player); } @@ -347,4 +439,5 @@ public static void playerLoadSavestateEventServer() { public static void playerLoadSavestateEventClient() { SavestatesChunkControl.addPlayerToChunk(Minecraft.getMinecraft().player); } + } \ No newline at end of file diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java index f63bcd87..d090c133 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java @@ -1,5 +1,6 @@ package de.scribble.lp.tasmod.savestates.server; +import de.scribble.lp.tasmod.TASmod; import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.text.TextComponentString; @@ -30,7 +31,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) { return; } try { - SavestateHandler.saveState(-1); + TASmod.savestateHandler.saveState(-1); } catch (SavestateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to create a savestate: "+ e.getMessage())); From 3e8b068df9e8c2322004f546e64f06f435e0498a Mon Sep 17 00:00:00 2001 From: Scribble Date: Fri, 15 Oct 2021 00:07:46 +0200 Subject: [PATCH 05/12] Added a new savestate file management system Will enable loading savestates much more precise than before --- .../savestates/server/SavestateHandler.java | 502 ++++++++++-------- .../server/SavestatePacketHandler.java | 2 +- 2 files changed, 294 insertions(+), 210 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index 30e1093a..24f14438 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -5,10 +5,10 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; @@ -22,7 +22,6 @@ import de.scribble.lp.tasmod.savestates.server.motion.ClientMotionServer; import de.scribble.lp.tasmod.savestates.server.playerloading.SavestatePlayerLoading; import de.scribble.lp.tasmod.tickratechanger.TickrateChangerServer; -import de.scribble.lp.tasmod.util.FileThread; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; @@ -37,8 +36,11 @@ import net.minecraftforge.fml.relauncher.SideOnly; /** - * Creates and loads savestates on both client and server without closing the world
- * The old version that you may find in TASTools was heavily inspired by bspkrs' WorldStateCheckpoints, + * Creates and loads savestates on both client and server without closing the + * world
+ * The old version that you may find in TASTools was heavily inspired by bspkrs' + * WorldStateCheckpoints, * but this new version is completely self written. * * @author ScribbleLP @@ -47,104 +49,122 @@ public class SavestateHandler { private MinecraftServer server; private File savestateDirectory; - - public static SavestateState state=SavestateState.NONE; - + + public static SavestateState state = SavestateState.NONE; + public SavestateHandler(MinecraftServer server) { - this.server=server; + this.server = server; createSavestateDirectory(); - refreshSavestateMap(); - loadCurrentIndex(); + refresh(); + loadCurrentIndexFromFile(); } - + /** - * Creates a copy of the currently played world and saves it in .minecraft/saves/savestates/worldname
+ * Creates a copy of the currently played world and saves it in + * .minecraft/saves/savestates/worldname
* Called in {@link SavestatePacketHandler}
*
* Side: Server - * @param savestateIndex The index where the mod will save the savestate -1 if it should load the latest + * + * @param savestateIndex The index where the mod will save the savestate. -1 if + * it should load the latest * @throws SavestateException * @throws IOException */ public void saveState(int savestateIndex) throws SavestateException, IOException { - if(state==SavestateState.SAVING) { + if (state == SavestateState.SAVING) { throw new SavestateException("A savestating operation is already being carried out"); } - if(state==SavestateState.LOADING) { + if (state == SavestateState.LOADING) { throw new SavestateException("A loadstate operation is being carried out"); } - //Lock savestating and loadstating - state=SavestateState.SAVING; - - //Create a directory just in case + // Lock savestating and loadstating + state = SavestateState.SAVING; + + // Create a directory just in case createSavestateDirectory(); - - increaseCurrentIndex(); - saveCurrentIndex(); - - //Enable tickrate 0 + + // Enable tickrate 0 TickrateChangerServer.changeServerTickrate(0); TickrateChangerServer.changeClientTickrate(0); - - //Update the server variable - server=TASmod.getServerInstance(); - - //Get the motion from the client + + // Update the server variable + server = TASmod.getServerInstance(); + + // Get the motion from the client ClientMotionServer.requestMotionFromClient(); - - //Save the world! + + // Save the world! server.getPlayerList().saveAllPlayerData(); server.saveAllWorlds(true); - - - //Get the current and target directory for copying - String worldname=server.getFolderName(); - File currentfolder=new File(savestateDirectory,".."+File.separator+worldname); - File targetfolder=getNextSaveFolderLocation(worldname); - - //Send the name of the world to all players. This will make a savestate of the recording on the client with that name - CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(true, nameWhenSaving(worldname))); - - //Wait for the chunkloader to save the game - for(WorldServer world:server.worlds) { - AnvilChunkLoader chunkloader=(AnvilChunkLoader)world.getChunkProvider().chunkLoader; - while(chunkloader.getPendingSaveCount()>0) { + + if (savestateIndex < 0) { + setCurrentIndex(currentIndex + 1); + } else { + setCurrentIndex(savestateIndex); + } + + // Get the current and target directory for copying + String worldname = server.getFolderName(); + File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname); + File targetfolder = get(currentIndex); + + if (targetfolder.exists()) { + TASmod.logger.warn("WARNING! Overwriting the savestate with the index {}", currentIndex); + FileUtils.deleteDirectory(targetfolder); + } + + // Send the name of the world to all players. This will make a savestate of the + // recording on the client with that name + CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(true, getSavestateNameWithIndex(currentIndex))); + + // Wait for the chunkloader to save the game + for (WorldServer world : server.worlds) { + AnvilChunkLoader chunkloader = (AnvilChunkLoader) world.getChunkProvider().chunkLoader; + while (chunkloader.getPendingSaveCount() > 0) { } } - - //Copy the directory + + // Copy the directory FileUtils.copyDirectory(currentfolder, targetfolder); - - //Incrementing info file - SavestateTrackerFile tracker = new SavestateTrackerFile(new File(savestateDirectory, worldname+"-info.txt")); + + // Incrementing info file + SavestateTrackerFile tracker = new SavestateTrackerFile(new File(savestateDirectory, worldname + "-info.txt")); tracker.increaseSavestates(); tracker.saveFile(); - - //Close the GuiSavestateScreen on the client + + saveCurrentIndexToFile(); + + // Close the GuiSavestateScreen on the client CommonProxy.NETWORK.sendToAll(new SavestatePacket()); - - //Unlock savestating - state=SavestateState.NONE; + + // Unlock savestating + state = SavestateState.NONE; } - + /** - * Searches through the savestate folder to look for the next possible savestate foldername
- * Savestate equivalent to {@link SavestateHandler#getLatestSavestateLocation(String)} + * Searches through the savestate folder to look for the next possible savestate + * foldername
+ * Savestate equivalent to + * {@link SavestateHandler#getLatestSavestateLocation(String)} + * * @param worldname The worldname of the current world * @return targetsavefolder The file where the savestate should be copied to - * @throws SavestateException if the found savestates count is greater or equal than 300 + * @throws SavestateException if the found savestates count is greater or equal + * than 300 */ + @SuppressWarnings("unused") @Deprecated private File getNextSaveFolderLocation(String worldname) throws SavestateException { int i = 1; - int limit=300; - File targetsavefolder=null; + int limit = 300; + File targetsavefolder = null; while (i <= limit) { if (i >= limit) { - throw new SavestateException("Savestatecount is greater or equal than "+limit); + throw new SavestateException("Savestatecount is greater or equal than " + limit); } - targetsavefolder = new File(savestateDirectory,worldname + "-Savestate" + Integer.toString(i)+File.separator); - + targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i) + File.separator); + if (!targetsavefolder.exists()) { break; } @@ -152,26 +172,28 @@ private File getNextSaveFolderLocation(String worldname) throws SavestateExcepti } return targetsavefolder; } - + /** - * Get's the correct string of the savestate, used in {@linkplain InputSavestatesHandler#savestate(String)} + * Get's the correct string of the savestate, used in + * {@linkplain InputSavestatesHandler#savestate(String)} * * @param worldname the name of the world currently on the server * @return The correct name of the next savestate */ + @SuppressWarnings("unused") @Deprecated private String nameWhenSaving(String worldname) { int i = 1; - int limit=300; - File targetsavefolder=null; - String name=""; + int limit = 300; + File targetsavefolder = null; + String name = ""; while (i <= limit) { if (i >= limit) { break; } - name=worldname + "-Savestate" + Integer.toString(i); - targetsavefolder = new File(savestateDirectory,name+File.separator); - + name = worldname + "-Savestate" + Integer.toString(i); + targetsavefolder = new File(savestateDirectory, name + File.separator); + if (!targetsavefolder.exists()) { break; } @@ -179,144 +201,163 @@ private String nameWhenSaving(String worldname) { } return name; } - + /** - * Loads the latest savestate it can find in .minecraft/saves/savestates/worldname-Savestate + * Loads the latest savestate it can find in + * .minecraft/saves/savestates/worldname-Savestate * * Side: Server + * * @throws LoadstateException * @throws IOException */ - public void loadState() throws LoadstateException, IOException { - if(state==SavestateState.SAVING) { + public void loadState(int savestateIndex) throws LoadstateException, IOException { + if (state == SavestateState.SAVING) { throw new LoadstateException("A savestating operation is already being carried out"); } - if(state==SavestateState.LOADING) { + if (state == SavestateState.LOADING) { throw new LoadstateException("A loadstate operation is being carried out"); } - //Lock savestating and loadstating - state=SavestateState.LOADING; - - //Create a directory just in case + // Lock savestating and loadstating + state = SavestateState.LOADING; + + // Create a directory just in case createSavestateDirectory(); - - //Enable tickrate 0 + + // Enable tickrate 0 TickrateChangerServer.changeServerTickrate(0); TickrateChangerServer.changeClientTickrate(0); - - - //Update the server instance - server=TASmod.getServerInstance(); - - //Get the current and target directory for copying - String worldname=server.getFolderName(); - File currentfolder=new File(savestateDirectory,".."+File.separator+worldname); - File targetfolder=getLatestSavestateLocation(worldname); - - //Load savestate on the client - CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, nameWhenLoading(worldname))); - - //Disabeling level saving for all worlds in case the auto save kicks in during world unload - for(WorldServer world: server.worlds) { - world.disableLevelSaving=true; + + // Update the server instance + server = TASmod.getServerInstance(); + + if (savestateIndex < 0) { + setCurrentIndex(currentIndex); + } else { + setCurrentIndex(savestateIndex); + } + + // Get the current and target directory for copying + String worldname = server.getFolderName(); + File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname); + File targetfolder = get(currentIndex); + + if (!targetfolder.exists()) { + throw new LoadstateException("The savestate to load doesn't exist"); } - - //Unload chunks on the client + + // Load savestate on the client + CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, getSavestateNameWithIndex(currentIndex))); + + // Disabeling level saving for all worlds in case the auto save kicks in during + // world unload + for (WorldServer world : server.worlds) { + world.disableLevelSaving = true; + } + + // Unload chunks on the client CommonProxy.NETWORK.sendToAll(new LoadstatePacket()); - - //Unload chunks on the server + + // Unload chunks on the server SavestatesChunkControl.disconnectPlayersFromChunkMap(); SavestatesChunkControl.unloadAllServerChunks(); SavestatesChunkControl.flushSaveHandler(); - - - //Delete and copy directories + + // Delete and copy directories FileUtils.deleteDirectory(currentfolder); FileUtils.copyDirectory(targetfolder, currentfolder); - - - //Update the player and the client + + // Update the player and the client SavestatePlayerLoading.loadAndSendMotionToPlayer(); - //Update the session.lock file so minecraft behaves and saves the world + // Update the session.lock file so minecraft behaves and saves the world SavestatesChunkControl.updateSessionLock(); - //Load the chunks and send them to the client + // Load the chunks and send them to the client SavestatesChunkControl.addPlayersToChunkMap(); - - - //Enable level saving again - for(WorldServer world: server.worlds) { - world.disableLevelSaving=false; + + // Enable level saving again + for (WorldServer world : server.worlds) { + world.disableLevelSaving = false; } - - //Incrementing info file - SavestateTrackerFile tracker = new SavestateTrackerFile(new File(savestateDirectory, worldname+"-info.txt")); + + // Incrementing info file + SavestateTrackerFile tracker = new SavestateTrackerFile(new File(savestateDirectory, worldname + "-info.txt")); tracker.increaseRerecords(); tracker.saveFile(); - - //Send a notification that the savestate has been loaded - server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN+"Savestate loaded")); - + + saveCurrentIndexToFile(); + + // Send a notification that the savestate has been loaded + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate loaded")); + WorldServer[] worlds = DimensionManager.getWorlds(); - - for(WorldServer world : worlds) { - world.tick(); - } - - //Unlock loadstating - state=SavestateState.WASLOADING; + + for (WorldServer world : worlds) { + world.tick(); + } + + // Unlock loadstating + state = SavestateState.WASLOADING; } - + /** * Searches through the savestate folder to look for the latest savestate
- * Loadstate equivalent to {@link SavestateHandler#getNextSaveFolderLocation(String)} + * Loadstate equivalent to + * {@link SavestateHandler#getNextSaveFolderLocation(String)} + * * @param worldname * @return targetsavefolder - * @throws LoadstateException if there is no savestate or more than 300 savestates + * @throws LoadstateException if there is no savestate or more than 300 + * savestates */ + @SuppressWarnings("unused") + @Deprecated private File getLatestSavestateLocation(String worldname) throws LoadstateException { - int i=1; - int limit=300; - - File targetsavefolder=null; - while(i<=300) { - targetsavefolder = new File(savestateDirectory,worldname+"-Savestate"+Integer.toString(i)); + int i = 1; + int limit = 300; + + File targetsavefolder = null; + while (i <= 300) { + targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i)); if (!targetsavefolder.exists()) { - if(i-1==0) { + if (i - 1 == 0) { throw new LoadstateException("Couldn't find any savestates"); } - if(i>300) { - throw new LoadstateException("Savestatecount is greater or equal than "+limit); + if (i > 300) { + throw new LoadstateException("Savestatecount is greater or equal than " + limit); } - targetsavefolder = new File(savestateDirectory,worldname+"-Savestate"+Integer.toString(i-1)); + targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i - 1)); break; } i++; } return targetsavefolder; } - + /** - * Get's the correct string of the loadstate, used in {@linkplain InputSavestatesHandler#loadstate(String)} + * Get's the correct string of the loadstate, used in + * {@linkplain InputSavestatesHandler#loadstate(String)} * * @param worldname the name of the world currently on the server * @return The correct name of the next loadstate */ + @SuppressWarnings("unused") + @Deprecated private String nameWhenLoading(String worldname) throws LoadstateException { - int i=1; - int limit=300; - String name=""; - File targetsavefolder=null; - while(i<=300) { - targetsavefolder = new File(savestateDirectory, worldname+"-Savestate"+Integer.toString(i)); + int i = 1; + int limit = 300; + String name = ""; + File targetsavefolder = null; + while (i <= 300) { + targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i)); if (!targetsavefolder.exists()) { - if(i-1==0) { + if (i - 1 == 0) { throw new LoadstateException("Couldn't find any savestates"); } - if(i>300) { - throw new LoadstateException("Savestatecount is greater or equal than "+limit); + if (i > 300) { + throw new LoadstateException("Savestatecount is greater or equal than " + limit); } - - name=worldname+"-Savestate"+Integer.toString(i-1); + + name = worldname + "-Savestate" + Integer.toString(i - 1); break; } i++; @@ -325,62 +366,100 @@ private String nameWhenLoading(String worldname) throws LoadstateException { } /** - * Creates the savestate directory in case the user deletes it between savestates + * Creates the savestate directory in case the user deletes it between + * savestates */ private void createSavestateDirectory() { - if(!server.isDedicatedServer()) { - savestateDirectory=new File(server.getDataDirectory()+File.separator+"saves"+File.separator+"savestates"+File.separator); - }else { - savestateDirectory=new File(server.getDataDirectory()+File.separator+"savestates"+File.separator); + if (!server.isDedicatedServer()) { + savestateDirectory = new File(server.getDataDirectory() + File.separator + "saves" + File.separator + "savestates" + File.separator); + } else { + savestateDirectory = new File(server.getDataDirectory() + File.separator + "savestates" + File.separator); } - if(!savestateDirectory.exists()) { + if (!savestateDirectory.exists()) { savestateDirectory.mkdir(); } } - - private Map savestateMap=new HashMap(); - - private int nextFreeIndex=0; - + + private final List indexList = new ArrayList<>(); + + private int nextFreeIndex = 0; + private int currentIndex; - - public void refreshSavestateMap() { - savestateMap.clear(); - File[] files=savestateDirectory.listFiles(new FileFilter() { - + + private void refresh() { + indexList.clear(); + File[] files = savestateDirectory.listFiles(new FileFilter() { + @Override public boolean accept(File pathname) { - return pathname.getName().startsWith(server.getFolderName()+"-Savestate"); + return pathname.getName().startsWith(server.getFolderName() + "-Savestate"); } + }); - int index=0; - for(File file:files) { + int index = 0; + for (File file : files) { try { - index=Integer.parseInt(file.getName().substring(file.getName().length()-1)); + Pattern patt = Pattern.compile("\\d+$"); + Matcher matcher = patt.matcher(file.getName()); + if (matcher.find()) { + index = Integer.parseInt(matcher.group(0)); + } else { + TASmod.logger.warn(String.format("Could not process the savestate %s", file.getName())); + continue; + } } catch (NumberFormatException e) { TASmod.logger.warn(String.format("Could not process the savestate %s", e.getMessage())); + continue; } - savestateMap.put(index, file); + indexList.add(index); + } + Collections.sort(indexList); + if (indexList.isEmpty()) { + indexList.add(1); } - nextFreeIndex=index+1; + nextFreeIndex = indexList.get(indexList.size() - 1); } - - public void saveCurrentIndex() { - File tasmodDir=new File(savestateDirectory, "../"+server.getFolderName()+"/tasmod/"); - if(!tasmodDir.exists()) { + + public void deleteIndex(int index) { + if (index < 0) { + return; + } + File toDelete = get(index); + if (toDelete.exists()) { + try { + FileUtils.deleteDirectory(toDelete); + } catch (IOException e) { + e.printStackTrace(); + } + } + refresh(); + } + + public List getIndexes() { + refresh(); + return indexList; + } + + private File get(int index) { + return new File(savestateDirectory, getSavestateNameWithIndex(index)); + } + + private void saveCurrentIndexToFile() { + File tasmodDir = new File(savestateDirectory, "../" + server.getFolderName() + "/tasmod/"); + if (!tasmodDir.exists()) { tasmodDir.mkdir(); } - File savestateDat=new File(tasmodDir, "savestate.data"); - List lines=new ArrayList(); - lines.add("currentIndex="+currentIndex); + File savestateDat = new File(tasmodDir, "savestate.data"); + List lines = new ArrayList(); + lines.add("currentIndex=" + currentIndex); try { FileUtils.writeLines(savestateDat, lines); } catch (IOException e) { e.printStackTrace(); } } - - public void loadCurrentIndex() { + + public void loadCurrentIndexFromFile() { int index = -1; List lines = new ArrayList(); File tasmodDir = new File(savestateDirectory, "../" + server.getFolderName() + "/tasmod/"); @@ -404,40 +483,45 @@ public void loadCurrentIndex() { } } } - setCurrentIndex(index);; + setCurrentIndex(index); + ; } private void setCurrentIndex(int index) { - if(index<0) { - currentIndex=nextFreeIndex-1; - }else { - currentIndex=index; + if (index < 0) { + currentIndex = nextFreeIndex - 1; + } else { + currentIndex = index; } TASmod.logger.info("Setting the savestate index to {}", currentIndex); } - - public void increaseCurrentIndex() { - setCurrentIndex(currentIndex+1); - } - + private String getSavestateNameWithIndex(int index) { - return server.getFolderName()+File.separator+"Savestate"+index; + return server.getFolderName() + "-Savestate" + index; } - + /** - * Event, that gets executed after a loadstate operation was carried out, get's called on the server side + * Event, that gets executed after a loadstate operation was carried out, get's + * called on the server side */ public static void playerLoadSavestateEventServer() { - PlayerList playerList=TASmod.getServerInstance().getPlayerList(); - EntityPlayerMP player=playerList.getPlayers().get(0); - NBTTagCompound nbttagcompound = playerList.getPlayerNBT(player); - //TODO Make this multiplayer compatible ffs - SavestatePlayerLoading.reattachEntityToPlayer(nbttagcompound, player.getServerWorld(), player); + PlayerList playerList = TASmod.getServerInstance().getPlayerList(); + for (EntityPlayerMP player : playerList.getPlayers()) { + NBTTagCompound nbttagcompound = playerList.getPlayerNBT(player); + SavestatePlayerLoading.reattachEntityToPlayer(nbttagcompound, player.getServerWorld(), player); + } } - + @SideOnly(Side.CLIENT) public static void playerLoadSavestateEventClient() { SavestatesChunkControl.addPlayerToChunk(Minecraft.getMinecraft().player); } - + + public void loadState() throws LoadstateException, IOException { + loadState(-1); + } + + public void saveState() throws SavestateException, IOException { + saveState(-1); + } } \ No newline at end of file diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java index d090c133..057213bf 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java @@ -31,7 +31,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) { return; } try { - TASmod.savestateHandler.saveState(-1); + TASmod.savestateHandler.saveState(); } catch (SavestateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to create a savestate: "+ e.getMessage())); From 7dd79562898860a87b3395fdadc33ef52aad2d19 Mon Sep 17 00:00:00 2001 From: Scribble Date: Sat, 16 Oct 2021 00:15:47 +0200 Subject: [PATCH 06/12] Added savestate command for #112 --- .../java/de/scribble/lp/tasmod/TASmod.java | 2 + .../lp/tasmod/mixin/MixinMinecraftServer.java | 4 +- .../server/LoadstatePacketHandler.java | 3 +- .../savestates/server/SavestateCommand.java | 153 ++++++++++++++++++ .../savestates/server/SavestateHandler.java | 57 +++++-- .../server/SavestatePacketHandler.java | 2 +- .../exceptions/SavestateDeleteException.java | 12 ++ 7 files changed, 212 insertions(+), 21 deletions(-) create mode 100644 src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java create mode 100644 src/main/java/de/scribble/lp/tasmod/savestates/server/exceptions/SavestateDeleteException.java diff --git a/src/main/java/de/scribble/lp/tasmod/TASmod.java b/src/main/java/de/scribble/lp/tasmod/TASmod.java index 14120520..68528e83 100644 --- a/src/main/java/de/scribble/lp/tasmod/TASmod.java +++ b/src/main/java/de/scribble/lp/tasmod/TASmod.java @@ -15,6 +15,7 @@ import de.scribble.lp.tasmod.commands.recording.CommandRecord; import de.scribble.lp.tasmod.commands.savetas.CommandSaveTAS; import de.scribble.lp.tasmod.commands.tutorial.CommandPlaybacktutorial; +import de.scribble.lp.tasmod.savestates.server.SavestateCommand; import de.scribble.lp.tasmod.savestates.server.SavestateHandler; import de.scribble.lp.tasmod.savestates.server.SavestateTrackerFile; import de.scribble.lp.tasmod.tickratechanger.CommandTickrate; @@ -102,6 +103,7 @@ public void serverStart(FMLServerStartingEvent ev) { ev.registerServerCommand(new CommandPlaybacktutorial()); ev.registerServerCommand(new CommandFolder()); ev.registerServerCommand(new CommandClearInputs()); + ev.registerServerCommand(new SavestateCommand()); // Save Loadstate Count File savestateDirectory = new File(serverInstance.getDataDirectory() + File.separator + "saves" + File.separator + "savestates" + File.separator); diff --git a/src/main/java/de/scribble/lp/tasmod/mixin/MixinMinecraftServer.java b/src/main/java/de/scribble/lp/tasmod/mixin/MixinMinecraftServer.java index cf3a34a7..db9bad61 100644 --- a/src/main/java/de/scribble/lp/tasmod/mixin/MixinMinecraftServer.java +++ b/src/main/java/de/scribble/lp/tasmod/mixin/MixinMinecraftServer.java @@ -37,8 +37,8 @@ public long modifyMSPT(long fiftyLong) { @Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tick()V", ordinal = 1)) public void redirectTick(MinecraftServer server) { this.tick(); - if (SavestateHandler.state == SavestateState.WASLOADING) { - SavestateHandler.state = SavestateState.NONE; + if (TASmod.savestateHandler.state == SavestateState.WASLOADING) { + TASmod.savestateHandler.state = SavestateState.NONE; SavestateHandler.playerLoadSavestateEventServer(); } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java index dfae6e84..0059c29d 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java @@ -26,12 +26,11 @@ public IMessage onMessage(LoadstatePacket message, MessageContext ctx) { TASmod.savestateHandler.loadState(); } catch (LoadstateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getMessage())); - } catch (Exception e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getCause().toString())); e.printStackTrace(); } finally { - SavestateHandler.state=SavestateState.NONE; + TASmod.savestateHandler.state=SavestateState.NONE; } }); }else { diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java new file mode 100644 index 00000000..4fa8f470 --- /dev/null +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java @@ -0,0 +1,153 @@ +package de.scribble.lp.tasmod.savestates.server; + +import java.io.IOException; +import java.util.List; + +import de.scribble.lp.tasmod.TASmod; +import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException; +import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateDeleteException; +import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentString; + +public class SavestateCommand extends CommandBase { + + @Override + public String getName() { + return "savestate"; + } + + @Override + public String getUsage(ICommandSender sender) { + return "/savestate [index]"; + } + + @Override + public int getRequiredPermissionLevel() { + return 2; + } + + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + if (args.length == 0) { + int currentIndex = TASmod.savestateHandler.getCurrentIndex(); + sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", currentIndex))); + sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString()))); + sender.sendMessage(new TextComponentString(" ")); + sender.sendMessage(new TextComponentString("/savestate [index]")); + sender.sendMessage(new TextComponentString("/savestate save - Make a savestate at the next index")); + sender.sendMessage(new TextComponentString("/savestate save - Make a savestate at the specified index")); + sender.sendMessage(new TextComponentString("/savestate load - Load the savestate at the current index")); + sender.sendMessage(new TextComponentString("/savestate load - Load the savestate at the specified index")); + sender.sendMessage(new TextComponentString("/savestate delete - Delete the savestate at the specified index")); + sender.sendMessage(new TextComponentString("/savestate delete - Delete the savestates from the first to the second index")); + sender.sendMessage(new TextComponentString("")); + sender.sendMessage(new TextComponentString("Instead of you can use ~ to specify an index relative to the current one e.g. ~-1 will load " + (currentIndex - 1))); + } else if (args.length >= 1) { + if ("save".equals(args[0])) { + if (args.length == 1) { + try { + TASmod.savestateHandler.saveState(); + } catch (SavestateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } else if (args.length == 2) { + try { + TASmod.savestateHandler.saveState(processIndex(args[1])); + } catch (SavestateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } else { + throw new CommandException("Too many arguments!", new Object[] {}); + } + } else if ("load".equals(args[0])) { + if (args.length == 1) { + try { + TASmod.savestateHandler.loadState(); + } catch (LoadstateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } else if (args.length == 2) { + try { + TASmod.savestateHandler.loadState(processIndex(args[1])); + } catch (LoadstateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } else { + throw new CommandException("Too many arguments!", new Object[] {}); + } + } else if ("delete".equals(args[0])) { + if (args.length == 2) { + try { + TASmod.savestateHandler.deleteIndex(processIndex(args[1])); + } catch (SavestateDeleteException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } + } else if (args.length == 3) { + try { + TASmod.savestateHandler.deleteIndex(processIndex(args[1]), processIndex(args[2])); + } catch (SavestateDeleteException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } + } else { + throw new CommandException("Too many arguments!", new Object[] {}); + } + } else if ("info".equals(args[0])) { + sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", TASmod.savestateHandler.getCurrentIndex()))); + sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString()))); + } + } + } + + private int processIndex(String arg) throws CommandException { + if ("~".equals(arg)) { + return TASmod.savestateHandler.getCurrentIndex(); + } else if (arg.matches("~-?\\d")) { + arg = arg.replace("~", ""); + int i = Integer.parseInt(arg); + return TASmod.savestateHandler.getCurrentIndex() + i; + } else { + int i = 0; + try { + i = Integer.parseInt(arg); + } catch (NumberFormatException e) { + throw new CommandException("The specified index is not a number: %s", arg); + } + return i; + } + } + + @Override + public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) { + if (args.length == 1) { + return getListOfStringsMatchingLastWord(args, new String[] { "save", "load", "delete", "info" }); + } else if (args.length == 2 && !"info".equals(args[0])) { + sender.sendMessage(new TextComponentString("Available indexes: " + TASmod.savestateHandler.getIndexesAsString())); + } + return super.getTabCompletions(server, sender, args, targetPos); + } +} diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index 24f14438..c19882a2 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -18,6 +18,7 @@ import de.scribble.lp.tasmod.savestates.client.InputSavestatesPacket; import de.scribble.lp.tasmod.savestates.server.chunkloading.SavestatesChunkControl; import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException; +import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateDeleteException; import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException; import de.scribble.lp.tasmod.savestates.server.motion.ClientMotionServer; import de.scribble.lp.tasmod.savestates.server.playerloading.SavestatePlayerLoading; @@ -50,7 +51,7 @@ public class SavestateHandler { private MinecraftServer server; private File savestateDirectory; - public static SavestateState state = SavestateState.NONE; + public SavestateState state = SavestateState.NONE; public SavestateHandler(MinecraftServer server) { this.server = server; @@ -66,8 +67,9 @@ public SavestateHandler(MinecraftServer server) { *
* Side: Server * - * @param savestateIndex The index where the mod will save the savestate. -1 if - * it should load the latest + * @param savestateIndex The index where the mod will save the savestate. + * index<=0 if it should load the next from the + * currentindex * @throws SavestateException * @throws IOException */ @@ -98,7 +100,7 @@ public void saveState(int savestateIndex) throws SavestateException, IOException server.getPlayerList().saveAllPlayerData(); server.saveAllWorlds(true); - if (savestateIndex < 0) { + if (savestateIndex <= 0) { setCurrentIndex(currentIndex + 1); } else { setCurrentIndex(savestateIndex); @@ -135,6 +137,9 @@ public void saveState(int savestateIndex) throws SavestateException, IOException saveCurrentIndexToFile(); + // Send a notification that the savestate has been loaded + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + currentIndex + " saved")); + // Close the GuiSavestateScreen on the client CommonProxy.NETWORK.sendToAll(new SavestatePacket()); @@ -234,6 +239,9 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException if (savestateIndex < 0) { setCurrentIndex(currentIndex); } else { + if (!get(savestateIndex).exists()) { + throw new LoadstateException("The savestate to load doesn't exist"); + } setCurrentIndex(savestateIndex); } @@ -242,10 +250,6 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname); File targetfolder = get(currentIndex); - if (!targetfolder.exists()) { - throw new LoadstateException("The savestate to load doesn't exist"); - } - // Load savestate on the client CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, getSavestateNameWithIndex(currentIndex))); @@ -287,7 +291,7 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException saveCurrentIndexToFile(); // Send a notification that the savestate has been loaded - server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate loaded")); + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + currentIndex + " loaded")); WorldServer[] worlds = DimensionManager.getWorlds(); @@ -415,14 +419,14 @@ public boolean accept(File pathname) { } Collections.sort(indexList); if (indexList.isEmpty()) { - indexList.add(1); + indexList.add(0); } nextFreeIndex = indexList.get(indexList.size() - 1); } - public void deleteIndex(int index) { - if (index < 0) { - return; + public void deleteIndex(int index) throws SavestateDeleteException { + if (index <= 0) { + throw new SavestateDeleteException("Cannot delete the indexes below or exactly 0: " + index); } File toDelete = get(index); if (toDelete.exists()) { @@ -433,11 +437,20 @@ public void deleteIndex(int index) { } } refresh(); + if(!indexList.contains(currentIndex)) { + setCurrentIndex(nextFreeIndex); + } + // Send a notification that the savestate has been deleted + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + index + " deleted")); } - public List getIndexes() { + public String getIndexesAsString() { refresh(); - return indexList; + String out = ""; + for (int i : indexList) { + out = out.concat(" " + i + ","); + } + return out; } private File get(int index) { @@ -484,7 +497,6 @@ public void loadCurrentIndexFromFile() { } } setCurrentIndex(index); - ; } private void setCurrentIndex(int index) { @@ -500,6 +512,10 @@ private String getSavestateNameWithIndex(int index) { return server.getFolderName() + "-Savestate" + index; } + public int getCurrentIndex() { + return currentIndex; + } + /** * Event, that gets executed after a loadstate operation was carried out, get's * called on the server side @@ -524,4 +540,13 @@ public void loadState() throws LoadstateException, IOException { public void saveState() throws SavestateException, IOException { saveState(-1); } + + public void deleteIndex(int from, int to) throws SavestateDeleteException { + if (from >= to) { + throw new SavestateDeleteException("The 'from-index' is smaller or equal to the 'to-index'"); + } + for (int i = from; i < to; i++) { + deleteIndex(i); + } + } } \ No newline at end of file diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java index 057213bf..c24131c4 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java @@ -39,7 +39,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) { e.printStackTrace(); player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to create a savestate: "+ e.getCause().toString())); } finally { - SavestateHandler.state=SavestateState.NONE; + TASmod.savestateHandler.state=SavestateState.NONE; } }); }else { diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/exceptions/SavestateDeleteException.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/exceptions/SavestateDeleteException.java new file mode 100644 index 00000000..c3877f1f --- /dev/null +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/exceptions/SavestateDeleteException.java @@ -0,0 +1,12 @@ +package de.scribble.lp.tasmod.savestates.server.exceptions; + +public class SavestateDeleteException extends Exception { + /** + * + */ + private static final long serialVersionUID = -3117656644168896404L; + + public SavestateDeleteException(String s) { + super(s); + } +} From cbebcaff35a1510c3259535867497f792b9781cc Mon Sep 17 00:00:00 2001 From: Scribble Date: Mon, 18 Oct 2021 23:55:33 +0200 Subject: [PATCH 07/12] Trying to fix indexing and deleting savestates --- .../savestates/server/SavestateHandler.java | 147 ++---------------- 1 file changed, 11 insertions(+), 136 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index c19882a2..b9ade5ed 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -147,66 +147,6 @@ public void saveState(int savestateIndex) throws SavestateException, IOException state = SavestateState.NONE; } - /** - * Searches through the savestate folder to look for the next possible savestate - * foldername
- * Savestate equivalent to - * {@link SavestateHandler#getLatestSavestateLocation(String)} - * - * @param worldname The worldname of the current world - * @return targetsavefolder The file where the savestate should be copied to - * @throws SavestateException if the found savestates count is greater or equal - * than 300 - */ - @SuppressWarnings("unused") - @Deprecated - private File getNextSaveFolderLocation(String worldname) throws SavestateException { - int i = 1; - int limit = 300; - File targetsavefolder = null; - while (i <= limit) { - if (i >= limit) { - throw new SavestateException("Savestatecount is greater or equal than " + limit); - } - targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i) + File.separator); - - if (!targetsavefolder.exists()) { - break; - } - i++; - } - return targetsavefolder; - } - - /** - * Get's the correct string of the savestate, used in - * {@linkplain InputSavestatesHandler#savestate(String)} - * - * @param worldname the name of the world currently on the server - * @return The correct name of the next savestate - */ - @SuppressWarnings("unused") - @Deprecated - private String nameWhenSaving(String worldname) { - int i = 1; - int limit = 300; - File targetsavefolder = null; - String name = ""; - while (i <= limit) { - if (i >= limit) { - break; - } - name = worldname + "-Savestate" + Integer.toString(i); - targetsavefolder = new File(savestateDirectory, name + File.separator); - - if (!targetsavefolder.exists()) { - break; - } - i++; - } - return name; - } - /** * Loads the latest savestate it can find in * .minecraft/saves/savestates/worldname-Savestate @@ -236,12 +176,9 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException // Update the server instance server = TASmod.getServerInstance(); - if (savestateIndex < 0) { - setCurrentIndex(currentIndex); + if (!get(savestateIndex).exists()) { + throw new LoadstateException("The savestate to load doesn't exist"); } else { - if (!get(savestateIndex).exists()) { - throw new LoadstateException("The savestate to load doesn't exist"); - } setCurrentIndex(savestateIndex); } @@ -303,72 +240,6 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException state = SavestateState.WASLOADING; } - /** - * Searches through the savestate folder to look for the latest savestate
- * Loadstate equivalent to - * {@link SavestateHandler#getNextSaveFolderLocation(String)} - * - * @param worldname - * @return targetsavefolder - * @throws LoadstateException if there is no savestate or more than 300 - * savestates - */ - @SuppressWarnings("unused") - @Deprecated - private File getLatestSavestateLocation(String worldname) throws LoadstateException { - int i = 1; - int limit = 300; - - File targetsavefolder = null; - while (i <= 300) { - targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i)); - if (!targetsavefolder.exists()) { - if (i - 1 == 0) { - throw new LoadstateException("Couldn't find any savestates"); - } - if (i > 300) { - throw new LoadstateException("Savestatecount is greater or equal than " + limit); - } - targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i - 1)); - break; - } - i++; - } - return targetsavefolder; - } - - /** - * Get's the correct string of the loadstate, used in - * {@linkplain InputSavestatesHandler#loadstate(String)} - * - * @param worldname the name of the world currently on the server - * @return The correct name of the next loadstate - */ - @SuppressWarnings("unused") - @Deprecated - private String nameWhenLoading(String worldname) throws LoadstateException { - int i = 1; - int limit = 300; - String name = ""; - File targetsavefolder = null; - while (i <= 300) { - targetsavefolder = new File(savestateDirectory, worldname + "-Savestate" + Integer.toString(i)); - if (!targetsavefolder.exists()) { - if (i - 1 == 0) { - throw new LoadstateException("Couldn't find any savestates"); - } - if (i > 300) { - throw new LoadstateException("Savestatecount is greater or equal than " + limit); - } - - name = worldname + "-Savestate" + Integer.toString(i - 1); - break; - } - i++; - } - return name; - } - /** * Creates the savestate directory in case the user deletes it between * savestates @@ -386,7 +257,7 @@ private void createSavestateDirectory() { private final List indexList = new ArrayList<>(); - private int nextFreeIndex = 0; + private int latestIndex = 0; private int currentIndex; @@ -421,7 +292,8 @@ public boolean accept(File pathname) { if (indexList.isEmpty()) { indexList.add(0); } - nextFreeIndex = indexList.get(indexList.size() - 1); + latestIndex = indexList.get(indexList.size() - 1); + System.out.println("LatestIndex: " + latestIndex); } public void deleteIndex(int index) throws SavestateDeleteException { @@ -435,10 +307,13 @@ public void deleteIndex(int index) throws SavestateDeleteException { } catch (IOException e) { e.printStackTrace(); } + } else { + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.YELLOW + "Savestate " + index + " doesn't exist so it can't be deleted")); + return; } refresh(); - if(!indexList.contains(currentIndex)) { - setCurrentIndex(nextFreeIndex); + if (!indexList.contains(currentIndex)) { + setCurrentIndex(latestIndex); } // Send a notification that the savestate has been deleted server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + index + " deleted")); @@ -501,7 +376,7 @@ public void loadCurrentIndexFromFile() { private void setCurrentIndex(int index) { if (index < 0) { - currentIndex = nextFreeIndex - 1; + currentIndex = latestIndex - 1; } else { currentIndex = index; } From 547b01fd9e41542de16edf8738f8dc13845cf205 Mon Sep 17 00:00:00 2001 From: Scribble Date: Tue, 19 Oct 2021 17:01:46 +0200 Subject: [PATCH 08/12] =?UTF-8?q?Fixing=20things=20with=20indexes=20and=20?= =?UTF-8?q?documentation=20=F0=9F=9A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../savestates/server/SavestateCommand.java | 4 +- .../savestates/server/SavestateHandler.java | 180 ++++++++++++------ 2 files changed, 127 insertions(+), 57 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java index 4fa8f470..36c756a1 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java @@ -103,13 +103,13 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args } else if ("delete".equals(args[0])) { if (args.length == 2) { try { - TASmod.savestateHandler.deleteIndex(processIndex(args[1])); + TASmod.savestateHandler.deleteSavestate(processIndex(args[1])); } catch (SavestateDeleteException e) { throw new CommandException(e.getMessage(), new Object[] {}); } } else if (args.length == 3) { try { - TASmod.savestateHandler.deleteIndex(processIndex(args[1]), processIndex(args[2])); + TASmod.savestateHandler.deleteSavestate(processIndex(args[1]), processIndex(args[2])); } catch (SavestateDeleteException e) { throw new CommandException(e.getMessage(), new Object[] {}); } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index b9ade5ed..f9d5d61c 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -14,7 +14,6 @@ import de.scribble.lp.tasmod.CommonProxy; import de.scribble.lp.tasmod.TASmod; -import de.scribble.lp.tasmod.savestates.client.InputSavestatesHandler; import de.scribble.lp.tasmod.savestates.client.InputSavestatesPacket; import de.scribble.lp.tasmod.savestates.server.chunkloading.SavestatesChunkControl; import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException; @@ -48,11 +47,22 @@ * */ public class SavestateHandler { + private MinecraftServer server; private File savestateDirectory; public SavestateState state = SavestateState.NONE; + private final List indexList = new ArrayList<>(); + + private int latestIndex = 0; + private int currentIndex; + + /** + * Creates a savestate handler on the specified server + * + * @param The server that should store the savestates + */ public SavestateHandler(MinecraftServer server) { this.server = server; createSavestateDirectory(); @@ -61,15 +71,28 @@ public SavestateHandler(MinecraftServer server) { } /** - * Creates a copy of the currently played world and saves it in - * .minecraft/saves/savestates/worldname
- * Called in {@link SavestatePacketHandler}
+ * Creates a copy of the world that is currently being played and saves it in + * .minecraft/saves/savestates/worldname-Savestate[{@linkplain #currentIndex}+1] + *
+ *
+ * Side: Server + * + * @throws SavestateException + * @throws IOException + */ + public void saveState() throws SavestateException, IOException { + saveState(-1); + } + + /** + * Creates a copy of the world that is currently being played and saves it in + * .minecraft/saves/savestates/worldname-Savestate[savestateIndex]
*
* Side: Server * * @param savestateIndex The index where the mod will save the savestate. - * index<=0 if it should load the next from the - * currentindex + * index<=0 if it should save it in the next index from + * the currentindex * @throws SavestateException * @throws IOException */ @@ -100,8 +123,12 @@ public void saveState(int savestateIndex) throws SavestateException, IOException server.getPlayerList().saveAllPlayerData(); server.saveAllWorlds(true); + // Refreshing the index list + refresh(); + + // Setting the current index depending on the savestateIndex. if (savestateIndex <= 0) { - setCurrentIndex(currentIndex + 1); + setCurrentIndex(currentIndex + 1); // If the savestateIndex <= 0, create a savestate at currentIndex+1 } else { setCurrentIndex(savestateIndex); } @@ -109,7 +136,7 @@ public void saveState(int savestateIndex) throws SavestateException, IOException // Get the current and target directory for copying String worldname = server.getFolderName(); File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname); - File targetfolder = get(currentIndex); + File targetfolder = getSavestateFile(currentIndex); if (targetfolder.exists()) { TASmod.logger.warn("WARNING! Overwriting the savestate with the index {}", currentIndex); @@ -118,7 +145,7 @@ public void saveState(int savestateIndex) throws SavestateException, IOException // Send the name of the world to all players. This will make a savestate of the // recording on the client with that name - CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(true, getSavestateNameWithIndex(currentIndex))); + CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(true, getSavestateName(currentIndex))); // Wait for the chunkloader to save the game for (WorldServer world : server.worlds) { @@ -147,6 +174,19 @@ public void saveState(int savestateIndex) throws SavestateException, IOException state = SavestateState.NONE; } + /** + * Loads the latest savestate at {@linkplain #currentIndex} + * .minecraft/saves/savestates/worldname-Savestate[{@linkplain #currentIndex}] + * + * Side: Server + * + * @throws LoadstateException + * @throws IOException + */ + public void loadState() throws LoadstateException, IOException { + loadState(-1); + } + /** * Loads the latest savestate it can find in * .minecraft/saves/savestates/worldname-Savestate @@ -176,19 +216,23 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException // Update the server instance server = TASmod.getServerInstance(); - if (!get(savestateIndex).exists()) { - throw new LoadstateException("The savestate to load doesn't exist"); + refresh(); + + int indexToLoad = savestateIndex < 0 ? currentIndex : savestateIndex; + + if (!getSavestateFile(indexToLoad).exists()) { + throw new LoadstateException("Savestate " + indexToLoad + " doesn't exist"); } else { - setCurrentIndex(savestateIndex); + setCurrentIndex(indexToLoad); } // Get the current and target directory for copying String worldname = server.getFolderName(); File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname); - File targetfolder = get(currentIndex); + File targetfolder = getSavestateFile(currentIndex); // Load savestate on the client - CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, getSavestateNameWithIndex(currentIndex))); + CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, getSavestateName(currentIndex))); // Disabeling level saving for all worlds in case the auto save kicks in during // world unload @@ -255,12 +299,6 @@ private void createSavestateDirectory() { } } - private final List indexList = new ArrayList<>(); - - private int latestIndex = 0; - - private int currentIndex; - private void refresh() { indexList.clear(); File[] files = savestateDirectory.listFiles(new FileFilter() { @@ -289,27 +327,52 @@ public boolean accept(File pathname) { indexList.add(index); } Collections.sort(indexList); - if (indexList.isEmpty()) { - indexList.add(0); + if (!indexList.isEmpty()) { + latestIndex = indexList.get(indexList.size() - 1); + } else { + latestIndex = 0; } - latestIndex = indexList.get(indexList.size() - 1); - System.out.println("LatestIndex: " + latestIndex); } - public void deleteIndex(int index) throws SavestateDeleteException { + /** + * @param index The index of the savestate file that we want to get + * @return The file of the savestate from the specified index + */ + private File getSavestateFile(int index) { + return new File(savestateDirectory, getSavestateName(index)); + } + + /** + * @param index The index of the savestate file that we want to get + * @return The savestate name without any paths + */ + private String getSavestateName(int index) { + return server.getFolderName() + "-Savestate" + index; + } + + /** + * Deletes the specified savestate + * + * @param index The index of the savestate that should be deleted + * @throws SavestateDeleteException + */ + public void deleteSavestate(int index) throws SavestateDeleteException { + if (state != SavestateState.NONE) { + throw new SavestateDeleteException("A savestate operation is currently being carried out"); + } if (index <= 0) { - throw new SavestateDeleteException("Cannot delete the indexes below or exactly 0: " + index); + throw new SavestateDeleteException("Cannot delete the indexes below or exactly zero"); } - File toDelete = get(index); + File toDelete = getSavestateFile(index); if (toDelete.exists()) { try { FileUtils.deleteDirectory(toDelete); } catch (IOException e) { e.printStackTrace(); + throw new SavestateDeleteException("Something went wrong while trying to delete the savestate " + index); } } else { - server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.YELLOW + "Savestate " + index + " doesn't exist so it can't be deleted")); - return; + throw new SavestateDeleteException(TextFormatting.YELLOW + "Savestate " + index + " doesn't exist, so it can't be deleted"); } refresh(); if (!indexList.contains(currentIndex)) { @@ -319,6 +382,30 @@ public void deleteIndex(int index) throws SavestateDeleteException { server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + index + " deleted")); } + /** + * Deletes savestates in a range from "from" to "to" + * + * @param from + * @param to (exclusive) + * @throws SavestateDeleteException + */ + public void deleteSavestate(int from, int to) throws SavestateDeleteException { + if (state != SavestateState.NONE) { + throw new SavestateDeleteException("A savestate operation is currently being carried out"); + } + if (from >= to) { + throw new SavestateDeleteException("The 'from-index' is smaller or equal to the 'to-index'"); + } + for (int i = from; i < to; i++) { + try { + deleteSavestate(i); + } catch (SavestateDeleteException e) { + server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.RED + e.getMessage())); + continue; + } + } + } + public String getIndexesAsString() { refresh(); String out = ""; @@ -328,10 +415,10 @@ public String getIndexesAsString() { return out; } - private File get(int index) { - return new File(savestateDirectory, getSavestateNameWithIndex(index)); - } - + /** + * Saves the current index to the current world-folder (not the savestate + * folder) + */ private void saveCurrentIndexToFile() { File tasmodDir = new File(savestateDirectory, "../" + server.getFolderName() + "/tasmod/"); if (!tasmodDir.exists()) { @@ -347,6 +434,10 @@ private void saveCurrentIndexToFile() { } } + /** + * Loads the current index to the current world-folder (not the savestate + * folder) + */ public void loadCurrentIndexFromFile() { int index = -1; List lines = new ArrayList(); @@ -376,17 +467,13 @@ public void loadCurrentIndexFromFile() { private void setCurrentIndex(int index) { if (index < 0) { - currentIndex = latestIndex - 1; + currentIndex = latestIndex; } else { currentIndex = index; } TASmod.logger.info("Setting the savestate index to {}", currentIndex); } - private String getSavestateNameWithIndex(int index) { - return server.getFolderName() + "-Savestate" + index; - } - public int getCurrentIndex() { return currentIndex; } @@ -407,21 +494,4 @@ public static void playerLoadSavestateEventServer() { public static void playerLoadSavestateEventClient() { SavestatesChunkControl.addPlayerToChunk(Minecraft.getMinecraft().player); } - - public void loadState() throws LoadstateException, IOException { - loadState(-1); - } - - public void saveState() throws SavestateException, IOException { - saveState(-1); - } - - public void deleteIndex(int from, int to) throws SavestateDeleteException { - if (from >= to) { - throw new SavestateDeleteException("The 'from-index' is smaller or equal to the 'to-index'"); - } - for (int i = from; i < to; i++) { - deleteIndex(i); - } - } } \ No newline at end of file From 27c01a8b246352d1dc9e3297ca87eccbe4287d8a Mon Sep 17 00:00:00 2001 From: Scribble Date: Sat, 23 Oct 2021 23:27:24 +0200 Subject: [PATCH 09/12] Redoing messages in SavestateCommand -Moved the logic to stop people from deleting/overwriting savestate 0 from the SavestateHandler to the savestate command -Modifying the savestate/loadstate packet, so you can save and load at a custom index with that packet --- .../savestates/server/LoadstatePacket.java | 17 ++ .../server/LoadstatePacketHandler.java | 2 +- .../savestates/server/SavestateCommand.java | 247 ++++++++++++------ .../savestates/server/SavestateHandler.java | 27 +- .../savestates/server/SavestatePacket.java | 17 ++ .../server/SavestatePacketHandler.java | 4 +- 6 files changed, 227 insertions(+), 87 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacket.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacket.java index ccf818c4..f27c2a23 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacket.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacket.java @@ -5,13 +5,30 @@ public class LoadstatePacket implements IMessage{ + public int index; + + /** + * Load a savestate at the current index + */ public LoadstatePacket() { + index=-1; + } + + /** + * Load the savestate at the specified index + * @param index The index to load the savestate + */ + public LoadstatePacket(int index) { + this.index = index; } + @Override public void fromBytes(ByteBuf buf) { + index=buf.readInt(); } @Override public void toBytes(ByteBuf buf) { + buf.writeInt(index); } } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java index 0059c29d..8a6bb309 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java @@ -23,7 +23,7 @@ public IMessage onMessage(LoadstatePacket message, MessageContext ctx) { return; } try { - TASmod.savestateHandler.loadState(); + TASmod.savestateHandler.loadState(message.index); } catch (LoadstateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getMessage())); } catch (Exception e) { diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java index 36c756a1..715a7ca8 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateCommand.java @@ -3,16 +3,23 @@ import java.io.IOException; import java.util.List; +import com.mojang.realmsclient.gui.ChatFormatting; + +import de.scribble.lp.tasmod.ClientProxy; import de.scribble.lp.tasmod.TASmod; import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException; import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateDeleteException; import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException; +import de.scribble.lp.tasmod.virtual.VirtualInput; +import de.scribble.lp.tasmod.virtual.VirtualKeyboard; +import net.minecraft.client.Minecraft; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.event.ClickEvent; public class SavestateCommand extends CommandBase { @@ -34,95 +41,195 @@ public int getRequiredPermissionLevel() { @Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { if (args.length == 0) { - int currentIndex = TASmod.savestateHandler.getCurrentIndex(); - sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", currentIndex))); - sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString()))); - sender.sendMessage(new TextComponentString(" ")); - sender.sendMessage(new TextComponentString("/savestate [index]")); - sender.sendMessage(new TextComponentString("/savestate save - Make a savestate at the next index")); - sender.sendMessage(new TextComponentString("/savestate save - Make a savestate at the specified index")); - sender.sendMessage(new TextComponentString("/savestate load - Load the savestate at the current index")); - sender.sendMessage(new TextComponentString("/savestate load - Load the savestate at the specified index")); - sender.sendMessage(new TextComponentString("/savestate delete - Delete the savestate at the specified index")); - sender.sendMessage(new TextComponentString("/savestate delete - Delete the savestates from the first to the second index")); - sender.sendMessage(new TextComponentString("")); - sender.sendMessage(new TextComponentString("Instead of you can use ~ to specify an index relative to the current one e.g. ~-1 will load " + (currentIndex - 1))); + sendHelp(sender); } else if (args.length >= 1) { if ("save".equals(args[0])) { if (args.length == 1) { - try { - TASmod.savestateHandler.saveState(); - } catch (SavestateException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } catch (IOException e) { - e.printStackTrace(); - throw new CommandException(e.getMessage(), new Object[] {}); - } finally { - TASmod.savestateHandler.state = SavestateState.NONE; - } + saveLatest(); } else if (args.length == 2) { - try { - TASmod.savestateHandler.saveState(processIndex(args[1])); - } catch (SavestateException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } catch (IOException e) { - e.printStackTrace(); - throw new CommandException(e.getMessage(), new Object[] {}); - } finally { - TASmod.savestateHandler.state = SavestateState.NONE; - } + saveWithIndex(args); } else { throw new CommandException("Too many arguments!", new Object[] {}); } } else if ("load".equals(args[0])) { if (args.length == 1) { - try { - TASmod.savestateHandler.loadState(); - } catch (LoadstateException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } catch (IOException e) { - e.printStackTrace(); - throw new CommandException(e.getMessage(), new Object[] {}); - } finally { - TASmod.savestateHandler.state = SavestateState.NONE; - } + loadLatest(); } else if (args.length == 2) { - try { - TASmod.savestateHandler.loadState(processIndex(args[1])); - } catch (LoadstateException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } catch (IOException e) { - e.printStackTrace(); - throw new CommandException(e.getMessage(), new Object[] {}); - } finally { - TASmod.savestateHandler.state = SavestateState.NONE; - } + loadLatest(args); } else { throw new CommandException("Too many arguments!", new Object[] {}); } } else if ("delete".equals(args[0])) { if (args.length == 2) { - try { - TASmod.savestateHandler.deleteSavestate(processIndex(args[1])); - } catch (SavestateDeleteException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } + delete(args); } else if (args.length == 3) { - try { - TASmod.savestateHandler.deleteSavestate(processIndex(args[1]), processIndex(args[2])); - } catch (SavestateDeleteException e) { - throw new CommandException(e.getMessage(), new Object[] {}); - } + int args1 = processIndex(args[1]); + int args2 = processIndex(args[2]); + int count = args2 - args1; + TextComponentString confirm = new TextComponentString(ChatFormatting.YELLOW + "Are you sure you want to delete " + count + (count == 1 ? " savestate? " : " savestates? ") + ChatFormatting.GREEN + "[YES]"); + confirm.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/savestate deletDis %s %s", args[1], args[2]))); + sender.sendMessage(confirm); } else { throw new CommandException("Too many arguments!", new Object[] {}); } + } else if ("deletDis".equals(args[0])) { + if (args.length == 3) { + deleteMultiple(args); + } } else if ("info".equals(args[0])) { - sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", TASmod.savestateHandler.getCurrentIndex()))); - sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString()))); + sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s%s", ChatFormatting.AQUA, TASmod.savestateHandler.getCurrentIndex()))); + sender.sendMessage(new TextComponentString(String.format("Available indexes are %s%s", ChatFormatting.AQUA, TASmod.savestateHandler.getIndexesAsString()))); + } else if ("help".equals(args[0])) { + if (args.length == 1) { + sendHelp(sender); + } else if (args.length == 2) { + int i = 1; + try { + i = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + throw new CommandException("Page number was not a number %s", new Object[] { args[1] }); + } + sendHelp(sender, i); + } else { + throw new CommandException("Too many arguments", new Object[] {}); + } + + } + } + } + + private void sendHelp(ICommandSender sender) throws CommandException { + sendHelp(sender, 1); + } + + private void sendHelp(ICommandSender sender, int i) throws CommandException { + int currentIndex = TASmod.savestateHandler.getCurrentIndex(); + if (i > 3) { + throw new CommandException("This help page doesn't exist (yet?)", new Object[] {}); + } + if(i==1) { + sender.sendMessage(new TextComponentString(ChatFormatting.GOLD+"-------------------Savestate Help 1--------------------\n"+ChatFormatting.RESET + + "Makes a backup of the minecraft world you are currently playing.\n\n" + + "The mod will keep track of the number of savestates you made in the 'current index' number which is currently "+ChatFormatting.AQUA+currentIndex+ChatFormatting.RESET + + String.format(". If you make a new savestate via %s/savestate save%s or by pressing %sJ%s by default, ", ChatFormatting.AQUA, ChatFormatting.RESET, ChatFormatting.AQUA, ChatFormatting.RESET) + + "the current index will increase by one. " + + String.format("If you load a savestate with %s/savestate load%s or %sK%s by default, it will load the savestate at the current index.\n", ChatFormatting.AQUA, ChatFormatting.RESET, ChatFormatting.AQUA, ChatFormatting.RESET))); + }else if(i==2) { + sender.sendMessage(new TextComponentString(String.format("%1$s-------------------Savestate Help 2--------------------\n" + + "You can load or save savestates in different indexes by specifying the index: %3$s/savestate %4$s %5$s%2$s\n" + + "This will change the %5$scurrent index%2$s to the index you specified.\n\n" + + "So, if you have the savestates %3$s1, 2, 3%2$s and your %5$scurrent index%2$s is %3$s3%2$s, %3$s/savestate %4$sload %5$s2%2$s will load the second savestate and will set the %5$scurrent index%2$s to %3$s2%2$s.\n" + + "But if you savestate again you will OVERWRITE the third savestate, so keep that in mind!!\n\n" + + "The savestate at index 0 will be the savestate when you started the TAS recording and can't be deleted or overwritten with this command" + , /*1*/ChatFormatting.GOLD, /*2*/ChatFormatting.RESET, /*3*/ChatFormatting.AQUA, /*4*/ChatFormatting.GREEN, /*5*/ChatFormatting.YELLOW))); + }else if(i==3) { + sender.sendMessage(new TextComponentString(String.format("%1$s-------------------Savestate Help 3--------------------\n%2$s" + + "%3$s/savestate %4$ssave%2$s - Make a savestate at the next index\n" + + "%3$s/savestate %4$ssave%5$s %2$s - Make a savestate at the specified index\n" + + "%3$s/savestate %4$sload%2$s - Load the savestate at the current index\n" + + "%3$s/savestate %4$sload%5$s %2$s - Load the savestate at the specified index\n" + + "%3$s/savestate %4$sdelete%5$s %2$s - Delete the savestate at the specified index\n" + + "%3$s/savestate %4$sdelete%5$s %2$s - Delete the savestates from the fromIndex to the toIndex\n" + + "%3$s/savestate %4$sinfo%2$s - Shows the current index as well as the available indexes\n" + + "\nInstead of %4$s %2$syou can use ~ to specify an index relative to the current index e.g. %3$s~-1%2$s will currently load %6$s\n", + /*1*/ChatFormatting.GOLD, /*2*/ChatFormatting.RESET, /*3*/ChatFormatting.AQUA, /*4*/ChatFormatting.GREEN, /*5*/ChatFormatting.YELLOW, /*6*/(currentIndex - 1)))); + return; + } + TextComponentString nextPage=new TextComponentString(ChatFormatting.GOLD+"Click here to go to the next help page ("+(i+1)+")\n"); + nextPage.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/savestate help "+(i+1)+"")); + sender.sendMessage(nextPage); + } + + @Override + public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) { + if (args.length == 1) { + return getListOfStringsMatchingLastWord(args, new String[] { "save", "load", "delete", "info", "help"}); + } else if (args.length == 2 && !"info".equals(args[0])) { + sender.sendMessage(new TextComponentString("Available indexes: " + ChatFormatting.AQUA + TASmod.savestateHandler.getIndexesAsString())); + } + return super.getTabCompletions(server, sender, args, targetPos); + } + + // ====================================================================== + + private void saveLatest() throws CommandException { + try { + TASmod.savestateHandler.saveState(); + } catch (SavestateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } + + private void saveWithIndex(String[] args) throws CommandException { + try { + int indexToSave = processIndex(args[1]); + if (indexToSave <= 0) { // Disallow to save on Savestate 0 + indexToSave = -1; } + TASmod.savestateHandler.saveState(indexToSave); + } catch (SavestateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } + + private void loadLatest() throws CommandException { + try { + TASmod.savestateHandler.loadState(); + } catch (LoadstateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; + } + } + + private void loadLatest(String[] args) throws CommandException { + try { + TASmod.savestateHandler.loadState(processIndex(args[1])); + } catch (LoadstateException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandException(e.getMessage(), new Object[] {}); + } finally { + TASmod.savestateHandler.state = SavestateState.NONE; } } + private void delete(String[] args) throws CommandException { + int arg1 = processIndex(args[1]); + if (arg1 == 0) { + throw new CommandException("Cannot delete savestate 0", new Object[] {}); + } + try { + TASmod.savestateHandler.deleteSavestate(arg1); + } catch (SavestateDeleteException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } + } + + private void deleteMultiple(String[] args) throws CommandException { + try { + TASmod.savestateHandler.deleteSavestate(processIndex(args[1]), processIndex(args[2])); + } catch (SavestateDeleteException e) { + throw new CommandException(e.getMessage(), new Object[] {}); + } + } + + // ====================================================================== + private int processIndex(String arg) throws CommandException { if ("~".equals(arg)) { return TASmod.savestateHandler.getCurrentIndex(); @@ -140,14 +247,4 @@ private int processIndex(String arg) throws CommandException { return i; } } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) { - if (args.length == 1) { - return getListOfStringsMatchingLastWord(args, new String[] { "save", "load", "delete", "info" }); - } else if (args.length == 2 && !"info".equals(args[0])) { - sender.sendMessage(new TextComponentString("Available indexes: " + TASmod.savestateHandler.getIndexesAsString())); - } - return super.getTabCompletions(server, sender, args, targetPos); - } } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java index f9d5d61c..a0106834 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java @@ -127,7 +127,7 @@ public void saveState(int savestateIndex) throws SavestateException, IOException refresh(); // Setting the current index depending on the savestateIndex. - if (savestateIndex <= 0) { + if (savestateIndex < 0) { setCurrentIndex(currentIndex + 1); // If the savestateIndex <= 0, create a savestate at currentIndex+1 } else { setCurrentIndex(savestateIndex); @@ -357,11 +357,14 @@ private String getSavestateName(int index) { * @throws SavestateDeleteException */ public void deleteSavestate(int index) throws SavestateDeleteException { - if (state != SavestateState.NONE) { - throw new SavestateDeleteException("A savestate operation is currently being carried out"); + if (state == SavestateState.SAVING) { + throw new SavestateDeleteException("A savestating operation is already being carried out"); } - if (index <= 0) { - throw new SavestateDeleteException("Cannot delete the indexes below or exactly zero"); + if (state == SavestateState.LOADING) { + throw new SavestateDeleteException("A loadstate operation is being carried out"); + } + if (index < 0) { + throw new SavestateDeleteException("Cannot delete the negative indexes"); } File toDelete = getSavestateFile(index); if (toDelete.exists()) { @@ -390,13 +393,19 @@ public void deleteSavestate(int index) throws SavestateDeleteException { * @throws SavestateDeleteException */ public void deleteSavestate(int from, int to) throws SavestateDeleteException { - if (state != SavestateState.NONE) { - throw new SavestateDeleteException("A savestate operation is currently being carried out"); + if (state == SavestateState.SAVING) { + throw new SavestateDeleteException("A savestating operation is already being carried out"); + } + if (state == SavestateState.LOADING) { + throw new SavestateDeleteException("A loadstate operation is being carried out"); } if (from >= to) { - throw new SavestateDeleteException("The 'from-index' is smaller or equal to the 'to-index'"); + throw new SavestateDeleteException("Can't delete amounts that are negative or 0"); } for (int i = from; i < to; i++) { + if (i == 0) { + continue; + } try { deleteSavestate(i); } catch (SavestateDeleteException e) { @@ -410,7 +419,7 @@ public String getIndexesAsString() { refresh(); String out = ""; for (int i : indexList) { - out = out.concat(" " + i + ","); + out = out.concat(" " + i + (i==indexList.size()-1?"":",")); } return out; } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacket.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacket.java index 1da8489a..e886e2f1 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacket.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacket.java @@ -15,15 +15,32 @@ */ public class SavestatePacket implements IMessage{ + public int index; + + /** + * Make a savestate at the next index + */ public SavestatePacket() { + index=-1; + } + + /** + * Make a savestate at the specified index + * + * @param index The index where to make a savestate + */ + public SavestatePacket(int index) { + this.index=index; } @Override public void fromBytes(ByteBuf buf) { + index=buf.readInt(); } @Override public void toBytes(ByteBuf buf) { + buf.writeInt(index); } } diff --git a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java index c24131c4..3f3cc26f 100644 --- a/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java +++ b/src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java @@ -31,7 +31,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) { return; } try { - TASmod.savestateHandler.saveState(); + TASmod.savestateHandler.saveState(message.index); } catch (SavestateException e) { player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to create a savestate: "+ e.getMessage())); @@ -43,7 +43,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) { } }); }else { - net.minecraft.client.Minecraft mc=net.minecraft.client.Minecraft.getMinecraft(); + net.minecraft.client.Minecraft mc=net.minecraft.client.Minecraft.getMinecraft(); //Forge will think this is executed on the server for some reason... workaround(mc); } return null; From e30003de99132c70ebbb6ad555760e2a6b0573a0 Mon Sep 17 00:00:00 2001 From: Scribble Date: Sun, 24 Oct 2021 15:32:36 +0200 Subject: [PATCH 10/12] Fixes #118 -Moved MixinDragonFight Manager to its own package And this is for the previous commit where I forgot to close things again... -Closes #112 --- .../{ => fixes}/MixinDragonFightManager.java | 2 +- .../mixin/fixes/MixinMinecraftFullscreen.java | 24 +++++++++++++++++++ src/main/resources/mixins.tasmod.json | 5 ++-- 3 files changed, 28 insertions(+), 3 deletions(-) rename src/main/java/de/scribble/lp/tasmod/mixin/{ => fixes}/MixinDragonFightManager.java (94%) create mode 100644 src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinMinecraftFullscreen.java diff --git a/src/main/java/de/scribble/lp/tasmod/mixin/MixinDragonFightManager.java b/src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinDragonFightManager.java similarity index 94% rename from src/main/java/de/scribble/lp/tasmod/mixin/MixinDragonFightManager.java rename to src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinDragonFightManager.java index cb9f51b3..cd15a9a3 100644 --- a/src/main/java/de/scribble/lp/tasmod/mixin/MixinDragonFightManager.java +++ b/src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinDragonFightManager.java @@ -1,4 +1,4 @@ -package de.scribble.lp.tasmod.mixin; +package de.scribble.lp.tasmod.mixin.fixes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinMinecraftFullscreen.java b/src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinMinecraftFullscreen.java new file mode 100644 index 00000000..95ccb514 --- /dev/null +++ b/src/main/java/de/scribble/lp/tasmod/mixin/fixes/MixinMinecraftFullscreen.java @@ -0,0 +1,24 @@ +package de.scribble.lp.tasmod.mixin.fixes; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import de.scribble.lp.tasmod.ClientProxy; +import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.GameSettings; + +@Mixin(Minecraft.class) +public class MixinMinecraftFullscreen { + + @Shadow + private GameSettings gameSettings; + + @Inject(method = "toggleFullscreen", at = @At("RETURN")) + public void inject_toggleFullscreen(CallbackInfo ci) { + int keyF11=this.gameSettings.keyBindFullscreen.getKeyCode(); + ClientProxy.virtual.getNextKeyboard().get(keyF11).setPressed(false); + } +} diff --git a/src/main/resources/mixins.tasmod.json b/src/main/resources/mixins.tasmod.json index e84921c1..93628ffa 100644 --- a/src/main/resources/mixins.tasmod.json +++ b/src/main/resources/mixins.tasmod.json @@ -17,8 +17,9 @@ //Events "events.MixinPlayerList", - //Fixing forge stuff - "MixinDragonFightManager" + //Fixing forge and vanilla stuff + "fixes.MixinDragonFightManager", + "fixes.MixinMinecraftFullscreen" ], "client": [ From 9a311191794189d0bb92be0e9070c0142802d4be Mon Sep 17 00:00:00 2001 From: Scribble Date: Sun, 24 Oct 2021 19:26:08 +0200 Subject: [PATCH 11/12] Closes #119 and closes #121 Removed deprecated stuff --- .../tasmod/inputcontainer/InputContainer.java | 73 +------------------ .../lp/tasmod/virtual/VirtualMouse.java | 26 +++---- 2 files changed, 15 insertions(+), 84 deletions(-) diff --git a/src/main/java/de/scribble/lp/tasmod/inputcontainer/InputContainer.java b/src/main/java/de/scribble/lp/tasmod/inputcontainer/InputContainer.java index 0c6a5d45..af989cbd 100644 --- a/src/main/java/de/scribble/lp/tasmod/inputcontainer/InputContainer.java +++ b/src/main/java/de/scribble/lp/tasmod/inputcontainer/InputContainer.java @@ -68,7 +68,7 @@ public class InputContainer { private BigArrayList inputs = new BigArrayList(directory + File.separator + "temp"); public DesyncMonitoring dMonitor = new DesyncMonitoring(); - + // ===================================================================================================== private String authors = "Insert author here"; @@ -123,6 +123,7 @@ public String setTASState(TASstate stateIn, boolean verbose) { return verbose ? TextFormatting.RED + "An error occured while reading the start location of the TAS. The file might be broken" : ""; } } + Minecraft.getMinecraft().gameSettings.chatLinks = false; // #119 index = 0; state = TASstate.PLAYBACK; return verbose ? TextFormatting.GREEN + "Starting playback" : ""; @@ -177,76 +178,6 @@ public TASstate getState() { return state; } - @Deprecated - public String setRecording(boolean enabled) { - return setRecording(enabled, true); - } - - /** - * Starts/Stops a recording - * - * @param enabled If true: starts a recording, else stops a running recording - * @return Chat message depending on the state - */ - @Deprecated - public String setRecording(boolean enabled, boolean verbose) { - if (state == TASstate.PLAYBACK) { - return verbose ? TextFormatting.RED + "A playback is already running" : ""; - } - if (enabled) { - state = TASstate.RECORDING; - } else { - state = TASstate.NONE; - } - - if (state == TASstate.RECORDING) { - if (Minecraft.getMinecraft().player != null) { - startLocation = getStartLocation(Minecraft.getMinecraft().player); // TODO #99 Make this a secondary command - } - return verbose ? TextFormatting.GREEN + "Starting the recording" : ""; - } else if (state == TASstate.NONE) { - return verbose ? TextFormatting.GREEN + "Stopping the recording" : ""; - } - return ""; - } - - @Deprecated - public String setPlayback(boolean enabled) { - return setPlayback(enabled, true); - } - - /** - * Starts/Stops a playback - * - * @param enabled If true: start a playback, else aborts a running playback - * @return Chat message depending on the state - */ - @Deprecated - public String setPlayback(boolean enabled, boolean verbose) { - if (state == TASstate.RECORDING) - return verbose ? TextFormatting.RED + "A recording is already running" : ""; - if (enabled) { - state = TASstate.PLAYBACK; - } else { - state = TASstate.NONE; - } - if (state == TASstate.PLAYBACK) { - if (Minecraft.getMinecraft().player != null && !startLocation.isEmpty()) { - try { - tpPlayer(startLocation); - } catch (NumberFormatException e) { - state = TASstate.NONE; - e.printStackTrace(); - return verbose ? TextFormatting.RED + "An error occured while reading the start location of the TAS. The file might be broken" : ""; - } - } - index = 0; - return verbose ? TextFormatting.GREEN + "Starting playback" : ""; - } else { - return verbose ? TextFormatting.GREEN + "Aborting playback" : ""; - } - } - // ===================================================================================================== // Methods to update the temporary variables of the container. // These act as an input and output, depending if a recording or a playback is diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualMouse.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualMouse.java index 2abaef03..f284c242 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualMouse.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualMouse.java @@ -54,19 +54,19 @@ public VirtualMouse() { keyList.put(-100, new VirtualKey("LC", -100)); keyList.put(-99, new VirtualKey("RC", -99)); keyList.put(-98, new VirtualKey("MC", -98)); - keyList.put(-97, new VirtualKey("MBUTTON3", -97)); - keyList.put(-96, new VirtualKey("MBUTTON4", -96)); - keyList.put(-95, new VirtualKey("MBUTTON5", -95)); - keyList.put(-94, new VirtualKey("MBUTTON6", -94)); - keyList.put(-93, new VirtualKey("MBUTTON7", -93)); - keyList.put(-92, new VirtualKey("MBUTTON8", -92)); - keyList.put(-91, new VirtualKey("MBUTTON9", -91)); - keyList.put(-90, new VirtualKey("MBUTTON10", -90)); - keyList.put(-89, new VirtualKey("MBUTTON11", -89)); - keyList.put(-88, new VirtualKey("MBUTTON12", -88)); - keyList.put(-87, new VirtualKey("MBUTTON13", -87)); - keyList.put(-86, new VirtualKey("MBUTTON14", -86)); - keyList.put(-85, new VirtualKey("MBUTTON15", -85)); + keyList.put(-97, new VirtualKey("MBUTTON4", -97)); + keyList.put(-96, new VirtualKey("MBUTTON5", -96)); + keyList.put(-95, new VirtualKey("MBUTTON6", -95)); + keyList.put(-94, new VirtualKey("MBUTTON7", -94)); + keyList.put(-93, new VirtualKey("MBUTTON8", -93)); + keyList.put(-92, new VirtualKey("MBUTTON9", -92)); + keyList.put(-91, new VirtualKey("MBUTTON10", -91)); + keyList.put(-90, new VirtualKey("MBUTTON11", -90)); + keyList.put(-89, new VirtualKey("MBUTTON12", -89)); + keyList.put(-88, new VirtualKey("MBUTTON13", -88)); + keyList.put(-87, new VirtualKey("MBUTTON14", -87)); + keyList.put(-86, new VirtualKey("MBUTTON15", -86)); + keyList.put(-85, new VirtualKey("MBUTTON16", -85)); this.scrollwheel = 0; From f1c29de0b7d4d9a2042d29ec14a417d95f43790b Mon Sep 17 00:00:00 2001 From: Scribble Date: Sun, 24 Oct 2021 20:13:24 +0200 Subject: [PATCH 12/12] Fixes and bump Hopefully fixed a softlock... --- build.gradle | 2 +- .../java/de/scribble/lp/tasmod/virtual/VirtualInput.java | 9 ++++++--- .../scribble/lp/tasmod/virtual/VirtualKeybindings.java | 8 ++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 5ce7d23b..0aff5c5e 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ apply plugin: 'org.spongepowered.mixin' //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -version = "Alpha7-WIP" +version = "Alpha7" group = "de.scribble.lp.tastools" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "TASmod-1.12.2" diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java index 50dcdbef..c286725e 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualInput.java @@ -262,15 +262,18 @@ public VirtualMouse getNextMouse() { public void updateNextMouse(int keycode, boolean keystate, int scrollwheel, int cursorX, int cursorY, boolean filter) { - if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode - 100)) { - return; - } boolean flag = true; if (filter) { flag = nextMouse.isSomethingDown() || scrollwheel != 0 || keycode != -1; } + VirtualKey key = nextMouse.get(keycode - 100); + if (VirtualKeybindings.isKeyCodeAlwaysBlocked(keycode - 100)) { + key.setPressed(false); + return; + } + key.setPressed(keystate); nextMouse.setScrollWheel(scrollwheel); diff --git a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java index 8774d41f..877e4b5d 100644 --- a/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java +++ b/src/main/java/de/scribble/lp/tasmod/virtual/VirtualKeybindings.java @@ -33,7 +33,7 @@ */ public class VirtualKeybindings { private static Minecraft mc = Minecraft.getMinecraft(); - private static long cooldown = 50*10; + private static long cooldown = 50*5; private static HashMap cooldownHashMap = Maps.newHashMap(); private static List blockedKeys = new ArrayList<>(); public static boolean focused = false; @@ -51,6 +51,10 @@ public static boolean isKeyDown(KeyBinding keybind) { boolean down = false; + if(mc.currentScreen instanceof GuiControls) { + return false; + } + if (isKeyCodeAlwaysBlocked(keycode)) { down = keycode >= 0 ? Keyboard.isKeyDown(keycode) : Mouse.isButtonDown(keycode + 100); } else { @@ -79,7 +83,7 @@ public static boolean isKeyDown(KeyBinding keybind) { * @return */ public static boolean isKeyDownExceptTextfield(KeyBinding keybind) { - if (mc.currentScreen instanceof GuiChat || mc.currentScreen instanceof GuiEditSign || (focused && mc.currentScreen != null) || mc.currentScreen instanceof GuiControls) { + if (mc.currentScreen instanceof GuiChat || mc.currentScreen instanceof GuiEditSign || (focused && mc.currentScreen != null)) { return false; } return isKeyDown(keybind);