Split mod into core, recording, replay, render[todo], paths[todo] and extras[wip] modules

Move everything to com.replaymod package
Add KeyBindingRegistry and SettingsRegistry
Recreate settings GUI with new GUI API and dynamically from SettingsRegistry
Use ReplayFile from ReplayStudio
ReplayHandler is now object oriented
Add GuiOverlay, GuiSlider and GuiTexturedButton to GUI API
Rewrite both overlays to use new GUI API
Fix size capping in vertical and horizontal layout
Allow CustomLayouts to have parents
Fix tooltip rendering when close to screen border
Allow changing of columns in GridLayout
This commit is contained in:
johni0702
2015-10-03 17:36:03 +02:00
parent 8bd051eb27
commit f925d56ca2
141 changed files with 6294 additions and 5582 deletions

View File

@@ -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<String, KeyBinding> keyBindings = new HashMap<String, KeyBinding>();
private Multimap<KeyBinding, Runnable> 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<String, KeyBinding> getKeyBindings() {
return Collections.unmodifiableMap(keyBindings);
}
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event) {
for (Map.Entry<KeyBinding, Collection<Runnable>> 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);
}
}
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<SettingKey<?>, Object> settings = new ConcurrentHashMap<>();
private Configuration configuration;
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
List<SettingKey<?>> 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<SettingKey<?>> getSettings() {
return settings.keySet();
}
@SuppressWarnings("unchecked")
public <T> T get(SettingKey<T> key) {
if (!settings.containsKey(key)) {
throw new IllegalArgumentException("Setting " + key + " unknown.");
}
return (T) settings.get(key);
}
public <T> void set(SettingKey<T> 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<T> {
String getCategory();
String getKey();
String getDisplayString();
T getDefault();
}
public static class SettingKeys<T> implements SettingKey<T> {
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;
}
}
}

View File

@@ -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<GuiReplaySettings> {
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<Boolean> booleanKey = (SettingsRegistry.SettingKey<Boolean>) 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<GuiReplaySettings>() {
@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;
}
}

View File

@@ -0,0 +1,7 @@
package com.replaymod.extras;
import com.replaymod.core.ReplayMod;
public interface Extra {
void register(ReplayMod mod) throws Exception;
}

View File

@@ -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<GuiElement> getChildren() {
return open ? super.getChildren() : Collections.<GuiElement>emptyList();
}
@Override
public Map<GuiElement, LayoutData> getElements() {
return open ? super.getElements() : Collections.<GuiElement, LayoutData>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<GuiReplayOverlay>(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));
}
});
}
}
}

View File

@@ -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<Class<? extends Extra>> builtin = Arrays.<Class<? extends Extra>>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<? extends Extra> cls : builtin) {
try {
Extra extra = cls.newInstance();
extra.register(core);
} catch (Throwable t) {
logger.warn("Failed to load extra " + cls.getName() + ": ", t);
}
}
}
}

View File

@@ -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));
}
}

View File

@@ -0,0 +1,17 @@
package com.replaymod.recording;
import com.replaymod.core.SettingsRegistry;
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
public static final Setting<Boolean> RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true);
public static final Setting<Boolean> RECORD_SERVER = make("recordServer", "recordserver", true);
public static final Setting<Boolean> INDICATOR = make("indicator", "indicator", true);
private static <T> Setting<T> 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);
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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<S38PacketPlayerListItem.AddPlayerData> 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();
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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<String> players = new HashSet<>();
private boolean singleplayer;
private final Set<Marker> markers = new HashSet<>();
private final Map<Integer, String> 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();
}
}
}
}

View File

@@ -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> marker = new Keyframe<Marker>(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

View File

@@ -1,4 +1,4 @@
package eu.crushedpixel.replaymod.recording;
package com.replaymod.recording.packet;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

View File

@@ -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
}

View File

@@ -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<Marker> 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.<Marker>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<Marker> 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<Entity> entities = (List<Entity>) 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.
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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<Integer, String> index = replayFile.resourcePackIndex().get();
Map<Integer, String> 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

View File

@@ -0,0 +1,17 @@
package com.replaymod.replay;
import com.replaymod.core.SettingsRegistry;
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
public static final Setting<Boolean> RECORD_SINGLEPLAYER = make("recordSingleplayer", "recordsingleplayer", true);
public static final Setting<Boolean> RECORD_SERVER = make("recordServer", "recordserver", true);
public static final Setting<Boolean> INDICATOR = make("indicator", "indicator", true);
private static <T> Setting<T> 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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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<Marker> 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<Marker> 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<Marker> 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> 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;
}

View File

@@ -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<GuiReplayOverlay> {
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<GuiReplayOverlay>() {
@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;
}
}

View File

@@ -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);

View File

@@ -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<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, 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<BufferedImage> 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();
}

View File

@@ -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;

