diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index 85c264e0..f18155a4 100755 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -3,7 +3,7 @@ package eu.crushedpixel.replaymod; import com.google.common.util.concurrent.ListenableFutureTask; import eu.crushedpixel.replaymod.api.ApiClient; import eu.crushedpixel.replaymod.chat.ChatMessageHandler; -import eu.crushedpixel.replaymod.events.*; +import eu.crushedpixel.replaymod.events.handlers.*; import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; import eu.crushedpixel.replaymod.holders.KeyframeSet; import eu.crushedpixel.replaymod.localization.LocalizedResourcePack; @@ -11,6 +11,8 @@ import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.registry.*; import eu.crushedpixel.replaymod.renderer.InvisibilityRender; +import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer; +import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayProcess; @@ -69,6 +71,7 @@ public class ReplayMod { public static RatedFileHandler ratedFileHandler; public static SpectatorRenderer spectatorRenderer; public static TooltipRenderer tooltipRenderer; + public static PathPreviewRenderer pathPreviewRenderer; // The instance of your mod that Forge uses. @Instance(value = "ReplayModID") @@ -122,13 +125,17 @@ public class ReplayMod { spectatorRenderer = new SpectatorRenderer(); + pathPreviewRenderer = new PathPreviewRenderer(); + FMLCommonHandler.instance().bus().register(pathPreviewRenderer); + MinecraftForge.EVENT_BUS.register(pathPreviewRenderer); + KeybindRegistry.initialize(); -// try { -// mc.entityRenderer = new SafeEntityRenderer(mc, mc.entityRenderer); -// } catch(Exception e) { -// e.printStackTrace(); -// } + try { + mc.entityRenderer = new SafeEntityRenderer(mc, mc.entityRenderer); + } catch(Exception e) { + e.printStackTrace(); + } tooltipRenderer = new TooltipRenderer(); diff --git a/src/main/java/eu/crushedpixel/replaymod/events/KeyframesModifyEvent.java b/src/main/java/eu/crushedpixel/replaymod/events/KeyframesModifyEvent.java new file mode 100644 index 00000000..86dc5195 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/events/KeyframesModifyEvent.java @@ -0,0 +1,15 @@ +package eu.crushedpixel.replaymod.events; + +import eu.crushedpixel.replaymod.holders.Keyframe; +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.List; + +public class KeyframesModifyEvent extends Event { + + public List keyframes; + + public KeyframesModifyEvent(List keyframes) { + this.keyframes = keyframes; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java index 0863fb55..d442ab40 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.gui.GuiConstants; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/KeyInputHandler.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/KeyInputHandler.java index 1d2e6dab..3c21b024 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/KeyInputHandler.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/MinecraftTicker.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/events/MinecraftTicker.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java index 1ccc8c03..a2ea2193 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/MinecraftTicker.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.ReplayMod; import net.minecraft.client.Minecraft; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/MouseInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java similarity index 95% rename from src/main/java/eu/crushedpixel/replaymod/events/MouseInputHandler.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java index e9b66dc9..e0ffcf3b 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/MouseInputHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.replay.ReplayHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java index 620f6875..6475769d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import io.netty.buffer.ByteBuf; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java similarity index 98% rename from src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java rename to src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java index c80b52ba..e5855e9a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/TickAndRenderListener.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.events; +package eu.crushedpixel.replaymod.events.handlers; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java index 85d9744c..14dde1ba 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java @@ -1,6 +1,7 @@ package eu.crushedpixel.replaymod.gui; import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.events.KeyframesModifyEvent; import eu.crushedpixel.replaymod.gui.elements.GuiArrowButton; import eu.crushedpixel.replaymod.gui.elements.GuiNumberInput; import eu.crushedpixel.replaymod.holders.*; @@ -10,6 +11,7 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.common.FMLCommonHandler; import org.lwjgl.input.Keyboard; import java.awt.*; @@ -195,6 +197,7 @@ public class GuiEditKeyframe extends GuiScreen { ((MarkerKeyframe)keyframe).setName(markerNameInput.getText().trim()); } } + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(ReplayHandler.getKeyframes())); Keyboard.enableRepeatEvents(false); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java index 6b46643c..3a129ff7 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java @@ -1,9 +1,8 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.settings.ReplaySettings; +import eu.crushedpixel.replaymod.gui.elements.GuiSettingsOnOffButton; +import eu.crushedpixel.replaymod.gui.elements.GuiToggleButton; import eu.crushedpixel.replaymod.settings.ReplaySettings.RecordingOptions; -import eu.crushedpixel.replaymod.settings.ReplaySettings.RenderOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; @@ -16,20 +15,18 @@ import java.io.IOException; public class GuiReplaySettings extends GuiScreen { //TODO: Move to GuiConstants - private static final int QUALITY_SLIDER_ID = 9003; private static final int RECORDSERVER_ID = 9004; private static final int RECORDSP_ID = 9005; private static final int SEND_CHAT = 9006; private static final int FORCE_LINEAR = 9007; private static final int ENABLE_LIGHTING = 9008; - private static final int FRAMERATE_SLIDER_ID = 9009; private static final int RESOURCEPACK_ID = 9010; - private static final int WAITFORCHUNKS_ID = 9011; private static final int INDICATOR_ID = 9012; + private static final int PATHPREVIEW_ID = 9013; protected String screenTitle = I18n.format("replaymod.gui.settings.title"); private GuiScreen parentGuiScreen; - private GuiButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton, - resourcePackButton, waitForChunksButton, showIndicatorButton; + private GuiToggleButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton, + resourcePackButton, showIndicatorButton, pathPreviewButton; public GuiReplaySettings(GuiScreen parentGuiScreen) { this.parentGuiScreen = parentGuiScreen; @@ -40,32 +37,31 @@ public class GuiReplaySettings extends GuiScreen { this.buttonList.clear(); this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height - 27, I18n.format("gui.done"))); - ReplaySettings settings = ReplayMod.replaySettings; - - int k = 0; int i = 0; for(RecordingOptions o : RecordingOptions.values()) { + + int xPos = this.width / 2 - 155 + i % 2 * 160; + int yPos = this.height / 6 + 24 * (i >> 1); + if(o == RecordingOptions.notifications) { - this.buttonList.add(sendChatButton = new GuiButton(SEND_CHAT, - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - I18n.format("replaymod.gui.settings.notifications")+": " + onOff(settings.isShowNotifications()))); + sendChatButton = new GuiSettingsOnOffButton(SEND_CHAT, xPos, yPos, 150, 20, o); + this.buttonList.add(sendChatButton); + } else if(o == RecordingOptions.recordServer) { - this.buttonList.add(recordServerButton = new GuiButton(RECORDSERVER_ID, - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - I18n.format("replaymod.gui.settings.recordserver")+": " - + onOff(settings.isEnableRecordingServer()))); + recordServerButton = new GuiSettingsOnOffButton(RECORDSERVER_ID, xPos, yPos, 150, 20, o); + this.buttonList.add(recordServerButton); + } else if(o == RecordingOptions.recordSingleplayer) { - this.buttonList.add(recordSPButton = new GuiButton(RECORDSP_ID, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.recordsingleplayer")+": " - + onOff(settings.isEnableRecordingSingleplayer()))); + recordSPButton = new GuiSettingsOnOffButton(RECORDSP_ID, xPos, yPos, 150, 20, o); + this.buttonList.add(recordSPButton); + } else if(o == RecordingOptions.indicator) { - this.buttonList.add(showIndicatorButton = new GuiButton(INDICATOR_ID, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.indicator")+": "+ onOff(settings.showRecordingIndicator()))); + showIndicatorButton = new GuiSettingsOnOffButton(INDICATOR_ID, xPos, yPos, 150, 20, o); + this.buttonList.add(showIndicatorButton); } ++i; - ++k; } @@ -74,48 +70,34 @@ public class GuiReplaySettings extends GuiScreen { } for(ReplayOptions o : ReplayOptions.values()) { + + int xPos = this.width / 2 - 155 + i % 2 * 160; + int yPos = this.height / 6 + 24 * (i >> 1); + if(o == ReplayOptions.lighting) { - this.buttonList.add(lightingButton = new GuiButton(ENABLE_LIGHTING, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.lighting")+": " + onOff(settings.isLightingEnabled()))); + lightingButton = new GuiSettingsOnOffButton(ENABLE_LIGHTING, xPos, yPos, 150, 20, o); + this.buttonList.add(lightingButton); + } else if(o == ReplayOptions.linear) { - this.buttonList.add(linearButton = new GuiButton(FORCE_LINEAR, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.interpolation")+": " + linearOnOff(settings.isLinearMovement()))); + linearButton = new GuiSettingsOnOffButton(FORCE_LINEAR, xPos, yPos, 150, 20, o, + I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic")); + this.buttonList.add(linearButton); + } else if(o == ReplayOptions.useResources) { - this.buttonList.add(resourcePackButton = new GuiButton(RESOURCEPACK_ID, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.resources")+": " + onOff(settings.getUseResourcePacks()))); + resourcePackButton = new GuiSettingsOnOffButton(RESOURCEPACK_ID, xPos, yPos, 150, 20, o); + this.buttonList.add(resourcePackButton); + + } else if(o == ReplayOptions.previewPath) { + pathPreviewButton = new GuiSettingsOnOffButton(PATHPREVIEW_ID, xPos, yPos, 150, 20, o); + this.buttonList.add(pathPreviewButton); } ++i; - ++k; } if(i % 2 == 1) { ++i; } - - for(RenderOptions o : RenderOptions.values()) { - if(o == RenderOptions.videoFramerate) { - this.buttonList.add(new GuiVideoFramerateSlider(FRAMERATE_SLIDER_ID, - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), settings.getVideoFramerate(), I18n.format("replaymod.gui.settings.framerate"))); - } else if(o == RenderOptions.videoQuality) { - this.buttonList.add(new GuiVideoQualitySlider(QUALITY_SLIDER_ID, - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), (float) settings.getVideoQuality(), I18n.format("replaymod.gui.settings.quality"))); - } else if(o == RenderOptions.waitForChunks) { - this.buttonList.add(waitForChunksButton = new GuiButton(WAITFORCHUNKS_ID, this.width / 2 - 155 + i % 2 * 160, - this.height / 6 + 24 * (i >> 1), 150, 20, I18n.format("replaymod.gui.settings.forcechunks")+": " + onOff(settings.getWaitForChunks()))); - } - - ++i; - ++k; - } - } - - private String onOff(boolean on) { - return on ? I18n.format("options.on") : I18n.format("options.off"); - } - - private String linearOnOff(boolean on) { - return on ? I18n.format("replaymod.gui.settings.interpolation.linear") : I18n.format("replaymod.gui.settings.interpolation.cubic"); } @Override @@ -136,54 +118,10 @@ public class GuiReplaySettings extends GuiScreen { case 200: this.mc.displayGuiScreen(this.parentGuiScreen); break; - case RECORDSERVER_ID: - boolean enabled = ReplayMod.replaySettings.isEnableRecordingServer(); - enabled = !enabled; - recordServerButton.displayString = I18n.format("replaymod.gui.settings.recordserver")+": " + onOff(enabled); - ReplayMod.replaySettings.setEnableRecordingServer(enabled); - break; - case RECORDSP_ID: - enabled = ReplayMod.replaySettings.isEnableRecordingSingleplayer(); - enabled = !enabled; - recordSPButton.displayString = I18n.format("replaymod.gui.settings.recordsingleplayer")+": " + onOff(enabled); - ReplayMod.replaySettings.setEnableRecordingSingleplayer(enabled); - break; - case SEND_CHAT: - enabled = ReplayMod.replaySettings.isShowNotifications(); - enabled = !enabled; - sendChatButton.displayString = I18n.format("replaymod.gui.settings.notifications")+": " + onOff(enabled); - ReplayMod.replaySettings.setShowNotifications(enabled); - break; - case FORCE_LINEAR: - enabled = ReplayMod.replaySettings.isLinearMovement(); - enabled = !enabled; - linearButton.displayString = I18n.format("replaymod.gui.settings.interpolation")+": " + linearOnOff(enabled); - ReplayMod.replaySettings.setLinearMovement(enabled); - break; - case ENABLE_LIGHTING: - enabled = ReplayMod.replaySettings.isLightingEnabled(); - enabled = !enabled; - lightingButton.displayString = I18n.format("replaymod.gui.settings.lighting")+": " + onOff(enabled); - ReplayMod.replaySettings.setLightingEnabled(enabled); - break; - case RESOURCEPACK_ID: - enabled = ReplayMod.replaySettings.getUseResourcePacks(); - enabled = !enabled; - resourcePackButton.displayString = I18n.format("replaymod.gui.settings.resources")+": " + onOff(enabled); - ReplayMod.replaySettings.setUseResourcePacks(enabled); - break; - case WAITFORCHUNKS_ID: - enabled = ReplayMod.replaySettings.getWaitForChunks(); - enabled = !enabled; - waitForChunksButton.displayString = I18n.format("replaymod.gui.settings.forcechunks")+": " + onOff(enabled); - ReplayMod.replaySettings.setWaitForChunks(enabled); - break; - case INDICATOR_ID: - enabled = ReplayMod.replaySettings.showRecordingIndicator(); - enabled = !enabled; - showIndicatorButton.displayString = I18n.format("replaymod.gui.settings.indicator")+": " + onOff(enabled); - ReplayMod.replaySettings.setEnableIndicator(enabled); - break; + } + + if(button instanceof GuiToggleButton) { + ((GuiToggleButton) button).toggle(); } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiOnOffButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiOnOffButton.java new file mode 100644 index 00000000..3c9e0cba --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiOnOffButton.java @@ -0,0 +1,24 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import net.minecraft.client.resources.I18n; + +public class GuiOnOffButton extends GuiToggleButton { + + private static final String[] values = new String[] {I18n.format("options.on"), I18n.format("options.off")}; + + public GuiOnOffButton(int buttonId, int x, int y, String buttonText) { + super(buttonId, x, y, buttonText, values); + } + + public GuiOnOffButton(int buttonId, int x, int y, int width, int height, String buttonText) { + super(buttonId, x, y, width, height, buttonText, values); + } + + public GuiOnOffButton(int buttonId, int x, int y, int width, int height, String buttonText, String onValue, String offValue) { + super(buttonId, x, y, width, height, buttonText, new String[] {onValue, offValue}); + } + + public boolean isOn() { + return getValue() == 0; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java new file mode 100644 index 00000000..1c9386fa --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java @@ -0,0 +1,39 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.settings.ReplaySettings; + +public class GuiSettingsOnOffButton extends GuiOnOffButton { + + private ReplaySettings.ValueEnum toChange; + + public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange) { + super(buttonId, x, y, width, height, toChange.getName()+": "); + this.toChange = toChange; + if(toChange.getValue() instanceof Boolean) { + this.setValue((Boolean) toChange.getValue() == true ? 0 : 1); + } + } + + public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange, String onValue, String offValue) { + super(buttonId, x, y, width, height, toChange.getName()+": ", onValue, offValue); + this.toChange = toChange; + if(toChange.getValue() instanceof Boolean) { + this.setValue((Boolean) toChange.getValue() == true ? 0 : 1); + } + } + + @Override + public void toggle() { + super.toggle(); + toChange.setValue(isOn()); + ReplayMod.replaySettings.rewriteSettings(); + } + + @Override + public void setValue(int value) { + super.setValue(value); + toChange.setValue(isOn()); + ReplayMod.replaySettings.rewriteSettings(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java index ca66d04e..f4105dc6 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiToggleButton.java @@ -20,6 +20,12 @@ public class GuiToggleButton extends GuiAdvancedButton { this.displayString = baseText+values[value]; } + public GuiToggleButton(int buttonId, int x, int y, int width, int height, String buttonText, String[] values) { + this(buttonId, x, y, buttonText, values); + this.width = width; + this.height = height; + } + @Override public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) { boolean success = super.mousePressed(mc, mouseX, mouseY); @@ -41,6 +47,7 @@ public class GuiToggleButton extends GuiAdvancedButton { public void setValue(int value) { this.value = value; + this.displayString = baseText+values[value]; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java index 74ac6e73..cbd712a5 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java @@ -180,7 +180,7 @@ public class GuiReplayOverlay extends Gui { @Override public GuiElement delegate() { boolean selected = ReplayHandler.getSelectedKeyframe() instanceof PositionKeyframe; - boolean camera = true; + boolean camera; if(selected) { camera = ((PositionKeyframe)ReplayHandler.getSelectedKeyframe()).getSpectatedEntityID() == null; } else { diff --git a/src/main/java/eu/crushedpixel/replaymod/holders/Position.java b/src/main/java/eu/crushedpixel/replaymod/holders/Position.java index 94b4a89a..ac7b6096 100755 --- a/src/main/java/eu/crushedpixel/replaymod/holders/Position.java +++ b/src/main/java/eu/crushedpixel/replaymod/holders/Position.java @@ -82,6 +82,14 @@ public class Position { public void setRoll(float roll) { this.roll = roll; } + public double distanceTo(double x, double y, double z) { + return distanceTo(new Position(x, y, z, 0, 0)); + } + + public double distanceTo(Position p2) { + return Math.sqrt(Math.pow((p2.getX() - getX()), 2) + Math.pow((p2.getY() - getY()), 2) + Math.pow((p2.getZ() - getZ()), 2)); + } + @Override public String toString() { return "X=" + x + ", Y=" + y + ", Z=" + z + ", Yaw=" + yaw + ", Pitch=" + pitch + ", Roll="+roll; diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java new file mode 100644 index 00000000..edcff6f5 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java @@ -0,0 +1,231 @@ +package eu.crushedpixel.replaymod.renderer; + +import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.events.KeyframesModifyEvent; +import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; +import eu.crushedpixel.replaymod.holders.Keyframe; +import eu.crushedpixel.replaymod.holders.Position; +import eu.crushedpixel.replaymod.holders.PositionKeyframe; +import eu.crushedpixel.replaymod.interpolation.SplinePoint; +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.entity.Entity; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class PathPreviewRenderer { + + private static final Minecraft mc = Minecraft.getMinecraft(); + + private SplinePoint spline = new SplinePoint(); + + private DistanceComparator distanceComparator = new DistanceComparator(); + + private List keyframes = new ArrayList(); + + @SubscribeEvent + public void renderCameraPath(RenderWorldLastEvent event) { + if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview()) return; + + Entity entity = ReplayHandler.getCameraEntity(); + if(entity == null) return; + + double doubleX = entity.posX; + double doubleY = entity.posY; + double doubleZ = entity.posZ; + + GlStateManager.pushAttrib(); + GlStateManager.pushMatrix(); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + + GlStateManager.disableTexture2D(); + + if(spline.getPoints().size() > 1) { + + Position prev = null; + + if(ReplayMod.replaySettings.isLinearMovement()) { + + for(int i = 0; i < spline.getPoints().size(); i++) { + Position point = spline.getPoints().get(i); + + if(prev != null) { + drawConnection(doubleX, doubleY, doubleZ, prev, point, Color.RED.getRGB()); + } + + prev = point; + } + + } else { + + float max = spline.getPoints().size() * 50; + for(int i = 0; i < max; i++) { + Position point = spline.getPoint(i / max); + + if(prev != null) { + drawConnection(doubleX, doubleY, doubleZ, prev, point, Color.RED.getRGB()); + } + + prev = point; + } + } + } + + + distanceComparator.setPlayerPos(doubleX, doubleY + 1.4, doubleZ); + + Collections.sort(keyframes, distanceComparator); + + for(PositionKeyframe kf : keyframes) { + drawPoint(doubleX, doubleY, doubleZ, kf); + } + + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + + GlStateManager.disableBlend(); + GlStateManager.popAttrib(); + GlStateManager.popMatrix(); + } + + @SubscribeEvent + public void recalcSpline(KeyframesModifyEvent event) { + keyframes = new ArrayList(); + spline = new SplinePoint(); + for(Keyframe kf : event.keyframes) { + if(kf instanceof PositionKeyframe) { + PositionKeyframe pkf = (PositionKeyframe)kf; + Position pos = pkf.getPosition(); + spline.addPoint(pos); + keyframes.add(pkf); + } + } + + if(spline.getPoints().size() > 1) { + spline.prepare(); + } + } + + private class DistanceComparator implements Comparator { + + private double playerX, playerY, playerZ; + + public void setPlayerPos(double playerX, double playerY, double playerZ) { + this.playerX = playerX; + this.playerY = playerY; + this.playerZ = playerZ; + } + + @Override + public int compare(PositionKeyframe o1, PositionKeyframe o2) { + return -(new Double(o1.getPosition().distanceTo(playerX, playerY, playerZ)).compareTo(o2.getPosition().distanceTo(playerX, playerY, playerZ))); + } + + @Override + public boolean equals(Object obj) { + return false; + } + } + + private void drawConnection(double playerX, double playerY, double playerZ, Position pos1, Position pos2, int color) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + + GL11.glLineWidth(3.0F); + + double x = pos1.getX() - playerX; + double y = pos1.getY() - playerY; + double z = pos1.getZ() - playerZ; + + renderer.setTranslation(x, y+1.4, z); + + renderer.startDrawing(1); + + renderer.setColorRGBA_I(color, 50); + + renderer.addVertex(pos2.getX() - pos1.getX(), pos2.getY() - pos1.getY(), pos2.getZ() - pos1.getZ()); + renderer.addVertex(0, 0, 0); + + tessellator.draw(); + renderer.setTranslation(0, 0, 0); + } + + private void drawPoint(double playerX, double playerY, double playerZ, PositionKeyframe kf) { + GlStateManager.pushMatrix(); + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.disableLighting(); + GlStateManager.enableAlpha(); + + GlStateManager.enableBlend(); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + + mc.renderEngine.bindTexture(GuiReplayOverlay.replay_gui); + + Position pos1 = kf.getPosition(); + + double x = pos1.getX() - playerX; + double y = pos1.getY() - playerY; + double z = pos1.getZ() - playerZ; + + GlStateManager.translate(x, y+1.4, z); + + float pitch = mc.getRenderManager().playerViewX; + float yaw = mc.getRenderManager().playerViewY; + + GL11.glNormal3f(0, 1, 0); + + GlStateManager.rotate(-yaw, 0, 1, 0); + GlStateManager.rotate(pitch, 1, 0, 0); + + renderer.setColorRGBA_F(1, 1, 1, 0.5f); + + renderer.startDrawingQuads(); + + float posX = 80/128f; + float posY = 0; + float size = 10/128f; + + + if(kf.equals(ReplayHandler.getSelectedKeyframe())) { + posY += size; + } + + if(kf.getSpectatedEntityID() != null) { + posX += size; + } + + renderer.addVertexWithUV(-0.5, 0.5, 0, posX+size, posY); + renderer.addVertexWithUV(0.5, 0.5, 0, posX+size, posY+size); + renderer.addVertexWithUV(-0.5, -0.5, 0, posX, posY); + renderer.addVertexWithUV(0.5, -0.5, 0, posX, posY+size); + + renderer.addVertexWithUV(0.5, -0.5, 0, posX+size, posY); + renderer.addVertexWithUV(-0.5, -0.5, 0, posX, posY); + renderer.addVertexWithUV(0.5, 0.5, 0, posX+size, posY+size); + renderer.addVertexWithUV(-0.5, 0.5, 0, posX, posY + size); + + tessellator.draw(); + renderer.setTranslation(0, 0, 0); + + GlStateManager.disableAlpha(); + GlStateManager.disableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/SafeEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/SafeEntityRenderer.java index 5bc9bf28..f5c0439e 100755 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/SafeEntityRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/SafeEntityRenderer.java @@ -14,6 +14,7 @@ public class SafeEntityRenderer extends EntityRenderer { try { super.updateCameraAndRender(partialTicks); } catch(Exception e) { + e.printStackTrace(); } //This is plain easier than doing proper error prevention. //If Johni reads this, don't think I'm a bad programmer... Just a lazy one :P } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index 153d0ef9..f4479001 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -3,6 +3,7 @@ package eu.crushedpixel.replaymod.replay; import com.mojang.authlib.GameProfile; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.entities.CameraEntity; +import eu.crushedpixel.replaymod.events.KeyframesModifyEvent; import eu.crushedpixel.replaymod.holders.*; import eu.crushedpixel.replaymod.registry.PlayerHandler; import eu.crushedpixel.replaymod.settings.RenderOptions; @@ -92,6 +93,8 @@ public class ReplayHandler { e.printStackTrace(); } } + + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes)); } public static void useKeyframePresetFromRepository(int index) { @@ -104,6 +107,8 @@ public class ReplayHandler { } if(!(selectedKeyframe instanceof MarkerKeyframe)) selectedKeyframe = null; + + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes)); } public static void spectateEntity(Entity e) { @@ -214,6 +219,8 @@ public class ReplayHandler { a = b; } } + + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes)); } public static void removeKeyframe(Keyframe keyframe) { @@ -223,6 +230,8 @@ public class ReplayHandler { } else { sortKeyframes(); } + + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes)); } public static int getKeyframeIndex(TimeKeyframe timeKeyframe) { @@ -430,6 +439,8 @@ public class ReplayHandler { } else { selectKeyframe(null); } + + FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(keyframes)); } public static boolean isSelected(Keyframe kf) { diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index 8aedbb20..8d97ec95 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -5,7 +5,7 @@ import com.google.common.io.Files; import com.google.common.util.concurrent.ListenableFutureTask; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.events.RecordingHandler; +import eu.crushedpixel.replaymod.events.handlers.RecordingHandler; import eu.crushedpixel.replaymod.holders.PacketData; import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.timer.MCTimerHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java index 6f2540d9..d7431991 100755 --- a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java @@ -2,6 +2,7 @@ package eu.crushedpixel.replaymod.settings; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.registry.LightingHandler; +import net.minecraft.client.resources.I18n; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; @@ -149,6 +150,13 @@ public class ReplaySettings { rewriteSettings(); } + public boolean showPathPreview() { return (Boolean) ReplayOptions.previewPath.getValue(); }; + + public void setShowPathPreview(boolean show) { + ReplayOptions.previewPath.setValue(show); + rewriteSettings(); + } + public void rewriteSettings() { ReplayMod.instance.config.load(); @@ -218,12 +226,17 @@ public class ReplaySettings { } public enum RecordingOptions implements ValueEnum { - recordServer(true), recordSingleplayer(true), notifications(true), indicator(true); + recordServer(true, "replaymod.gui.settings.recordserver"), + recordSingleplayer(true, "replaymod.gui.settings.recordsingleplayer"), + notifications(true, "replaymod.gui.settings.notifications"), + indicator(true, "replaymod.gui.settings.indicator"); private Object value; + private String name; - RecordingOptions(Object value) { + RecordingOptions(Object value, String name) { this.value = value; + this.name = name; } public Object getValue() { @@ -233,15 +246,22 @@ public class ReplaySettings { public void setValue(Object value) { this.value = value; } + + public String getName() { return I18n.format(name); }; } public enum ReplayOptions implements ValueEnum { - linear(false), lighting(false), useResources(true); + linear(false, "replaymod.gui.settings.interpolation"), + lighting(false, "replaymod.gui.settings.lighting"), + useResources(true, "replaymod.gui.settings.resources"), + previewPath(true, "replaymod.gui.settings.pathpreview"); private Object value; + private String name; - ReplayOptions(Object value) { + ReplayOptions(Object value, String name) { this.value = value; + this.name = name; } public Object getValue() { @@ -251,15 +271,21 @@ public class ReplaySettings { public void setValue(Object value) { this.value = value; } + + public String getName() { return I18n.format(name); }; } public enum RenderOptions implements ValueEnum { - videoQuality(0.5f), videoFramerate(30), waitForChunks(true); + videoQuality(0.5f, "replaymod.gui.settings.quality"), + videoFramerate(30, "replaymod.gui.settings.framerate"), + waitForChunks(true, "replaymod.gui.settings.forcechunks"); private Object value; + private String name; - RenderOptions(Object value) { + RenderOptions(Object value, String name) { this.value = value; + this.name = name; } public Object getValue() { @@ -269,15 +295,21 @@ public class ReplaySettings { public void setValue(Object value) { this.value = value; } + + public String getName() { return I18n.format(name); }; } public enum AdvancedOptions implements ValueEnum { - recordingPath("./replay_recordings/"), renderPath("./replay_videos/"), downloadPath("./replay_downloads"); + recordingPath("./replay_recordings/", ""), + renderPath("./replay_videos/", ""), + downloadPath("./replay_downloads", ""); private Object value; + private String name; - AdvancedOptions(Object value) { + AdvancedOptions(Object value, String name) { this.value = value; + this.name = name; } public Object getValue() { @@ -287,11 +319,15 @@ public class ReplaySettings { public void setValue(Object value) { this.value = value; } + + public String getName() { return I18n.format(name); }; } public interface ValueEnum { Object getValue(); void setValue(Object value); + + String getName(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java b/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java index 32b6a645..d1e43296 100755 --- a/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java @@ -2,7 +2,7 @@ package eu.crushedpixel.replaymod.video; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType; -import eu.crushedpixel.replaymod.events.TickAndRenderListener; +import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.ImageUtils; import net.minecraft.client.Minecraft; diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 03d82d55..985ac5ce 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -210,6 +210,7 @@ replaymod.gui.settings.lighting=Ambient Lighting replaymod.gui.settings.forcechunks=Force Render Chunks replaymod.gui.settings.resources=Server Resource Packs replaymod.gui.settings.interpolation=Path Interpolation +replaymod.gui.settings.pathpreview=Show Path Preview replaymod.gui.settings.videoquality.draft=Draft replaymod.gui.settings.videoquality.normal=Normal diff --git a/src/main/resources/assets/replaymod/replay_gui.png b/src/main/resources/assets/replaymod/replay_gui.png index 526925d9..64648ab2 100755 Binary files a/src/main/resources/assets/replaymod/replay_gui.png and b/src/main/resources/assets/replaymod/replay_gui.png differ