diff --git a/src/main/java/com/minecrafttas/mctcommon/file/AbstractDataFile.java b/src/main/java/com/minecrafttas/mctcommon/file/AbstractDataFile.java index dcd1cb2e..2b2fb05d 100644 --- a/src/main/java/com/minecrafttas/mctcommon/file/AbstractDataFile.java +++ b/src/main/java/com/minecrafttas/mctcommon/file/AbstractDataFile.java @@ -54,12 +54,6 @@ protected AbstractDataFile(Path file, String name, String comment) { this.name = name; this.comment = comment; this.properties = new Properties(); - - try { - createDirectory(file.getParent()); - } catch (IOException e) { - MCTCommon.LOGGER.catching(e); - } } /** @@ -97,6 +91,11 @@ protected void saveToProperties() { } protected void saveToProperties(Path file) { + try { + createDirectory(file.getParent()); + } catch (IOException e) { + MCTCommon.LOGGER.catching(e); + } try { OutputStream fos = Files.newOutputStream(file); properties.store(fos, comment); @@ -118,6 +117,11 @@ protected void saveToXML() { * @param file The file to save the {@link #properties} to */ protected void saveToXML(Path file) { + try { + createDirectory(file.getParent()); + } catch (IOException e) { + MCTCommon.LOGGER.catching(e); + } try { OutputStream fos = Files.newOutputStream(file); properties.storeToXML(fos, comment, "UTF-8"); @@ -132,6 +136,11 @@ protected void saveToJson() { } protected void saveToJson(Path file) { + try { + createDirectory(file.getParent()); + } catch (IOException e) { + MCTCommon.LOGGER.catching(e); + } //@formatter:off Gson json = new GsonBuilder() .registerTypeAdapter(Properties.class, new PropertiesSerializer()) diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinMinecraft.java b/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinMinecraft.java index 9fca7861..53f6aeda 100644 --- a/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinMinecraft.java +++ b/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinMinecraft.java @@ -1,5 +1,7 @@ package com.minecrafttas.tasmod.mixin.playbackhooks; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -8,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.minecrafttas.tasmod.TASmodClient; +import com.minecrafttas.tasmod.virtual.SubtickGuiScreen; import com.minecrafttas.tasmod.virtual.VirtualInput; import com.minecrafttas.tasmod.virtual.VirtualInput.VirtualKeyboardInput; import com.minecrafttas.tasmod.virtual.VirtualInput.VirtualMouseInput; @@ -16,6 +19,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.settings.KeyBinding; @Mixin(Minecraft.class) public class MixinMinecraft { @@ -158,4 +162,29 @@ public int playback_redirectGetEventDWheel() { return TASmodClient.virtual.MOUSE.getEventMouseScrollWheel(); } + // ============================ DisplayGui + + @Redirect(method = "displayGuiScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/settings/KeyBinding;unPressAllKeys()V")) + private static void playback_unpressAllKeys(GuiScreen guiScreen) { + if (guiScreen instanceof SubtickGuiScreen) { + return; + } + KeyBinding.unPressAllKeys(); + } + + @Redirect(method = "displayGuiScreen", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Mouse;next()Z")) + private static boolean playback_mouseNext(GuiScreen guiScreen) { + if (guiScreen instanceof SubtickGuiScreen) { + return false; + } + return Mouse.next(); + } + + @Redirect(method = "displayGuiScreen", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;next()Z")) + private static boolean playback_keyboardNext(GuiScreen guiScreen) { + if (guiScreen instanceof SubtickGuiScreen) { + return false; + } + return Keyboard.next(); + } } diff --git a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java index c4c1943f..6c48a0ba 100644 --- a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java +++ b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java @@ -1074,7 +1074,7 @@ public void onClientInit(Minecraft mc) { // Execute /restartandplay. Load the file to start from the config. If it exists load the playback file on start. String fileOnStart = TASmodClient.config.get(TASmodConfig.FileToOpen); if (fileOnStart.isEmpty()) { - fileOnStart = null; + return; } else { TASmodClient.config.reset(TASmodConfig.FileToOpen); } diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java index bbd88526..7c486dbf 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java @@ -46,6 +46,7 @@ public enum TASmodKeybinds implements KeybindID { TASmodClient.virtual.CAMERA_ANGLE.updateNextCameraAngle(0, 45); }), TEST1("Various Testing", "TASmod", Keyboard.KEY_F12, () -> { + Minecraft.getMinecraft().displayGuiScreen(null); }, VirtualKeybindings::isKeyDown), TEST2("Various Testing2", "TASmod", Keyboard.KEY_F7, () -> { }, VirtualKeybindings::isKeyDown); diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java index fd282b38..5fdaf3d9 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java @@ -4,6 +4,7 @@ import com.minecrafttas.mctcommon.networking.Client.Side; import com.minecrafttas.mctcommon.networking.CompactPacketHandler; import com.minecrafttas.mctcommon.networking.interfaces.PacketID; +import com.minecrafttas.tasmod.TASmod; import com.minecrafttas.tasmod.TASmodClient; import com.minecrafttas.tasmod.playback.PlaybackControllerClient; import com.minecrafttas.tasmod.playback.PlaybackControllerClient.TASstate; @@ -106,7 +107,7 @@ public enum TASmodPackets implements PacketID { SAVESTATE_CLEAR_SCREEN(Side.CLIENT, (buf, clientID) -> { Minecraft mc = Minecraft.getMinecraft(); if (mc.currentScreen instanceof GuiSavestate || mc.currentScreen instanceof GuiDownloadTerrain) { - mc.addScheduledTask(() -> { + TASmod.gameLoopSchedulerServer.add(() -> { mc.displayGuiScreen(null); }); } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerClient.java b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerClient.java index bf5a08d3..1d650125 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerClient.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerClient.java @@ -118,9 +118,16 @@ public static void savestate(String nameOfSavestate) throws SavestateException, return; } - createClientSavestateDirectory(); + Path targetfile = clientSavestateDirectory.resolve(nameOfSavestate + ".mctas").normalize(); - Path targetfile = clientSavestateDirectory.resolve(nameOfSavestate + ".mctas"); + if (!targetfile.startsWith(clientSavestateDirectory)) { + LOGGER.error("Could not create client savestate: Savestate won't be saved in savestate folder {}", targetfile); + return; + } + + Path targetParentDir = targetfile.getParent(); + if (!Files.exists(targetParentDir)) + Files.createDirectories(targetParentDir); PlaybackControllerClient container = TASmodClient.controller; if (container.isRecording()) { @@ -146,6 +153,13 @@ public static void loadstate(String nameOfSavestate) throws Exception { return; } + Path targetfile = clientSavestateDirectory.resolve(nameOfSavestate + ".mctas").normalize(); + + if (!targetfile.startsWith(clientSavestateDirectory)) { + LOGGER.error("Could not load client savestate: Savestate won't be saved in savestate folder {}", targetfile); + return; + } + PlaybackControllerClient controller = TASmodClient.controller; TASstate state = controller.getState(); @@ -161,8 +175,6 @@ public static void loadstate(String nameOfSavestate) throws Exception { state = controller.getStateAfterPause(); } - Path targetfile = clientSavestateDirectory.resolve(nameOfSavestate + ".mctas"); - BigArrayList savestateContainerList; if (Files.exists(targetfile)) { @@ -254,11 +266,6 @@ else if (state == TASstate.PLAYBACK) { }); } - private static void createClientSavestateDirectory() throws IOException { - LOGGER.trace(LoggerMarkers.Savestate, "Creating savestate directory at {}", clientSavestateDirectory); - Files.createDirectories(clientSavestateDirectory); - } - private static void preload(BigArrayList containerList, long index) { LOGGER.trace(LoggerMarkers.Savestate, "Preloading container at index {}", index); InputContainer containerToPreload = containerList.get(index); diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java index c8c6f5a6..aae6764a 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java @@ -177,9 +177,12 @@ private void savestateInner(SavestatePaths paths, SavestateCallback cb, Savestat * Send the name of the world to all players. This will make a savestate of the * recording on the client with that name */ + Path folder = paths.getSavestate().folder; + Path savestateDir = folder.getParent().getParent(); + Path relativeFolder = savestateDir.relativize(folder); try { // savestate inputs client - TASmod.server.sendToAll(new TASmodBufferBuilder(TASmodPackets.SAVESTATE_SAVE).writeString(paths.getSavestate().folder.toString())); + TASmod.server.sendToAll(new TASmodBufferBuilder(TASmodPackets.SAVESTATE_SAVE).writeString(relativeFolder.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -286,9 +289,12 @@ private void loadStateInner(SavestatePaths paths, SavestateCallback cb, Savestat * InputSavestate) */ if (!SavestateFlags.BLOCK_CLIENT_SAVESTATE.isBlocked(flags)) { + Path folder = paths.getSavestate().folder; + Path savestateDir = folder.getParent().getParent(); + Path relativeFolder = savestateDir.relativize(folder); try { // loadstate inputs client - TASmod.server.sendToAll(new TASmodBufferBuilder(TASmodPackets.SAVESTATE_LOAD).writeString(paths.getSavestate().folder.toString())); + TASmod.server.sendToAll(new TASmodBufferBuilder(TASmodPackets.SAVESTATE_LOAD).writeString(relativeFolder.toString())); } catch (Exception e) { e.printStackTrace(); } @@ -451,7 +457,8 @@ public void onServerPacket(PacketID id, ByteBuffer buf, String username) throws * Once the player is done renaming the savestate, the screens are cleared for all players. */ try { - TASmod.server.sendTo(player, new TASmodBufferBuilder(TASmodPackets.SAVESTATE_RENAME_SCREEN).writeInt(paths.getSavestate().index)); + // TODO Currently desyncs the savestates... Bigger investigation necessary +// TASmod.server.sendTo(player, new TASmodBufferBuilder(TASmodPackets.SAVESTATE_RENAME_SCREEN).writeInt(paths.getSavestate().index)); } catch (Exception e) { LOGGER.catching(e); } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateIndexer.java b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateIndexer.java index ea8e4e0c..9874b3ec 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateIndexer.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateIndexer.java @@ -204,7 +204,7 @@ public SavestatePaths loadSavestate(int index, boolean changeIndex) throws Loads throw new LoadstateException("msg.tasmod.savestate.error.filenoexist", missingFile); } - SavestatePaths out = SavestatePaths.of(currentSavestate.clone(), sourceDir, targetDir); + SavestatePaths out = SavestatePaths.of(savestateToLoad.clone(), sourceDir, targetDir); trackerfile.increaseLoadstateCount(); diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/gui/GuiSavestateRename.java b/src/main/java/com/minecrafttas/tasmod/savestates/gui/GuiSavestateRename.java index 83fe24a1..b00b3bb6 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/gui/GuiSavestateRename.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/gui/GuiSavestateRename.java @@ -27,7 +27,6 @@ public GuiSavestateRename(ITextComponent msg, int index) { @Override public void initGui() { - TASmodClient.virtual.clearNext(); this.buttonList.clear(); int boxWidth = 200; buttonList.add(new GuiButton(1, width / 2 - (boxWidth / 2) - 1, height / 2 + 62, boxWidth + 3, 20, new TextComponentTranslation("gui.tasmod.savestate.save.rename.button").getFormattedText())); @@ -76,8 +75,6 @@ private void renameAndExit() { } catch (Exception e) { TASmod.LOGGER.catching(e); } - TASmodClient.virtual.clearNext(); - mc.displayGuiScreen(null); } @Override @@ -87,6 +84,12 @@ public void updateScreen() { @Override public void onGuiClosed() { + TASmodClient.virtual.clearNext(); Keyboard.enableRepeatEvents(false); } + + @Override + public boolean doesGuiPauseGame() { + return false; + } } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateGuiHandlerClient.java b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateGuiHandlerClient.java index edf2325a..43556cfa 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateGuiHandlerClient.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateGuiHandlerClient.java @@ -10,6 +10,7 @@ import com.minecrafttas.mctcommon.networking.exception.WrongSideException; import com.minecrafttas.mctcommon.networking.interfaces.ClientPacketHandler; import com.minecrafttas.mctcommon.networking.interfaces.PacketID; +import com.minecrafttas.tasmod.TASmodClient; import com.minecrafttas.tasmod.networking.TASmodBufferBuilder; import com.minecrafttas.tasmod.registries.TASmodPackets; import com.minecrafttas.tasmod.savestates.SavestateHandlerServer.SavestateState; @@ -44,20 +45,18 @@ public void onClientPacket(PacketID id, ByteBuffer buf, String username) throws case SAVESTATE_LOADING_SCREEN: // Open Savestate screen SavestateState state = TASmodBufferBuilder.readEnum(SavestateState.class, buf); - mc.addScheduledTask(() -> { - String msg = ""; - if (state == SavestateState.SAVING) - msg = "gui.tasmod.savestate.save.start"; - else if (state == SavestateState.LOADING) - msg = "gui.tasmod.savestate.load.start"; + String msg = ""; + if (state == SavestateState.SAVING) + msg = "gui.tasmod.savestate.save.start"; + else if (state == SavestateState.LOADING) + msg = "gui.tasmod.savestate.load.start"; - mc.displayGuiScreen(new GuiSavestate(Component.translatable(msg).withStyle(TextFormatting.YELLOW).build())); - }); + mc.displayGuiScreen(new GuiSavestate(Component.translatable(msg).withStyle(TextFormatting.YELLOW).build())); break; case SAVESTATE_RENAME_SCREEN: int index = TASmodBufferBuilder.readInt(buf); - mc.addScheduledTask(() -> { + TASmodClient.tickSchedulerClient.add(() -> { displayGuiRename(index); }); break; diff --git a/src/main/java/com/minecrafttas/tasmod/virtual/SubtickGuiScreen.java b/src/main/java/com/minecrafttas/tasmod/virtual/SubtickGuiScreen.java index 075b1246..2896e19a 100644 --- a/src/main/java/com/minecrafttas/tasmod/virtual/SubtickGuiScreen.java +++ b/src/main/java/com/minecrafttas/tasmod/virtual/SubtickGuiScreen.java @@ -1,6 +1,6 @@ package com.minecrafttas.tasmod.virtual; -import com.minecrafttas.tasmod.TASmodClient; +import org.lwjgl.input.Keyboard; import net.minecraft.client.gui.GuiScreen; @@ -33,7 +33,6 @@ public void mouseClicked(int i, int j, int k) { @Override public void onGuiClosed() { - TASmodClient.virtual.clearNext(); - super.onGuiClosed(); + Keyboard.enableRepeatEvents(false); } } diff --git a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java index 678e0aa2..1638c7d1 100644 --- a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java +++ b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java @@ -82,22 +82,25 @@ public VirtualInput(Logger logger, VirtualKeyboard preloadedKeyboard, VirtualMou */ public void update(GuiScreen currentScreen) { while (Keyboard.next()) { - KEYBOARD.updateNextKeyboard(Keyboard.getEventKey(), Keyboard.getEventKeyState(), Keyboard.getEventCharacter(), Keyboard.areRepeatEventsEnabled()); - updateSubtickGuiScreenKeyboard(currentScreen); + if (updateSubtickGuiScreenKeyboard(currentScreen)) + return; + + KEYBOARD.updateNextKeyboard(Keyboard.getEventKey(), Keyboard.getEventKeyState(), Keyboard.getEventCharacter(), Keyboard.areRepeatEventsEnabled()); } while (Mouse.next()) { if (currentScreen == null) { MOUSE.updateNextMouse(Mouse.getEventButton() - 100, Mouse.getEventButtonState(), Mouse.getEventDWheel(), 0, 0); } else { + if (updateSubtickGuiScreenMouse(currentScreen)) + return; + Ducks.GuiScreenDuck screen = (Ducks.GuiScreenDuck) currentScreen; int eventX = screen.unscaleX(Mouse.getEventX()); int eventY = screen.unscaleY(Mouse.getEventY()); eventX = PointerNormalizer.getNormalizedX(eventX); eventY = PointerNormalizer.getNormalizedY(eventY); MOUSE.updateNextMouse(Mouse.getEventButton() - 100, Mouse.getEventButtonState(), Mouse.getEventDWheel(), eventX, eventY); - - updateSubtickGuiScreenMouse(currentScreen); } } } @@ -105,28 +108,34 @@ public void update(GuiScreen currentScreen) { /** * Update the {@link SubtickGuiScreen#keyTyped(char, int)}, if the current screen is a {@link SubtickGuiScreen} * @param currentScreen The current screen to update + * @return True if the next keyboard should not be updated */ - private void updateSubtickGuiScreenKeyboard(GuiScreen currentScreen) { + private boolean updateSubtickGuiScreenKeyboard(GuiScreen currentScreen) { if (currentScreen instanceof SubtickGuiScreen) { SubtickGuiScreen screenSubtickable = (SubtickGuiScreen) currentScreen; if (Keyboard.getEventKeyState()) screenSubtickable.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey()); + return true; } + return false; } /** * Update the {@link SubtickGuiScreen#mouseClicked(int, int, int)}, if the current screen is a {@link SubtickGuiScreen} * @param currentScreen The current screen to update + * @return True if the next mouse should not be updated */ - private void updateSubtickGuiScreenMouse(GuiScreen currentScreen) { + private boolean updateSubtickGuiScreenMouse(GuiScreen currentScreen) { if (currentScreen instanceof SubtickGuiScreen) { SubtickGuiScreen screenSubtickable = (SubtickGuiScreen) currentScreen; Ducks.GuiScreenDuck screenDuck = (Ducks.GuiScreenDuck) screenSubtickable; if (Mouse.getEventButtonState()) screenSubtickable.mouseClicked(screenDuck.unscaleX(Mouse.getEventX()), screenDuck.unscaleY(Mouse.getEventY()), Mouse.getEventButton()); + return true; } + return false; } /**