View File

@@ -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<GuiButton> 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<GuiButton> 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());
}
}
}
}

View File

@@ -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<T extends AbstractGuiOverlay<T>> extends AbstractGuiContainer<T> {
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;
}
}
}

View File

@@ -83,21 +83,21 @@ public abstract class AbstractGuiScreen<T extends AbstractGuiScreen<T>> 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);

View File

@@ -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<GuiOverlay> {
@Override
protected GuiOverlay getThis() {
return this;
}
}

View File

@@ -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<T extends AbstractGuiElement<T>> implements GuiElement<T> {
protected static final ResourceLocation TEXTURE = new ResourceLocation("guiapi", "gui.png");
@Getter
private final Minecraft minecraft = Minecraft.getMinecraft();

View File

@@ -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<T extends AbstractGuiSlider<T>> extends AbstractGuiElement<T> implements Clickable, Draggable, IGuiSlider<T> {
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();
}
}

View File

@@ -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<T extends AbstractGuiTexturedButton<T>> extends AbstractGuiClickable<T> implements Clickable, IGuiTexturedButton<T> {
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);
}
}

View File

@@ -47,7 +47,7 @@ public abstract class AbstractGuiToggleButton<V, T extends AbstractGuiToggleButt
@Override
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
String orgLabel = getLabel();
setLabel(orgLabel + values[selected]);
setLabel(orgLabel + ": " + values[selected]);
super.draw(renderer, size, renderInfo);
setLabel(orgLabel);
}

View File

@@ -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 GuiSlider extends AbstractGuiSlider<GuiSlider> {
public GuiSlider() {
}
public GuiSlider(GuiContainer container) {
super(container);
}
@Override
protected GuiSlider getThis() {
return this;
}
}

View File

@@ -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<GuiTexturedButton> {
public GuiTexturedButton() {
}
public GuiTexturedButton(GuiContainer container) {
super(container);
}
@Override
protected GuiTexturedButton getThis() {
return this;
}
}

View File

@@ -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<T extends IGuiSlider<T>> extends GuiElement<T> {
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);
}

View File

@@ -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<T extends IGuiTexturedButton<T>> extends IGuiClickable<T> {
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);
}

View File

@@ -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<T extends AbstractGuiTimeline<T>> extends AbstractGuiElement<T> implements IGuiTimeline<T>, 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;
}
}

View File

@@ -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<GuiTimeline> {
public GuiTimeline() {
}
public GuiTimeline(GuiContainer container) {
super(container);
}
@Override
protected GuiTimeline getThis() {
return this;
}
}

View File

