diff --git a/build.gradle b/build.gradle index 6182fa4e..df206de6 100755 --- a/build.gradle +++ b/build.gradle @@ -119,7 +119,7 @@ jar { manifest { attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker', 'TweakOrder': '0', - 'MixinConfigs': 'mixins.replaymod.json', + 'MixinConfigs': 'mixins.replaymod.json,mixins.recording.replaymod.json', 'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin', 'FMLAT': 'replaymod_at.cfg' } diff --git a/libs/replaystudio-0.0.1-SNAPSHOT-all.jar b/libs/replaystudio-0.0.1-SNAPSHOT-all.jar index d08f9102..9d462c12 100644 Binary files a/libs/replaystudio-0.0.1-SNAPSHOT-all.jar and b/libs/replaystudio-0.0.1-SNAPSHOT-all.jar differ diff --git a/src/main/java/com/replaymod/core/KeyBindingRegistry.java b/src/main/java/com/replaymod/core/KeyBindingRegistry.java new file mode 100644 index 00000000..24a3807b --- /dev/null +++ b/src/main/java/com/replaymod/core/KeyBindingRegistry.java @@ -0,0 +1,60 @@ +package com.replaymod.core; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.crash.CrashReport; +import net.minecraft.crash.CrashReportCategory; +import net.minecraft.util.ReportedException; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Callable; + +public class KeyBindingRegistry { + private Map keyBindings = new HashMap(); + private Multimap keyBindingHandlers = ArrayListMultimap.create(); + + public void registerKeyBinding(String name, int keyCode, Runnable whenPressed) { + KeyBinding keyBinding = keyBindings.get(name); + if (keyBinding == null) { + keyBinding = new KeyBinding(name, keyCode, "replaymod.title"); + keyBindings.put(name, keyBinding); + ClientRegistry.registerKeyBinding(keyBinding); + } + keyBindingHandlers.put(keyBinding, whenPressed); + } + + public Map getKeyBindings() { + return Collections.unmodifiableMap(keyBindings); + } + + @SubscribeEvent + public void onKeyInput(InputEvent.KeyInputEvent event) { + for (Map.Entry> entry : keyBindingHandlers.asMap().entrySet()) { + while (entry.getKey().isPressed()) { + for (final Runnable runnable : entry.getValue()) { + try { + runnable.run(); + } catch (Throwable cause) { + CrashReport crashReport = CrashReport.makeCrashReport(cause, "Handling Key Binding"); + CrashReportCategory category = crashReport.makeCategory("Key Binding"); + category.addCrashSection("Key Binding", entry.getKey()); + category.addCrashSectionCallable("Handler", new Callable() { + @Override + public Object call() throws Exception { + return runnable; + } + }); + throw new ReportedException(crashReport); + } + } + } + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java similarity index 82% rename from src/main/java/eu/crushedpixel/replaymod/ReplayMod.java rename to src/main/java/com/replaymod/core/ReplayMod.java index ffd90e6a..7c97eeee 100755 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -1,34 +1,30 @@ -package eu.crushedpixel.replaymod; +package com.replaymod.core; import com.google.common.util.concurrent.ListenableFutureTask; +import com.replaymod.replay.ReplaySender; import eu.crushedpixel.replaymod.api.ApiClient; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import eu.crushedpixel.replaymod.chat.ChatMessageHandler; -import eu.crushedpixel.replaymod.events.handlers.*; +import eu.crushedpixel.replaymod.events.handlers.CrosshairRenderHandler; +import eu.crushedpixel.replaymod.events.handlers.GuiEventHandler; +import eu.crushedpixel.replaymod.events.handlers.MouseInputHandler; +import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener; import eu.crushedpixel.replaymod.events.handlers.keyboard.KeyInputHandler; import eu.crushedpixel.replaymod.gui.online.GuiReplayDownloading; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.holders.KeyframeSet; import eu.crushedpixel.replaymod.localization.LocalizedResourcePack; import eu.crushedpixel.replaymod.online.authentication.ConfigurationAuthData; import eu.crushedpixel.replaymod.online.urischeme.UriScheme; -import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.registry.*; import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer; import eu.crushedpixel.replaymod.renderer.InvisibilityRender; import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplayProcess; -import eu.crushedpixel.replaymod.replay.ReplaySender; import eu.crushedpixel.replaymod.settings.EncodingPreset; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.sound.SoundHandler; import eu.crushedpixel.replaymod.timer.ReplayTimer; import eu.crushedpixel.replaymod.utils.OpenGLUtils; -import eu.crushedpixel.replaymod.utils.ReplayFile; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; import eu.crushedpixel.replaymod.utils.TooltipRenderer; import eu.crushedpixel.replaymod.video.rendering.Pipelines; import lombok.Getter; @@ -38,6 +34,7 @@ import net.minecraft.client.resources.IResourcePack; import net.minecraft.client.settings.GameSettings; import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReportCategory; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.client.FMLClientHandler; @@ -50,6 +47,7 @@ import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.File; @@ -61,14 +59,11 @@ import java.util.List; import java.util.Map; import java.util.Queue; -import static org.apache.commons.io.FileUtils.forceDelete; -import static org.apache.commons.io.FileUtils.listFiles; - -@Mod(modid = ReplayMod.MODID, useMetadata = true) +@Mod(modid = ReplayMod.MOD_ID, useMetadata = true) public class ReplayMod { public static ModContainer getContainer() { - return Loader.instance().getIndexedModList().get(MODID); + return Loader.instance().getIndexedModList().get(MOD_ID); } @Getter(lazy = true) @@ -85,14 +80,16 @@ public class ReplayMod { return "Unknown"; } - public static final String MODID = "replaymod"; + public static final String MOD_ID = "replaymod"; + + public static final ResourceLocation TEXTURE = new ResourceLocation("replaymod", "replay_gui.png"); + public static final int TEXTURE_SIZE = 128; + private static final Minecraft mc = Minecraft.getMinecraft(); public static GuiEventHandler guiEventHandler; - public static GuiReplayOverlay overlay; public static ReplaySettings replaySettings; public static Configuration config; public static boolean firstMainMenu = true; - public static RecordingHandler recordingHandler; public static ChatMessageHandler chatMessageHandler = new ChatMessageHandler(); public static KeyInputHandler keyInputHandler = new KeyInputHandler(); public static MouseInputHandler mouseInputHandler = new MouseInputHandler(); @@ -111,13 +108,30 @@ public class ReplayMod { public static CrosshairRenderHandler crosshairRenderHandler; public static ApiClient apiClient; + private final KeyBindingRegistry keyBindingRegistry = new KeyBindingRegistry(); + private final SettingsRegistry settingsRegistry = new SettingsRegistry(); + @Getter private static boolean latestModVersion = true; // The instance of your mod that Forge uses. - @Instance(value = "ReplayModID") + @Instance(MOD_ID) public static ReplayMod instance; + public KeyBindingRegistry getKeyBindingRegistry() { + return keyBindingRegistry; + } + + public SettingsRegistry getSettingsRegistry() { + return settingsRegistry; + } + + public File getReplayFolder() throws IOException { + File folder = new File(replaySettings.getRecordingPath()); + FileUtils.forceMkdir(folder); + return folder; + } + @EventHandler public void preInit(FMLPreInitializationEvent event) { try { @@ -137,6 +151,7 @@ public class ReplayMod { config = new Configuration(event.getSuggestedConfigurationFile()); config.load(); + settingsRegistry.setConfiguration(config); ConfigurationAuthData authData = new ConfigurationAuthData(config); apiClient = new ApiClient(authData); authData.load(apiClient); @@ -144,7 +159,6 @@ public class ReplayMod { uploadedFileHandler = new UploadedFileHandler(event.getModConfigurationDirectory()); replaySettings = new ReplaySettings(); - replaySettings.readValues(); downloadedFileHandler = new DownloadedFileHandler(); favoritedFileHandler = new FavoritedFileHandler(); @@ -164,27 +178,22 @@ public class ReplayMod { @EventHandler public void init(FMLInitializationEvent event) { mc.timer = new ReplayTimer(); - overlay = new GuiReplayOverlay(); - FMLCommonHandler.instance().bus().register(new ConnectionEventHandler()); MinecraftForge.EVENT_BUS.register(guiEventHandler = new GuiEventHandler()); FMLCommonHandler.instance().bus().register(keyInputHandler); + FMLCommonHandler.instance().bus().register(keyBindingRegistry); FMLCommonHandler.instance().bus().register(mouseInputHandler); MinecraftForge.EVENT_BUS.register(mouseInputHandler); - - recordingHandler = new RecordingHandler(); - FMLCommonHandler.instance().bus().register(recordingHandler); - MinecraftForge.EVENT_BUS.register(recordingHandler); } @EventHandler public void postInit(FMLPostInitializationEvent event) throws IOException { + settingsRegistry.save(); // Save default values to disk + if(!FMLClientHandler.instance().hasOptifine()) GameSettings.Options.RENDER_DISTANCE.setValueMax(64f); - overlay.register(); - TickAndRenderListener tarl = new TickAndRenderListener(); FMLCommonHandler.instance().bus().register(tarl); MinecraftForge.EVENT_BUS.register(tarl); @@ -212,9 +221,6 @@ public class ReplayMod { skinMap.put("default", new InvisibilityRender(mc.getRenderManager())); skinMap.put("slim", new InvisibilityRender(mc.getRenderManager(), true)); - //clean up replay_recordings folder - removeTmcprFiles(); - Thread localizedResourcePackLoader = new Thread(new Runnable() { @Override public void run() { @@ -330,36 +336,42 @@ public class ReplayMod { } System.out.println("Loading replay..."); - ReplayHandler.startReplay(file, false); - - int index = 0; - if (path != null) { - for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) { - if (set.getName().equals(path)) { - break; - } - index++; - } - if (index >= ReplayHandler.getKeyframeRepository().length) { - throw new IllegalArgumentException("No path named \"" + path + "\"."); - } - } else if (ReplayHandler.getKeyframeRepository().length == 0) { - throw new IllegalArgumentException("Replay file has no paths defined."); - } - ReplayHandler.useKeyframePresetFromRepository(index); - - System.out.println("Rendering started..."); - try { - ReplayProcess.startReplayProcess(options, true); - } catch (Throwable t) { - t.printStackTrace(); - FMLCommonHandler.instance().exitJava(1, false); - } - if (mc.hasCrashed) { - System.out.println(mc.crashReporter.getCompleteReport()); - } - System.out.println("Rendering done. Shutting down..."); - mc.shutdown(); + // TODO +// try { +// ReplayHandler.startReplay(file, false); +// } catch (Throwable t) { +// t.printStackTrace(); +// FMLCommonHandler.instance().exitJava(1, false); +// } +// +// int index = 0; +// if (path != null) { +// for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) { +// if (set.getName().equals(path)) { +// break; +// } +// index++; +// } +// if (index >= ReplayHandler.getKeyframeRepository().length) { +// throw new IllegalArgumentException("No path named \"" + path + "\"."); +// } +// } else if (ReplayHandler.getKeyframeRepository().length == 0) { +// throw new IllegalArgumentException("Replay file has no paths defined."); +// } +// ReplayHandler.useKeyframePresetFromRepository(index); +// +// System.out.println("Rendering started..."); +// try { +// ReplayProcess.startReplayProcess(options, true); +// } catch (Throwable t) { +// t.printStackTrace(); +// FMLCommonHandler.instance().exitJava(1, false); +// } +// if (mc.hasCrashed) { +// System.out.println(mc.crashReporter.getCompleteReport()); +// } +// System.out.println("Rendering done. Shutting down..."); +// mc.shutdown(); } }, null)); } @@ -422,7 +434,8 @@ public class ReplayMod { new GuiReplayDownloading(info).display(); } else { try { - ReplayHandler.startReplay(file); + // TODO +// ReplayHandler.startReplay(file); } catch (Exception e) { e.printStackTrace(); } @@ -434,16 +447,4 @@ public class ReplayMod { System.exit(-1); } } - - private void removeTmcprFiles() { - try { - File folder = ReplayFileIO.getReplayFolder(); - - for (File file : listFiles(folder, new String[]{ReplayFile.TEMP_FILE_EXTENSION.substring(1)}, false)) { - forceDelete(file); - } - } catch (IOException e) { - e.printStackTrace(); - } - } } diff --git a/src/main/java/com/replaymod/core/SettingsRegistry.java b/src/main/java/com/replaymod/core/SettingsRegistry.java new file mode 100644 index 00000000..6cb0f234 --- /dev/null +++ b/src/main/java/com/replaymod/core/SettingsRegistry.java @@ -0,0 +1,133 @@ +package com.replaymod.core; + +import net.minecraft.client.resources.I18n; +import net.minecraftforge.common.config.Configuration; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class SettingsRegistry { + private static final Object NULL_OBJECT = new Object(); + private Map, Object> settings = new ConcurrentHashMap<>(); + private Configuration configuration; + + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + + List> keys = new ArrayList<>(settings.keySet()); + settings.clear(); + for (SettingKey key : keys) { + register(key); + } + } + + public void register(Class settingsClass) { + for (Field field : settingsClass.getDeclaredFields()) { + if ((field.getModifiers() & (Modifier.STATIC | Modifier.PUBLIC)) != 0 + && SettingKey.class.isAssignableFrom(field.getType())) { + try { + register((SettingKey) field.get(null)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + } + + public void register(SettingKey key) { + Object value; + if (configuration != null) { + if (key.getDefault() instanceof Boolean) { + value = configuration.get(key.getCategory(), key.getKey(), (Boolean) key.getDefault()).getBoolean(); + } else if (key.getDefault() instanceof Integer) { + value = configuration.get(key.getCategory(), key.getKey(), (Integer) key.getDefault()).getInt(); + } else if (key.getDefault() instanceof Double) { + value = configuration.get(key.getCategory(), key.getKey(), (Double) key.getDefault()).getDouble(); + } else if (key.getDefault() instanceof String) { + value = configuration.get(key.getCategory(), key.getKey(), (String) key.getDefault()).getString(); + } else { + throw new IllegalArgumentException("Default type " + key.getDefault().getClass() + " not supported."); + } + } else { + value = NULL_OBJECT; + } + settings.put(key, value); + } + + public Set> getSettings() { + return settings.keySet(); + } + + @SuppressWarnings("unchecked") + public T get(SettingKey key) { + if (!settings.containsKey(key)) { + throw new IllegalArgumentException("Setting " + key + " unknown."); + } + return (T) settings.get(key); + } + + public void set(SettingKey key, T value) { + if (key.getDefault() instanceof Boolean) { + configuration.get(key.getCategory(), key.getKey(), (Boolean) key.getDefault()).set((Boolean) value); + } else if (key.getDefault() instanceof Integer) { + configuration.get(key.getCategory(), key.getKey(), (Integer) key.getDefault()).set((Integer) value); + } else if (key.getDefault() instanceof Double) { + configuration.get(key.getCategory(), key.getKey(), (Double) key.getDefault()).set((Double) value); + } else if (key.getDefault() instanceof String) { + configuration.get(key.getCategory(), key.getKey(), (String) key.getDefault()).set((String) value); + } else { + throw new IllegalArgumentException("Default type " + key.getDefault().getClass() + " not supported."); + } + settings.put(key, value); + } + + public void save() { + configuration.save(); + } + + public interface SettingKey { + String getCategory(); + String getKey(); + String getDisplayString(); + T getDefault(); + } + + public static class SettingKeys implements SettingKey { + private final String category; + private final String key; + private final String displayString; + private final T defaultValue; + + public SettingKeys(String category, String key, String displayString, T defaultValue) { + this.category = category; + this.key = key; + this.displayString = displayString; + this.defaultValue = defaultValue; + } + + @Override + public String getCategory() { + return category; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String getDisplayString() { + return I18n.format(displayString); + } + + @Override + public T getDefault() { + return defaultValue; + } + } +} diff --git a/src/main/java/com/replaymod/core/gui/GuiReplaySettings.java b/src/main/java/com/replaymod/core/gui/GuiReplaySettings.java new file mode 100644 index 00000000..90e3d150 --- /dev/null +++ b/src/main/java/com/replaymod/core/gui/GuiReplaySettings.java @@ -0,0 +1,75 @@ +package com.replaymod.core.gui; + +import de.johni0702.minecraft.gui.container.AbstractGuiScreen; +import de.johni0702.minecraft.gui.container.GuiPanel; +import de.johni0702.minecraft.gui.element.GuiButton; +import de.johni0702.minecraft.gui.element.GuiElement; +import de.johni0702.minecraft.gui.element.GuiLabel; +import de.johni0702.minecraft.gui.element.GuiToggleButton; +import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import de.johni0702.minecraft.gui.layout.VerticalLayout; +import com.replaymod.core.SettingsRegistry; +import net.minecraft.client.resources.I18n; + +public class GuiReplaySettings extends AbstractGuiScreen { + + public GuiReplaySettings(final net.minecraft.client.gui.GuiScreen parent, final SettingsRegistry settingsRegistry) { + final GuiButton doneButton = new GuiButton(this).setI18nLabel("gui.done").setSize(200, 20).onClick(new Runnable() { + @Override + public void run() { + getMinecraft().displayGuiScreen(parent); + } + }); + + final GuiPanel allElements = new GuiPanel(this).setLayout(new HorizontalLayout().setSpacing(10)); + GuiPanel leftColumn = new GuiPanel().setLayout(new VerticalLayout().setSpacing(4)); + GuiPanel rightColumn = new GuiPanel().setLayout(new VerticalLayout().setSpacing(4)); + allElements.addElements(new VerticalLayout.Data(0), leftColumn, rightColumn); + HorizontalLayout.Data leftHorizontalData = new HorizontalLayout.Data(1); + HorizontalLayout.Data rightHorizontalData = new HorizontalLayout.Data(0); + int i = 0; + for (final SettingsRegistry.SettingKey key : settingsRegistry.getSettings()) { + if (key.getDisplayString() != null) { + GuiElement element; + if (key.getDefault() instanceof Boolean) { + @SuppressWarnings("unchecked") + final SettingsRegistry.SettingKey booleanKey = (SettingsRegistry.SettingKey) key; + final GuiToggleButton button = new GuiToggleButton<>().setSize(150, 20) + .setLabel(key.getDisplayString()).setSelected(settingsRegistry.get(booleanKey) ? 0 : 1) + .setValues(I18n.format("options.on"), I18n.format("options.off")); + element = button.onClick(new Runnable() { + @Override + public void run() { + settingsRegistry.set(booleanKey, button.getSelected() == 0); + settingsRegistry.save(); + } + }); + } else { + throw new IllegalArgumentException("Type " + key.getDefault().getClass() + " not supported."); + } + + if (i++ % 2 == 0) { + leftColumn.addElements(leftHorizontalData, element); + } else { + rightColumn.addElements(rightHorizontalData, element); + } + } + } + + setLayout(new CustomLayout() { + @Override + protected void layout(GuiReplaySettings container, int width, int height) { + pos(allElements, width / 2 - 155, height / 6); + pos(doneButton, width / 2 - 100, height - 27); + } + }); + + setTitle(new GuiLabel().setI18nText("replaymod.gui.settings.title")); + } + + @Override + protected GuiReplaySettings getThis() { + return this; + } +} diff --git a/src/main/java/com/replaymod/extras/Extra.java b/src/main/java/com/replaymod/extras/Extra.java new file mode 100644 index 00000000..93f3acd6 --- /dev/null +++ b/src/main/java/com/replaymod/extras/Extra.java @@ -0,0 +1,7 @@ +package com.replaymod.extras; + +import com.replaymod.core.ReplayMod; + +public interface Extra { + void register(ReplayMod mod) throws Exception; +} diff --git a/src/main/java/com/replaymod/extras/HotkeyButtons.java b/src/main/java/com/replaymod/extras/HotkeyButtons.java new file mode 100644 index 00000000..1aea2bfa --- /dev/null +++ b/src/main/java/com/replaymod/extras/HotkeyButtons.java @@ -0,0 +1,101 @@ +package com.replaymod.extras; + +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.events.ReplayOpenEvent; +import com.replaymod.replay.gui.overlay.GuiReplayOverlay; +import de.johni0702.minecraft.gui.container.GuiPanel; +import de.johni0702.minecraft.gui.element.GuiButton; +import de.johni0702.minecraft.gui.element.GuiElement; +import de.johni0702.minecraft.gui.element.GuiLabel; +import de.johni0702.minecraft.gui.element.GuiTexturedButton; +import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.layout.GridLayout; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import de.johni0702.minecraft.gui.layout.LayoutData; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public class HotkeyButtons implements Extra { + private ReplayMod mod; + + @Override + public void register(ReplayMod mod) throws Exception { + this.mod = mod; + + FMLCommonHandler.instance().bus().register(this); + } + + @SubscribeEvent + public void postReplayOpen(ReplayOpenEvent.Post event) { + GuiReplayOverlay overlay = event.getReplayHandler().getOverlay(); + new Gui(mod, overlay); + } + + public static final class Gui { + private final GuiTexturedButton toggleButton; + private final GridLayout panelLayout; + private final GuiPanel panel; + + private boolean open; + + public Gui(ReplayMod mod, GuiReplayOverlay overlay) { + toggleButton = new GuiTexturedButton(overlay).setSize(20, 20) + .setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(0, 0) + .onClick(new Runnable() { + @Override + public void run() { + open = !open; + } + }); + + panel = new GuiPanel(overlay) { + @Override + public Collection getChildren() { + return open ? super.getChildren() : Collections.emptyList(); + } + + @Override + public Map getElements() { + return open ? super.getElements() : Collections.emptyMap(); + } + }.setLayout(panelLayout = new GridLayout().setSpacingX(5).setSpacingY(5).setColumns(1)); + + for (final KeyBinding keyBinding : mod.getKeyBindingRegistry().getKeyBindings().values()) { + String keyName = "???"; + try { + keyName = Keyboard.getKeyName(keyBinding.getKeyCode()); + } catch (ArrayIndexOutOfBoundsException e) { + // Apparently windows likes to press strange keys, see https://www.replaymod.com/forum/thread/55 + } + panel.addElements(null, new GuiPanel().setSize(150, 20).setLayout(new HorizontalLayout().setSpacing(2)) + .addElements(new HorizontalLayout.Data(0.5), + new GuiButton().setSize(20, 20).setLabel(keyName).onClick(new Runnable() { + @Override + public void run() { + keyBinding.pressTime++; + FMLCommonHandler.instance().fireKeyInput(); + } + }), + new GuiLabel().setI18nText(keyBinding.getKeyDescription()) + )); + } + + overlay.setLayout(new CustomLayout(overlay.getLayout()) { + @Override + protected void layout(GuiReplayOverlay container, int width, int height) { + panelLayout.setColumns((width - 10) / 105); + size(panel, panelLayout.calcMinSize(container)); + + pos(toggleButton, 5, height - 25); + pos(panel, 5, y(toggleButton) - 5 - height(panel)); + } + }); + } + } +} diff --git a/src/main/java/com/replaymod/extras/ReplayModExtras.java b/src/main/java/com/replaymod/extras/ReplayModExtras.java new file mode 100644 index 00000000..623bbaa1 --- /dev/null +++ b/src/main/java/com/replaymod/extras/ReplayModExtras.java @@ -0,0 +1,44 @@ +package com.replaymod.extras; + +import com.replaymod.core.ReplayMod; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import org.apache.logging.log4j.Logger; + +import java.util.Arrays; +import java.util.List; + +@Mod(modid = ReplayModExtras.MOD_ID, useMetadata = true) +public class ReplayModExtras { + public static final String MOD_ID = "replaymod-extras"; + + @Mod.Instance(MOD_ID) + public static ReplayModExtras instance; + + @Mod.Instance(ReplayMod.MOD_ID) + private static ReplayMod core; + + private static final List> builtin = Arrays.>asList( + HotkeyButtons.class + ); + + private Logger logger; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + logger = event.getModLog(); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) { + for (Class cls : builtin) { + try { + Extra extra = cls.newInstance(); + extra.register(core); + } catch (Throwable t) { + logger.warn("Failed to load extra " + cls.getName() + ": ", t); + } + } + } +} diff --git a/src/main/java/com/replaymod/recording/ReplayModRecording.java b/src/main/java/com/replaymod/recording/ReplayModRecording.java new file mode 100644 index 00000000..66d3ce10 --- /dev/null +++ b/src/main/java/com/replaymod/recording/ReplayModRecording.java @@ -0,0 +1,47 @@ +package com.replaymod.recording; + +import com.replaymod.recording.handler.ConnectionEventHandler; +import com.replaymod.recording.packet.PacketListener; +import com.replaymod.core.ReplayMod; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.EventBus; +import org.apache.logging.log4j.Logger; +import org.lwjgl.input.Keyboard; + +@Mod(modid = ReplayModRecording.MOD_ID, useMetadata = true) +public class ReplayModRecording { + public static final String MOD_ID = "replaymod-recording"; + + @Mod.Instance(ReplayMod.MOD_ID) + private static ReplayMod core; + + private Logger logger; + + private ConnectionEventHandler connectionEventHandler; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + logger = event.getModLog(); + + core.getSettingsRegistry().register(Setting.class); + + core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.marker", Keyboard.KEY_M, new Runnable() { + @Override + public void run() { + PacketListener packetListener = connectionEventHandler.getPacketListener(); + if (packetListener != null) { + packetListener.addMarker(); + } + } + }); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) { + EventBus bus = FMLCommonHandler.instance().bus(); + bus.register(connectionEventHandler = new ConnectionEventHandler(logger, core)); + } +} diff --git a/src/main/java/com/replaymod/recording/Setting.java b/src/main/java/com/replaymod/recording/Setting.java new file mode 100644 index 00000000..e3742d8b --- /dev/null +++ b/src/main/java/com/replaymod/recording/Setting.java @@ -0,0 +1,17 @@ +package com.replaymod.recording; + +import com.replaymod.core.SettingsRegistry; + +public final class Setting extends SettingsRegistry.SettingKeys { + public static final Setting RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true); + public static final Setting RECORD_SERVER = make("recordServer", "recordserver", true); + public static final Setting INDICATOR = make("indicator", "indicator", true); + + private static Setting make(String key, String displayName, T defaultValue) { + return new Setting<>(key, displayName, defaultValue); + } + + public Setting(String key, String displayString, T defaultValue) { + super("recording", key, "replaymod.gui.settings." + displayString, defaultValue); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiRecordingOverlay.java b/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java similarity index 74% rename from src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiRecordingOverlay.java rename to src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java index 30722889..68b8d9b1 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiRecordingOverlay.java +++ b/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java @@ -1,16 +1,17 @@ -package eu.crushedpixel.replaymod.gui.overlay; +package com.replaymod.recording.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; +import static com.replaymod.core.ReplayMod.TEXTURE; +import static com.replaymod.core.ReplayMod.TEXTURE_SIZE; /** * Renders overlay during recording. @@ -22,6 +23,14 @@ public class GuiRecordingOverlay { this.mc = mc; } + public void register() { + MinecraftForge.EVENT_BUS.register(this); + } + + public void unregister() { + MinecraftForge.EVENT_BUS.unregister(this); + } + /** * Render the recording icon and text in the top left corner of the screen. * @param event Rendered post game overlay @@ -32,7 +41,7 @@ public class GuiRecordingOverlay { if(ReplayMod.replaySettings.showRecordingIndicator()) { FontRenderer fontRenderer = mc.fontRendererObj; fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff); - mc.renderEngine.bindTexture(replay_gui); + mc.renderEngine.bindTexture(TEXTURE); GlStateManager.resetColor(); GlStateManager.enableAlpha(); Gui.drawModalRectWithCustomSizedTexture(10, 10, 58, 20, 16, 16, TEXTURE_SIZE, TEXTURE_SIZE); diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java similarity index 52% rename from src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java rename to src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java index 1785721a..5cd214b0 100755 --- a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java @@ -1,79 +1,53 @@ -package eu.crushedpixel.replaymod.recording; +package com.replaymod.recording.handler; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.recording.Setting; +import com.replaymod.recording.gui.GuiRecordingOverlay; +import com.replaymod.recording.packet.PacketListener; +import de.johni0702.replaystudio.replay.ReplayFile; +import de.johni0702.replaystudio.replay.ZipReplayFile; +import de.johni0702.replaystudio.studio.ReplayStudio; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType; -import eu.crushedpixel.replaymod.gui.overlay.GuiRecordingOverlay; -import eu.crushedpixel.replaymod.utils.ReplayFile; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; import io.netty.channel.Channel; import io.netty.channel.ChannelPipeline; import net.minecraft.client.Minecraft; import net.minecraft.network.NetworkManager; -import net.minecraft.network.Packet; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldType; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent; -import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.text.SimpleDateFormat; import java.util.Calendar; +/** + * Handles connection events and initiates recording if enabled. + */ public class ConnectionEventHandler { private static final String packetHandlerKey = "packet_handler"; private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss"; private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); - private static PacketListener packetListener = null; - private static boolean isRecording = false; - private final GuiRecordingOverlay guiOverlay = new GuiRecordingOverlay(Minecraft.getMinecraft()); + private static final Minecraft mc = Minecraft.getMinecraft(); - private static final Logger logger = LogManager.getLogger(); + private final Logger logger; + private final ReplayMod core; - public static boolean isRecording() { - return isRecording; - } + private RecordingEventHandler recordingEventHandler; + private PacketListener packetListener; + private GuiRecordingOverlay guiOverlay; - public static void notifyServerPaused() { - if (packetListener != null) { - packetListener.serverWasPaused = true; - } - } - - public static void insertPacket(Packet packet) { - if(!isRecording || packetListener == null) { - String reason = isRecording ? " (recording)" : " (null)"; - logger.error("Invalid attempt to insert Packet!" + reason); - return; - } - try { - packetListener.saveOnly(packet); - } catch(Exception e) { - e.printStackTrace(); - } - } - - public static void addMarker() { - if(!isRecording || packetListener == null) { - String reason = isRecording ? " (recording)" : " (null)"; - logger.error("Invalid attempt to insert MarkerKeyframe!" + reason); - return; - } - try { - packetListener.addMarker(); - } catch(Exception e) { - e.printStackTrace(); - } + public ConnectionEventHandler(Logger logger, ReplayMod core) { + this.logger = logger; + this.core = core; } @SubscribeEvent public void onConnectedToServerEvent(ClientConnectedToServerEvent event) { ReplayMod.chatMessageHandler.initialize(); - ReplayMod.recordingHandler.resetVars(); try { if(event.isLocal) { @@ -81,16 +55,17 @@ public class ConnectionEventHandler { logger.info("Debug World recording is not supported."); return; } - if(!ReplayMod.replaySettings.isEnableRecordingSingleplayer()) { + if(!core.getSettingsRegistry().get(Setting.RECORD_SINGLEPLAYER)) { logger.info("Singleplayer Recording is disabled"); return; } } else { - if(!ReplayMod.replaySettings.isEnableRecordingServer()) { + if(!core.getSettingsRegistry().get(Setting.RECORD_SERVER)) { logger.info("Multiplayer Recording is disabled"); return; } } + NetworkManager nm = event.manager; String worldName; if(event.isLocal) { @@ -101,17 +76,22 @@ public class ConnectionEventHandler { Channel channel = nm.channel(); ChannelPipeline pipeline = channel.pipeline(); - File folder = ReplayFileIO.getReplayFolder(); + File folder = core.getReplayFolder(); - String fileName = sdf.format(Calendar.getInstance().getTime()); - File currentFile = new File(folder, fileName + ReplayFile.TEMP_FILE_EXTENSION); + String name = sdf.format(Calendar.getInstance().getTime()); + File currentFile = new File(folder, name + ".mcpr"); + ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), currentFile); + + packetListener = new PacketListener(replayFile, name, worldName, System.currentTimeMillis(), event.isLocal); + pipeline.addBefore(packetHandlerKey, "replay_recorder", packetListener); + + recordingEventHandler = new RecordingEventHandler(packetListener); + recordingEventHandler.register(); + + guiOverlay = new GuiRecordingOverlay(mc); + guiOverlay.register(); - pipeline.addBefore(packetHandlerKey, "replay_recorder", packetListener = new PacketListener - (currentFile, fileName, worldName, System.currentTimeMillis(), event.isLocal)); ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingstarted", ChatMessageType.INFORMATION); - isRecording = true; - - MinecraftForge.EVENT_BUS.register(guiOverlay); } catch(Exception e) { ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingfailed", ChatMessageType.WARNING); e.printStackTrace(); @@ -120,11 +100,18 @@ public class ConnectionEventHandler { @SubscribeEvent public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) { - if (isRecording) { - isRecording = false; - MinecraftForge.EVENT_BUS.unregister(guiOverlay); + if (packetListener != null) { + guiOverlay.unregister(); + guiOverlay = null; + recordingEventHandler.unregister(); + recordingEventHandler = null; packetListener = null; + ReplayMod.chatMessageHandler.stop(); } } + + public PacketListener getPacketListener() { + return packetListener; + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java similarity index 81% rename from src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java rename to src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java index 6bd7ad8f..4aafa8ee 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/RecordingHandler.java +++ b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java @@ -1,6 +1,6 @@ -package eu.crushedpixel.replaymod.events.handlers; +package com.replaymod.recording.handler; -import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; +import com.replaymod.recording.packet.PacketListener; import eu.crushedpixel.replaymod.utils.Objects; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -13,39 +13,60 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.*; import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove; import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.BlockPos; import net.minecraft.util.MathHelper; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent; import net.minecraftforge.event.entity.player.PlayerUseItemEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.ItemPickupEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent; -public class RecordingHandler { +public class RecordingEventHandler { private final Minecraft mc = Minecraft.getMinecraft(); - private Double lastX = null, lastY = null, lastZ = null; + private final PacketListener packetListener; + + private Double lastX, lastY, lastZ; private ItemStack[] playerItems = new ItemStack[5]; - private int ticksSinceLastCorrection = 0; - private boolean wasSleeping = false; + private int ticksSinceLastCorrection; + private boolean wasSleeping; private int lastRiding = -1; - private Integer rotationYawHeadBefore = null; + private Integer rotationYawHeadBefore; + + public RecordingEventHandler(PacketListener packetListener) { + this.packetListener = packetListener; + } + + public void register() { + FMLCommonHandler.instance().bus().register(this); + MinecraftForge.EVENT_BUS.register(this); + ((RecordingEventSender) mc.renderGlobal).setRecordingEventHandler(this); + } + + public void unregister() { + FMLCommonHandler.instance().bus().unregister(this); + MinecraftForge.EVENT_BUS.unregister(this); + RecordingEventSender recordingEventSender = ((RecordingEventSender) mc.renderGlobal); + if (recordingEventSender.getRecordingEventHandler() == this) { + recordingEventSender.setRecordingEventHandler(null); + } + } public void onPlayerJoin() { try { - if(!ConnectionEventHandler.isRecording()) return; - - ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer)); + packetListener.save(spawnPlayer(mc.thePlayer)); } catch(Exception e1) { e1.printStackTrace(); } } public void onPlayerRespawn() { - if(!ConnectionEventHandler.isRecording()) return; try { - ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer)); + packetListener.save(spawnPlayer(mc.thePlayer)); } catch(Exception e) { e.printStackTrace(); } @@ -81,18 +102,10 @@ public class RecordingHandler { } } - public void resetVars() { - lastX = lastY = lastZ = null; - rotationYawHeadBefore = null; - playerItems = new ItemStack[5]; - } - @SubscribeEvent public void onPlayerTick(PlayerTickEvent e) { - if(!ConnectionEventHandler.isRecording()) return; try { if(e.player != mc.thePlayer) return; - if(!ConnectionEventHandler.isRecording()) return; boolean force = false; if(lastX == null || lastY == null || lastZ == null) { @@ -133,7 +146,7 @@ public class RecordingHandler { newYaw, newPitch, e.player.onGround); } - ConnectionEventHandler.insertPacket(packet); + packetListener.save(packet); //HEAD POS int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F)); @@ -148,13 +161,13 @@ public class RecordingHandler { head.readPacketData(pb1); - ConnectionEventHandler.insertPacket(head); + packetListener.save(head); rotationYawHeadBefore = rotationYawHead; } S12PacketEntityVelocity vel = new S12PacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ); - ConnectionEventHandler.insertPacket(vel); + packetListener.save(vel); //Animation Packets //Swing Animation @@ -169,7 +182,7 @@ public class RecordingHandler { pac.readPacketData(pb); - ConnectionEventHandler.insertPacket(pac); + packetListener.save(pac); } /* @@ -179,13 +192,13 @@ public class RecordingHandler { found.add(pe.getPotionID()); if(lastEffects.contains(found)) continue; S1DPacketEntityEffect pee = new S1DPacketEntityEffect(entityID, pe); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } for(int id : lastEffects) { if(!found.contains(id)) { S1EPacketRemoveEntityEffect pre = new S1EPacketRemoveEntityEffect(entityID, new PotionEffect(id, 0)); - ConnectionEventHandler.insertPacket(pre); + packetListener.save(pre); } } @@ -196,31 +209,31 @@ public class RecordingHandler { if(playerItems[0] != mc.thePlayer.getHeldItem()) { playerItems[0] = mc.thePlayer.getHeldItem(); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 0, playerItems[0]); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } if(playerItems[1] != mc.thePlayer.inventory.armorInventory[0]) { playerItems[1] = mc.thePlayer.inventory.armorInventory[0]; S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 1, playerItems[1]); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } if(playerItems[2] != mc.thePlayer.inventory.armorInventory[1]) { playerItems[2] = mc.thePlayer.inventory.armorInventory[1]; S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 2, playerItems[2]); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } if(playerItems[3] != mc.thePlayer.inventory.armorInventory[2]) { playerItems[3] = mc.thePlayer.inventory.armorInventory[2]; S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 3, playerItems[3]); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } if(playerItems[4] != mc.thePlayer.inventory.armorInventory[3]) { playerItems[4] = mc.thePlayer.inventory.armorInventory[3]; S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 4, playerItems[4]); - ConnectionEventHandler.insertPacket(pee); + packetListener.save(pee); } //Leaving Ride @@ -244,7 +257,7 @@ public class RecordingHandler { pea.readPacketData(pbuf); - ConnectionEventHandler.insertPacket(pea); + packetListener.save(pea); } //Sleeping @@ -259,7 +272,7 @@ public class RecordingHandler { pac.readPacketData(pb); - ConnectionEventHandler.insertPacket(pac); + packetListener.save(pac); wasSleeping = false; } @@ -271,9 +284,8 @@ public class RecordingHandler { @SubscribeEvent public void onPickupItem(ItemPickupEvent event) { - if(!ConnectionEventHandler.isRecording()) return; try { - ConnectionEventHandler.insertPacket(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId())); + packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId())); } catch(Exception e) { e.printStackTrace(); } @@ -281,7 +293,6 @@ public class RecordingHandler { @SubscribeEvent public void onStartEating(PlayerUseItemEvent.Start event) { - if(!ConnectionEventHandler.isRecording()) return; try { if(!event.entityPlayer.isEating()) return; S0BPacketAnimation packet = new S0BPacketAnimation(); @@ -294,7 +305,7 @@ public class RecordingHandler { packet.readPacketData(pb); - ConnectionEventHandler.insertPacket(packet); + packetListener.save(packet); } catch(Exception e) { e.printStackTrace(); } @@ -302,13 +313,11 @@ public class RecordingHandler { @SubscribeEvent public void onSleep(PlayerSleepInBedEvent event) { - if(!ConnectionEventHandler.isRecording()) return; try { if(event.entityPlayer != mc.thePlayer) { return; } - System.out.println(event.getResult()); S0APacketUseBed pub = new S0APacketUseBed(); ByteBuf buf = Unpooled.buffer(); @@ -319,7 +328,7 @@ public class RecordingHandler { pub.readPacketData(pbuf); - ConnectionEventHandler.insertPacket(pub); + packetListener.save(pub); wasSleeping = true; @@ -330,7 +339,6 @@ public class RecordingHandler { @SubscribeEvent public void enterMinecart(MinecartInteractEvent event) { - if(!ConnectionEventHandler.isRecording()) return; try { if(event.player != mc.thePlayer) { return; @@ -347,7 +355,7 @@ public class RecordingHandler { pea.readPacketData(pbuf); - ConnectionEventHandler.insertPacket(pea); + packetListener.save(pea); lastRiding = event.minecart.getEntityId(); } catch(Exception e) { @@ -355,15 +363,26 @@ public class RecordingHandler { } } + public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) { + EntityPlayer thePlayer = mc.thePlayer; + if (thePlayer != null && breakerId == thePlayer.getEntityId()) { + packetListener.save(new S25PacketBlockBreakAnim(breakerId, pos, progress)); + } + } + @SubscribeEvent public void checkForGamePaused(TickEvent.RenderTickEvent event) { if (event.phase != TickEvent.Phase.START) return; - if (!ConnectionEventHandler.isRecording()) return; if (mc.isIntegratedServerRunning()) { IntegratedServer server = mc.getIntegratedServer(); if (server != null && server.isGamePaused) { - ConnectionEventHandler.notifyServerPaused(); + packetListener.serverWasPaused = true; } } } + + public interface RecordingEventSender { + void setRecordingEventHandler(RecordingEventHandler recordingEventHandler); + RecordingEventHandler getRecordingEventHandler(); + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinNetHandlerPlayClient.java b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java similarity index 72% rename from src/main/java/eu/crushedpixel/replaymod/mixin/MixinNetHandlerPlayClient.java rename to src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java index 5f0e73dd..baf316ed 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinNetHandlerPlayClient.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java @@ -1,12 +1,12 @@ -package eu.crushedpixel.replaymod.mixin; +package com.replaymod.recording.mixin; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; +import com.replaymod.recording.handler.RecordingEventHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.network.play.server.S07PacketRespawn; import net.minecraft.network.play.server.S38PacketPlayerListItem; 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; @@ -16,6 +16,13 @@ import java.util.List; @Mixin(NetHandlerPlayClient.class) public abstract class MixinNetHandlerPlayClient { + @Shadow + private Minecraft gameController; + + public RecordingEventHandler getRecordingEventHandler() { + return ((RecordingEventHandler.RecordingEventSender) gameController.renderGlobal).getRecordingEventHandler(); + } + /** * Record the own player entity joining the world. * We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id @@ -25,12 +32,13 @@ public abstract class MixinNetHandlerPlayClient { */ @Inject(method = "handlePlayerListItem", at=@At("RETURN")) public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) { - if (ConnectionEventHandler.isRecording() && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) { + RecordingEventHandler handler = getRecordingEventHandler(); + if (handler != null && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) { @SuppressWarnings("unchecked") List dataList = packet.func_179767_a(); for (S38PacketPlayerListItem.AddPlayerData data : dataList) { if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())) { - ReplayMod.recordingHandler.onPlayerJoin(); + handler.onPlayerJoin(); } } } @@ -45,8 +53,9 @@ public abstract class MixinNetHandlerPlayClient { */ @Inject(method = "handleRespawn", at=@At("RETURN")) public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) { - if (ConnectionEventHandler.isRecording()) { - ReplayMod.recordingHandler.onPlayerRespawn(); + RecordingEventHandler handler = getRecordingEventHandler(); + if (handler != null) { + handler.onPlayerRespawn(); } } } diff --git a/src/main/java/com/replaymod/recording/mixin/MixinRenderGlobal.java b/src/main/java/com/replaymod/recording/mixin/MixinRenderGlobal.java new file mode 100644 index 00000000..d9e11de1 --- /dev/null +++ b/src/main/java/com/replaymod/recording/mixin/MixinRenderGlobal.java @@ -0,0 +1,32 @@ +package com.replaymod.recording.mixin; + +import com.replaymod.recording.handler.RecordingEventHandler; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.util.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(RenderGlobal.class) +public abstract class MixinRenderGlobal implements RecordingEventHandler.RecordingEventSender { + + private RecordingEventHandler recordingEventHandler; + + @Override + public void setRecordingEventHandler(RecordingEventHandler recordingEventHandler) { + this.recordingEventHandler = recordingEventHandler; + } + + @Override + public RecordingEventHandler getRecordingEventHandler() { + return recordingEventHandler; + } + + @Inject(method = "sendBlockBreakProgress", at = @At("HEAD")) + public void saveBlockBreakProgressPacket(int breakerId, BlockPos pos, int progress, CallbackInfo info) { + if (recordingEventHandler != null) { + recordingEventHandler.onBlockBreakAnim(breakerId, pos, progress); + } + } +} diff --git a/src/main/java/com/replaymod/recording/packet/DataListener.java b/src/main/java/com/replaymod/recording/packet/DataListener.java new file mode 100755 index 00000000..01ce0e27 --- /dev/null +++ b/src/main/java/com/replaymod/recording/packet/DataListener.java @@ -0,0 +1,182 @@ +package com.replaymod.recording.packet; + +import com.google.common.hash.Hashing; +import com.google.common.io.Files; +import de.johni0702.replaystudio.data.Marker; +import de.johni0702.replaystudio.replay.ReplayFile; +import de.johni0702.replaystudio.replay.ReplayMetaData; +import com.replaymod.core.ReplayMod; +import eu.crushedpixel.replaymod.chat.ChatMessageHandler; +import eu.crushedpixel.replaymod.holders.AdvancedPosition; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import net.minecraft.client.Minecraft; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public abstract class DataListener extends ChannelInboundHandlerAdapter { + + private static final Logger logger = LogManager.getLogger(); + + private final ReplayFile replayFile; + protected final DataWriter dataWriter; + + protected Long startTime = null; + protected String name; + protected String worldName; + public boolean serverWasPaused; + protected long lastSentPacket = 0; + protected boolean alive = true; + protected Set players = new HashSet<>(); + private boolean singleplayer; + + private final Set markers = new HashSet<>(); + private final Map requestToHash = new ConcurrentHashMap<>(); + + public DataListener(ReplayFile replayFile, String name, String worldName, long startTime, boolean singleplayer) throws IOException { + this.replayFile = replayFile; + this.startTime = startTime; + this.name = name; + this.worldName = worldName; + this.singleplayer = singleplayer; + + dataWriter = new DataWriter(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + dataWriter.requestFinish(); + } + + protected void recordResourcePack(File file, int requestId) { + try { + String hash = Hashing.sha1().hashBytes(Files.toByteArray(file)).toString(); + synchronized (dataWriter) { + if (!requestToHash.containsValue(hash)) { + try (OutputStream out = replayFile.writeResourcePack(hash)) { + FileUtils.copyFile(file, out); + } + } + } + requestToHash.put(requestId, hash); + } catch (IOException e) { + logger.warn("Failed to save resource pack.", e); + } + } + + public void addMarker() { + AdvancedPosition pos = new AdvancedPosition(Minecraft.getMinecraft().getRenderViewEntity()); + int timestamp = (int) (System.currentTimeMillis() - startTime); + + Marker marker = new Marker(); + marker.setTime(timestamp); + marker.setX(pos.getX()); + marker.setY(pos.getY()); + marker.setZ(pos.getZ()); + marker.setYaw((float) pos.getYaw()); + marker.setPitch((float) pos.getPitch()); + marker.setRoll((float) pos.getRoll()); + markers.add(marker); + + ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.addedmarker", ChatMessageHandler.ChatMessageType.INFORMATION); + } + + public class DataWriter { + private long paused; + + private DataOutputStream stream; + private ExecutorService saveService = Executors.newSingleThreadExecutor(); + + private final Thread shutdownHook = new Thread(new Runnable() { + @Override + public void run() { + if (!saveService.isShutdown()) { + requestFinish(); + } + } + }, "shutdown-hook-data-listener"); + + public DataWriter() throws IOException { + stream = new DataOutputStream(replayFile.writePacketData()); + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + + public synchronized void writePacket(final byte[] bytes) { + long now = System.currentTimeMillis(); + if(startTime == null) { + startTime = now; + } + + if (serverWasPaused) { + paused = now - startTime - lastSentPacket; + serverWasPaused = false; + } + final int timestamp = (int) (now - startTime - paused); + lastSentPacket = timestamp; + saveService.submit(new Runnable() { + @Override + public void run() { + try { + stream.writeInt(timestamp); + stream.writeInt(bytes.length); + stream.write(bytes); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } + + public synchronized void requestFinish() { + if (saveService.isShutdown()) return; + try { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + saveService.shutdown(); + saveService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + stream.close(); + + // TODO: Get rid of replay file appender + ReplayMod.replayFileAppender.startNewReplayFileWriting(); + + String mcversion = ReplayMod.getMinecraftVersion(); + + String[] pl = players.toArray(new String[players.size()]); + + String generator = "ReplayMod v" + ReplayMod.getContainer().getVersion(); + + ReplayMetaData metaData = new ReplayMetaData(); + metaData.setSingleplayer(singleplayer); + metaData.setServerName(worldName); + metaData.setGenerator(generator); + metaData.setDuration((int) lastSentPacket); + metaData.setDate(startTime); + metaData.setPlayers(pl); + metaData.setMcVersion(mcversion); + + replayFile.writeMetaData(metaData); + replayFile.writeMarkers(markers); + replayFile.writeResourcePackIndex(requestToHash); + replayFile.save(); + } catch(Exception e) { + e.printStackTrace(); + } finally { + ReplayMod.replayFileAppender.replayFileWritingFinished(); + } + } + + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java similarity index 92% rename from src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java rename to src/main/java/com/replaymod/recording/packet/PacketListener.java index 90cc3e9b..daae000b 100755 --- a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -1,15 +1,11 @@ -package eu.crushedpixel.replaymod.recording; +package com.replaymod.recording.packet; import com.google.common.hash.Hashing; import com.google.common.io.Files; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.chat.ChatMessageHandler; -import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.Marker; +import de.johni0702.replaystudio.replay.ReplayFile; import eu.crushedpixel.replaymod.replay.Restrictions; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import io.netty.channel.ChannelHandlerContext; @@ -35,7 +31,6 @@ import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.Map; @@ -50,11 +45,11 @@ public class PacketListener extends DataListener { private int nextRequestId; - public PacketListener(File file, String name, String worldName, long startTime, boolean singleplayer) throws FileNotFoundException { + public PacketListener(ReplayFile file, String name, String worldName, long startTime, boolean singleplayer) throws IOException { super(file, name, worldName, startTime, singleplayer); } - public void saveOnly(Packet packet) { + public void save(Packet packet) { try { if(packet instanceof S0CPacketSpawnPlayer) { UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c(); @@ -101,7 +96,7 @@ public class PacketListener extends DataListener { if (packet instanceof S48PacketResourcePackSend) { S48PacketResourcePackSend p = (S48PacketResourcePackSend) packet; int requestId = handleResourcePack(p); - saveOnly(new S48PacketResourcePackSend("replay://" + requestId, "")); + save(new S48PacketResourcePackSend("replay://" + requestId, "")); return; } @@ -216,17 +211,6 @@ public class PacketListener extends DataListener { return requestId; } - public void addMarker() { - AdvancedPosition pos = new AdvancedPosition(Minecraft.getMinecraft().getRenderViewEntity()); - int timestamp = (int) (System.currentTimeMillis() - startTime); - - Keyframe marker = new Keyframe(timestamp, new Marker(null, pos)); - - markers.add(marker); - - ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.addedmarker", ChatMessageHandler.ChatMessageType.INFORMATION); - } - private void downloadResourcePackFuture(int requestId, String url, final String hash) { Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() { @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/PacketSerializer.java b/src/main/java/com/replaymod/recording/packet/PacketSerializer.java similarity index 96% rename from src/main/java/eu/crushedpixel/replaymod/recording/PacketSerializer.java rename to src/main/java/com/replaymod/recording/packet/PacketSerializer.java index e8379a7a..12b3f214 100755 --- a/src/main/java/eu/crushedpixel/replaymod/recording/PacketSerializer.java +++ b/src/main/java/com/replaymod/recording/packet/PacketSerializer.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.recording; +package com.replaymod.recording.packet; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; diff --git a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java b/src/main/java/com/replaymod/replay/CameraEntity.java similarity index 91% rename from src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java rename to src/main/java/com/replaymod/replay/CameraEntity.java index 5cff2b60..94f4dcfa 100755 --- a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java +++ b/src/main/java/com/replaymod/replay/CameraEntity.java @@ -1,14 +1,12 @@ -package eu.crushedpixel.replaymod.entities; +package com.replaymod.replay; import eu.crushedpixel.replaymod.holders.AdvancedPosition; import eu.crushedpixel.replaymod.replay.LesserDataWatcher; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.stats.StatFileWriter; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; @@ -48,12 +46,12 @@ public class CameraEntity extends EntityPlayerSP { private Vec3 dirBefore; private double motion; + public float roll; + private long lastCall = 0; private boolean speedup = false; - public static UUID spectating; - public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) { super(mcIn, worldIn, netHandlerPlayClient, statFileWriter); } @@ -133,11 +131,11 @@ public class CameraEntity extends EntityPlayerSP { this.moveAbsolute(pos.getX(), pos.getY(), pos.getZ()); rotationPitch = prevRotationPitch = (float)pos.getPitch(); rotationYaw = prevRotationYaw = (float)pos.getYaw(); + roll = (float) pos.getRoll(); updateBoundingBox(); } public void moveAbsolute(double x, double y, double z) { - if(ReplayHandler.isInPath()) return; this.lastTickPosX = this.prevPosX = this.posX = x; this.lastTickPosY = this.prevPosY = this.posY = y; this.lastTickPosZ = this.prevPosZ = this.posZ = z; @@ -145,7 +143,6 @@ public class CameraEntity extends EntityPlayerSP { } public void moveRelative(double x, double y, double z) { - if(ReplayHandler.isInPath()) return; this.lastTickPosX = this.prevPosX = this.posX = this.posX + x; this.lastTickPosY = this.prevPosY = this.posY = this.posY + y; this.lastTickPosZ = this.prevPosZ = this.posZ = this.posZ + z; @@ -155,6 +152,7 @@ public class CameraEntity extends EntityPlayerSP { public void movePath(AdvancedPosition pos) { this.prevRotationPitch = this.rotationPitch = (float)pos.getPitch(); this.prevRotationYaw = this.rotationYaw = (float)pos.getYaw(); + this.roll = (float) pos.getRoll(); this.lastTickPosX = this.prevPosX = this.posX = pos.getX(); this.lastTickPosY = this.prevPosY = this.posY = pos.getY(); this.lastTickPosZ = this.prevPosZ = this.posZ = pos.getZ(); @@ -166,7 +164,7 @@ public class CameraEntity extends EntityPlayerSP { posX + width / 2, posY + height, posZ + width / 2)); } - private void updatePos(Entity to) { + protected void updatePos(Entity to) { prevPosX = to.prevPosX; prevPosY = to.prevPosY; prevPosZ = to.prevPosZ; @@ -188,9 +186,6 @@ public class CameraEntity extends EntityPlayerSP { @Override public void setAngles(float yaw, float pitch) { - if (ReplayHandler.isInPath()) { - return; // Disallow camera movement by mouse during path preview - } this.rotationYaw = (float) ((double) this.rotationYaw + (double) yaw * 0.15D); this.rotationPitch = (float) ((double) this.rotationPitch - (double) pitch * 0.15D); this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F); @@ -202,6 +197,7 @@ public class CameraEntity extends EntityPlayerSP { public void onUpdate() { Entity view = mc.getRenderViewEntity(); if (view != null) { + UUID spectating = ReplayModReplay.instance.getReplayHandler().spectating; if (spectating != null && (view.getUniqueID() != spectating || view.worldObj != worldObj)) { view = worldObj.getPlayerEntityByUUID(spectating); if (view != null) { @@ -263,20 +259,6 @@ public class CameraEntity extends EntityPlayerSP { return true; } - public void spectate(Entity e) { - if (e == null || e == this) { - spectating = null; - e = this; - } else if (e instanceof EntityPlayer) { - spectating = e.getUniqueID(); - } - - if (mc.getRenderViewEntity() != e) { - mc.setRenderViewEntity(e); - updatePos(e); - } - } - public enum MoveDirection { UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD } diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java new file mode 100755 index 00000000..09fa3484 --- /dev/null +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -0,0 +1,349 @@ +package com.replaymod.replay; + +import com.google.common.base.Preconditions; +import com.mojang.authlib.GameProfile; +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.events.ReplayCloseEvent; +import com.replaymod.replay.events.ReplayOpenEvent; +import com.replaymod.replay.gui.overlay.GuiReplayOverlay; +import de.johni0702.replaystudio.data.Marker; +import de.johni0702.replaystudio.replay.ReplayFile; +import eu.crushedpixel.replaymod.holders.AdvancedPosition; +import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; +import eu.crushedpixel.replaymod.replay.Restrictions; +import eu.crushedpixel.replaymod.utils.MouseUtils; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.embedded.EmbeddedChannel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.EnumPacketDirection; +import net.minecraft.network.NetworkManager; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher; +import org.lwjgl.opengl.Display; +import org.lwjgl.util.Point; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static net.minecraft.client.renderer.GlStateManager.*; +import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; + +public class ReplayHandler { + + private static Minecraft mc = Minecraft.getMinecraft(); + + /** + * The file currently being played. + */ + private final ReplayFile replayFile; + + /** + * Decodes and sends packets into channel. + */ + private final ReplaySender replaySender; + + /** + * Currently active replay restrictions. + */ + private Restrictions restrictions = new Restrictions(); + + /** + * Whether camera movements by user input and/or server packets should be suppressed. + */ + private boolean suppressCameraMovements; + + private final Set markers; + + private final GuiReplayOverlay overlay; + + private EmbeddedChannel channel; + + /** + * The position at which the camera should be located after the next jump. + */ + private AdvancedPosition targetCameraPosition; + + protected UUID spectating; + + public ReplayHandler(ReplayFile replayFile, boolean asyncMode) throws IOException { + Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread."); + this.replayFile = replayFile; + + FMLCommonHandler.instance().bus().post(new ReplayOpenEvent.Pre(this)); + + markers = replayFile.getMarkers().or(Collections.emptySet()); + + // TODO: get rid of chat message handler + ReplayMod.chatMessageHandler.initialize(); + + replaySender = new ReplaySender(this, replayFile, asyncMode); + + setup(); + + overlay = new GuiReplayOverlay(this); + overlay.setVisible(true); + + FMLCommonHandler.instance().bus().post(new ReplayOpenEvent.Post(this)); + } + + void restartedReplay() { + channel.close(); + + restrictions = new Restrictions(); + + setup(); + } + + public void endReplay() throws IOException { + Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread."); + + FMLCommonHandler.instance().bus().post(new ReplayCloseEvent.Pre(this)); + + replaySender.terminateReplay(); + + replayFile.save(); + replayFile.close(); + + channel.close().awaitUninterruptibly(); + + if (mc.theWorld != null) { + mc.theWorld.sendQuittingDisconnectingPacket(); + mc.loadWorld(null); + } + + overlay.setVisible(false); + + // These might have been hidden by the overlay, so we have to make sure they're visible again + ReplayGuiRegistry.show(); + + FMLCommonHandler.instance().bus().post(new ReplayCloseEvent.Post(this)); + } + + private void setup() { + mc.ingameGUI.getChatGUI().clearChatMessages(); + + NetworkManager networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { + t.printStackTrace(); + } + }; + networkManager.setNetHandler(new NetHandlerPlayClient( + mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player"))); + + channel = new EmbeddedChannel(networkManager); + channel.attr(NetworkDispatcher.FML_DISPATCHER).set(new NetworkDispatcher(networkManager)); + + channel.pipeline().addFirst(replaySender); + channel.pipeline().fireChannelActive(); + } + + public ReplayFile getReplayFile() { + return replayFile; + } + + public Restrictions getRestrictions() { + return restrictions; + } + + public ReplaySender getReplaySender() { + return replaySender; + } + + public GuiReplayOverlay getOverlay() { + return overlay; + } + + /** + * Return whether camera movement by user inputs and/or server packets should be suppressed. + * @return {@code true} if these kinds of movement should be suppressed + */ + public boolean shouldSuppressCameraMovements() { + return suppressCameraMovements; + } + + /** + * Set whether camera movement by user inputs and/or server packets should be suppressed. + * @param suppressCameraMovements {@code true} to suppress these kinds of movement, {@code false} to allow them + */ + public void setSuppressCameraMovements(boolean suppressCameraMovements) { + this.suppressCameraMovements = suppressCameraMovements; + } + + /** + * Returns all markers. + * When changed, {@link #saveMarkers()} should be called to save the changes. + * @return Set of markers + */ + public Set getMarkers() { + return markers; + } + + /** + * Saves all markers. + */ + public void saveMarkers() { + try { + replayFile.writeMarkers(markers); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Spectate the specified entity. + * When the entity is {@code null} or the camera entity, the camera becomes the view entity. + * @param e The entity to spectate + */ + public void spectateEntity(Entity e) { + CameraEntity cameraEntity = getCameraEntity(); + if (e == null || e == cameraEntity) { + spectating = null; + e = cameraEntity; + } else if (e instanceof EntityPlayer) { + spectating = e.getUniqueID(); + } + + if (mc.getRenderViewEntity() != e) { + mc.setRenderViewEntity(e); + cameraEntity.updatePos(e); + } + } + + /** + * Set the camera as the view entity. + * This is equivalent to {@link #spectateEntity(Entity) spectateEntity(null)}. + */ + public void spectateCamera() { + spectateEntity(null); + } + + /** + * Returns whether the current view entity is the camera entity. + * @return {@code true} if the camera is the view entity, {@code false} otherwise + */ + public boolean isCameraView() { + return mc.thePlayer instanceof CameraEntity && mc.thePlayer == mc.getRenderViewEntity(); + } + + /** + * Returns the camera entity. + * @return The camera entity or {@code null} if it does not yet exist + */ + public CameraEntity getCameraEntity() { + return mc.thePlayer instanceof CameraEntity ? (CameraEntity) mc.thePlayer : null; + } + + public void setTargetPosition(AdvancedPosition pos) { + targetCameraPosition = pos; + } + + public void moveCameraToTargetPosition() { + CameraEntity cam = getCameraEntity(); + if (cam != null && targetCameraPosition != null) { + cam.moveAbsolute(targetCameraPosition); + } + } + + public void doJump(int targetTime, boolean retainCameraPosition) { + if (replaySender.isHurrying()) { + return; // When hurrying, no Timeline jumping etc. is possible + } + + if (targetTime < replaySender.currentTimeStamp()) { + mc.displayGuiScreen(null); + } + + if (retainCameraPosition) { + CameraEntity cam = getCameraEntity(); + if (cam != null) { + targetCameraPosition = new AdvancedPosition(cam.posX, cam.posY, cam.posZ, + cam.rotationPitch, cam.rotationYaw, cam.roll); + } else { + targetCameraPosition = null; + } + } + + long diff = targetTime - replaySender.getDesiredTimestamp(); + if (diff != 0) { + if (diff > 0 && diff < 5000) { // Small difference and no time travel + replaySender.jumpToTime(targetTime); + } else { // We either have to restart the replay or send a significant amount of packets + // Render our please-wait-screen + GuiScreen guiScreen = new GuiScreen() { + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawBackground(0); + drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.pleasewait"), + width / 2, height / 2, 0xffffffff); + } + }; + + // Make sure that the replaysender changes into sync mode + replaySender.setSyncModeAndWait(); + + // Perform the rendering using OpenGL + pushMatrix(); + clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + enableTexture2D(); + mc.getFramebuffer().bindFramebuffer(true); + mc.entityRenderer.setupOverlayRendering(); + + Point point = MouseUtils.getScaledDimensions(); + guiScreen.setWorldAndResolution(mc, point.getX(), point.getY()); + guiScreen.drawScreen(0, 0, 0); + + mc.getFramebuffer().unbindFramebuffer(); + popMatrix(); + pushMatrix(); + mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight); + popMatrix(); + + Display.update(); + + // Send the packets + ReplayMod.replaySender.sendPacketsTill(targetTime); + ReplayMod.replaySender.setAsyncMode(true); + ReplayMod.replaySender.setReplaySpeed(0); + + mc.getNetHandler().getNetworkManager().processReceivedPackets(); + @SuppressWarnings("unchecked") + List entities = (List) mc.theWorld.loadedEntityList; + for (Entity entity : entities) { + if (entity instanceof EntityOtherPlayerMP) { + EntityOtherPlayerMP e = (EntityOtherPlayerMP) entity; + e.setPosition(e.otherPlayerMPX, e.otherPlayerMPY, e.otherPlayerMPZ); + e.rotationYaw = (float) e.otherPlayerMPYaw; + e.rotationPitch = (float) e.otherPlayerMPPitch; + } + entity.lastTickPosX = entity.prevPosX = entity.posX; + entity.lastTickPosY = entity.prevPosY = entity.posY; + entity.lastTickPosZ = entity.prevPosZ = entity.posZ; + entity.prevRotationYaw = entity.rotationYaw; + entity.prevRotationPitch = entity.rotationPitch; + } + try { + mc.runTick(); + } catch (IOException e) { + e.printStackTrace(); // This should never be thrown but whatever + } + + //finally, updating the camera's position (which is not done by the sync jumping) + moveCameraToTargetPosition(); + + // No need to remove our please-wait-screen. It'll vanish with the next + // render pass as it's never been a real GuiScreen in the first place. + } + } + } +} diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java new file mode 100644 index 00000000..599a9c28 --- /dev/null +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -0,0 +1,58 @@ +package com.replaymod.replay; + +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.handler.GuiHandler; +import de.johni0702.replaystudio.replay.ReplayFile; +import de.johni0702.replaystudio.replay.ZipReplayFile; +import de.johni0702.replaystudio.studio.ReplayStudio; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import org.apache.logging.log4j.Logger; +import org.lwjgl.input.Keyboard; + +import java.io.File; +import java.io.IOException; + +@Mod(modid = ReplayModReplay.MOD_ID, useMetadata = true) +public class ReplayModReplay { + public static final String MOD_ID = "replaymod-replay"; + + @Mod.Instance(MOD_ID) + public static ReplayModReplay instance; + + @Mod.Instance(ReplayMod.MOD_ID) + private static ReplayMod core; + + private Logger logger; + + private ReplayHandler replayHandler; + + public ReplayHandler getReplayHandler() { + return replayHandler; + } + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + logger = event.getModLog(); + + core.getSettingsRegistry().register(Setting.class); + + core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.marker", Keyboard.KEY_M, new Runnable() { + @Override + public void run() { + + } + }); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) { + new GuiHandler(this).register(); + } + + public void startReplay(File file) throws IOException { + ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file); + replayHandler = new ReplayHandler(replayFile, true); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/com/replaymod/replay/ReplaySender.java similarity index 95% rename from src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java rename to src/main/java/com/replaymod/replay/ReplaySender.java index a001ba51..321b2aec 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/com/replaymod/replay/ReplaySender.java @@ -1,13 +1,13 @@ -package eu.crushedpixel.replaymod.replay; +package com.replaymod.replay; import com.google.common.base.Preconditions; 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 de.johni0702.replaystudio.replay.ReplayFile; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.holders.PacketData; +import eu.crushedpixel.replaymod.replay.Restrictions; import eu.crushedpixel.replaymod.settings.ReplaySettings; -import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; @@ -67,6 +67,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { S39PacketPlayerAbilities.class, S45PacketTitle.class); + /** + * The replay handler responsible for the current replay. + */ + private final ReplayHandler replayHandler; + /** * Whether to work in async mode. * @@ -156,10 +161,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { * @param asyncMode {@code true} for async mode, {@code false} otherwise * @see #asyncMode */ - public ReplaySender(ReplayFile file, boolean asyncMode) { + public ReplaySender(ReplayHandler replayHandler, ReplayFile file, boolean asyncMode) throws IOException { + this.replayHandler = replayHandler; this.replayFile = file; this.asyncMode = asyncMode; - this.replayLength = file.metadata().get().getDuration(); + this.replayLength = file.getMetaData().getDuration(); if (asyncMode) { new Thread(asyncSender, "replaymod-async-sender").start(); @@ -296,7 +302,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { if (p instanceof S3FPacketCustomPayload) { S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p; if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) { - final String unknown = ReplayHandler.getRestrictions().handle(packet); + final String unknown = replayHandler.getRestrictions().handle(packet); if (unknown == null) { return null; } else { @@ -306,7 +312,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { mc.addScheduledTask(new Runnable() { @Override public void run() { - ReplayHandler.endReplay(); + try { + replayHandler.endReplay(); + } catch (IOException e) { + e.printStackTrace(); + } mc.displayGuiScreen(new GuiErrorScreen( I18n.format("replaymod.error.unknownrestriction1"), I18n.format("replaymod.error.unknownrestriction2", unknown) @@ -327,12 +337,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { if(BAD_PACKETS.contains(p.getClass())) return null; - if(ReplayProcess.isVideoRecording() && ReplayHandler.isInPath()) { - if(p instanceof S29PacketSoundEffect) { - return null; - } - } - convertLegacyEntityIds(p); if(p instanceof S48PacketResourcePackSend) { @@ -340,13 +344,13 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { String url = packet.func_179783_a(); if (url.startsWith("replay://")) { int id = Integer.parseInt(url.substring("replay://".length())); - Map index = replayFile.resourcePackIndex().get(); + Map index = replayFile.getResourcePackIndex(); if (index != null) { String hash = index.get(id); if (hash != null) { File file = new File(tempResourcePackFolder, hash + ".zip"); if (!file.exists()) { - IOUtils.copy(replayFile.resourcePack(hash).get(), new FileOutputStream(file)); + IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file)); } mc.getResourcePackRepository().func_177319_a(file); } @@ -387,9 +391,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { mc.displayGuiScreen(null); } - if(ReplayHandler.isInPath()) return null; + if(replayHandler.shouldSuppressCameraMovements()) return null; - CameraEntity cent = ReplayHandler.getCameraEntity(); + CameraEntity cent = replayHandler.getCameraEntity(); for (Object relative : ppl.func_179834_f()) { if (relative == S08PacketPlayerPosLook.EnumFlags.X @@ -419,7 +423,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { return null; } - CameraEntity cent = ReplayHandler.getCameraEntity(); + CameraEntity cent = replayHandler.getCameraEntity(); cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e()); return null; } @@ -461,7 +465,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - replayFile.close(); FileUtils.deleteDirectory(tempResourcePackFolder); super.channelInactive(ctx); } @@ -522,7 +525,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { while (!terminate) { synchronized (ReplaySender.this) { if (dis == null) { - dis = new DataInputStream(replayFile.recording().get()); + dis = new DataInputStream(replayFile.getPacketData()); } // Packet loop while (true) { @@ -580,7 +583,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { if (isHurrying() && lastTimeStamp > desiredTimeStamp && !startFromBeginning) { desiredTimeStamp = -1; - ReplayHandler.moveCameraToLastPosition(); + replayHandler.moveCameraToTargetPosition(); // Pause after jumping setReplaySpeed(0); @@ -605,7 +608,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { startFromBeginning = false; nextPacket = null; lastPacketSent = System.currentTimeMillis(); - ReplayHandler.restartReplay(); + replayHandler.restartedReplay(); if (dis != null) { dis.close(); dis = null; @@ -659,8 +662,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } protected Packet processPacketAsync(Packet p) { - //If hurrying, ignore some packets, unless during Replay Path and *not* in short hurries - if(!ReplayHandler.isInPath() && desiredTimeStamp - lastTimeStamp > 1000) { + //If hurrying, ignore some packets, except for short durations + if(desiredTimeStamp - lastTimeStamp > 1000) { if(p instanceof S2APacketParticles) return null; if(p instanceof S0EPacketSpawnObject) { @@ -700,11 +703,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } startFromBeginning = false; nextPacket = null; - ReplayHandler.restartReplay(); + replayHandler.restartedReplay(); } if (dis == null) { - dis = new DataInputStream(replayFile.recording().get()); + dis = new DataInputStream(replayFile.getPacketData()); } while (true) { // Send packets diff --git a/src/main/java/com/replaymod/replay/Setting.java b/src/main/java/com/replaymod/replay/Setting.java new file mode 100644 index 00000000..7adf2527 --- /dev/null +++ b/src/main/java/com/replaymod/replay/Setting.java @@ -0,0 +1,17 @@ +package com.replaymod.replay; + +import com.replaymod.core.SettingsRegistry; + +public final class Setting extends SettingsRegistry.SettingKeys { + public static final Setting RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true); + public static final Setting RECORD_SERVER = make("recordServer", "recordserver", true); + public static final Setting INDICATOR = make("indicator", "indicator", true); + + private static Setting make(String key, String displayName, T defaultValue) { + return new Setting<>(key, displayName, defaultValue); + } + + public Setting(String key, String displayString, T defaultValue) { + super("recording", key, "replaymod.gui.settings." + displayString, defaultValue); + } +} diff --git a/src/main/java/com/replaymod/replay/events/ReplayCloseEvent.java b/src/main/java/com/replaymod/replay/events/ReplayCloseEvent.java new file mode 100644 index 00000000..f01720e6 --- /dev/null +++ b/src/main/java/com/replaymod/replay/events/ReplayCloseEvent.java @@ -0,0 +1,24 @@ +package com.replaymod.replay.events; + +import com.replaymod.replay.ReplayHandler; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraftforge.fml.common.eventhandler.Event; + +@RequiredArgsConstructor +public abstract class ReplayCloseEvent extends Event { + @Getter + private final ReplayHandler replayHandler; + + public static class Pre extends ReplayCloseEvent { + public Pre(ReplayHandler replayHandler) { + super(replayHandler); + } + } + + public static class Post extends ReplayCloseEvent { + public Post(ReplayHandler replayHandler) { + super(replayHandler); + } + } +} diff --git a/src/main/java/com/replaymod/replay/events/ReplayOpenEvent.java b/src/main/java/com/replaymod/replay/events/ReplayOpenEvent.java new file mode 100644 index 00000000..ad970a37 --- /dev/null +++ b/src/main/java/com/replaymod/replay/events/ReplayOpenEvent.java @@ -0,0 +1,24 @@ +package com.replaymod.replay.events; + +import com.replaymod.replay.ReplayHandler; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraftforge.fml.common.eventhandler.Event; + +@RequiredArgsConstructor +public abstract class ReplayOpenEvent extends Event { + @Getter + private final ReplayHandler replayHandler; + + public static class Pre extends ReplayOpenEvent { + public Pre(ReplayHandler replayHandler) { + super(replayHandler); + } + } + + public static class Post extends ReplayOpenEvent { + public Post(ReplayHandler replayHandler) { + super(replayHandler); + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiMarkerTimeline.java b/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java similarity index 56% rename from src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiMarkerTimeline.java rename to src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java index 6ae4e025..d12ecc3c 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiMarkerTimeline.java +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java @@ -1,10 +1,10 @@ -package eu.crushedpixel.replaymod.gui.elements.timelines; +package com.replaymod.replay.gui.overlay; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.gui.GuiEditKeyframe; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.Marker; -import eu.crushedpixel.replaymod.replay.ReplayHandler; +import de.johni0702.replaystudio.data.Marker; +import com.replaymod.core.ReplayMod; +import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline; +import eu.crushedpixel.replaymod.holders.AdvancedPosition; +import com.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.MouseUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.I18n; @@ -16,13 +16,16 @@ public class GuiMarkerTimeline extends GuiTimeline { private static final int KEYFRAME_MARKER_X = 109; private static final int KEYFRAME_MARKER_Y = 20; - private Keyframe clickedKeyFrame; + private final ReplayHandler replayHandler; + private Marker selectedMarker; + private Marker clickedMarker; private long clickTime; private boolean dragging; - public GuiMarkerTimeline(int positionX, int positionY, int width, int height, boolean showMarkers) { + public GuiMarkerTimeline(ReplayHandler replayHandler, int positionX, int positionY, int width, int height) { super(positionX, positionY, width, height); - this.showMarkers = showMarkers; + this.replayHandler = replayHandler; + this.showMarkers = false; } @Override @@ -36,30 +39,33 @@ public class GuiMarkerTimeline extends GuiTimeline { int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); - Keyframe closest = null; + Marker closest = null; if(mouseY >= positionY + BORDER_TOP + 10) { - closest = ReplayHandler.getMarkerKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); + long distance = tolerance; + for (Marker m : replayHandler.getMarkers()) { + long d = Math.abs(m.getTime() - time); + if (d <= distance) { + closest = m; + distance = d; + } + } } //left mouse button if(button == 0) { - ReplayHandler.selectKeyframe(closest); - if(closest == null) { //if no keyframe clicked, jump in time - ReplayMod.overlay.performJump(getTimeAt(mouseX, mouseY)); + replayHandler.doJump((int) getTimeAt(mouseX, mouseY), true); } else { + selectedMarker = closest; // If we clicked on a key frame, then continue monitoring the mouse for movements long currentTime = System.currentTimeMillis(); - if(closest != null) { - if(currentTime - clickTime < 500) { // if double clicked then open GUI instead - mc.displayGuiScreen(GuiEditKeyframe.create(closest)); - this.clickedKeyFrame = null; - } else { - this.clickedKeyFrame = closest; - this.dragging = false; - } - } else { // If we didn't then just update the cursor - this.dragging = true; + if(currentTime - clickTime < 500) { // if double clicked then open GUI instead +// mc.displayGuiScreen(GuiEditKeyframe.create(closest)); + // TODO Edit Gui + this.clickedMarker = null; + } else { + this.clickedMarker = closest; + this.dragging = false; } this.clickTime = currentTime; } @@ -67,10 +73,13 @@ public class GuiMarkerTimeline extends GuiTimeline { } else if(button == 1) { if(closest != null) { //Jump to clicked Marker Keyframe (explicitly force to jump to this position) - ReplayHandler.setLastPosition(closest.getValue().getPosition(), true); + replayHandler.setTargetPosition(new AdvancedPosition( + closest.getX(), closest.getY(), closest.getZ(), + closest.getPitch(), closest.getYaw(), closest.getRoll() + )); //perform the jump, telling the Overlay not to override the last position value - ReplayMod.overlay.performJump(closest.getRealTimestamp(), false); + replayHandler.doJump(closest.getTime(), false); } } @@ -82,11 +91,11 @@ public class GuiMarkerTimeline extends GuiTimeline { if(!enabled) return; long time = getTimeAt(mouseX, mouseY); if (time != -1) { - if (clickedKeyFrame != null) { + if (clickedMarker != null) { int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); - if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) { - clickedKeyFrame.setRealTimestamp((int) time); + if (dragging || Math.abs(clickedMarker.getTime() - time) > tolerance) { + clickedMarker.setTime((int) time); dragging = true; } } @@ -96,8 +105,11 @@ public class GuiMarkerTimeline extends GuiTimeline { @Override public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { mouseDrag(mc, mouseX, mouseY, button); - clickedKeyFrame = null; - dragging = false; + clickedMarker = null; + if (dragging) { + replayHandler.saveMarkers(); + dragging = false; + } } @Override @@ -114,17 +126,12 @@ public class GuiMarkerTimeline extends GuiTimeline { drawTimelineCursor(leftTime, rightTime, bodyWidth); //Draw Keyframe logos - for(Keyframe kf : ReplayHandler.getMarkerKeyframes()) { - if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe())) - drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength); - } - - if(ReplayHandler.getSelectedKeyframe() != null && ReplayHandler.getSelectedKeyframe().getValue() instanceof Marker) { - drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength); + for (Marker marker : replayHandler.getMarkers()) { + drawMarker(marker, bodyWidth, leftTime, rightTime, segmentLength); } } - private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { + private int getMarkerX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { long positionInSegment = timestamp - leftTime; double fractionOfSegment = positionInSegment / segmentLength; return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); @@ -139,12 +146,12 @@ public class GuiMarkerTimeline extends GuiTimeline { long leftTime = Math.round(timeStart * timelineLength); double segmentLength = timelineLength * zoom; - for(Keyframe marker : ReplayHandler.getMarkerKeyframes()) { - int keyframeX = getKeyframeX(marker.getRealTimestamp(), leftTime, bodyWidth, segmentLength); + for (Marker marker : replayHandler.getMarkers()) { + int markerX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength); - if(MouseUtils.isMouseWithinBounds(keyframeX - 2, this.positionY + BORDER_TOP + 10 + 1, 5, 5)) { + if(MouseUtils.isMouseWithinBounds(markerX - 2, this.positionY + BORDER_TOP + 10 + 1, 5, 5)) { Point mouse = MouseUtils.getMousePos(); - String markerName = marker.getValue().getName(); + String markerName = marker.getName(); if(markerName == null || markerName.isEmpty()) markerName = I18n.format("replaymod.gui.ingame.unnamedmarker"); ReplayMod.tooltipRenderer.drawTooltip(mouse.getX(), mouse.getY(), markerName, null, Color.WHITE); @@ -157,15 +164,15 @@ public class GuiMarkerTimeline extends GuiTimeline { } } - private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) { - if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { + private void drawMarker(Marker marker, int bodyWidth, long leftTime, long rightTime, double segmentLength) { + if (marker.getTime() <= rightTime && marker.getTime() >= leftTime) { int textureX = KEYFRAME_MARKER_X; int textureY = KEYFRAME_MARKER_Y; int y = positionY+10; - int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); + int keyframeX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength); - if (ReplayHandler.isSelected(kf)) { + if (selectedMarker == marker) { textureX += 5; } diff --git a/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java b/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java new file mode 100644 index 00000000..a6bfaddf --- /dev/null +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java @@ -0,0 +1,140 @@ +package com.replaymod.replay.gui.overlay; + +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.ReplayHandler; +import com.replaymod.replay.ReplaySender; +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.container.AbstractGuiOverlay; +import de.johni0702.minecraft.gui.container.GuiPanel; +import de.johni0702.minecraft.gui.element.GuiSlider; +import de.johni0702.minecraft.gui.element.GuiTexturedButton; +import de.johni0702.minecraft.gui.element.advanced.GuiTimeline; +import de.johni0702.minecraft.gui.element.advanced.IGuiTimeline; +import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.settings.GameSettings; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import org.lwjgl.util.ReadableDimension; +import org.lwjgl.util.ReadablePoint; +import org.lwjgl.util.WritablePoint; + +import static com.replaymod.core.ReplayMod.TEXTURE_SIZE; + +public class GuiReplayOverlay extends AbstractGuiOverlay { + + private final ReplayHandler replayHandler; + public final GuiPanel topPanel = new GuiPanel(this) + .setLayout(new HorizontalLayout(HorizontalLayout.Alignment.LEFT).setSpacing(5)); + public final GuiTexturedButton playPauseButton = new GuiTexturedButton().setSize(20, 20) + .setTexture(ReplayMod.TEXTURE, TEXTURE_SIZE); + public final GuiSlider speedSlider = new GuiSlider().setSize(100, 20).setSteps(37); // 0.0 is not included + public final GuiTimeline timeline = new GuiTimeline(){ + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + setCursorPosition(replayHandler.getReplaySender().currentTimeStamp()); + super.draw(renderer, size, renderInfo); + } + }.setSize(Integer.MAX_VALUE, 20); + + public GuiReplayOverlay(final ReplayHandler replayHandler) { + this.replayHandler = replayHandler; + + topPanel.addElements(null, playPauseButton, speedSlider, timeline); + setLayout(new CustomLayout() { + @Override + protected void layout(GuiReplayOverlay container, int width, int height) { + pos(topPanel, 10, 10); + size(topPanel, width - 20, 20); + } + }); + + playPauseButton.setTexturePosH(new ReadablePoint() { + @Override + public int getX() { + return 0; + } + + @Override + public int getY() { + return replayHandler.getReplaySender().paused() ? 0 : 20; + } + + @Override + public void getLocation(WritablePoint dest) { + dest.setLocation(getX(), getY()); + } + }).onClick(new Runnable() { + @Override + public void run() { + ReplaySender replaySender = replayHandler.getReplaySender(); + // If currently paused + if (replaySender.paused()) { + // then play + replaySender.setReplaySpeed(getSpeed()); + } else { + // else pause + replaySender.setReplaySpeed(0); + } + } + }); + + speedSlider.onValueChanged(new Runnable() { + @Override + public void run() { + double speed = getSpeed(); + speedSlider.setText(I18n.format("replaymod.gui.speed") + ": " + speed + "x"); + ReplaySender replaySender = replayHandler.getReplaySender(); + if (!replaySender.paused()) { + replaySender.setReplaySpeed(speed); + } + } + }).setValue(9); + + timeline.onClick(new IGuiTimeline.OnClick() { + @Override + public void run(int time) { + replayHandler.doJump(time, true); + } + }).setLength(replayHandler.getReplaySender().replayLength()); + } + + private double getSpeed() { + int value = speedSlider.getValue() + 1; + if (value <= 9) { + return value / 10d; + } else { + return 1 + (0.25d * (value - 10)); + } + } + + @Override + public void setVisible(boolean visible) { + if (isVisible() != visible) { + if (visible) { + FMLCommonHandler.instance().bus().register(this); + } else { + FMLCommonHandler.instance().bus().unregister(this); + } + } + super.setVisible(visible); + } + + @SubscribeEvent + public void onKeyInput(InputEvent.KeyInputEvent event) { + GameSettings gameSettings = getMinecraft().gameSettings; + while (gameSettings.keyBindChat.isPressed() || gameSettings.keyBindCommand.isPressed()) { + if (!isMouseVisible()) { + setMouseVisible(true); + } + } + } + + @Override + protected GuiReplayOverlay getThis() { + return this; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiRenameReplay.java b/src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java similarity index 94% rename from src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiRenameReplay.java rename to src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java index 787605fd..c580200f 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiRenameReplay.java +++ b/src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java @@ -1,6 +1,5 @@ -package eu.crushedpixel.replaymod.gui.replayviewer; +package com.replaymod.replay.gui.screen; -import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiErrorScreen; @@ -57,7 +56,7 @@ public class GuiRenameReplay extends GuiScreen { } else if(button.id == 0) { File folder = ReplayFileIO.getReplayFolder(); - File initRenamed = new File(folder, (this.replayNameInput.getText().trim() + ReplayFile.ZIP_FILE_EXTENSION).replaceAll("[^a-zA-Z0-9\\.\\- ]", "_")); + File initRenamed = new File(folder, (this.replayNameInput.getText().trim() + ".zip").replaceAll("[^a-zA-Z0-9\\.\\- ]", "_")); File renamed = ReplayFileIO.getNextFreeFile(initRenamed); try { FileUtils.moveFile(file, renamed); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java similarity index 91% rename from src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java rename to src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java index 6be4fd91..e41770d3 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java +++ b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java @@ -1,18 +1,21 @@ -package eu.crushedpixel.replaymod.gui.replayviewer; +package com.replaymod.replay.gui.screen; +import com.google.common.base.Optional; import com.mojang.realmsclient.util.Pair; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; +import com.replaymod.core.gui.GuiReplaySettings; +import com.replaymod.replay.ReplayModReplay; +import de.johni0702.replaystudio.replay.ReplayFile; +import de.johni0702.replaystudio.replay.ReplayMetaData; +import de.johni0702.replaystudio.replay.ZipReplayFile; +import de.johni0702.replaystudio.studio.ReplayStudio; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; -import eu.crushedpixel.replaymod.gui.GuiReplaySettings; import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; -import eu.crushedpixel.replaymod.recording.ReplayMetaData; import eu.crushedpixel.replaymod.registry.ResourceHelper; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.ImageUtils; -import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; @@ -34,6 +37,7 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.List; +import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { @@ -45,6 +49,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { private static final int DELETE_BUTTON_ID = 9005; private static final int SETTINGS_BUTTON_ID = 9006; private static final int CANCEL_BUTTON_ID = 9007; + private final ReplayModReplay mod; private boolean initialized; private GuiReplayListExtended replayGuiList; private List, File>> replayFileList = new ArrayList, File>>(); @@ -58,6 +63,10 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { private Thread fileReloader; + public GuiReplayViewer(ReplayModReplay mod) { + this.mod = mod; + } + private class FileReloaderThread extends Thread { private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry(); @@ -74,26 +83,26 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { for(final File file : ReplayFileIO.getAllReplayFiles()) { if(interrupted()) break; try { - ReplayFile replayFile = new ReplayFile(file); - final ReplayMetaData metaData = replayFile.metadata().get(); - BufferedImage img = replayFile.thumb().get(); + ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file); + final ReplayMetaData metaData = replayFile.getMetaData(); + Optional thumb = replayFile.getThumb(); replayFile.close(); File tmp = null; - if(img != null) { - img = ImageUtils.scaleImage(img, new Dimension(1280, 720)); + if(thumb.isPresent()) { + BufferedImage img = ImageUtils.scaleImage(thumb.get(), new Dimension(1280, 720)); tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg"); tmp.deleteOnExit(); ImageIO.write(img, "jpg", tmp); } - final File thumb = tmp; + final File thumbFile = tmp; loadedReplaysQueue.offer(new Runnable() { @Override public void run() { - addEntry(file, metaData, thumb); + addEntry(file, metaData, thumbFile); } }); } catch(Exception e) { @@ -213,7 +222,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { this.mc.displayGuiScreen(guiyesno); } } else if(button.id == SETTINGS_BUTTON_ID) { - this.mc.displayGuiScreen(new GuiReplaySettings(this)); + new GuiReplaySettings(this, ReplayMod.instance.getSettingsRegistry()).display(); } else if(button.id == RENAME_BUTTON_ID) { File file = replayFileList.get(replayGuiList.selected).first().first(); this.mc.displayGuiScreen(new GuiRenameReplay(this, file)); @@ -306,7 +315,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { mc.displayGuiScreen(null); try { - ReplayHandler.startReplay(replayFileList.get(id).first().first()); + mod.startReplay(replayFileList.get(id).first().first()); } catch(Exception e) { e.printStackTrace(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java b/src/main/java/com/replaymod/replay/gui/screen/ReplayList.java similarity index 94% rename from src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java rename to src/main/java/com/replaymod/replay/gui/screen/ReplayList.java index 29912d7a..c08f517b 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java +++ b/src/main/java/com/replaymod/replay/gui/screen/ReplayList.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui.replayviewer; +package com.replaymod.replay.gui.screen; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/replaymod/replay/handler/GuiHandler.java b/src/main/java/com/replaymod/replay/handler/GuiHandler.java new file mode 100644 index 00000000..8ad74d1f --- /dev/null +++ b/src/main/java/com/replaymod/replay/handler/GuiHandler.java @@ -0,0 +1,111 @@ +package com.replaymod.replay.handler; + +import com.replaymod.replay.ReplayModReplay; +import com.replaymod.replay.gui.screen.GuiReplayViewer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiIngameMenu; +import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GuiHandler { + private static final int BUTTON_EXIT_SERVER = 1; + private static final int BUTTON_RETURN_TO_GAME = 4; + private static final int BUTTON_ACHIEVEMENTS = 5; + private static final int BUTTON_STATS = 6; + private static final int BUTTON_OPEN_TO_LAN = 7; + + private static final int BUTTON_REPLAY_VIEWER = 17890234; + private static final int BUTTON_EXIT_REPLAY = 17890235; + + private static final Minecraft mc = Minecraft.getMinecraft(); + + private final ReplayModReplay mod; + + public GuiHandler(ReplayModReplay mod) { + this.mod = mod; + } + + public void register() { + FMLCommonHandler.instance().bus().register(this); + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void injectIntoIngameMenu(GuiScreenEvent.InitGuiEvent.Post event) { + if (!(event.gui instanceof GuiIngameMenu)) { + return; + } + + if (mod.getReplayHandler() != null) { + // Pause replay when menu is opened + mod.getReplayHandler().getReplaySender().setReplaySpeed(0); + + @SuppressWarnings("unchecked") + List buttonList = event.buttonList; + for(GuiButton b : new ArrayList<>(buttonList)) { + switch (b.id) { + // Replace "Exit Server" button with "Exit Replay" button + case BUTTON_EXIT_SERVER: + b.displayString = I18n.format("replaymod.gui.exit"); + b.id = BUTTON_EXIT_REPLAY; + break; + // Remove "Achievements", "Stats" and "Open to LAN" buttons + case BUTTON_ACHIEVEMENTS: + case BUTTON_STATS: + case BUTTON_OPEN_TO_LAN: + buttonList.remove(b); + } + // Move all buttons except the "Return to game" button upwards + if (b.id != BUTTON_RETURN_TO_GAME) { + b.yPosition -= 48; + } + } + } + } + + @SubscribeEvent + public void injectIntoMainMenu(GuiScreenEvent.InitGuiEvent event) { + if (!(event.gui instanceof GuiMainMenu)) { + return; + } + + @SuppressWarnings("unchecked") + List buttonList = event.buttonList; + GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.gui.width / 2 - 100, + event.gui.height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer")); + button.width = button.width / 2 - 2; + buttonList.add(button); + } + + @SubscribeEvent + public void onButton(GuiScreenEvent.ActionPerformedEvent event) { + if(!event.button.enabled) return; + + if (event.gui instanceof GuiMainMenu) { + if (event.button.id == BUTTON_REPLAY_VIEWER) { + mc.displayGuiScreen(new GuiReplayViewer(mod)); + } + } + + if (event.gui instanceof GuiIngameMenu && mod.getReplayHandler() != null) { + if (event.button.id == BUTTON_EXIT_REPLAY) { + event.button.enabled = false; + try { + mod.getReplayHandler().endReplay(); + } catch (IOException e) { + e.printStackTrace(); + } + mc.displayGuiScreen(new GuiMainMenu()); + } + } + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java new file mode 100644 index 00000000..36130eff --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.container; + +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.MinecraftGuiRenderer; +import de.johni0702.minecraft.gui.OffsetGuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.element.GuiElement; +import de.johni0702.minecraft.gui.function.*; +import eu.crushedpixel.replaymod.utils.MouseUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.crash.CrashReport; +import net.minecraft.crash.CrashReportCategory; +import net.minecraft.util.ReportedException; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.util.Dimension; +import org.lwjgl.util.Point; +import org.lwjgl.util.ReadableDimension; +import org.lwjgl.util.ReadablePoint; + +import java.io.IOException; +import java.util.concurrent.Callable; + +public abstract class AbstractGuiOverlay> extends AbstractGuiContainer { + + private final UserInputGuiScreen userInputGuiScreen = new UserInputGuiScreen(); + private final EventHandler eventHandler = new EventHandler(); + private boolean visible; + private Dimension screenSize; + private boolean mouseVisible; + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + if (this.visible != visible) { + if (visible) { + MinecraftForge.EVENT_BUS.register(eventHandler); + } else { + forEach(Closeable.class).close(); + MinecraftForge.EVENT_BUS.unregister(eventHandler); + } + updateUserInputGui(); + } + this.visible = visible; + } + + public boolean isMouseVisible() { + return mouseVisible; + } + + public void setMouseVisible(boolean mouseVisible) { + this.mouseVisible = mouseVisible; + updateUserInputGui(); + } + + private void updateUserInputGui() { + Minecraft mc = getMinecraft(); + if (visible) { + if (mouseVisible) { + if (mc.currentScreen != userInputGuiScreen) { + mc.displayGuiScreen(userInputGuiScreen); + } + } else { + if (mc.currentScreen == userInputGuiScreen) { + mc.displayGuiScreen(null); + } + } + } + } + + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + super.draw(renderer, size, renderInfo); + if (mouseVisible && renderInfo.layer == getMaxLayer()) { + final GuiElement tooltip = forEach(GuiElement.class).getTooltip(renderInfo); + if (tooltip != null) { + final ReadableDimension tooltipSize = tooltip.getMinSize(); + int x, y; + if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) { + x = renderInfo.mouseX + 8; + } else { + x = screenSize.getWidth() - tooltipSize.getWidth() - 1; + } + if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) { + y = renderInfo.mouseY + 8; + } else { + y = screenSize.getHeight() - tooltipSize.getHeight() - 1; + } + final ReadablePoint position = new Point(x, y); + try { + OffsetGuiRenderer eRenderer = new OffsetGuiRenderer(renderer, position, tooltipSize); + tooltip.draw(eRenderer, tooltipSize, renderInfo); + } catch (Exception ex) { + CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip"); + renderInfo.addTo(crashReport); + CrashReportCategory category = crashReport.makeCategory("Gui container details"); + category.addCrashSectionCallable("Container", new Callable() { + @Override + public Object call() throws Exception { + return this; + } + }); + category.addCrashSection("Width", size.getWidth()); + category.addCrashSection("Height", size.getHeight()); + category = crashReport.makeCategory("Tooltip details"); + category.addCrashSectionCallable("Element", new Callable() { + @Override + public Object call() throws Exception { + return tooltip; + } + }); + category.addCrashSectionCallable("Position", new Callable() { + @Override + public Object call() throws Exception { + return position; + } + }); + category.addCrashSectionCallable("Size", new Callable() { + @Override + public Object call() throws Exception { + return tooltipSize; + } + }); + throw new ReportedException(crashReport); + } + } + } + } + + @Override + public ReadableDimension getMinSize() { + return screenSize; + } + + @Override + public ReadableDimension getMaxSize() { + return screenSize; + } + + private class EventHandler { + private MinecraftGuiRenderer renderer; + + @SubscribeEvent + public void renderOverlay(RenderGameOverlayEvent.Post event) { + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + updateRenderer(); + int layers = getMaxLayer(); + int mouseX = -1, mouseY = -1; + if (mouseVisible) { + Point mouse = MouseUtils.getMousePos(); + mouseX = mouse.getX(); + mouseY = mouse.getY(); + } + for (int layer = 0; layer <= layers; layer++) { + draw(renderer, screenSize, new RenderInfo(event.partialTicks, mouseX, mouseY, layer)); + } + } + } + + @SubscribeEvent + public void tickOverlay(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + forEach(Tickable.class).tick(); + } + } + + private void updateRenderer() { + Minecraft mc = getMinecraft(); + ScaledResolution res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + if (screenSize == null + || screenSize.getWidth() != res.getScaledWidth() + || screenSize.getHeight() != res.getScaledHeight()) { + screenSize = new Dimension(res.getScaledWidth(), res.getScaledHeight()); + renderer = new MinecraftGuiRenderer(screenSize); + } + } + } + + protected class UserInputGuiScreen extends net.minecraft.client.gui.GuiScreen { + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + forEach(Typeable.class).typeKey(MouseUtils.getMousePos(), keyCode, typedChar, isCtrlKeyDown(), isShiftKeyDown()); + super.keyTyped(typedChar, keyCode); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + forEach(Clickable.class).mouseClick(new Point(mouseX, mouseY), mouseButton); + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int mouseButton) { + forEach(Draggable.class).mouseClick(new Point(mouseX, mouseY), mouseButton); + } + + @Override + protected void mouseClickMove(int mouseX, int mouseY, int mouseButton, long timeSinceLastClick) { + forEach(Draggable.class).mouseDrag(new Point(mouseX, mouseY), mouseButton, timeSinceLastClick); + } + + @Override + public void updateScreen() { + forEach(Tickable.class).tick(); + } + + @Override + public void onGuiClosed() { + mouseVisible = false; + } + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java index 520d214e..4558c9ea 100644 --- a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java +++ b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiScreen.java @@ -83,21 +83,21 @@ public abstract class AbstractGuiScreen> extends final GuiElement tooltip = forEach(GuiElement.class).getTooltip(renderInfo); if (tooltip != null) { final ReadableDimension tooltipSize = tooltip.getMinSize(); - int dx, dy; + int x, y; if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) { - dx = 8; + x = renderInfo.mouseX + 8; } else { - dx = -8; + x = screenSize.getWidth() - tooltipSize.getWidth() - 1; } if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) { - dy = 8; + y = renderInfo.mouseY + 8; } else { - dy = -8; + y = screenSize.getHeight() - tooltipSize.getHeight() - 1; } - final ReadablePoint position = new Point(renderInfo.mouseX + dx, renderInfo.mouseY + dy); + final ReadablePoint position = new Point(x, y); try { OffsetGuiRenderer eRenderer = new OffsetGuiRenderer(renderer, position, tooltipSize); - tooltip.draw(eRenderer, tooltipSize, renderInfo.offsetMouse(position.getX(), position.getY())); + tooltip.draw(eRenderer, tooltipSize, renderInfo); } catch (Exception ex) { CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip"); renderInfo.addTo(crashReport); diff --git a/src/main/java/de/johni0702/minecraft/gui/container/GuiOverlay.java b/src/main/java/de/johni0702/minecraft/gui/container/GuiOverlay.java new file mode 100644 index 00000000..acfe39b6 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/container/GuiOverlay.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.container; + +public class GuiOverlay extends AbstractGuiOverlay { + @Override + protected GuiOverlay getThis() { + return this; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiElement.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiElement.java index a72bfda2..cdc66592 100644 --- a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiElement.java +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiElement.java @@ -26,11 +26,14 @@ import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.container.GuiContainer; import lombok.Getter; import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; import org.lwjgl.util.Dimension; import org.lwjgl.util.Point; import org.lwjgl.util.ReadableDimension; public abstract class AbstractGuiElement> implements GuiElement { + protected static final ResourceLocation TEXTURE = new ResourceLocation("guiapi", "gui.png"); + @Getter private final Minecraft minecraft = Minecraft.getMinecraft(); diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiSlider.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiSlider.java new file mode 100644 index 00000000..2a3c58b5 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiSlider.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element; + +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.container.GuiContainer; +import de.johni0702.minecraft.gui.function.Clickable; +import de.johni0702.minecraft.gui.function.Draggable; +import net.minecraft.client.resources.I18n; +import org.lwjgl.util.Dimension; +import org.lwjgl.util.Point; +import org.lwjgl.util.ReadableDimension; +import org.lwjgl.util.ReadablePoint; + +// TODO: Currently assumes a height of 20 +public abstract class AbstractGuiSlider> extends AbstractGuiElement implements Clickable, Draggable, IGuiSlider { + private Runnable onValueChanged; + private ReadableDimension size; + + private int value; + private int steps; + + private String text = ""; + + private boolean dragging; + + public AbstractGuiSlider() { + } + + public AbstractGuiSlider(GuiContainer container) { + super(container); + } + + @Override + protected ReadableDimension calcMinSize() { + return new Dimension(0, 0); + } + + @Override + public boolean mouseClick(ReadablePoint position, int button) { + Point pos = new Point(position); + if (getContainer() != null) { + getContainer().convertFor(this, pos); + } + + if (isMouseHovering(pos) && isEnabled()) { + updateValue(pos); + dragging = true; + return true; + } + return false; + } + + @Override + public boolean mouseDrag(ReadablePoint position, int button, long timeSinceLastCall) { + if (dragging) { + Point pos = new Point(position); + if (getContainer() != null) { + getContainer().convertFor(this, pos); + } + updateValue(pos); + } + return dragging; + } + + @Override + public boolean mouseRelease(ReadablePoint position, int button) { + if (dragging) { + dragging = false; + Point pos = new Point(position); + if (getContainer() != null) { + getContainer().convertFor(this, pos); + } + updateValue(pos); + return true; + } else { + return false; + } + } + + protected boolean isMouseHovering(ReadablePoint pos) { + return pos.getX() > 0 && pos.getY() > 0 + && pos.getX() < size.getWidth() && pos.getY() < size.getHeight(); + } + + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + this.size = size; + + int width = size.getWidth(); + int height = size.getHeight(); + + renderer.bindTexture(GuiButton.WIDGETS_TEXTURE); + + // Draw background + renderer.drawTexturedRect(0, 0, 0, 46, width / 2, height); + renderer.drawTexturedRect(width / 2, 0, 200 - width / 2, 46, width / 2, height); + + // Draw slider + int sliderX = (width - 8) * value / steps; + renderer.drawTexturedRect(sliderX, 0, 0, 66, 4, 20); + renderer.drawTexturedRect(sliderX + 4, 0, 196, 66, 4, 20); + + // Draw text + int color = 0xe0e0e0; + if (!isEnabled()) { + color = 0xa0a0a0; + } else if (isMouseHovering(new Point(renderInfo.mouseX, renderInfo.mouseY))) { + color = 0xffffa0; + } + renderer.drawCenteredString(width / 2, height / 2 - 4, color, text); + } + + protected void updateValue(ReadablePoint position) { + if (size == null) { + return; + } + int width = size.getWidth() - 8; + int pos = Math.max(0, Math.min(width, position.getX() - 4)); + setValue(steps * pos / width); + } + + public void onValueChanged() { + if (onValueChanged != null) { + onValueChanged.run(); + } + } + + @Override + public T setText(String text) { + this.text = text; + return getThis(); + } + + @Override + public T setI18nText(String text, Object... args) { + return setText(I18n.format(text, args)); + } + + @Override + public T setValue(int value) { + this.value = value; + onValueChanged(); + return getThis(); + } + + @Override + public int getValue() { + return value; + } + + @Override + public int getSteps() { + return steps; + } + + @Override + public T setSteps(int steps) { + this.steps = steps; + return getThis(); + } + + @Override + public T onValueChanged(Runnable runnable) { + this.onValueChanged = runnable; + return getThis(); + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTexturedButton.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTexturedButton.java new file mode 100644 index 00000000..02b77f6f --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiTexturedButton.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element; + +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.container.GuiContainer; +import de.johni0702.minecraft.gui.function.Clickable; +import lombok.Getter; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.util.*; + +import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA; +import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA; + +public abstract class AbstractGuiTexturedButton> extends AbstractGuiClickable implements Clickable, IGuiTexturedButton { + protected static final ResourceLocation BUTTON_SOUND = new ResourceLocation("gui.button.press"); + + @Getter + private ResourceLocation texture; + + @Getter + private ReadableDimension textureSize = new ReadableDimension() { + @Override + public int getWidth() { + return getMaxSize().getWidth(); + } + + @Override + public int getHeight() { + return getMaxSize().getHeight(); + } + + @Override + public void getSize(WritableDimension dest) { + getMaxSize().getSize(dest); + } + }; + + @Getter + private ReadableDimension textureTotalSize; + + @Getter + private ReadablePoint textureNormal; + + @Getter + private ReadablePoint textureHover; + + @Getter + private ReadablePoint textureDisabled; + + public AbstractGuiTexturedButton() { + } + + public AbstractGuiTexturedButton(GuiContainer container) { + super(container); + } + + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + super.draw(renderer, size, renderInfo); + + renderer.bindTexture(texture); + + ReadablePoint texture = textureNormal; + if (!isEnabled()) { + texture = textureDisabled; + } else if (isMouseHovering(new Point(renderInfo.mouseX, renderInfo.mouseY))) { + texture = textureHover; + } + + if (texture == null) { // Button is disabled but we have no texture for that + GlStateManager.color(0.5f, 0.5f, 0.5f, 1); + texture = textureNormal; + } + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + renderer.drawTexturedRect(0, 0, texture.getX(), texture.getY(), size.getWidth(), size.getHeight(), + textureSize.getWidth(), textureSize.getHeight(), + textureTotalSize.getWidth(), textureTotalSize.getHeight()); + } + + @Override + public ReadableDimension calcMinSize() { + return new Dimension(0, 0); + } + + @Override + public void onClick() { + getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); + super.onClick(); + } + + @Override + public T setTexture(ResourceLocation resourceLocation, int size) { + return setTexture(resourceLocation, size, size); + } + + @Override + public T setTexture(ResourceLocation resourceLocation, int width, int height) { + this.texture = resourceLocation; + this.textureTotalSize = new Dimension(width, height); + return getThis(); + } + + @Override + public T setTextureSize(int size) { + return setTextureSize(size, size); + } + + @Override + public T setTextureSize(int width, int height) { + this.textureSize = new Dimension(width, height); + return getThis(); + } + + @Override + public T setTexturePosH(final int x, final int y) { + return setTexturePosH(new Point(x, y)); + } + + @Override + public T setTexturePosV(final int x, final int y) { + return setTexturePosV(new Point(x, y)); + } + + @Override + public T setTexturePosH(final ReadablePoint pos) { + this.textureNormal = pos; + this.textureHover = new ReadablePoint() { + @Override + public int getX() { + return pos.getX() + textureSize.getWidth(); + } + + @Override + public int getY() { + return pos.getY(); + } + + @Override + public void getLocation(WritablePoint dest) { + dest.setLocation(getX(), getY()); + } + }; + return getThis(); + } + + @Override + public T setTexturePosV(final ReadablePoint pos) { + this.textureNormal = pos; + this.textureHover = new ReadablePoint() { + @Override + public int getX() { + return pos.getX(); + } + + @Override + public int getY() { + return pos.getY() + textureSize.getHeight(); + } + + @Override + public void getLocation(WritablePoint dest) { + dest.setLocation(getX(), getY()); + } + }; + return getThis(); + } + + @Override + public T setTexturePos(int normalX, int normalY, int hoverX, int hoverY) { + return setTexturePos(new Point(normalX, normalY), new Point(hoverX, hoverY)); + } + + @Override + public T setTexturePos(ReadablePoint normal, ReadablePoint hover) { + this.textureNormal = normal; + this.textureHover = hover; + return getThis(); + } + + @Override + public T setTexturePos(int normalX, int normalY, int hoverX, int hoverY, int disabledX, int disabledY) { + return setTexturePos(new Point(normalX, normalY), new Point(hoverX, hoverY), new Point(disabledX, disabledY)); + } + + @Override + public T setTexturePos(ReadablePoint normal, ReadablePoint hover, ReadablePoint disabled) { + this.textureDisabled = disabled; + return setTexturePos(normal, hover); + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiToggleButton.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiToggleButton.java index bcbcbbf8..64bed00e 100644 --- a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiToggleButton.java +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiToggleButton.java @@ -47,7 +47,7 @@ public abstract class AbstractGuiToggleButton { + public GuiSlider() { + } + + public GuiSlider(GuiContainer container) { + super(container); + } + + @Override + protected GuiSlider getThis() { + return this; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/GuiTexturedButton.java b/src/main/java/de/johni0702/minecraft/gui/element/GuiTexturedButton.java new file mode 100644 index 00000000..dfe9ca67 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/GuiTexturedButton.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element; + +import de.johni0702.minecraft.gui.container.GuiContainer; + +public class GuiTexturedButton extends AbstractGuiTexturedButton { + public GuiTexturedButton() { + } + + public GuiTexturedButton(GuiContainer container) { + super(container); + } + + @Override + protected GuiTexturedButton getThis() { + return this; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/IGuiSlider.java b/src/main/java/de/johni0702/minecraft/gui/element/IGuiSlider.java new file mode 100644 index 00000000..2a947c55 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/IGuiSlider.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element; + +public interface IGuiSlider> extends GuiElement { + T setText(String text); + T setI18nText(String text, Object... args); + + T setValue(int value); + int getValue(); + + int getSteps(); + T setSteps(int steps); + + T onValueChanged(Runnable runnable); +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/IGuiTexturedButton.java b/src/main/java/de/johni0702/minecraft/gui/element/IGuiTexturedButton.java new file mode 100644 index 00000000..88637530 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/IGuiTexturedButton.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element; + +import net.minecraft.util.ResourceLocation; +import org.lwjgl.util.ReadableDimension; +import org.lwjgl.util.ReadablePoint; + +public interface IGuiTexturedButton> extends IGuiClickable { + ResourceLocation getTexture(); + ReadableDimension getTextureTotalSize(); + T setTexture(ResourceLocation resourceLocation, int size); + T setTexture(ResourceLocation resourceLocation, int width, int height); + + ReadableDimension getTextureSize(); + T setTextureSize(int size); + T setTextureSize(int width, int height); + + ReadablePoint getTextureNormal(); + ReadablePoint getTextureHover(); + ReadablePoint getTextureDisabled(); + T setTexturePosH(int x, int y); + T setTexturePosV(int x, int y); + T setTexturePosH(ReadablePoint pos); + T setTexturePosV(ReadablePoint pos); + T setTexturePos(int normalX, int normalY, int hoverX, int hoverY); + T setTexturePos(ReadablePoint normal, ReadablePoint hover); + T setTexturePos(int normalX, int normalY, int hoverX, int hoverY, int disabledX, int disabledY); + T setTexturePos(ReadablePoint normal, ReadablePoint hover, ReadablePoint disabled); +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/advanced/AbstractGuiTimeline.java b/src/main/java/de/johni0702/minecraft/gui/element/advanced/AbstractGuiTimeline.java new file mode 100644 index 00000000..98d11e88 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/advanced/AbstractGuiTimeline.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element.advanced; + +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.container.GuiContainer; +import de.johni0702.minecraft.gui.element.AbstractGuiElement; +import de.johni0702.minecraft.gui.element.GuiTooltip; +import de.johni0702.minecraft.gui.function.Clickable; +import net.minecraft.util.MathHelper; +import org.lwjgl.util.Dimension; +import org.lwjgl.util.Point; +import org.lwjgl.util.ReadableDimension; +import org.lwjgl.util.ReadablePoint; + +public abstract class AbstractGuiTimeline> extends AbstractGuiElement implements IGuiTimeline, Clickable { + protected static final int TEXTURE_WIDTH = 64; + protected static final int TEXTURE_HEIGHT = 22; + + protected static final int TEXTURE_X = 0; + protected static final int TEXTURE_Y = 16; + + protected static final int BORDER_LEFT = 4; + protected static final int BORDER_RIGHT = 4; + protected static final int BORDER_TOP = 4; + protected static final int BORDER_BOTTOM = 3; + protected static final int BODY_WIDTH = TEXTURE_WIDTH - BORDER_LEFT - BORDER_RIGHT; + protected static final int BODY_HEIGHT = TEXTURE_HEIGHT - BORDER_TOP - BORDER_BOTTOM; + + private OnClick onClick; + + private int length; + private int cursorPosition; + private double zoom = 1; + private int offset; + + private ReadableDimension size; + + public AbstractGuiTimeline() { + } + + public AbstractGuiTimeline(GuiContainer container) { + super(container); + } + + { + setTooltip(new GuiTooltip(){ + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + int ms = getTimeAt(renderInfo.mouseX, renderInfo.mouseY); + int s = ms / 1000 % 60; + int m = ms / 1000 / 60; + setText(String.format("%02d:%02d", m, s)); + super.draw(renderer, size, renderInfo); + } + }.setText("00:00")); + } + + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + this.size = size; + + int width = size.getWidth(); + int height = size.getHeight(); + + // We have to increase the border size as there is one pixel row which is part of the border while drawing + // but isn't during position calculations due to shadows + int BORDER_LEFT = GuiTimeline.BORDER_LEFT + 1; + int BODY_WIDTH = GuiTimeline.BODY_WIDTH - 1; + + renderer.bindTexture(TEXTURE); + + // Left and right borders + for (int pass = 0; pass < 2; pass++) { + int x = pass == 0 ? 0 : width - BORDER_RIGHT; + int textureX = pass == 0 ? TEXTURE_X : TEXTURE_X + TEXTURE_WIDTH - BORDER_RIGHT; + // Border + for (int y = BORDER_TOP; y < height - BORDER_BOTTOM; y += BODY_HEIGHT) { + int segmentHeight = Math.min(BODY_HEIGHT, height - BORDER_BOTTOM - y); + renderer.drawTexturedRect(x, y, textureX, TEXTURE_Y + BORDER_TOP, BORDER_LEFT, segmentHeight); + } + // Top corner + renderer.drawTexturedRect(x, 0, textureX, TEXTURE_Y, BORDER_LEFT, BORDER_TOP); + // Bottom corner + renderer.drawTexturedRect(x, height - BORDER_BOTTOM, textureX, TEXTURE_Y + TEXTURE_HEIGHT - BORDER_BOTTOM, + BORDER_LEFT, BORDER_BOTTOM); + } + + for (int x = BORDER_LEFT; x < width - BORDER_RIGHT; x += BODY_WIDTH) { + int segmentWidth = Math.min(BODY_WIDTH, width - BORDER_RIGHT - x); + int textureX = TEXTURE_X + BORDER_LEFT; + + // Content + for (int y = BORDER_TOP; y < height - BORDER_BOTTOM; y += BODY_HEIGHT) { + int segmentHeight = Math.min(BODY_HEIGHT, height - BORDER_BOTTOM - y); + renderer.drawTexturedRect(x, y, textureX, TEXTURE_Y + BORDER_TOP, segmentWidth, segmentHeight); + } + + // Top border + renderer.drawTexturedRect(x, 0, textureX, TEXTURE_Y, segmentWidth, BORDER_TOP); + // Bottom border + renderer.drawTexturedRect(x, height - BORDER_BOTTOM, textureX, TEXTURE_Y + TEXTURE_HEIGHT - BORDER_BOTTOM, + segmentWidth, BORDER_BOTTOM); + } + + drawTimelineCursor(renderer, size); + } + + /** + * Draws the timeline cursor. + * This is separate from the main draw method so subclasses can repaint the cursor + * in case it got drawn over by other elements. + * @param renderer Gui renderer used to draw the cursor + * @param size Size of the drawable area + */ + protected void drawTimelineCursor(GuiRenderer renderer, ReadableDimension size) { + int height = size.getHeight(); + renderer.bindTexture(TEXTURE); + + int visibleLength = (int) (length * zoom); + int cursor = MathHelper.clamp_int(cursorPosition, offset, offset + visibleLength); + double positionInVisible = cursor - offset; + double fractionOfVisible = positionInVisible / visibleLength; + int cursorX = (int) (BORDER_LEFT + fractionOfVisible * (size.getWidth() - BORDER_LEFT - BORDER_RIGHT)); + + // Pin + renderer.drawTexturedRect(cursorX - 2, BORDER_TOP - 1, 64, 0, 5, 4); + // Needle + for (int y = BORDER_TOP - 1; y < height - BORDER_BOTTOM; y += 11) { + int segmentHeight = Math.min(11, height - BORDER_BOTTOM - y); + renderer.drawTexturedRect(cursorX - 2, y, 64, 4, 5, segmentHeight); + } + } + + /** + * Returns the time which the mouse is at. + * @param mouseX X coordinate of the mouse + * @param mouseY Y coordinate of the mouse + * @return The time or -1 if the mouse isn't on the timeline + */ + protected int getTimeAt(int mouseX, int mouseY) { + if (size == null) { + return -1; + } + Point mouse = new Point(mouseX, mouseY); + getContainer().convertFor(this, mouse); + mouseX = mouse.getX(); + mouseY = mouse.getY(); + + if (mouseX < 0 || mouseY < 0 + || mouseX > size.getWidth() || mouseY > size.getHeight()) { + return -1; + } + + int width = size.getWidth(); + int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; + double segmentLength = length * zoom; + double segmentTime = segmentLength * (mouseX - BORDER_LEFT) / bodyWidth; + return Math.min(Math.max((int) Math.round(offset + segmentTime), 0), length); + } + + public void onClick(int time) { + if (onClick != null) { + onClick.run(time); + } + } + + @Override + public ReadableDimension calcMinSize() { + return new Dimension(0, 0); + } + + @Override + public T setLength(int length) { + this.length = length; + return getThis(); + } + + @Override + public int getLength() { + return length; + } + + @Override + public T setCursorPosition(int position) { + this.cursorPosition = position; + return getThis(); + } + + @Override + public int getCursorPosition() { + return cursorPosition; + } + + @Override + public T setZoom(double zoom) { + this.zoom = zoom; + return getThis(); + } + + @Override + public double getZoom() { + return zoom; + } + + @Override + public T setOffset(int offset) { + this.offset = offset; + return getThis(); + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public T onClick(OnClick onClick) { + this.onClick = onClick; + return getThis(); + } + + @Override + public boolean mouseClick(ReadablePoint position, int button) { + int time = getTimeAt(position.getX(), position.getY()); + if (time != -1) { + onClick(time); + return true; + } + return false; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/advanced/GuiTimeline.java b/src/main/java/de/johni0702/minecraft/gui/element/advanced/GuiTimeline.java new file mode 100644 index 00000000..d21068f8 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/advanced/GuiTimeline.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element.advanced; + +import de.johni0702.minecraft.gui.container.GuiContainer; + +public class GuiTimeline extends AbstractGuiTimeline { + public GuiTimeline() { + } + + public GuiTimeline(GuiContainer container) { + super(container); + } + + @Override + protected GuiTimeline getThis() { + return this; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/advanced/IGuiTimeline.java b/src/main/java/de/johni0702/minecraft/gui/element/advanced/IGuiTimeline.java new file mode 100644 index 00000000..a82f9d28 --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/element/advanced/IGuiTimeline.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.element.advanced; + +import de.johni0702.minecraft.gui.element.GuiElement; + +public interface IGuiTimeline> extends GuiElement { + + /** + * Set the total length of the timeline. + * @param length length in milliseconds, must be > 0 + * @return {@code this}, for chaining + */ + T setLength(int length); + + /** + * Returns the total length of the timeline. + * @return The total length in millisconds + */ + int getLength(); + + /** + * Set the current position of the cursor. Should be between 0 and {@link #getLength()}. + * @param position Position of the cursor in milliseconds + * @return {@code this}, for chaining + */ + T setCursorPosition(int position); + + /** + * Returns the current position of the cursor. Should be between 0 and {@link #getLength()}. + * @return cursor position in milliseconds + */ + int getCursorPosition(); + + /** + * Set the zoom of this timeline. 1/10 allows the user to see 1/10 of the total length. + * @param zoom The zoom factor. Must be between 1 (inclusive) and 0 (exclusive) + * @return {@code this}, for chaining + */ + T setZoom(double zoom); + + /** + * Returns the zoom of this timeline. 1/10 allows the user to see 1/10 of the total length. + * @return The zoom factor. Must be between 1 (inclusive) and 0 (exclusive) + */ + double getZoom(); + + /** + * Set the position of the timeline which should be shown. + * The left side of the timeline will start at this offset. + * @param offset The offset in milliseconds + * @return {@code this}, for chaining + */ + T setOffset(int offset); + + /** + * Returns the position of the timeline which should be shown. + * The left side of the timeline will start at this offset. + * @return The offset in milliseconds + */ + int getOffset(); + + T onClick(OnClick onClick); + + interface OnClick { + void run(int time); + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/layout/CustomLayout.java b/src/main/java/de/johni0702/minecraft/gui/layout/CustomLayout.java index 624b96be..020ada36 100644 --- a/src/main/java/de/johni0702/minecraft/gui/layout/CustomLayout.java +++ b/src/main/java/de/johni0702/minecraft/gui/layout/CustomLayout.java @@ -35,15 +35,32 @@ import java.util.Collection; import java.util.Map; public abstract class CustomLayout> implements Layout { + private final Layout parent; private Map> result = Maps.newHashMap(); + public CustomLayout() { + this(null); + } + + public CustomLayout(Layout parent) { + this.parent = parent; + } + @Override @SuppressWarnings("unchecked") public Map> layOut(GuiContainer container, ReadableDimension size) { result.clear(); - Collection elements = container.getChildren(); - for (GuiElement element : elements) { - result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize()))); + if (parent == null) { + Collection elements = container.getChildren(); + for (GuiElement element : elements) { + result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize()))); + } + } else { + Map> elements = parent.layOut(container, size); + for (Map.Entry> entry : elements.entrySet()) { + Pair pair = entry.getValue(); + result.put(entry.getKey(), Pair.of(new Point(pair.getLeft()), new Dimension(pair.getRight()))); + } } layout((T) container, size.getWidth(), size.getHeight()); diff --git a/src/main/java/de/johni0702/minecraft/gui/layout/GridLayout.java b/src/main/java/de/johni0702/minecraft/gui/layout/GridLayout.java index ca523885..1f077dc1 100644 --- a/src/main/java/de/johni0702/minecraft/gui/layout/GridLayout.java +++ b/src/main/java/de/johni0702/minecraft/gui/layout/GridLayout.java @@ -27,7 +27,6 @@ import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.element.GuiElement; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; import org.apache.commons.lang3.tuple.Pair; @@ -40,11 +39,13 @@ import java.util.Collections; import java.util.Iterator; import java.util.Map; -@RequiredArgsConstructor public class GridLayout implements Layout { private static final Data DEFAULT_DATA = new Data(); - private final int columns; + @Accessors(chain = true) + @Getter + @Setter + private int columns; @Accessors(chain = true) @Getter diff --git a/src/main/java/de/johni0702/minecraft/gui/layout/HorizontalLayout.java b/src/main/java/de/johni0702/minecraft/gui/layout/HorizontalLayout.java index 53cf4987..1f2a80d0 100644 --- a/src/main/java/de/johni0702/minecraft/gui/layout/HorizontalLayout.java +++ b/src/main/java/de/johni0702/minecraft/gui/layout/HorizontalLayout.java @@ -67,7 +67,9 @@ public class HorizontalLayout implements Layout { GuiElement element = entry.getKey(); Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA; Dimension elementSize = new Dimension(element.getMinSize()); - elementSize.setHeight(Math.min(size.getHeight(), element.getMaxSize().getHeight())); + ReadableDimension elementMaxSize = element.getMaxSize(); + elementSize.setWidth(Math.min(size.getWidth() - x, Math.min(elementSize.getWidth(), elementMaxSize.getWidth()))); + elementSize.setHeight(Math.min(size.getHeight(), elementMaxSize.getHeight())); int remainingHeight = size.getHeight() - elementSize.getHeight(); int y = (int) (data.alignment * remainingHeight); map.put(element, Pair.of(new Point(x, y), elementSize)); diff --git a/src/main/java/de/johni0702/minecraft/gui/layout/VerticalLayout.java b/src/main/java/de/johni0702/minecraft/gui/layout/VerticalLayout.java index 48554d52..5a333201 100644 --- a/src/main/java/de/johni0702/minecraft/gui/layout/VerticalLayout.java +++ b/src/main/java/de/johni0702/minecraft/gui/layout/VerticalLayout.java @@ -67,6 +67,8 @@ public class VerticalLayout implements Layout { GuiElement element = entry.getKey(); Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA; Dimension elementSize = new Dimension(element.getMinSize()); + ReadableDimension elementMaxSize = element.getMaxSize(); + elementSize.setHeight(Math.min(size.getHeight() - y, Math.min(elementSize.getHeight(), elementMaxSize.getHeight()))); elementSize.setWidth(Math.min(size.getWidth(), element.getMaxSize().getWidth())); int remainingWidth = size.getWidth() - elementSize.getWidth(); int x = (int) (data.alignment * remainingWidth); diff --git a/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java index 91b12774..3418da84 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/ApiClient.java @@ -5,7 +5,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.mojang.authlib.exceptions.AuthenticationException; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.ReplayModApiMethods; import eu.crushedpixel.replaymod.api.replay.SearchQuery; import eu.crushedpixel.replaymod.api.replay.holders.*; diff --git a/src/main/java/eu/crushedpixel/replaymod/api/GsonApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/GsonApiClient.java index 2e0de1f9..07ae5200 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/GsonApiClient.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/GsonApiClient.java @@ -1,26 +1,26 @@ -package eu.crushedpixel.replaymod.api; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import org.apache.commons.lang3.StringEscapeUtils; - -import java.io.IOException; - -public class GsonApiClient { - - private static final JsonParser parser = new JsonParser(); - - public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException { - String apiResult = SimpleApiClient.invoke(query); - return wrapWithJson(apiResult); - } - - public static JsonElement invokeJson(String url) throws IOException, ApiException { - String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace(""", "\\\"")); - return wrapWithJson(apiResult); - } - - private static JsonElement wrapWithJson(String apiResult) { - return parser.parse(apiResult); - } -} +package eu.crushedpixel.replaymod.api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import org.apache.commons.lang3.StringEscapeUtils; + +import java.io.IOException; + +public class GsonApiClient { + + private static final JsonParser parser = new JsonParser(); + + public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException { + String apiResult = SimpleApiClient.invoke(query); + return wrapWithJson(apiResult); + } + + public static JsonElement invokeJson(String url) throws IOException, ApiException { + String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace(""", "\\\"")); + return wrapWithJson(apiResult); + } + + private static JsonElement wrapWithJson(String apiResult) { + return parser.parse(apiResult); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/SimpleApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/SimpleApiClient.java index a3f23c43..3e79dadc 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/SimpleApiClient.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/SimpleApiClient.java @@ -1,123 +1,123 @@ -package eu.crushedpixel.replaymod.api; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import eu.crushedpixel.replaymod.api.replay.holders.ApiError; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Map; - -public class SimpleApiClient { - - private static final JsonParser jsonParser = new JsonParser(); - private static final Gson gson = new Gson(); - - /** - * Returns a Json String from the given QueryBuilder - * - * @param query The QueryBuilder to use - * @return A Json String from the API - * @throws IOException - * @throws ApiException - */ - public static String invoke(QueryBuilder query) throws IOException, ApiException { - return invokeImpl(query.toString()); - } - - /** - * Returns a Json String from the given URL - * - * @param url The URL to parse the Json from - * @return A Json String from the API - * @throws IOException - * @throws ApiException - */ - public static String invokeUrl(String url) throws IOException, ApiException { - return invokeImpl(url); - } - - /** - * Returns a Json String from the API - * - * @param method The apiMethod to be called - * @param paramMap The parameters to apply - * @return A Json String from the API - * @throws IOException - * @throws ApiException - */ - public static String invoke(String method, Map paramMap) throws IOException, ApiException { - return invokeImpl(method, paramMap); - } - - /** - * Returns a Json String from the API - * - * @param method The apiMethod to be called - * @return A Json String from the API - * @throws IOException - * @throws ApiException - */ - public static String invoke(String method) throws IOException, ApiException { - return invokeImpl(method, null); - } - - private static String invokeImpl(String urlString) throws IOException, ApiException { - - // read response - String responseContent = null; - InputStream is = null; - HttpURLConnection httpUrlConnection = null; - try { - URL url = new URL(urlString); - httpUrlConnection = (HttpURLConnection) url.openConnection(); - - httpUrlConnection.setRequestMethod("GET"); - - // give it 15 seconds to respond - httpUrlConnection.setReadTimeout(15 * 1000); - httpUrlConnection.connect(); - - int responseCode = httpUrlConnection.getResponseCode(); - - if(responseCode != 200) { - is = httpUrlConnection.getErrorStream(); - if(is != null) { - responseContent = IOUtils.toString(is, "UTF-8"); - } else { - responseContent = ""; - } - try { - JsonObject response = jsonParser.parse(responseContent).getAsJsonObject(); - throw new ApiException(gson.fromJson(response, ApiError.class)); - } catch(JsonParseException e) { - throw new ApiException(responseContent); - } - } - - is = httpUrlConnection.getInputStream(); - - responseContent = IOUtils.toString(is, "UTF-8"); - - } finally { - if(is != null) { - is.close(); - } - if(httpUrlConnection != null) { - httpUrlConnection.disconnect(); - } - } - return responseContent; - } - - private static String invokeImpl(String method, Map paramMap) throws IOException, ApiException { - QueryBuilder queryBuilder = new QueryBuilder(method); - queryBuilder.put(paramMap); - return invokeImpl(queryBuilder.toString()); - } -} +package eu.crushedpixel.replaymod.api; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import eu.crushedpixel.replaymod.api.replay.holders.ApiError; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; + +public class SimpleApiClient { + + private static final JsonParser jsonParser = new JsonParser(); + private static final Gson gson = new Gson(); + + /** + * Returns a Json String from the given QueryBuilder + * + * @param query The QueryBuilder to use + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(QueryBuilder query) throws IOException, ApiException { + return invokeImpl(query.toString()); + } + + /** + * Returns a Json String from the given URL + * + * @param url The URL to parse the Json from + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invokeUrl(String url) throws IOException, ApiException { + return invokeImpl(url); + } + + /** + * Returns a Json String from the API + * + * @param method The apiMethod to be called + * @param paramMap The parameters to apply + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(String method, Map paramMap) throws IOException, ApiException { + return invokeImpl(method, paramMap); + } + + /** + * Returns a Json String from the API + * + * @param method The apiMethod to be called + * @return A Json String from the API + * @throws IOException + * @throws ApiException + */ + public static String invoke(String method) throws IOException, ApiException { + return invokeImpl(method, null); + } + + private static String invokeImpl(String urlString) throws IOException, ApiException { + + // read response + String responseContent = null; + InputStream is = null; + HttpURLConnection httpUrlConnection = null; + try { + URL url = new URL(urlString); + httpUrlConnection = (HttpURLConnection) url.openConnection(); + + httpUrlConnection.setRequestMethod("GET"); + + // give it 15 seconds to respond + httpUrlConnection.setReadTimeout(15 * 1000); + httpUrlConnection.connect(); + + int responseCode = httpUrlConnection.getResponseCode(); + + if(responseCode != 200) { + is = httpUrlConnection.getErrorStream(); + if(is != null) { + responseContent = IOUtils.toString(is, "UTF-8"); + } else { + responseContent = ""; + } + try { + JsonObject response = jsonParser.parse(responseContent).getAsJsonObject(); + throw new ApiException(gson.fromJson(response, ApiError.class)); + } catch(JsonParseException e) { + throw new ApiException(responseContent); + } + } + + is = httpUrlConnection.getInputStream(); + + responseContent = IOUtils.toString(is, "UTF-8"); + + } finally { + if(is != null) { + is.close(); + } + if(httpUrlConnection != null) { + httpUrlConnection.disconnect(); + } + } + return responseContent; + } + + private static String invokeImpl(String method, Map paramMap) throws IOException, ApiException { + QueryBuilder queryBuilder = new QueryBuilder(method); + queryBuilder.put(paramMap); + return invokeImpl(queryBuilder.toString()); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/FileUploader.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/FileUploader.java index 93d2df3f..0dcb2e89 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/FileUploader.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/FileUploader.java @@ -1,7 +1,7 @@ package eu.crushedpixel.replaymod.api.replay; import com.google.gson.Gson; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.holders.ApiError; import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/ReplayModApiMethods.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/ReplayModApiMethods.java index 4e47f049..26afd9c0 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/ReplayModApiMethods.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/ReplayModApiMethods.java @@ -1,24 +1,24 @@ -package eu.crushedpixel.replaymod.api.replay; - -public class ReplayModApiMethods { - - public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/"; - - public static final String register = REPLAYMOD_BASE_URL+"register"; - public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey"; - public static final String login = REPLAYMOD_BASE_URL+"login"; - public static final String logout = REPLAYMOD_BASE_URL+"logout"; - public static final String file_details = REPLAYMOD_BASE_URL+"file_details"; - public static final String upload_file = REPLAYMOD_BASE_URL+"upload_file"; - public static final String download_file = REPLAYMOD_BASE_URL+"download_file"; - public static final String get_thumbnail = REPLAYMOD_BASE_URL+"get_thumbnail"; - public static final String remove_file = REPLAYMOD_BASE_URL+"remove_file"; - public static final String rate_file = REPLAYMOD_BASE_URL+"rate_file"; - public static final String get_ratings = REPLAYMOD_BASE_URL+"get_ratings"; - public static final String fav_file = REPLAYMOD_BASE_URL+"fav_file"; - public static final String get_favorites = REPLAYMOD_BASE_URL+"get_favorites"; - public static final String check_auth = REPLAYMOD_BASE_URL+"check_auth"; - public static final String get_language = REPLAYMOD_BASE_URL+"get_language"; - public static final String search = REPLAYMOD_BASE_URL+"search"; - public static final String up_to_date = REPLAYMOD_BASE_URL+"up_to_date"; -} +package eu.crushedpixel.replaymod.api.replay; + +public class ReplayModApiMethods { + + public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/"; + + public static final String register = REPLAYMOD_BASE_URL+"register"; + public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey"; + public static final String login = REPLAYMOD_BASE_URL+"login"; + public static final String logout = REPLAYMOD_BASE_URL+"logout"; + public static final String file_details = REPLAYMOD_BASE_URL+"file_details"; + public static final String upload_file = REPLAYMOD_BASE_URL+"upload_file"; + public static final String download_file = REPLAYMOD_BASE_URL+"download_file"; + public static final String get_thumbnail = REPLAYMOD_BASE_URL+"get_thumbnail"; + public static final String remove_file = REPLAYMOD_BASE_URL+"remove_file"; + public static final String rate_file = REPLAYMOD_BASE_URL+"rate_file"; + public static final String get_ratings = REPLAYMOD_BASE_URL+"get_ratings"; + public static final String fav_file = REPLAYMOD_BASE_URL+"fav_file"; + public static final String get_favorites = REPLAYMOD_BASE_URL+"get_favorites"; + public static final String check_auth = REPLAYMOD_BASE_URL+"check_auth"; + public static final String get_language = REPLAYMOD_BASE_URL+"get_language"; + public static final String search = REPLAYMOD_BASE_URL+"search"; + public static final String up_to_date = REPLAYMOD_BASE_URL+"up_to_date"; +} diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/FileInfo.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/FileInfo.java index 87b65807..d3c5d41a 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/FileInfo.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/holders/FileInfo.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.api.replay.holders; -import eu.crushedpixel.replaymod.recording.ReplayMetaData; +import de.johni0702.replaystudio.replay.ReplayMetaData; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/DownloadedFilePagination.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/DownloadedFilePagination.java index ff43a607..857d23d3 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/DownloadedFilePagination.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/DownloadedFilePagination.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.api.replay.pagination; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import java.io.File; diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/FavoritedFilePagination.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/FavoritedFilePagination.java index 36a86e1e..63224821 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/FavoritedFilePagination.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/FavoritedFilePagination.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.api.replay.pagination; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import java.util.ArrayList; diff --git a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/SearchPagination.java b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/SearchPagination.java index 90b682c8..64ea66b0 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/SearchPagination.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/replay/pagination/SearchPagination.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.api.replay.pagination; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.SearchQuery; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; diff --git a/src/main/java/eu/crushedpixel/replaymod/assets/AssetRepository.java b/src/main/java/eu/crushedpixel/replaymod/assets/AssetRepository.java index da9898cc..d96a7cee 100644 --- a/src/main/java/eu/crushedpixel/replaymod/assets/AssetRepository.java +++ b/src/main/java/eu/crushedpixel/replaymod/assets/AssetRepository.java @@ -1,18 +1,12 @@ package eu.crushedpixel.replaymod.assets; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.utils.ReplayFile; import lombok.EqualsAndHashCode; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ArrayUtils; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; -import java.util.zip.ZipEntry; @EqualsAndHashCode public class AssetRepository { @@ -62,40 +56,29 @@ public class AssetRepository { } public void saveAssets() { - try { - ReplayFile replayFile = new ReplayFile(ReplayHandler.getReplayFile()); - - Enumeration entries = replayFile.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(entry.getName().startsWith(ReplayFile.ENTRY_ASSET_FOLDER)) { - ReplayMod.replayFileAppender.registerModifiedFile(null, entry.getName(), ReplayHandler.getReplayFile()); - } - } - - replayFile.close(); - - ReplayMod.replayFileAppender.deleteAllFilesByFolder(ReplayFile.ENTRY_ASSET_FOLDER, ReplayHandler.getReplayFile()); - - for(Map.Entry e : replayAssets.entrySet()) { - UUID uuid = e.getKey(); - ReplayAsset asset = e.getValue(); - try { - String filepath = ReplayFile.ENTRY_ASSET_FOLDER + uuid.toString()+ "_" + asset.getDisplayString() + "." + asset.getSavedFileExtension(); - - File toAdd = File.createTempFile("ASSET_"+asset.getDisplayString(), asset.getSavedFileExtension()); - FileOutputStream fos = new FileOutputStream(toAdd); - asset.writeToStream(fos); - - - ReplayMod.replayFileAppender.registerModifiedFile(toAdd, filepath, ReplayHandler.getReplayFile()); - } catch(IOException io) { - io.printStackTrace(); - } - } - } catch(IOException e) { - e.printStackTrace(); - } + // TODO +// try { +// ReplayFile replayFile = ReplayHandler.getReplayFile(); +// +// for (ReplayAssetEntry entry : replayFile.getAssets()) { +// if (!replayAssets.containsKey(entry.getUuid())) { +// replayFile.removeAsset(entry.getUuid()); +// } +// } +// +// for(Map.Entry e : replayAssets.entrySet()) { +// UUID uuid = e.getKey(); +// ReplayAsset asset = e.getValue(); +// String extension = asset.getSavedFileExtension(); +// String name = asset.getAssetName(); +// +// try (OutputStream out = replayFile.writeAsset(new ReplayAssetEntry(uuid, extension, name))) { +// asset.writeToStream(out); +// } +// } +// } catch(IOException e) { +// e.printStackTrace(); +// } } public static ReplayAsset assetFromFileName(String filename) { diff --git a/src/main/java/eu/crushedpixel/replaymod/assets/CustomImageObject.java b/src/main/java/eu/crushedpixel/replaymod/assets/CustomImageObject.java index 2307eed6..5f3b17b0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/assets/CustomImageObject.java +++ b/src/main/java/eu/crushedpixel/replaymod/assets/CustomImageObject.java @@ -3,7 +3,6 @@ package eu.crushedpixel.replaymod.assets; import eu.crushedpixel.replaymod.holders.GuiEntryListEntry; import eu.crushedpixel.replaymod.holders.Transformations; import eu.crushedpixel.replaymod.registry.ResourceHelper; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -55,19 +54,20 @@ public class CustomImageObject implements GuiEntryListEntry { //if no asset repository available, simply accept the UUID and it will load the image later //when calling getResourceLocation for the first time - if(ReplayHandler.getAssetRepository() == null) { - this.linkedAsset = assetUUID; - return; - } - - ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID); - - if(asset instanceof ReplayImageAsset) { - this.linkedAsset = assetUUID; - setImage(((ReplayImageAsset)asset).getObject()); - } else if(asset != null) { - throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset"); - } + // TODO +// if(ReplayHandler.getAssetRepository() == null) { +// this.linkedAsset = assetUUID; +// return; +// } +// +// ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID); +// +// if(asset instanceof ReplayImageAsset) { +// this.linkedAsset = assetUUID; +// setImage(((ReplayImageAsset)asset).getObject()); +// } else if(asset != null) { +// throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset"); +// } } public void setImage(final BufferedImage bufferedImage) throws IOException { @@ -103,14 +103,15 @@ public class CustomImageObject implements GuiEntryListEntry { public ResourceLocation getResourceLocation() { if(resourceLocation == null) { - ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset); - if(asset instanceof ReplayImageAsset) { - try { - setImage(((ReplayImageAsset) asset).getObject()); - } catch(Exception e) { - e.printStackTrace(); - } - } + // TODO +// ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset); +// if(asset instanceof ReplayImageAsset) { +// try { +// setImage(((ReplayImageAsset) asset).getObject()); +// } catch(Exception e) { +// e.printStackTrace(); +// } +// } return null; } diff --git a/src/main/java/eu/crushedpixel/replaymod/assets/ReplayImageAsset.java b/src/main/java/eu/crushedpixel/replaymod/assets/ReplayImageAsset.java index 70d719d8..3ddd568c 100644 --- a/src/main/java/eu/crushedpixel/replaymod/assets/ReplayImageAsset.java +++ b/src/main/java/eu/crushedpixel/replaymod/assets/ReplayImageAsset.java @@ -1,7 +1,6 @@ package eu.crushedpixel.replaymod.assets; import eu.crushedpixel.replaymod.registry.ResourceHelper; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.BoundingUtils; import eu.crushedpixel.replaymod.utils.BufferedImageUtils; import lombok.EqualsAndHashCode; @@ -67,11 +66,12 @@ public class ReplayImageAsset implements ReplayAsset { this.bufferedImageHashCode = BufferedImageUtils.hashCode(object); ResourceHelper.freeResource(previewResource); - for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) { - if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) { - object.setImage(this.object); - } - } + // TODO +// for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) { +// if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) { +// object.setImage(this.object); +// } +// } } @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/chat/ChatMessageHandler.java b/src/main/java/eu/crushedpixel/replaymod/chat/ChatMessageHandler.java index 78508337..24fe1b12 100755 --- a/src/main/java/eu/crushedpixel/replaymod/chat/ChatMessageHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/chat/ChatMessageHandler.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.chat; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java index 04314bac..02536d38 100755 --- a/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java +++ b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java @@ -17,6 +17,7 @@ public class LoadingPlugin implements IFMLLoadingPlugin { public LoadingPlugin() { MixinBootstrap.init(); MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replaymod.json"); + MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.recording.replaymod.json"); CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); if (codeSource != null) { diff --git a/src/main/java/eu/crushedpixel/replaymod/events/ReplayExitEvent.java b/src/main/java/eu/crushedpixel/replaymod/events/ReplayExitEvent.java deleted file mode 100644 index 948c3ff2..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/events/ReplayExitEvent.java +++ /dev/null @@ -1,6 +0,0 @@ -package eu.crushedpixel.replaymod.events; - -import net.minecraftforge.fml.common.eventhandler.Event; - -public class ReplayExitEvent extends Event { -} diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/CrosshairRenderHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/CrosshairRenderHandler.java index 1a052043..597e3241 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/CrosshairRenderHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/CrosshairRenderHandler.java @@ -1,8 +1,6 @@ package eu.crushedpixel.replaymod.events.handlers; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -13,18 +11,20 @@ public class CrosshairRenderHandler { @SubscribeEvent public void preCrosshairRender(RenderGameOverlayEvent.Pre event) { //Crosshair should only render if hovered Entity can actually be spectated - if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) { - boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity); - event.setCanceled(cancel); - } + // TODO +// if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) { +// boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity); +// event.setCanceled(cancel); +// } } @SubscribeEvent public void preChatRender(RenderGameOverlayEvent.Pre event) { - if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CHAT) { - //when a crosshair was displayed, the background of the lowest line of chat would be opaque - GlStateManager.enableTexture2D(); - GlStateManager.disableBlend(); - } + // TODO +// if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CHAT) { +// //when a crosshair was displayed, the background of the lowest line of chat would be opaque +// GlStateManager.enableTexture2D(); +// GlStateManager.disableBlend(); +// } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java index 44f0291a..4315f473 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java @@ -1,14 +1,11 @@ package eu.crushedpixel.replaymod.events.handlers; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; +import com.replaymod.core.gui.GuiReplaySettings; import eu.crushedpixel.replaymod.gui.GuiConstants; -import eu.crushedpixel.replaymod.gui.GuiReplaySettings; import eu.crushedpixel.replaymod.gui.online.GuiLoginPrompt; import eu.crushedpixel.replaymod.gui.online.GuiReplayCenter; import eu.crushedpixel.replaymod.gui.replayeditor.GuiReplayEditor; -import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplayProcess; import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.studio.VersionValidator; import eu.crushedpixel.replaymod.utils.MouseUtils; @@ -26,7 +23,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.util.Point; import java.awt.*; -import java.util.ArrayList; import java.util.List; public class GuiEventHandler { @@ -54,19 +50,20 @@ public class GuiEventHandler { e.printStackTrace(); } } - if(ReplayHandler.isInReplay()) ReplayHandler.setInReplay(false); } if(!ReplayMod.apiClient.isLoggedIn()) return; if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) { - if(ReplayHandler.isInReplay()) { - event.setCanceled(true); - } + // TODO +// if(ReplayHandler.isInReplay()) { +// event.setCanceled(true); +// } } else if(event.gui instanceof GuiDisconnected) { - if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) { - event.setCanceled(true); - } + // TODO +// if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) { +// event.setCanceled(true); +// } } } @@ -121,20 +118,7 @@ public class GuiEventHandler { public void onInit(InitGuiEvent event) { @SuppressWarnings("unchecked") List buttonList = event.buttonList; - if(event.gui instanceof GuiIngameMenu && ReplayHandler.isInReplay()) { - ReplayMod.replaySender.setReplaySpeed(0); - for(GuiButton b : new ArrayList(buttonList)) { - if(b.id == 1) { - b.displayString = I18n.format("replaymod.gui.exit"); - b.yPosition -= 24 * 2; - b.id = GuiConstants.EXIT_REPLAY_BUTTON; - } else if(b.id >= 5 && b.id <= 7) { - buttonList.remove(b); - } else if(b.id != 4) { - b.yPosition -= 24 * 2; - } - } - } else if(event.gui instanceof GuiMainMenu) { + if(event.gui instanceof GuiMainMenu) { int i1 = event.gui.height / 4 + 24 + 10; for(GuiButton b : buttonList) { @@ -171,9 +155,7 @@ public class GuiEventHandler { public void onButton(ActionPerformedEvent event) { if(!event.button.enabled) return; if(event.gui instanceof GuiMainMenu) { - if(event.button.id == GuiConstants.REPLAY_MANAGER_BUTTON_ID) { - mc.displayGuiScreen(new GuiReplayViewer()); - } else if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) { + if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) { if(ReplayMod.apiClient.isLoggedIn()) { mc.displayGuiScreen(new GuiReplayCenter()); } else { @@ -183,17 +165,7 @@ public class GuiEventHandler { mc.displayGuiScreen(new GuiReplayEditor()); } } else if(event.gui instanceof GuiOptions && event.button.id == GuiConstants.REPLAY_OPTIONS_BUTTON_ID) { - mc.displayGuiScreen(new GuiReplaySettings(event.gui)); - } - - if(ReplayHandler.isInReplay() && event.gui instanceof GuiIngameMenu && event.button.id == GuiConstants.EXIT_REPLAY_BUTTON) { - if(ReplayHandler.isInPath()) ReplayProcess.stopReplayProcess(false); - - event.button.enabled = false; - - mc.displayGuiScreen(new GuiMainMenu()); - - ReplayHandler.endReplay(); + new GuiReplaySettings(event.gui, ReplayMod.instance.getSettingsRegistry()).display(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java index 469ccd19..3ceb9e81 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java @@ -1,20 +1,19 @@ package eu.crushedpixel.replaymod.events.handlers; -import eu.crushedpixel.replaymod.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.KeyBinding; import net.minecraft.crash.CrashReport; import net.minecraft.util.ReportedException; -import net.minecraftforge.client.event.MouseEvent; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; public class MinecraftTicker { public static void runMouseKeyboardTick(Minecraft mc) { - ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent()); + // TODO +// ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent()); if(mc.thePlayer == null) return; try { mc.mcProfiler.endStartSection("mouse"); diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java index 79d63f2f..bd9cbcc9 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MouseInputHandler.java @@ -1,51 +1,45 @@ package eu.crushedpixel.replaymod.events.handlers; -import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import net.minecraft.client.Minecraft; -import net.minecraftforge.client.event.MouseEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Mouse; - public class MouseInputHandler { - private final Minecraft mc = Minecraft.getMinecraft(); - private boolean rightDown = false; - private boolean leftDown = false; - - @SubscribeEvent - public void mouseEvent(MouseEvent event) { - if(!ReplayHandler.isInReplay()) { - return; - } - - if(event.dwheel != 0 && mc.currentScreen == null) { - boolean increase = event.dwheel > 0; - CameraEntity.modifyCameraSpeed(increase); - } - - if(Mouse.isButtonDown(0)) { - if(!leftDown) { - leftDown = true; - if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) { - if(SpectatingHandler.canSpectate(mc.pointedEntity)) - ReplayHandler.spectateEntity(mc.pointedEntity); - } - } - } else { - leftDown = false; - } - - if(Mouse.isButtonDown(1)) { - if(!rightDown) { - rightDown = true; - if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) { - if(SpectatingHandler.canSpectate(mc.pointedEntity)) - ReplayHandler.spectateEntity(mc.pointedEntity); - } - } - } else { - rightDown = false; - } - } + // TODO +// private final Minecraft mc = Minecraft.getMinecraft(); +// private boolean rightDown = false; +// private boolean leftDown = false; +// +// @SubscribeEvent +// public void mouseEvent(MouseEvent event) { +// if(!ReplayHandler.isInReplay()) { +// return; +// } +// +// if(event.dwheel != 0 && mc.currentScreen == null) { +// boolean increase = event.dwheel > 0; +// CameraEntity.modifyCameraSpeed(increase); +// } +// +// if(Mouse.isButtonDown(0)) { +// if(!leftDown) { +// leftDown = true; +// if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) { +// if(SpectatingHandler.canSpectate(mc.pointedEntity)) +// ReplayHandler.spectateEntity(mc.pointedEntity); +// } +// } +// } else { +// leftDown = false; +// } +// +// if(Mouse.isButtonDown(1)) { +// if(!rightDown) { +// rightDown = true; +// if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) { +// if(SpectatingHandler.canSpectate(mc.pointedEntity)) +// ReplayHandler.spectateEntity(mc.pointedEntity); +// } +// } +// } else { +// rightDown = false; +// } +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java index 0257442c..5c879d36 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/TickAndRenderListener.java @@ -1,18 +1,10 @@ package eu.crushedpixel.replaymod.events.handlers; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.chat.ChatMessageHandler; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplayProcess; -import eu.crushedpixel.replaymod.video.ReplayScreenshot; import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.MouseEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.Display; public class TickAndRenderListener { @@ -30,75 +22,78 @@ public class TickAndRenderListener { @SubscribeEvent public void onRenderWorld(RenderWorldLastEvent event) throws Exception { - if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel - if (ReplayProcess.isVideoRecording()) return; // If recording, cancel - - if(requestScreenshot == 1) { - mc.addScheduledTask(new Runnable() { - @Override - public void run() { - ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION); - ReplayScreenshot.prepareScreenshot(); - requestScreenshot = 2; - } - }); - } else if(requestScreenshot == 2) { - mc.addScheduledTask(new Runnable() { - @Override - public void run() { - ReplayScreenshot.saveScreenshot(); - } - }); - } - - if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false); - if(ReplayHandler.isCamera()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity()); - - if(mc.isGamePaused() && ReplayHandler.isInPath()) { - mc.isGamePaused = false; - } + // TODO +// if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel +// if (ReplayProcess.isVideoRecording()) return; // If recording, cancel +// +// if(requestScreenshot == 1) { +// mc.addScheduledTask(new Runnable() { +// @Override +// public void run() { +// ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION); +// ReplayScreenshot.prepareScreenshot(); +// requestScreenshot = 2; +// } +// }); +// } else if(requestScreenshot == 2) { +// mc.addScheduledTask(new Runnable() { +// @Override +// public void run() { +// ReplayScreenshot.saveScreenshot(); +// } +// }); +// } +// +// if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false); +// if(ReplayHandler.isCameraView()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity()); +// +// if(mc.isGamePaused() && ReplayHandler.isInPath()) { +// mc.isGamePaused = false; +// } } @SubscribeEvent public void onRenderTick(TickEvent.RenderTickEvent event) { - if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return; - - if(ReplayHandler.getCameraEntity() != null) - ReplayHandler.getCameraEntity().updateMovement(); - if(ReplayHandler.isInPath()) { - ReplayProcess.tickReplay(true); - } else onMouseMove(new MouseEvent()); - - FMLCommonHandler.instance().fireKeyInput(); + // TODO +// if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return; +// +// if(ReplayHandler.getCameraEntity() != null) +// ReplayHandler.getCameraEntity().updateMovement(); +// if(ReplayHandler.isInPath()) { +// ReplayProcess.tickReplay(true); +// } else onMouseMove(new MouseEvent()); +// +// FMLCommonHandler.instance().fireKeyInput(); } @SubscribeEvent public void onMouseMove(MouseEvent event) { - if(!ReplayHandler.isInReplay()) return; - - mc.mcProfiler.startSection("mouse"); - - if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) { - Mouse.setGrabbed(false); - Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2); - Mouse.setGrabbed(true); - } - - if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) { - mc.mouseHelper.mouseXYChange(); - float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F; - float f2 = f1 * f1 * f1 * 8.0F; - float f3 = (float) mc.mouseHelper.deltaX * f2; - float f4 = (float) mc.mouseHelper.deltaY * f2; - byte b0 = 1; - - if(mc.gameSettings.invertMouse) { - b0 = -1; - } - - if(ReplayHandler.getCameraEntity() != null) { - ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0); - } - } + // TODO +// if(!ReplayHandler.isInReplay()) return; +// +// mc.mcProfiler.startSection("mouse"); +// +// if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) { +// Mouse.setGrabbed(false); +// Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2); +// Mouse.setGrabbed(true); +// } +// +// if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) { +// mc.mouseHelper.mouseXYChange(); +// float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F; +// float f2 = f1 * f1 * f1 * 8.0F; +// float f3 = (float) mc.mouseHelper.deltaX * f2; +// float f4 = (float) mc.mouseHelper.deltaY * f2; +// byte b0 = 1; +// +// if(mc.gameSettings.invertMouse) { +// b0 = -1; +// } +// +// if(ReplayHandler.getCameraEntity() != null) { +// ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0); +// } +// } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/keyboard/KeyInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/keyboard/KeyInputHandler.java index c0635528..e46e69d8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/keyboard/KeyInputHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/keyboard/KeyInputHandler.java @@ -1,22 +1,8 @@ package eu.crushedpixel.replaymod.events.handlers.keyboard; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection; -import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener; -import eu.crushedpixel.replaymod.gui.GuiAssetManager; -import eu.crushedpixel.replaymod.gui.GuiKeyframeRepository; -import eu.crushedpixel.replaymod.gui.GuiMouseInput; -import eu.crushedpixel.replaymod.gui.GuiObjectManager; -import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; -import eu.crushedpixel.replaymod.registry.KeybindRegistry; -import eu.crushedpixel.replaymod.registry.PlayerHandler; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.KeyBinding; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.InputEvent; import org.lwjgl.Sys; -import org.lwjgl.input.Keyboard; public class KeyInputHandler { @@ -25,200 +11,200 @@ public class KeyInputHandler { private long prevKeysDown = Sys.getTime(); public void onKeyInput() throws Exception { - if(!ReplayHandler.isInReplay()) return; - - KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; - - boolean speedup = false; - - if(mc.currentScreen == null) { - boolean forward = false, backward = false, left = false, right = false, up = false, down = false; - - if(!ReplayHandler.isInPath()) { - for(KeyBinding kb : keyBindings) { - if(!kb.isKeyDown()) continue; - if(ReplayHandler.isCamera()) { - if(kb.getKeyDescription().equals("key.forward")) { - forward = true; - speedup = true; - } - - if(kb.getKeyDescription().equals("key.back")) { - backward = true; - speedup = true; - } - - if(kb.getKeyDescription().equals("key.jump")) { - up = true; - speedup = true; - } - - if(kb.getKeyDescription().equals("key.left")) { - left = true; - speedup = true; - } - - if(kb.getKeyDescription().equals("key.right")) { - right = true; - speedup = true; - } - } - - if(kb.getKeyDescription().equals("key.sneak")) { - if(ReplayHandler.isCamera()) { - down = true; - speedup = true; - } - ReplayHandler.spectateCamera(); - } - } - - forwardCameraMovement(forward, backward, left, right, up, down); - } - } - - if(ReplayHandler.getCameraEntity() != null) { - if(speedup) { - ReplayHandler.getCameraEntity().speedUp(); - prevKeysDown = Sys.getTime(); - } else { - if(Sys.getTime() - prevKeysDown > 100) { - ReplayHandler.getCameraEntity().stopSpeedUp(); - } - } - } - } - - @SubscribeEvent - public void keyInput(InputEvent.KeyInputEvent event) { - try { - onKeyInput(); - } catch(Exception e) { - e.printStackTrace(); - } - - KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; - - boolean found = false; - - for(KeyBinding kb : keyBindings) { - if(!kb.isKeyDown()) continue; - - handleCustomKeybindings(kb, found, -1); - found = true; - } - - if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return; - - for(StaticKeybinding staticKeybinding : KeybindRegistry.staticKeybindings) { - if(!Keyboard.isKeyDown(staticKeybinding.getKeyCode())) { - staticKeybinding.setDown(false); - return; - } - - if(staticKeybinding.isDown()) return; - staticKeybinding.setDown(true); - - switch(staticKeybinding.getId()) { - case KeybindRegistry.STATIC_DELETE_KEYFRAME: - if(ReplayHandler.getSelectedKeyframe() != null) ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe()); - break; - } - } - } - - private void forwardCameraMovement(boolean forward, boolean backward, boolean left, boolean right, boolean up, boolean down) { - if(forward && !backward) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD); - } else if(backward && !forward) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD); - } - - if(left && !right) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT); - } else if(right && !left) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT); - } - - if(up && !down) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP); - } else if(down && !up) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN); - } + // TODO +// if(!ReplayHandler.isInReplay()) return; +// +// KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; +// +// boolean speedup = false; +// +// if(mc.currentScreen == null) { +// boolean forward = false, backward = false, left = false, right = false, up = false, down = false; +// +// if(!ReplayHandler.isInPath()) { +// for(KeyBinding kb : keyBindings) { +// if(!kb.isKeyDown()) continue; +// if(ReplayHandler.isCameraView()) { +// if(kb.getKeyDescription().equals("key.forward")) { +// forward = true; +// speedup = true; +// } +// +// if(kb.getKeyDescription().equals("key.back")) { +// backward = true; +// speedup = true; +// } +// +// if(kb.getKeyDescription().equals("key.jump")) { +// up = true; +// speedup = true; +// } +// +// if(kb.getKeyDescription().equals("key.left")) { +// left = true; +// speedup = true; +// } +// +// if(kb.getKeyDescription().equals("key.right")) { +// right = true; +// speedup = true; +// } +// } +// +// if(kb.getKeyDescription().equals("key.sneak")) { +// if(ReplayHandler.isCameraView()) { +// down = true; +// speedup = true; +// } +// ReplayHandler.spectateCamera(); +// } +// } +// +// forwardCameraMovement(forward, backward, left, right, up, down); +// } +// } +// +// if(ReplayHandler.getCameraEntity() != null) { +// if(speedup) { +// ReplayHandler.getCameraEntity().speedUp(); +// prevKeysDown = Sys.getTime(); +// } else { +// if(Sys.getTime() - prevKeysDown > 100) { +// ReplayHandler.getCameraEntity().stopSpeedUp(); +// } +// } +// } } +// +// @SubscribeEvent +// public void keyInput(InputEvent.KeyInputEvent event) { +// try { +// onKeyInput(); +// } catch(Exception e) { +// e.printStackTrace(); +// } +// +// KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; +// +// boolean found = false; +// +// for(KeyBinding kb : keyBindings) { +// if(!kb.isKeyDown()) continue; +// +// handleCustomKeybindings(kb, found, -1); +// found = true; +// } +// +// if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return; +// +// for(StaticKeybinding staticKeybinding : KeybindRegistry.staticKeybindings) { +// if(!Keyboard.isKeyDown(staticKeybinding.getKeyCode())) { +// staticKeybinding.setDown(false); +// return; +// } +// +// if(staticKeybinding.isDown()) return; +// staticKeybinding.setDown(true); +// +// switch(staticKeybinding.getId()) { +// case KeybindRegistry.STATIC_DELETE_KEYFRAME: +// if(ReplayHandler.getSelectedKeyframe() != null) ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe()); +// break; +// } +// } +// } +// +// private void forwardCameraMovement(boolean forward, boolean backward, boolean left, boolean right, boolean up, boolean down) { +// if(forward && !backward) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD); +// } else if(backward && !forward) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD); +// } +// +// if(left && !right) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT); +// } else if(right && !left) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT); +// } +// +// if(up && !down) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP); +// } else if(down && !up) { +// ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN); +// } +// } public void handleCustomKeybindings(KeyBinding kb, boolean found, int keyCode) { //Custom registered handlers - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) { - if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) { - ReplayHandler.toggleMarker(); - } else if(ConnectionEventHandler.isRecording()) { - ConnectionEventHandler.addMarker(); - } - } - - if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return; - - if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command")) - && (kb.isPressed() || kb.getKeyCode() == keyCode)) { - mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay)); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayMod.overlay.togglePlayPause(); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_CLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? 0.2f : 1); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_COUNTERCLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? -0.2f : -1); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_RESET_TILT) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayHandler.setCameraTilt(0); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { - TickAndRenderListener.requestScreenshot(); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { - PlayerHandler.openPlayerOverview(); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled()); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback()); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SYNC_TIMELINE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayHandler.syncTimeCursor(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_KEYFRAME_PRESETS) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository())); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview()); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - mc.displayGuiScreen(new GuiAssetManager()); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - mc.displayGuiScreen(new GuiObjectManager()); - } - - if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { - ReplayMod.replaySettings.toggleInterpolation(); - } + // TODO: Transfer to new key binding registry +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) { +// if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) { +// ReplayHandler.toggleMarker(); +// } +// } +// +// if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return; +// +// if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command")) +// && (kb.isPressed() || kb.getKeyCode() == keyCode)) { +// mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay)); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayMod.overlay.togglePlayPause(); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_CLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? 0.2f : 1); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_COUNTERCLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? -0.2f : -1); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_RESET_TILT) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayHandler.setCameraTilt(0); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { +// TickAndRenderListener.requestScreenshot(); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { +// PlayerHandler.openPlayerOverview(); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled()); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback()); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SYNC_TIMELINE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayHandler.syncTimeCursor(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_KEYFRAME_PRESETS) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository())); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview()); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// mc.displayGuiScreen(new GuiAssetManager()); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// mc.displayGuiScreen(new GuiObjectManager()); +// } +// +// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { +// ReplayMod.replaySettings.toggleInterpolation(); +// } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiAssetManager.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiAssetManager.java index 2836509b..3a09b099 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiAssetManager.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiAssetManager.java @@ -6,8 +6,6 @@ import eu.crushedpixel.replaymod.assets.ReplayAsset; import eu.crushedpixel.replaymod.gui.elements.*; import eu.crushedpixel.replaymod.gui.elements.listeners.FileChooseListener; import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.MouseUtils; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; @@ -22,7 +20,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOverlay { +public class GuiAssetManager extends GuiScreen { private String screenTitle; @@ -43,8 +41,10 @@ public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOve private ReplayAsset currentAsset; public GuiAssetManager() { - this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository()); - this.assetRepository = ReplayHandler.getAssetRepository(); + // TODO + initialRepository = null; +// this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository()); +// this.assetRepository = ReplayHandler.getAssetRepository(); } @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java index 39568ffb..ee8edb81 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEditKeyframe.java @@ -1,35 +1,30 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.*; -import eu.crushedpixel.replaymod.gui.elements.listeners.NumberValueChangeListener; -import eu.crushedpixel.replaymod.holders.*; +import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.interpolation.KeyframeList; import eu.crushedpixel.replaymod.interpolation.KeyframeValue; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.MouseUtils; -import eu.crushedpixel.replaymod.utils.RoundUtils; import eu.crushedpixel.replaymod.utils.TimestampUtils; 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 org.lwjgl.input.Keyboard; import org.lwjgl.util.Point; import java.awt.*; import java.io.IOException; -import java.util.Arrays; import java.util.List; public abstract class GuiEditKeyframe extends GuiScreen { @SuppressWarnings("unchecked") public static GuiEditKeyframe create(Keyframe kf) { - if(kf.getValue() instanceof Marker) return new GuiEditKeyframeMarker(kf); - if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf); - if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf); - if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf); + // TODO +// if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf); +// if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf); +// if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf); throw new UnsupportedOperationException("Keyframe type unknown: " + kf); } @@ -156,13 +151,14 @@ public abstract class GuiEditKeyframe extends GuiScreen @Override public void onGuiClosed() { - if(!save) { - ReplayHandler.removeKeyframe(keyframe); - ReplayHandler.addKeyframe(keyframeBackup); - ReplayHandler.selectKeyframe(keyframeBackup); - } - ReplayHandler.fireKeyframesModifyEvent(); - Keyboard.enableRepeatEvents(false); + // TODO +// if(!save) { +// ReplayHandler.removeKeyframe(keyframe); +// ReplayHandler.addKeyframe(keyframeBackup); +// ReplayHandler.selectKeyframe(keyframeBackup); +// } +// ReplayHandler.fireKeyframesModifyEvent(); +// Keyboard.enableRepeatEvents(false); } @Override @@ -218,300 +214,301 @@ public abstract class GuiEditKeyframe extends GuiScreen protected void drawScreen0() {} - private static class GuiEditKeyframeMarker extends GuiEditKeyframe { - private GuiAdvancedTextField markerNameInput; - - public GuiEditKeyframeMarker(Keyframe keyframe) { - super(keyframe, ReplayHandler.getMarkerKeyframes()); - } - - @Override - public void initGui() { - super.initGui(); - - if (!initialized) { - String name = keyframe.getValue().getName(); - if (name == null) name = ""; - markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20); - markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername"); - markerNameInput.setText(name); - - inputs.addPart(markerNameInput); - - new KeyframeValueChangeListener(this); - } - - markerNameInput.xPosition = width/2 - 100; - markerNameInput.yPosition = height/2-10; - - initialized = true; - } - - @Override - public void onGuiClosed() { - keyframe.getValue().setName(markerNameInput.getText().trim()); - super.onGuiClosed(); - } - } - - private static class GuiEditKeyframeTime extends GuiEditKeyframe { - private GuiNumberInput kfMin, kfSec, kfMs; - - public GuiEditKeyframeTime(Keyframe keyframe) { - super(keyframe, ReplayHandler.getTimeKeyframes()); - screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time"); - } - - @Override - public void initGui() { - super.initGui(); - - if (!initialized) { - int time = keyframe.getValue().asInt(); - - kfMin = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, null, (double)TimestampUtils.timestampToWholeMinutes(time), false, "", 1); - kfSec = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 25, 0d, 59d, (double)TimestampUtils.getSecondsFromTimestamp(time), false, "", 1); - kfMs = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(time), false, "", 1); - - inputs.addPart(kfMin); - inputs.addPart(kfSec); - inputs.addPart(kfMs); - - KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { - @Override - public void onValueChange(double value) { - keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp( - kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue()))); - - super.onValueChange(value); - } - }; - - kfMin.addValueChangeListener(listener); - kfSec.addValueChangeListener(listener); - kfMs.addValueChangeListener(listener); - } - - kfMin.xPosition = min.xPosition; - kfSec.xPosition = sec.xPosition; - kfMs.xPosition = ms.xPosition; - - kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20; - - initialized = true; - } - - @Override - protected void drawScreen0() { - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, kfMin.yPosition + 7, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.seconds"), kfSec.xPosition + kfSec.width + 5, kfSec.yPosition + 7, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.milliseconds"), kfMs.xPosition + kfMs.width + 5, kfMs.yPosition + 7, Color.WHITE.getRGB()); - } - - } - - private static class GuiEditKeyframePosition extends GuiEditKeyframe { - private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll; - private ComposedElement posInputs; - - public GuiEditKeyframePosition(Keyframe keyframe) { - super(keyframe, ReplayHandler.getPositionKeyframes()); - screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos"); - } - - @Override - public void initGui() { - super.initGui(); - - if (!initialized) { - AdvancedPosition pos = keyframe.getValue(); - xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true); - yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true); - zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true); - yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true); - pitch = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, -90d, 90d, RoundUtils.round2Decimals(pos.getPitch()), true); - roll = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getRoll()), true); - - posInputs = new ComposedElement(xCoord, yCoord, zCoord, yaw, pitch, roll); - inputs.addPart(posInputs); - - KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { - @Override - public void onValueChange(double value) { - keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(), - zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(), - (float) roll.getPreciseValue())); - - super.onValueChange(value); - } - }; - - xCoord.addValueChangeListener(listener); - yCoord.addValueChangeListener(listener); - zCoord.addValueChangeListener(listener); - pitch.addValueChangeListener(listener); - yaw.addValueChangeListener(listener); - roll.addValueChangeListener(listener); - } - - int w = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.xpos")), - Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.ypos")), - fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos")))); - w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")), - Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.campitch")), - fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camroll")))); - - totalWidth = w +100+w2+100+5+5+10; - left = (this.width - totalWidth)/2; - - int x = w + left + 5; - int i = 0; - for(GuiElement input : posInputs.getParts()) { - if(input instanceof GuiTextField) { - GuiTextField textField = (GuiTextField)input; - textField.xPosition = i < 3 ? x : left+totalWidth-100; - textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30; - i++; - } - } - - initialized = true; - } - - @Override - protected void drawScreen0() { - if (keyframe.getValue() instanceof SpectatorData) return; - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.zpos"), left, virtualY + 87, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camyaw"), left + totalWidth - 100 - 5 - w2, virtualY + 27, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.campitch"), left + totalWidth - 100 - 5 - w2, virtualY + 57, Color.WHITE.getRGB()); - drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camroll"), left + totalWidth - 100 - 5 - w2, virtualY + 87, Color.WHITE.getRGB()); - } - - } - - private static class GuiEditKeyframeSpectator extends GuiEditKeyframe { - private GuiToggleButton perspectiveButton; - - private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString; - private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput, - shoulderYawOffsetInput, shoulderSmoothnessInput; - - private ComposedElement spectatorCamSettings; - private ComposedElement shoulderCamSettings; - - private DelegatingElement perspectiveSettings = new DelegatingElement() { - @Override - public GuiElement delegate() { - switch(perspectiveButton.getValue()) { - case 0: - return spectatorCamSettings; - case 1: - return shoulderCamSettings; - default: - return null; - } - } - }; - - public GuiEditKeyframeSpectator(Keyframe keyframe) { - super(keyframe, ReplayHandler.getPositionKeyframes()); - screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec"); - } - - @Override - public void initGui() { - super.initGui(); - - if (!initialized) { - SpectatorData data = (SpectatorData)keyframe.getValue(); - - perspectiveButton = new GuiToggleButton(0, 0, 0, 200, 20, I18n.format("replaymod.gui.editkeyframe.spec.method")+": ", new String[]{ - I18n.format("replaymod.gui.editkeyframe.spec.method.firstperson"), - I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder")}); - - perspectiveButton.setValue(Arrays.asList(SpectatorData.SpectatingMethod.values()).indexOf(data.getSpectatingMethod())); - - spectatorCamSettings = new ComposedElement(); - - //create elements in shoulderCamSettings - shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance")); - shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch")); - shoulderYawString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.yaw")); - shoulderSmoothnessString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.smoothness")); - - shoulderDistanceInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0d, 30d, data.getThirdPersonInfo().shoulderCamDistance, true, "", 0.1); - shoulderPitchOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, -90d, 90d, data.getThirdPersonInfo().shoulderCamPitchOffset, false, "°", 1); - shoulderYawOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, null, null, data.getThirdPersonInfo().shoulderCamYawOffset, false, "°", 1); - shoulderSmoothnessInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0.1d, 3d, data.getThirdPersonInfo().shoulderCamSmoothness, true, "", 0.1); - - shoulderCamSettings = new ComposedElement( - shoulderDistanceString, shoulderDistanceInput, - shoulderPitchString, shoulderPitchOffsetInput, - shoulderYawString, shoulderYawOffsetInput, - shoulderSmoothnessString, shoulderSmoothnessInput); - - inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings)); - } - - perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2; - perspectiveButton.yPosition = this.virtualY + 20; - - int verticalSpacing = 20 + 5; - int totalWidth = 300; - int elementWidth = 145; - int horizontalSpacing = 10; - - int y = perspectiveButton.yPos() + verticalSpacing; - - int i = 0; - for(GuiElement el : shoulderCamSettings.getParts()) { - el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing)); - el.width(elementWidth); - - el.yPos(y + ((i+1)%2)*7); - - if(i%2 == 1) { - y += verticalSpacing; - } - i++; - } - - initialized = true; - } - - @Override - public void onGuiClosed() { - SpectatorData data = (SpectatorData)keyframe.getValue(); - data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]); - data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue(); - data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue(); - data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue(); - data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue(); - super.onGuiClosed(); - } - } - - private static class KeyframeValueChangeListener implements NumberValueChangeListener { - - private GuiEditKeyframe parent; - - public KeyframeValueChangeListener(GuiEditKeyframe parent) { - this.parent = parent; - - parent.min.addValueChangeListener(this); - parent.sec.addValueChangeListener(this); - parent.ms.addValueChangeListener(this); - } - - @Override - public void onValueChange(double value) { - int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue()); - parent.keyframe.setRealTimestamp(realTimestamp); - - ReplayHandler.fireKeyframesModifyEvent(); - } - } + // TODO +// private static class GuiEditKeyframeMarker extends GuiEditKeyframe { +// private GuiAdvancedTextField markerNameInput; +// +// public GuiEditKeyframeMarker(Keyframe keyframe) { +// super(keyframe, ReplayHandler.getMarkerKeyframes()); +// } +// +// @Override +// public void initGui() { +// super.initGui(); +// +// if (!initialized) { +// String name = keyframe.getValue().getName(); +// if (name == null) name = ""; +// markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20); +// markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername"); +// markerNameInput.setText(name); +// +// inputs.addPart(markerNameInput); +// +// new KeyframeValueChangeListener(this); +// } +// +// markerNameInput.xPosition = width/2 - 100; +// markerNameInput.yPosition = height/2-10; +// +// initialized = true; +// } +// +// @Override +// public void onGuiClosed() { +// keyframe.getValue().setName(markerNameInput.getText().trim()); +// super.onGuiClosed(); +// } +// } +// +// private static class GuiEditKeyframeTime extends GuiEditKeyframe { +// private GuiNumberInput kfMin, kfSec, kfMs; +// +// public GuiEditKeyframeTime(Keyframe keyframe) { +// super(keyframe, ReplayHandler.getTimeKeyframes()); +// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time"); +// } +// +// @Override +// public void initGui() { +// super.initGui(); +// +// if (!initialized) { +// int time = keyframe.getValue().asInt(); +// +// kfMin = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, null, (double)TimestampUtils.timestampToWholeMinutes(time), false, "", 1); +// kfSec = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 25, 0d, 59d, (double)TimestampUtils.getSecondsFromTimestamp(time), false, "", 1); +// kfMs = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(time), false, "", 1); +// +// inputs.addPart(kfMin); +// inputs.addPart(kfSec); +// inputs.addPart(kfMs); +// +// KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { +// @Override +// public void onValueChange(double value) { +// keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp( +// kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue()))); +// +// super.onValueChange(value); +// } +// }; +// +// kfMin.addValueChangeListener(listener); +// kfSec.addValueChangeListener(listener); +// kfMs.addValueChangeListener(listener); +// } +// +// kfMin.xPosition = min.xPosition; +// kfSec.xPosition = sec.xPosition; +// kfMs.xPosition = ms.xPosition; +// +// kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20; +// +// initialized = true; +// } +// +// @Override +// protected void drawScreen0() { +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, kfMin.yPosition + 7, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.seconds"), kfSec.xPosition + kfSec.width + 5, kfSec.yPosition + 7, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.milliseconds"), kfMs.xPosition + kfMs.width + 5, kfMs.yPosition + 7, Color.WHITE.getRGB()); +// } +// +// } +// +// private static class GuiEditKeyframePosition extends GuiEditKeyframe { +// private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll; +// private ComposedElement posInputs; +// +// public GuiEditKeyframePosition(Keyframe keyframe) { +// super(keyframe, ReplayHandler.getPositionKeyframes()); +// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos"); +// } +// +// @Override +// public void initGui() { +// super.initGui(); +// +// if (!initialized) { +// AdvancedPosition pos = keyframe.getValue(); +// xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true); +// yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true); +// zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true); +// yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true); +// pitch = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, -90d, 90d, RoundUtils.round2Decimals(pos.getPitch()), true); +// roll = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getRoll()), true); +// +// posInputs = new ComposedElement(xCoord, yCoord, zCoord, yaw, pitch, roll); +// inputs.addPart(posInputs); +// +// KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { +// @Override +// public void onValueChange(double value) { +// keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(), +// zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(), +// (float) roll.getPreciseValue())); +// +// super.onValueChange(value); +// } +// }; +// +// xCoord.addValueChangeListener(listener); +// yCoord.addValueChangeListener(listener); +// zCoord.addValueChangeListener(listener); +// pitch.addValueChangeListener(listener); +// yaw.addValueChangeListener(listener); +// roll.addValueChangeListener(listener); +// } +// +// int w = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.xpos")), +// Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.ypos")), +// fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos")))); +// w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")), +// Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.campitch")), +// fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camroll")))); +// +// totalWidth = w +100+w2+100+5+5+10; +// left = (this.width - totalWidth)/2; +// +// int x = w + left + 5; +// int i = 0; +// for(GuiElement input : posInputs.getParts()) { +// if(input instanceof GuiTextField) { +// GuiTextField textField = (GuiTextField)input; +// textField.xPosition = i < 3 ? x : left+totalWidth-100; +// textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30; +// i++; +// } +// } +// +// initialized = true; +// } +// +// @Override +// protected void drawScreen0() { +// if (keyframe.getValue() instanceof SpectatorData) return; +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.zpos"), left, virtualY + 87, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camyaw"), left + totalWidth - 100 - 5 - w2, virtualY + 27, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.campitch"), left + totalWidth - 100 - 5 - w2, virtualY + 57, Color.WHITE.getRGB()); +// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camroll"), left + totalWidth - 100 - 5 - w2, virtualY + 87, Color.WHITE.getRGB()); +// } +// +// } +// +// private static class GuiEditKeyframeSpectator extends GuiEditKeyframe { +// private GuiToggleButton perspectiveButton; +// +// private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString; +// private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput, +// shoulderYawOffsetInput, shoulderSmoothnessInput; +// +// private ComposedElement spectatorCamSettings; +// private ComposedElement shoulderCamSettings; +// +// private DelegatingElement perspectiveSettings = new DelegatingElement() { +// @Override +// public GuiElement delegate() { +// switch(perspectiveButton.getValue()) { +// case 0: +// return spectatorCamSettings; +// case 1: +// return shoulderCamSettings; +// default: +// return null; +// } +// } +// }; +// +// public GuiEditKeyframeSpectator(Keyframe keyframe) { +// super(keyframe, ReplayHandler.getPositionKeyframes()); +// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec"); +// } +// +// @Override +// public void initGui() { +// super.initGui(); +// +// if (!initialized) { +// SpectatorData data = (SpectatorData)keyframe.getValue(); +// +// perspectiveButton = new GuiToggleButton(0, 0, 0, 200, 20, I18n.format("replaymod.gui.editkeyframe.spec.method")+": ", new String[]{ +// I18n.format("replaymod.gui.editkeyframe.spec.method.firstperson"), +// I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder")}); +// +// perspectiveButton.setValue(Arrays.asList(SpectatorData.SpectatingMethod.values()).indexOf(data.getSpectatingMethod())); +// +// spectatorCamSettings = new ComposedElement(); +// +// //create elements in shoulderCamSettings +// shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance")); +// shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch")); +// shoulderYawString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.yaw")); +// shoulderSmoothnessString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.smoothness")); +// +// shoulderDistanceInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0d, 30d, data.getThirdPersonInfo().shoulderCamDistance, true, "", 0.1); +// shoulderPitchOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, -90d, 90d, data.getThirdPersonInfo().shoulderCamPitchOffset, false, "°", 1); +// shoulderYawOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, null, null, data.getThirdPersonInfo().shoulderCamYawOffset, false, "°", 1); +// shoulderSmoothnessInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0.1d, 3d, data.getThirdPersonInfo().shoulderCamSmoothness, true, "", 0.1); +// +// shoulderCamSettings = new ComposedElement( +// shoulderDistanceString, shoulderDistanceInput, +// shoulderPitchString, shoulderPitchOffsetInput, +// shoulderYawString, shoulderYawOffsetInput, +// shoulderSmoothnessString, shoulderSmoothnessInput); +// +// inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings)); +// } +// +// perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2; +// perspectiveButton.yPosition = this.virtualY + 20; +// +// int verticalSpacing = 20 + 5; +// int totalWidth = 300; +// int elementWidth = 145; +// int horizontalSpacing = 10; +// +// int y = perspectiveButton.yPos() + verticalSpacing; +// +// int i = 0; +// for(GuiElement el : shoulderCamSettings.getParts()) { +// el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing)); +// el.width(elementWidth); +// +// el.yPos(y + ((i+1)%2)*7); +// +// if(i%2 == 1) { +// y += verticalSpacing; +// } +// i++; +// } +// +// initialized = true; +// } +// +// @Override +// public void onGuiClosed() { +// SpectatorData data = (SpectatorData)keyframe.getValue(); +// data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]); +// data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue(); +// data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue(); +// data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue(); +// data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue(); +// super.onGuiClosed(); +// } +// } +// +// private static class KeyframeValueChangeListener implements NumberValueChangeListener { +// +// private GuiEditKeyframe parent; +// +// public KeyframeValueChangeListener(GuiEditKeyframe parent) { +// this.parent = parent; +// +// parent.min.addValueChangeListener(this); +// parent.sec.addValueChangeListener(this); +// parent.ms.addValueChangeListener(this); +// } +// +// @Override +// public void onValueChange(double value) { +// int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue()); +// parent.keyframe.setRealTimestamp(realTimestamp); +// +// ReplayHandler.fireKeyframesModifyEvent(); +// } +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiKeyframeRepository.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiKeyframeRepository.java index d9428856..059b9a82 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiKeyframeRepository.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiKeyframeRepository.java @@ -1,13 +1,9 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.GuiEntryList; import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.KeyframeSet; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.utils.CameraPathValidator; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; @@ -22,7 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay.NoOverlay { +public class GuiKeyframeRepository extends GuiScreen { private boolean initialized = false; @@ -133,39 +129,40 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay @Override public void actionPerformed(GuiButton button) { - if(!button.enabled) return; - switch(button.id) { - case GuiConstants.KEYFRAME_REPOSITORY_ADD_BUTTON: - List kfs = new ArrayList(ReplayHandler.getAllKeyframes()); - - Keyframe[] keyframes = kfs.toArray(new Keyframe[ReplayHandler.getAllKeyframes().size()]); - KeyframeSet newSet = new KeyframeSet(I18n.format("replaymod.gui.keyframerepository.preset.defaultname"), keyframes, ReplayHandler.getCustomImageObjects()); - - try { - CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes()); - } catch(CameraPathValidator.InvalidCameraPathException e) { - message = e.getLocalizedMessage(); - break; - } - - if(keyframeSetList.getCopyOfElements().contains(newSet)) { - message = I18n.format("replaymod.gui.keyframerepository.duplicate"); - break; - } - message = null; - - keyframeSetList.addElement(newSet); - keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1); - break; - case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON: - keyframeSetList.removeElement(keyframeSetList.getSelectionIndex()); - break; - case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON: - ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex())); - saveOnQuit(); - mc.displayGuiScreen(null); - break; - } + // TODO +// if(!button.enabled) return; +// switch(button.id) { +// case GuiConstants.KEYFRAME_REPOSITORY_ADD_BUTTON: +// List kfs = new ArrayList(ReplayHandler.getAllKeyframes()); +// +// Keyframe[] keyframes = kfs.toArray(new Keyframe[ReplayHandler.getAllKeyframes().size()]); +// KeyframeSet newSet = new KeyframeSet(I18n.format("replaymod.gui.keyframerepository.preset.defaultname"), keyframes, ReplayHandler.getCustomImageObjects()); +// +// try { +// CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes()); +// } catch(CameraPathValidator.InvalidCameraPathException e) { +// message = e.getLocalizedMessage(); +// break; +// } +// +// if(keyframeSetList.getCopyOfElements().contains(newSet)) { +// message = I18n.format("replaymod.gui.keyframerepository.duplicate"); +// break; +// } +// message = null; +// +// keyframeSetList.addElement(newSet); +// keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1); +// break; +// case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON: +// keyframeSetList.removeElement(keyframeSetList.getSelectionIndex()); +// break; +// case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON: +// ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex())); +// saveOnQuit(); +// mc.displayGuiScreen(null); +// break; +// } } @Override @@ -241,7 +238,8 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay if(initialKeyframeSets.equals(copy)) return; this.keyframeRepository = copy.toArray(new KeyframeSet[copy.size()]); - ReplayHandler.setKeyframeRepository(keyframeRepository, true); + // TODO +// ReplayHandler.setKeyframeRepository(keyframeRepository, true); } @Override diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java deleted file mode 100755 index e04f61f2..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java +++ /dev/null @@ -1,53 +0,0 @@ -package eu.crushedpixel.replaymod.gui; - -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import org.lwjgl.input.Mouse; - -import java.io.IOException; - -public class GuiMouseInput extends GuiScreen { - - private final Minecraft mc = Minecraft.getMinecraft(); - - private final GuiReplayOverlay overlay; - - private boolean shouldClose = false; - - public GuiMouseInput(GuiReplayOverlay overlay) { - this.overlay = overlay; - Mouse.setGrabbed(false); - Mouse.setCursorPosition(mc.displayWidth/2, mc.displayHeight/2); - - if(mc.currentScreen instanceof GuiMouseInput) { - shouldClose = true; - } - } - - @Override - public void initGui() { - if(shouldClose) mc.displayGuiScreen(null); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - overlay.mouseClicked(mouseX, mouseY, mouseButton); - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - overlay.mouseReleased(mouseX, mouseY, state); - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - overlay.mouseDrag(mouseX, mouseY, clickedMouseButton); - } - - @Override - public void onGuiClosed() { - ReplayMod.overlay.closeToolbar(); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiObjectManager.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiObjectManager.java index 3c436fc0..fe8156e1 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiObjectManager.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiObjectManager.java @@ -1,723 +1,698 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.assets.CustomImageObject; -import eu.crushedpixel.replaymod.assets.ReplayAsset; -import eu.crushedpixel.replaymod.gui.elements.*; -import eu.crushedpixel.replaymod.gui.elements.listeners.NumberValueChangeListener; -import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; -import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.holders.*; -import eu.crushedpixel.replaymod.interpolation.KeyframeList; -import eu.crushedpixel.replaymod.interpolation.KeyframeValue; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.utils.MouseUtils; -import lombok.Getter; -import lombok.Setter; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import org.lwjgl.input.Keyboard; -import org.lwjgl.util.Point; -import java.awt.*; -import java.io.IOException; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.UUID; - -public class GuiObjectManager extends GuiScreen implements GuiReplayOverlay.NoOverlay { - - private boolean initialized = false; - - private GuiEntryList objectList; - private GuiAdvancedButton addButton, removeButton; - - private GuiAdvancedTextField nameInput; - - private GuiString dropdownLabel; - private GuiDropdown> assetDropdown; - - private final List initialObjects = ReplayHandler.getCustomImageObjects(); - - private GuiDraggingNumberInput anchorXInput, anchorYInput, anchorZInput; - private GuiDraggingNumberInput positionXInput, positionYInput, positionZInput; - private GuiDraggingNumberInput orientationXInput, orientationYInput, orientationZInput; - private GuiDraggingNumberInput scaleXInput, scaleYInput, scaleZInput; - private GuiDraggingNumberInput opacityInput; - - private NumberPositionInputGroup anchorNumberInputs, positionNumberInputs, orientationNumberInputs, scaleNumberInputs; - private NumberValueInputGroup opacityNumberInputs; - - @Getter - private GuiObjectKeyframeTimeline objectKeyframeTimeline; - - private ComposedElement disableElements, allElements; - - private static final int KEYFRAME_BUTTON_X = 80; - private static final int KEYFRAME_BUTTON_Y = 40; - - private static final float ZOOM_STEPS = 0.05f; - - private DelegatingElement keyframeButton(final int x, final int y, final int line) { - return new DelegatingElement() { - - private GuiTexturedButton normal = new GuiTexturedButton(0, x, y, 20, 20, - GuiReplayOverlay.replay_gui, KEYFRAME_BUTTON_X, KEYFRAME_BUTTON_Y, - GuiReplayOverlay.TEXTURE_SIZE, GuiReplayOverlay.TEXTURE_SIZE, new Runnable() { - @Override - public void run() { - objectKeyframeTimeline.addKeyframe(line); - } - }, - null); - - private GuiTexturedButton selected = new GuiTexturedButton(0, x, y, 20, 20, - GuiReplayOverlay.replay_gui, KEYFRAME_BUTTON_X, KEYFRAME_BUTTON_Y+20, - GuiReplayOverlay.TEXTURE_SIZE, GuiReplayOverlay.TEXTURE_SIZE, new Runnable() { - @Override - public void run() { - objectKeyframeTimeline.removeKeyframe(line); - } - }, - null); - - @Override - public GuiElement delegate() { - if(objectKeyframeTimeline.getSelectedKeyframeRow() == line) { - return selected; - } else { - return normal; - } - } - - @Override - public void setElementEnabled(boolean enabled) { - selected.setElementEnabled(enabled); - normal.setElementEnabled(enabled); - } - }; - } - - @Override - public void initGui() { - if(!initialized) { - anchorXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); - anchorYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); - anchorZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); - anchorNumberInputs = new NumberPositionInputGroup(null, anchorXInput, anchorYInput, anchorZInput); - - positionXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - positionYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - positionZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - positionNumberInputs = new NumberPositionInputGroup(null, positionXInput, positionYInput, positionZInput); - - orientationXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - orientationYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - orientationZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); - orientationNumberInputs = new NumberPositionInputGroup(null, orientationXInput, orientationYInput, orientationZInput); - - scaleXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); - scaleYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); - scaleZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); - scaleNumberInputs = new NumberPositionInputGroup(null, scaleXInput, scaleYInput, scaleZInput); - - opacityInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, 0d, 100d, 100d, true, "%", 0.5); - opacityNumberInputs = new NumberValueInputGroup(null, opacityInput); - - dropdownLabel = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.assets.filechooser")+": "); - assetDropdown = new GuiDropdown>(fontRendererObj, 0, 0, 0, 5); - List assets = ReplayHandler.getAssetRepository().getCopyOfReplayAssets(); - Collections.sort(assets, new Comparator() { - @Override - public int compare(ReplayAsset o1, ReplayAsset o2) { - return o1.getAssetName().compareTo(o2.getAssetName()); - } - }); - if(assets.isEmpty()) { - assetDropdown.addElement(new GuiEntryListValueEntry(I18n.format("replaymod.gui.assets.emptylist"), null)); - } else { - assetDropdown.addElement(new GuiEntryListValueEntry(I18n.format("replaymod.gui.assets.noselection"), null)); - for(ReplayAsset asset : assets) { - assetDropdown.addElement(new GuiEntryListValueEntry( - asset.getDisplayString(), ReplayHandler.getAssetRepository().getUUIDForAsset(asset))); - } - } - - objectList = new GuiEntryList(fontRendererObj, 0, 0, 0, 0); - objectList.setEmptyMessage(I18n.format("replaymod.gui.objects.empty")); - - addButton = new GuiAdvancedButton(0, 0, 0, 20, I18n.format("replaymod.gui.add"), new Runnable() { - @Override - public void run() { - try { - CustomImageObject customImageObject = new CustomImageObject(I18n.format("replaymod.gui.objects.defaultname"), null); - - Position defaultPosition = new Position(mc.getRenderViewEntity()); - customImageObject.getTransformations().setDefaultPosition(defaultPosition); - - objectList.addElement(customImageObject); - } catch(IOException e) { - e.printStackTrace(); - } - } - }, null); - - removeButton = new GuiAdvancedButton(0, 0, 0, 20, I18n.format("replaymod.gui.remove"), new Runnable() { - @Override - public void run() { - if(objectList.getElement(objectList.getSelectionIndex()) != null) - objectList.removeElement(objectList.getSelectionIndex()); - } - }, null); - - nameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 0, 20); - nameInput.hint = I18n.format("replaymod.gui.objects.properties.name"); - - for(CustomImageObject customImageObject : initialObjects) { - try { - objectList.addElement(customImageObject.copy()); - } catch(IOException ioe) { - ioe.printStackTrace(); - } - } - - objectList.addSelectionListener(new SelectionListener() { - @Override - public void onSelectionChanged(int selectionIndex) { - CustomImageObject selectedObject = objectList.getElement(selectionIndex); - if(selectedObject != null) { - disableElements.setElementEnabled(true); - - nameInput.setText(selectedObject.getName()); - - //setting the dropdown value - int sel = 0; - if(selectedObject.getLinkedAsset() != null) { - int i = 0; - for(GuiEntryListValueEntry entry : assetDropdown.getAllElements()) { - if(selectedObject.getLinkedAsset().equals(entry.getValue())) { - sel = i; - break; - } - i++; - } - } - - assetDropdown.setSelectionIndexQuietly(sel); - - Transformations transformations = selectedObject.getTransformations(); - - objectKeyframeTimeline.setTransformations(transformations); - - anchorNumberInputs.setUnderlyingKeyframeList(transformations.getAnchorKeyframes()); - positionNumberInputs.setUnderlyingKeyframeList(transformations.getPositionKeyframes()); - orientationNumberInputs.setUnderlyingKeyframeList(transformations.getOrientationKeyframes()); - scaleNumberInputs.setUnderlyingKeyframeList(transformations.getScaleKeyframes()); - opacityNumberInputs.setUnderlyingKeyframeList(transformations.getOpacityKeyframes()); - - updateValuesForTransformation(objectKeyframeTimeline.getTransformations().getTransformationForTimestamp(objectKeyframeTimeline.cursorPosition)); - } else { - disableElements.setElementEnabled(false); - } - } - }); - - assetDropdown.addSelectionListener(new SelectionListener() { - @Override - public void onSelectionChanged(int selectionIndex) { - CustomImageObject selectedObject = objectList.getElement(objectList.getSelectionIndex()); - GuiEntryListValueEntry entry = assetDropdown.getElement(selectionIndex); - if(selectedObject != null && entry != null) { - try { - selectedObject.setLinkedAsset(entry.getValue()); - } catch(IOException e) { - e.printStackTrace(); - } - } - } - }); - } - - String[] labelStrings = new String[] { - I18n.format("replaymod.gui.objects.properties.anchor"), - I18n.format("replaymod.gui.objects.properties.position"), - I18n.format("replaymod.gui.objects.properties.orientation"), - I18n.format("replaymod.gui.objects.properties.scale"), - I18n.format("replaymod.gui.objects.properties.opacity"), - }; - - int maxStringWidth = 0; - for(String label : labelStrings) { - int stringWidth = fontRendererObj.getStringWidth(label); - if(stringWidth > maxStringWidth) { - maxStringWidth = stringWidth; - } - } - - disableElements = new ComposedElement(); - allElements = new ComposedElement(); - - int inputWidth = 40; - - ComposedElement anchorInputs = new ComposedElement(anchorXInput, anchorYInput, anchorZInput); - ComposedElement positionInputs = new ComposedElement(positionXInput, positionYInput, positionZInput); - ComposedElement orientationInputs = new ComposedElement(orientationXInput, orientationYInput, orientationZInput); - ComposedElement scaleInputs = new ComposedElement(scaleXInput, scaleYInput, scaleZInput); - ComposedElement opacityInputs = new ComposedElement(opacityInput); - ComposedElement numberInputs = new ComposedElement(anchorInputs, positionInputs, orientationInputs, scaleInputs, opacityInputs); - - for(int i = numberInputs.getParts().size()-1; i >= 0; i--) { - int yPos = this.height-5-10-(25*(numberInputs.getParts().size()-i)); - DelegatingElement button = keyframeButton(10, yPos, i); - GuiString label = new GuiString(35, yPos + 6, Color.WHITE, labelStrings[i]); - - ComposedElement child = (ComposedElement) numberInputs.getParts().get(i); - int x = 0; - for(GuiElement el : child.getParts()) { - GuiDraggingNumberInput dni = (GuiDraggingNumberInput)el; - dni.width = inputWidth; - dni.xPosition = 35+maxStringWidth+5 + (x*(inputWidth+5)); - dni.yPosition = yPos; - x++; - } - - child.addPart(button); - child.addPart(label); - - disableElements.addPart(child); - } - - int timelineX = anchorZInput.xPosition + anchorZInput.width + 5 - 1; - int timelineY = anchorZInput.yPosition - 1; - - int timelineWidth = this.width-10-timelineX + 2; - int timelineHeight = this.height-10-10-timelineY + 2; - - objectKeyframeTimeline = new GuiObjectKeyframeTimeline(timelineX, timelineY, timelineWidth, timelineHeight); - disableElements.addPart(objectKeyframeTimeline); - - GuiScrollbar timelineScrollbar = new GuiScrollbar(timelineX, this.height - 15, timelineWidth - 21) { - @Override - public void dragged() { - objectKeyframeTimeline.timeStart = (float) sliderPosition; - } - }; - - timelineScrollbar.size = objectKeyframeTimeline.zoom; - timelineScrollbar.sliderPosition = objectKeyframeTimeline.timeStart; - - disableElements.addPart(timelineScrollbar); - - GuiTexturedButton zoomInButton = GuiReplayOverlay.texturedButton(width - 28, this.height - 15, 40, 20, 9, new Runnable() { - @Override - public void run() { - objectKeyframeTimeline.zoom = Math.max(0.025f, objectKeyframeTimeline.zoom - ZOOM_STEPS); - } - }, "replaymod.gui.ingame.menu.zoomin"); - - GuiTexturedButton zoomOutButton = GuiReplayOverlay.texturedButton(width - 18, this.height - 15, 40, 30, 9, new Runnable() { - - @Override - public void run() { - objectKeyframeTimeline.zoom = Math.min(1f, objectKeyframeTimeline.zoom + ZOOM_STEPS); - objectKeyframeTimeline.timeStart = Math.min(objectKeyframeTimeline.timeStart, 1f - objectKeyframeTimeline.zoom); - } - }, "replaymod.gui.ingame.menu.zoomout"); - - disableElements.addPart(zoomInButton); - disableElements.addPart(zoomOutButton); - - objectList.xPosition = 11; - objectList.yPosition = 11; - objectList.width = width/2 - 11 - 5; - - int visibleElements = (int)((anchorXInput.yPosition-5 - objectList.yPosition)/14f); - objectList.setVisibleElements(visibleElements); - - allElements.addPart(objectList); - - nameInput.xPosition = width/2 + 5; - nameInput.yPosition = objectList.yPosition; - nameInput.width = objectList.width; - - disableElements.addPart(nameInput); - - dropdownLabel.positionX = (width/2)+5; - int strWidth = fontRendererObj.getStringWidth(I18n.format("replaymod.gui.assets.filechooser")+": "); - - assetDropdown.xPosition = dropdownLabel.positionX+strWidth+5; - assetDropdown.yPosition = objectList.yPosition+25; - dropdownLabel.positionY = assetDropdown.yPosition + 6; - assetDropdown.width = (objectList.width-strWidth-5); - - disableElements.addPart(dropdownLabel); - disableElements.addPart(assetDropdown); - - addButton.xPosition = nameInput.xPosition; - addButton.width = removeButton.width = nameInput.width/2 - 2; - removeButton.xPosition = addButton.xPosition + nameInput.width/2 + 2; - addButton.yPosition = removeButton.yPosition = objectList.yPosition+objectList.height-25; - - allElements.addPart(addButton); - disableElements.addPart(removeButton); - - allElements.addPart(disableElements); - - objectList.setSelectionIndex(objectList.getSelectionIndex()); // trigger an event for the SelectionListener - - initialized = true; - } - - private void saveOnQuit() { - List objects = objectList.getCopyOfElements(); - - if(objects.equals(initialObjects)) { - return; - } - - ReplayHandler.setCustomImageObjects(objects); - - } - - private void updateValuesForTransformation(Transformation transformation) { - anchorXInput.setValueQuietly(transformation.getAnchor().getX()); - anchorYInput.setValueQuietly(transformation.getAnchor().getY()); - anchorZInput.setValueQuietly(transformation.getAnchor().getZ()); - - positionXInput.setValueQuietly(transformation.getPosition().getX()); - positionYInput.setValueQuietly(transformation.getPosition().getY()); - positionZInput.setValueQuietly(transformation.getPosition().getZ()); - - orientationXInput.setValueQuietly(transformation.getOrientation().getX()); - orientationYInput.setValueQuietly(transformation.getOrientation().getY()); - orientationZInput.setValueQuietly(transformation.getOrientation().getZ()); - - scaleXInput.setValueQuietly(transformation.getScale().getX()); - scaleYInput.setValueQuietly(transformation.getScale().getY()); - scaleZInput.setValueQuietly(transformation.getScale().getZ()); - - opacityInput.setValueQuietly(transformation.getOpacity()); - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - this.drawDefaultBackground(); - - allElements.draw(mc, mouseX, mouseY); - - GlStateManager.enableBlend(); - - super.drawScreen(mouseX, mouseY, partialTicks); - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - Point mousePos = MouseUtils.getMousePos(); - allElements.buttonPressed(mc, mousePos.getX(), mousePos.getY(), typedChar, keyCode); - - CustomImageObject selectedObject = objectList.getElement(objectList.getSelectionIndex()); - if(selectedObject != null) { - selectedObject.setName(nameInput.getText().trim()); - } - - if(keyCode == Keyboard.KEY_DELETE) { - if(objectKeyframeTimeline.getSelectedKeyframe() != null) { - objectKeyframeTimeline.removeKeyframe(objectKeyframeTimeline.getSelectedKeyframeRow()); - } - } - - super.keyTyped(typedChar, keyCode); - } - - @Override - public void updateScreen() { - allElements.tick(mc); - super.updateScreen(); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - allElements.mouseClick(mc, mouseX, mouseY, mouseButton); - super.mouseClicked(mouseX, mouseY, mouseButton); - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, int mouseButton, long timeSinceLastClick) { - allElements.mouseDrag(mc, mouseX, mouseY, mouseButton); - super.mouseClickMove(mouseX, mouseY, mouseButton, timeSinceLastClick); - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int mouseButton) { - allElements.mouseRelease(mc, mouseX, mouseY, mouseButton); - super.mouseReleased(mouseX, mouseY, mouseButton); - } - - @Override - public void onGuiClosed() { - saveOnQuit(); - } - - public abstract class NumberInputGroup implements NumberValueChangeListener { - - KeyframeList toModify; - - public void setUnderlyingKeyframeList(KeyframeList toModify) { - this.toModify = toModify; - } - - } - - public class NumberValueInputGroup extends NumberInputGroup { - - public NumberValueInputGroup(KeyframeList toModify, GuiNumberInput input) { - this.toModify = toModify; - - input.addValueChangeListener(this); - } - - @Override - @SuppressWarnings("unchecked") - public void onValueChange(double value) { - NumberValue numberValue = new NumberValue(value); - - //if keyframe selected, overwrite its value - if(toModify.contains(objectKeyframeTimeline.getSelectedKeyframe())) { - objectKeyframeTimeline.getSelectedKeyframe().setValue(numberValue); - } else { - toModify.add(new Keyframe(objectKeyframeTimeline.cursorPosition, numberValue)); - } - } - } - - public class NumberPositionInputGroup extends NumberInputGroup { - - public NumberPositionInputGroup(KeyframeList toModify, GuiNumberInput xInput, GuiNumberInput yInput, GuiNumberInput zInput) { - this.toModify = toModify; - this.xInput = xInput; - this.yInput = yInput; - this.zInput = zInput; - - xInput.addValueChangeListener(this); - yInput.addValueChangeListener(this); - zInput.addValueChangeListener(this); - } - - private GuiNumberInput xInput, yInput, zInput; - - @Override - @SuppressWarnings("unchecked") - public void onValueChange(double value) { - Position position = new Position(xInput.getPreciseValue(), yInput.getPreciseValue(), zInput.getPreciseValue()); - - //if keyframe selected, overwrite its value - if(toModify.contains(objectKeyframeTimeline.getSelectedKeyframe())) { - objectKeyframeTimeline.getSelectedKeyframe().setValue(position); - } else { - toModify.add(new Keyframe(objectKeyframeTimeline.cursorPosition, position)); - } - } - } - - public class GuiObjectKeyframeTimeline extends GuiTimeline { - - private static final int KEYFRAME_X = 74; - private static final int KEYFRAME_Y = 35; - private static final int KEYFRAME_SIZE = 5; - - @Getter @Setter - private Transformations transformations; - - @Getter private int selectedKeyframeRow = -1; - @Getter private Keyframe selectedKeyframe = null; - - private boolean dragging = false; - - public GuiObjectKeyframeTimeline(int x, int y, int width, int height) { - super(x, y, width, height); - - this.zoom = 0.1; - this.timelineLength = 10 * 60 * 1000; - this.showMarkers = true; - - this.cursorPosition = ReplayHandler.getRealTimelineCursor(); - } - - @Override - public void draw(Minecraft mc, int mouseX, int mouseY) { - super.draw(mc, mouseX, mouseY); - - int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; - - long leftTime = Math.round(timeStart * timelineLength); - long rightTime = Math.round((timeStart + zoom) * timelineLength); - - double segmentLength = timelineLength * zoom; - - if(transformations != null) { - for(int i = 0; i < 5; i++) { - KeyframeList keyframes = transformations.getKeyframeListByID(i); - - //Draw Keyframe logos - for(Keyframe kf : keyframes) { - drawKeyframe(kf, (int)(i * (height / 5f)) + 10, bodyWidth, leftTime, rightTime, segmentLength); - } - } - } - } - - private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { - long positionInSegment = timestamp - leftTime; - double fractionOfSegment = positionInSegment / segmentLength; - return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); - } - - private void drawKeyframe(Keyframe kf, int y, int bodyWidth, long leftTime, long rightTime, double segmentLength) { - if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { - int textureX = KEYFRAME_X; - int textureY = KEYFRAME_Y; - y = positionY+y; - - int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); - - if (kf == selectedKeyframe) { - textureX += KEYFRAME_SIZE; - } - - rect(keyframeX - 2, y, textureX, textureY, 5, 5); - } - } - - @Override - public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { - if(!enabled) return false; - super.mouseClick(mc, mouseX, mouseY, button); - int time = (int) getTimeAt(mouseX, mouseY); - if(time != -1) { - boolean clicked = false; - - int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); - - if(transformations != null) { - for(int i = 0; i < 5; i++) { - int upper = positionY + (int)(i * (height / 5f)) + 10; - int lower = upper + KEYFRAME_SIZE; - if(mouseY >= upper && mouseY <= lower) { - KeyframeList keyframes = transformations.getKeyframeListByID(i); - - selectedKeyframe = keyframes.getClosestKeyframeForTimestamp(time, tolerance); - - if(selectedKeyframe != null) { - selectedKeyframeRow = i; - } else { - selectedKeyframeRow = -1; - } - - clicked = true; - } - } - } - - if(!clicked) { - selectedKeyframe = null; - selectedKeyframeRow = -1; - } - - cursorPosition = time; - updateValuesForTransformation(getTransformations().getTransformationForTimestamp(cursorPosition)); - - dragging = true; - return true; - } - - return false; - } - - @Override - public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { - if(!enabled) return; - super.mouseDrag(mc, mouseX, mouseY, button); - if(dragging) { - int time = (int) getTimeAt(mouseX, mouseY); - if(time != -1) { - if(selectedKeyframe != null) { - selectedKeyframe.setRealTimestamp(time); - } - cursorPosition = time; - updateValuesForTransformation(getTransformations().getTransformationForTimestamp(cursorPosition)); - } - } - } - - @Override - public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { - if(!enabled) return; - super.mouseRelease(mc, mouseX, mouseY, button); - this.dragging = false; - } - - @SuppressWarnings("unchecked") - public void addKeyframe(int line) { - CustomImageObject currentObject = objectList.getElement(objectList.getSelectionIndex()); - if(currentObject != null) { - KeyframeList list = currentObject.getTransformations().getKeyframeListByID(line); - int timestamp = objectKeyframeTimeline.cursorPosition; - - Keyframe kf = null; - - switch(line) { - case 0: - - kf = new Keyframe(timestamp, new Position( - anchorXInput.getPreciseValue(), - anchorYInput.getPreciseValue(), - anchorZInput.getPreciseValue())); - break; - case 1: - kf = new Keyframe(timestamp, new Position( - positionXInput.getPreciseValue(), - positionYInput.getPreciseValue(), - positionZInput.getPreciseValue())); - break; - case 2: - kf = new Keyframe(timestamp, new Position( - orientationXInput.getPreciseValue(), - orientationYInput.getPreciseValue(), - orientationZInput.getPreciseValue())); - break; - case 3: - kf = new Keyframe(timestamp, new Position( - scaleXInput.getPreciseValue(), - scaleYInput.getPreciseValue(), - scaleZInput.getPreciseValue())); - break; - case 4: - kf = new Keyframe(timestamp, new NumberValue( - opacityInput.getPreciseValue() - )); - break; - } - - list.add(kf); - - selectedKeyframe = kf; - selectedKeyframeRow = line; - } - } - - public void removeKeyframe(int line) { - if(selectedKeyframeRow == line) { - CustomImageObject currentObject = objectList.getElement(objectList.getSelectionIndex()); - if(currentObject != null) { - KeyframeList list = currentObject.getTransformations().getKeyframeListByID(line); - list.remove(selectedKeyframe); - selectedKeyframe = null; - selectedKeyframeRow = -1; - } - } - } - } +public class GuiObjectManager extends GuiScreen { + // TODO +// +// private boolean initialized = false; +// +// private GuiEntryList objectList; +// private GuiAdvancedButton addButton, removeButton; +// +// private GuiAdvancedTextField nameInput; +// +// private GuiString dropdownLabel; +// private GuiDropdown> assetDropdown; +// +// private final List initialObjects = ReplayHandler.getCustomImageObjects(); +// +// private GuiDraggingNumberInput anchorXInput, anchorYInput, anchorZInput; +// private GuiDraggingNumberInput positionXInput, positionYInput, positionZInput; +// private GuiDraggingNumberInput orientationXInput, orientationYInput, orientationZInput; +// private GuiDraggingNumberInput scaleXInput, scaleYInput, scaleZInput; +// private GuiDraggingNumberInput opacityInput; +// +// private NumberPositionInputGroup anchorNumberInputs, positionNumberInputs, orientationNumberInputs, scaleNumberInputs; +// private NumberValueInputGroup opacityNumberInputs; +// +// @Getter +// private GuiObjectKeyframeTimeline objectKeyframeTimeline; +// +// private ComposedElement disableElements, allElements; +// +// private static final int KEYFRAME_BUTTON_X = 80; +// private static final int KEYFRAME_BUTTON_Y = 40; +// +// private static final float ZOOM_STEPS = 0.05f; +// +// private DelegatingElement keyframeButton(final int x, final int y, final int line) { +// return new DelegatingElement() { +// +// private GuiTexturedButton normal = new GuiTexturedButton(0, x, y, 20, 20, +// GuiReplayOverlay.replay_gui, KEYFRAME_BUTTON_X, KEYFRAME_BUTTON_Y, +// GuiReplayOverlay.TEXTURE_SIZE, GuiReplayOverlay.TEXTURE_SIZE, new Runnable() { +// @Override +// public void run() { +// objectKeyframeTimeline.addKeyframe(line); +// } +// }, +// null); +// +// private GuiTexturedButton selected = new GuiTexturedButton(0, x, y, 20, 20, +// GuiReplayOverlay.replay_gui, KEYFRAME_BUTTON_X, KEYFRAME_BUTTON_Y+20, +// GuiReplayOverlay.TEXTURE_SIZE, GuiReplayOverlay.TEXTURE_SIZE, new Runnable() { +// @Override +// public void run() { +// objectKeyframeTimeline.removeKeyframe(line); +// } +// }, +// null); +// +// @Override +// public GuiElement delegate() { +// if(objectKeyframeTimeline.getSelectedKeyframeRow() == line) { +// return selected; +// } else { +// return normal; +// } +// } +// +// @Override +// public void setElementEnabled(boolean enabled) { +// selected.setElementEnabled(enabled); +// normal.setElementEnabled(enabled); +// } +// }; +// } +// +// @Override +// public void initGui() { +// if(!initialized) { +// anchorXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); +// anchorYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); +// anchorZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true, "", 0.1); +// anchorNumberInputs = new NumberPositionInputGroup(null, anchorXInput, anchorYInput, anchorZInput); +// +// positionXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// positionYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// positionZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// positionNumberInputs = new NumberPositionInputGroup(null, positionXInput, positionYInput, positionZInput); +// +// orientationXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// orientationYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// orientationZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 0d, true); +// orientationNumberInputs = new NumberPositionInputGroup(null, orientationXInput, orientationYInput, orientationZInput); +// +// scaleXInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); +// scaleYInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); +// scaleZInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, null, null, 100d, true, "%", 0.5); +// scaleNumberInputs = new NumberPositionInputGroup(null, scaleXInput, scaleYInput, scaleZInput); +// +// opacityInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 50, 0d, 100d, 100d, true, "%", 0.5); +// opacityNumberInputs = new NumberValueInputGroup(null, opacityInput); +// +// dropdownLabel = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.assets.filechooser")+": "); +// assetDropdown = new GuiDropdown>(fontRendererObj, 0, 0, 0, 5); +// List assets = ReplayHandler.getAssetRepository().getCopyOfReplayAssets(); +// Collections.sort(assets, new Comparator() { +// @Override +// public int compare(ReplayAsset o1, ReplayAsset o2) { +// return o1.getAssetName().compareTo(o2.getAssetName()); +// } +// }); +// if(assets.isEmpty()) { +// assetDropdown.addElement(new GuiEntryListValueEntry(I18n.format("replaymod.gui.assets.emptylist"), null)); +// } else { +// assetDropdown.addElement(new GuiEntryListValueEntry(I18n.format("replaymod.gui.assets.noselection"), null)); +// for(ReplayAsset asset : assets) { +// assetDropdown.addElement(new GuiEntryListValueEntry( +// asset.getDisplayString(), ReplayHandler.getAssetRepository().getUUIDForAsset(asset))); +// } +// } +// +// objectList = new GuiEntryList(fontRendererObj, 0, 0, 0, 0); +// objectList.setEmptyMessage(I18n.format("replaymod.gui.objects.empty")); +// +// addButton = new GuiAdvancedButton(0, 0, 0, 20, I18n.format("replaymod.gui.add"), new Runnable() { +// @Override +// public void run() { +// try { +// CustomImageObject customImageObject = new CustomImageObject(I18n.format("replaymod.gui.objects.defaultname"), null); +// +// Position defaultPosition = new Position(mc.getRenderViewEntity()); +// customImageObject.getTransformations().setDefaultPosition(defaultPosition); +// +// objectList.addElement(customImageObject); +// } catch(IOException e) { +// e.printStackTrace(); +// } +// } +// }, null); +// +// removeButton = new GuiAdvancedButton(0, 0, 0, 20, I18n.format("replaymod.gui.remove"), new Runnable() { +// @Override +// public void run() { +// if(objectList.getElement(objectList.getSelectionIndex()) != null) +// objectList.removeElement(objectList.getSelectionIndex()); +// } +// }, null); +// +// nameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 0, 20); +// nameInput.hint = I18n.format("replaymod.gui.objects.properties.name"); +// +// for(CustomImageObject customImageObject : initialObjects) { +// try { +// objectList.addElement(customImageObject.copy()); +// } catch(IOException ioe) { +// ioe.printStackTrace(); +// } +// } +// +// objectList.addSelectionListener(new SelectionListener() { +// @Override +// public void onSelectionChanged(int selectionIndex) { +// CustomImageObject selectedObject = objectList.getElement(selectionIndex); +// if(selectedObject != null) { +// disableElements.setElementEnabled(true); +// +// nameInput.setText(selectedObject.getName()); +// +// //setting the dropdown value +// int sel = 0; +// if(selectedObject.getLinkedAsset() != null) { +// int i = 0; +// for(GuiEntryListValueEntry entry : assetDropdown.getAllElements()) { +// if(selectedObject.getLinkedAsset().equals(entry.getValue())) { +// sel = i; +// break; +// } +// i++; +// } +// } +// +// assetDropdown.setSelectionIndexQuietly(sel); +// +// Transformations transformations = selectedObject.getTransformations(); +// +// objectKeyframeTimeline.setTransformations(transformations); +// +// anchorNumberInputs.setUnderlyingKeyframeList(transformations.getAnchorKeyframes()); +// positionNumberInputs.setUnderlyingKeyframeList(transformations.getPositionKeyframes()); +// orientationNumberInputs.setUnderlyingKeyframeList(transformations.getOrientationKeyframes()); +// scaleNumberInputs.setUnderlyingKeyframeList(transformations.getScaleKeyframes()); +// opacityNumberInputs.setUnderlyingKeyframeList(transformations.getOpacityKeyframes()); +// +// updateValuesForTransformation(objectKeyframeTimeline.getTransformations().getTransformationForTimestamp(objectKeyframeTimeline.cursorPosition)); +// } else { +// disableElements.setElementEnabled(false); +// } +// } +// }); +// +// assetDropdown.addSelectionListener(new SelectionListener() { +// @Override +// public void onSelectionChanged(int selectionIndex) { +// CustomImageObject selectedObject = objectList.getElement(objectList.getSelectionIndex()); +// GuiEntryListValueEntry entry = assetDropdown.getElement(selectionIndex); +// if(selectedObject != null && entry != null) { +// try { +// selectedObject.setLinkedAsset(entry.getValue()); +// } catch(IOException e) { +// e.printStackTrace(); +// } +// } +// } +// }); +// } +// +// String[] labelStrings = new String[] { +// I18n.format("replaymod.gui.objects.properties.anchor"), +// I18n.format("replaymod.gui.objects.properties.position"), +// I18n.format("replaymod.gui.objects.properties.orientation"), +// I18n.format("replaymod.gui.objects.properties.scale"), +// I18n.format("replaymod.gui.objects.properties.opacity"), +// }; +// +// int maxStringWidth = 0; +// for(String label : labelStrings) { +// int stringWidth = fontRendererObj.getStringWidth(label); +// if(stringWidth > maxStringWidth) { +// maxStringWidth = stringWidth; +// } +// } +// +// disableElements = new ComposedElement(); +// allElements = new ComposedElement(); +// +// int inputWidth = 40; +// +// ComposedElement anchorInputs = new ComposedElement(anchorXInput, anchorYInput, anchorZInput); +// ComposedElement positionInputs = new ComposedElement(positionXInput, positionYInput, positionZInput); +// ComposedElement orientationInputs = new ComposedElement(orientationXInput, orientationYInput, orientationZInput); +// ComposedElement scaleInputs = new ComposedElement(scaleXInput, scaleYInput, scaleZInput); +// ComposedElement opacityInputs = new ComposedElement(opacityInput); +// ComposedElement numberInputs = new ComposedElement(anchorInputs, positionInputs, orientationInputs, scaleInputs, opacityInputs); +// +// for(int i = numberInputs.getParts().size()-1; i >= 0; i--) { +// int yPos = this.height-5-10-(25*(numberInputs.getParts().size()-i)); +// DelegatingElement button = keyframeButton(10, yPos, i); +// GuiString label = new GuiString(35, yPos + 6, Color.WHITE, labelStrings[i]); +// +// ComposedElement child = (ComposedElement) numberInputs.getParts().get(i); +// int x = 0; +// for(GuiElement el : child.getParts()) { +// GuiDraggingNumberInput dni = (GuiDraggingNumberInput)el; +// dni.width = inputWidth; +// dni.xPosition = 35+maxStringWidth+5 + (x*(inputWidth+5)); +// dni.yPosition = yPos; +// x++; +// } +// +// child.addPart(button); +// child.addPart(label); +// +// disableElements.addPart(child); +// } +// +// int timelineX = anchorZInput.xPosition + anchorZInput.width + 5 - 1; +// int timelineY = anchorZInput.yPosition - 1; +// +// int timelineWidth = this.width-10-timelineX + 2; +// int timelineHeight = this.height-10-10-timelineY + 2; +// +// objectKeyframeTimeline = new GuiObjectKeyframeTimeline(timelineX, timelineY, timelineWidth, timelineHeight); +// disableElements.addPart(objectKeyframeTimeline); +// +// GuiScrollbar timelineScrollbar = new GuiScrollbar(timelineX, this.height - 15, timelineWidth - 21) { +// @Override +// public void dragged() { +// objectKeyframeTimeline.timeStart = (float) sliderPosition; +// } +// }; +// +// timelineScrollbar.size = objectKeyframeTimeline.zoom; +// timelineScrollbar.sliderPosition = objectKeyframeTimeline.timeStart; +// +// disableElements.addPart(timelineScrollbar); +// +// GuiTexturedButton zoomInButton = GuiReplayOverlay.texturedButton(width - 28, this.height - 15, 40, 20, 9, new Runnable() { +// @Override +// public void run() { +// objectKeyframeTimeline.zoom = Math.max(0.025f, objectKeyframeTimeline.zoom - ZOOM_STEPS); +// } +// }, "replaymod.gui.ingame.menu.zoomin"); +// +// GuiTexturedButton zoomOutButton = GuiReplayOverlay.texturedButton(width - 18, this.height - 15, 40, 30, 9, new Runnable() { +// +// @Override +// public void run() { +// objectKeyframeTimeline.zoom = Math.min(1f, objectKeyframeTimeline.zoom + ZOOM_STEPS); +// objectKeyframeTimeline.timeStart = Math.min(objectKeyframeTimeline.timeStart, 1f - objectKeyframeTimeline.zoom); +// } +// }, "replaymod.gui.ingame.menu.zoomout"); +// +// disableElements.addPart(zoomInButton); +// disableElements.addPart(zoomOutButton); +// +// objectList.xPosition = 11; +// objectList.yPosition = 11; +// objectList.width = width/2 - 11 - 5; +// +// int visibleElements = (int)((anchorXInput.yPosition-5 - objectList.yPosition)/14f); +// objectList.setVisibleElements(visibleElements); +// +// allElements.addPart(objectList); +// +// nameInput.xPosition = width/2 + 5; +// nameInput.yPosition = objectList.yPosition; +// nameInput.width = objectList.width; +// +// disableElements.addPart(nameInput); +// +// dropdownLabel.positionX = (width/2)+5; +// int strWidth = fontRendererObj.getStringWidth(I18n.format("replaymod.gui.assets.filechooser")+": "); +// +// assetDropdown.xPosition = dropdownLabel.positionX+strWidth+5; +// assetDropdown.yPosition = objectList.yPosition+25; +// dropdownLabel.positionY = assetDropdown.yPosition + 6; +// assetDropdown.width = (objectList.width-strWidth-5); +// +// disableElements.addPart(dropdownLabel); +// disableElements.addPart(assetDropdown); +// +// addButton.xPosition = nameInput.xPosition; +// addButton.width = removeButton.width = nameInput.width/2 - 2; +// removeButton.xPosition = addButton.xPosition + nameInput.width/2 + 2; +// addButton.yPosition = removeButton.yPosition = objectList.yPosition+objectList.height-25; +// +// allElements.addPart(addButton); +// disableElements.addPart(removeButton); +// +// allElements.addPart(disableElements); +// +// objectList.setSelectionIndex(objectList.getSelectionIndex()); // trigger an event for the SelectionListener +// +// initialized = true; +// } +// +// private void saveOnQuit() { +// List objects = objectList.getCopyOfElements(); +// +// if(objects.equals(initialObjects)) { +// return; +// } +// +// ReplayHandler.setCustomImageObjects(objects); +// +// } +// +// private void updateValuesForTransformation(Transformation transformation) { +// anchorXInput.setValueQuietly(transformation.getAnchor().getX()); +// anchorYInput.setValueQuietly(transformation.getAnchor().getY()); +// anchorZInput.setValueQuietly(transformation.getAnchor().getZ()); +// +// positionXInput.setValueQuietly(transformation.getPosition().getX()); +// positionYInput.setValueQuietly(transformation.getPosition().getY()); +// positionZInput.setValueQuietly(transformation.getPosition().getZ()); +// +// orientationXInput.setValueQuietly(transformation.getOrientation().getX()); +// orientationYInput.setValueQuietly(transformation.getOrientation().getY()); +// orientationZInput.setValueQuietly(transformation.getOrientation().getZ()); +// +// scaleXInput.setValueQuietly(transformation.getScale().getX()); +// scaleYInput.setValueQuietly(transformation.getScale().getY()); +// scaleZInput.setValueQuietly(transformation.getScale().getZ()); +// +// opacityInput.setValueQuietly(transformation.getOpacity()); +// } +// +// @Override +// public void drawScreen(int mouseX, int mouseY, float partialTicks) { +// this.drawDefaultBackground(); +// +// allElements.draw(mc, mouseX, mouseY); +// +// GlStateManager.enableBlend(); +// +// super.drawScreen(mouseX, mouseY, partialTicks); +// } +// +// @Override +// protected void keyTyped(char typedChar, int keyCode) throws IOException { +// Point mousePos = MouseUtils.getMousePos(); +// allElements.buttonPressed(mc, mousePos.getX(), mousePos.getY(), typedChar, keyCode); +// +// CustomImageObject selectedObject = objectList.getElement(objectList.getSelectionIndex()); +// if(selectedObject != null) { +// selectedObject.setName(nameInput.getText().trim()); +// } +// +// if(keyCode == Keyboard.KEY_DELETE) { +// if(objectKeyframeTimeline.getSelectedKeyframe() != null) { +// objectKeyframeTimeline.removeKeyframe(objectKeyframeTimeline.getSelectedKeyframeRow()); +// } +// } +// +// super.keyTyped(typedChar, keyCode); +// } +// +// @Override +// public void updateScreen() { +// allElements.tick(mc); +// super.updateScreen(); +// } +// +// @Override +// protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { +// allElements.mouseClick(mc, mouseX, mouseY, mouseButton); +// super.mouseClicked(mouseX, mouseY, mouseButton); +// } +// +// @Override +// protected void mouseClickMove(int mouseX, int mouseY, int mouseButton, long timeSinceLastClick) { +// allElements.mouseDrag(mc, mouseX, mouseY, mouseButton); +// super.mouseClickMove(mouseX, mouseY, mouseButton, timeSinceLastClick); +// } +// +// @Override +// protected void mouseReleased(int mouseX, int mouseY, int mouseButton) { +// allElements.mouseRelease(mc, mouseX, mouseY, mouseButton); +// super.mouseReleased(mouseX, mouseY, mouseButton); +// } +// +// @Override +// public void onGuiClosed() { +// saveOnQuit(); +// } +// +// public abstract class NumberInputGroup implements NumberValueChangeListener { +// +// KeyframeList toModify; +// +// public void setUnderlyingKeyframeList(KeyframeList toModify) { +// this.toModify = toModify; +// } +// +// } +// +// public class NumberValueInputGroup extends NumberInputGroup { +// +// public NumberValueInputGroup(KeyframeList toModify, GuiNumberInput input) { +// this.toModify = toModify; +// +// input.addValueChangeListener(this); +// } +// +// @Override +// @SuppressWarnings("unchecked") +// public void onValueChange(double value) { +// NumberValue numberValue = new NumberValue(value); +// +// //if keyframe selected, overwrite its value +// if(toModify.contains(objectKeyframeTimeline.getSelectedKeyframe())) { +// objectKeyframeTimeline.getSelectedKeyframe().setValue(numberValue); +// } else { +// toModify.add(new Keyframe(objectKeyframeTimeline.cursorPosition, numberValue)); +// } +// } +// } +// +// public class NumberPositionInputGroup extends NumberInputGroup { +// +// public NumberPositionInputGroup(KeyframeList toModify, GuiNumberInput xInput, GuiNumberInput yInput, GuiNumberInput zInput) { +// this.toModify = toModify; +// this.xInput = xInput; +// this.yInput = yInput; +// this.zInput = zInput; +// +// xInput.addValueChangeListener(this); +// yInput.addValueChangeListener(this); +// zInput.addValueChangeListener(this); +// } +// +// private GuiNumberInput xInput, yInput, zInput; +// +// @Override +// @SuppressWarnings("unchecked") +// public void onValueChange(double value) { +// Position position = new Position(xInput.getPreciseValue(), yInput.getPreciseValue(), zInput.getPreciseValue()); +// +// //if keyframe selected, overwrite its value +// if(toModify.contains(objectKeyframeTimeline.getSelectedKeyframe())) { +// objectKeyframeTimeline.getSelectedKeyframe().setValue(position); +// } else { +// toModify.add(new Keyframe(objectKeyframeTimeline.cursorPosition, position)); +// } +// } +// } +// +// public class GuiObjectKeyframeTimeline extends GuiTimeline { +// +// private static final int KEYFRAME_X = 74; +// private static final int KEYFRAME_Y = 35; +// private static final int KEYFRAME_SIZE = 5; +// +// @Getter @Setter +// private Transformations transformations; +// +// @Getter private int selectedKeyframeRow = -1; +// @Getter private Keyframe selectedKeyframe = null; +// +// private boolean dragging = false; +// +// public GuiObjectKeyframeTimeline(int x, int y, int width, int height) { +// super(x, y, width, height); +// +// this.zoom = 0.1; +// this.timelineLength = 10 * 60 * 1000; +// this.showMarkers = true; +// +// this.cursorPosition = ReplayHandler.getRealTimelineCursor(); +// } +// +// @Override +// public void draw(Minecraft mc, int mouseX, int mouseY) { +// super.draw(mc, mouseX, mouseY); +// +// int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; +// +// long leftTime = Math.round(timeStart * timelineLength); +// long rightTime = Math.round((timeStart + zoom) * timelineLength); +// +// double segmentLength = timelineLength * zoom; +// +// if(transformations != null) { +// for(int i = 0; i < 5; i++) { +// KeyframeList keyframes = transformations.getKeyframeListByID(i); +// +// //Draw Keyframe logos +// for(Keyframe kf : keyframes) { +// drawKeyframe(kf, (int)(i * (height / 5f)) + 10, bodyWidth, leftTime, rightTime, segmentLength); +// } +// } +// } +// } +// +// private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { +// long positionInSegment = timestamp - leftTime; +// double fractionOfSegment = positionInSegment / segmentLength; +// return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); +// } +// +// private void drawKeyframe(Keyframe kf, int y, int bodyWidth, long leftTime, long rightTime, double segmentLength) { +// if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { +// int textureX = KEYFRAME_X; +// int textureY = KEYFRAME_Y; +// y = positionY+y; +// +// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); +// +// if (kf == selectedKeyframe) { +// textureX += KEYFRAME_SIZE; +// } +// +// rect(keyframeX - 2, y, textureX, textureY, 5, 5); +// } +// } +// +// @Override +// public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { +// if(!enabled) return false; +// super.mouseClick(mc, mouseX, mouseY, button); +// int time = (int) getTimeAt(mouseX, mouseY); +// if(time != -1) { +// boolean clicked = false; +// +// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); +// +// if(transformations != null) { +// for(int i = 0; i < 5; i++) { +// int upper = positionY + (int)(i * (height / 5f)) + 10; +// int lower = upper + KEYFRAME_SIZE; +// if(mouseY >= upper && mouseY <= lower) { +// KeyframeList keyframes = transformations.getKeyframeListByID(i); +// +// selectedKeyframe = keyframes.getClosestKeyframeForTimestamp(time, tolerance); +// +// if(selectedKeyframe != null) { +// selectedKeyframeRow = i; +// } else { +// selectedKeyframeRow = -1; +// } +// +// clicked = true; +// } +// } +// } +// +// if(!clicked) { +// selectedKeyframe = null; +// selectedKeyframeRow = -1; +// } +// +// cursorPosition = time; +// updateValuesForTransformation(getTransformations().getTransformationForTimestamp(cursorPosition)); +// +// dragging = true; +// return true; +// } +// +// return false; +// } +// +// @Override +// public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { +// if(!enabled) return; +// super.mouseDrag(mc, mouseX, mouseY, button); +// if(dragging) { +// int time = (int) getTimeAt(mouseX, mouseY); +// if(time != -1) { +// if(selectedKeyframe != null) { +// selectedKeyframe.setRealTimestamp(time); +// } +// cursorPosition = time; +// updateValuesForTransformation(getTransformations().getTransformationForTimestamp(cursorPosition)); +// } +// } +// } +// +// @Override +// public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { +// if(!enabled) return; +// super.mouseRelease(mc, mouseX, mouseY, button); +// this.dragging = false; +// } +// +// @SuppressWarnings("unchecked") +// public void addKeyframe(int line) { +// CustomImageObject currentObject = objectList.getElement(objectList.getSelectionIndex()); +// if(currentObject != null) { +// KeyframeList list = currentObject.getTransformations().getKeyframeListByID(line); +// int timestamp = objectKeyframeTimeline.cursorPosition; +// +// Keyframe kf = null; +// +// switch(line) { +// case 0: +// +// kf = new Keyframe(timestamp, new Position( +// anchorXInput.getPreciseValue(), +// anchorYInput.getPreciseValue(), +// anchorZInput.getPreciseValue())); +// break; +// case 1: +// kf = new Keyframe(timestamp, new Position( +// positionXInput.getPreciseValue(), +// positionYInput.getPreciseValue(), +// positionZInput.getPreciseValue())); +// break; +// case 2: +// kf = new Keyframe(timestamp, new Position( +// orientationXInput.getPreciseValue(), +// orientationYInput.getPreciseValue(), +// orientationZInput.getPreciseValue())); +// break; +// case 3: +// kf = new Keyframe(timestamp, new Position( +// scaleXInput.getPreciseValue(), +// scaleYInput.getPreciseValue(), +// scaleZInput.getPreciseValue())); +// break; +// case 4: +// kf = new Keyframe(timestamp, new NumberValue( +// opacityInput.getPreciseValue() +// )); +// break; +// } +// +// list.add(kf); +// +// selectedKeyframe = kf; +// selectedKeyframeRow = line; +// } +// } +// +// public void removeKeyframe(int line) { +// if(selectedKeyframeRow == line) { +// CustomImageObject currentObject = objectList.getElement(objectList.getSelectionIndex()); +// if(currentObject != null) { +// KeyframeList list = currentObject.getTransformations().getKeyframeListByID(line); +// list.remove(selectedKeyframe); +// selectedKeyframe = null; +// selectedKeyframeRow = -1; +// } +// } +// } +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java index b2cecf7d..318f65e9 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java @@ -1,347 +1,314 @@ package eu.crushedpixel.replaymod.gui; -import com.mojang.realmsclient.util.Pair; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.holders.PlayerVisibility; -import eu.crushedpixel.replaymod.registry.PlayerHandler; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.utils.ReplayFile; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; -import eu.crushedpixel.replaymod.utils.SkinProvider; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EnumPlayerModelParts; -import net.minecraft.potion.Potion; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.client.config.GuiCheckBox; -import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; -import java.awt.*; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.List; - -public class GuiPlayerOverview extends GuiScreen implements GuiReplayOverlay.NoOverlay { +public class GuiPlayerOverview extends GuiScreen { public static boolean defaultSave = false; - private List> players; - private List checkBoxes; - - private GuiCheckBox hideAllBox, showAllBox; - private GuiCheckBox rememberHidden; - - private boolean initialized = false; - - private int playerCount; - private int upperPlayer = 0; - - private int lowerBound; - - private boolean drag = false; - private int lastY = 0; - private int fitting = 0; - - private final Minecraft mc = Minecraft.getMinecraft(); - - private final String screenTitle = I18n.format("replaymod.input.playeroverview"); - - private final Set initialHiddenPlayers; - - public GuiPlayerOverview(List players) { - initialHiddenPlayers = new HashSet(PlayerHandler.getHiddenPlayers()); - - Collections.sort(players, new PlayerComparator()); - - this.players = new ArrayList>(); - this.checkBoxes = new ArrayList(); - - for(final EntityPlayer p : players) { - final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID()); - this.players.add(Pair.of(p, loc)); - } - - playerCount = players.size(); - - ReplayMod.replaySender.setReplaySpeed(0); - } - - private boolean isSpectator(EntityPlayer e) { - return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null; - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) - throws IOException { - - if(fitting < playerCount) { - float visiblePerc = (float) fitting / (float) playerCount; - - int h = this.height - 32 - 32; - int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h); - - int lower = Math.round(32 + offset + (h * visiblePerc)) - 2; - - int k2 = (int) (this.width * 0.3); - - if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) { - lastY = mouseY; - drag = true; - return; - } - } - int k2 = (int) (this.width * 0.3); - - if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) { - int off = mouseY - upperBound; - int p = (off / 21) + upperPlayer; - ReplayHandler.spectateEntity(players.get(p).first()); - mc.displayGuiScreen(null); - } - - super.mouseClicked(mouseX, mouseY, mouseButton); - } - - @Override - protected void mouseClickMove(int mouseX, int mouseY, - int clickedMouseButton, long timeSinceLastClick) { - - if(drag) { - float step = 1f / (float) playerCount; - - int diff = mouseY - lastY; - int h = this.height - 32 - 32; - - float percDiff = (float) diff / (float) h; - if(Math.abs(percDiff) > Math.abs(step)) { - int s = (int) (percDiff / step); - lastY = mouseY; - upperPlayer += s; - if(upperPlayer > playerCount - fitting) { - upperPlayer = playerCount - fitting; - } else if(upperPlayer < 0) { - upperPlayer = 0; - } - } - } - - super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - drag = false; - - for(GuiCheckBox checkBox : checkBoxes) { - checkBox.mouseReleased(mouseX, mouseY); - } - - super.mouseReleased(mouseX, mouseY, state); - } - - @Override - public void initGui() { - upperPlayer = 0; - lowerBound = this.height - 10; - - @SuppressWarnings("unchecked") - List buttonList = this.buttonList; - - int i = 0; - for(GuiCheckBox checkBox : checkBoxes) { - checkBox.xPosition = (int)(this.width*0.7)-5; - buttonList.add(checkBox); - i++; - if(i >= fitting) break; - } - - if(!initialized) { - hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false); - showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true); - rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave); - } - - hideAllBox.xPosition = (int)(this.width*0.7)-5; - showAllBox.xPosition = (int)(this.width*0.7)-20; - hideAllBox.yPosition = showAllBox.yPosition = 45; - - rememberHidden.xPosition = (int)(this.width*0.3); - rememberHidden.yPosition = 45; - - buttonList.add(hideAllBox); - buttonList.add(showAllBox); - buttonList.add(rememberHidden); - - initialized = true; - } - - @Override - protected void actionPerformed(GuiButton button) throws IOException { - if(button == showAllBox) { - showAllBox.setIsChecked(true); - for(Pair p : players) { - PlayerHandler.showPlayer(p.first()); - } - } else if(button == hideAllBox) { - hideAllBox.setIsChecked(false); - for(Pair p : players) { - PlayerHandler.hidePlayer(p.first()); - } - } - - if(!(button instanceof GuiCheckBox)) return; - if(button.id >= fitting) return; - if(!checkBoxes.contains(button)) return; - PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked()); - } - - private static final int upperBound = 65; - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB()); - int k2 = (int)(this.width * 0.3); - int l2 = upperBound; - - drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680); - - drawString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.spectate"), k2 - 10, 30, Color.WHITE.getRGB()); - - String visibleString = I18n.format("replaymod.gui.playeroverview.visible"); - drawString(fontRendererObj, visibleString, (int) (this.width * 0.7) + 10 - fontRendererObj.getStringWidth(visibleString), 30, Color.WHITE.getRGB()); - - fitting = 0; - - int sk = 0; - for(Pair p : players) { - if(sk < upperPlayer) { - sk++; - continue; - } - boolean spec = isSpectator(p.first()); - - this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2), - spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB()); - - mc.getTextureManager().bindTexture(p.second()); - - drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F); - if(p.first().func_175148_a(EnumPlayerModelParts.HAT)) - Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F); - - GlStateManager.resetColor(); - if(fitting >= checkBoxes.size()) { - checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true)); - @SuppressWarnings("unchecked") - List buttonList = this.buttonList; - buttonList.add(checkBoxes.get(checkBoxes.size() - 1)); - } - checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID())); - - l2 += 16 + 5; - fitting++; - if(l2 + 32 > lowerBound) { - break; - } - } - - int dw = Mouse.getDWheel(); - if(dw > 0) { - dw = -1; - } else if(dw < 0) { - dw = 1; - } - - upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0); - - if(fitting < playerCount) { - float visiblePerc = ((float) fitting) / playerCount; - int barHeight = (int) (visiblePerc * (height - 32 - 32)); - - float posPerc = ((float) upperPlayer) / playerCount; - int barY = (int) (posPerc * (height - 32 - 32)); - - drawRect(k2 - 18, upperBound - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB()); - drawRect(k2 - 16, upperBound+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB()); - } - - int i = 0; - for(GuiCheckBox checkBox : checkBoxes) { - checkBox.drawButton(mc, mouseX, mouseY); - i++; - if(i >= fitting) break; - } - - hideAllBox.drawButton(mc, mouseX, mouseY); - showAllBox.drawButton(mc, mouseX, mouseY); - rememberHidden.drawButton(mc, mouseX, mouseY); - - if(hideAllBox.isMouseOver()) { - ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.hideall"), this, Color.WHITE); - } - - if(showAllBox.isMouseOver()) { - ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.showall"), this, Color.WHITE); - } - - if(rememberHidden.isMouseOver()) { - ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.remembersettings.description"), this, Color.WHITE); - } - - //this is necessary to reset the GL parameters for further GUI rendering - GlStateManager.enableBlend(); - } - - private PlayerVisibility getVisibilityInstance() { - Set hidden = PlayerHandler.getHiddenPlayers(); - return new PlayerVisibility(hidden.toArray(new UUID[hidden.size()])); - } - - - private void saveOnQuit() { - if(rememberHidden.isChecked()) { - if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return; - try { - File f = File.createTempFile(ReplayFile.ENTRY_VISIBILITY, "json"); - ReplayFileIO.write(getVisibilityInstance(), f); - ReplayMod.replayFileAppender.registerModifiedFile(f, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); - } catch(Exception e) { - e.printStackTrace(); - } - } else { - if(initialHiddenPlayers.isEmpty()) return; - ReplayMod.replayFileAppender.registerModifiedFile(null, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); - } - } - - @Override - public void keyTyped(char typedChar, int keyCode) throws IOException { - if(keyCode == Keyboard.KEY_ESCAPE) { - saveOnQuit(); - super.keyTyped(typedChar, keyCode); - } - } - - private class PlayerComparator implements Comparator { - - @Override - public int compare(EntityPlayer o1, EntityPlayer o2) { - if(isSpectator(o1) && !isSpectator(o2)) { - return 1; - } else if(isSpectator(o2) && !isSpectator(o1)) { - return -1; - } else { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - } - - } +// private List> players; +// private List checkBoxes; +// +// private GuiCheckBox hideAllBox, showAllBox; +// private GuiCheckBox rememberHidden; +// +// private boolean initialized = false; +// +// private int playerCount; +// private int upperPlayer = 0; +// +// private int lowerBound; +// +// private boolean drag = false; +// private int lastY = 0; +// private int fitting = 0; +// +// private final Minecraft mc = Minecraft.getMinecraft(); +// +// private final String screenTitle = I18n.format("replaymod.input.playeroverview"); +// +// private final Set initialHiddenPlayers; +// +// public GuiPlayerOverview(List players) { +// initialHiddenPlayers = new HashSet(PlayerHandler.getHiddenPlayers()); +// +// Collections.sort(players, new PlayerComparator()); +// +// this.players = new ArrayList>(); +// this.checkBoxes = new ArrayList(); +// +// for(final EntityPlayer p : players) { +// final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID()); +// this.players.add(Pair.of(p, loc)); +// } +// +// playerCount = players.size(); +// +// ReplayMod.replaySender.setReplaySpeed(0); +// } +// +// private boolean isSpectator(EntityPlayer e) { +// return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null; +// } +// +// @Override +// protected void mouseClicked(int mouseX, int mouseY, int mouseButton) +// throws IOException { +// +// if(fitting < playerCount) { +// float visiblePerc = (float) fitting / (float) playerCount; +// +// int h = this.height - 32 - 32; +// int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h); +// +// int lower = Math.round(32 + offset + (h * visiblePerc)) - 2; +// +// int k2 = (int) (this.width * 0.3); +// +// if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) { +// lastY = mouseY; +// drag = true; +// return; +// } +// } +// int k2 = (int) (this.width * 0.3); +// +// if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) { +// int off = mouseY - upperBound; +// int p = (off / 21) + upperPlayer; +// // TODO +//// ReplayHandler.spectateEntity(players.get(p).first()); +// mc.displayGuiScreen(null); +// } +// +// super.mouseClicked(mouseX, mouseY, mouseButton); +// } +// +// @Override +// protected void mouseClickMove(int mouseX, int mouseY, +// int clickedMouseButton, long timeSinceLastClick) { +// +// if(drag) { +// float step = 1f / (float) playerCount; +// +// int diff = mouseY - lastY; +// int h = this.height - 32 - 32; +// +// float percDiff = (float) diff / (float) h; +// if(Math.abs(percDiff) > Math.abs(step)) { +// int s = (int) (percDiff / step); +// lastY = mouseY; +// upperPlayer += s; +// if(upperPlayer > playerCount - fitting) { +// upperPlayer = playerCount - fitting; +// } else if(upperPlayer < 0) { +// upperPlayer = 0; +// } +// } +// } +// +// super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); +// } +// +// @Override +// protected void mouseReleased(int mouseX, int mouseY, int state) { +// drag = false; +// +// for(GuiCheckBox checkBox : checkBoxes) { +// checkBox.mouseReleased(mouseX, mouseY); +// } +// +// super.mouseReleased(mouseX, mouseY, state); +// } +// +// @Override +// public void initGui() { +// upperPlayer = 0; +// lowerBound = this.height - 10; +// +// @SuppressWarnings("unchecked") +// List buttonList = this.buttonList; +// +// int i = 0; +// for(GuiCheckBox checkBox : checkBoxes) { +// checkBox.xPosition = (int)(this.width*0.7)-5; +// buttonList.add(checkBox); +// i++; +// if(i >= fitting) break; +// } +// +// if(!initialized) { +// hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false); +// showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true); +// rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave); +// } +// +// hideAllBox.xPosition = (int)(this.width*0.7)-5; +// showAllBox.xPosition = (int)(this.width*0.7)-20; +// hideAllBox.yPosition = showAllBox.yPosition = 45; +// +// rememberHidden.xPosition = (int)(this.width*0.3); +// rememberHidden.yPosition = 45; +// +// buttonList.add(hideAllBox); +// buttonList.add(showAllBox); +// buttonList.add(rememberHidden); +// +// initialized = true; +// } +// +// @Override +// protected void actionPerformed(GuiButton button) throws IOException { +// if(button == showAllBox) { +// showAllBox.setIsChecked(true); +// for(Pair p : players) { +// PlayerHandler.showPlayer(p.first()); +// } +// } else if(button == hideAllBox) { +// hideAllBox.setIsChecked(false); +// for(Pair p : players) { +// PlayerHandler.hidePlayer(p.first()); +// } +// } +// +// if(!(button instanceof GuiCheckBox)) return; +// if(button.id >= fitting) return; +// if(!checkBoxes.contains(button)) return; +// PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked()); +// } +// +// private static final int upperBound = 65; +// +// @Override +// public void drawScreen(int mouseX, int mouseY, float partialTicks) { +// this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB()); +// int k2 = (int)(this.width * 0.3); +// int l2 = upperBound; +// +// drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680); +// +// drawString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.spectate"), k2 - 10, 30, Color.WHITE.getRGB()); +// +// String visibleString = I18n.format("replaymod.gui.playeroverview.visible"); +// drawString(fontRendererObj, visibleString, (int) (this.width * 0.7) + 10 - fontRendererObj.getStringWidth(visibleString), 30, Color.WHITE.getRGB()); +// +// fitting = 0; +// +// int sk = 0; +// for(Pair p : players) { +// if(sk < upperPlayer) { +// sk++; +// continue; +// } +// boolean spec = isSpectator(p.first()); +// +// this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2), +// spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB()); +// +// mc.getTextureManager().bindTexture(p.second()); +// +// drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F); +// if(p.first().func_175148_a(EnumPlayerModelParts.HAT)) +// Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F); +// +// GlStateManager.resetColor(); +// if(fitting >= checkBoxes.size()) { +// checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true)); +// @SuppressWarnings("unchecked") +// List buttonList = this.buttonList; +// buttonList.add(checkBoxes.get(checkBoxes.size() - 1)); +// } +// checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID())); +// +// l2 += 16 + 5; +// fitting++; +// if(l2 + 32 > lowerBound) { +// break; +// } +// } +// +// int dw = Mouse.getDWheel(); +// if(dw > 0) { +// dw = -1; +// } else if(dw < 0) { +// dw = 1; +// } +// +// upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0); +// +// if(fitting < playerCount) { +// float visiblePerc = ((float) fitting) / playerCount; +// int barHeight = (int) (visiblePerc * (height - 32 - 32)); +// +// float posPerc = ((float) upperPlayer) / playerCount; +// int barY = (int) (posPerc * (height - 32 - 32)); +// +// drawRect(k2 - 18, upperBound - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB()); +// drawRect(k2 - 16, upperBound+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB()); +// } +// +// int i = 0; +// for(GuiCheckBox checkBox : checkBoxes) { +// checkBox.drawButton(mc, mouseX, mouseY); +// i++; +// if(i >= fitting) break; +// } +// +// hideAllBox.drawButton(mc, mouseX, mouseY); +// showAllBox.drawButton(mc, mouseX, mouseY); +// rememberHidden.drawButton(mc, mouseX, mouseY); +// +// if(hideAllBox.isMouseOver()) { +// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.hideall"), this, Color.WHITE); +// } +// +// if(showAllBox.isMouseOver()) { +// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.showall"), this, Color.WHITE); +// } +// +// if(rememberHidden.isMouseOver()) { +// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.remembersettings.description"), this, Color.WHITE); +// } +// +// //this is necessary to reset the GL parameters for further GUI rendering +// GlStateManager.enableBlend(); +// } +// +// private void saveOnQuit() { +// try { +// // TODO +//// if(rememberHidden.isChecked()) { +//// if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return; +//// ReplayHandler.getReplayFile().writeInvisiblePlayers(PlayerHandler.getHiddenPlayers()); +//// } else { +//// if(initialHiddenPlayers.isEmpty()) return; +//// ReplayHandler.getReplayFile().writeInvisiblePlayers(Collections.emptySet()); +//// } +// } catch(Exception e) { +// e.printStackTrace(); +// } +// } +// +// @Override +// public void keyTyped(char typedChar, int keyCode) throws IOException { +// if(keyCode == Keyboard.KEY_ESCAPE) { +// saveOnQuit(); +// super.keyTyped(typedChar, keyCode); +// } +// } +// +// private class PlayerComparator implements Comparator { +// +// @Override +// public int compare(EntityPlayer o1, EntityPlayer o2) { +// if(isSpectator(o1) && !isSpectator(o2)) { +// return 1; +// } else if(isSpectator(o2) && !isSpectator(o1)) { +// return -1; +// } else { +// return o1.getName().compareToIgnoreCase(o2.getName()); +// } +// } +// +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java index 5a4025ac..f38b1c9b 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiRenderSettings.java @@ -1,12 +1,10 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.*; import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener; import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; import eu.crushedpixel.replaymod.holders.GuiEntryListEntry; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.settings.EncodingPreset; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.utils.MouseUtils; @@ -29,7 +27,7 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; -public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoOverlay { +public class GuiRenderSettings extends GuiScreen { private final Minecraft mc = Minecraft.getMinecraft(); @@ -542,7 +540,8 @@ public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoO if(FMLClientHandler.instance().hasOptifine()) { mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine"))); } else { - ReplayHandler.startPath(options, true); + // TODO +// ReplayHandler.startPath(options, true); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySaving.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySaving.java index e96b7f7b..bfbddd93 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySaving.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySaving.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java index 40c2c9fa..f6e2cdfb 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySettings.java @@ -1,7 +1,5 @@ package eu.crushedpixel.replaymod.gui; -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.ReplayOptions; import net.minecraft.client.gui.GuiButton; @@ -12,8 +10,6 @@ import net.minecraftforge.fml.client.FMLClientHandler; import java.awt.*; import java.io.IOException; -import static eu.crushedpixel.replaymod.gui.GuiConstants.*; - public class GuiReplaySettings extends GuiScreen { protected String screenTitle = I18n.format("replaymod.gui.settings.title"); private GuiScreen parentGuiScreen; @@ -38,23 +34,23 @@ public class GuiReplaySettings extends GuiScreen { int xPos = this.width / 2 - 155 + i % 2 * 160; int yPos = this.height / 6 + 24 * (i >> 1); - - if(o == RecordingOptions.notifications) { - GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o); - buttonList.add(sendChatButton); - - } else if(o == RecordingOptions.recordServer) { - GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o); - buttonList.add(recordServerButton); - - } else if(o == RecordingOptions.recordSingleplayer) { - GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o); - buttonList.add(recordSPButton); - - } else if(o == RecordingOptions.indicator) { - GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o); - buttonList.add(showIndicatorButton); - } +// TODO +// if(o == RecordingOptions.notifications) { +// GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o); +// buttonList.add(sendChatButton); +// +// } else if(o == RecordingOptions.recordServer) { +// GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o); +// buttonList.add(recordServerButton); +// +// } else if(o == RecordingOptions.recordSingleplayer) { +// GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o); +// buttonList.add(recordSPButton); +// +// } else if(o == RecordingOptions.indicator) { +// GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o); +// buttonList.add(showIndicatorButton); +// } ++i; } @@ -69,14 +65,15 @@ public class GuiReplaySettings extends GuiScreen { int xPos = this.width / 2 - 155 + i % 2 * 160; int yPos = this.height / 6 + 24 * (i >> 1); - if(o == ReplayOptions.linear) { - GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o, - I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic")); - buttonList.add(linearButton); - - } else { - buttonList.add(new GuiSettingsOnOffButton(0, xPos, yPos, 150, 20, o)); - } +// TODO +// if(o == ReplayOptions.linear) { +// GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o, +// I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic")); +// buttonList.add(linearButton); +// +// } else { +// buttonList.add(new GuiSettingsOnOffButton(0, xPos, yPos, 150, 20, o)); +// } ++i; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java index 459874f3..f0dd6806 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java @@ -1,12 +1,11 @@ package eu.crushedpixel.replaymod.gui; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.MathHelper; -import net.minecraftforge.fml.client.FMLClientHandler; public class GuiReplaySpeedSlider extends GuiAdvancedButton { @@ -74,7 +73,7 @@ public class GuiReplaySpeedSlider extends GuiAdvancedButton { l = packedFGColour; } else if(!this.enabled) { l = 10526880; - } else if(this.hovered && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { + } else if(this.hovered) { l = 16777120; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java index 20c92ac7..43d78a58 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedButton.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.elements; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java index f4579bc7..4ec5030e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiAdvancedCheckBox.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.elements; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener; import net.minecraft.client.Minecraft; import net.minecraftforge.fml.client.config.GuiCheckBox; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java index ccf2691a..75cd03d7 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java @@ -1,11 +1,12 @@ package eu.crushedpixel.replaymod.gui.elements; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; import eu.crushedpixel.replaymod.utils.OpenGLUtils; import lombok.AllArgsConstructor; import lombok.Getter; import net.minecraft.client.Minecraft; +import static com.replaymod.core.ReplayMod.TEXTURE; + public class GuiArrowButton extends GuiAdvancedButton { private static final int TEXTURE_X = 40; @@ -42,7 +43,7 @@ public class GuiArrowButton extends GuiAdvancedButton { try { super.draw(mc, mouseX, mouseY, hovering); - mc.getTextureManager().bindTexture(GuiReplayOverlay.replay_gui); + mc.getTextureManager().bindTexture(TEXTURE); OpenGLUtils.drawRotatedRectWithCustomSizedTexture(xPosition+4, yPosition+4, dir.getRotation(), TEXTURE_X, TEXTURE_Y, TEXTURE_WIDTH, TEXTURE_HEIGHT, 128, 128); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java index 7cb60f3b..5bb72e8c 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.elements; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; import eu.crushedpixel.replaymod.holders.GuiEntryListEntry; import eu.crushedpixel.replaymod.utils.MouseUtils; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java index ac2fddf3..bdaf4b3f 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiScrollbar.java @@ -6,8 +6,8 @@ import net.minecraft.client.renderer.GlStateManager; import java.awt.*; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; +import static com.replaymod.core.ReplayMod.TEXTURE; +import static com.replaymod.core.ReplayMod.TEXTURE_SIZE; import static org.lwjgl.opengl.GL11.GL_BLEND; import static org.lwjgl.opengl.GL11.glEnable; @@ -105,7 +105,7 @@ public class GuiScrollbar extends Gui implements GuiElement { @Override public void draw(Minecraft mc, int mouseX, int mouseY) { GlStateManager.resetColor(); - mc.renderEngine.bindTexture(replay_gui); + mc.renderEngine.bindTexture(TEXTURE); glEnable(GL_BLEND); // Background @@ -157,7 +157,7 @@ public class GuiScrollbar extends Gui implements GuiElement { if(!enabled) { GlStateManager.color(Color.GRAY.getRed()/255f, Color.GRAY.getGreen()/255f, Color.GRAY.getBlue()/255f, 1f); } - Minecraft.getMinecraft().renderEngine.bindTexture(replay_gui); + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); glEnable(GL_BLEND); drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java index 7958bc1d..010fde76 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiSettingsOnOffButton.java @@ -1,39 +1,39 @@ package eu.crushedpixel.replaymod.gui.elements; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.settings.ReplaySettings; +import com.replaymod.core.SettingsRegistry; public class GuiSettingsOnOffButton extends GuiOnOffButton { - private ReplaySettings.ValueEnum toChange; + private SettingsRegistry settingsRegistry; + private SettingsRegistry.SettingKey toChange; - public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange) { - super(buttonId, x, y, width, height, toChange.getName()+": "); + public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry, + SettingsRegistry.SettingKey toChange) { + super(buttonId, x, y, width, height, toChange.getDisplayString()+": "); + this.settingsRegistry = settingsRegistry; this.toChange = toChange; - if(toChange.getValue() instanceof Boolean) { - this.setValue((Boolean) toChange.getValue() ? 0 : 1); - } + this.setValue(settingsRegistry.get(toChange) ? 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); + public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry, + SettingsRegistry.SettingKey toChange, String onValue, String offValue) { + super(buttonId, x, y, width, height, toChange.getDisplayString()+": ", onValue, offValue); + this.settingsRegistry = settingsRegistry; this.toChange = toChange; - if(toChange.getValue() instanceof Boolean) { - this.setValue((Boolean) toChange.getValue() ? 0 : 1); - } + this.setValue(settingsRegistry.get(toChange) ? 0 : 1); } @Override public void toggle() { super.toggle(); - toChange.setValue(isOn()); - ReplayMod.replaySettings.rewriteSettings(); + settingsRegistry.set(toChange, isOn()); + settingsRegistry.save(); } @Override public void setValue(int value) { super.setValue(value); - toChange.setValue(isOn()); - ReplayMod.replaySettings.rewriteSettings(); + settingsRegistry.set(toChange, isOn()); + settingsRegistry.save(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiKeyframeTimeline.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiKeyframeTimeline.java index 543dee99..648056fb 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiKeyframeTimeline.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiKeyframeTimeline.java @@ -1,13 +1,6 @@ package eu.crushedpixel.replaymod.gui.elements.timelines; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.gui.GuiEditKeyframe; -import eu.crushedpixel.replaymod.holders.*; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; - -import java.util.ListIterator; +import eu.crushedpixel.replaymod.holders.Keyframe; public class GuiKeyframeTimeline extends GuiTimeline { private static final int KEYFRAME_PLACE_X = 74; @@ -31,230 +24,231 @@ public class GuiKeyframeTimeline extends GuiTimeline { this.placeKeyframes = showPlaceKeyframes; } - @Override - public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { - if(!enabled) return false; - - long time = getTimeAt(mouseX, mouseY); - if(time == -1) { - return false; - } - - int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); - - Keyframe closest; - if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) { - closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); - } else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) { - closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); - } else { - closest = null; - } - - //left mouse button - if(button == 0) { - ReplayHandler.selectKeyframe(closest); //can be null, deselects keyframe - - // If we clicked on a key frame, then continue monitoring the mouse for movements - long currentTime = System.currentTimeMillis(); - if(closest != null) { - if(currentTime - clickTime < 500) { // if double clicked then open GUI instead - mc.displayGuiScreen(GuiEditKeyframe.create(closest)); - this.clickedKeyFrame = null; - } else { - this.clickedKeyFrame = closest; - this.dragging = false; - } - } else { // If we didn't then just update the cursor - ReplayHandler.setRealTimelineCursor((int) time); - this.dragging = true; - } - this.clickTime = currentTime; - - } else if(button == 1) { - if(closest != null) { - if(closest.getValue() instanceof AdvancedPosition) { - AdvancedPosition pos = (AdvancedPosition)closest.getValue(); - ReplayHandler.getCameraEntity().movePath(pos); - } else if(closest.getValue() instanceof TimestampValue) { - ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt()); - } - } - } - - return isHovering(mouseX, mouseY); - } - - @Override - public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { - if(!enabled) return; - long time = getTimeAt(mouseX, mouseY); - if (time != -1) { - if (clickedKeyFrame != null) { - int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); - - if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) { - clickedKeyFrame.setRealTimestamp((int) time); - ReplayHandler.getPositionKeyframes().sort(); - ReplayHandler.getTimeKeyframes().sort(); - dragging = true; - } - } else if (dragging) { - ReplayHandler.setRealTimelineCursor((int) time); - } - } - } - - @Override - public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { - mouseDrag(mc, mouseX, mouseY, button); - clickedKeyFrame = null; - dragging = false; - } - - @Override - public void draw(Minecraft mc, int mouseX, int mouseY) { - super.draw(mc, mouseX, mouseY); - - int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; - - long leftTime = Math.round(timeStart * timelineLength); - long rightTime = Math.round((timeStart + zoom) * timelineLength); - - double segmentLength = timelineLength * zoom; - - //iterate over keyframes to find spectator segments - if(placeKeyframes) { - ListIterator> iterator = ReplayHandler.getPositionKeyframes().listIterator(); - while(iterator.hasNext()) { - Keyframe kf = iterator.next(); - - if(!(kf.getValue() instanceof SpectatorData)) - continue; - - int i = iterator.nextIndex(); - int nextSpectatorKeyframeRealTime = -1; - - if (iterator.hasNext()) { - Keyframe kf2 = iterator.next(); - - if(kf2.getValue() instanceof SpectatorData) { - SpectatorData spectatorData1 = (SpectatorData)kf.getValue(); - SpectatorData spectatorData2 = (SpectatorData)kf2.getValue(); - - if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) { - nextSpectatorKeyframeRealTime = kf2.getRealTimestamp(); - } - } - } - - int i2 = iterator.previousIndex(); - - while(i2 >= i) { - iterator.previous(); - i2--; - } - - if(nextSpectatorKeyframeRealTime != -1) { - int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); - int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength); - - int color = ((SpectatorData)kf.getValue()).getSpectatingMethod().getColor(); - - drawRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 1, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1), - positionY + BORDER_TOP + 4, color); - - GlStateManager.color(1, 1, 1, 1); - } - } - } - - //iterate over time keyframes to find negative replay speeds - if(timeKeyframes) { - ListIterator> iterator = ReplayHandler.getTimeKeyframes().listIterator(); - while(iterator.hasNext()) { - Keyframe kf = iterator.next(); - - int i = iterator.nextIndex(); - int nextTimeKeyframeRealTime = -1; - - if (iterator.hasNext()) { - Keyframe kf2 = iterator.next(); - if(kf.getValue().asInt() > kf2.getValue().asInt()) { - nextTimeKeyframeRealTime = kf2.getRealTimestamp(); - } - } - - int i2 = iterator.previousIndex(); - - while(i2 >= i) { - iterator.previous(); - i2--; - } - - if(nextTimeKeyframeRealTime != -1) { - int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); - int nextX = getKeyframeX(nextTimeKeyframeRealTime, leftTime, bodyWidth, segmentLength); - - drawGradientRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 6, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1), - positionY + BORDER_TOP + 9, 0xFFFF0000, 0xFFFF0000); - } - } - } - - drawTimelineCursor(leftTime, rightTime, bodyWidth); - - - //Draw Keyframe logos - for (Keyframe kf : ReplayHandler.getAllKeyframes()) { - if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe())) - drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength); - } - - if(ReplayHandler.getSelectedKeyframe() != null && !(ReplayHandler.getSelectedKeyframe().getValue() instanceof Marker)) { - drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength); - } - } - - private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { - long positionInSegment = timestamp - leftTime; - double fractionOfSegment = positionInSegment / segmentLength; - return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); - } - - private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) { - if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { - int textureX; - int textureY; - int y = positionY; - - int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); - - if(kf.getValue() instanceof AdvancedPosition) { - if(!placeKeyframes) return; - textureX = KEYFRAME_PLACE_X; - textureY = KEYFRAME_PLACE_Y; - y += 0; - - //If Spectator Keyframe, use different texture - if(kf.getValue() instanceof SpectatorData) { - textureX = KEYFRAME_SPEC_X; - textureY = KEYFRAME_SPEC_Y; - } - } else if(kf.getValue() instanceof TimestampValue) { - if(!timeKeyframes) return; - textureX = KEYFRAME_TIME_X; - textureY = KEYFRAME_TIME_Y; - y += 5; - } else { - throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass()); - } - - if (ReplayHandler.isSelected(kf)) { - textureX += 5; - } - - rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5); - } - } + // TODO +// @Override +// public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { +// if(!enabled) return false; +// +// long time = getTimeAt(mouseX, mouseY); +// if(time == -1) { +// return false; +// } +// +// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); +// +// Keyframe closest; +// if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) { +// closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); +// } else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) { +// closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); +// } else { +// closest = null; +// } +// +// //left mouse button +// if(button == 0) { +// ReplayHandler.selectKeyframe(closest); //can be null, deselects keyframe +// +// // If we clicked on a key frame, then continue monitoring the mouse for movements +// long currentTime = System.currentTimeMillis(); +// if(closest != null) { +// if(currentTime - clickTime < 500) { // if double clicked then open GUI instead +// mc.displayGuiScreen(GuiEditKeyframe.create(closest)); +// this.clickedKeyFrame = null; +// } else { +// this.clickedKeyFrame = closest; +// this.dragging = false; +// } +// } else { // If we didn't then just update the cursor +// ReplayHandler.setRealTimelineCursor((int) time); +// this.dragging = true; +// } +// this.clickTime = currentTime; +// +// } else if(button == 1) { +// if(closest != null) { +// if(closest.getValue() instanceof AdvancedPosition) { +// AdvancedPosition pos = (AdvancedPosition)closest.getValue(); +// ReplayHandler.getCameraEntity().movePath(pos); +// } else if(closest.getValue() instanceof TimestampValue) { +// ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt()); +// } +// } +// } +// +// return isHovering(mouseX, mouseY); +// } +// +// @Override +// public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { +// if(!enabled) return; +// long time = getTimeAt(mouseX, mouseY); +// if (time != -1) { +// if (clickedKeyFrame != null) { +// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); +// +// if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) { +// clickedKeyFrame.setRealTimestamp((int) time); +// ReplayHandler.getPositionKeyframes().sort(); +// ReplayHandler.getTimeKeyframes().sort(); +// dragging = true; +// } +// } else if (dragging) { +// ReplayHandler.setRealTimelineCursor((int) time); +// } +// } +// } +// +// @Override +// public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { +// mouseDrag(mc, mouseX, mouseY, button); +// clickedKeyFrame = null; +// dragging = false; +// } +// +// @Override +// public void draw(Minecraft mc, int mouseX, int mouseY) { +// super.draw(mc, mouseX, mouseY); +// +// int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; +// +// long leftTime = Math.round(timeStart * timelineLength); +// long rightTime = Math.round((timeStart + zoom) * timelineLength); +// +// double segmentLength = timelineLength * zoom; +// +// //iterate over keyframes to find spectator segments +// if(placeKeyframes) { +// ListIterator> iterator = ReplayHandler.getPositionKeyframes().listIterator(); +// while(iterator.hasNext()) { +// Keyframe kf = iterator.next(); +// +// if(!(kf.getValue() instanceof SpectatorData)) +// continue; +// +// int i = iterator.nextIndex(); +// int nextSpectatorKeyframeRealTime = -1; +// +// if (iterator.hasNext()) { +// Keyframe kf2 = iterator.next(); +// +// if(kf2.getValue() instanceof SpectatorData) { +// SpectatorData spectatorData1 = (SpectatorData)kf.getValue(); +// SpectatorData spectatorData2 = (SpectatorData)kf2.getValue(); +// +// if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) { +// nextSpectatorKeyframeRealTime = kf2.getRealTimestamp(); +// } +// } +// } +// +// int i2 = iterator.previousIndex(); +// +// while(i2 >= i) { +// iterator.previous(); +// i2--; +// } +// +// if(nextSpectatorKeyframeRealTime != -1) { +// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); +// int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength); +// +// int color = ((SpectatorData)kf.getValue()).getSpectatingMethod().getColor(); +// +// drawRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 1, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1), +// positionY + BORDER_TOP + 4, color); +// +// GlStateManager.color(1, 1, 1, 1); +// } +// } +// } +// +// //iterate over time keyframes to find negative replay speeds +// if(timeKeyframes) { +// ListIterator> iterator = ReplayHandler.getTimeKeyframes().listIterator(); +// while(iterator.hasNext()) { +// Keyframe kf = iterator.next(); +// +// int i = iterator.nextIndex(); +// int nextTimeKeyframeRealTime = -1; +// +// if (iterator.hasNext()) { +// Keyframe kf2 = iterator.next(); +// if(kf.getValue().asInt() > kf2.getValue().asInt()) { +// nextTimeKeyframeRealTime = kf2.getRealTimestamp(); +// } +// } +// +// int i2 = iterator.previousIndex(); +// +// while(i2 >= i) { +// iterator.previous(); +// i2--; +// } +// +// if(nextTimeKeyframeRealTime != -1) { +// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); +// int nextX = getKeyframeX(nextTimeKeyframeRealTime, leftTime, bodyWidth, segmentLength); +// +// drawGradientRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 6, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1), +// positionY + BORDER_TOP + 9, 0xFFFF0000, 0xFFFF0000); +// } +// } +// } +// +// drawTimelineCursor(leftTime, rightTime, bodyWidth); +// +// +// //Draw Keyframe logos +// for (Keyframe kf : ReplayHandler.getAllKeyframes()) { +// if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe())) +// drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength); +// } +// +// if(ReplayHandler.getSelectedKeyframe() != null) { +// drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength); +// } +// } +// +// private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) { +// long positionInSegment = timestamp - leftTime; +// double fractionOfSegment = positionInSegment / segmentLength; +// return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); +// } +// +// private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) { +// if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { +// int textureX; +// int textureY; +// int y = positionY; +// +// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); +// +// if(kf.getValue() instanceof AdvancedPosition) { +// if(!placeKeyframes) return; +// textureX = KEYFRAME_PLACE_X; +// textureY = KEYFRAME_PLACE_Y; +// y += 0; +// +// //If Spectator Keyframe, use different texture +// if(kf.getValue() instanceof SpectatorData) { +// textureX = KEYFRAME_SPEC_X; +// textureY = KEYFRAME_SPEC_Y; +// } +// } else if(kf.getValue() instanceof TimestampValue) { +// if(!timeKeyframes) return; +// textureX = KEYFRAME_TIME_X; +// textureY = KEYFRAME_TIME_Y; +// y += 5; +// } else { +// throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass()); +// } +// +// if (ReplayHandler.isSelected(kf)) { +// textureX += 5; +// } +// +// rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5); +// } +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiTimeline.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiTimeline.java index 8cab99c4..7630b411 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiTimeline.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/timelines/GuiTimeline.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.elements.timelines; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.GuiElement; import eu.crushedpixel.replaymod.utils.RoundUtils; import lombok.AllArgsConstructor; @@ -11,8 +11,8 @@ import net.minecraft.client.renderer.GlStateManager; import java.awt.*; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; -import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; +import static com.replaymod.core.ReplayMod.TEXTURE; +import static com.replaymod.core.ReplayMod.TEXTURE_SIZE; import static org.lwjgl.opengl.GL11.GL_BLEND; import static org.lwjgl.opengl.GL11.glEnable; @@ -76,7 +76,7 @@ public class GuiTimeline extends Gui implements GuiElement { * This draws the time at big markers above the timeline. Therefore extra space in negative y direction * should be kept empty if markers are desired. */ - public boolean showMarkers; + public boolean showMarkers; // TODO: Rename to not be confused with Marker protected final int positionX; protected final int positionY; @@ -280,7 +280,7 @@ public class GuiTimeline extends Gui implements GuiElement { if(!enabled) { GlStateManager.color(Color.GRAY.getRed() / 255f, Color.GRAY.getGreen() / 255f, Color.GRAY.getBlue() / 255f, 1f); } - Minecraft.getMinecraft().renderEngine.bindTexture(replay_gui); + Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE); glEnable(GL_BLEND); drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java index 07518a31..1d205259 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java @@ -6,7 +6,7 @@ import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiPasswordField; import de.johni0702.minecraft.gui.element.GuiTextField; import de.johni0702.minecraft.gui.layout.CustomLayout; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.GuiConstants; public class GuiLoginPrompt extends AbstractGuiScreen { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiRegister.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiRegister.java index 83cfa255..e6df4189 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiRegister.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiRegister.java @@ -7,7 +7,7 @@ import de.johni0702.minecraft.gui.element.*; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.ApiException; import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.utils.EmailAddressUtils; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java index 59adec65..8bb8d1ea 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.online; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.replay.SearchQuery; import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; @@ -12,7 +12,6 @@ import eu.crushedpixel.replaymod.api.replay.pagination.Pagination; import eu.crushedpixel.replaymod.api.replay.pagination.SearchPagination; import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.elements.*; -import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry; import net.minecraft.client.gui.*; import net.minecraft.client.resources.I18n; @@ -265,7 +264,8 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback { } else if(button.id == GuiConstants.CENTER_LOGOUT_BUTTON) { mc.displayGuiScreen(getYesNoGui(this, LOGOUT_CALLBACK_ID)); } else if(button.id == GuiConstants.CENTER_MANAGER_BUTTON) { - mc.displayGuiScreen(new GuiReplayViewer()); + // TODO +// mc.displayGuiScreen(new GuiReplayViewer(mod)); } else if(button.id == GuiConstants.CENTER_RECENT_BUTTON) { disableTopBarButton(button.id); showOnlineRecent(); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java index ba660111..fab239cf 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayDownloading.java @@ -1,15 +1,14 @@ package eu.crushedpixel.replaymod.gui.online; import com.mojang.realmsclient.gui.ChatFormatting; +import com.replaymod.core.ReplayMod; import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; import de.johni0702.minecraft.gui.layout.CustomLayout; -import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import java.io.File; @@ -49,7 +48,8 @@ public class GuiReplayDownloading extends AbstractGuiScreen img = archive.getThumb(); + if(img.isPresent()) { + thumb = ImageUtils.scaleImage(img.get(), new Dimension(1280, 720)); hasThumbnail = true; } @@ -307,21 +312,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener { if(hideServerIP.isChecked()) { File tmp = File.createTempFile("replay_hidden_ip", "mcpr"); - File tmpMeta = File.createTempFile("metadata", "json"); - ReplayMetaData newMetaData = metaData.copy(); - newMetaData.removeServer(); - ReplayFileIO.write(newMetaData, tmpMeta); - - HashMap toAdd = new HashMap(); - toAdd.put(ReplayFile.ENTRY_METADATA, tmpMeta); - - FileUtils.copyFile(replayFile, tmp); - ReplayFileIO.addFilesToZip(tmp, toAdd); + ReplayMetaData newMetaData = new ReplayMetaData(metaData); + newMetaData.setServerName(null); + ReplayFile replay = new ZipReplayFile(new ReplayStudio(), replayFile); + replay.writeMetaData(newMetaData); + replay.saveTo(tmp); uploader.uploadFile(GuiUploadFile.this, name, tags, tmp, category, desc); - FileUtils.deleteQuietly(tmpMeta); FileUtils.deleteQuietly(tmp); } else { uploader.uploadFile(GuiUploadFile.this, name, tags, replayFile, category, desc); diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java deleted file mode 100755 index 7d2360c1..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/gui/overlay/GuiReplayOverlay.java +++ /dev/null @@ -1,657 +0,0 @@ -package eu.crushedpixel.replaymod.gui.overlay; - -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.gui.GuiMouseInput; -import eu.crushedpixel.replaymod.gui.GuiRenderSettings; -import eu.crushedpixel.replaymod.gui.GuiReplaySpeedSlider; -import eu.crushedpixel.replaymod.gui.elements.*; -import eu.crushedpixel.replaymod.gui.elements.timelines.GuiKeyframeTimeline; -import eu.crushedpixel.replaymod.gui.elements.timelines.GuiMarkerTimeline; -import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.SpectatorData; -import eu.crushedpixel.replaymod.holders.TimestampValue; -import eu.crushedpixel.replaymod.registry.KeybindRegistry; -import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.utils.CameraPathValidator; -import eu.crushedpixel.replaymod.utils.MouseUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityOtherPlayerMP; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiChat; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.inventory.GuiInventory; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.KeyBinding; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.client.FMLClientHandler; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.Display; -import org.lwjgl.util.Point; - -import java.awt.Color; -import java.io.IOException; -import java.util.List; - -import static net.minecraft.client.renderer.GlStateManager.*; -import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; -import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; - -public class GuiReplayOverlay extends Gui { - private static final Minecraft mc = Minecraft.getMinecraft(); - public static final ResourceLocation replay_gui = new ResourceLocation("replaymod", "replay_gui.png"); - public static final int TEXTURE_SIZE = 128; - - public static final int KEYFRAME_TIMELINE_LENGTH = 30 * 60 * 1000; - - public static GuiTexturedButton texturedButton(int x, int y, int u, int v, int size, Runnable action, String hoverText) { - return new GuiTexturedButton(0, x, y, size, size, replay_gui, u, v, TEXTURE_SIZE, TEXTURE_SIZE, action, I18n.format(hoverText)); - } - - private final Point screenDimensions = MouseUtils.getScaledDimensions(); - private final int WIDTH = screenDimensions.getX(); - private final int HEIGHT = screenDimensions.getY(); - - // Top row - private final int TOP_ROW = 10; - private final int BUTTON_PLAY_PAUSE_X = 10; - private final int SPEED_X = 35; - private final int SPEED_WIDTH = 100; - private final int TIMELINE_X = SPEED_X + SPEED_WIDTH + 5; - - // Bottom row - private final int BOTTOM_ROW = TOP_ROW + 33; - private final int BUTTON_PLAY_PATH_X = 10; - private final int BUTTON_EXPORT_X = BUTTON_PLAY_PATH_X + 25; - private final int BUTTON_PLACE_X = BUTTON_EXPORT_X + 25; - private final int BUTTON_TIME_X = BUTTON_PLACE_X + 25; - private final int TIMELINE_REAL_X = BUTTON_TIME_X + 25; - private final int TIMELINE_REAL_WIDTH = WIDTH - 14 - 11 - TIMELINE_REAL_X; - - private final GuiElement buttonPlayPause = new DelegatingElement() { - - private final GuiElement buttonPlay = texturedButton(BUTTON_PLAY_PAUSE_X, TOP_ROW, 0, 0, 20, new Runnable() { - @Override - public void run() { - ReplayMod.replaySender.setReplaySpeed(speedSlider.getSliderValue()); - } - }, "replaymod.gui.ingame.menu.unpause"); - - private final GuiElement buttonPause = texturedButton(BUTTON_PLAY_PAUSE_X, TOP_ROW, 0, 20, 20, new Runnable() { - @Override - public void run() { - ReplayMod.replaySender.setReplaySpeed(0); - } - }, "replaymod.gui.ingame.menu.pause"); - - @Override - public GuiElement delegate() { - return ReplayMod.replaySender.paused() ? buttonPlay : buttonPause; - } - }; - - private final GuiElement buttonExport = texturedButton(BUTTON_EXPORT_X, BOTTOM_ROW, 40, 0, 20, new Runnable() { - @Override - public void run() { - try { - CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes()); - } catch(CameraPathValidator.InvalidCameraPathException e) { - e.printToChat(); - return; - } - mc.displayGuiScreen(new GuiRenderSettings()); - - } - }, "replaymod.gui.ingame.menu.renderpath"); - - private final GuiElement buttonPlayPausePath = new DelegatingElement() { - - private final GuiElement buttonPlay = texturedButton(BUTTON_PLAY_PATH_X, BOTTOM_ROW, 0, 0, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.startPath(null, GuiScreen.isCtrlKeyDown()); - - } - }, "replaymod.gui.ingame.menu.playpath"); - - private final GuiElement buttonPlayFromStart = texturedButton(BUTTON_PLAY_PATH_X, BOTTOM_ROW, 0, 0, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.startPath(null, GuiScreen.isCtrlKeyDown()); - - } - }, "replaymod.gui.ingame.menu.playpathfromstart"); - - private final GuiElement buttonPause = texturedButton(BUTTON_PLAY_PATH_X, BOTTOM_ROW, 0, 20, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.interruptReplay(); - - } - }, "replaymod.gui.ingame.menu.pausepath"); - - @Override - public GuiElement delegate() { - return ReplayHandler.isInPath() ? buttonPause : GuiScreen.isCtrlKeyDown() ? buttonPlayFromStart : buttonPlay; - } - }; - - private final GuiElement buttonPlace = new DelegatingElement() { - private final GuiElement buttonNotSelected = texturedButton(BUTTON_PLACE_X, BOTTOM_ROW, 0, 40, 20, new Runnable() { - @Override - public void run() { - Entity cam = mc.getRenderViewEntity(); - if (cam != null) { - AdvancedPosition position = new AdvancedPosition(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, - cam.rotationYaw % 360, ReplayHandler.getCameraTilt()); - - if (ReplayHandler.isCamera()) - ReplayHandler.addKeyframe(new Keyframe(ReplayHandler.getRealTimelineCursor(), position)); - else - ReplayHandler.addKeyframe(new Keyframe(ReplayHandler.getRealTimelineCursor(), new SpectatorData(cam))); - } - } - }, "replaymod.gui.ingame.menu.addposkeyframe"); - - private final GuiElement buttonSelected = texturedButton(BUTTON_PLACE_X, BOTTOM_ROW, 0, 60, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe()); - } - }, "replaymod.gui.ingame.menu.removeposkeyframe"); - - private final GuiElement buttonSpectatorNotSelected = texturedButton(BUTTON_PLACE_X, BOTTOM_ROW, 40, 40, 20, new Runnable() { - @Override - public void run() { - Entity cam = mc.getRenderViewEntity(); - if (cam != null) { - AdvancedPosition position = new AdvancedPosition(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, - cam.rotationYaw % 360, ReplayHandler.getCameraTilt()); - - if (ReplayHandler.isCamera()) - ReplayHandler.addKeyframe(new Keyframe(ReplayHandler.getRealTimelineCursor(), position)); - else - ReplayHandler.addKeyframe(new Keyframe(ReplayHandler.getRealTimelineCursor(), new SpectatorData(cam))); - } - } - }, "replaymod.gui.ingame.menu.addspeckeyframe"); - - private final GuiElement buttonSpectatorSelected = texturedButton(BUTTON_PLACE_X, BOTTOM_ROW, 40, 60, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe()); - } - }, "replaymod.gui.ingame.menu.removespeckeyframe"); - - @Override - public GuiElement delegate() { - boolean selected = ReplayHandler.getSelectedKeyframe() != null && ReplayHandler.getSelectedKeyframe().getValue() instanceof AdvancedPosition; - boolean camera; - if(selected) { - camera = !(ReplayHandler.getSelectedKeyframe().getValue() instanceof SpectatorData); - } else { - camera = ReplayHandler.isCamera(); - } - - if(camera) { - return selected ? buttonSelected : buttonNotSelected; - } else { - return selected ? buttonSpectatorSelected : buttonSpectatorNotSelected; - } - } - }; - - private final GuiElement buttonTime = new DelegatingElement() { - - private final GuiElement buttonNotSelected = texturedButton(BUTTON_TIME_X, BOTTOM_ROW, 0, 80, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.addKeyframe(new Keyframe(ReplayHandler.getRealTimelineCursor(), new TimestampValue(ReplayMod.replaySender.currentTimeStamp()))); - } - }, "replaymod.gui.ingame.menu.addtimekeyframe"); - - private final GuiElement buttonSelected = texturedButton(BUTTON_TIME_X, BOTTOM_ROW, 0, 100, 20, new Runnable() { - @Override - public void run() { - ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe()); - } - }, "replaymod.gui.ingame.menu.removetimekeyframe"); - - @Override - public GuiElement delegate() { - return ReplayHandler.getSelectedKeyframe() != null && ReplayHandler.getSelectedKeyframe().getValue() instanceof TimestampValue ? buttonSelected : buttonNotSelected; - } - }; - private final GuiElement buttonZoomIn = texturedButton(WIDTH - 14 - 9, BOTTOM_ROW, 40, 20, 9, new Runnable() { - @Override - public void run() { - timelineReal.zoomIn(); - } - }, "replaymod.gui.ingame.menu.zoomin"); - - private final GuiElement buttonZoomOut = texturedButton(WIDTH - 14 - 9, BOTTOM_ROW + 11, 40, 30, 9, new Runnable() { - - @Override - public void run() { - timelineReal.zoomOut(); - } - }, "replaymod.gui.ingame.menu.zoomout"); - - - private final GuiMarkerTimeline timeline = new GuiMarkerTimeline(TIMELINE_X, TOP_ROW - 1, WIDTH - 14 - TIMELINE_X, 22, false); - - private final GuiKeyframeTimeline timelineReal = new GuiKeyframeTimeline(TIMELINE_REAL_X, BOTTOM_ROW - 1, TIMELINE_REAL_WIDTH, 22, true, true, true); - { - timelineReal.timelineLength = KEYFRAME_TIMELINE_LENGTH; - } - - private final GuiScrollbar scrollbar = new GuiScrollbar(TIMELINE_REAL_X, BOTTOM_ROW + 22, TIMELINE_REAL_WIDTH) { - @Override - public void dragged() { - timelineReal.timeStart = scrollbar.sliderPosition; - } - }; - - private final GuiReplaySpeedSlider speedSlider = new GuiReplaySpeedSlider(SPEED_X, TOP_ROW, I18n.format("replaymod.gui.speed")); - - public double getSpeedSliderValue() { - return speedSlider.getSliderValue(); - } - - private boolean toolbarOpen = false; - - private final DelegatingElement toolbar = new DelegatingElement() { - - private void toggleOpen() { - toolbarOpen = !toolbarOpen; - } - - private GuiElement buttonOpenToolbar = new GuiArrowButton(-1, 10, HEIGHT-10-20, "", GuiArrowButton.Direction.UP) { - @Override - public void performAction() { - toggleOpen(); - } - }; - - private GuiElement buttonCloseToolbar = new GuiArrowButton(-1, 10, HEIGHT-10-20, "", GuiArrowButton.Direction.DOWN) { - @Override - public void performAction() { - toggleOpen(); - } - }; - - private ComposedElement openElements = new ComposedElement(buttonCloseToolbar); - - private int maxButtonY = -1; - - { - int buttonX = 10; - int maxWidth = 0; - int i = 0; - - for(final KeyBinding kb : KeybindRegistry.getReplayModKeyBindings()) { - int buttonY = HEIGHT-55-(i*25); - - if(buttonY < 80) { - buttonX += 25 + maxWidth + 5; - maxWidth = 0; - - i = 0; - buttonY = HEIGHT-55-(i*25); - } - - if(buttonY < maxButtonY || maxButtonY == -1) maxButtonY = buttonY; - - String keyName = "???"; - try { - keyName = Keyboard.getKeyName(kb.getKeyCode()); - } catch (ArrayIndexOutOfBoundsException e) { - // Apparently windows likes to press strange keys, see https://www.replaymod.com/forum/thread/55 - } - GuiElement button = new GuiAdvancedButton(buttonX, buttonY, 20, 20, keyName, new Runnable() { - @Override - public void run() { - ReplayMod.keyInputHandler.handleCustomKeybindings(kb, false, kb.getKeyCode()); - } - }, null); - - String stringText = I18n.format(kb.getKeyDescription()); - int stringWidth = mc.fontRendererObj.getStringWidth(stringText); - - if(stringWidth > maxWidth) { - maxWidth = stringWidth; - } - - GuiString string = new GuiString(buttonX+25, buttonY+6, Color.WHITE, stringText); - - openElements.addPart(button); - openElements.addPart(string); - - i++; - } - } - - @Override - public GuiElement delegate() { - if(toolbarOpen) { - return openElements; - } else { - return buttonOpenToolbar; - } - } - - @Override - public void draw(Minecraft mc, int mouseX, int mouseY) { - if(toolbarOpen) { - drawGradientRect(0, maxButtonY - 10, WIDTH, HEIGHT, -1072689136, -804253680); - } - super.draw(mc, mouseX, mouseY); - } - }; - - public void closeToolbar() { - toolbarOpen = false; - } - - private final GuiElement content = new ComposedElement(buttonPlayPause, buttonExport, buttonPlace, buttonTime, - buttonPlayPausePath, buttonZoomIn, buttonZoomOut, timeline, timelineReal, scrollbar, speedSlider, toolbar); - - public boolean isVisible() { - return ReplayHandler.isInReplay(); - } - - /** - * Resets the UI. - * @param resetElements Whether the timeline and Speed Slider should be reset as well - */ - public void resetUI(boolean resetElements) { - if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { - mc.displayGuiScreen(null); - } - if (resetElements) { - timelineReal.zoom = 0.033f; - timelineReal.timeStart = 0; - - ReplayHandler.setRealTimelineCursor(0); - speedSlider.reset(); - } - } - - public void register() { - FMLCommonHandler.instance().bus().register(this); - MinecraftForge.EVENT_BUS.register(this); - } - - public void unregister() { - FMLCommonHandler.instance().bus().unregister(this); - MinecraftForge.EVENT_BUS.unregister(this); - } - - private void checkResize() { - if (!screenDimensions.equals(MouseUtils.getScaledDimensions())) { - GuiReplayOverlay other = new GuiReplayOverlay(); - other.timelineReal.zoom = this.timelineReal.zoom; - other.timelineReal.timeStart = this.timelineReal.timeStart; - other.speedSlider.copyValueFrom(this.speedSlider); - - this.unregister(); - other.register(); - ReplayMod.overlay = other; - - if (mc.currentScreen instanceof GuiMouseInput) { - mc.displayGuiScreen(new GuiMouseInput(other)); - } - } - } - - @SubscribeEvent - public void onRenderTabList(RenderGameOverlayEvent.Pre event) { //cancelling tab list rendering and rendering help instead - if (!isVisible()) return; - if (event.type == RenderGameOverlayEvent.ElementType.PLAYER_LIST) { - event.setCanceled(true); - } - } - - private void tick() { - if (FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { - Entity player = ReplayHandler.getCameraEntity(); - if(player != null) { - player.setVelocity(0, 0, 0); - } - } - - checkResize(); - } - - public void mouseDrag(int mouseX, int mouseY, int button) { - content.mouseDrag(mc, mouseX, mouseY, button); - } - - public void mouseReleased(int mouseX, int mouseY, int button) { - content.mouseRelease(mc, mouseX, mouseY, button); - } - - public void mouseClicked(int mouseX, int mouseY, int button) { - if (ReplayHandler.isInPath()) { // Only allow clicking of cancel button during path replay - buttonPlayPausePath.mouseClick(mc, mouseX, mouseY, button); - } else { - content.mouseClick(mc, mouseX, mouseY, button); - } - } - - public void performJump(long timelineTime) { - performJump(timelineTime, true); - } - - public void performJump(long timelineTime, boolean setLastPosition) { - if (timelineTime != -1) { // Click on timeline - //When hurrying, no Timeline jumping etc. is possible - if(!ReplayMod.replaySender.isHurrying()) { - if(timelineTime < ReplayMod.replaySender.currentTimeStamp()) { - mc.displayGuiScreen(null); - } - - if(setLastPosition) { - CameraEntity cam = ReplayHandler.getCameraEntity(); - if(cam != null) { - ReplayHandler.setLastPosition(new AdvancedPosition(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, cam.rotationYaw), false); - } else { - ReplayHandler.setLastPosition(null, false); - } - } - - long diff = timelineTime - ReplayMod.replaySender.getDesiredTimestamp(); - if(diff != 0) { - if (diff > 0 && diff < 5000) { // Small difference and no time travel - ReplayMod.replaySender.jumpToTime((int) timelineTime); - } else { // We either have to restart the replay or send a significant amount of packets - // Render our please-wait-screen - GuiScreen guiScreen = new GuiScreen() { - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - drawBackground(0); - drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.pleasewait"), - width / 2, height / 2, 0xffffffff); - } - }; - - // Make sure that the replaysender changes into sync mode - ReplayMod.replaySender.setSyncModeAndWait(); - - // Perform the rendering using OpenGL - pushMatrix(); - clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - enableTexture2D(); - mc.getFramebuffer().bindFramebuffer(true); - mc.entityRenderer.setupOverlayRendering(); - - guiScreen.setWorldAndResolution(mc, WIDTH, HEIGHT); - guiScreen.drawScreen(0, 0, 0); - - mc.getFramebuffer().unbindFramebuffer(); - popMatrix(); - pushMatrix(); - mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight); - popMatrix(); - - Display.update(); - - // Send the packets - ReplayMod.replaySender.sendPacketsTill((int) timelineTime); - ReplayMod.replaySender.setAsyncMode(true); - ReplayMod.replaySender.setReplaySpeed(0); - - mc.getNetHandler().getNetworkManager().processReceivedPackets(); - @SuppressWarnings("unchecked") - List entities = (List) mc.theWorld.loadedEntityList; - for (Entity entity : entities) { - if (entity instanceof EntityOtherPlayerMP) { - EntityOtherPlayerMP e = (EntityOtherPlayerMP) entity; - e.setPosition(e.otherPlayerMPX, e.otherPlayerMPY, e.otherPlayerMPZ); - e.rotationYaw = (float) e.otherPlayerMPYaw; - e.rotationPitch = (float) e.otherPlayerMPPitch; - } - entity.lastTickPosX = entity.prevPosX = entity.posX; - entity.lastTickPosY = entity.prevPosY = entity.posY; - entity.lastTickPosZ = entity.prevPosZ = entity.posZ; - entity.prevRotationYaw = entity.rotationYaw; - entity.prevRotationPitch = entity.rotationPitch; - } - try { - mc.runTick(); - } catch (IOException e) { - e.printStackTrace(); // This should never be thrown but whatever - } - - //finally, updating the camera's position (which is not done by the sync jumping) - ReplayHandler.moveCameraToLastPosition(); - - // No need to remove our please-wait-screen. It'll vanish with the next - // render pass as it's never been a real GuiScreen in the first place. - } - } - } - } - } - - @SubscribeEvent - public void onRenderGui(RenderGameOverlayEvent.Post event) throws IllegalArgumentException, IllegalAccessException { - if (event.type != RenderGameOverlayEvent.ElementType.ALL) return; - if (!isVisible()) return; - - FMLClientHandler fml = FMLClientHandler.instance(); - - tick(); - - // Do not draw if GUI doesn't want us to - if(mc.currentScreen instanceof NoOverlay) { - return; - } - - // If we are not currently spectating someone - if (ReplayHandler.isCamera()) { - ReplayGuiRegistry.hide(); // hide all normal UI - } else { - ReplayGuiRegistry.show(); // otherwise show them - } - - // Replace chat and inventory GUI (opened by pressing the respective hotkey) with a dummy input GUI - if(fml.isGUIOpen(GuiChat.class) || fml.isGUIOpen(GuiInventory.class)) { - mc.displayGuiScreen(new GuiMouseInput(this)); - } - - GlStateManager.resetColor(); - - Point mousePoint = MouseUtils.getMousePos(); - int mouseX = mousePoint.getX(); - int mouseY = mousePoint.getY(); - - if (!(mc.currentScreen instanceof GuiMouseInput)) { - // We only react to the mouse if our gui screen is opened. - // Otherwise we just move the mouse away so it doesn't activate any buttons - mouseX = mouseY = -1000; - } - - // Setup scrollbar and timelines - if (timelineReal.timeStart + timelineReal.zoom > 1) { - timelineReal.timeStart = 1 - timelineReal.zoom; - } - scrollbar.size = timelineReal.zoom; - scrollbar.sliderPosition = timelineReal.timeStart; - - timeline.cursorPosition = ReplayMod.replaySender.currentTimeStamp(); - timeline.timelineLength = ReplayMod.replaySender.replayLength(); - - timelineReal.cursorPosition = ReplayHandler.getRealTimelineCursor(); - - // Draw all elements - content.draw(mc, mouseX, mouseY); - content.drawOverlay(mc, mouseX, mouseY); - - GlStateManager.enableBlend(); - } - - public void togglePlayPause() { - if (ReplayMod.replaySender.paused()) { - ReplayMod.replaySender.setReplaySpeed(speedSlider.getSliderValue()); - } else { - ReplayMod.replaySender.setReplaySpeed(0); - } - } - - /** - * Render the Ambient Lighting and Path Preview indicators in the lower right corner. - * @param event Rendered post game overlay - */ - @SubscribeEvent - public void renderIndicators(RenderGameOverlayEvent.Post event) { - if (event.type != RenderGameOverlayEvent.ElementType.ALL) return; - if(!ReplayHandler.isInReplay() || mc.currentScreen instanceof NoOverlay) return; - - int xPos = WIDTH-10; - - if(ReplayMod.replaySettings.isLightingEnabled()) { - int width = 19; - - mc.renderEngine.bindTexture(replay_gui); - GlStateManager.color(1, 1, 1, 1); - GlStateManager.enableAlpha(); - GlStateManager.disableLighting(); - Gui.drawModalRectWithCustomSizedTexture(xPos-width, HEIGHT - 10 - 13, - 90, 20, 19, 13, TEXTURE_SIZE, TEXTURE_SIZE); - - xPos -= width + 5; - } - - if(ReplayMod.replaySettings.showPathPreview()) { - int width = 20; - - mc.renderEngine.bindTexture(replay_gui); - GlStateManager.color(1, 1, 1, 1); - GlStateManager.enableAlpha(); - GlStateManager.disableLighting(); - Gui.drawModalRectWithCustomSizedTexture(xPos - width, HEIGHT - 10 - 13, - 100, 0, 20, 13, TEXTURE_SIZE, TEXTURE_SIZE); - - //noinspection UnusedAssignment - xPos -= width + 5; - } - - //can be continued - } - - /** - * Dummy interface for GUI on which this replay overlay shall not be rendered. - */ - public interface NoOverlay { - - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditingProcess.java b/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditingProcess.java index 17e10222..27622be9 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditingProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditingProcess.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.replayeditor; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar; import net.minecraft.client.gui.GuiButton; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditor.java b/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditor.java index 48182a15..ab7d93ad 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditor.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replayeditor/GuiReplayEditor.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.replayeditor; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.elements.GuiDropdown; import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry; diff --git a/src/main/java/eu/crushedpixel/replaymod/holders/Marker.java b/src/main/java/eu/crushedpixel/replaymod/holders/Marker.java deleted file mode 100644 index 32071cb5..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/holders/Marker.java +++ /dev/null @@ -1,33 +0,0 @@ -package eu.crushedpixel.replaymod.holders; - -import eu.crushedpixel.replaymod.interpolation.GenericLinearInterpolation; -import eu.crushedpixel.replaymod.interpolation.GenericSplineInterpolation; -import eu.crushedpixel.replaymod.interpolation.Interpolation; -import eu.crushedpixel.replaymod.interpolation.KeyframeValue; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class Marker implements KeyframeValue { - - private String name; - private AdvancedPosition position; - - @Override - public KeyframeValue newInstance() { - return new Marker(); - } - - @Override - public Interpolation getLinearInterpolator() { - return new GenericLinearInterpolation(); - } - - @Override - public Interpolation getCubicInterpolator() { - return new GenericSplineInterpolation(); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java b/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java deleted file mode 100644 index fb26f223..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/holders/PlayerVisibility.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.crushedpixel.replaymod.holders; - -import lombok.AllArgsConstructor; -import lombok.Data; - -import java.util.UUID; - -@Data -@AllArgsConstructor -public class PlayerVisibility { - private UUID[] hidden; -} diff --git a/src/main/java/eu/crushedpixel/replaymod/interpolation/AdvancedPositionKeyframeList.java b/src/main/java/eu/crushedpixel/replaymod/interpolation/AdvancedPositionKeyframeList.java index c27bdfa6..a1d03c49 100644 --- a/src/main/java/eu/crushedpixel/replaymod/interpolation/AdvancedPositionKeyframeList.java +++ b/src/main/java/eu/crushedpixel/replaymod/interpolation/AdvancedPositionKeyframeList.java @@ -3,8 +3,6 @@ package eu.crushedpixel.replaymod.interpolation; import eu.crushedpixel.replaymod.holders.AdvancedPosition; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.SpectatorData; -import eu.crushedpixel.replaymod.holders.TimestampValue; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import lombok.NoArgsConstructor; import java.util.ListIterator; @@ -56,17 +54,18 @@ public class AdvancedPositionKeyframeList extends KeyframeList spectatorInterpolation = new SpectatorDataInterpolation(linear); } int keyframeTimestamp = keyframe.getRealTimestamp(); - TimestampValue timestampValue = ReplayHandler.getTimeKeyframes().getInterpolatedValueForTimestamp(keyframeTimestamp, true); - int replayTimestamp = timestampValue == null ? 0 : timestampValue.asInt(); - if(firstTimestamp == -1) firstTimestamp = replayTimestamp; - spectatorInterpolation.addPoint(keyframe, replayTimestamp); - if(iterator.hasNext()) { - keyframe = iterator.next(); - found = keyframe.getValue() instanceof SpectatorData; - if(!found) completedKeyframes.add(keyframe); - } else { - found = false; - } + // TODO +// TimestampValue timestampValue = ReplayHandler.getTimeKeyframes().getInterpolatedValueForTimestamp(keyframeTimestamp, true); +// int replayTimestamp = timestampValue == null ? 0 : timestampValue.asInt(); +// if(firstTimestamp == -1) firstTimestamp = replayTimestamp; +// spectatorInterpolation.addPoint(keyframe, replayTimestamp); +// if(iterator.hasNext()) { +// keyframe = iterator.next(); +// found = keyframe.getValue() instanceof SpectatorData; +// if(!found) completedKeyframes.add(keyframe); +// } else { +// found = false; +// } } if(spectatorInterpolation != null && spectatorInterpolation.size() > 1) { diff --git a/src/main/java/eu/crushedpixel/replaymod/interpolation/SpectatorDataInterpolation.java b/src/main/java/eu/crushedpixel/replaymod/interpolation/SpectatorDataInterpolation.java index 86f61be7..bf85f566 100644 --- a/src/main/java/eu/crushedpixel/replaymod/interpolation/SpectatorDataInterpolation.java +++ b/src/main/java/eu/crushedpixel/replaymod/interpolation/SpectatorDataInterpolation.java @@ -4,7 +4,6 @@ import eu.crushedpixel.replaymod.holders.AdvancedPosition; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.SpectatorData; import eu.crushedpixel.replaymod.holders.SpectatorDataThirdPersonInfo; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; @@ -58,20 +57,21 @@ public class SpectatorDataInterpolation { //updating the spectator keyframe's position in the world to smoothly continue the path //with non-spectator position keyframes for(Pair> pair : points) { - AdvancedPosition entityPosition = ReplayHandler.getEntityPositionTracker().getEntityPositionAtTimestamp(entityID, pair.getKey()); - if(entityPosition == null) continue; - - //transform the entity position (sry for no dry code :x ) - SpectatorDataThirdPersonInfo thirdPersonInfo = ((SpectatorData)pair.getValue().getValue()).getThirdPersonInfo(); - - //first, rotate the camera pitch and yaw according to the settings - entityPosition.setYaw(entityPosition.getYaw() + thirdPersonInfo.shoulderCamYawOffset); - entityPosition.setPitch(entityPosition.getPitch() + thirdPersonInfo.shoulderCamPitchOffset); - - //next, move the camera point to fulfill the specified distance to the entity - entityPosition = entityPosition.getDestination(-1 * thirdPersonInfo.shoulderCamDistance); - - pair.getValue().getValue().apply(entityPosition); + // TODO +// AdvancedPosition entityPosition = ReplayHandler.getEntityPositionTracker().getEntityPositionAtTimestamp(entityID, pair.getKey()); +// if(entityPosition == null) continue; +// +// //transform the entity position (sry for no dry code :x ) +// SpectatorDataThirdPersonInfo thirdPersonInfo = ((SpectatorData)pair.getValue().getValue()).getThirdPersonInfo(); +// +// //first, rotate the camera pitch and yaw according to the settings +// entityPosition.setYaw(entityPosition.getYaw() + thirdPersonInfo.shoulderCamYawOffset); +// entityPosition.setPitch(entityPosition.getPitch() + thirdPersonInfo.shoulderCamPitchOffset); +// +// //next, move the camera point to fulfill the specified distance to the entity +// entityPosition = entityPosition.getDestination(-1 * thirdPersonInfo.shoulderCamDistance); +// +// pair.getValue().getValue().apply(entityPosition); } //feed the underlying keyframe list with AdvancedPosition Keyframes that are derived from the Spectator Keyframes @@ -116,17 +116,18 @@ public class SpectatorDataInterpolation { smoothness = (int)(thirdPersonInfo.shoulderCamSmoothness*1000); //calculate the Position relative to the Entity - AdvancedPosition entityPosition = ReplayHandler.getEntityPositionTracker().getEntityPositionAtTimestamp(entityID, currentTimestamp); - if(entityPosition == null) continue; - - //first, rotate the camera pitch and yaw according to the settings - entityPosition.setYaw(entityPosition.getYaw() + thirdPersonInfo.shoulderCamYawOffset); - entityPosition.setPitch(entityPosition.getPitch() + thirdPersonInfo.shoulderCamPitchOffset); - - //next, move the camera point to fulfill the specified distance to the entity - entityPosition = entityPosition.getDestination(-1 * thirdPersonInfo.shoulderCamDistance); - - underlyingKeyframes.add(new Keyframe(interpolatedRealTimestamp, entityPosition)); + // TODO +// AdvancedPosition entityPosition = ReplayHandler.getEntityPositionTracker().getEntityPositionAtTimestamp(entityID, currentTimestamp); +// if(entityPosition == null) continue; +// +// //first, rotate the camera pitch and yaw according to the settings +// entityPosition.setYaw(entityPosition.getYaw() + thirdPersonInfo.shoulderCamYawOffset); +// entityPosition.setPitch(entityPosition.getPitch() + thirdPersonInfo.shoulderCamPitchOffset); +// +// //next, move the camera point to fulfill the specified distance to the entity +// entityPosition = entityPosition.getDestination(-1 * thirdPersonInfo.shoulderCamDistance); +// +// underlyingKeyframes.add(new Keyframe(interpolatedRealTimestamp, entityPosition)); } i++; diff --git a/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java b/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java index 22075e2e..a70d54f6 100644 --- a/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java +++ b/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java @@ -2,7 +2,7 @@ package eu.crushedpixel.replaymod.localization; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableSet; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.ApiException; import net.minecraft.client.resources.IResourcePack; import net.minecraft.client.resources.data.IMetadataSection; diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java index b0c83dc4..74d308b0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java @@ -1,7 +1,7 @@ package eu.crushedpixel.replaymod.mixin; +import com.replaymod.replay.CameraEntity; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.video.EntityRendererHandler; import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer; @@ -18,6 +18,7 @@ import net.minecraft.util.MovingObjectPosition; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.Project; 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.Redirect; @@ -25,6 +26,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderer.class) public abstract class MixinEntityRenderer implements EntityRendererHandler.IEntityRenderer, EntityRendererHandler.GluPerspective { + @Shadow + public Minecraft mc; + private EntityRendererHandler handler; private SpectatorRenderer spectatorRenderer = new SpectatorRenderer(); @@ -65,8 +69,8 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti if (options.getIgnoreCameraRotation()[1]) { entity.prevRotationPitch = entity.rotationPitch = 0; } - if (options.getIgnoreCameraRotation()[2]) { - ReplayHandler.setCameraTilt(0); + if (options.getIgnoreCameraRotation()[2] && entity instanceof CameraEntity) { + ((CameraEntity) entity).roll = 0; } } } @@ -85,7 +89,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti orgPitch = entity.rotationPitch; orgPrevYaw = entity.prevRotationYaw; orgPrevPitch = entity.prevRotationPitch; - orgRoll = ReplayHandler.getCameraTilt(); + orgRoll = entity instanceof CameraEntity ? ((CameraEntity) entity).roll : 0; } } @@ -97,28 +101,31 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti entity.rotationPitch = orgPitch; entity.prevRotationYaw = orgPrevYaw; entity.prevRotationPitch = orgPrevPitch; - ReplayHandler.setCameraTilt(orgRoll); + if (entity instanceof CameraEntity) { + ((CameraEntity) entity).roll = orgRoll; + } } } @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) private void renderSpectatorHand(float partialTicks, int renderPass, CallbackInfo ci) { - if (handler != null) { - if (handler.data instanceof CubicOpenGlFrameCapturer.Data) { - ci.cancel(); - return; // No spectator hands during 360° view, we wouldn't even know where to put it - } - Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity(); - if (!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) { - renderPass = handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0; - spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); - } - } else if (ReplayHandler.isInReplay() && !ReplayHandler.isCamera()) { - Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity(); - if (!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) { - spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); - } - } + // TODO +// if (handler != null) { +// if (handler.data instanceof CubicOpenGlFrameCapturer.Data) { +// ci.cancel(); +// return; // No spectator hands during 360° view, we wouldn't even know where to put it +// } +// Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity(); +// if (!ReplayHandler.isCameraView() && currentEntity instanceof EntityPlayer) { +// renderPass = handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0; +// spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); +// } +// } else if (ReplayHandler.isInReplay() && !ReplayHandler.isCameraView()) { +// Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity(); +// if (!ReplayHandler.isCameraView() && currentEntity instanceof EntityPlayer) { +// spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); +// } +// } } @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V")) @@ -242,8 +249,8 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti @Inject(method = "orientCamera", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;translate(FFF)V", shift = At.Shift.AFTER, ordinal = 3)) private void setupCameraRoll(float partialTicks, CallbackInfo ci) { - if (ReplayHandler.isInReplay()) { - GL11.glRotated(ReplayHandler.getCameraTilt(), 0D, 0D, 1D); + if (mc.getRenderViewEntity() instanceof CameraEntity) { + GL11.glRotated(((CameraEntity) mc.getRenderViewEntity()).roll, 0D, 0D, 1D); } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java index 050bf313..8c5c75f6 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java @@ -1,17 +1,22 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.replay.ReplayHandler; +import com.replaymod.replay.CameraEntity; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiSpectator; 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; @Mixin(GuiSpectator.class) public abstract class MixinGuiSpectator { + @Shadow + private Minecraft field_175268_g; + @Inject(method = "func_175260_a", at = @At("HEAD"), cancellable = true) public void isInReplay(int i, CallbackInfo ci) { - if (ReplayHandler.isInReplay()) { + if (field_175268_g.thePlayer instanceof CameraEntity) { ci.cancel(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinMinecraft.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinMinecraft.java index df9f7665..8b0a71ff 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinMinecraft.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinMinecraft.java @@ -1,6 +1,5 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.SoundHandler; import net.minecraft.entity.player.EntityPlayer; @@ -12,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; public class MixinMinecraft { @Redirect(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/audio/SoundHandler;setListener(Lnet/minecraft/entity/player/EntityPlayer;F)V")) public void setSoundSystemListener(SoundHandler soundHandler, EntityPlayer listener, float renderPartialTicks) { - soundHandler.setListener(ReplayHandler.isInReplay() ? ReplayHandler.getCameraEntity() : listener, renderPartialTicks); + //TODO might no longer be necessary? +// soundHandler.setListener(ReplayHandler.isInReplay() ? ReplayHandler.getCameraEntity() : listener, renderPartialTicks); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java index b6daa62d..87a54bf0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java @@ -1,7 +1,7 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.replay.ReplayHandler; +import com.replaymod.replay.CameraEntity; +import com.replaymod.replay.ReplayModReplay; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.multiplayer.PlayerControllerMP; @@ -25,7 +25,7 @@ public abstract class MixinPlayerControllerMP { @Inject(method = "func_178892_a", at=@At("HEAD"), cancellable = true) public void createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable ci) { - if (ReplayHandler.isInReplay()) { + if (ReplayModReplay.instance.getReplayHandler() != null) { ci.setReturnValue(new CameraEntity(mc, worldIn, netClientHandler, statFileWriter)); ci.cancel(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderArrow.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderArrow.java index f74fb51d..3482eeea 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderArrow.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderArrow.java @@ -1,11 +1,8 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderArrow; import net.minecraft.client.renderer.entity.RenderManager; -import net.minecraft.entity.Entity; import org.spongepowered.asm.mixin.Mixin; @Mixin(RenderArrow.class) @@ -14,8 +11,9 @@ public abstract class MixinRenderArrow extends Render { super(renderManager); } - @Override - public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) { - return ReplayHandler.isInReplay() || super.shouldRender(entity, camera, camX, camY, camZ); - } + // TODO +// @Override +// public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) { +// return ReplayHandler.isInReplay() || super.shouldRender(entity, camera, camX, camY, camZ); +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderGlobal.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderGlobal.java deleted file mode 100644 index d951898a..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderGlobal.java +++ /dev/null @@ -1,32 +0,0 @@ -package eu.crushedpixel.replaymod.mixin; - -import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; -import eu.crushedpixel.replaymod.timer.EnchantmentTimer; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.RenderGlobal; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.play.server.S25PacketBlockBreakAnim; -import net.minecraft.util.BlockPos; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(RenderGlobal.class) -public abstract class MixinRenderGlobal { - @Inject(method = "sendBlockBreakProgress", at = @At("HEAD")) - public void saveBlockBreakProgressPacket(int breakerId, BlockPos pos, int progress, CallbackInfo info) { - if(ConnectionEventHandler.isRecording()) { - EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer; - if(thePlayer != null && breakerId == thePlayer.getEntityId()) { - ConnectionEventHandler.insertPacket(new S25PacketBlockBreakAnim(breakerId, pos, progress)); - } - } - } - - @Redirect(method = "renderWorldBorder", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J")) - private long getEnchantmentTime() { - return EnchantmentTimer.getEnchantmentTime(); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRendererLivingEntity.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRendererLivingEntity.java index 2aabf70c..2dd14743 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRendererLivingEntity.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRendererLivingEntity.java @@ -1,7 +1,5 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.video.EntityRendererHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.entity.RendererLivingEntity; @@ -22,17 +20,19 @@ public abstract class MixinRendererLivingEntity { ci.setReturnValue(false); //this calls the cancel method } - if(ReplayHandler.isInReplay() && entity.isInvisible() - && ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.FALSE) { - ci.setReturnValue(false); - } + // TODO +// if(ReplayHandler.isInReplay() && entity.isInvisible() +// && ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.FALSE) { +// ci.setReturnValue(false); +// } } @Redirect(method = "renderModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityLivingBase;isInvisibleToPlayer(Lnet/minecraft/entity/player/EntityPlayer;)Z")) private boolean shouldInvisibleNotBeRendered(EntityLivingBase entity, EntityPlayer thePlayer) { - if(ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.TRUE|| !ReplayHandler.isInReplay()) { - return entity.isInvisibleToPlayer(thePlayer); - } + // TODO +// if(ReplaySettings.ReplayOptions.renderInvisible.getValue() == Boolean.TRUE|| !ReplayHandler.isInReplay()) { +// return entity.isInvisibleToPlayer(thePlayer); +// } return true; //the original method inverts the return value } } diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinViewFrustum.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinViewFrustum.java index f63a1b7b..2ffcd735 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinViewFrustum.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinViewFrustum.java @@ -1,6 +1,5 @@ package eu.crushedpixel.replaymod.mixin; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.ViewFrustum; import net.minecraft.client.renderer.chunk.IRenderChunkFactory; @@ -39,9 +38,10 @@ public abstract class MixinViewFrustum { */ @Inject(method = "updateChunkPositions", at = @At("HEAD"), cancellable = true) public void fixedUpdateChunkPositions(double viewEntityX, double viewEntityZ, CallbackInfo ci) { - if (!ReplayHandler.isInReplay()) { - return; - } + // TODO +// if (!ReplayHandler.isInReplay()) { +// return; +// } int i = MathHelper.floor_double(viewEntityX) - 8; int j = MathHelper.floor_double(viewEntityZ) - 8; diff --git a/src/main/java/eu/crushedpixel/replaymod/online/urischeme/LinuxUriScheme.java b/src/main/java/eu/crushedpixel/replaymod/online/urischeme/LinuxUriScheme.java index b9597534..340d9822 100644 --- a/src/main/java/eu/crushedpixel/replaymod/online/urischeme/LinuxUriScheme.java +++ b/src/main/java/eu/crushedpixel/replaymod/online/urischeme/LinuxUriScheme.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.online.urischeme; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.StringBuilderWriter; diff --git a/src/main/java/eu/crushedpixel/replaymod/online/urischeme/WindowsUriScheme.java b/src/main/java/eu/crushedpixel/replaymod/online/urischeme/WindowsUriScheme.java index 146d3de1..2d614a41 100644 --- a/src/main/java/eu/crushedpixel/replaymod/online/urischeme/WindowsUriScheme.java +++ b/src/main/java/eu/crushedpixel/replaymod/online/urischeme/WindowsUriScheme.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.online.urischeme; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.StringBuilderWriter; diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/DataListener.java b/src/main/java/eu/crushedpixel/replaymod/recording/DataListener.java deleted file mode 100755 index ea88b3cf..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/recording/DataListener.java +++ /dev/null @@ -1,197 +0,0 @@ -package eu.crushedpixel.replaymod.recording; - -import com.google.common.hash.Hashing; -import com.google.common.io.Files; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.Marker; -import eu.crushedpixel.replaymod.holders.PacketData; -import eu.crushedpixel.replaymod.utils.ReplayFile; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import org.apache.commons.io.FileUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.*; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -public abstract class DataListener extends ChannelInboundHandlerAdapter { - - private static final Logger logger = LogManager.getLogger(); - - protected File file; - protected Long startTime = null; - protected String name; - protected String worldName; - protected boolean serverWasPaused; - protected long lastSentPacket = 0; - protected boolean alive = true; - protected DataWriter dataWriter; - protected Set players = new HashSet(); - protected Set> markers = new HashSet>(); - private boolean singleplayer; - - private int saveState = 0; //0: Idle, 1: Saving, 2: Saved - - private final File tempResourcePacksFolder = Files.createTempDir(); - private final Map requestToHash = new ConcurrentHashMap(); - private final Map resourcePacks = new HashMap(); - - public DataListener(File file, String name, String worldName, long startTime, boolean singleplayer) throws FileNotFoundException { - this.file = file; - this.startTime = startTime; - this.name = name; - this.worldName = worldName; - this.singleplayer = singleplayer; - - FileOutputStream fos = new FileOutputStream(file); - BufferedOutputStream bos = new BufferedOutputStream(fos); - DataOutputStream out = new DataOutputStream(bos); - dataWriter = new DataWriter(out); - - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - @Override - public void run() { - try { - if(saveState == 0) { - System.out.println("Saving Replay File to prevent Corruption"); - DataListener.this.channelInactive(null); - } - } catch(Exception e) { - e.printStackTrace(); - } - } - }, "shutdown-hook-data-listener")); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - dataWriter.requestFinish(players, markers); - } - - protected void recordResourcePack(File file, int requestId) { - try { - String hash = Hashing.sha1().hashBytes(Files.toByteArray(file)).toString(); - requestToHash.put(requestId, hash); - synchronized (resourcePacks) { - if (!resourcePacks.containsKey(hash)) { - File tempFile = new File(tempResourcePacksFolder, hash); - FileUtils.copyFile(file, tempFile); - resourcePacks.put(hash, tempFile); - } - } - } catch (IOException e) { - logger.warn("Failed to save resource pack.", e); - } - } - - public class DataWriter { - - private boolean active = true; - private long paused; - - private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); - private DataOutputStream stream; - - Thread outputThread = new Thread(new Runnable() { - - @Override - public void run() { - - while(active) { - PacketData dataReciever = queue.poll(); - if(dataReciever != null) { - //write the ByteBuf to the given OutputStream - - byte[] array = dataReciever.getByteArray(); - - if(array != null) { - try { - ReplayFileIO.writePacket(dataReciever, stream); - stream.flush(); - } catch(Exception e) { - e.printStackTrace(); - } - } - - } else { - try { - //let the Thread sleep for 1/4 second and queue up new Packets - Thread.sleep(250L); - } catch(InterruptedException e) { - e.printStackTrace(); - } - } - } - - try { - stream.flush(); - stream.close(); - } catch(Exception e) { - e.printStackTrace(); - } - - } - }, "replaymod-packet-writer"); - - public DataWriter(DataOutputStream stream) { - this.stream = stream; - outputThread.start(); - } - - public synchronized void writePacket(byte[] bytes) { - long now = System.currentTimeMillis(); - if(startTime == null) { - startTime = now; - } - - if (serverWasPaused) { - paused = now - startTime - lastSentPacket; - serverWasPaused = false; - } - int timestamp = (int) (now - startTime - paused); - lastSentPacket = timestamp; - queue.add(new PacketData(bytes, timestamp)); - } - - public void requestFinish(Set players, Set> markers) { - active = false; - - try { - ReplayMod.replayFileAppender.startNewReplayFileWriting(); - saveState = 1; - - String mcversion = ReplayMod.getMinecraftVersion(); - - String[] pl = players.toArray(new String[players.size()]); - - String generator = "ReplayMod v" + ReplayMod.getContainer().getVersion(); - - ReplayMetaData metaData = new ReplayMetaData(singleplayer, worldName, generator, (int) lastSentPacket, startTime, pl, mcversion); - - File folder = ReplayFileIO.getReplayFolder(); - - File archive = new File(folder, name + ReplayFile.ZIP_FILE_EXTENSION); - ReplayFileIO.writeReplayFile(archive, file, metaData, markers, resourcePacks, requestToHash); - - FileUtils.forceDelete(file); - FileUtils.deleteDirectory(tempResourcePacksFolder); - - } catch(Exception e) { - e.printStackTrace(); - } finally { - ReplayMod.replayFileAppender.replayFileWritingFinished(); - saveState = 2; - } - } - - } - -} diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/ReplayMetaData.java b/src/main/java/eu/crushedpixel/replaymod/recording/ReplayMetaData.java deleted file mode 100755 index 1ba6d590..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/recording/ReplayMetaData.java +++ /dev/null @@ -1,24 +0,0 @@ -package eu.crushedpixel.replaymod.recording; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data -@AllArgsConstructor -public class ReplayMetaData { - - private boolean singleplayer; - private String serverName; - private String generator; - private int duration; - private long date; - private String[] players; - private String mcversion; - - public ReplayMetaData copy() { - return new ReplayMetaData(this.singleplayer, this.serverName, this.generator, - this.duration, this.date, this.players, this.mcversion); - } - - public void removeServer() { this.serverName = null; } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java index dd02b0b3..b183b624 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/DownloadedFileHandler.java @@ -1,8 +1,7 @@ package eu.crushedpixel.replaymod.registry; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; -import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; @@ -35,7 +34,7 @@ public class DownloadedFileHandler { } private File generateFileForID(int id) { - return new File(downloadFolder, id+ReplayFile.ZIP_FILE_EXTENSION); + return new File(downloadFolder, id+ ".zip"); } public void addToIndex(int id) { diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/FavoritedFileHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/FavoritedFileHandler.java index eb84b52a..d13db16e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/FavoritedFileHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/FavoritedFileHandler.java @@ -1,7 +1,7 @@ package eu.crushedpixel.replaymod.registry; import com.google.common.primitives.Ints; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.ApiException; import java.io.IOException; diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java index ef3861d7..b7eea11e 100755 --- a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java @@ -45,7 +45,6 @@ public class KeybindRegistry { replayModKeyBindings.add(new KeyBinding(KEY_KEYFRAME_PRESETS, Keyboard.KEY_X, "replaymod.title")); replayModKeyBindings.add(new KeyBinding(KEY_PATH_PREVIEW, Keyboard.KEY_H, "replaymod.title")); - replayModKeyBindings.add(new KeyBinding(KEY_ADD_MARKER, Keyboard.KEY_M, "replaymod.title")); replayModKeyBindings.add(new KeyBinding(KEY_SYNC_TIMELINE, Keyboard.KEY_V, "replaymod.title")); replayModKeyBindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_N, "replaymod.title")); diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/LightingHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/LightingHandler.java index 509f44b4..5ba5dcd7 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/LightingHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/LightingHandler.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.registry; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.GameSettings.Options; diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java deleted file mode 100755 index 55812d8e..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -package eu.crushedpixel.replaymod.registry; - -import com.google.common.base.Predicate; -import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.gui.GuiPlayerOverview; -import eu.crushedpixel.replaymod.holders.PlayerVisibility; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.EntityPlayer; - -import java.util.*; - -public class PlayerHandler { - - private static Minecraft mc = Minecraft.getMinecraft(); - - private static Predicate playerPredicate = new Predicate() { - @Override - public boolean apply(EntityPlayer input) { - return !(input instanceof CameraEntity || input == mc.thePlayer); - } - }; - - private static Set hidden = new HashSet(); - - public static void hidePlayer(EntityPlayer player) { - hidden.remove(player.getUniqueID()); - hidden.add(player.getUniqueID()); - } - - public static void showPlayer(EntityPlayer player) { - hidden.remove(player.getUniqueID()); - } - - public static void setIsVisible(EntityPlayer player, boolean visible) { - if(visible) showPlayer(player); - else hidePlayer(player); - } - - public static void loadPlayerVisibilityConfiguration(PlayerVisibility visibility) { - resetHiddenPlayers(); - if(visibility != null) { - GuiPlayerOverview.defaultSave = true; - Collections.addAll(hidden, visibility.getHidden()); - } else { - GuiPlayerOverview.defaultSave = false; - } - } - - public static Set getHiddenPlayers() { - return hidden; - } - - public static boolean isHidden(UUID uuid) { - return hidden.contains(uuid); - } - - public static void resetHiddenPlayers() { - hidden.clear(); - } - - public static void openPlayerOverview() { - if(!ReplayHandler.isInReplay()) { - return; - } - - @SuppressWarnings("unchecked") - List players = mc.theWorld.getEntities(EntityPlayer.class, playerPredicate); - mc.displayGuiScreen(new GuiPlayerOverview(players)); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/RatedFileHandler.java b/src/main/java/eu/crushedpixel/replaymod/registry/RatedFileHandler.java index 03d98489..c8798352 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/RatedFileHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/RatedFileHandler.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.registry; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.api.ApiException; import eu.crushedpixel.replaymod.api.replay.holders.FileRating; import eu.crushedpixel.replaymod.api.replay.holders.Rating; diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java b/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java index d5cd3864..59e12624 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/ReplayFileAppender.java @@ -2,7 +2,7 @@ package eu.crushedpixel.replaymod.registry; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; -import eu.crushedpixel.replaymod.events.ReplayExitEvent; +import com.replaymod.replay.events.ReplayCloseEvent; import eu.crushedpixel.replaymod.gui.GuiReplaySaving; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import net.minecraft.client.Minecraft; @@ -91,7 +91,7 @@ public class ReplayFileAppender { } @SubscribeEvent - public void onReplayExit(ReplayExitEvent event) { + public void onReplayExit(ReplayCloseEvent.Post event) { if(!filesToRewrite.isEmpty()) { openGuiSavingScreen(); writeFiles(); diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/CustomObjectRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/CustomObjectRenderer.java index f75873d0..24c2f791 100644 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/CustomObjectRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/CustomObjectRenderer.java @@ -1,19 +1,8 @@ package eu.crushedpixel.replaymod.renderer; -import eu.crushedpixel.replaymod.assets.CustomImageObject; -import eu.crushedpixel.replaymod.gui.GuiObjectManager; -import eu.crushedpixel.replaymod.holders.Position; -import eu.crushedpixel.replaymod.holders.Transformation; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplayProcess; 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.util.ResourceLocation; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; /** * Allows users to render custom images in the World. @@ -24,91 +13,92 @@ public class CustomObjectRenderer { @SubscribeEvent public void renderCustomObjects(RenderWorldLastEvent event) { - if(!ReplayHandler.isInReplay() || mc.getRenderViewEntity() == null || ReplayHandler.getCustomImageObjects().isEmpty()) return; - - double dX = mc.getRenderViewEntity().lastTickPosX + (mc.getRenderViewEntity().posX - mc.getRenderViewEntity().lastTickPosX) * (double)event.partialTicks; - double dY = mc.getRenderViewEntity().lastTickPosY + (mc.getRenderViewEntity().posY - mc.getRenderViewEntity().lastTickPosY) * (double)event.partialTicks; - double dZ = mc.getRenderViewEntity().lastTickPosZ + (mc.getRenderViewEntity().posZ - mc.getRenderViewEntity().lastTickPosZ) * (double)event.partialTicks; - - GlStateManager.enableTexture2D(); - - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - - for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) { - drawCustomImageObject(dX, dY, dZ, object); - } - } - - private void drawCustomImageObject(double playerX, double playerY, double playerZ, CustomImageObject customImageObject) { - ResourceLocation resourceLocation = customImageObject.getResourceLocation(); - - if(customImageObject.getLinkedAsset() == null - || ReplayHandler.getAssetRepository().getAssetByUUID(customImageObject.getLinkedAsset()) == null - || resourceLocation == null) return; - - GlStateManager.pushMatrix(); - GlStateManager.pushAttrib(); - - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer renderer = tessellator.getWorldRenderer(); - - mc.renderEngine.bindTexture(resourceLocation); - - int renderTimestamp; - if(mc.currentScreen instanceof GuiObjectManager) { - renderTimestamp = ((GuiObjectManager) mc.currentScreen).getObjectKeyframeTimeline().cursorPosition; - } else if(ReplayProcess.isVideoRecording()) { - renderTimestamp = ReplayProcess.getVideoRenderer().getVideoTime(); - } else { - renderTimestamp = ReplayHandler.getRealTimelineCursor(); - } - - Transformation transformation = customImageObject.getTransformations().getTransformationForTimestamp(renderTimestamp); - - Position objectAnchor = transformation.getAnchor(); - Position objectPosition = transformation.getPosition(); - Position objectOrientation = transformation.getOrientation(); - - double x = objectPosition.getX() - playerX; - double y = objectPosition.getY() - playerY; - double z = objectPosition.getZ() - playerZ; - - GL11.glNormal3f(0, 1, 0); - - GlStateManager.translate(x, y + 1.4, z); - - GlStateManager.rotate((float) -objectOrientation.getX(), 0, 1, 0); - GlStateManager.rotate((float) objectOrientation.getY(), 0, 0, 1); - GlStateManager.rotate((float) objectOrientation.getZ(), 1, 0, 0); - - float opacity = (float)transformation.getOpacity() / 100; - GlStateManager.color(1, 1, 1, opacity); - - float width = (float)(customImageObject.getWidth() * transformation.getScale().getX() / 100f); - float height = (float)(customImageObject.getHeight() * transformation.getScale().getY() / 100f); - - float minX = (float)(-width/2 + objectAnchor.getX()); - float maxX = (float)(width/2 + objectAnchor.getX()); - float minY = (float)(-height/2 + objectAnchor.getY()); - float maxY = (float)(height/2 + objectAnchor.getY()); - - renderer.startDrawingQuads(); - - renderer.addVertexWithUV(minX, minY, 0, 1, 1); - renderer.addVertexWithUV(minX, maxY, 0, 1, 0); - renderer.addVertexWithUV(maxX, maxY, 0, 0, 0); - renderer.addVertexWithUV(maxX, minY, 0, 0, 1); - - renderer.addVertexWithUV(maxX, maxY, 0, 0, 0); - renderer.addVertexWithUV(minX, maxY, 0, 1, 0); - renderer.addVertexWithUV(minX, minY, 0, 1, 1); - renderer.addVertexWithUV(maxX, minY, 0, 0, 1); - - tessellator.draw(); - renderer.setTranslation(0, 0, 0); - - GlStateManager.popAttrib(); - GlStateManager.popMatrix(); + // TODO +// if(!ReplayHandler.isInReplay() || mc.getRenderViewEntity() == null || ReplayHandler.getCustomImageObjects().isEmpty()) return; +// +// double dX = mc.getRenderViewEntity().lastTickPosX + (mc.getRenderViewEntity().posX - mc.getRenderViewEntity().lastTickPosX) * (double)event.partialTicks; +// double dY = mc.getRenderViewEntity().lastTickPosY + (mc.getRenderViewEntity().posY - mc.getRenderViewEntity().lastTickPosY) * (double)event.partialTicks; +// double dZ = mc.getRenderViewEntity().lastTickPosZ + (mc.getRenderViewEntity().posZ - mc.getRenderViewEntity().lastTickPosZ) * (double)event.partialTicks; +// +// GlStateManager.enableTexture2D(); +// +// GlStateManager.enableBlend(); +// GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); +// +// for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) { +// drawCustomImageObject(dX, dY, dZ, object); +// } +// } +// +// private void drawCustomImageObject(double playerX, double playerY, double playerZ, CustomImageObject customImageObject) { +// ResourceLocation resourceLocation = customImageObject.getResourceLocation(); +// +// if(customImageObject.getLinkedAsset() == null +// || ReplayHandler.getAssetRepository().getAssetByUUID(customImageObject.getLinkedAsset()) == null +// || resourceLocation == null) return; +// +// GlStateManager.pushMatrix(); +// GlStateManager.pushAttrib(); +// +// Tessellator tessellator = Tessellator.getInstance(); +// WorldRenderer renderer = tessellator.getWorldRenderer(); +// +// mc.renderEngine.bindTexture(resourceLocation); +// +// int renderTimestamp; +// if(mc.currentScreen instanceof GuiObjectManager) { +// renderTimestamp = ((GuiObjectManager) mc.currentScreen).getObjectKeyframeTimeline().cursorPosition; +// } else if(ReplayProcess.isVideoRecording()) { +// renderTimestamp = ReplayProcess.getVideoRenderer().getVideoTime(); +// } else { +// renderTimestamp = ReplayHandler.getRealTimelineCursor(); +// } +// +// Transformation transformation = customImageObject.getTransformations().getTransformationForTimestamp(renderTimestamp); +// +// Position objectAnchor = transformation.getAnchor(); +// Position objectPosition = transformation.getPosition(); +// Position objectOrientation = transformation.getOrientation(); +// +// double x = objectPosition.getX() - playerX; +// double y = objectPosition.getY() - playerY; +// double z = objectPosition.getZ() - playerZ; +// +// GL11.glNormal3f(0, 1, 0); +// +// GlStateManager.translate(x, y + 1.4, z); +// +// GlStateManager.rotate((float) -objectOrientation.getX(), 0, 1, 0); +// GlStateManager.rotate((float) objectOrientation.getY(), 0, 0, 1); +// GlStateManager.rotate((float) objectOrientation.getZ(), 1, 0, 0); +// +// float opacity = (float)transformation.getOpacity() / 100; +// GlStateManager.color(1, 1, 1, opacity); +// +// float width = (float)(customImageObject.getWidth() * transformation.getScale().getX() / 100f); +// float height = (float)(customImageObject.getHeight() * transformation.getScale().getY() / 100f); +// +// float minX = (float)(-width/2 + objectAnchor.getX()); +// float maxX = (float)(width/2 + objectAnchor.getX()); +// float minY = (float)(-height/2 + objectAnchor.getY()); +// float maxY = (float)(height/2 + objectAnchor.getY()); +// +// renderer.startDrawingQuads(); +// +// renderer.addVertexWithUV(minX, minY, 0, 1, 1); +// renderer.addVertexWithUV(minX, maxY, 0, 1, 0); +// renderer.addVertexWithUV(maxX, maxY, 0, 0, 0); +// renderer.addVertexWithUV(maxX, minY, 0, 0, 1); +// +// renderer.addVertexWithUV(maxX, maxY, 0, 0, 0); +// renderer.addVertexWithUV(minX, maxY, 0, 1, 0); +// renderer.addVertexWithUV(minX, minY, 0, 1, 1); +// renderer.addVertexWithUV(maxX, minY, 0, 0, 1); +// +// tessellator.draw(); +// renderer.setTranslation(0, 0, 0); +// +// GlStateManager.popAttrib(); +// GlStateManager.popMatrix(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/InvisibilityRender.java b/src/main/java/eu/crushedpixel/replaymod/renderer/InvisibilityRender.java index cfb56cd2..586be482 100644 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/InvisibilityRender.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/InvisibilityRender.java @@ -1,8 +1,5 @@ package eu.crushedpixel.replaymod.renderer; -import eu.crushedpixel.replaymod.registry.PlayerHandler; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.entity.RenderPlayer; @@ -20,8 +17,10 @@ public class InvisibilityRender extends RenderPlayer { @Override public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) { - return !(PlayerHandler.isHidden(entity.getUniqueID()) || (ReplayHandler.isInReplay() - && entity == Minecraft.getMinecraft().thePlayer)) - && super.shouldRender(entity, camera, camX, camY, camZ); + // TODO + return false; +// return !(PlayerHandler.isHidden(entity.getUniqueID()) || (ReplayHandler.isInReplay() +// && entity == Minecraft.getMinecraft().thePlayer)) +// && super.shouldRender(entity, camera, camX, camY, camZ); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java index 7b4e9742..31ffbf1e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/PathPreviewRenderer.java @@ -1,28 +1,23 @@ 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.AdvancedPosition; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.SpectatorData; import eu.crushedpixel.replaymod.interpolation.AdvancedPositionKeyframeList; -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.minecraft.util.ResourceLocation; 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; + +import static com.replaymod.core.ReplayMod.TEXTURE; public class PathPreviewRenderer { @@ -38,83 +33,85 @@ public class PathPreviewRenderer { @SubscribeEvent public void renderCameraPath(RenderWorldLastEvent event) { - if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview() || mc.gameSettings.hideGUI) return; - - GlStateManager.pushAttrib(); - - int renderDistanceSquared = mc.gameSettings.renderDistanceChunks*16 * mc.gameSettings.renderDistanceChunks*16; - - Entity entity = ReplayHandler.getCameraEntity(); - if(entity == null) return; - - double doubleX = entity.posX; - double doubleY = entity.posY; - double doubleZ = entity.posZ; - - GlStateManager.disableLighting(); - GlStateManager.disableTexture2D(); - GlStateManager.enableBlend(); - - if(keyframes.size() > 1) { - AdvancedPosition previousPosition = null; - - int i = 0; - for(Keyframe keyframe : keyframes) { - int timestamp = keyframe.getRealTimestamp(); - int nextTimestamp = timestamp; - - if(i+1 < keyframes.size()) { - nextTimestamp = keyframes.get(i+1).getRealTimestamp(); - } - - int diff = nextTimestamp-timestamp; - int step = diff/100; - - for(int currentTimestamp = timestamp; currentTimestamp < nextTimestamp; currentTimestamp += step) { - AdvancedPosition position = keyframes.getInterpolatedValueForTimestamp(currentTimestamp, ReplayMod.replaySettings.isLinearMovement()); - if(previousPosition != null) { - drawConnection(doubleX, doubleY, doubleZ, previousPosition, position, DEFAULT_PATH_COLOR, renderDistanceSquared); - } - previousPosition = position; - } - - i++; - } - } - - distanceComparator.setPlayerPos(doubleX, doubleY + 1.4, doubleZ); - - List> distanceSorted = new ArrayList>(keyframes); - Collections.sort(distanceSorted, distanceComparator); - - GlStateManager.enableTexture2D(); - GlStateManager.blendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR); - - GlStateManager.disableDepth(); - - for(Keyframe kf : distanceSorted) { - if(kf.getValue().distanceSquared(entity.posX, entity.posY, entity.posZ) < renderDistanceSquared) { - drawPoint(doubleX, doubleY, doubleZ, kf); - } - } - - if(ReplayHandler.getPositionKeyframes().size() > 1) { - AdvancedPosition cameraPosition = ReplayHandler.getPositionKeyframes().getInterpolatedValueForTimestamp(ReplayHandler.getRealTimelineCursor(), - ReplayMod.replaySettings.isLinearMovement()); - if(cameraPosition != null) { - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - drawCamera(doubleX, doubleY, doubleZ, cameraPosition); - } - } - - GlStateManager.disableBlend(); - - GlStateManager.popAttrib(); + // TODO +// if(!ReplayHandler.isInReplay() || ReplayHandler.isInPath() || !ReplayMod.replaySettings.showPathPreview() || mc.gameSettings.hideGUI) return; +// +// GlStateManager.pushAttrib(); +// +// int renderDistanceSquared = mc.gameSettings.renderDistanceChunks*16 * mc.gameSettings.renderDistanceChunks*16; +// +// Entity entity = ReplayHandler.getCameraEntity(); +// if(entity == null) return; +// +// double doubleX = entity.posX; +// double doubleY = entity.posY; +// double doubleZ = entity.posZ; +// +// GlStateManager.disableLighting(); +// GlStateManager.disableTexture2D(); +// GlStateManager.enableBlend(); +// +// if(keyframes.size() > 1) { +// AdvancedPosition previousPosition = null; +// +// int i = 0; +// for(Keyframe keyframe : keyframes) { +// int timestamp = keyframe.getRealTimestamp(); +// int nextTimestamp = timestamp; +// +// if(i+1 < keyframes.size()) { +// nextTimestamp = keyframes.get(i+1).getRealTimestamp(); +// } +// +// int diff = nextTimestamp-timestamp; +// int step = diff/100; +// +// for(int currentTimestamp = timestamp; currentTimestamp < nextTimestamp; currentTimestamp += step) { +// AdvancedPosition position = keyframes.getInterpolatedValueForTimestamp(currentTimestamp, ReplayMod.replaySettings.isLinearMovement()); +// if(previousPosition != null) { +// drawConnection(doubleX, doubleY, doubleZ, previousPosition, position, DEFAULT_PATH_COLOR, renderDistanceSquared); +// } +// previousPosition = position; +// } +// +// i++; +// } +// } +// +// distanceComparator.setPlayerPos(doubleX, doubleY + 1.4, doubleZ); +// +// List> distanceSorted = new ArrayList>(keyframes); +// Collections.sort(distanceSorted, distanceComparator); +// +// GlStateManager.enableTexture2D(); +// GlStateManager.blendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR); +// +// GlStateManager.disableDepth(); +// +// for(Keyframe kf : distanceSorted) { +// if(kf.getValue().distanceSquared(entity.posX, entity.posY, entity.posZ) < renderDistanceSquared) { +// drawPoint(doubleX, doubleY, doubleZ, kf); +// } +// } +// +// if(ReplayHandler.getPositionKeyframes().size() > 1) { +// AdvancedPosition cameraPosition = ReplayHandler.getPositionKeyframes().getInterpolatedValueForTimestamp(ReplayHandler.getRealTimelineCursor(), +// ReplayMod.replaySettings.isLinearMovement()); +// if(cameraPosition != null) { +// GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); +// drawCamera(doubleX, doubleY, doubleZ, cameraPosition); +// } +// } +// +// GlStateManager.disableBlend(); +// +// GlStateManager.popAttrib(); } @SubscribeEvent public void recalcSpline(KeyframesModifyEvent event) { - keyframes = ReplayHandler.getPositionKeyframes(); + // TODO +// keyframes = ReplayHandler.getPositionKeyframes(); } private class DistanceComparator implements Comparator> { @@ -172,7 +169,7 @@ public class PathPreviewRenderer { Tessellator tessellator = Tessellator.getInstance(); WorldRenderer renderer = tessellator.getWorldRenderer(); - mc.renderEngine.bindTexture(GuiReplayOverlay.replay_gui); + mc.renderEngine.bindTexture(TEXTURE); AdvancedPosition pos1 = kf.getValue(); @@ -197,9 +194,10 @@ public class PathPreviewRenderer { float size = 10/128f; - if(kf.equals(ReplayHandler.getSelectedKeyframe())) { - posY += size; - } + // TODO +// if(kf.equals(ReplayHandler.getSelectedKeyframe())) { +// posY += size; +// } if(pos1 instanceof SpectatorData) { posX += size; diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index 0f9338e5..05e6243c 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -1,595 +1,522 @@ package eu.crushedpixel.replaymod.replay; -import com.mojang.authlib.GameProfile; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.assets.AssetRepository; -import eu.crushedpixel.replaymod.assets.CustomImageObject; -import eu.crushedpixel.replaymod.assets.CustomObjectRepository; -import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.events.KeyframesModifyEvent; -import eu.crushedpixel.replaymod.events.ReplayExitEvent; -import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; -import eu.crushedpixel.replaymod.holders.*; -import eu.crushedpixel.replaymod.interpolation.AdvancedPositionKeyframeList; -import eu.crushedpixel.replaymod.interpolation.KeyframeList; -import eu.crushedpixel.replaymod.preparation.EntityPositionTracker; -import eu.crushedpixel.replaymod.registry.LightingHandler; -import eu.crushedpixel.replaymod.registry.PlayerHandler; -import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; -import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.utils.ReplayFile; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.embedded.EmbeddedChannel; -import lombok.Getter; -import lombok.Setter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; -import net.minecraft.client.network.NetHandlerPlayClient; -import net.minecraft.client.resources.I18n; -import net.minecraft.crash.CrashReport; -import net.minecraft.entity.Entity; -import net.minecraft.init.Bootstrap; -import net.minecraft.network.EnumPacketDirection; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.play.INetHandlerPlayClient; -import net.minecraft.util.ReportedException; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.*; - +// For later use in render and path module public class ReplayHandler { - - public static long lastExit = 0; - private static NetworkManager networkManager; - private static Minecraft mc = Minecraft.getMinecraft(); - private static EmbeddedChannel channel; - private static int realTimelinePosition = 0; - - private static Keyframe selectedKeyframe; - - private static boolean inPath = false; - - private static AdvancedPositionKeyframeList positionKeyframes = new AdvancedPositionKeyframeList(); - private static KeyframeList timeKeyframes = new KeyframeList(); - - private static boolean inReplay = false; - private static AdvancedPosition lastPosition = null; - - private static KeyframeList initialMarkers = new KeyframeList(); - private static KeyframeList markerKeyframes = new KeyframeList(); - - private static float cameraTilt = 0; - - private static KeyframeSet[] keyframeRepository = new KeyframeSet[]{}; - - @Getter @Setter - private static AssetRepository assetRepository; - - private static CustomObjectRepository customImageObjects = new CustomObjectRepository(); - - /** - * The file currently being played. - */ - private static ReplayFile currentReplayFile; - - /** - * Currently active replay restrictions. - */ - private static Restrictions restrictions; - - /** - * The EntityPositionTracker for the current Replay File. - */ - @Getter - private static EntityPositionTracker entityPositionTracker; - - public static KeyframeSet[] getKeyframeRepository() { - return keyframeRepository; - } - - public static void setKeyframeRepository(KeyframeSet[] repo, boolean write) { - keyframeRepository = repo; - if(write) { - try { - File tempFile = File.createTempFile(ReplayFile.ENTRY_PATHS, "json"); - - ReplayFileIO.write(repo, tempFile); - - ReplayMod.replayFileAppender.registerModifiedFile(tempFile, ReplayFile.ENTRY_PATHS, getReplayFile()); - } catch(Exception e) { - e.printStackTrace(); - } - } - } - - public static KeyframeList getMarkerKeyframes() { - return markerKeyframes; - } - - public static void setMarkers(KeyframeList m, boolean write) { - markerKeyframes.clear(); - markerKeyframes.addAll(m); - - if(write) { - try { - File tempFile = File.createTempFile(ReplayFile.ENTRY_MARKERS, "json"); - - ReplayFileIO.write(m, tempFile); - - ReplayMod.replayFileAppender.registerModifiedFile(tempFile, ReplayFile.ENTRY_MARKERS, getReplayFile()); - } catch(Exception e) { - e.printStackTrace(); - } - } - } - - public static void useKeyframePresetFromRepository(int index) { - useKeyframePreset(keyframeRepository[index]); - } - - public static void useKeyframePreset(KeyframeSet keyframeSet) { - setCustomImageObjects(Arrays.asList(keyframeSet.getCustomObjects())); - - Keyframe[] kfs = keyframeSet.getKeyframes(); - - positionKeyframes.clear(); - timeKeyframes.clear(); - for(Keyframe kf : kfs) { - addKeyframe(kf); - } - - selectKeyframe(null); - - fireKeyframesModifyEvent(); - } - - public static void spectateEntity(Entity e) { - getCameraEntity().spectate(e); - } - - public static void spectateCamera() { - spectateEntity(null); - } - - public static boolean isCamera() { - return mc.thePlayer instanceof CameraEntity && mc.thePlayer == mc.getRenderViewEntity(); - } - - public static void startPath(RenderOptions renderOptions, boolean fromStart) { - if(!ReplayHandler.isInPath()) { - try { - ReplayProcess.startReplayProcess(renderOptions, fromStart); - } catch (ReportedException e) { - // We have to manually unwrap OOM errors as Minecraft doesn't handle them when they're wrapped - Throwable prevCause = null; - Throwable cause = e; - while (cause != null && cause != prevCause) { - if (cause instanceof OutOfMemoryError) { - // Nevertheless save the crash report in case we actually need it - Minecraft minecraft = Minecraft.getMinecraft(); - CrashReport crashReport = e.getCrashReport(); - minecraft.addGraphicsAndWorldToCrashReport(crashReport); - Bootstrap.printToSYSOUT(crashReport.getCompleteReport()); - File folder = new File(minecraft.mcDataDir, "crash-reports"); - File file = new File(folder, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-client.txt"); - crashReport.saveToFile(file); - throw (OutOfMemoryError) cause; - } - prevCause = cause; - cause = e.getCause(); - } - throw e; - } - } - } - - public static void interruptReplay() { - ReplayProcess.stopReplayProcess(false); - } - - public static boolean isInPath() { - return inPath; - } - - public static void setInPath(boolean replaying) { - inPath = replaying; - } - - public static CameraEntity getCameraEntity() { - return mc.thePlayer instanceof CameraEntity ? (CameraEntity) mc.thePlayer : null; - } - - public static float getCameraTilt() { - return cameraTilt; - } - - public static void setCameraTilt(float tilt) { - cameraTilt = tilt; - } - - public static void addCameraTilt(float tilt) { - cameraTilt += tilt; - } - - public static void toggleMarker() { - if(selectedKeyframe != null && selectedKeyframe.getValue() instanceof Marker) { - markerKeyframes.remove(selectedKeyframe); - ReplayHandler.selectKeyframe(null); - } else { - AdvancedPosition pos = new AdvancedPosition(mc.getRenderViewEntity()); - int timestamp = ReplayMod.replaySender.currentTimeStamp(); - Keyframe markerKeyframe = new Keyframe(timestamp, new Marker(null, pos)); - markerKeyframes.add(markerKeyframe); - ReplayHandler.selectKeyframe(markerKeyframe); - } - } - - public static void addTimeKeyframe(Keyframe keyframe) { - timeKeyframes.add(keyframe); - selectKeyframe(keyframe); - - fireKeyframesModifyEvent(); - } - - public static void addPositionKeyframe(Keyframe keyframe) { - positionKeyframes.add(keyframe); - selectKeyframe(keyframe); - - fireKeyframesModifyEvent(); - } - - @SuppressWarnings("unchecked") - public static void addKeyframe(Keyframe keyframe) { - if(keyframe.getValue() instanceof AdvancedPosition) { - addPositionKeyframe(keyframe); - } else if(keyframe.getValue() instanceof TimestampValue) { - addTimeKeyframe(keyframe); - } - } - - public static void removeKeyframe(Keyframe keyframe) { - if(keyframe.getValue() instanceof AdvancedPosition) { - positionKeyframes.remove(keyframe); - } else if(keyframe.getValue() instanceof TimestampValue) { - timeKeyframes.remove(keyframe); - } else if(keyframe.getValue() instanceof Marker) { - markerKeyframes.remove(keyframe); - } - - if(keyframe == selectedKeyframe) { - selectKeyframe(null); - } - - fireKeyframesModifyEvent(); - } - - public static AdvancedPositionKeyframeList getPositionKeyframes() { - return positionKeyframes; - } - - public static KeyframeList getTimeKeyframes() { - return timeKeyframes; - } - - public static ArrayList getAllKeyframes() { - ArrayList keyframeList = new ArrayList(); - keyframeList.addAll(positionKeyframes); - keyframeList.addAll(timeKeyframes); - - return keyframeList; - } - - public static void resetKeyframes(final boolean resetMarkers, boolean callback) { - if(getPositionKeyframes().isEmpty() && getTimeKeyframes().isEmpty()) return; - - if(!callback) { - resetKeyframes(resetMarkers); - } else { - mc.displayGuiScreen(new GuiYesNo(new GuiYesNoCallback() { - @Override - public void confirmClicked(boolean result, int id) { - if(result) { - resetKeyframes(resetMarkers); - } - - mc.displayGuiScreen(null); - } - }, I18n.format("replaymod.gui.clearcallback.title"), I18n.format("replaymod.gui.clearcallback.message"), 1)); - } - } - - private static void resetKeyframes(boolean resetMarkers) { - timeKeyframes.clear(); - positionKeyframes.clear(); - selectKeyframe(null); - - if(resetMarkers) { - markerKeyframes.clear(); - } - - setRealTimelineCursor(0); - - fireKeyframesModifyEvent(); - } - - public static void selectKeyframe(Keyframe kf) { - selectedKeyframe = kf; - } - - public static boolean isSelected(Keyframe kf) { - return kf == selectedKeyframe; - } - - public static boolean isInReplay() { - return inReplay; - } - - public static void startReplay(File file) { - startReplay(file, true); - } - - public static void startReplay(File file, boolean asyncMode) { - entityPositionTracker = new EntityPositionTracker(file); - try { - entityPositionTracker.load(); - } catch(IOException ioe) { - ioe.printStackTrace(); - } - - ReplayMod.chatMessageHandler.initialize(); - mc.ingameGUI.getChatGUI().clearChatMessages(); - resetKeyframes(true); - - if(ReplayMod.replaySender != null) { - ReplayMod.replaySender.terminateReplay(); - } - - if(channel != null) { - channel.close(); - } - - setCameraTilt(0); - - restrictions = new Restrictions(); - - networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { - t.printStackTrace(); - } - }; - INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player")); - networkManager.setNetHandler(pc); - - channel = new EmbeddedChannel(networkManager); - channel.attr(NetworkDispatcher.FML_DISPATCHER).set(new NetworkDispatcher(networkManager)); - - // Open replay - try { - currentReplayFile = new ReplayFile(file); - } catch(Exception e) { - throw new RuntimeException(e); - } - - KeyframeSet[] paths = currentReplayFile.paths().get(); - ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false); - - ReplayHandler.selectKeyframe(null); - - List> rawMarkerList = currentReplayFile.markers().get(); - if (rawMarkerList == null) { - rawMarkerList = Collections.emptyList(); - } - KeyframeList markerList = new KeyframeList(rawMarkerList); - ReplayHandler.setMarkers(markerList, false); - ReplayHandler.initialMarkers = markerList; - - PlayerVisibility visibility = currentReplayFile.visibility().get(); - PlayerHandler.loadPlayerVisibilityConfiguration(visibility); - - //load assets - assetRepository = currentReplayFile.assetRepository().get(); - - customImageObjects = new CustomObjectRepository(); - - ReplayMod.replaySender = new ReplaySender(currentReplayFile, asyncMode); - channel.pipeline().addFirst(ReplayMod.replaySender); - channel.pipeline().fireChannelActive(); - - try { - ReplayMod.overlay.resetUI(true); - } catch(Exception e) { - e.printStackTrace(); - // TODO: Fix exception - } - - //Load lighting and trigger update - ReplayMod.replaySettings.setLightingEnabled(ReplayMod.replaySettings.isLightingEnabled()); - - inReplay = true; - } - - public static void restartReplay() { - mc.ingameGUI.getChatGUI().clearChatMessages(); - - if(channel != null) { - channel.close(); - } - - restrictions = new Restrictions(); - - networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { - t.printStackTrace(); - } - }; - - INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player")); - networkManager.setNetHandler(pc); - - channel = new EmbeddedChannel(networkManager); - channel.attr(NetworkDispatcher.FML_DISPATCHER).set(new NetworkDispatcher(networkManager)); - - channel.pipeline().addFirst(ReplayMod.replaySender); - channel.pipeline().fireChannelActive(); - - mc.addScheduledTask(new Runnable() { - @Override - public void run() { - try { - ReplayMod.overlay.resetUI(false); - } catch(Exception e) { - e.printStackTrace(); - } - } - }); - - inReplay = true; - } - - public static void endReplay() { - if(ReplayMod.replaySender != null) { - ReplayMod.replaySender.terminateReplay(); - } - - if (currentReplayFile != null) { - try { - - //only if Marker keyframes changed, rewrite them - if(!initialMarkers.equals(markerKeyframes)) { - File markerFile = File.createTempFile(ReplayFile.ENTRY_MARKERS, "json"); - ReplayFileIO.write(getMarkerKeyframes(), markerFile); - ReplayMod.replayFileAppender.registerModifiedFile(markerFile, ReplayFile.ENTRY_MARKERS, ReplayHandler.getReplayFile()); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - currentReplayFile.close(); - } catch(IOException e) { - e.printStackTrace(); - } - } - - currentReplayFile = null; - } - - resetKeyframes(true); - - PlayerHandler.resetHiddenPlayers(); - ReplayGuiRegistry.show(); - LightingHandler.setLighting(false); - - if (mc.theWorld != null) { - mc.theWorld.sendQuittingDisconnectingPacket(); - mc.loadWorld(null); - } - - CameraEntity.spectating = null; - - inReplay = false; - lastExit = System.currentTimeMillis(); - - FMLCommonHandler.instance().bus().post(new ReplayExitEvent()); - } - - public static void setInReplay(boolean inReplay1) { - inReplay = inReplay1; - } - - public static Keyframe getSelectedKeyframe() { - return selectedKeyframe; - } - - public static int getRealTimelineCursor() { - return realTimelinePosition; - } - - public static void setRealTimelineCursor(int pos) { - realTimelinePosition = pos; - } - - public static AdvancedPosition getLastPosition() { - return lastPosition; - } - - @Getter - private static boolean forceLastPosition = false; - - public static void setLastPosition(AdvancedPosition position, boolean force) { - lastPosition = position; - forceLastPosition = force; - } - - public static void moveCameraToLastPosition() { - //get the camera position we had before jumping in time - AdvancedPosition pos = ReplayHandler.getLastPosition(); - CameraEntity cam = ReplayHandler.getCameraEntity(); - if (cam != null && pos != null) { - // Move camera back in case we have been respawned, unless we're more than ReplayMod.TP_DISTANCE_LIMIT away from that point - // this is ignored if we explicitly said to respect this position, e.g. when jumping to marker keyframes. - if (ReplayHandler.isForceLastPosition() || - (Math.abs(pos.getX() - cam.posX) < ReplayMod.TP_DISTANCE_LIMIT && - Math.abs(pos.getZ() - cam.posZ) < ReplayMod.TP_DISTANCE_LIMIT)) { - cam.moveAbsolute(pos); - } - } - } - - public static File getReplayFile() { - return currentReplayFile == null ? null : currentReplayFile.getFile(); - } - - /** - * Synchronizes the cursor on the Keyframe Timeline with the Replay Time - * @param ignoreReplaySpeed If true, it always uses 1.0 as the stretch factor - */ - public static void syncTimeCursor(boolean ignoreReplaySpeed) { - selectKeyframe(null); - - int curTime = ReplayMod.replaySender.currentTimeStamp(); - - int prevTime, prevRealTime; - - Keyframe keyframe = timeKeyframes.last(); - - if(keyframe == null) { - prevTime = 0; - prevRealTime = 0; - } else { - prevTime = (int)keyframe.getValue().value; - prevRealTime = keyframe.getRealTimestamp(); - } - - double speed = ignoreReplaySpeed ? 1 : ReplayMod.overlay.getSpeedSliderValue(); - - int newCursorPos = Math.min(GuiReplayOverlay.KEYFRAME_TIMELINE_LENGTH, (int)(prevRealTime+((curTime-prevTime)/speed))); - - setRealTimelineCursor(newCursorPos); - } - - public static List getCustomImageObjects() { - return customImageObjects.getObjects(); - } - - public static void setCustomImageObjects(List objects) { - customImageObjects.setObjects(new ArrayList(objects)); - } - - public static void fireKeyframesModifyEvent() { - FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(positionKeyframes, timeKeyframes)); - positionKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); - timeKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); - } - - public static Restrictions getRestrictions() { - return restrictions; - } +// +// private static Minecraft mc = Minecraft.getMinecraft(); +// private static long lastExit; +// private static NetworkManager networkManager; +// private static EmbeddedChannel channel; +// private int realTimelinePosition = 0; +// +// private static Keyframe selectedKeyframe; +// +// private static boolean inPath = false; +// +// private static AdvancedPositionKeyframeList positionKeyframes = new AdvancedPositionKeyframeList(); +// private static KeyframeList timeKeyframes = new KeyframeList(); +// +// private static boolean inReplay = false; +// private static AdvancedPosition lastPosition = null; +// +// private static Set markers; +// +// private static float cameraTilt = 0; +// +// private static KeyframeSet[] keyframeRepository = new KeyframeSet[]{}; +// +// @Getter @Setter +// private static AssetRepository assetRepository; +// +// private static CustomObjectRepository customImageObjects = new CustomObjectRepository(); +// +// /** +// * The file currently being played. +// */ +// private static ReplayFile currentReplayFile; +// +// /** +// * Currently active replay restrictions. +// */ +// private static Restrictions restrictions; +// +// /** +// * The EntityPositionTracker for the current Replay File. +// */ +// @Getter +// private static EntityPositionTracker entityPositionTracker; +// +// public static KeyframeSet[] getKeyframeRepository() { +// return keyframeRepository; +// } +// +// public static void setKeyframeRepository(KeyframeSet[] repo, boolean write) { +// keyframeRepository = repo; +// if(write) { +// try (OutputStream out = currentReplayFile.write("paths.json")) { +// out.write(new Gson().toJson(repo).getBytes()); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// } +// +// public static Set getMarkers() { +// return markers; +// } +// +// public static void setMarkers(Set markers, boolean write) { +// ReplayHandler.markers = markers; +// if(write) { +// try { +// currentReplayFile.writeMarkers(markers); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// } +// +// public static void useKeyframePresetFromRepository(int index) { +// useKeyframePreset(keyframeRepository[index]); +// } +// +// public static void useKeyframePreset(KeyframeSet keyframeSet) { +// setCustomImageObjects(Arrays.asList(keyframeSet.getCustomObjects())); +// +// Keyframe[] kfs = keyframeSet.getKeyframes(); +// +// positionKeyframes.clear(); +// timeKeyframes.clear(); +// for(Keyframe kf : kfs) { +// addKeyframe(kf); +// } +// +// selectKeyframe(null); +// +// fireKeyframesModifyEvent(); +// } +// +// public static void spectateEntity(Entity e) { +// getCameraEntity().spectate(e); +// } +// +// public static void spectateCamera() { +// spectateEntity(null); +// } +// +// public static boolean isCamera() { +// return mc.thePlayer instanceof CameraEntity && mc.thePlayer == mc.getRenderViewEntity(); +// } +// +// public static void startPath(RenderOptions renderOptions, boolean fromStart) { +// if(!com.replaymod.replay.ReplayHandler.isInPath()) { +// try { +// ReplayProcess.startReplayProcess(renderOptions, fromStart); +// } catch (ReportedException e) { +// // We have to manually unwrap OOM errors as Minecraft doesn't handle them when they're wrapped +// Throwable prevCause = null; +// Throwable cause = e; +// while (cause != null && cause != prevCause) { +// if (cause instanceof OutOfMemoryError) { +// // Nevertheless save the crash report in case we actually need it +// Minecraft minecraft = Minecraft.getMinecraft(); +// CrashReport crashReport = e.getCrashReport(); +// minecraft.addGraphicsAndWorldToCrashReport(crashReport); +// Bootstrap.printToSYSOUT(crashReport.getCompleteReport()); +// File folder = new File(minecraft.mcDataDir, "crash-reports"); +// File file = new File(folder, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-client.txt"); +// crashReport.saveToFile(file); +// throw (OutOfMemoryError) cause; +// } +// prevCause = cause; +// cause = e.getCause(); +// } +// throw e; +// } +// } +// } +// +// public static void interruptReplay() { +// ReplayProcess.stopReplayProcess(false); +// } +// +// public static boolean isInPath() { +// return inPath; +// } +// +// public static void setInPath(boolean replaying) { +// inPath = replaying; +// } +// +// public static CameraEntity getCameraEntity() { +// return mc.thePlayer instanceof CameraEntity ? (CameraEntity) mc.thePlayer : null; +// } +// +// public static float getCameraTilt() { +// return cameraTilt; +// } +// +// public static void setCameraTilt(float tilt) { +// cameraTilt = tilt; +// } +// +// public static void addCameraTilt(float tilt) { +// cameraTilt += tilt; +// } +// +// public static void toggleMarker() { +// // TODO +// } +// +// public static void addTimeKeyframe(Keyframe keyframe) { +// timeKeyframes.add(keyframe); +// selectKeyframe(keyframe); +// +// fireKeyframesModifyEvent(); +// } +// +// public static void addPositionKeyframe(Keyframe keyframe) { +// positionKeyframes.add(keyframe); +// selectKeyframe(keyframe); +// +// fireKeyframesModifyEvent(); +// } +// +// @SuppressWarnings("unchecked") +// public static void addKeyframe(Keyframe keyframe) { +// if(keyframe.getValue() instanceof AdvancedPosition) { +// addPositionKeyframe(keyframe); +// } else if(keyframe.getValue() instanceof TimestampValue) { +// addTimeKeyframe(keyframe); +// } +// } +// +// public static void removeKeyframe(Keyframe keyframe) { +// if(keyframe.getValue() instanceof AdvancedPosition) { +// positionKeyframes.remove(keyframe); +// } else if(keyframe.getValue() instanceof TimestampValue) { +// timeKeyframes.remove(keyframe); +// } +// // TODO Marker +// +// if(keyframe == selectedKeyframe) { +// selectKeyframe(null); +// } +// +// fireKeyframesModifyEvent(); +// } +// +// public static AdvancedPositionKeyframeList getPositionKeyframes() { +// return positionKeyframes; +// } +// +// public static KeyframeList getTimeKeyframes() { +// return timeKeyframes; +// } +// +// public static ArrayList getAllKeyframes() { +// ArrayList keyframeList = new ArrayList(); +// keyframeList.addAll(positionKeyframes); +// keyframeList.addAll(timeKeyframes); +// +// return keyframeList; +// } +// +// public static void resetKeyframes(final boolean resetMarkers, boolean callback) { +// if(getPositionKeyframes().isEmpty() && getTimeKeyframes().isEmpty()) return; +// +// if(!callback) { +// resetKeyframes(resetMarkers); +// } else { +// mc.displayGuiScreen(new GuiYesNo(new GuiYesNoCallback() { +// @Override +// public void confirmClicked(boolean result, int id) { +// if(result) { +// resetKeyframes(resetMarkers); +// } +// +// mc.displayGuiScreen(null); +// } +// }, I18n.format("replaymod.gui.clearcallback.title"), I18n.format("replaymod.gui.clearcallback.message"), 1)); +// } +// } +// +// private static void resetKeyframes(boolean resetMarkers) { +// timeKeyframes.clear(); +// positionKeyframes.clear(); +// selectKeyframe(null); +// +// if(resetMarkers) { +// // TODO Markers +// } +// +//// setRealTimelineCursor(0); TODO +// +// fireKeyframesModifyEvent(); +// } +// +// public static void selectKeyframe(Keyframe kf) { +// selectedKeyframe = kf; +// } +// +// public static boolean isSelected(Keyframe kf) { +// return kf == selectedKeyframe; +// } +// +// public static boolean isInReplay() { +// return inReplay; +// } +// +// public static void startReplay(File file) { +// try { +// startReplay(file, true); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// +// public static void startReplay(File file, boolean asyncMode) throws IOException { +// entityPositionTracker = new EntityPositionTracker(file); +// entityPositionTracker.load(); +// +// ReplayMod.chatMessageHandler.initialize(); +// mc.ingameGUI.getChatGUI().clearChatMessages(); +// resetKeyframes(true); +// +// if(ReplayMod.replaySender != null) { +// ReplayMod.replaySender.terminateReplay(); +// } +// +// if(channel != null) { +// channel.close(); +// } +// +// setCameraTilt(0); +// +// restrictions = new Restrictions(); +// +// networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { +// @Override +// public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { +// t.printStackTrace(); +// } +// }; +// INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player")); +// networkManager.setNetHandler(pc); +// +// channel = new EmbeddedChannel(networkManager); +// channel.attr(NetworkDispatcher.FML_DISPATCHER).set(new NetworkDispatcher(networkManager)); +// +// // Open replay +// currentReplayFile = new ZipReplayFile(new ReplayStudio(), file); +// +// KeyframeSet[] paths; +// Optional is = currentReplayFile.get("paths.json"); +// if (!is.isPresent()) { +// is = currentReplayFile.get("paths"); +// } +// if (is.isPresent()) { +// try (Reader reader = new InputStreamReader(is.get())) { +// paths = new GsonBuilder().registerTypeAdapter(KeyframeSet[].class, new LegacyKeyframeSetAdapter()) +// .create().fromJson(reader, KeyframeSet[].class); +// } +// } else { +// paths = new KeyframeSet[0]; +// } +// com.replaymod.replay.ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false); +// com.replaymod.replay.ReplayHandler.selectKeyframe(null); +// com.replaymod.replay.ReplayHandler.setMarkers(currentReplayFile.getMarkers().or(Collections.emptySet()), false); +// PlayerHandler.loadPlayerVisibilityConfiguration(currentReplayFile.getInvisiblePlayers()); +// +// //load assets +// assetRepository = new AssetRepository(); +// for (ReplayAssetEntry entry : currentReplayFile.getAssets()) { +// UUID uuid = entry.getUuid(); +// assetRepository.addAsset(entry.getName(), currentReplayFile.getAsset(uuid).get(), uuid); +// } +// +// customImageObjects = new CustomObjectRepository(); +// +// ReplayMod.replaySender = new ReplaySender(currentReplayFile, asyncMode); +// channel.pipeline().addFirst(ReplayMod.replaySender); +// channel.pipeline().fireChannelActive(); +// +// try { +// ReplayMod.overlay.resetUI(true); +// } catch(Exception e) { +// e.printStackTrace(); +// // TODO: Fix exception +// } +// +// //Load lighting and trigger update +// ReplayMod.replaySettings.setLightingEnabled(ReplayMod.replaySettings.isLightingEnabled()); +// +// inReplay = true; +// } +// +// public static void restartReplay() { +// mc.ingameGUI.getChatGUI().clearChatMessages(); +// +// if(channel != null) { +// channel.close(); +// } +// +// restrictions = new Restrictions(); +// +// networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { +// @Override +// public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { +// t.printStackTrace(); +// } +// }; +// +// INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player")); +// networkManager.setNetHandler(pc); +// +// channel = new EmbeddedChannel(networkManager); +// channel.attr(NetworkDispatcher.FML_DISPATCHER).set(new NetworkDispatcher(networkManager)); +// +// channel.pipeline().addFirst(ReplayMod.replaySender); +// channel.pipeline().fireChannelActive(); +// +// mc.addScheduledTask(new Runnable() { +// @Override +// public void run() { +// try { +// ReplayMod.overlay.resetUI(false); +// } catch(Exception e) { +// e.printStackTrace(); +// } +// } +// }); +// +// inReplay = true; +// } +// +// public static void endReplay() { +// if(ReplayMod.replaySender != null) { +// ReplayMod.replaySender.terminateReplay(); +// } +// +// if (currentReplayFile != null) { +// try { +// currentReplayFile.save(); +// currentReplayFile.close(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// currentReplayFile = null; +// } +// +// resetKeyframes(true); +// +// PlayerHandler.resetHiddenPlayers(); +// ReplayGuiRegistry.show(); +// LightingHandler.setLighting(false); +// +// if (mc.theWorld != null) { +// mc.theWorld.sendQuittingDisconnectingPacket(); +// mc.loadWorld(null); +// } +// +// CameraEntity.spectating = null; +// +// inReplay = false; +// lastExit = System.currentTimeMillis(); +// +// FMLCommonHandler.instance().bus().post(new ReplayExitEvent()); +// } +// +// public static void setInReplay(boolean inReplay1) { +// inReplay = inReplay1; +// } +// +// public static Keyframe getSelectedKeyframe() { +// return selectedKeyframe; +// } +// +//// public static int getRealTimelineCursor() { +//// return realTimelinePosition; +//// } +//// +//// public static void setRealTimelineCursor(int pos) { +//// realTimelinePosition = pos; +//// } +// +// public static AdvancedPosition getLastPosition() { +// return lastPosition; +// } +// +// @Getter +// private static boolean forceLastPosition = false; +// +// public static void setLastPosition(AdvancedPosition position, boolean force) { +// lastPosition = position; +// forceLastPosition = force; +// } +// +// public static void moveCameraToLastPosition() { +// //get the camera position we had before jumping in time +// AdvancedPosition pos = com.replaymod.replay.ReplayHandler.getLastPosition(); +// CameraEntity cam = com.replaymod.replay.ReplayHandler.getCameraEntity(); +// if (cam != null && pos != null) { +// // Move camera back in case we have been respawned, unless we're more than ReplayMod.TP_DISTANCE_LIMIT away from that point +// // this is ignored if we explicitly said to respect this position, e.g. when jumping to marker keyframes. +// if (com.replaymod.replay.ReplayHandler.isForceLastPosition() || +// (Math.abs(pos.getX() - cam.posX) < ReplayMod.TP_DISTANCE_LIMIT && +// Math.abs(pos.getZ() - cam.posZ) < ReplayMod.TP_DISTANCE_LIMIT)) { +// cam.moveAbsolute(pos); +// } +// } +// } +// +// public static ReplayFile getReplayFile() { +// return currentReplayFile; +// } +// +// /** +// * Synchronizes the cursor on the Keyframe Timeline with the Replay Time +// * @param ignoreReplaySpeed If true, it always uses 1.0 as the stretch factor +// */ +// public static void syncTimeCursor(boolean ignoreReplaySpeed) { +// selectKeyframe(null); +// +// int curTime = ReplayMod.replaySender.currentTimeStamp(); +// +// int prevTime, prevRealTime; +// +// Keyframe keyframe = timeKeyframes.last(); +// +// if(keyframe == null) { +// prevTime = 0; +// prevRealTime = 0; +// } else { +// prevTime = (int)keyframe.getValue().value; +// prevRealTime = keyframe.getRealTimestamp(); +// } +// +// double speed = ignoreReplaySpeed ? 1 : ReplayMod.overlay.getSpeedSliderValue(); +// +// int newCursorPos = Math.min(GuiReplayOverlay.KEYFRAME_TIMELINE_LENGTH, (int)(prevRealTime+((curTime-prevTime)/speed))); +// +//// setRealTimelineCursor(newCursorPos); TODO +// } +// +// public static List getCustomImageObjects() { +// return customImageObjects.getObjects(); +// } +// +// public static void setCustomImageObjects(List objects) { +// customImageObjects.setObjects(new ArrayList(objects)); +// } +// +// public static void fireKeyframesModifyEvent() { +// FMLCommonHandler.instance().bus().post(new KeyframesModifyEvent(positionKeyframes, timeKeyframes)); +// positionKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); +// timeKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); +// } +// +// public static Restrictions getRestrictions() { +// return restrictions; +// } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java deleted file mode 100755 index a665f960..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ /dev/null @@ -1,318 +0,0 @@ -package eu.crushedpixel.replaymod.replay; - -import com.google.common.collect.Maps; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType; -import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.SpectatorData; -import eu.crushedpixel.replaymod.holders.TimestampValue; -import eu.crushedpixel.replaymod.interpolation.KeyframeList; -import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.timer.EnchantmentTimer; -import eu.crushedpixel.replaymod.timer.ReplayTimer; -import eu.crushedpixel.replaymod.utils.CameraPathValidator; -import eu.crushedpixel.replaymod.video.VideoRenderer; -import lombok.Getter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.SoundCategory; -import net.minecraft.client.gui.GuiErrorScreen; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.chunk.RenderChunk; -import net.minecraft.client.resources.I18n; -import net.minecraft.crash.CrashReport; -import net.minecraft.entity.Entity; -import net.minecraft.util.ReportedException; -import org.lwjgl.opengl.Display; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class ReplayProcess { - - private static Minecraft mc = Minecraft.getMinecraft(); - - private static int lastRealReplayTime; - private static long lastRealTime = 0; - - private static boolean linear = false; - - private static int initialTimestamp = 0; - - private static double previousReplaySpeed = 0; - - @Getter - private static VideoRenderer videoRenderer = null; - - private static boolean isVideoRecording = false; - private static boolean requestFinish = false; - private static boolean firstTime = false; - - public static boolean isVideoRecording() { - return isVideoRecording; - } - - //a copy of the initial sound settings, - //which we will modify to prevent game sounds from annoying us while rendering - - @SuppressWarnings("unchecked") //I, too, blame Forge for not re-adding generics to that Map. - private static Map mapSoundLevelsBefore = null; - - private static void resetProcess() { - firstTime = true; - - requestFinish = false; - - lastRealTime = System.currentTimeMillis(); - lastRealReplayTime = 0; - linear = ReplayMod.replaySettings.isLinearMovement(); - - previousReplaySpeed = ReplayMod.replaySender.getReplaySpeed(); - - EnchantmentTimer.resetRecordingTime(); - } - - public static void startReplayProcess(RenderOptions renderOptions, boolean fromStart) { - mc.displayGuiScreen(null); - - ReplayHandler.selectKeyframe(null); - resetProcess(); - - isVideoRecording = renderOptions != null; - - ReplayMod.chatMessageHandler.initialize(); - - try { - CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes()); - } catch(CameraPathValidator.InvalidCameraPathException e) { - e.printToChat(); - return; - } - - ReplayHandler.setInPath(true); - ReplayMod.replaySender.setAsyncMode(false); - - //default camera path, no rendering - if (renderOptions == null) { - initialTimestamp = fromStart ? 0 : ReplayHandler.getRealTimelineCursor(); - - //if the cursor is at (or very near) the end, play from the beginning as well - if(initialTimestamp + 50 >= Math.max(ReplayHandler.getTimeKeyframes().last().getRealTimestamp(), - ReplayHandler.getPositionKeyframes().last().getRealTimestamp())) { - initialTimestamp = 0; - } - - lastRealReplayTime = initialTimestamp; - - int ts = ReplayHandler.getTimeKeyframes().getInterpolatedValueForTimestamp(initialTimestamp, true).asInt(); - if (ts < ReplayMod.replaySender.currentTimeStamp()) { - mc.displayGuiScreen(null); - } - ReplayMod.replaySender.sendPacketsTill(ts); - - ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.pathstarted", ChatMessageType.INFORMATION); - mc.timer.timerSpeed = 1; - - //set the sound level map to null - //so a previous map doesn't override the current game settings after a camera path - mapSoundLevelsBefore = null; - } else { - //if FBOs are not enabled/supported, prevent the user from resizing the MC window - if(!OpenGlHelper.isFramebufferEnabled()) { - Display.setResizable(false); - } - - //if rendering, disable all game sounds except for gui sounds - @SuppressWarnings("unchecked") //I, too, blame Forge for not re-adding generics to that Map. - Map orgMap = (Map)mc.gameSettings.mapSoundLevels; - if(orgMap != null) { - mapSoundLevelsBefore = new HashMap(orgMap); - } else { - orgMap = Maps.newEnumMap(SoundCategory.class); - } - - //turn down for what? to mute all sound of course! - //the GUI sounds (button clicks etc) are not muted this way. - for(SoundCategory category : SoundCategory.values()) { - if(category == SoundCategory.MASTER) continue; - orgMap.put(category, 0f); - } - - mc.gameSettings.mapSoundLevels = orgMap; - - initialTimestamp = 0; - boolean success = false; - try { - isVideoRecording = true; - videoRenderer = new VideoRenderer(renderOptions); - success = videoRenderer.renderVideo(); - } catch (IOException e) { - e.printStackTrace(); - - GuiErrorScreen errorScreen = new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), - I18n.format("replaymod.gui.rendering.error.message")); - mc.displayGuiScreen(errorScreen); - } catch (Throwable t) { - CrashReport crashReport = CrashReport.makeCrashReport(t, "Rendering video"); - throw new ReportedException(crashReport); - } finally { - isVideoRecording = false; - stopReplayProcess(success); - } - } - } - - 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); - } - - ReplayHandler.setInPath(false); - ReplayMod.replaySender.setAsyncMode(true); - - ReplayMod.replaySender.stopHurrying(); - - ReplayTimer.get(mc).passive = false; - ReplayMod.replaySender.setReplaySpeed(previousReplaySpeed); - ReplayMod.replaySender.setReplaySpeed(0); - - //re-enable window resizing after rendering - Display.setResizable(true); - - //restore the sound settings - if (mapSoundLevelsBefore != null) { - mc.gameSettings.mapSoundLevels = mapSoundLevelsBefore; - } - } - - //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. - public static void tickReplay(boolean justCheck) { - final long curTime = System.currentTimeMillis(); - KeyframeList positionKeyframes = ReplayHandler.getPositionKeyframes(); - KeyframeList timeKeyframes = ReplayHandler.getTimeKeyframes(); - - int curRealReplayTime; - - if (isVideoRecording) { - return; - } - if(ReplayMod.replaySender.isHurrying()) { - lastRealTime = curTime; - return; - } - - if(firstTime) { - if(RenderChunk.renderChunksUpdated != 0 || mc.currentScreen != null) { - return; - } - - lastRealTime = curTime; - - firstTime = false; - mc.timer.renderPartialTicks = 100; - mc.timer.elapsedPartialTicks = 100; - mc.timer.elapsedTicks = 100; - - curRealReplayTime = lastRealReplayTime = initialTimestamp; - } else { - long timeStep = curTime - lastRealTime; - curRealReplayTime = (int) (lastRealReplayTime + timeStep); - } - - if(justCheck) return; - - Keyframe lastPos = positionKeyframes.getPreviousKeyframe(curRealReplayTime, true); - Keyframe nextPos = positionKeyframes.getNextKeyframe(curRealReplayTime, true); - - boolean spectateCamera = true; - - //check whether between two First Person Spectator Keyframes - if(lastPos != null && nextPos != null) { - if(lastPos.getValue() instanceof SpectatorData && nextPos.getValue() instanceof SpectatorData) { - SpectatorData previousSpectatorData = (SpectatorData)lastPos.getValue(); - SpectatorData nextSpectatorData = (SpectatorData)nextPos.getValue(); - if(previousSpectatorData.getSpectatedEntityID() == nextSpectatorData.getSpectatedEntityID()) { - if(previousSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON - && nextSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON) { - spectateCamera = false; - } - } - } - } - - ReplayHandler.setRealTimelineCursor(curRealReplayTime); - - Keyframe lastTime = timeKeyframes.getPreviousKeyframe(curRealReplayTime, true); - Keyframe nextTime = timeKeyframes.getNextKeyframe(curRealReplayTime, true); - - int lastTimeStamp; - int nextTimeStamp; - - double curSpeed = 0; - - if(nextTime != null && lastTime != null && nextTime.getRealTimestamp() == lastTime.getRealTimestamp()) { - curSpeed = 0; - } else { - if(nextTime != null) { - nextTimeStamp = nextTime.getRealTimestamp(); - } else { - nextTimeStamp = lastTime.getRealTimestamp(); - } - - if(lastTime != null) { - lastTimeStamp = lastTime.getRealTimestamp(); - } else { - lastTimeStamp = nextTime.getRealTimestamp(); - } - - if(!(nextTime == null || lastTime == null)) { - curSpeed = ((double) (((int)nextTime.getValue().value - (int)lastTime.getValue().value))) / ((double) ((nextTimeStamp - lastTimeStamp))); - } - - if(lastTimeStamp == nextTimeStamp) { - curSpeed = 0f; - } - } - - AdvancedPosition cameraPosition = null; - if(spectateCamera) { - cameraPosition = positionKeyframes.getInterpolatedValueForTimestamp(curRealReplayTime, linear); - ReplayHandler.spectateCamera(); - } else { - Entity toSpectate = mc.theWorld.getEntityByID(((SpectatorData) lastPos.getValue()).getSpectatedEntityID()); - ReplayHandler.spectateEntity(toSpectate); - } - - if(cameraPosition != null) { - ReplayHandler.setCameraTilt((float)cameraPosition.getRoll()); - ReplayHandler.getCameraEntity().movePath(cameraPosition); - } - - Integer curTimestamp = timeKeyframes.getInterpolatedValueForTimestamp(curRealReplayTime, true).asInt(); - - if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed); - - ReplayMod.replaySender.sendPacketsTill(curTimestamp); - - lastRealReplayTime = curRealReplayTime; - lastRealTime = curTime; - - if(requestFinish) { - stopReplayProcess(true); - requestFinish = false; - } - - if(curRealReplayTime > timeKeyframes.last().getRealTimestamp() - && curRealReplayTime > positionKeyframes.last().getRealTimestamp()) { - requestFinish = true; - } - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java index 1d0b8786..690c3179 100755 --- a/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java +++ b/src/main/java/eu/crushedpixel/replaymod/settings/ReplaySettings.java @@ -1,6 +1,5 @@ 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; @@ -10,34 +9,6 @@ public class ReplaySettings { private static final String[] CATEGORIES = new String[]{"recording", "replay", "render", "advanced"}; - public void readValues() { - Configuration config = ReplayMod.config; - - config.load(); - - for(RecordingOptions o : RecordingOptions.values()) { - Property p = getConfigSetting(config, o.name(), o.getValue(), "recording", false); - o.setValue(getValueObject(p)); - } - - for(ReplayOptions o : ReplayOptions.values()) { - Property p = getConfigSetting(config, o.name(), o.getValue(), "replay", false); - o.setValue(getValueObject(p)); - } - - for(RenderOptions o : RenderOptions.values()) { - Property p = getConfigSetting(config, o.name(), o.getValue(), "render", false); - o.setValue(getValueObject(p)); - } - - for(AdvancedOptions o : AdvancedOptions.values()) { - Property p = getConfigSetting(config, o.name(), o.getValue(), "advanced", true); - o.setValue(getValueObject(p)); - } - - config.save(); - } - public String getRecordingPath() { return (String) AdvancedOptions.recordingPath.getValue(); } @@ -54,12 +25,10 @@ public class ReplaySettings { public void setVideoFramerate(int framerate) { RenderOptions.videoFramerate.setValue(Math.min(120, Math.max(10, framerate))); - rewriteSettings(); } public void toggleInterpolation() { ReplayOptions.linear.setValue(!((Boolean)ReplayOptions.linear.getValue())); - rewriteSettings(); } public boolean showRecordingIndicator() { @@ -89,46 +58,18 @@ public class ReplaySettings { public void setLightingEnabled(boolean enabled) { ReplayOptions.lighting.setValue(enabled); LightingHandler.setLighting(enabled); - rewriteSettings(); } public boolean showPathPreview() { return (Boolean) ReplayOptions.previewPath.getValue(); } public void setShowPathPreview(boolean show) { ReplayOptions.previewPath.setValue(show); - rewriteSettings(); } public boolean showClearKeyframesCallback() { return (Boolean) ReplayOptions.keyframeCleanCallback.getValue(); } - public void rewriteSettings() { - ReplayMod.config.load(); - - for(String cat : CATEGORIES) { - ReplayMod.config.removeCategory(ReplayMod.config.getCategory(cat)); - } - - for(RecordingOptions o : RecordingOptions.values()) { - getConfigSetting(ReplayMod.config, o.name(), o.getValue(), "recording", false); - } - - for(ReplayOptions o : ReplayOptions.values()) { - getConfigSetting(ReplayMod.config, o.name(), o.getValue(), "replay", false); - } - - for(RenderOptions o : RenderOptions.values()) { - getConfigSetting(ReplayMod.config, o.name(), o.getValue(), "render", false); - } - - for(AdvancedOptions o : AdvancedOptions.values()) { - getConfigSetting(ReplayMod.config, o.name(), o.getValue(), "advanced", false); - } - - ReplayMod.config.save(); - } - private Property getConfigSetting(Configuration config, String name, Object value, String category, boolean warning) { if(warning) { String warningMsg = "Please be careful when modifying this setting, as setting it to an invalid value might harm your computer."; @@ -174,7 +115,7 @@ public class ReplaySettings { public enum RecordingOptions implements ValueEnum { recordServer(true, "replaymod.gui.settings.recordserver"), recordSingleplayer(true, "replaymod.gui.settings.recordsingleplayer"), - notifications(true, "replaymod.gui.settings.notifications"), + notifications(true, "replaymod.gui.settings.notifications"), // TODO indicator(true, "replaymod.gui.settings.indicator"); private Object value; diff --git a/src/main/java/eu/crushedpixel/replaymod/studio/ConnectMetadataFilter.java b/src/main/java/eu/crushedpixel/replaymod/studio/ConnectMetadataFilter.java index ccb4da1e..ad6094a6 100644 --- a/src/main/java/eu/crushedpixel/replaymod/studio/ConnectMetadataFilter.java +++ b/src/main/java/eu/crushedpixel/replaymod/studio/ConnectMetadataFilter.java @@ -8,7 +8,7 @@ import de.johni0702.replaystudio.filter.StreamFilter; import de.johni0702.replaystudio.replay.ReplayFile; import de.johni0702.replaystudio.replay.ReplayMetaData; import de.johni0702.replaystudio.stream.PacketStream; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import org.apache.commons.io.IOUtils; import org.spacehq.mc.protocol.packet.ingame.server.ServerResourcePackSendPacket; import org.spacehq.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; diff --git a/src/main/java/eu/crushedpixel/replaymod/studio/StudioImplementation.java b/src/main/java/eu/crushedpixel/replaymod/studio/StudioImplementation.java index 790cb5c6..b11589fa 100755 --- a/src/main/java/eu/crushedpixel/replaymod/studio/StudioImplementation.java +++ b/src/main/java/eu/crushedpixel/replaymod/studio/StudioImplementation.java @@ -90,9 +90,9 @@ public class StudioImplementation { } private static void shiftPaths(ReplayFile replayFile, int beginning, int ending) throws IOException { - Optional in = replayFile.get(eu.crushedpixel.replaymod.utils.ReplayFile.ENTRY_PATHS); + Optional in = replayFile.get("paths.json"); if (!in.isPresent()) { - in = replayFile.get(eu.crushedpixel.replaymod.utils.ReplayFile.ENTRY_PATHS_OLD); + in = replayFile.get("paths"); if (!in.isPresent()) { return; } @@ -126,7 +126,7 @@ public class StudioImplementation { } } - Writer out = new OutputStreamWriter(replayFile.write(eu.crushedpixel.replaymod.utils.ReplayFile.ENTRY_PATHS)); + Writer out = new OutputStreamWriter(replayFile.write("paths.json")); new Gson().toJson(resultSets.toArray(new KeyframeSet[resultSets.size()]), out); out.flush(); out.close(); diff --git a/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java b/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java index 27857e62..71d0a4b8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java +++ b/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java @@ -1,9 +1,5 @@ package eu.crushedpixel.replaymod.timer; -import eu.crushedpixel.replaymod.ReplayMod; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplayProcess; - public class EnchantmentTimer { private static long lastRealTime = System.currentTimeMillis(); @@ -20,17 +16,18 @@ public class EnchantmentTimer { } public static long getEnchantmentTime() { - if(!(ReplayHandler.isInPath() && ReplayProcess.isVideoRecording())) { - if(ReplayHandler.isInReplay()) { - long timeDiff = System.currentTimeMillis() - lastRealTime; - double toAdd = timeDiff * ReplayMod.replaySender.getReplaySpeed(); - lastFakeTime = Math.round(lastFakeTime + toAdd); - lastRealTime = System.currentTimeMillis(); - return lastFakeTime; - } - lastFakeTime = lastRealTime = System.currentTimeMillis(); - return lastRealTime; - } + // TODO +// if(!(ReplayHandler.isInPath() && ReplayProcess.isVideoRecording())) { +// if(ReplayHandler.isInReplay()) { +// long timeDiff = System.currentTimeMillis() - lastRealTime; +// double toAdd = timeDiff * ReplayMod.replaySender.getReplaySpeed(); +// lastFakeTime = Math.round(lastFakeTime + toAdd); +// lastRealTime = System.currentTimeMillis(); +// return lastFakeTime; +// } +// lastFakeTime = lastRealTime = System.currentTimeMillis(); +// return lastRealTime; +// } return recordingTime; } } diff --git a/src/main/java/eu/crushedpixel/replaymod/utils/CameraPathValidator.java b/src/main/java/eu/crushedpixel/replaymod/utils/CameraPathValidator.java index a2c22a84..d15e7dca 100644 --- a/src/main/java/eu/crushedpixel/replaymod/utils/CameraPathValidator.java +++ b/src/main/java/eu/crushedpixel/replaymod/utils/CameraPathValidator.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.utils; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageHandler; import eu.crushedpixel.replaymod.holders.AdvancedPosition; import eu.crushedpixel.replaymod.holders.Keyframe; diff --git a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java deleted file mode 100644 index 1ed76094..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFile.java +++ /dev/null @@ -1,269 +0,0 @@ -package eu.crushedpixel.replaymod.utils; - -import com.google.common.base.Supplier; -import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import eu.crushedpixel.replaymod.assets.AssetRepository; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.KeyframeSet; -import eu.crushedpixel.replaymod.holders.Marker; -import eu.crushedpixel.replaymod.holders.PlayerVisibility; -import eu.crushedpixel.replaymod.recording.ReplayMetaData; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.*; -import java.lang.reflect.Type; -import java.util.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -public class ReplayFile extends ZipFile { - - public static final String TEMP_FILE_EXTENSION = ".tmcpr"; - public static final String JSON_FILE_EXTENSION = ".json"; - public static final String ZIP_FILE_EXTENSION = ".mcpr"; - public static final String ENTRY_RECORDING = "recording" + TEMP_FILE_EXTENSION; - public static final String ENTRY_METADATA = "metaData" + JSON_FILE_EXTENSION; - public static final String ENTRY_PATHS_OLD = "paths"; - public static final String ENTRY_PATHS = "paths" + JSON_FILE_EXTENSION; - public static final String ENTRY_THUMB = "thumb"; - public static final String ENTRY_RESOURCE_PACK = "resourcepack/%s.zip"; - public static final String ENTRY_RESOURCE_PACK_INDEX = "resourcepack/index"+JSON_FILE_EXTENSION; - public static final String ENTRY_VISIBILITY_OLD = "visibility"; - public static final String ENTRY_VISIBILITY = "visibility" + JSON_FILE_EXTENSION; - public static final String ENTRY_MARKERS = "markers" + JSON_FILE_EXTENSION; - public static final String ENTRY_ASSET_FOLDER = "asset/"; - - private final File file; - - public ReplayFile(File f) throws IOException { - super(f); - this.file = f; - } - - public File getFile() { - return file; - } - - public ZipEntry recordingEntry() { - return getEntry(ENTRY_RECORDING); - } - - public Supplier recording() { - return new Supplier() { - @Override - public InputStream get() { - try { - return getInputStream(recordingEntry()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry metadataEntry() { - return getEntry(ENTRY_METADATA); - } - - public Supplier metadata() { - return new Supplier() { - @Override - public ReplayMetaData get() { - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(metadataEntry()))); - return new Gson().fromJson(reader, ReplayMetaData.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry pathsEntry() { - ZipEntry newEntry = getEntry(ENTRY_PATHS); - return newEntry != null ? newEntry : getEntry(ENTRY_PATHS_OLD); - } - - public Supplier paths() { - return new Supplier() { - @Override - public KeyframeSet[] get() { - try { - ZipEntry entry = pathsEntry(); - if (entry == null) { - return null; - } - BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(entry))); - - GsonBuilder gsonBuilder = new GsonBuilder().registerTypeAdapter(KeyframeSet[].class, new LegacyKeyframeSetAdapter()); - Gson gson = gsonBuilder.create(); - - return gson.fromJson(reader, KeyframeSet[].class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry visibilityEntry() { - ZipEntry newEntry = getEntry(ENTRY_VISIBILITY); - return newEntry != null ? newEntry : getEntry(ENTRY_VISIBILITY_OLD); - } - - public Supplier visibility() { - return new Supplier() { - @Override - public PlayerVisibility get() { - try { - ZipEntry entry = visibilityEntry(); - if (entry == null) { - return null; - } - BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(entry))); - return new Gson().fromJson(reader, PlayerVisibility.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry markersEntry() { - return getEntry(ENTRY_MARKERS); - } - - public Supplier>> markers() { - return new Supplier>>() { - @Override - public List> get() { - try { - ZipEntry entry = markersEntry(); - if (entry == null) { - return null; - } - BufferedReader reader = new BufferedReader(new InputStreamReader(getInputStream(entry))); - - Type keyframeType = new TypeToken>>(){}.getType(); - - return new Gson().fromJson(reader, keyframeType); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry thumbEntry() { - return getEntry(ENTRY_THUMB); - } - - public Supplier thumb() { - return new Supplier() { - @Override - public BufferedImage get() { - try { - ZipEntry entry = thumbEntry(); - if (entry == null) { - return null; - } - InputStream is = getInputStream(entry); - int i = 7; - while (i > 0) { - i -= is.skip(i); // Security through obscurity \o/ - } - return ImageIO.read(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry resourcePackIndexEntry() { - return getEntry(ENTRY_RESOURCE_PACK_INDEX); - } - - public Supplier> resourcePackIndex() { - return new Supplier>() { - @Override - @SuppressWarnings("unchecked") - public Map get() { - try { - ZipEntry entry = resourcePackIndexEntry(); - if (entry == null) { - return null; - } - Map index = new HashMap(); - JsonObject json = new Gson().fromJson(new InputStreamReader(getInputStream(entry)), JsonObject.class); - for (Map.Entry e : json.entrySet()) { - index.put(Integer.parseInt(e.getKey()), e.getValue().getAsString()); - } - return index; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public ZipEntry resourcePackEntry(String hash) { - return getEntry(String.format(ENTRY_RESOURCE_PACK, hash)); - } - - public Supplier resourcePack(final String hash) { - return new Supplier() { - @Override - public InputStream get() { - try { - ZipEntry entry = resourcePackEntry(hash); - if (entry == null) { - return null; - } - return getInputStream(entry); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - } - - public Supplier assetRepository() { - return new Supplier() { - @Override - @SuppressWarnings("unchecked") - public AssetRepository get() { - AssetRepository assetRepository = new AssetRepository(); - - Enumeration entries = entries(); - - while(entries.hasMoreElements()) { - - try { - ZipEntry entry = entries.nextElement(); - - String entryName = entry.getName(); - - if(entryName.startsWith(ENTRY_ASSET_FOLDER)) { - String name = entry.getName().substring(ENTRY_ASSET_FOLDER.length()); - - String[] split = name.split("_"); - UUID uuid = UUID.fromString(split[0]); - - assetRepository.addAsset(name, getInputStream(entry), uuid); - } - } catch(Exception e) { - e.printStackTrace(); - } - } - - return assetRepository; - } - }; - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java index 04431c5f..12109d61 100755 --- a/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java +++ b/src/main/java/eu/crushedpixel/replaymod/utils/ReplayFileIO.java @@ -1,12 +1,12 @@ package eu.crushedpixel.replaymod.utils; import com.google.gson.Gson; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.recording.packet.PacketSerializer; +import de.johni0702.replaystudio.replay.ReplayMetaData; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.assets.CustomObjectRepository; -import eu.crushedpixel.replaymod.holders.*; -import eu.crushedpixel.replaymod.interpolation.KeyframeList; -import eu.crushedpixel.replaymod.recording.PacketSerializer; -import eu.crushedpixel.replaymod.recording.ReplayMetaData; +import eu.crushedpixel.replaymod.holders.KeyframeSet; +import eu.crushedpixel.replaymod.holders.PacketData; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import net.minecraft.network.EnumConnectionState; @@ -15,10 +15,12 @@ import net.minecraft.network.Packet; import net.minecraft.network.PacketBuffer; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; import java.io.*; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -72,57 +74,6 @@ public class ReplayFileIO { return files; } - public static void writeReplayFile(File replayFile, File tempFile, ReplayMetaData metaData, Set> markers, - Map resourcePacks, Map resourcePackRequests) throws IOException { - byte[] buffer = new byte[1024]; - - FileOutputStream fos = new FileOutputStream(replayFile); - ZipOutputStream zos = new ZipOutputStream(fos); - - String json = new Gson().toJson(metaData); - - zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_METADATA)); - PrintWriter pw = new PrintWriter(zos); - pw.write(json); - pw.flush(); - zos.closeEntry(); - - zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_RECORDING)); - FileInputStream fis = new FileInputStream(tempFile); - int len; - while((len = fis.read(buffer)) > 0) { - zos.write(buffer, 0, len); - } - - fis.close(); - zos.closeEntry(); - - if(!markers.isEmpty()) { - zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_MARKERS)); - - pw = new PrintWriter(zos); - pw.write(new Gson().toJson(markers.toArray(new Keyframe[markers.size()]))); - pw.flush(); - zos.closeEntry(); - } - - if(!resourcePackRequests.isEmpty()) { - zos.putNextEntry(new ZipEntry(ReplayFile.ENTRY_RESOURCE_PACK_INDEX)); - pw = new PrintWriter(zos); - pw.write(new Gson().toJson(resourcePackRequests)); - pw.flush(); - zos.closeEntry(); - - for(Map.Entry entry : resourcePacks.entrySet()) { - zos.putNextEntry(new ZipEntry(String.format(ReplayFile.ENTRY_RESOURCE_PACK, entry.getKey()))); - IOUtils.copy(new FileInputStream(entry.getValue()), zos); - zos.closeEntry(); - } - } - - zos.close(); - } - public static PacketData readPacketData(DataInputStream dis) throws IOException { int timestamp = dis.readInt(); int bytes = dis.readInt(); @@ -160,12 +111,6 @@ public class ReplayFileIO { return array; } - public static void writePacket(PacketData pd, DataOutput out) throws IOException { - out.writeInt(pd.getTimestamp()); - out.writeInt(pd.getByteArray().length); - out.write(pd.getByteArray()); - } - private static final Gson gson = new Gson(); private static void write(Object obj, File file) throws IOException { @@ -177,18 +122,10 @@ public class ReplayFileIO { write((Object) keyframeRegistry, file); } - public static void write(PlayerVisibility visibility, File file) throws IOException { - write((Object) visibility, file); - } - public static void write(ReplayMetaData metaData, File file) throws IOException { write((Object) metaData, file); } - public static void write(KeyframeList markers, File file) throws IOException { - write((Object) markers, file); - } - public static void write(CustomObjectRepository repository, File file) throws IOException { write((Object) repository, file); } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java b/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java index 7ada6d92..fc1c95d0 100755 --- a/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/ReplayScreenshot.java @@ -1,17 +1,14 @@ package eu.crushedpixel.replaymod.video; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType; import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener; -import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.ImageUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.File; public class ReplayScreenshot { @@ -67,20 +64,13 @@ public class ReplayScreenshot { final BufferedImage nbi = ImageUtils.cropImage(fbi, rect); - File replayFile = ReplayHandler.getReplayFile(); - - File tempImage = File.createTempFile("thumb", null); - int h = 720; int w = 1280; BufferedImage img = ImageUtils.scaleImage(nbi, new Dimension(w, h)); - ImageIO.write(img, "jpg", tempImage); - - ReplayMod.replayFileAppender.registerModifiedFile(tempImage, "thumb", replayFile); - - tempImage.deleteOnExit(); + // TODO +// ReplayHandler.getReplayFile().writeThumb(img); ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savedthumb", ChatMessageType.INFORMATION); } catch(Exception e) { diff --git a/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java index f5ae743b..132e2f6b 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/VideoRenderer.java @@ -1,17 +1,13 @@ package eu.crushedpixel.replaymod.video; -import eu.crushedpixel.replaymod.ReplayMod; +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.ReplaySender; import eu.crushedpixel.replaymod.gui.GuiVideoRenderer; import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.holders.Keyframe; -import eu.crushedpixel.replaymod.holders.SpectatorData; import eu.crushedpixel.replaymod.holders.TimestampValue; import eu.crushedpixel.replaymod.interpolation.KeyframeList; import eu.crushedpixel.replaymod.renderer.ChunkLoadingRenderGlobal; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.replay.ReplaySender; import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.timer.EnchantmentTimer; import eu.crushedpixel.replaymod.timer.ReplayTimer; import eu.crushedpixel.replaymod.video.capturer.RenderInfo; import eu.crushedpixel.replaymod.video.frame.RGBFrame; @@ -148,8 +144,9 @@ public class VideoRenderer implements RenderInfo { fps = options.getFps(); - positionKeyframes = ReplayHandler.getPositionKeyframes(); - timeKeyframes = ReplayHandler.getTimeKeyframes(); + // TODO +// positionKeyframes = ReplayHandler.getPositionKeyframes(); +// timeKeyframes = ReplayHandler.getTimeKeyframes(); int duration = Math.max(timeKeyframes.last().getRealTimestamp(), positionKeyframes.last().getRealTimestamp()); @@ -179,128 +176,130 @@ public class VideoRenderer implements RenderInfo { } private void updateCam() { - KeyframeList positionKeyframes = ReplayHandler.getPositionKeyframes(); - - if (mc.thePlayer == null) { - return; // Not ready yet - } - int videoTime = framesDone * 1000 / fps; - int posCount = ReplayHandler.getPositionKeyframes().size(); - - AdvancedPosition pos = new AdvancedPosition(); - Keyframe lastPos = positionKeyframes.getPreviousKeyframe(videoTime, true); - Keyframe nextPos = null; - - // Position interpolation - nextPos = positionKeyframes.getNextKeyframe(videoTime, true); - - int lastPosStamp = lastPos.getRealTimestamp(); - int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp(); - - int diffLength = nextPosStamp - lastPosStamp; - float diffPct = (float) (videoTime - lastPosStamp) / diffLength; - if(Float.isInfinite(diffPct) || Float.isNaN(diffPct)) diffPct = 0; - - float totalPct = (positionKeyframes.indexOf(lastPos) + diffPct) / (posCount-1); - pos = positionKeyframes.getInterpolatedValueForPathPosition(Math.max(0, Math.min(1, totalPct)), ReplayMod.replaySettings.isLinearMovement()); - - boolean spectateCamera = true; - - //check whether between two First Person Spectator Keyframes - if(lastPos != null && nextPos != null) { - if(lastPos.getValue() instanceof SpectatorData && nextPos.getValue() instanceof SpectatorData) { - SpectatorData previousSpectatorData = (SpectatorData)lastPos.getValue(); - SpectatorData nextSpectatorData = (SpectatorData)nextPos.getValue(); - if(previousSpectatorData.getSpectatedEntityID() == nextSpectatorData.getSpectatedEntityID()) { - if(previousSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON - && nextSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON) { - spectateCamera = false; - } - } - } - } - - if(spectateCamera) { - // Make sure we're spectating the camera entity - // We do not use .spectateCamera() as that method sets the position of the camera to the previous - // entity, overriding our calculations - ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity()); - - if(pos != null) { - ReplayHandler.setCameraTilt((float)pos.getRoll()); - ReplayHandler.getCameraEntity().movePath(pos); - mc.entityRenderer.fovModifierHand = mc.entityRenderer.fovModifierHandPrev = 1; - } - } else { - ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(((SpectatorData)lastPos.getValue()).getSpectatedEntityID())); - } + //TODO +// KeyframeList positionKeyframes = ReplayHandler.getPositionKeyframes(); +// +// if (mc.thePlayer == null) { +// return; // Not ready yet +// } +// int videoTime = framesDone * 1000 / fps; +// int posCount = ReplayHandler.getPositionKeyframes().size(); +// +// AdvancedPosition pos = new AdvancedPosition(); +// Keyframe lastPos = positionKeyframes.getPreviousKeyframe(videoTime, true); +// Keyframe nextPos = null; +// +// // Position interpolation +// nextPos = positionKeyframes.getNextKeyframe(videoTime, true); +// +// int lastPosStamp = lastPos.getRealTimestamp(); +// int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp(); +// +// int diffLength = nextPosStamp - lastPosStamp; +// float diffPct = (float) (videoTime - lastPosStamp) / diffLength; +// if(Float.isInfinite(diffPct) || Float.isNaN(diffPct)) diffPct = 0; +// +// float totalPct = (positionKeyframes.indexOf(lastPos) + diffPct) / (posCount-1); +// pos = positionKeyframes.getInterpolatedValueForPathPosition(Math.max(0, Math.min(1, totalPct)), ReplayMod.replaySettings.isLinearMovement()); +// +// boolean spectateCamera = true; +// +// //check whether between two First Person Spectator Keyframes +// if(lastPos != null && nextPos != null) { +// if(lastPos.getValue() instanceof SpectatorData && nextPos.getValue() instanceof SpectatorData) { +// SpectatorData previousSpectatorData = (SpectatorData)lastPos.getValue(); +// SpectatorData nextSpectatorData = (SpectatorData)nextPos.getValue(); +// if(previousSpectatorData.getSpectatedEntityID() == nextSpectatorData.getSpectatedEntityID()) { +// if(previousSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON +// && nextSpectatorData.getSpectatingMethod() == SpectatorData.SpectatingMethod.FIRST_PERSON) { +// spectateCamera = false; +// } +// } +// } +// } +// +// if(spectateCamera) { +// // Make sure we're spectating the camera entity +// // We do not use .spectateCamera() as that method sets the position of the camera to the previous +// // entity, overriding our calculations +// ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity()); +// +// if(pos != null) { +// ReplayHandler.setCameraTilt((float)pos.getRoll()); +// ReplayHandler.getCameraEntity().movePath(pos); +// mc.entityRenderer.fovModifierHand = mc.entityRenderer.fovModifierHandPrev = 1; +// } +// } else { +// ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(((SpectatorData)lastPos.getValue()).getSpectatedEntityID())); +// } } private void updateTime(Timer timer, int framesDone) { - KeyframeList timeKeyframes = ReplayHandler.getTimeKeyframes(); - - int videoTime = framesDone * 1000 / fps; - int timeCount = timeKeyframes.size(); - - // WARNING: The rest of this method contains some magic for which Marius is responsible - // Time interpolation - Keyframe lastTime = timeKeyframes.getPreviousKeyframe(videoTime, true); - Keyframe nextTime = timeKeyframes.getNextKeyframe(videoTime, true); - - int lastTimeStamp = 0; - int nextTimeStamp = 0; - - double curSpeed = 0; - - if(nextTime != null || lastTime != null) { - if(nextTime != null && lastTime != null && nextTime.getRealTimestamp() == lastTime.getRealTimestamp()) { - curSpeed = 0; - } else { - if(nextTime != null) { - nextTimeStamp = nextTime.getRealTimestamp(); - } else { - nextTimeStamp = lastTime.getRealTimestamp(); - } - - if(lastTime != null) { - lastTimeStamp = lastTime.getRealTimestamp(); - } else { - lastTimeStamp = nextTime.getRealTimestamp(); - } - - if(!(nextTime == null || lastTime == null)) { - curSpeed = ((double)(((int)nextTime.getValue().value-(int)lastTime.getValue().value)))/((double)((nextTimeStamp-lastTimeStamp))); - } - - if(lastTimeStamp == nextTimeStamp) { - curSpeed = 0f; - } - } - } - - int currentTimeDiff = nextTimeStamp - lastTimeStamp; - int currentTime = videoTime - lastTimeStamp; - - float currentTimeStepPerc = (float)currentTime/(float)currentTimeDiff; //The percentage of the travelled path between the current timestamps - if(Float.isInfinite(currentTimeStepPerc) || Float.isNaN(currentTimeStepPerc)) currentTimeStepPerc = 0; - - float timePos = (timeKeyframes.indexOf(lastTime) + currentTimeStepPerc) / (timeCount-1f); - - Integer replayTime = timeKeyframes.getInterpolatedValueForPathPosition(Math.max(0, Math.min(1, timePos)), true).asInt(); - - replaySender.sendPacketsTill(replayTime); - - if (curSpeed >= 0) { - replaySender.setReplaySpeed(curSpeed); - } - - // Update Timer - EnchantmentTimer.increaseRecordingTime(1000 / fps); - - timer.elapsedPartialTicks += timer.timerSpeed * 20 / fps; - timer.elapsedTicks = (int) timer.elapsedPartialTicks; - timer.elapsedPartialTicks -= timer.elapsedTicks; - timer.renderPartialTicks = timer.elapsedPartialTicks; + // TODO +// KeyframeList timeKeyframes = ReplayHandler.getTimeKeyframes(); +// +// int videoTime = framesDone * 1000 / fps; +// int timeCount = timeKeyframes.size(); +// +// // WARNING: The rest of this method contains some magic for which Marius is responsible +// // Time interpolation +// Keyframe lastTime = timeKeyframes.getPreviousKeyframe(videoTime, true); +// Keyframe nextTime = timeKeyframes.getNextKeyframe(videoTime, true); +// +// int lastTimeStamp = 0; +// int nextTimeStamp = 0; +// +// double curSpeed = 0; +// +// if(nextTime != null || lastTime != null) { +// if(nextTime != null && lastTime != null && nextTime.getRealTimestamp() == lastTime.getRealTimestamp()) { +// curSpeed = 0; +// } else { +// if(nextTime != null) { +// nextTimeStamp = nextTime.getRealTimestamp(); +// } else { +// nextTimeStamp = lastTime.getRealTimestamp(); +// } +// +// if(lastTime != null) { +// lastTimeStamp = lastTime.getRealTimestamp(); +// } else { +// lastTimeStamp = nextTime.getRealTimestamp(); +// } +// +// if(!(nextTime == null || lastTime == null)) { +// curSpeed = ((double)(((int)nextTime.getValue().value-(int)lastTime.getValue().value)))/((double)((nextTimeStamp-lastTimeStamp))); +// } +// +// if(lastTimeStamp == nextTimeStamp) { +// curSpeed = 0f; +// } +// } +// } +// +// int currentTimeDiff = nextTimeStamp - lastTimeStamp; +// int currentTime = videoTime - lastTimeStamp; +// +// float currentTimeStepPerc = (float)currentTime/(float)currentTimeDiff; //The percentage of the travelled path between the current timestamps +// if(Float.isInfinite(currentTimeStepPerc) || Float.isNaN(currentTimeStepPerc)) currentTimeStepPerc = 0; +// +// float timePos = (timeKeyframes.indexOf(lastTime) + currentTimeStepPerc) / (timeCount-1f); +// +// Integer replayTime = timeKeyframes.getInterpolatedValueForPathPosition(Math.max(0, Math.min(1, timePos)), true).asInt(); +// +// replaySender.sendPacketsTill(replayTime); +// +// if (curSpeed >= 0) { +// replaySender.setReplaySpeed(curSpeed); +// } +// +// // Update Timer +// EnchantmentTimer.increaseRecordingTime(1000 / fps); +// +// timer.elapsedPartialTicks += timer.timerSpeed * 20 / fps; +// timer.elapsedTicks = (int) timer.elapsedPartialTicks; +// timer.elapsedPartialTicks -= timer.elapsedTicks; +// timer.renderPartialTicks = timer.elapsedPartialTicks; } private void tick() { diff --git a/src/main/resources/META-INF/replaymod_at.cfg b/src/main/resources/META-INF/replaymod_at.cfg index c7a9a905..a728ce6d 100644 --- a/src/main/resources/META-INF/replaymod_at.cfg +++ b/src/main/resources/META-INF/replaymod_at.cfg @@ -101,5 +101,8 @@ public net.minecraft.client.renderer.culling.Frustum field_78552_a # clippingHel public net.minecraft.crash.CrashReportCategory field_85077_c # children public net.minecraft.crash.CrashReportCategory$Entry +# KeyBinding +public net.minecraft.client.settings.KeyBinding field_151474_i # pressTime + # Example # public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName diff --git a/src/main/resources/assets/guiapi/gui.png b/src/main/resources/assets/guiapi/gui.png new file mode 100644 index 00000000..20df55ca Binary files /dev/null and b/src/main/resources/assets/guiapi/gui.png differ diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 0bc2a067..b26e5dc3 100755 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -1,15 +1,69 @@ [ -{ - "modid": "replaymod", - "name": "Replay Mod", - "description": "A Mod which allows you to record, replay and share your Minecraft experience.", - "version": "${version}", - "mcversion": "${mcversion}", - "url": "https://replaymod.com", - "updateUrl": "https://replaymod.com/download", - "authorList": ["CrushedPixel", "johni0702"], - "logoFile": "replaymod_logo.png", - "screenshots": [], - "dependencies": [] -} + { + "modid": "replaymod", + "name": "Replay Mod", + "description": "A Mod which allows you to record, replay and share your Minecraft experience.", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://replaymod.com", + "updateUrl": "https://replaymod.com/download", + "authorList": [ + "CrushedPixel", + "johni0702" + ], + "logoFile": "replaymod_logo.png", + "screenshots": [], + "dependencies": [] + }, + { + "modid": "replaymod-recording", + "name": "Replay Mod - Recording", + "description": "Recording Module of the ReplayMod", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://replaymod.com", + "updateUrl": "https://replaymod.com/download", + "authorList": [ + "CrushedPixel", + "johni0702" + ], + "logoFile": "replaymod_logo.png", + "parent": "replaymod", + "screenshots": [], + "dependencies": [] + }, + { + "modid": "replaymod-replay", + "name": "Replay Mod - Replay", + "description": "Replay Module of the ReplayMod", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://replaymod.com", + "updateUrl": "https://replaymod.com/download", + "authorList": [ + "CrushedPixel", + "johni0702" + ], + "logoFile": "replaymod_logo.png", + "parent": "replaymod", + "screenshots": [], + "dependencies": [] + }, + { + "modid": "replaymod-extras", + "name": "Replay Mod - Extras", + "description": "Extras Module of the ReplayMod - Small but neat additions", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://replaymod.com", + "updateUrl": "https://replaymod.com/download", + "authorList": [ + "CrushedPixel", + "johni0702" + ], + "logoFile": "replaymod_logo.png", + "parent": "replaymod", + "screenshots": [], + "dependencies": [] + } ] diff --git a/src/main/resources/mixins.recording.replaymod.json b/src/main/resources/mixins.recording.replaymod.json new file mode 100644 index 00000000..272114ff --- /dev/null +++ b/src/main/resources/mixins.recording.replaymod.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "com.replaymod.recording.mixin", + "mixins": [], + "server": [], + "client": [ + "MixinNetHandlerPlayClient", + "MixinRenderGlobal" + ], + "refmap": "mixins.replaymod.refmap.json" +} \ No newline at end of file diff --git a/src/main/resources/mixins.replaymod.json b/src/main/resources/mixins.replaymod.json index d514ad09..9a3b623e 100644 --- a/src/main/resources/mixins.replaymod.json +++ b/src/main/resources/mixins.replaymod.json @@ -6,12 +6,10 @@ "MixinEntityRenderer", "MixinGuiSpectator", "MixinMinecraft", - "MixinNetHandlerPlayClient", "MixinPlayerControllerMP", "MixinRender", "MixinRenderArrow", "MixinRendererLivingEntity", - "MixinRenderGlobal", "MixinRenderItem", "MixinRenderManager", "MixinTileEntityEndPortalRenderer",