From ae5eca9c997fdea544c261ff4f1a0214d8d4816d Mon Sep 17 00:00:00 2001 From: CrushedPixel Date: Thu, 30 Apr 2015 17:46:13 +0200 Subject: [PATCH] Localized Keyboard Bindings and added "Synchronize Timeline" and "Clear Keyframes" --- .../replaymod/events/GuiReplayOverlay.java | 3 - .../events/TickAndRenderListener.java | 14 +--- .../replaymod/registry/KeybindRegistry.java | 16 ++-- .../replaymod/replay/ReplayHandler.java | 80 +++++++++++++++++++ .../replaymod/replay/ReplayProcess.java | 53 +++++++----- .../replaymod/replay/ReplaySender.java | 2 - .../assets/replaymod/lang/en_US.lang | 9 ++- 7 files changed, 134 insertions(+), 43 deletions(-) diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index ebdfe223..c7a6575d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -65,7 +65,6 @@ public class GuiReplayOverlay extends Gui { private int place_ButtonY = realTimelineY + 1; private int time_ButtonX = 85; private int time_ButtonY = realTimelineY + 1; - private long lastSystemTime = System.currentTimeMillis(); private ResourceLocation replay_gui = new ResourceLocation("replaymod", "replay_gui.png"); private ResourceLocation extended_gui = new ResourceLocation("replaymod", "extended_gui.png"); private ResourceLocation timeline_icons = new ResourceLocation("replaymod", "timeline_icons.png"); @@ -79,7 +78,6 @@ public class GuiReplayOverlay extends Gui { private int tl_y = 40; private float zoom_scale = 0.1f; //can see 1/10th of the timeline private float pos_left = 0f; //left border of timeline is at 0% - private float cursor_pos = 0f; //cursor is at 0% private long timelineLength = 10 * 60 * 1000; //10 min of timeline private float zoom_steps = 0.05f; private boolean wasSliding = false; @@ -218,7 +216,6 @@ public class GuiReplayOverlay extends Gui { } } - //TODO: Save Video Button hover = false; x = 0; y = 18; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java b/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java index 967bb32b..2a5c6d4d 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java @@ -91,16 +91,6 @@ public class TickAndRenderListener { public void tick(TickEvent event) { if(!ReplayHandler.isInReplay()) return; - /* - if(Keyboard.getEventKeyState() && Keyboard.isKeyDown(Keyboard.KEY_F1) - && ReplayHandler.isInPath() && !ReplayProcess.isVideoRecording() - && mc.currentScreen instanceof GuiMouseInput && !f1Down) { - mc.gameSettings.hideGUI = !mc.gameSettings.hideGUI; - } - - f1Down = Keyboard.isKeyDown(Keyboard.KEY_F1) && Keyboard.getEventKeyState(); - */ - if(ReplayHandler.getCameraEntity() != null) ReplayHandler.getCameraEntity().updateMovement(); if(ReplayHandler.isInPath()) { @@ -110,14 +100,14 @@ public class TickAndRenderListener { mc.displayGuiScreen(new GuiMouseInput()); } } else onMouseMove(new MouseEvent()); + FMLCommonHandler.instance().bus().post(new InputEvent.KeyInputEvent()); } @SubscribeEvent public void onMouseMove(MouseEvent event) { if(!ReplayHandler.isInReplay()) return; - boolean flag = Display.isActive(); - flag = true; + boolean flag = true; mc.mcProfiler.startSection("mouse"); diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java index e1fea75b..0c9a41a6 100755 --- a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java @@ -10,17 +10,21 @@ import java.util.List; public class KeybindRegistry { - public static final String KEY_LIGHTING = "Toggle Lighting"; - public static final String KEY_THUMBNAIL = "Create Thumbnail"; - public static final String KEY_SPECTATE = "Spectate Entity"; + public static final String KEY_LIGHTING = "replaymod.input.lighting"; + public static final String KEY_THUMBNAIL = "replaymod.input.thumbnail"; + public static final String KEY_SPECTATE = "replaymod.input.spectate"; + public static final String KEY_CLEAR_KEYFRAMES = "replaymod.input.clearkeyframes"; + public static final String KEY_SYNC_TIMELINE = "replaymod.input.synctimeline"; private static Minecraft mc = Minecraft.getMinecraft(); public static void initialize() { List bindings = new ArrayList(Arrays.asList(mc.gameSettings.keyBindings)); - bindings.add(new KeyBinding(KEY_LIGHTING, Keyboard.KEY_V, "Replay Mod")); - bindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_B, "Replay Mod")); - bindings.add(new KeyBinding(KEY_SPECTATE, Keyboard.KEY_C, "Replay Mod")); + bindings.add(new KeyBinding(KEY_LIGHTING, Keyboard.KEY_M, "replaymod.title")); + bindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_N, "replaymod.title")); + bindings.add(new KeyBinding(KEY_SPECTATE, Keyboard.KEY_B, "replaymod.title")); + bindings.add(new KeyBinding(KEY_SYNC_TIMELINE, Keyboard.KEY_V, "replaymod.title")); + bindings.add(new KeyBinding(KEY_CLEAR_KEYFRAMES, Keyboard.KEY_C, "replaymod.title")); mc.gameSettings.keyBindings = bindings.toArray(new KeyBinding[bindings.size()]); } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index 96727e81..d6c1d8c8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -343,4 +343,84 @@ public class ReplayHandler { } return null; } + + public static TimeKeyframe getFirstTimeKeyframe() { + Keyframe sel = getSelected(); + sortKeyframes(); + for(Keyframe k : getKeyframes()) { + if(k instanceof TimeKeyframe) { + selectKeyframe(sel); + return (TimeKeyframe)k; + } + } + selectKeyframe(sel); + return null; + } + + public static PositionKeyframe getFirstPositionKeyframe() { + Keyframe sel = getSelected(); + sortKeyframes(); + for(Keyframe k : getKeyframes()) { + if(k instanceof PositionKeyframe) { + selectKeyframe(sel); + return (PositionKeyframe)k; + } + } + selectKeyframe(sel); + return null; + } + + public static TimeKeyframe getLastTimeKeyframe() { + ArrayList rev = new ArrayList(getKeyframes()); + Collections.reverse(rev); + + for(Keyframe k : rev) { + if(k instanceof TimeKeyframe) { + return (TimeKeyframe)k; + } + } + return null; + } + + public static PositionKeyframe getLastPositionKeyframe() { + ArrayList rev = new ArrayList(getKeyframes()); + Collections.reverse(rev); + + for(Keyframe k : rev) { + if(k instanceof PositionKeyframe) { + return (PositionKeyframe)k; + } + } + return null; + } + + public static void syncTimeCursor(boolean shiftMode) { + selectKeyframe(null); + + int curTime = ReplayMod.replaySender.currentTimeStamp(); + + int prevTime, prevRealTime; + + TimeKeyframe keyframe; + + //if shift is down, it will refer to the previous Time Keyframe instead of the last one + if(shiftMode) { + int realTime = getRealTimelineCursor(); + keyframe = getPreviousTimeKeyframe(realTime); + } else { + keyframe = getLastTimeKeyframe(); + } + + if(keyframe == null) { + prevTime = 0; + prevRealTime = 0; + } else { + prevTime = keyframe.getTimestamp(); + prevRealTime = keyframe.getRealTimestamp(); + } + + int newCursorPos = prevRealTime+(curTime-prevTime); + + setRealTimelineCursor(newCursorPos); + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java index 83799f4d..1d18450d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java @@ -55,12 +55,9 @@ public class ReplayProcess { return isVideoRecording; } - public static void startReplayProcess(boolean record) { - ReplayHandler.selectKeyframe(null); - + private static void resetProcess() { firstTime = true; - isVideoRecording = record; lastPosition = null; motionSpline = null; motionLinear = null; @@ -70,12 +67,6 @@ public class ReplayProcess { ReplayMod.replaySender.resetToleratedTimeStamp(); - ReplayMod.chatMessageHandler.initialize(); - if(ReplayHandler.getPosKeyframeCount() < 2 && ReplayHandler.getTimeKeyframeCount() < 2) { - ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.notenoughkeyframes", ChatMessageType.WARNING); - return; - } - blocked = deepBlock = false; startRealTime = System.currentTimeMillis(); @@ -84,13 +75,31 @@ public class ReplayProcess { lastTimestamp = -1; lastSpeed = 1f; linear = ReplayMod.replaySettings.isLinearMovement(); - ReplayHandler.sortKeyframes(); - ReplayHandler.setInPath(true); + previousReplaySpeed = ReplayMod.replaySender.getReplaySpeed(); EnchantmentTimer.resetRecordingTime(); + } - TimeKeyframe tf = ReplayHandler.getNextTimeKeyframe(-1); + public static void startReplayProcess(boolean record) { + ReplayHandler.selectKeyframe(null); + resetProcess(); + + isVideoRecording = record; + + ReplayMod.chatMessageHandler.initialize(); + + //if not enough keyframes, abort and leave chat message + if(ReplayHandler.getPosKeyframeCount() < 2 && ReplayHandler.getTimeKeyframeCount() < 2) { + ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.notenoughkeyframes", ChatMessageType.WARNING); + return; + } + + ReplayHandler.sortKeyframes(); + ReplayHandler.setInPath(true); + + //gets first Timestamp and sets Replay Time to it + TimeKeyframe tf = ReplayHandler.getFirstTimeKeyframe(); if(tf != null) { int ts = tf.getTimestamp(); if(ts < ReplayMod.replaySender.currentTimeStamp()) { @@ -101,6 +110,7 @@ public class ReplayProcess { ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION); + //if video is recording, the Replay Process takes control over the Minecraft Timer if(isVideoRecording()) { MCTimerHandler.setTimerSpeed(1f); MCTimerHandler.setPassiveTimer(); @@ -109,6 +119,8 @@ public class ReplayProcess { public static void stopReplayProcess(boolean finished) { if(!ReplayHandler.isInPath()) return; + + //if canceled, display a different chat message if(finished) ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathfinished", ChatMessageType.INFORMATION); else { ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathinterrupted", ChatMessageType.INFORMATION); @@ -116,8 +128,11 @@ public class ReplayProcess { VideoWriter.abortRecording(); } } + ReplayHandler.setInPath(false); + ReplayMod.replaySender.stopHurrying(); + MCTimerHandler.setActiveTimer(); ReplayMod.replaySender.setReplaySpeed(previousReplaySpeed); ReplayMod.replaySender.setReplaySpeed(0); @@ -126,13 +141,13 @@ public class ReplayProcess { public static void unblockAndTick(boolean justCheck) { if(!deepBlock) blocked = false; if(!blocked || !isVideoRecording()) - ReplayProcess.tickReplay(justCheck); - } - - public static void tickReplay(boolean justCheck) { - pathTick(isVideoRecording(), justCheck); + pathTick(isVideoRecording(), justCheck); } + //if justCheck is true, no Screenshot will be taken, it will only be checked + //whether all chunks have been rendered. This is necessary because no Render ticks + //are called if the Timer speed is set to 0, leading to this method never being + //called from the RenderWorldLastEvent handlers. private static void pathTick(boolean recording, boolean justCheck) { if(ReplayMod.replaySender.isHurrying()) { lastRealTime = System.currentTimeMillis(); @@ -312,7 +327,7 @@ public class ReplayProcess { } } else { if(posCount == 1) { - pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition(); + pos = ReplayHandler.getFirstPositionKeyframe().getPosition(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index ae508d14..a832d94a 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -141,7 +141,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { * If hurrying, don't wait for correct timing. */ - if(!hurryToTimestamp && ReplayHandler.isInPath()) { continue; } @@ -149,7 +148,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { PacketData pd = ReplayFileIO.readPacketData(dis); currentTimeStamp = pd.getTimestamp(); - //System.out.println(currentTimeStamp); if(!ReplayHandler.isInPath() && !hurryToTimestamp && hasWorldLoaded) { int timeWait = (int) Math.round((currentTimeStamp - lastTimeStamp) / replaySpeed); diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index c0105f09..9d68d2e0 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -137,4 +137,11 @@ replaymod.gui.settings.videoquality.good=Good replaymod.gui.settings.videoquality.best=Best replaymod.gui.settings.warning.linea=WARNING: Recording settings will be -replaymod.gui.settings.warning.lineb=applied the next time you join a world. \ No newline at end of file +replaymod.gui.settings.warning.lineb=applied the next time you join a world. + +#Replay Mod Keybindings +replaymod.input.lighting=Toggle Lighting +replaymod.input.thumbnail=Capture Thumbnail +replaymod.input.spectate=Spectate Players +replaymod.input.clearkeyframes=Clear Keyframes +replaymod.input.synctimeline=Synchronize Timeline \ No newline at end of file