@@ -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<T extends IGuiTimeline<T>> extends GuiElement<T> {
/**
* 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);
}
}

View File

@@ -35,15 +35,32 @@ import java.util.Collection;
import java.util.Map;
public abstract class CustomLayout<T extends GuiContainer<T>> implements Layout {
private final Layout parent;
private Map<GuiElement, Pair<Point, Dimension>> result = Maps.newHashMap();
public CustomLayout() {
this(null);
}
public CustomLayout(Layout parent) {
this.parent = parent;
}
@Override
@SuppressWarnings("unchecked")
public Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> layOut(GuiContainer container, ReadableDimension size) {
result.clear();
Collection<GuiElement> elements = container.getChildren();
for (GuiElement element : elements) {
result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize())));
if (parent == null) {
Collection<GuiElement> elements = container.getChildren();
for (GuiElement element : elements) {
result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize())));
}
} else {
Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> elements = parent.layOut(container, size);
for (Map.Entry<GuiElement, Pair<ReadablePoint, ReadableDimension>> entry : elements.entrySet()) {
Pair<ReadablePoint, ReadableDimension> pair = entry.getValue();
result.put(entry.getKey(), Pair.of(new Point(pair.getLeft()), new Dimension(pair.getRight())));
}
}
layout((T) container, size.getWidth(), size.getHeight());

View File

@@ -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

View File

@@ -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.<ReadablePoint, ReadableDimension>of(new Point(x, y), elementSize));

View File

@@ -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);

View File

@@ -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.*;

View File

@@ -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("&#34;", "\\\""));
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("&#34;", "\\\""));
return wrapWithJson(apiResult);
}
private static JsonElement wrapWithJson(String apiResult) {
return parser.parse(apiResult);
}
}

View File

@@ -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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> paramMap) throws IOException, ApiException {
QueryBuilder queryBuilder = new QueryBuilder(method);
queryBuilder.put(paramMap);
return invokeImpl(queryBuilder.toString());
}
}

View File

@@ -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;

View File

@@ -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";
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<? extends ZipEntry> 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<UUID, ReplayAsset> 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<UUID, ReplayAsset> 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) {

View File

@@ -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;
}

View File

@@ -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<BufferedImage> {
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

View File

@@ -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;

View File

@@ -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) {

View File

@@ -1,6 +0,0 @@
package eu.crushedpixel.replaymod.events;
import net.minecraftforge.fml.common.eventhandler.Event;
public class ReplayExitEvent extends Event {
}

View File

@@ -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();
// }
}
}

View File

@@ -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<GuiButton> buttonList = event.buttonList;
if(event.gui instanceof GuiIngameMenu && ReplayHandler.isInReplay()) {
ReplayMod.replaySender.setReplaySpeed(0);
for(GuiButton b : new ArrayList<GuiButton>(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();
}
}

View File

@@ -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");

View File

@@ -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;
// }
// }
}

View File

@@ -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);
// }
// }
}
}

View File

@@ -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();
// }
}
}

View File

@@ -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

View File

@@ -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<T extends KeyframeValue> 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<T extends KeyframeValue> 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<T extends KeyframeValue> extends GuiScreen
protected void drawScreen0() {}
private static class GuiEditKeyframeMarker extends GuiEditKeyframe<Marker> {
private GuiAdvancedTextField markerNameInput;
public GuiEditKeyframeMarker(Keyframe<Marker> 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<TimestampValue> {
private GuiNumberInput kfMin, kfSec, kfMs;
public GuiEditKeyframeTime(Keyframe<TimestampValue> 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<AdvancedPosition> {
private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll;
private ComposedElement posInputs;
public GuiEditKeyframePosition(Keyframe<AdvancedPosition> 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<AdvancedPosition> {
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<AdvancedPosition> 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<Marker> {
// private GuiAdvancedTextField markerNameInput;
//
// public GuiEditKeyframeMarker(Keyframe<Marker> 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<TimestampValue> {
// private GuiNumberInput kfMin, kfSec, kfMs;
//
// public GuiEditKeyframeTime(Keyframe<TimestampValue> 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<AdvancedPosition> {
// private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll;
// private ComposedElement posInputs;
//
// public GuiEditKeyframePosition(Keyframe<AdvancedPosition> 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<AdvancedPosition> {
// 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<AdvancedPosition> 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();
// }
// }
}

View File

@@ -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<Keyframe> kfs = new ArrayList<Keyframe>(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<Keyframe> kfs = new ArrayList<Keyframe>(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

View File

@@ -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();
}
}

View File

@@ -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<Pair<EntityPlayer, ResourceLocation>> players;
private List<GuiCheckBox> 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<UUID> initialHiddenPlayers;
public GuiPlayerOverview(List<EntityPlayer> players) {
initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers());
Collections.sort(players, new PlayerComparator());
this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
this.checkBoxes = new ArrayList<GuiCheckBox>();
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<GuiButton> 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<EntityPlayer, ResourceLocation> p : players) {
PlayerHandler.showPlayer(p.first());
}
} else if(button == hideAllBox) {
hideAllBox.setIsChecked(false);
for(Pair<EntityPlayer, ResourceLocation> 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<EntityPlayer, ResourceLocation> 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<GuiButton> 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<UUID> 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<EntityPlayer> {
@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<Pair<EntityPlayer, ResourceLocation>> players;
// private List<GuiCheckBox> 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<UUID> initialHiddenPlayers;
//
// public GuiPlayerOverview(List<EntityPlayer> players) {
// initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers());
//
// Collections.sort(players, new PlayerComparator());
//
// this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
// this.checkBoxes = new ArrayList<GuiCheckBox>();
//
// 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<GuiButton> 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<EntityPlayer, ResourceLocation> p : players) {
// PlayerHandler.showPlayer(p.first());
// }
// } else if(button == hideAllBox) {
// hideAllBox.setIsChecked(false);
// for(Pair<EntityPlayer, ResourceLocation> 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<EntityPlayer, ResourceLocation> 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<GuiButton> 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.<UUID>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<EntityPlayer> {
//
// @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());
// }
// }
//
// }
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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<Boolean> 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<Boolean> 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<Boolean> 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();
}
}

View File

@@ -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<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator();
while(iterator.hasNext()) {
Keyframe<AdvancedPosition> kf = iterator.next();
if(!(kf.getValue() instanceof SpectatorData))
continue;
int i = iterator.nextIndex();
int nextSpectatorKeyframeRealTime = -1;
if (iterator.hasNext()) {
Keyframe<AdvancedPosition> 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<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator();
while(iterator.hasNext()) {
Keyframe<TimestampValue> kf = iterator.next();
int i = iterator.nextIndex();
int nextTimeKeyframeRealTime = -1;
if (iterator.hasNext()) {
Keyframe<TimestampValue> 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<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator();
// while(iterator.hasNext()) {
// Keyframe<AdvancedPosition> kf = iterator.next();
//
// if(!(kf.getValue() instanceof SpectatorData))
// continue;
//
// int i = iterator.nextIndex();
// int nextSpectatorKeyframeRealTime = -1;
//
// if (iterator.hasNext()) {
// Keyframe<AdvancedPosition> 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<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator();
// while(iterator.hasNext()) {
// Keyframe<TimestampValue> kf = iterator.next();
//
// int i = iterator.nextIndex();
// int nextTimeKeyframeRealTime = -1;
//
// if (iterator.hasNext()) {
// Keyframe<TimestampValue> 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);
// }
// }
}

View File

@@ -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);

View File

@@ -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<GuiLoginPrompt> {

View File

@@ -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;

View File

@@ -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();

View File

@@ -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<GuiReplayDownloading
@Override
public void run() {
try {
ReplayHandler.startReplay(replayFile);
// TODO
// ReplayHandler.startReplay(replayFile);
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -7,8 +7,6 @@ import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton;
import eu.crushedpixel.replaymod.gui.elements.GuiDropdown;
import eu.crushedpixel.replaymod.gui.elements.GuiString;
import eu.crushedpixel.replaymod.holders.GuiEntryListValueEntry;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.ReplayFile;
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
@@ -55,7 +53,7 @@ public class GuiReplayInstanceChooser extends GuiScreen {
for(File file : files) {
try {
String extension = FilenameUtils.getExtension(file.getAbsolutePath());
if(!("." + extension).equals(ReplayFile.ZIP_FILE_EXTENSION)) continue;
if(!"zip".equals(extension)) continue;
String filename = FilenameUtils.getBaseName(file.getAbsolutePath());
String[] split = filename.split("_");
@@ -72,7 +70,8 @@ public class GuiReplayInstanceChooser extends GuiScreen {
//if no modified versions of the replay were found, start the downloaded one
if(chooseableFiles.isEmpty()) {
ReplayHandler.startReplay(downloadedFile);
// TODO
// ReplayHandler.startReplay(downloadedFile);
return;
}
@@ -103,7 +102,8 @@ public class GuiReplayInstanceChooser extends GuiScreen {
public void run() {
try {
File file = fileDropdown.getElement(fileDropdown.getSelectionIndex()).getValue();
ReplayHandler.startReplay(file);
//TODO
// ReplayHandler.startReplay(file);
} catch(Exception e) {
e.printStackTrace();
}

View File

@@ -1,16 +1,22 @@
package eu.crushedpixel.replaymod.gui.online;
import eu.crushedpixel.replaymod.ReplayMod;
import com.google.common.base.Optional;
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 com.replaymod.core.ReplayMod;
import eu.crushedpixel.replaymod.api.replay.FileUploader;
import eu.crushedpixel.replaymod.api.replay.holders.Category;
import eu.crushedpixel.replaymod.gui.GuiConstants;
import eu.crushedpixel.replaymod.gui.elements.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener;
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
import com.replaymod.replay.gui.screen.GuiReplayViewer;
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
import eu.crushedpixel.replaymod.registry.ResourceHelper;
import eu.crushedpixel.replaymod.utils.*;
import eu.crushedpixel.replaymod.utils.ImageUtils;
import eu.crushedpixel.replaymod.utils.MouseUtils;
import eu.crushedpixel.replaymod.utils.RegexUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiButton;
@@ -35,7 +41,6 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;
@@ -84,15 +89,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener {
boolean correctFile = false;
this.replayFile = file;
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ReplayFile.ZIP_FILE_EXTENSION)) {
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(".zip")) {
ReplayFile archive = null;
try {
archive = new ReplayFile(file);
archive = new ZipReplayFile(new ReplayStudio(), file);
metaData = archive.metadata().get();
BufferedImage img = archive.thumb().get();
if(img != null) {
thumb = ImageUtils.scaleImage(img, new Dimension(1280, 720));
metaData = archive.getMetaData();
Optional<BufferedImage> 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<String, File> toAdd = new HashMap<String, File>();
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);

View File

@@ -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<AdvancedPosition>(ReplayHandler.getRealTimelineCursor(), position));
else
ReplayHandler.addKeyframe(new Keyframe<AdvancedPosition>(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<AdvancedPosition>(ReplayHandler.getRealTimelineCursor(), position));
else
ReplayHandler.addKeyframe(new Keyframe<AdvancedPosition>(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<TimestampValue>(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<Entity> entities = (List<Entity>) 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 {
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<Marker>();
}
@Override
public Interpolation getCubicInterpolator() {
return new GenericSplineInterpolation<Marker>();
}
}

View File

@@ -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;
}

View File

@@ -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<AdvancedPosition>
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) {

View File

@@ -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<Integer, Keyframe<AdvancedPosition>> 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<AdvancedPosition>(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<AdvancedPosition>(interpolatedRealTimestamp, entityPosition));
}
i++;

Some files were not shown because too many files have changed in this diff Show More