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

@@ -119,7 +119,7 @@ jar {
manifest { manifest {
attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker', attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
'TweakOrder': '0', 'TweakOrder': '0',
'MixinConfigs': 'mixins.replaymod.json', 'MixinConfigs': 'mixins.replaymod.json,mixins.recording.replaymod.json',
'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin', 'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin',
'FMLAT': 'replaymod_at.cfg' 'FMLAT': 'replaymod_at.cfg'
} }

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.google.common.util.concurrent.ListenableFutureTask;
import com.replaymod.replay.ReplaySender;
import eu.crushedpixel.replaymod.api.ApiClient; import eu.crushedpixel.replaymod.api.ApiClient;
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
import eu.crushedpixel.replaymod.chat.ChatMessageHandler; 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.events.handlers.keyboard.KeyInputHandler;
import eu.crushedpixel.replaymod.gui.online.GuiReplayDownloading; 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.localization.LocalizedResourcePack;
import eu.crushedpixel.replaymod.online.authentication.ConfigurationAuthData; import eu.crushedpixel.replaymod.online.authentication.ConfigurationAuthData;
import eu.crushedpixel.replaymod.online.urischeme.UriScheme; import eu.crushedpixel.replaymod.online.urischeme.UriScheme;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import eu.crushedpixel.replaymod.registry.*; import eu.crushedpixel.replaymod.registry.*;
import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer; import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer;
import eu.crushedpixel.replaymod.renderer.InvisibilityRender; import eu.crushedpixel.replaymod.renderer.InvisibilityRender;
import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer; import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer;
import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; 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.EncodingPreset;
import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.settings.RenderOptions;
import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.settings.ReplaySettings;
import eu.crushedpixel.replaymod.sound.SoundHandler; import eu.crushedpixel.replaymod.sound.SoundHandler;
import eu.crushedpixel.replaymod.timer.ReplayTimer; import eu.crushedpixel.replaymod.timer.ReplayTimer;
import eu.crushedpixel.replaymod.utils.OpenGLUtils; 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.utils.TooltipRenderer;
import eu.crushedpixel.replaymod.video.rendering.Pipelines; import eu.crushedpixel.replaymod.video.rendering.Pipelines;
import lombok.Getter; import lombok.Getter;
@@ -38,6 +34,7 @@ import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory; import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.FMLClientHandler; 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.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import java.io.File; import java.io.File;
@@ -61,14 +59,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import static org.apache.commons.io.FileUtils.forceDelete; @Mod(modid = ReplayMod.MOD_ID, useMetadata = true)
import static org.apache.commons.io.FileUtils.listFiles;
@Mod(modid = ReplayMod.MODID, useMetadata = true)
public class ReplayMod { public class ReplayMod {
public static ModContainer getContainer() { public static ModContainer getContainer() {
return Loader.instance().getIndexedModList().get(MODID); return Loader.instance().getIndexedModList().get(MOD_ID);
} }
@Getter(lazy = true) @Getter(lazy = true)
@@ -85,14 +80,16 @@ public class ReplayMod {
return "Unknown"; 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(); private static final Minecraft mc = Minecraft.getMinecraft();
public static GuiEventHandler guiEventHandler; public static GuiEventHandler guiEventHandler;
public static GuiReplayOverlay overlay;
public static ReplaySettings replaySettings; public static ReplaySettings replaySettings;
public static Configuration config; public static Configuration config;
public static boolean firstMainMenu = true; public static boolean firstMainMenu = true;
public static RecordingHandler recordingHandler;
public static ChatMessageHandler chatMessageHandler = new ChatMessageHandler(); public static ChatMessageHandler chatMessageHandler = new ChatMessageHandler();
public static KeyInputHandler keyInputHandler = new KeyInputHandler(); public static KeyInputHandler keyInputHandler = new KeyInputHandler();
public static MouseInputHandler mouseInputHandler = new MouseInputHandler(); public static MouseInputHandler mouseInputHandler = new MouseInputHandler();
@@ -111,13 +108,30 @@ public class ReplayMod {
public static CrosshairRenderHandler crosshairRenderHandler; public static CrosshairRenderHandler crosshairRenderHandler;
public static ApiClient apiClient; public static ApiClient apiClient;
private final KeyBindingRegistry keyBindingRegistry = new KeyBindingRegistry();
private final SettingsRegistry settingsRegistry = new SettingsRegistry();
@Getter @Getter
private static boolean latestModVersion = true; private static boolean latestModVersion = true;
// The instance of your mod that Forge uses. // The instance of your mod that Forge uses.
@Instance(value = "ReplayModID") @Instance(MOD_ID)
public static ReplayMod instance; 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 @EventHandler
public void preInit(FMLPreInitializationEvent event) { public void preInit(FMLPreInitializationEvent event) {
try { try {
@@ -137,6 +151,7 @@ public class ReplayMod {
config = new Configuration(event.getSuggestedConfigurationFile()); config = new Configuration(event.getSuggestedConfigurationFile());
config.load(); config.load();
settingsRegistry.setConfiguration(config);
ConfigurationAuthData authData = new ConfigurationAuthData(config); ConfigurationAuthData authData = new ConfigurationAuthData(config);
apiClient = new ApiClient(authData); apiClient = new ApiClient(authData);
authData.load(apiClient); authData.load(apiClient);
@@ -144,7 +159,6 @@ public class ReplayMod {
uploadedFileHandler = new UploadedFileHandler(event.getModConfigurationDirectory()); uploadedFileHandler = new UploadedFileHandler(event.getModConfigurationDirectory());
replaySettings = new ReplaySettings(); replaySettings = new ReplaySettings();
replaySettings.readValues();
downloadedFileHandler = new DownloadedFileHandler(); downloadedFileHandler = new DownloadedFileHandler();
favoritedFileHandler = new FavoritedFileHandler(); favoritedFileHandler = new FavoritedFileHandler();
@@ -164,27 +178,22 @@ public class ReplayMod {
@EventHandler @EventHandler
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
mc.timer = new ReplayTimer(); mc.timer = new ReplayTimer();
overlay = new GuiReplayOverlay();
FMLCommonHandler.instance().bus().register(new ConnectionEventHandler());
MinecraftForge.EVENT_BUS.register(guiEventHandler = new GuiEventHandler()); MinecraftForge.EVENT_BUS.register(guiEventHandler = new GuiEventHandler());
FMLCommonHandler.instance().bus().register(keyInputHandler); FMLCommonHandler.instance().bus().register(keyInputHandler);
FMLCommonHandler.instance().bus().register(keyBindingRegistry);
FMLCommonHandler.instance().bus().register(mouseInputHandler); FMLCommonHandler.instance().bus().register(mouseInputHandler);
MinecraftForge.EVENT_BUS.register(mouseInputHandler); MinecraftForge.EVENT_BUS.register(mouseInputHandler);
recordingHandler = new RecordingHandler();
FMLCommonHandler.instance().bus().register(recordingHandler);
MinecraftForge.EVENT_BUS.register(recordingHandler);
} }
@EventHandler @EventHandler
public void postInit(FMLPostInitializationEvent event) throws IOException { public void postInit(FMLPostInitializationEvent event) throws IOException {
settingsRegistry.save(); // Save default values to disk
if(!FMLClientHandler.instance().hasOptifine()) if(!FMLClientHandler.instance().hasOptifine())
GameSettings.Options.RENDER_DISTANCE.setValueMax(64f); GameSettings.Options.RENDER_DISTANCE.setValueMax(64f);
overlay.register();
TickAndRenderListener tarl = new TickAndRenderListener(); TickAndRenderListener tarl = new TickAndRenderListener();
FMLCommonHandler.instance().bus().register(tarl); FMLCommonHandler.instance().bus().register(tarl);
MinecraftForge.EVENT_BUS.register(tarl); MinecraftForge.EVENT_BUS.register(tarl);
@@ -212,9 +221,6 @@ public class ReplayMod {
skinMap.put("default", new InvisibilityRender(mc.getRenderManager())); skinMap.put("default", new InvisibilityRender(mc.getRenderManager()));
skinMap.put("slim", new InvisibilityRender(mc.getRenderManager(), true)); skinMap.put("slim", new InvisibilityRender(mc.getRenderManager(), true));
//clean up replay_recordings folder
removeTmcprFiles();
Thread localizedResourcePackLoader = new Thread(new Runnable() { Thread localizedResourcePackLoader = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -330,36 +336,42 @@ public class ReplayMod {
} }
System.out.println("Loading replay..."); System.out.println("Loading replay...");
ReplayHandler.startReplay(file, false); // TODO
// try {
int index = 0; // ReplayHandler.startReplay(file, false);
if (path != null) { // } catch (Throwable t) {
for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) { // t.printStackTrace();
if (set.getName().equals(path)) { // FMLCommonHandler.instance().exitJava(1, false);
break; // }
} //
index++; // int index = 0;
} // if (path != null) {
if (index >= ReplayHandler.getKeyframeRepository().length) { // for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) {
throw new IllegalArgumentException("No path named \"" + path + "\"."); // if (set.getName().equals(path)) {
} // break;
} else if (ReplayHandler.getKeyframeRepository().length == 0) { // }
throw new IllegalArgumentException("Replay file has no paths defined."); // index++;
} // }
ReplayHandler.useKeyframePresetFromRepository(index); // if (index >= ReplayHandler.getKeyframeRepository().length) {
// throw new IllegalArgumentException("No path named \"" + path + "\".");
System.out.println("Rendering started..."); // }
try { // } else if (ReplayHandler.getKeyframeRepository().length == 0) {
ReplayProcess.startReplayProcess(options, true); // throw new IllegalArgumentException("Replay file has no paths defined.");
} catch (Throwable t) { // }
t.printStackTrace(); // ReplayHandler.useKeyframePresetFromRepository(index);
FMLCommonHandler.instance().exitJava(1, false); //
} // System.out.println("Rendering started...");
if (mc.hasCrashed) { // try {
System.out.println(mc.crashReporter.getCompleteReport()); // ReplayProcess.startReplayProcess(options, true);
} // } catch (Throwable t) {
System.out.println("Rendering done. Shutting down..."); // t.printStackTrace();
mc.shutdown(); // FMLCommonHandler.instance().exitJava(1, false);
// }
// if (mc.hasCrashed) {
// System.out.println(mc.crashReporter.getCompleteReport());
// }
// System.out.println("Rendering done. Shutting down...");
// mc.shutdown();
} }
}, null)); }, null));
} }
@@ -422,7 +434,8 @@ public class ReplayMod {
new GuiReplayDownloading(info).display(); new GuiReplayDownloading(info).display();
} else { } else {
try { try {
ReplayHandler.startReplay(file); // TODO
// ReplayHandler.startReplay(file);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -434,16 +447,4 @@ public class ReplayMod {
System.exit(-1); 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.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; import static com.replaymod.core.ReplayMod.TEXTURE;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
/** /**
* Renders overlay during recording. * Renders overlay during recording.
@@ -22,6 +23,14 @@ public class GuiRecordingOverlay {
this.mc = mc; 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. * Render the recording icon and text in the top left corner of the screen.
* @param event Rendered post game overlay * @param event Rendered post game overlay
@@ -32,7 +41,7 @@ public class GuiRecordingOverlay {
if(ReplayMod.replaySettings.showRecordingIndicator()) { if(ReplayMod.replaySettings.showRecordingIndicator()) {
FontRenderer fontRenderer = mc.fontRendererObj; FontRenderer fontRenderer = mc.fontRendererObj;
fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff); 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.resetColor();
GlStateManager.enableAlpha(); GlStateManager.enableAlpha();
Gui.drawModalRectWithCustomSizedTexture(10, 10, 58, 20, 16, 16, TEXTURE_SIZE, TEXTURE_SIZE); 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.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.Channel;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.WorldType; import net.minecraft.world.WorldType;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.File; import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
/**
* Handles connection events and initiates recording if enabled.
*/
public class ConnectionEventHandler { public class ConnectionEventHandler {
private static final String packetHandlerKey = "packet_handler"; private static final String packetHandlerKey = "packet_handler";
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss"; private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
private static PacketListener packetListener = null; private static final Minecraft mc = Minecraft.getMinecraft();
private static boolean isRecording = false;
private final GuiRecordingOverlay guiOverlay = new GuiRecordingOverlay(Minecraft.getMinecraft());
private static final Logger logger = LogManager.getLogger(); private final Logger logger;
private final ReplayMod core;
public static boolean isRecording() { private RecordingEventHandler recordingEventHandler;
return isRecording; private PacketListener packetListener;
} private GuiRecordingOverlay guiOverlay;
public static void notifyServerPaused() { public ConnectionEventHandler(Logger logger, ReplayMod core) {
if (packetListener != null) { this.logger = logger;
packetListener.serverWasPaused = true; this.core = core;
}
}
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();
}
} }
@SubscribeEvent @SubscribeEvent
public void onConnectedToServerEvent(ClientConnectedToServerEvent event) { public void onConnectedToServerEvent(ClientConnectedToServerEvent event) {
ReplayMod.chatMessageHandler.initialize(); ReplayMod.chatMessageHandler.initialize();
ReplayMod.recordingHandler.resetVars();
try { try {
if(event.isLocal) { if(event.isLocal) {
@@ -81,16 +55,17 @@ public class ConnectionEventHandler {
logger.info("Debug World recording is not supported."); logger.info("Debug World recording is not supported.");
return; return;
} }
if(!ReplayMod.replaySettings.isEnableRecordingSingleplayer()) { if(!core.getSettingsRegistry().get(Setting.RECORD_SINGLEPLAYER)) {
logger.info("Singleplayer Recording is disabled"); logger.info("Singleplayer Recording is disabled");
return; return;
} }
} else { } else {
if(!ReplayMod.replaySettings.isEnableRecordingServer()) { if(!core.getSettingsRegistry().get(Setting.RECORD_SERVER)) {
logger.info("Multiplayer Recording is disabled"); logger.info("Multiplayer Recording is disabled");
return; return;
} }
} }
NetworkManager nm = event.manager; NetworkManager nm = event.manager;
String worldName; String worldName;
if(event.isLocal) { if(event.isLocal) {
@@ -101,17 +76,22 @@ public class ConnectionEventHandler {
Channel channel = nm.channel(); Channel channel = nm.channel();
ChannelPipeline pipeline = channel.pipeline(); ChannelPipeline pipeline = channel.pipeline();
File folder = ReplayFileIO.getReplayFolder(); File folder = core.getReplayFolder();
String fileName = sdf.format(Calendar.getInstance().getTime()); String name = sdf.format(Calendar.getInstance().getTime());
File currentFile = new File(folder, fileName + ReplayFile.TEMP_FILE_EXTENSION); 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); ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingstarted", ChatMessageType.INFORMATION);
isRecording = true;
MinecraftForge.EVENT_BUS.register(guiOverlay);
} catch(Exception e) { } catch(Exception e) {
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingfailed", ChatMessageType.WARNING); ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingfailed", ChatMessageType.WARNING);
e.printStackTrace(); e.printStackTrace();
@@ -120,11 +100,18 @@ public class ConnectionEventHandler {
@SubscribeEvent @SubscribeEvent
public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) { public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) {
if (isRecording) { if (packetListener != null) {
isRecording = false; guiOverlay.unregister();
MinecraftForge.EVENT_BUS.unregister(guiOverlay); guiOverlay = null;
recordingEventHandler.unregister();
recordingEventHandler = null;
packetListener = null; packetListener = null;
ReplayMod.chatMessageHandler.stop(); 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 eu.crushedpixel.replaymod.utils.Objects;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; 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.*;
import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove; import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove;
import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent; import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent; 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.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.ItemPickupEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.ItemPickupEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;
public class RecordingHandler { public class RecordingEventHandler {
private final Minecraft mc = Minecraft.getMinecraft(); 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 ItemStack[] playerItems = new ItemStack[5];
private int ticksSinceLastCorrection = 0; private int ticksSinceLastCorrection;
private boolean wasSleeping = false; private boolean wasSleeping;
private int lastRiding = -1; 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() { public void onPlayerJoin() {
try { try {
if(!ConnectionEventHandler.isRecording()) return; packetListener.save(spawnPlayer(mc.thePlayer));
ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer));
} catch(Exception e1) { } catch(Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
public void onPlayerRespawn() { public void onPlayerRespawn() {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer)); packetListener.save(spawnPlayer(mc.thePlayer));
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -81,18 +102,10 @@ public class RecordingHandler {
} }
} }
public void resetVars() {
lastX = lastY = lastZ = null;
rotationYawHeadBefore = null;
playerItems = new ItemStack[5];
}
@SubscribeEvent @SubscribeEvent
public void onPlayerTick(PlayerTickEvent e) { public void onPlayerTick(PlayerTickEvent e) {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
if(e.player != mc.thePlayer) return; if(e.player != mc.thePlayer) return;
if(!ConnectionEventHandler.isRecording()) return;
boolean force = false; boolean force = false;
if(lastX == null || lastY == null || lastZ == null) { if(lastX == null || lastY == null || lastZ == null) {
@@ -133,7 +146,7 @@ public class RecordingHandler {
newYaw, newPitch, e.player.onGround); newYaw, newPitch, e.player.onGround);
} }
ConnectionEventHandler.insertPacket(packet); packetListener.save(packet);
//HEAD POS //HEAD POS
int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F)); int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F));
@@ -148,13 +161,13 @@ public class RecordingHandler {
head.readPacketData(pb1); head.readPacketData(pb1);
ConnectionEventHandler.insertPacket(head); packetListener.save(head);
rotationYawHeadBefore = rotationYawHead; rotationYawHeadBefore = rotationYawHead;
} }
S12PacketEntityVelocity vel = new S12PacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ); S12PacketEntityVelocity vel = new S12PacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ);
ConnectionEventHandler.insertPacket(vel); packetListener.save(vel);
//Animation Packets //Animation Packets
//Swing Animation //Swing Animation
@@ -169,7 +182,7 @@ public class RecordingHandler {
pac.readPacketData(pb); pac.readPacketData(pb);
ConnectionEventHandler.insertPacket(pac); packetListener.save(pac);
} }
/* /*
@@ -179,13 +192,13 @@ public class RecordingHandler {
found.add(pe.getPotionID()); found.add(pe.getPotionID());
if(lastEffects.contains(found)) continue; if(lastEffects.contains(found)) continue;
S1DPacketEntityEffect pee = new S1DPacketEntityEffect(entityID, pe); S1DPacketEntityEffect pee = new S1DPacketEntityEffect(entityID, pe);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
for(int id : lastEffects) { for(int id : lastEffects) {
if(!found.contains(id)) { if(!found.contains(id)) {
S1EPacketRemoveEntityEffect pre = new S1EPacketRemoveEntityEffect(entityID, new PotionEffect(id, 0)); 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()) { if(playerItems[0] != mc.thePlayer.getHeldItem()) {
playerItems[0] = mc.thePlayer.getHeldItem(); playerItems[0] = mc.thePlayer.getHeldItem();
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 0, playerItems[0]); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 0, playerItems[0]);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
if(playerItems[1] != mc.thePlayer.inventory.armorInventory[0]) { if(playerItems[1] != mc.thePlayer.inventory.armorInventory[0]) {
playerItems[1] = mc.thePlayer.inventory.armorInventory[0]; playerItems[1] = mc.thePlayer.inventory.armorInventory[0];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 1, playerItems[1]); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 1, playerItems[1]);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
if(playerItems[2] != mc.thePlayer.inventory.armorInventory[1]) { if(playerItems[2] != mc.thePlayer.inventory.armorInventory[1]) {
playerItems[2] = mc.thePlayer.inventory.armorInventory[1]; playerItems[2] = mc.thePlayer.inventory.armorInventory[1];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 2, playerItems[2]); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 2, playerItems[2]);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
if(playerItems[3] != mc.thePlayer.inventory.armorInventory[2]) { if(playerItems[3] != mc.thePlayer.inventory.armorInventory[2]) {
playerItems[3] = mc.thePlayer.inventory.armorInventory[2]; playerItems[3] = mc.thePlayer.inventory.armorInventory[2];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 3, playerItems[3]); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 3, playerItems[3]);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
if(playerItems[4] != mc.thePlayer.inventory.armorInventory[3]) { if(playerItems[4] != mc.thePlayer.inventory.armorInventory[3]) {
playerItems[4] = mc.thePlayer.inventory.armorInventory[3]; playerItems[4] = mc.thePlayer.inventory.armorInventory[3];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 4, playerItems[4]); S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 4, playerItems[4]);
ConnectionEventHandler.insertPacket(pee); packetListener.save(pee);
} }
//Leaving Ride //Leaving Ride
@@ -244,7 +257,7 @@ public class RecordingHandler {
pea.readPacketData(pbuf); pea.readPacketData(pbuf);
ConnectionEventHandler.insertPacket(pea); packetListener.save(pea);
} }
//Sleeping //Sleeping
@@ -259,7 +272,7 @@ public class RecordingHandler {
pac.readPacketData(pb); pac.readPacketData(pb);
ConnectionEventHandler.insertPacket(pac); packetListener.save(pac);
wasSleeping = false; wasSleeping = false;
} }
@@ -271,9 +284,8 @@ public class RecordingHandler {
@SubscribeEvent @SubscribeEvent
public void onPickupItem(ItemPickupEvent event) { public void onPickupItem(ItemPickupEvent event) {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
ConnectionEventHandler.insertPacket(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId())); packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -281,7 +293,6 @@ public class RecordingHandler {
@SubscribeEvent @SubscribeEvent
public void onStartEating(PlayerUseItemEvent.Start event) { public void onStartEating(PlayerUseItemEvent.Start event) {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
if(!event.entityPlayer.isEating()) return; if(!event.entityPlayer.isEating()) return;
S0BPacketAnimation packet = new S0BPacketAnimation(); S0BPacketAnimation packet = new S0BPacketAnimation();
@@ -294,7 +305,7 @@ public class RecordingHandler {
packet.readPacketData(pb); packet.readPacketData(pb);
ConnectionEventHandler.insertPacket(packet); packetListener.save(packet);
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -302,13 +313,11 @@ public class RecordingHandler {
@SubscribeEvent @SubscribeEvent
public void onSleep(PlayerSleepInBedEvent event) { public void onSleep(PlayerSleepInBedEvent event) {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
if(event.entityPlayer != mc.thePlayer) { if(event.entityPlayer != mc.thePlayer) {
return; return;
} }
System.out.println(event.getResult());
S0APacketUseBed pub = new S0APacketUseBed(); S0APacketUseBed pub = new S0APacketUseBed();
ByteBuf buf = Unpooled.buffer(); ByteBuf buf = Unpooled.buffer();
@@ -319,7 +328,7 @@ public class RecordingHandler {
pub.readPacketData(pbuf); pub.readPacketData(pbuf);
ConnectionEventHandler.insertPacket(pub); packetListener.save(pub);
wasSleeping = true; wasSleeping = true;
@@ -330,7 +339,6 @@ public class RecordingHandler {
@SubscribeEvent @SubscribeEvent
public void enterMinecart(MinecartInteractEvent event) { public void enterMinecart(MinecartInteractEvent event) {
if(!ConnectionEventHandler.isRecording()) return;
try { try {
if(event.player != mc.thePlayer) { if(event.player != mc.thePlayer) {
return; return;
@@ -347,7 +355,7 @@ public class RecordingHandler {
pea.readPacketData(pbuf); pea.readPacketData(pbuf);
ConnectionEventHandler.insertPacket(pea); packetListener.save(pea);
lastRiding = event.minecart.getEntityId(); lastRiding = event.minecart.getEntityId();
} catch(Exception e) { } 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 @SubscribeEvent
public void checkForGamePaused(TickEvent.RenderTickEvent event) { public void checkForGamePaused(TickEvent.RenderTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase != TickEvent.Phase.START) return;
if (!ConnectionEventHandler.isRecording()) return;
if (mc.isIntegratedServerRunning()) { if (mc.isIntegratedServerRunning()) {
IntegratedServer server = mc.getIntegratedServer(); IntegratedServer server = mc.getIntegratedServer();
if (server != null && server.isGamePaused) { 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 com.replaymod.recording.handler.RecordingEventHandler;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.S07PacketRespawn; import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S38PacketPlayerListItem; import net.minecraft.network.play.server.S38PacketPlayerListItem;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -16,6 +16,13 @@ import java.util.List;
@Mixin(NetHandlerPlayClient.class) @Mixin(NetHandlerPlayClient.class)
public abstract class MixinNetHandlerPlayClient { 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. * Record the own player entity joining the world.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id * 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")) @Inject(method = "handlePlayerListItem", at=@At("RETURN"))
public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) { 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") @SuppressWarnings("unchecked")
List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a(); List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a();
for (S38PacketPlayerListItem.AddPlayerData data : dataList) { for (S38PacketPlayerListItem.AddPlayerData data : dataList) {
if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())) { 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")) @Inject(method = "handleRespawn", at=@At("RETURN"))
public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) { public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) {
if (ConnectionEventHandler.isRecording()) { RecordingEventHandler handler = getRecordingEventHandler();
ReplayMod.recordingHandler.onPlayerRespawn(); 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.hash.Hashing;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import eu.crushedpixel.replaymod.ReplayMod; import de.johni0702.replaystudio.replay.ReplayFile;
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 eu.crushedpixel.replaymod.replay.Restrictions; import eu.crushedpixel.replaymod.replay.Restrictions;
import eu.crushedpixel.replaymod.utils.ReplayFileIO; import eu.crushedpixel.replaymod.utils.ReplayFileIO;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@@ -35,7 +31,6 @@ import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -50,11 +45,11 @@ public class PacketListener extends DataListener {
private int nextRequestId; 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); super(file, name, worldName, startTime, singleplayer);
} }
public void saveOnly(Packet packet) { public void save(Packet packet) {
try { try {
if(packet instanceof S0CPacketSpawnPlayer) { if(packet instanceof S0CPacketSpawnPlayer) {
UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c(); UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c();
@@ -101,7 +96,7 @@ public class PacketListener extends DataListener {
if (packet instanceof S48PacketResourcePackSend) { if (packet instanceof S48PacketResourcePackSend) {
S48PacketResourcePackSend p = (S48PacketResourcePackSend) packet; S48PacketResourcePackSend p = (S48PacketResourcePackSend) packet;
int requestId = handleResourcePack(p); int requestId = handleResourcePack(p);
saveOnly(new S48PacketResourcePackSend("replay://" + requestId, "")); save(new S48PacketResourcePackSend("replay://" + requestId, ""));
return; return;
} }
@@ -216,17 +211,6 @@ public class PacketListener extends DataListener {
return requestId; 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) { private void downloadResourcePackFuture(int requestId, String url, final String hash) {
Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() { Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() {
@Override @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.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; 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.holders.AdvancedPosition;
import eu.crushedpixel.replaymod.replay.LesserDataWatcher; import eu.crushedpixel.replaymod.replay.LesserDataWatcher;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.stats.StatFileWriter; import net.minecraft.stats.StatFileWriter;
import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
@@ -48,12 +46,12 @@ public class CameraEntity extends EntityPlayerSP {
private Vec3 dirBefore; private Vec3 dirBefore;
private double motion; private double motion;
public float roll;
private long lastCall = 0; private long lastCall = 0;
private boolean speedup = false; private boolean speedup = false;
public static UUID spectating;
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) { public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) {
super(mcIn, worldIn, netHandlerPlayClient, statFileWriter); super(mcIn, worldIn, netHandlerPlayClient, statFileWriter);
} }
@@ -133,11 +131,11 @@ public class CameraEntity extends EntityPlayerSP {
this.moveAbsolute(pos.getX(), pos.getY(), pos.getZ()); this.moveAbsolute(pos.getX(), pos.getY(), pos.getZ());
rotationPitch = prevRotationPitch = (float)pos.getPitch(); rotationPitch = prevRotationPitch = (float)pos.getPitch();
rotationYaw = prevRotationYaw = (float)pos.getYaw(); rotationYaw = prevRotationYaw = (float)pos.getYaw();
roll = (float) pos.getRoll();
updateBoundingBox(); updateBoundingBox();
} }
public void moveAbsolute(double x, double y, double z) { public void moveAbsolute(double x, double y, double z) {
if(ReplayHandler.isInPath()) return;
this.lastTickPosX = this.prevPosX = this.posX = x; this.lastTickPosX = this.prevPosX = this.posX = x;
this.lastTickPosY = this.prevPosY = this.posY = y; this.lastTickPosY = this.prevPosY = this.posY = y;
this.lastTickPosZ = this.prevPosZ = this.posZ = z; 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) { public void moveRelative(double x, double y, double z) {
if(ReplayHandler.isInPath()) return;
this.lastTickPosX = this.prevPosX = this.posX = this.posX + x; this.lastTickPosX = this.prevPosX = this.posX = this.posX + x;
this.lastTickPosY = this.prevPosY = this.posY = this.posY + y; this.lastTickPosY = this.prevPosY = this.posY = this.posY + y;
this.lastTickPosZ = this.prevPosZ = this.posZ = this.posZ + z; this.lastTickPosZ = this.prevPosZ = this.posZ = this.posZ + z;
@@ -155,6 +152,7 @@ public class CameraEntity extends EntityPlayerSP {
public void movePath(AdvancedPosition pos) { public void movePath(AdvancedPosition pos) {
this.prevRotationPitch = this.rotationPitch = (float)pos.getPitch(); this.prevRotationPitch = this.rotationPitch = (float)pos.getPitch();
this.prevRotationYaw = this.rotationYaw = (float)pos.getYaw(); this.prevRotationYaw = this.rotationYaw = (float)pos.getYaw();
this.roll = (float) pos.getRoll();
this.lastTickPosX = this.prevPosX = this.posX = pos.getX(); this.lastTickPosX = this.prevPosX = this.posX = pos.getX();
this.lastTickPosY = this.prevPosY = this.posY = pos.getY(); this.lastTickPosY = this.prevPosY = this.posY = pos.getY();
this.lastTickPosZ = this.prevPosZ = this.posZ = pos.getZ(); 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)); posX + width / 2, posY + height, posZ + width / 2));
} }
private void updatePos(Entity to) { protected void updatePos(Entity to) {
prevPosX = to.prevPosX; prevPosX = to.prevPosX;
prevPosY = to.prevPosY; prevPosY = to.prevPosY;
prevPosZ = to.prevPosZ; prevPosZ = to.prevPosZ;
@@ -188,9 +186,6 @@ public class CameraEntity extends EntityPlayerSP {
@Override @Override
public void setAngles(float yaw, float pitch) { 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.rotationYaw = (float) ((double) this.rotationYaw + (double) yaw * 0.15D);
this.rotationPitch = (float) ((double) this.rotationPitch - (double) pitch * 0.15D); this.rotationPitch = (float) ((double) this.rotationPitch - (double) pitch * 0.15D);
this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F); this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F);
@@ -202,6 +197,7 @@ public class CameraEntity extends EntityPlayerSP {
public void onUpdate() { public void onUpdate() {
Entity view = mc.getRenderViewEntity(); Entity view = mc.getRenderViewEntity();
if (view != null) { if (view != null) {
UUID spectating = ReplayModReplay.instance.getReplayHandler().spectating;
if (spectating != null && (view.getUniqueID() != spectating || view.worldObj != worldObj)) { if (spectating != null && (view.getUniqueID() != spectating || view.worldObj != worldObj)) {
view = worldObj.getPlayerEntityByUUID(spectating); view = worldObj.getPlayerEntityByUUID(spectating);
if (view != null) { if (view != null) {
@@ -263,20 +259,6 @@ public class CameraEntity extends EntityPlayerSP {
return true; 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 { public enum MoveDirection {
UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD 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.base.Preconditions;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.common.util.concurrent.ListenableFutureTask; import com.google.common.util.concurrent.ListenableFutureTask;
import eu.crushedpixel.replaymod.ReplayMod; import de.johni0702.replaystudio.replay.ReplayFile;
import eu.crushedpixel.replaymod.entities.CameraEntity; import com.replaymod.core.ReplayMod;
import eu.crushedpixel.replaymod.holders.PacketData; import eu.crushedpixel.replaymod.holders.PacketData;
import eu.crushedpixel.replaymod.replay.Restrictions;
import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.settings.ReplaySettings;
import eu.crushedpixel.replaymod.utils.ReplayFile;
import eu.crushedpixel.replaymod.utils.ReplayFileIO; import eu.crushedpixel.replaymod.utils.ReplayFileIO;
import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@@ -67,6 +67,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
S39PacketPlayerAbilities.class, S39PacketPlayerAbilities.class,
S45PacketTitle.class); S45PacketTitle.class);
/**
* The replay handler responsible for the current replay.
*/
private final ReplayHandler replayHandler;
/** /**
* Whether to work in async mode. * 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 * @param asyncMode {@code true} for async mode, {@code false} otherwise
* @see #asyncMode * @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.replayFile = file;
this.asyncMode = asyncMode; this.asyncMode = asyncMode;
this.replayLength = file.metadata().get().getDuration(); this.replayLength = file.getMetaData().getDuration();
if (asyncMode) { if (asyncMode) {
new Thread(asyncSender, "replaymod-async-sender").start(); new Thread(asyncSender, "replaymod-async-sender").start();
@@ -296,7 +302,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
if (p instanceof S3FPacketCustomPayload) { if (p instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p; S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) { if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) {
final String unknown = ReplayHandler.getRestrictions().handle(packet); final String unknown = replayHandler.getRestrictions().handle(packet);
if (unknown == null) { if (unknown == null) {
return null; return null;
} else { } else {
@@ -306,7 +312,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
mc.addScheduledTask(new Runnable() { mc.addScheduledTask(new Runnable() {
@Override @Override
public void run() { public void run() {
ReplayHandler.endReplay(); try {
replayHandler.endReplay();
} catch (IOException e) {
e.printStackTrace();
}
mc.displayGuiScreen(new GuiErrorScreen( mc.displayGuiScreen(new GuiErrorScreen(
I18n.format("replaymod.error.unknownrestriction1"), I18n.format("replaymod.error.unknownrestriction1"),
I18n.format("replaymod.error.unknownrestriction2", unknown) I18n.format("replaymod.error.unknownrestriction2", unknown)
@@ -327,12 +337,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
if(BAD_PACKETS.contains(p.getClass())) return null; if(BAD_PACKETS.contains(p.getClass())) return null;
if(ReplayProcess.isVideoRecording() && ReplayHandler.isInPath()) {
if(p instanceof S29PacketSoundEffect) {
return null;
}
}
convertLegacyEntityIds(p); convertLegacyEntityIds(p);
if(p instanceof S48PacketResourcePackSend) { if(p instanceof S48PacketResourcePackSend) {
@@ -340,13 +344,13 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
String url = packet.func_179783_a(); String url = packet.func_179783_a();
if (url.startsWith("replay://")) { if (url.startsWith("replay://")) {
int id = Integer.parseInt(url.substring("replay://".length())); int id = Integer.parseInt(url.substring("replay://".length()));
Map<Integer, String> index = replayFile.resourcePackIndex().get(); Map<Integer, String> index = replayFile.getResourcePackIndex();
if (index != null) { if (index != null) {
String hash = index.get(id); String hash = index.get(id);
if (hash != null) { if (hash != null) {
File file = new File(tempResourcePackFolder, hash + ".zip"); File file = new File(tempResourcePackFolder, hash + ".zip");
if (!file.exists()) { 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); mc.getResourcePackRepository().func_177319_a(file);
} }
@@ -387,9 +391,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
mc.displayGuiScreen(null); 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()) { for (Object relative : ppl.func_179834_f()) {
if (relative == S08PacketPlayerPosLook.EnumFlags.X if (relative == S08PacketPlayerPosLook.EnumFlags.X
@@ -419,7 +423,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
return null; return null;
} }
CameraEntity cent = ReplayHandler.getCameraEntity(); CameraEntity cent = replayHandler.getCameraEntity();
cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e()); cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e());
return null; return null;
} }
@@ -461,7 +465,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
replayFile.close();
FileUtils.deleteDirectory(tempResourcePackFolder); FileUtils.deleteDirectory(tempResourcePackFolder);
super.channelInactive(ctx); super.channelInactive(ctx);
} }
@@ -522,7 +525,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
while (!terminate) { while (!terminate) {
synchronized (ReplaySender.this) { synchronized (ReplaySender.this) {
if (dis == null) { if (dis == null) {
dis = new DataInputStream(replayFile.recording().get()); dis = new DataInputStream(replayFile.getPacketData());
} }
// Packet loop // Packet loop
while (true) { while (true) {
@@ -580,7 +583,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
if (isHurrying() && lastTimeStamp > desiredTimeStamp && !startFromBeginning) { if (isHurrying() && lastTimeStamp > desiredTimeStamp && !startFromBeginning) {
desiredTimeStamp = -1; desiredTimeStamp = -1;
ReplayHandler.moveCameraToLastPosition(); replayHandler.moveCameraToTargetPosition();
// Pause after jumping // Pause after jumping
setReplaySpeed(0); setReplaySpeed(0);
@@ -605,7 +608,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
startFromBeginning = false; startFromBeginning = false;
nextPacket = null; nextPacket = null;
lastPacketSent = System.currentTimeMillis(); lastPacketSent = System.currentTimeMillis();
ReplayHandler.restartReplay(); replayHandler.restartedReplay();
if (dis != null) { if (dis != null) {
dis.close(); dis.close();
dis = null; dis = null;
@@ -659,8 +662,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
} }
protected Packet processPacketAsync(Packet p) { protected Packet processPacketAsync(Packet p) {
//If hurrying, ignore some packets, unless during Replay Path and *not* in short hurries //If hurrying, ignore some packets, except for short durations
if(!ReplayHandler.isInPath() && desiredTimeStamp - lastTimeStamp > 1000) { if(desiredTimeStamp - lastTimeStamp > 1000) {
if(p instanceof S2APacketParticles) return null; if(p instanceof S2APacketParticles) return null;
if(p instanceof S0EPacketSpawnObject) { if(p instanceof S0EPacketSpawnObject) {
@@ -700,11 +703,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
} }
startFromBeginning = false; startFromBeginning = false;
nextPacket = null; nextPacket = null;
ReplayHandler.restartReplay(); replayHandler.restartedReplay();
} }
if (dis == null) { if (dis == null) {
dis = new DataInputStream(replayFile.recording().get()); dis = new DataInputStream(replayFile.getPacketData());
} }
while (true) { // Send packets 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 de.johni0702.replaystudio.data.Marker;
import eu.crushedpixel.replaymod.gui.GuiEditKeyframe; import com.replaymod.core.ReplayMod;
import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline;
import eu.crushedpixel.replaymod.holders.Marker; import eu.crushedpixel.replaymod.holders.AdvancedPosition;
import eu.crushedpixel.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.MouseUtils;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.I18n; 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_X = 109;
private static final int KEYFRAME_MARKER_Y = 20; 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 long clickTime;
private boolean dragging; 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); super(positionX, positionY, width, height);
this.showMarkers = showMarkers; this.replayHandler = replayHandler;
this.showMarkers = false;
} }
@Override @Override
@@ -36,30 +39,33 @@ public class GuiMarkerTimeline extends GuiTimeline {
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
Keyframe<Marker> closest = null; Marker closest = null;
if(mouseY >= positionY + BORDER_TOP + 10) { 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 //left mouse button
if(button == 0) { if(button == 0) {
ReplayHandler.selectKeyframe(closest);
if(closest == null) { //if no keyframe clicked, jump in time if(closest == null) { //if no keyframe clicked, jump in time
ReplayMod.overlay.performJump(getTimeAt(mouseX, mouseY)); replayHandler.doJump((int) getTimeAt(mouseX, mouseY), true);
} else { } else {
selectedMarker = closest;
// If we clicked on a key frame, then continue monitoring the mouse for movements // If we clicked on a key frame, then continue monitoring the mouse for movements
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if(closest != null) { if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead // mc.displayGuiScreen(GuiEditKeyframe.create(closest));
mc.displayGuiScreen(GuiEditKeyframe.create(closest)); // TODO Edit Gui
this.clickedKeyFrame = null; this.clickedMarker = null;
} else { } else {
this.clickedKeyFrame = closest; this.clickedMarker = closest;
this.dragging = false; this.dragging = false;
}
} else { // If we didn't then just update the cursor
this.dragging = true;
} }
this.clickTime = currentTime; this.clickTime = currentTime;
} }
@@ -67,10 +73,13 @@ public class GuiMarkerTimeline extends GuiTimeline {
} else if(button == 1) { } else if(button == 1) {
if(closest != null) { if(closest != null) {
//Jump to clicked Marker Keyframe (explicitly force to jump to this position) //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 //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; if(!enabled) return;
long time = getTimeAt(mouseX, mouseY); long time = getTimeAt(mouseX, mouseY);
if (time != -1) { if (time != -1) {
if (clickedKeyFrame != null) { if (clickedMarker != null) {
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) { if (dragging || Math.abs(clickedMarker.getTime() - time) > tolerance) {
clickedKeyFrame.setRealTimestamp((int) time); clickedMarker.setTime((int) time);
dragging = true; dragging = true;
} }
} }
@@ -96,8 +105,11 @@ public class GuiMarkerTimeline extends GuiTimeline {
@Override @Override
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
mouseDrag(mc, mouseX, mouseY, button); mouseDrag(mc, mouseX, mouseY, button);
clickedKeyFrame = null; clickedMarker = null;
dragging = false; if (dragging) {
replayHandler.saveMarkers();
dragging = false;
}
} }
@Override @Override
@@ -114,17 +126,12 @@ public class GuiMarkerTimeline extends GuiTimeline {
drawTimelineCursor(leftTime, rightTime, bodyWidth); drawTimelineCursor(leftTime, rightTime, bodyWidth);
//Draw Keyframe logos //Draw Keyframe logos
for(Keyframe<Marker> kf : ReplayHandler.getMarkerKeyframes()) { for (Marker marker : replayHandler.getMarkers()) {
if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe())) drawMarker(marker, bodyWidth, leftTime, rightTime, segmentLength);
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) { private int getMarkerX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
long positionInSegment = timestamp - leftTime; long positionInSegment = timestamp - leftTime;
double fractionOfSegment = positionInSegment / segmentLength; double fractionOfSegment = positionInSegment / segmentLength;
return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
@@ -139,12 +146,12 @@ public class GuiMarkerTimeline extends GuiTimeline {
long leftTime = Math.round(timeStart * timelineLength); long leftTime = Math.round(timeStart * timelineLength);
double segmentLength = timelineLength * zoom; double segmentLength = timelineLength * zoom;
for(Keyframe<Marker> marker : ReplayHandler.getMarkerKeyframes()) { for (Marker marker : replayHandler.getMarkers()) {
int keyframeX = getKeyframeX(marker.getRealTimestamp(), leftTime, bodyWidth, segmentLength); 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(); 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"); if(markerName == null || markerName.isEmpty()) markerName = I18n.format("replaymod.gui.ingame.unnamedmarker");
ReplayMod.tooltipRenderer.drawTooltip(mouse.getX(), mouse.getY(), markerName, null, Color.WHITE); 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) { private void drawMarker(Marker marker, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) { if (marker.getTime() <= rightTime && marker.getTime() >= leftTime) {
int textureX = KEYFRAME_MARKER_X; int textureX = KEYFRAME_MARKER_X;
int textureY = KEYFRAME_MARKER_Y; int textureY = KEYFRAME_MARKER_Y;
int y = positionY+10; 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; 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 eu.crushedpixel.replaymod.utils.ReplayFileIO;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiErrorScreen; import net.minecraft.client.gui.GuiErrorScreen;
@@ -57,7 +56,7 @@ public class GuiRenameReplay extends GuiScreen {
} else if(button.id == 0) { } else if(button.id == 0) {
File folder = ReplayFileIO.getReplayFolder(); 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); File renamed = ReplayFileIO.getNextFreeFile(initRenamed);
try { try {
FileUtils.moveFile(file, renamed); 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 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.api.replay.holders.FileInfo;
import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry; import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry;
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry;
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
import eu.crushedpixel.replaymod.registry.ResourceHelper; import eu.crushedpixel.replaymod.registry.ResourceHelper;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.ImageUtils; import eu.crushedpixel.replaymod.utils.ImageUtils;
import eu.crushedpixel.replaymod.utils.ReplayFile;
import eu.crushedpixel.replaymod.utils.ReplayFileIO; import eu.crushedpixel.replaymod.utils.ReplayFileIO;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -34,6 +37,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { 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 DELETE_BUTTON_ID = 9005;
private static final int SETTINGS_BUTTON_ID = 9006; private static final int SETTINGS_BUTTON_ID = 9006;
private static final int CANCEL_BUTTON_ID = 9007; private static final int CANCEL_BUTTON_ID = 9007;
private final ReplayModReplay mod;
private boolean initialized; private boolean initialized;
private GuiReplayListExtended replayGuiList; private GuiReplayListExtended replayGuiList;
private List<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>(); 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; private Thread fileReloader;
public GuiReplayViewer(ReplayModReplay mod) {
this.mod = mod;
}
private class FileReloaderThread extends Thread { private class FileReloaderThread extends Thread {
private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry(); private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry();
@@ -74,26 +83,26 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
for(final File file : ReplayFileIO.getAllReplayFiles()) { for(final File file : ReplayFileIO.getAllReplayFiles()) {
if(interrupted()) break; if(interrupted()) break;
try { try {
ReplayFile replayFile = new ReplayFile(file); ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file);
final ReplayMetaData metaData = replayFile.metadata().get(); final ReplayMetaData metaData = replayFile.getMetaData();
BufferedImage img = replayFile.thumb().get(); Optional<BufferedImage> thumb = replayFile.getThumb();
replayFile.close(); replayFile.close();
File tmp = null; File tmp = null;
if(img != null) { if(thumb.isPresent()) {
img = ImageUtils.scaleImage(img, new Dimension(1280, 720)); BufferedImage img = ImageUtils.scaleImage(thumb.get(), new Dimension(1280, 720));
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg"); tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg");
tmp.deleteOnExit(); tmp.deleteOnExit();
ImageIO.write(img, "jpg", tmp); ImageIO.write(img, "jpg", tmp);
} }
final File thumb = tmp; final File thumbFile = tmp;
loadedReplaysQueue.offer(new Runnable() { loadedReplaysQueue.offer(new Runnable() {
@Override @Override
public void run() { public void run() {
addEntry(file, metaData, thumb); addEntry(file, metaData, thumbFile);
} }
}); });
} catch(Exception e) { } catch(Exception e) {
@@ -213,7 +222,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
this.mc.displayGuiScreen(guiyesno); this.mc.displayGuiScreen(guiyesno);
} }
} else if(button.id == SETTINGS_BUTTON_ID) { } 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) { } else if(button.id == RENAME_BUTTON_ID) {
File file = replayFileList.get(replayGuiList.selected).first().first(); File file = replayFileList.get(replayGuiList.selected).first().first();
this.mc.displayGuiScreen(new GuiRenameReplay(this, file)); this.mc.displayGuiScreen(new GuiRenameReplay(this, file));
@@ -306,7 +315,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
mc.displayGuiScreen(null); mc.displayGuiScreen(null);
try { try {
ReplayHandler.startReplay(replayFileList.get(id).first().first()); mod.startReplay(replayFileList.get(id).first().first());
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); 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 eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
import net.minecraft.client.Minecraft; 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); final GuiElement tooltip = forEach(GuiElement.class).getTooltip(renderInfo);
if (tooltip != null) { if (tooltip != null) {
final ReadableDimension tooltipSize = tooltip.getMinSize(); final ReadableDimension tooltipSize = tooltip.getMinSize();
int dx, dy; int x, y;
if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) { if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) {
dx = 8; x = renderInfo.mouseX + 8;
} else { } else {
dx = -8; x = screenSize.getWidth() - tooltipSize.getWidth() - 1;
} }
if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) { if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) {
dy = 8; y = renderInfo.mouseY + 8;
} else { } 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 { try {
OffsetGuiRenderer eRenderer = new OffsetGuiRenderer(renderer, position, tooltipSize); 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) { } catch (Exception ex) {
CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip"); CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip");
renderInfo.addTo(crashReport); 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 de.johni0702.minecraft.gui.container.GuiContainer;
import lombok.Getter; import lombok.Getter;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Dimension; import org.lwjgl.util.Dimension;
import org.lwjgl.util.Point; import org.lwjgl.util.Point;
import org.lwjgl.util.ReadableDimension; import org.lwjgl.util.ReadableDimension;
public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implements GuiElement<T> { public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implements GuiElement<T> {
protected static final ResourceLocation TEXTURE = new ResourceLocation("guiapi", "gui.png");
@Getter @Getter
private final Minecraft minecraft = Minecraft.getMinecraft(); 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 @Override
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
String orgLabel = getLabel(); String orgLabel = getLabel();
setLabel(orgLabel + values[selected]); setLabel(orgLabel + ": " + values[selected]);
super.draw(renderer, size, renderInfo); super.draw(renderer, size, renderInfo);
setLabel(orgLabel); 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; import java.util.Map;
public abstract class CustomLayout<T extends GuiContainer<T>> implements Layout { public abstract class CustomLayout<T extends GuiContainer<T>> implements Layout {
private final Layout parent;
private Map<GuiElement, Pair<Point, Dimension>> result = Maps.newHashMap(); private Map<GuiElement, Pair<Point, Dimension>> result = Maps.newHashMap();
public CustomLayout() {
this(null);
}
public CustomLayout(Layout parent) {
this.parent = parent;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> layOut(GuiContainer container, ReadableDimension size) { public Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> layOut(GuiContainer container, ReadableDimension size) {
result.clear(); result.clear();
Collection<GuiElement> elements = container.getChildren(); if (parent == null) {
for (GuiElement element : elements) { Collection<GuiElement> elements = container.getChildren();
result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize()))); 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()); 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 de.johni0702.minecraft.gui.element.GuiElement;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -40,11 +39,13 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@RequiredArgsConstructor
public class GridLayout implements Layout { public class GridLayout implements Layout {
private static final Data DEFAULT_DATA = new Data(); private static final Data DEFAULT_DATA = new Data();
private final int columns; @Accessors(chain = true)
@Getter
@Setter
private int columns;
@Accessors(chain = true) @Accessors(chain = true)
@Getter @Getter

View File

@@ -67,7 +67,9 @@ public class HorizontalLayout implements Layout {
GuiElement element = entry.getKey(); GuiElement element = entry.getKey();
Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA; Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA;
Dimension elementSize = new Dimension(element.getMinSize()); 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 remainingHeight = size.getHeight() - elementSize.getHeight();
int y = (int) (data.alignment * remainingHeight); int y = (int) (data.alignment * remainingHeight);
map.put(element, Pair.<ReadablePoint, ReadableDimension>of(new Point(x, y), elementSize)); 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(); GuiElement element = entry.getKey();
Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA; Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA;
Dimension elementSize = new Dimension(element.getMinSize()); 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())); elementSize.setWidth(Math.min(size.getWidth(), element.getMaxSize().getWidth()));
int remainingWidth = size.getWidth() - elementSize.getWidth(); int remainingWidth = size.getWidth() - elementSize.getWidth();
int x = (int) (data.alignment * remainingWidth); 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.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.mojang.authlib.exceptions.AuthenticationException; 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.ReplayModApiMethods;
import eu.crushedpixel.replaymod.api.replay.SearchQuery; import eu.crushedpixel.replaymod.api.replay.SearchQuery;
import eu.crushedpixel.replaymod.api.replay.holders.*; import eu.crushedpixel.replaymod.api.replay.holders.*;

View File

@@ -1,26 +1,26 @@
package eu.crushedpixel.replaymod.api; package eu.crushedpixel.replaymod.api;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringEscapeUtils;
import java.io.IOException; import java.io.IOException;
public class GsonApiClient { public class GsonApiClient {
private static final JsonParser parser = new JsonParser(); private static final JsonParser parser = new JsonParser();
public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException { public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException {
String apiResult = SimpleApiClient.invoke(query); String apiResult = SimpleApiClient.invoke(query);
return wrapWithJson(apiResult); return wrapWithJson(apiResult);
} }
public static JsonElement invokeJson(String url) throws IOException, ApiException { public static JsonElement invokeJson(String url) throws IOException, ApiException {
String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace("&#34;", "\\\"")); String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace("&#34;", "\\\""));
return wrapWithJson(apiResult); return wrapWithJson(apiResult);
} }
private static JsonElement wrapWithJson(String apiResult) { private static JsonElement wrapWithJson(String apiResult) {
return parser.parse(apiResult); return parser.parse(apiResult);
} }
} }

View File

@@ -1,123 +1,123 @@
package eu.crushedpixel.replaymod.api; package eu.crushedpixel.replaymod.api;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import eu.crushedpixel.replaymod.api.replay.holders.ApiError; import eu.crushedpixel.replaymod.api.replay.holders.ApiError;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
public class SimpleApiClient { public class SimpleApiClient {
private static final JsonParser jsonParser = new JsonParser(); private static final JsonParser jsonParser = new JsonParser();
private static final Gson gson = new Gson(); private static final Gson gson = new Gson();
/** /**
* Returns a Json String from the given QueryBuilder * Returns a Json String from the given QueryBuilder
* *
* @param query The QueryBuilder to use * @param query The QueryBuilder to use
* @return A Json String from the API * @return A Json String from the API
* @throws IOException * @throws IOException
* @throws ApiException * @throws ApiException
*/ */
public static String invoke(QueryBuilder query) throws IOException, ApiException { public static String invoke(QueryBuilder query) throws IOException, ApiException {
return invokeImpl(query.toString()); return invokeImpl(query.toString());
} }
/** /**
* Returns a Json String from the given URL * Returns a Json String from the given URL
* *
* @param url The URL to parse the Json from * @param url The URL to parse the Json from
* @return A Json String from the API * @return A Json String from the API
* @throws IOException * @throws IOException
* @throws ApiException * @throws ApiException
*/ */
public static String invokeUrl(String url) throws IOException, ApiException { public static String invokeUrl(String url) throws IOException, ApiException {
return invokeImpl(url); return invokeImpl(url);
} }
/** /**
* Returns a Json String from the API * Returns a Json String from the API
* *
* @param method The apiMethod to be called * @param method The apiMethod to be called
* @param paramMap The parameters to apply * @param paramMap The parameters to apply
* @return A Json String from the API * @return A Json String from the API
* @throws IOException * @throws IOException
* @throws ApiException * @throws ApiException
*/ */
public static String invoke(String method, Map<String, Object> paramMap) throws IOException, ApiException { public static String invoke(String method, Map<String, Object> paramMap) throws IOException, ApiException {
return invokeImpl(method, paramMap); return invokeImpl(method, paramMap);
} }
/** /**
* Returns a Json String from the API * Returns a Json String from the API
* *
* @param method The apiMethod to be called * @param method The apiMethod to be called
* @return A Json String from the API * @return A Json String from the API
* @throws IOException * @throws IOException
* @throws ApiException * @throws ApiException
*/ */
public static String invoke(String method) throws IOException, ApiException { public static String invoke(String method) throws IOException, ApiException {
return invokeImpl(method, null); return invokeImpl(method, null);
} }
private static String invokeImpl(String urlString) throws IOException, ApiException { private static String invokeImpl(String urlString) throws IOException, ApiException {
// read response // read response
String responseContent = null; String responseContent = null;
InputStream is = null; InputStream is = null;
HttpURLConnection httpUrlConnection = null; HttpURLConnection httpUrlConnection = null;
try { try {
URL url = new URL(urlString); URL url = new URL(urlString);
httpUrlConnection = (HttpURLConnection) url.openConnection(); httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setRequestMethod("GET"); httpUrlConnection.setRequestMethod("GET");
// give it 15 seconds to respond // give it 15 seconds to respond
httpUrlConnection.setReadTimeout(15 * 1000); httpUrlConnection.setReadTimeout(15 * 1000);
httpUrlConnection.connect(); httpUrlConnection.connect();
int responseCode = httpUrlConnection.getResponseCode(); int responseCode = httpUrlConnection.getResponseCode();
if(responseCode != 200) { if(responseCode != 200) {
is = httpUrlConnection.getErrorStream(); is = httpUrlConnection.getErrorStream();
if(is != null) { if(is != null) {
responseContent = IOUtils.toString(is, "UTF-8"); responseContent = IOUtils.toString(is, "UTF-8");
} else { } else {
responseContent = ""; responseContent = "";
} }
try { try {
JsonObject response = jsonParser.parse(responseContent).getAsJsonObject(); JsonObject response = jsonParser.parse(responseContent).getAsJsonObject();
throw new ApiException(gson.fromJson(response, ApiError.class)); throw new ApiException(gson.fromJson(response, ApiError.class));
} catch(JsonParseException e) { } catch(JsonParseException e) {
throw new ApiException(responseContent); throw new ApiException(responseContent);
} }
} }
is = httpUrlConnection.getInputStream(); is = httpUrlConnection.getInputStream();
responseContent = IOUtils.toString(is, "UTF-8"); responseContent = IOUtils.toString(is, "UTF-8");
} finally { } finally {
if(is != null) { if(is != null) {
is.close(); is.close();
} }
if(httpUrlConnection != null) { if(httpUrlConnection != null) {
httpUrlConnection.disconnect(); httpUrlConnection.disconnect();
} }
} }
return responseContent; return responseContent;
} }
private static String invokeImpl(String method, Map<String, Object> paramMap) throws IOException, ApiException { private static String invokeImpl(String method, Map<String, Object> paramMap) throws IOException, ApiException {
QueryBuilder queryBuilder = new QueryBuilder(method); QueryBuilder queryBuilder = new QueryBuilder(method);
queryBuilder.put(paramMap); queryBuilder.put(paramMap);
return invokeImpl(queryBuilder.toString()); return invokeImpl(queryBuilder.toString());
} }
} }

View File

@@ -1,7 +1,7 @@
package eu.crushedpixel.replaymod.api.replay; package eu.crushedpixel.replaymod.api.replay;
import com.google.gson.Gson; 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.ApiError;
import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.api.replay.holders.Category;
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;

View File

@@ -1,24 +1,24 @@
package eu.crushedpixel.replaymod.api.replay; package eu.crushedpixel.replaymod.api.replay;
public class ReplayModApiMethods { public class ReplayModApiMethods {
public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/"; public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/";
public static final String register = REPLAYMOD_BASE_URL+"register"; public static final String register = REPLAYMOD_BASE_URL+"register";
public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey"; public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey";
public static final String login = REPLAYMOD_BASE_URL+"login"; public static final String login = REPLAYMOD_BASE_URL+"login";
public static final String logout = REPLAYMOD_BASE_URL+"logout"; public static final String logout = REPLAYMOD_BASE_URL+"logout";
public static final String file_details = REPLAYMOD_BASE_URL+"file_details"; 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 upload_file = REPLAYMOD_BASE_URL+"upload_file";
public static final String download_file = REPLAYMOD_BASE_URL+"download_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 get_thumbnail = REPLAYMOD_BASE_URL+"get_thumbnail";
public static final String remove_file = REPLAYMOD_BASE_URL+"remove_file"; 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 rate_file = REPLAYMOD_BASE_URL+"rate_file";
public static final String get_ratings = REPLAYMOD_BASE_URL+"get_ratings"; 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 fav_file = REPLAYMOD_BASE_URL+"fav_file";
public static final String get_favorites = REPLAYMOD_BASE_URL+"get_favorites"; 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 check_auth = REPLAYMOD_BASE_URL+"check_auth";
public static final String get_language = REPLAYMOD_BASE_URL+"get_language"; public static final String get_language = REPLAYMOD_BASE_URL+"get_language";
public static final String search = REPLAYMOD_BASE_URL+"search"; public static final String search = REPLAYMOD_BASE_URL+"search";
public static final String up_to_date = REPLAYMOD_BASE_URL+"up_to_date"; 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; package eu.crushedpixel.replaymod.api.replay.holders;
import eu.crushedpixel.replaymod.recording.ReplayMetaData; import de.johni0702.replaystudio.replay.ReplayMetaData;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.api.replay.pagination; 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 eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
import java.io.File; import java.io.File;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.api.replay.pagination; 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 eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.api.replay.pagination; 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.SearchQuery;
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;

View File

@@ -1,18 +1,12 @@
package eu.crushedpixel.replaymod.assets; 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 lombok.EqualsAndHashCode;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import java.util.zip.ZipEntry;
@EqualsAndHashCode @EqualsAndHashCode
public class AssetRepository { public class AssetRepository {
@@ -62,40 +56,29 @@ public class AssetRepository {
} }
public void saveAssets() { public void saveAssets() {
try { // TODO
ReplayFile replayFile = new ReplayFile(ReplayHandler.getReplayFile()); // try {
// ReplayFile replayFile = ReplayHandler.getReplayFile();
Enumeration<? extends ZipEntry> entries = replayFile.entries(); //
while(entries.hasMoreElements()) { // for (ReplayAssetEntry entry : replayFile.getAssets()) {
ZipEntry entry = entries.nextElement(); // if (!replayAssets.containsKey(entry.getUuid())) {
if(entry.getName().startsWith(ReplayFile.ENTRY_ASSET_FOLDER)) { // replayFile.removeAsset(entry.getUuid());
ReplayMod.replayFileAppender.registerModifiedFile(null, entry.getName(), ReplayHandler.getReplayFile()); // }
} // }
} //
// for(Map.Entry<UUID, ReplayAsset> e : replayAssets.entrySet()) {
replayFile.close(); // UUID uuid = e.getKey();
// ReplayAsset asset = e.getValue();
ReplayMod.replayFileAppender.deleteAllFilesByFolder(ReplayFile.ENTRY_ASSET_FOLDER, ReplayHandler.getReplayFile()); // String extension = asset.getSavedFileExtension();
// String name = asset.getAssetName();
for(Map.Entry<UUID, ReplayAsset> e : replayAssets.entrySet()) { //
UUID uuid = e.getKey(); // try (OutputStream out = replayFile.writeAsset(new ReplayAssetEntry(uuid, extension, name))) {
ReplayAsset asset = e.getValue(); // asset.writeToStream(out);
try { // }
String filepath = ReplayFile.ENTRY_ASSET_FOLDER + uuid.toString()+ "_" + asset.getDisplayString() + "." + asset.getSavedFileExtension(); // }
// } catch(IOException e) {
File toAdd = File.createTempFile("ASSET_"+asset.getDisplayString(), asset.getSavedFileExtension()); // e.printStackTrace();
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();
}
} }
public static ReplayAsset assetFromFileName(String filename) { 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.GuiEntryListEntry;
import eu.crushedpixel.replaymod.holders.Transformations; import eu.crushedpixel.replaymod.holders.Transformations;
import eu.crushedpixel.replaymod.registry.ResourceHelper; import eu.crushedpixel.replaymod.registry.ResourceHelper;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; 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 //if no asset repository available, simply accept the UUID and it will load the image later
//when calling getResourceLocation for the first time //when calling getResourceLocation for the first time
if(ReplayHandler.getAssetRepository() == null) { // TODO
this.linkedAsset = assetUUID; // if(ReplayHandler.getAssetRepository() == null) {
return; // this.linkedAsset = assetUUID;
} // return;
// }
ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID); //
// ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID);
if(asset instanceof ReplayImageAsset) { //
this.linkedAsset = assetUUID; // if(asset instanceof ReplayImageAsset) {
setImage(((ReplayImageAsset)asset).getObject()); // this.linkedAsset = assetUUID;
} else if(asset != null) { // setImage(((ReplayImageAsset)asset).getObject());
throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset"); // } else if(asset != null) {
} // throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset");
// }
} }
public void setImage(final BufferedImage bufferedImage) throws IOException { public void setImage(final BufferedImage bufferedImage) throws IOException {
@@ -103,14 +103,15 @@ public class CustomImageObject implements GuiEntryListEntry {
public ResourceLocation getResourceLocation() { public ResourceLocation getResourceLocation() {
if(resourceLocation == null) { if(resourceLocation == null) {
ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset); // TODO
if(asset instanceof ReplayImageAsset) { // ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset);
try { // if(asset instanceof ReplayImageAsset) {
setImage(((ReplayImageAsset) asset).getObject()); // try {
} catch(Exception e) { // setImage(((ReplayImageAsset) asset).getObject());
e.printStackTrace(); // } catch(Exception e) {
} // e.printStackTrace();
} // }
// }
return null; return null;
} }

View File

@@ -1,7 +1,6 @@
package eu.crushedpixel.replaymod.assets; package eu.crushedpixel.replaymod.assets;
import eu.crushedpixel.replaymod.registry.ResourceHelper; import eu.crushedpixel.replaymod.registry.ResourceHelper;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.BoundingUtils; import eu.crushedpixel.replaymod.utils.BoundingUtils;
import eu.crushedpixel.replaymod.utils.BufferedImageUtils; import eu.crushedpixel.replaymod.utils.BufferedImageUtils;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@@ -67,11 +66,12 @@ public class ReplayImageAsset implements ReplayAsset<BufferedImage> {
this.bufferedImageHashCode = BufferedImageUtils.hashCode(object); this.bufferedImageHashCode = BufferedImageUtils.hashCode(object);
ResourceHelper.freeResource(previewResource); ResourceHelper.freeResource(previewResource);
for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) { // TODO
if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) { // for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) {
object.setImage(this.object); // if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) {
} // object.setImage(this.object);
} // }
// }
} }
@Override @Override

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.chat; package eu.crushedpixel.replaymod.chat;
import eu.crushedpixel.replaymod.ReplayMod; import com.replaymod.core.ReplayMod;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;

View File

@@ -17,6 +17,7 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
public LoadingPlugin() { public LoadingPlugin() {
MixinBootstrap.init(); MixinBootstrap.init();
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replaymod.json"); MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replaymod.json");
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.recording.replaymod.json");
CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); CodeSource codeSource = getClass().getProtectionDomain().getCodeSource();
if (codeSource != null) { 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; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -13,18 +11,20 @@ public class CrosshairRenderHandler {
@SubscribeEvent @SubscribeEvent
public void preCrosshairRender(RenderGameOverlayEvent.Pre event) { public void preCrosshairRender(RenderGameOverlayEvent.Pre event) {
//Crosshair should only render if hovered Entity can actually be spectated //Crosshair should only render if hovered Entity can actually be spectated
if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) { // TODO
boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity); // if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
event.setCanceled(cancel); // boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity);
} // event.setCanceled(cancel);
// }
} }
@SubscribeEvent @SubscribeEvent
public void preChatRender(RenderGameOverlayEvent.Pre event) { public void preChatRender(RenderGameOverlayEvent.Pre event) {
if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CHAT) { // TODO
//when a crosshair was displayed, the background of the lowest line of chat would be opaque // if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CHAT) {
GlStateManager.enableTexture2D(); // //when a crosshair was displayed, the background of the lowest line of chat would be opaque
GlStateManager.disableBlend(); // GlStateManager.enableTexture2D();
} // GlStateManager.disableBlend();
// }
} }
} }

View File

@@ -1,14 +1,11 @@
package eu.crushedpixel.replaymod.events.handlers; 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.GuiConstants;
import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
import eu.crushedpixel.replaymod.gui.online.GuiLoginPrompt; import eu.crushedpixel.replaymod.gui.online.GuiLoginPrompt;
import eu.crushedpixel.replaymod.gui.online.GuiReplayCenter; import eu.crushedpixel.replaymod.gui.online.GuiReplayCenter;
import eu.crushedpixel.replaymod.gui.replayeditor.GuiReplayEditor; 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.settings.ReplaySettings;
import eu.crushedpixel.replaymod.studio.VersionValidator; import eu.crushedpixel.replaymod.studio.VersionValidator;
import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.MouseUtils;
@@ -26,7 +23,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.util.Point; import org.lwjgl.util.Point;
import java.awt.*; import java.awt.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class GuiEventHandler { public class GuiEventHandler {
@@ -54,19 +50,20 @@ public class GuiEventHandler {
e.printStackTrace(); e.printStackTrace();
} }
} }
if(ReplayHandler.isInReplay()) ReplayHandler.setInReplay(false);
} }
if(!ReplayMod.apiClient.isLoggedIn()) return; if(!ReplayMod.apiClient.isLoggedIn()) return;
if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) { if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) {
if(ReplayHandler.isInReplay()) { // TODO
event.setCanceled(true); // if(ReplayHandler.isInReplay()) {
} // event.setCanceled(true);
// }
} else if(event.gui instanceof GuiDisconnected) { } else if(event.gui instanceof GuiDisconnected) {
if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) { // TODO
event.setCanceled(true); // if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) {
} // event.setCanceled(true);
// }
} }
} }
@@ -121,20 +118,7 @@ public class GuiEventHandler {
public void onInit(InitGuiEvent event) { public void onInit(InitGuiEvent event) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<GuiButton> buttonList = event.buttonList; List<GuiButton> buttonList = event.buttonList;
if(event.gui instanceof GuiIngameMenu && ReplayHandler.isInReplay()) { if(event.gui instanceof GuiMainMenu) {
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) {
int i1 = event.gui.height / 4 + 24 + 10; int i1 = event.gui.height / 4 + 24 + 10;
for(GuiButton b : buttonList) { for(GuiButton b : buttonList) {
@@ -171,9 +155,7 @@ public class GuiEventHandler {
public void onButton(ActionPerformedEvent event) { public void onButton(ActionPerformedEvent event) {
if(!event.button.enabled) return; if(!event.button.enabled) return;
if(event.gui instanceof GuiMainMenu) { if(event.gui instanceof GuiMainMenu) {
if(event.button.id == GuiConstants.REPLAY_MANAGER_BUTTON_ID) { if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) {
mc.displayGuiScreen(new GuiReplayViewer());
} else if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) {
if(ReplayMod.apiClient.isLoggedIn()) { if(ReplayMod.apiClient.isLoggedIn()) {
mc.displayGuiScreen(new GuiReplayCenter()); mc.displayGuiScreen(new GuiReplayCenter());
} else { } else {
@@ -183,17 +165,7 @@ public class GuiEventHandler {
mc.displayGuiScreen(new GuiReplayEditor()); mc.displayGuiScreen(new GuiReplayEditor());
} }
} else if(event.gui instanceof GuiOptions && event.button.id == GuiConstants.REPLAY_OPTIONS_BUTTON_ID) { } else if(event.gui instanceof GuiOptions && event.button.id == GuiConstants.REPLAY_OPTIONS_BUTTON_ID) {
mc.displayGuiScreen(new GuiReplaySettings(event.gui)); new GuiReplaySettings(event.gui, ReplayMod.instance.getSettingsRegistry()).display();
}
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();
} }
} }

View File

@@ -1,20 +1,19 @@
package eu.crushedpixel.replaymod.events.handlers; package eu.crushedpixel.replaymod.events.handlers;
import eu.crushedpixel.replaymod.ReplayMod;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraftforge.client.event.MouseEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
public class MinecraftTicker { public class MinecraftTicker {
public static void runMouseKeyboardTick(Minecraft mc) { public static void runMouseKeyboardTick(Minecraft mc) {
ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent()); // TODO
// ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent());
if(mc.thePlayer == null) return; if(mc.thePlayer == null) return;
try { try {
mc.mcProfiler.endStartSection("mouse"); mc.mcProfiler.endStartSection("mouse");

View File

@@ -1,51 +1,45 @@
package eu.crushedpixel.replaymod.events.handlers; 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 { public class MouseInputHandler {
private final Minecraft mc = Minecraft.getMinecraft(); // TODO
private boolean rightDown = false; // private final Minecraft mc = Minecraft.getMinecraft();
private boolean leftDown = false; // private boolean rightDown = false;
// private boolean leftDown = false;
@SubscribeEvent //
public void mouseEvent(MouseEvent event) { // @SubscribeEvent
if(!ReplayHandler.isInReplay()) { // public void mouseEvent(MouseEvent event) {
return; // if(!ReplayHandler.isInReplay()) {
} // return;
// }
if(event.dwheel != 0 && mc.currentScreen == null) { //
boolean increase = event.dwheel > 0; // if(event.dwheel != 0 && mc.currentScreen == null) {
CameraEntity.modifyCameraSpeed(increase); // boolean increase = event.dwheel > 0;
} // CameraEntity.modifyCameraSpeed(increase);
// }
if(Mouse.isButtonDown(0)) { //
if(!leftDown) { // if(Mouse.isButtonDown(0)) {
leftDown = true; // if(!leftDown) {
if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) { // leftDown = true;
if(SpectatingHandler.canSpectate(mc.pointedEntity)) // if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) {
ReplayHandler.spectateEntity(mc.pointedEntity); // if(SpectatingHandler.canSpectate(mc.pointedEntity))
} // ReplayHandler.spectateEntity(mc.pointedEntity);
} // }
} else { // }
leftDown = false; // } else {
} // leftDown = false;
// }
if(Mouse.isButtonDown(1)) { //
if(!rightDown) { // if(Mouse.isButtonDown(1)) {
rightDown = true; // if(!rightDown) {
if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) { // rightDown = true;
if(SpectatingHandler.canSpectate(mc.pointedEntity)) // if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) {
ReplayHandler.spectateEntity(mc.pointedEntity); // if(SpectatingHandler.canSpectate(mc.pointedEntity))
} // ReplayHandler.spectateEntity(mc.pointedEntity);
} // }
} else { // }
rightDown = false; // } else {
} // rightDown = false;
} // }
// }
} }

View File

@@ -1,18 +1,10 @@
package eu.crushedpixel.replaymod.events.handlers; 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.minecraft.client.Minecraft;
import net.minecraftforge.client.event.MouseEvent; import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
public class TickAndRenderListener { public class TickAndRenderListener {
@@ -30,75 +22,78 @@ public class TickAndRenderListener {
@SubscribeEvent @SubscribeEvent
public void onRenderWorld(RenderWorldLastEvent event) throws Exception { public void onRenderWorld(RenderWorldLastEvent event) throws Exception {
if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel // TODO
if (ReplayProcess.isVideoRecording()) return; // If recording, cancel // if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel
// if (ReplayProcess.isVideoRecording()) return; // If recording, cancel
if(requestScreenshot == 1) { //
mc.addScheduledTask(new Runnable() { // if(requestScreenshot == 1) {
@Override // mc.addScheduledTask(new Runnable() {
public void run() { // @Override
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION); // public void run() {
ReplayScreenshot.prepareScreenshot(); // ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION);
requestScreenshot = 2; // ReplayScreenshot.prepareScreenshot();
} // requestScreenshot = 2;
}); // }
} else if(requestScreenshot == 2) { // });
mc.addScheduledTask(new Runnable() { // } else if(requestScreenshot == 2) {
@Override // mc.addScheduledTask(new Runnable() {
public void run() { // @Override
ReplayScreenshot.saveScreenshot(); // public void run() {
} // ReplayScreenshot.saveScreenshot();
}); // }
} // });
// }
if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false); //
if(ReplayHandler.isCamera()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity()); // if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false);
// if(ReplayHandler.isCameraView()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity());
if(mc.isGamePaused() && ReplayHandler.isInPath()) { //
mc.isGamePaused = false; // if(mc.isGamePaused() && ReplayHandler.isInPath()) {
} // mc.isGamePaused = false;
// }
} }
@SubscribeEvent @SubscribeEvent
public void onRenderTick(TickEvent.RenderTickEvent event) { public void onRenderTick(TickEvent.RenderTickEvent event) {
if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return; // TODO
// if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return;
if(ReplayHandler.getCameraEntity() != null) //
ReplayHandler.getCameraEntity().updateMovement(); // if(ReplayHandler.getCameraEntity() != null)
if(ReplayHandler.isInPath()) { // ReplayHandler.getCameraEntity().updateMovement();
ReplayProcess.tickReplay(true); // if(ReplayHandler.isInPath()) {
} else onMouseMove(new MouseEvent()); // ReplayProcess.tickReplay(true);
// } else onMouseMove(new MouseEvent());
FMLCommonHandler.instance().fireKeyInput(); //
// FMLCommonHandler.instance().fireKeyInput();
} }
@SubscribeEvent @SubscribeEvent
public void onMouseMove(MouseEvent event) { public void onMouseMove(MouseEvent event) {
if(!ReplayHandler.isInReplay()) return; // TODO
// if(!ReplayHandler.isInReplay()) return;
mc.mcProfiler.startSection("mouse"); //
// mc.mcProfiler.startSection("mouse");
if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) { //
Mouse.setGrabbed(false); // if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) {
Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2); // Mouse.setGrabbed(false);
Mouse.setGrabbed(true); // Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2);
} // Mouse.setGrabbed(true);
// }
if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) { //
mc.mouseHelper.mouseXYChange(); // if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) {
float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F; // mc.mouseHelper.mouseXYChange();
float f2 = f1 * f1 * f1 * 8.0F; // float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F;
float f3 = (float) mc.mouseHelper.deltaX * f2; // float f2 = f1 * f1 * f1 * 8.0F;
float f4 = (float) mc.mouseHelper.deltaY * f2; // float f3 = (float) mc.mouseHelper.deltaX * f2;
byte b0 = 1; // float f4 = (float) mc.mouseHelper.deltaY * f2;
// byte b0 = 1;
if(mc.gameSettings.invertMouse) { //
b0 = -1; // if(mc.gameSettings.invertMouse) {
} // b0 = -1;
// }
if(ReplayHandler.getCameraEntity() != null) { //
ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0); // if(ReplayHandler.getCameraEntity() != null) {
} // ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0);
} // }
// }
} }
} }

View File

@@ -1,22 +1,8 @@
package eu.crushedpixel.replaymod.events.handlers.keyboard; 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.Minecraft;
import net.minecraft.client.settings.KeyBinding; 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.Sys;
import org.lwjgl.input.Keyboard;
public class KeyInputHandler { public class KeyInputHandler {
@@ -25,200 +11,200 @@ public class KeyInputHandler {
private long prevKeysDown = Sys.getTime(); private long prevKeysDown = Sys.getTime();
public void onKeyInput() throws Exception { public void onKeyInput() throws Exception {
if(!ReplayHandler.isInReplay()) return; // TODO
// if(!ReplayHandler.isInReplay()) return;
KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; //
// KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
boolean speedup = false; //
// boolean speedup = false;
if(mc.currentScreen == null) { //
boolean forward = false, backward = false, left = false, right = false, up = false, down = 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(!ReplayHandler.isInPath()) {
if(!kb.isKeyDown()) continue; // for(KeyBinding kb : keyBindings) {
if(ReplayHandler.isCamera()) { // if(!kb.isKeyDown()) continue;
if(kb.getKeyDescription().equals("key.forward")) { // if(ReplayHandler.isCameraView()) {
forward = true; // if(kb.getKeyDescription().equals("key.forward")) {
speedup = true; // forward = true;
} // speedup = true;
// }
if(kb.getKeyDescription().equals("key.back")) { //
backward = true; // if(kb.getKeyDescription().equals("key.back")) {
speedup = true; // backward = true;
} // speedup = true;
// }
if(kb.getKeyDescription().equals("key.jump")) { //
up = true; // if(kb.getKeyDescription().equals("key.jump")) {
speedup = true; // up = true;
} // speedup = true;
// }
if(kb.getKeyDescription().equals("key.left")) { //
left = true; // if(kb.getKeyDescription().equals("key.left")) {
speedup = true; // left = true;
} // speedup = true;
// }
if(kb.getKeyDescription().equals("key.right")) { //
right = true; // if(kb.getKeyDescription().equals("key.right")) {
speedup = true; // right = true;
} // speedup = true;
} // }
// }
if(kb.getKeyDescription().equals("key.sneak")) { //
if(ReplayHandler.isCamera()) { // if(kb.getKeyDescription().equals("key.sneak")) {
down = true; // if(ReplayHandler.isCameraView()) {
speedup = true; // down = true;
} // speedup = true;
ReplayHandler.spectateCamera(); // }
} // ReplayHandler.spectateCamera();
} // }
// }
forwardCameraMovement(forward, backward, left, right, up, down); //
} // forwardCameraMovement(forward, backward, left, right, up, down);
} // }
// }
if(ReplayHandler.getCameraEntity() != null) { //
if(speedup) { // if(ReplayHandler.getCameraEntity() != null) {
ReplayHandler.getCameraEntity().speedUp(); // if(speedup) {
prevKeysDown = Sys.getTime(); // ReplayHandler.getCameraEntity().speedUp();
} else { // prevKeysDown = Sys.getTime();
if(Sys.getTime() - prevKeysDown > 100) { // } else {
ReplayHandler.getCameraEntity().stopSpeedUp(); // 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);
}
} }
//
// @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) { public void handleCustomKeybindings(KeyBinding kb, boolean found, int keyCode) {
//Custom registered handlers //Custom registered handlers
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) { // TODO: Transfer to new key binding registry
if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) { // if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
ReplayHandler.toggleMarker(); // if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) {
} else if(ConnectionEventHandler.isRecording()) { // ReplayHandler.toggleMarker();
ConnectionEventHandler.addMarker(); // }
} // }
} //
// if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return;
if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return; //
// if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command"))
if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command")) // && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
&& (kb.isPressed() || kb.getKeyCode() == keyCode)) { // mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay));
mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay)); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayMod.overlay.togglePlayPause();
ReplayMod.overlay.togglePlayPause(); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_CLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
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);
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()) {
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);
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()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_RESET_TILT) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayHandler.setCameraTilt(0);
ReplayHandler.setCameraTilt(0); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { // TickAndRenderListener.requestScreenshot();
TickAndRenderListener.requestScreenshot(); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) { // PlayerHandler.openPlayerOverview();
PlayerHandler.openPlayerOverview(); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled());
ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled()); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback());
ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback()); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SYNC_TIMELINE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
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));
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()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_KEYFRAME_PRESETS) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository()));
mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository())); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview());
ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview()); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // mc.displayGuiScreen(new GuiAssetManager());
mc.displayGuiScreen(new GuiAssetManager()); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // mc.displayGuiScreen(new GuiObjectManager());
mc.displayGuiScreen(new GuiObjectManager()); // }
} //
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) { // ReplayMod.replaySettings.toggleInterpolation();
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.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.FileChooseListener; import eu.crushedpixel.replaymod.gui.elements.listeners.FileChooseListener;
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; 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 eu.crushedpixel.replaymod.utils.MouseUtils;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
@@ -22,7 +20,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOverlay { public class GuiAssetManager extends GuiScreen {
private String screenTitle; private String screenTitle;
@@ -43,8 +41,10 @@ public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOve
private ReplayAsset currentAsset; private ReplayAsset currentAsset;
public GuiAssetManager() { public GuiAssetManager() {
this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository()); // TODO
this.assetRepository = ReplayHandler.getAssetRepository(); initialRepository = null;
// this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository());
// this.assetRepository = ReplayHandler.getAssetRepository();
} }
@Override @Override

View File

@@ -1,35 +1,30 @@
package eu.crushedpixel.replaymod.gui; 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.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.NumberValueChangeListener; import eu.crushedpixel.replaymod.holders.Keyframe;
import eu.crushedpixel.replaymod.holders.*;
import eu.crushedpixel.replaymod.interpolation.KeyframeList; import eu.crushedpixel.replaymod.interpolation.KeyframeList;
import eu.crushedpixel.replaymod.interpolation.KeyframeValue; import eu.crushedpixel.replaymod.interpolation.KeyframeValue;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.MouseUtils;
import eu.crushedpixel.replaymod.utils.RoundUtils;
import eu.crushedpixel.replaymod.utils.TimestampUtils; import eu.crushedpixel.replaymod.utils.TimestampUtils;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.util.Point; import org.lwjgl.util.Point;
import java.awt.*; import java.awt.*;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.List; import java.util.List;
public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen { public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static GuiEditKeyframe create(Keyframe kf) { public static GuiEditKeyframe create(Keyframe kf) {
if(kf.getValue() instanceof Marker) return new GuiEditKeyframeMarker(kf); // TODO
if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf); // if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf);
if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf); // if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf);
if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf); // if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf);
throw new UnsupportedOperationException("Keyframe type unknown: " + kf); throw new UnsupportedOperationException("Keyframe type unknown: " + kf);
} }
@@ -156,13 +151,14 @@ public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen
@Override @Override
public void onGuiClosed() { public void onGuiClosed() {
if(!save) { // TODO
ReplayHandler.removeKeyframe(keyframe); // if(!save) {
ReplayHandler.addKeyframe(keyframeBackup); // ReplayHandler.removeKeyframe(keyframe);
ReplayHandler.selectKeyframe(keyframeBackup); // ReplayHandler.addKeyframe(keyframeBackup);
} // ReplayHandler.selectKeyframe(keyframeBackup);
ReplayHandler.fireKeyframesModifyEvent(); // }
Keyboard.enableRepeatEvents(false); // ReplayHandler.fireKeyframesModifyEvent();
// Keyboard.enableRepeatEvents(false);
} }
@Override @Override
@@ -218,300 +214,301 @@ public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen
protected void drawScreen0() {} protected void drawScreen0() {}
private static class GuiEditKeyframeMarker extends GuiEditKeyframe<Marker> { // TODO
private GuiAdvancedTextField markerNameInput; // private static class GuiEditKeyframeMarker extends GuiEditKeyframe<Marker> {
// private GuiAdvancedTextField markerNameInput;
public GuiEditKeyframeMarker(Keyframe<Marker> keyframe) { //
super(keyframe, ReplayHandler.getMarkerKeyframes()); // public GuiEditKeyframeMarker(Keyframe<Marker> keyframe) {
} // super(keyframe, ReplayHandler.getMarkerKeyframes());
// }
@Override //
public void initGui() { // @Override
super.initGui(); // public void initGui() {
// super.initGui();
if (!initialized) { //
String name = keyframe.getValue().getName(); // if (!initialized) {
if (name == null) name = ""; // String name = keyframe.getValue().getName();
markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20); // if (name == null) name = "";
markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername"); // markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20);
markerNameInput.setText(name); // markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername");
// markerNameInput.setText(name);
inputs.addPart(markerNameInput); //
// inputs.addPart(markerNameInput);
new KeyframeValueChangeListener(this); //
} // new KeyframeValueChangeListener(this);
// }
markerNameInput.xPosition = width/2 - 100; //
markerNameInput.yPosition = height/2-10; // markerNameInput.xPosition = width/2 - 100;
// markerNameInput.yPosition = height/2-10;
initialized = true; //
} // initialized = true;
// }
@Override //
public void onGuiClosed() { // @Override
keyframe.getValue().setName(markerNameInput.getText().trim()); // public void onGuiClosed() {
super.onGuiClosed(); // keyframe.getValue().setName(markerNameInput.getText().trim());
} // super.onGuiClosed();
} // }
// }
private static class GuiEditKeyframeTime extends GuiEditKeyframe<TimestampValue> { //
private GuiNumberInput kfMin, kfSec, kfMs; // private static class GuiEditKeyframeTime extends GuiEditKeyframe<TimestampValue> {
// private GuiNumberInput kfMin, kfSec, kfMs;
public GuiEditKeyframeTime(Keyframe<TimestampValue> keyframe) { //
super(keyframe, ReplayHandler.getTimeKeyframes()); // public GuiEditKeyframeTime(Keyframe<TimestampValue> keyframe) {
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time"); // super(keyframe, ReplayHandler.getTimeKeyframes());
} // screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time");
// }
@Override //
public void initGui() { // @Override
super.initGui(); // public void initGui() {
// super.initGui();
if (!initialized) { //
int time = keyframe.getValue().asInt(); // 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); // kfMin = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, null, (double)TimestampUtils.timestampToWholeMinutes(time), false, "", 1);
kfMs = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(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(kfMin);
inputs.addPart(kfMs); // inputs.addPart(kfSec);
// inputs.addPart(kfMs);
KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { //
@Override // KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
public void onValueChange(double value) { // @Override
keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp( // public void onValueChange(double value) {
kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue()))); // keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp(
// kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue())));
super.onValueChange(value); //
} // super.onValueChange(value);
}; // }
// };
kfMin.addValueChangeListener(listener); //
kfSec.addValueChangeListener(listener); // kfMin.addValueChangeListener(listener);
kfMs.addValueChangeListener(listener); // kfSec.addValueChangeListener(listener);
} // kfMs.addValueChangeListener(listener);
// }
kfMin.xPosition = min.xPosition; //
kfSec.xPosition = sec.xPosition; // kfMin.xPosition = min.xPosition;
kfMs.xPosition = ms.xPosition; // kfSec.xPosition = sec.xPosition;
// kfMs.xPosition = ms.xPosition;
kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20; //
// kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20;
initialized = true; //
} // initialized = true;
// }
@Override //
protected void drawScreen0() { // @Override
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, kfMin.yPosition + 7, Color.WHITE.getRGB()); // protected void drawScreen0() {
drawString(fontRendererObj, I18n.format("replaymod.gui.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB()); // drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, 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.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB());
drawString(fontRendererObj, I18n.format("replaymod.gui.milliseconds"), kfMs.xPosition + kfMs.width + 5, kfMs.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 static class GuiEditKeyframePosition extends GuiEditKeyframe<AdvancedPosition> {
private ComposedElement posInputs; // private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll;
// private ComposedElement posInputs;
public GuiEditKeyframePosition(Keyframe<AdvancedPosition> keyframe) { //
super(keyframe, ReplayHandler.getPositionKeyframes()); // public GuiEditKeyframePosition(Keyframe<AdvancedPosition> keyframe) {
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos"); // super(keyframe, ReplayHandler.getPositionKeyframes());
} // screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos");
// }
@Override //
public void initGui() { // @Override
super.initGui(); // public void initGui() {
// super.initGui();
if (!initialized) { //
AdvancedPosition pos = keyframe.getValue(); // if (!initialized) {
xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true); // AdvancedPosition pos = keyframe.getValue();
yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true); // xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true);
zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true); // yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true);
yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true); // zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true);
pitch = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, -90d, 90d, RoundUtils.round2Decimals(pos.getPitch()), true); // yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true);
roll = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getRoll()), 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); // posInputs = new ComposedElement(xCoord, yCoord, zCoord, yaw, pitch, roll);
// inputs.addPart(posInputs);
KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) { //
@Override // KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
public void onValueChange(double value) { // @Override
keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(), // public void onValueChange(double value) {
zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(), // keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(),
(float) roll.getPreciseValue())); // zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(),
// (float) roll.getPreciseValue()));
super.onValueChange(value); //
} // super.onValueChange(value);
}; // }
// };
xCoord.addValueChangeListener(listener); //
yCoord.addValueChangeListener(listener); // xCoord.addValueChangeListener(listener);
zCoord.addValueChangeListener(listener); // yCoord.addValueChangeListener(listener);
pitch.addValueChangeListener(listener); // zCoord.addValueChangeListener(listener);
yaw.addValueChangeListener(listener); // pitch.addValueChangeListener(listener);
roll.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")), // int w = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.xpos")),
fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos")))); // Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.ypos")),
w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")), // fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos"))));
Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.campitch")), // w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")),
fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camroll")))); // 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; // totalWidth = w +100+w2+100+5+5+10;
// left = (this.width - totalWidth)/2;
int x = w + left + 5; //
int i = 0; // int x = w + left + 5;
for(GuiElement input : posInputs.getParts()) { // int i = 0;
if(input instanceof GuiTextField) { // for(GuiElement input : posInputs.getParts()) {
GuiTextField textField = (GuiTextField)input; // if(input instanceof GuiTextField) {
textField.xPosition = i < 3 ? x : left+totalWidth-100; // GuiTextField textField = (GuiTextField)input;
textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30; // textField.xPosition = i < 3 ? x : left+totalWidth-100;
i++; // textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30;
} // i++;
} // }
// }
initialized = true; //
} // initialized = true;
// }
@Override //
protected void drawScreen0() { // @Override
if (keyframe.getValue() instanceof SpectatorData) return; // protected void drawScreen0() {
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB()); // if (keyframe.getValue() instanceof SpectatorData) return;
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, Color.WHITE.getRGB()); // drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB());
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.zpos"), left, virtualY + 87, Color.WHITE.getRGB()); // drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, 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.zpos"), left, virtualY + 87, 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.camyaw"), left + totalWidth - 100 - 5 - w2, virtualY + 27, Color.WHITE.getRGB());
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camroll"), left + totalWidth - 100 - 5 - w2, virtualY + 87, 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 static class GuiEditKeyframeSpectator extends GuiEditKeyframe<AdvancedPosition> {
// private GuiToggleButton perspectiveButton;
private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString; //
private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput, // private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString;
shoulderYawOffsetInput, shoulderSmoothnessInput; // private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput,
// shoulderYawOffsetInput, shoulderSmoothnessInput;
private ComposedElement spectatorCamSettings; //
private ComposedElement shoulderCamSettings; // private ComposedElement spectatorCamSettings;
// private ComposedElement shoulderCamSettings;
private DelegatingElement perspectiveSettings = new DelegatingElement() { //
@Override // private DelegatingElement perspectiveSettings = new DelegatingElement() {
public GuiElement delegate() { // @Override
switch(perspectiveButton.getValue()) { // public GuiElement delegate() {
case 0: // switch(perspectiveButton.getValue()) {
return spectatorCamSettings; // case 0:
case 1: // return spectatorCamSettings;
return shoulderCamSettings; // case 1:
default: // return shoulderCamSettings;
return null; // default:
} // return null;
} // }
}; // }
// };
public GuiEditKeyframeSpectator(Keyframe<AdvancedPosition> keyframe) { //
super(keyframe, ReplayHandler.getPositionKeyframes()); // public GuiEditKeyframeSpectator(Keyframe<AdvancedPosition> keyframe) {
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec"); // super(keyframe, ReplayHandler.getPositionKeyframes());
} // screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec");
// }
@Override //
public void initGui() { // @Override
super.initGui(); // public void initGui() {
// super.initGui();
if (!initialized) { //
SpectatorData data = (SpectatorData)keyframe.getValue(); // 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"), // perspectiveButton = new GuiToggleButton(0, 0, 0, 200, 20, I18n.format("replaymod.gui.editkeyframe.spec.method")+": ", new String[]{
I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder")}); // 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())); //
// perspectiveButton.setValue(Arrays.asList(SpectatorData.SpectatingMethod.values()).indexOf(data.getSpectatingMethod()));
spectatorCamSettings = new ComposedElement(); //
// spectatorCamSettings = new ComposedElement();
//create elements in shoulderCamSettings //
shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance")); // //create elements in shoulderCamSettings
shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch")); // shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance"));
shoulderYawString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.yaw")); // shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch"));
shoulderSmoothnessString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.smoothness")); // 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); // shoulderDistanceInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0d, 30d, data.getThirdPersonInfo().shoulderCamDistance, true, "", 0.1);
shoulderYawOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, null, null, data.getThirdPersonInfo().shoulderCamYawOffset, false, "°", 1); // shoulderPitchOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, -90d, 90d, data.getThirdPersonInfo().shoulderCamPitchOffset, false, "°", 1);
shoulderSmoothnessInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0.1d, 3d, data.getThirdPersonInfo().shoulderCamSmoothness, true, "", 0.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, // shoulderCamSettings = new ComposedElement(
shoulderPitchString, shoulderPitchOffsetInput, // shoulderDistanceString, shoulderDistanceInput,
shoulderYawString, shoulderYawOffsetInput, // shoulderPitchString, shoulderPitchOffsetInput,
shoulderSmoothnessString, shoulderSmoothnessInput); // shoulderYawString, shoulderYawOffsetInput,
// shoulderSmoothnessString, shoulderSmoothnessInput);
inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings)); //
} // inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings));
// }
perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2; //
perspectiveButton.yPosition = this.virtualY + 20; // perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2;
// perspectiveButton.yPosition = this.virtualY + 20;
int verticalSpacing = 20 + 5; //
int totalWidth = 300; // int verticalSpacing = 20 + 5;
int elementWidth = 145; // int totalWidth = 300;
int horizontalSpacing = 10; // int elementWidth = 145;
// int horizontalSpacing = 10;
int y = perspectiveButton.yPos() + verticalSpacing; //
// int y = perspectiveButton.yPos() + verticalSpacing;
int i = 0; //
for(GuiElement el : shoulderCamSettings.getParts()) { // int i = 0;
el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing)); // for(GuiElement el : shoulderCamSettings.getParts()) {
el.width(elementWidth); // el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing));
// el.width(elementWidth);
el.yPos(y + ((i+1)%2)*7); //
// el.yPos(y + ((i+1)%2)*7);
if(i%2 == 1) { //
y += verticalSpacing; // if(i%2 == 1) {
} // y += verticalSpacing;
i++; // }
} // i++;
// }
initialized = true; //
} // initialized = true;
// }
@Override //
public void onGuiClosed() { // @Override
SpectatorData data = (SpectatorData)keyframe.getValue(); // public void onGuiClosed() {
data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]); // SpectatorData data = (SpectatorData)keyframe.getValue();
data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue(); // data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]);
data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue(); // data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue();
data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue(); // data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue();
data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue(); // data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue();
super.onGuiClosed(); // data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue();
} // super.onGuiClosed();
} // }
// }
private static class KeyframeValueChangeListener implements NumberValueChangeListener { //
// private static class KeyframeValueChangeListener implements NumberValueChangeListener {
private GuiEditKeyframe parent; //
// private GuiEditKeyframe parent;
public KeyframeValueChangeListener(GuiEditKeyframe parent) { //
this.parent = parent; // public KeyframeValueChangeListener(GuiEditKeyframe parent) {
// this.parent = parent;
parent.min.addValueChangeListener(this); //
parent.sec.addValueChangeListener(this); // parent.min.addValueChangeListener(this);
parent.ms.addValueChangeListener(this); // parent.sec.addValueChangeListener(this);
} // parent.ms.addValueChangeListener(this);
// }
@Override //
public void onValueChange(double value) { // @Override
int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue()); // public void onValueChange(double value) {
parent.keyframe.setRealTimestamp(realTimestamp); // int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue());
// parent.keyframe.setRealTimestamp(realTimestamp);
ReplayHandler.fireKeyframesModifyEvent(); //
} // ReplayHandler.fireKeyframesModifyEvent();
} // }
// }
} }

View File

@@ -1,13 +1,9 @@
package eu.crushedpixel.replaymod.gui; 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.GuiEntryList;
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; 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.holders.KeyframeSet;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.CameraPathValidator;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
@@ -22,7 +18,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay.NoOverlay { public class GuiKeyframeRepository extends GuiScreen {
private boolean initialized = false; private boolean initialized = false;
@@ -133,39 +129,40 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay
@Override @Override
public void actionPerformed(GuiButton button) { public void actionPerformed(GuiButton button) {
if(!button.enabled) return; // TODO
switch(button.id) { // if(!button.enabled) return;
case GuiConstants.KEYFRAME_REPOSITORY_ADD_BUTTON: // switch(button.id) {
List<Keyframe> kfs = new ArrayList<Keyframe>(ReplayHandler.getAllKeyframes()); // 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()); // 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()); // try {
} catch(CameraPathValidator.InvalidCameraPathException e) { // CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes());
message = e.getLocalizedMessage(); // } catch(CameraPathValidator.InvalidCameraPathException e) {
break; // message = e.getLocalizedMessage();
} // break;
// }
if(keyframeSetList.getCopyOfElements().contains(newSet)) { //
message = I18n.format("replaymod.gui.keyframerepository.duplicate"); // if(keyframeSetList.getCopyOfElements().contains(newSet)) {
break; // message = I18n.format("replaymod.gui.keyframerepository.duplicate");
} // break;
message = null; // }
// message = null;
keyframeSetList.addElement(newSet); //
keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1); // keyframeSetList.addElement(newSet);
break; // keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1);
case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON: // break;
keyframeSetList.removeElement(keyframeSetList.getSelectionIndex()); // case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON:
break; // keyframeSetList.removeElement(keyframeSetList.getSelectionIndex());
case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON: // break;
ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex())); // case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON:
saveOnQuit(); // ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex()));
mc.displayGuiScreen(null); // saveOnQuit();
break; // mc.displayGuiScreen(null);
} // break;
// }
} }
@Override @Override
@@ -241,7 +238,8 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay
if(initialKeyframeSets.equals(copy)) return; if(initialKeyframeSets.equals(copy)) return;
this.keyframeRepository = copy.toArray(new KeyframeSet[copy.size()]); this.keyframeRepository = copy.toArray(new KeyframeSet[copy.size()]);
ReplayHandler.setKeyframeRepository(keyframeRepository, true); // TODO
// ReplayHandler.setKeyframeRepository(keyframeRepository, true);
} }
@Override @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; 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.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.*; public class GuiPlayerOverview extends GuiScreen {
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
public class GuiPlayerOverview extends GuiScreen implements GuiReplayOverlay.NoOverlay {
public static boolean defaultSave = false; public static boolean defaultSave = false;
private List<Pair<EntityPlayer, ResourceLocation>> players; // private List<Pair<EntityPlayer, ResourceLocation>> players;
private List<GuiCheckBox> checkBoxes; // private List<GuiCheckBox> checkBoxes;
//
private GuiCheckBox hideAllBox, showAllBox; // private GuiCheckBox hideAllBox, showAllBox;
private GuiCheckBox rememberHidden; // private GuiCheckBox rememberHidden;
//
private boolean initialized = false; // private boolean initialized = false;
//
private int playerCount; // private int playerCount;
private int upperPlayer = 0; // private int upperPlayer = 0;
//
private int lowerBound; // private int lowerBound;
//
private boolean drag = false; // private boolean drag = false;
private int lastY = 0; // private int lastY = 0;
private int fitting = 0; // private int fitting = 0;
//
private final Minecraft mc = Minecraft.getMinecraft(); // private final Minecraft mc = Minecraft.getMinecraft();
//
private final String screenTitle = I18n.format("replaymod.input.playeroverview"); // private final String screenTitle = I18n.format("replaymod.input.playeroverview");
//
private final Set<UUID> initialHiddenPlayers; // private final Set<UUID> initialHiddenPlayers;
//
public GuiPlayerOverview(List<EntityPlayer> players) { // public GuiPlayerOverview(List<EntityPlayer> players) {
initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers()); // initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers());
//
Collections.sort(players, new PlayerComparator()); // Collections.sort(players, new PlayerComparator());
//
this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>(); // this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
this.checkBoxes = new ArrayList<GuiCheckBox>(); // this.checkBoxes = new ArrayList<GuiCheckBox>();
//
for(final EntityPlayer p : players) { // for(final EntityPlayer p : players) {
final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID()); // final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID());
this.players.add(Pair.of(p, loc)); // this.players.add(Pair.of(p, loc));
} // }
//
playerCount = players.size(); // playerCount = players.size();
//
ReplayMod.replaySender.setReplaySpeed(0); // ReplayMod.replaySender.setReplaySpeed(0);
} // }
//
private boolean isSpectator(EntityPlayer e) { // private boolean isSpectator(EntityPlayer e) {
return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null; // return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
} // }
//
@Override // @Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) // protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
throws IOException { // throws IOException {
//
if(fitting < playerCount) { // if(fitting < playerCount) {
float visiblePerc = (float) fitting / (float) playerCount; // float visiblePerc = (float) fitting / (float) playerCount;
//
int h = this.height - 32 - 32; // int h = this.height - 32 - 32;
int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h); // int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h);
//
int lower = Math.round(32 + offset + (h * visiblePerc)) - 2; // int lower = Math.round(32 + offset + (h * visiblePerc)) - 2;
//
int k2 = (int) (this.width * 0.3); // int k2 = (int) (this.width * 0.3);
//
if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) { // if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) {
lastY = mouseY; // lastY = mouseY;
drag = true; // drag = true;
return; // return;
} // }
} // }
int k2 = (int) (this.width * 0.3); // int k2 = (int) (this.width * 0.3);
//
if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) { // if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) {
int off = mouseY - upperBound; // int off = mouseY - upperBound;
int p = (off / 21) + upperPlayer; // int p = (off / 21) + upperPlayer;
ReplayHandler.spectateEntity(players.get(p).first()); // // TODO
mc.displayGuiScreen(null); //// ReplayHandler.spectateEntity(players.get(p).first());
} // mc.displayGuiScreen(null);
// }
super.mouseClicked(mouseX, mouseY, mouseButton); //
} // super.mouseClicked(mouseX, mouseY, mouseButton);
// }
@Override //
protected void mouseClickMove(int mouseX, int mouseY, // @Override
int clickedMouseButton, long timeSinceLastClick) { // protected void mouseClickMove(int mouseX, int mouseY,
// int clickedMouseButton, long timeSinceLastClick) {
if(drag) { //
float step = 1f / (float) playerCount; // if(drag) {
// float step = 1f / (float) playerCount;
int diff = mouseY - lastY; //
int h = this.height - 32 - 32; // int diff = mouseY - lastY;
// int h = this.height - 32 - 32;
float percDiff = (float) diff / (float) h; //
if(Math.abs(percDiff) > Math.abs(step)) { // float percDiff = (float) diff / (float) h;
int s = (int) (percDiff / step); // if(Math.abs(percDiff) > Math.abs(step)) {
lastY = mouseY; // int s = (int) (percDiff / step);
upperPlayer += s; // lastY = mouseY;
if(upperPlayer > playerCount - fitting) { // upperPlayer += s;
upperPlayer = playerCount - fitting; // if(upperPlayer > playerCount - fitting) {
} else if(upperPlayer < 0) { // upperPlayer = playerCount - fitting;
upperPlayer = 0; // } else if(upperPlayer < 0) {
} // upperPlayer = 0;
} // }
} // }
// }
super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); //
} // super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
// }
@Override //
protected void mouseReleased(int mouseX, int mouseY, int state) { // @Override
drag = false; // protected void mouseReleased(int mouseX, int mouseY, int state) {
// drag = false;
for(GuiCheckBox checkBox : checkBoxes) { //
checkBox.mouseReleased(mouseX, mouseY); // for(GuiCheckBox checkBox : checkBoxes) {
} // checkBox.mouseReleased(mouseX, mouseY);
// }
super.mouseReleased(mouseX, mouseY, state); //
} // super.mouseReleased(mouseX, mouseY, state);
// }
@Override //
public void initGui() { // @Override
upperPlayer = 0; // public void initGui() {
lowerBound = this.height - 10; // upperPlayer = 0;
// lowerBound = this.height - 10;
@SuppressWarnings("unchecked") //
List<GuiButton> buttonList = this.buttonList; // @SuppressWarnings("unchecked")
// List<GuiButton> buttonList = this.buttonList;
int i = 0; //
for(GuiCheckBox checkBox : checkBoxes) { // int i = 0;
checkBox.xPosition = (int)(this.width*0.7)-5; // for(GuiCheckBox checkBox : checkBoxes) {
buttonList.add(checkBox); // checkBox.xPosition = (int)(this.width*0.7)-5;
i++; // buttonList.add(checkBox);
if(i >= fitting) break; // i++;
} // if(i >= fitting) break;
// }
if(!initialized) { //
hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false); // if(!initialized) {
showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true); // hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false);
rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave); // 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.xPosition = (int)(this.width*0.7)-5;
hideAllBox.yPosition = showAllBox.yPosition = 45; // showAllBox.xPosition = (int)(this.width*0.7)-20;
// hideAllBox.yPosition = showAllBox.yPosition = 45;
rememberHidden.xPosition = (int)(this.width*0.3); //
rememberHidden.yPosition = 45; // rememberHidden.xPosition = (int)(this.width*0.3);
// rememberHidden.yPosition = 45;
buttonList.add(hideAllBox); //
buttonList.add(showAllBox); // buttonList.add(hideAllBox);
buttonList.add(rememberHidden); // buttonList.add(showAllBox);
// buttonList.add(rememberHidden);
initialized = true; //
} // initialized = true;
// }
@Override //
protected void actionPerformed(GuiButton button) throws IOException { // @Override
if(button == showAllBox) { // protected void actionPerformed(GuiButton button) throws IOException {
showAllBox.setIsChecked(true); // if(button == showAllBox) {
for(Pair<EntityPlayer, ResourceLocation> p : players) { // showAllBox.setIsChecked(true);
PlayerHandler.showPlayer(p.first()); // for(Pair<EntityPlayer, ResourceLocation> p : players) {
} // PlayerHandler.showPlayer(p.first());
} else if(button == hideAllBox) { // }
hideAllBox.setIsChecked(false); // } else if(button == hideAllBox) {
for(Pair<EntityPlayer, ResourceLocation> p : players) { // hideAllBox.setIsChecked(false);
PlayerHandler.hidePlayer(p.first()); // for(Pair<EntityPlayer, ResourceLocation> p : players) {
} // PlayerHandler.hidePlayer(p.first());
} // }
// }
if(!(button instanceof GuiCheckBox)) return; //
if(button.id >= fitting) return; // if(!(button instanceof GuiCheckBox)) return;
if(!checkBoxes.contains(button)) return; // if(button.id >= fitting) return;
PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked()); // if(!checkBoxes.contains(button)) return;
} // PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked());
// }
private static final int upperBound = 65; //
// private static final int upperBound = 65;
@Override //
public void drawScreen(int mouseX, int mouseY, float partialTicks) { // @Override
this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB()); // public void drawScreen(int mouseX, int mouseY, float partialTicks) {
int k2 = (int)(this.width * 0.3); // this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB());
int l2 = upperBound; // 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); //
// 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()); //
// 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()); // 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; //
// fitting = 0;
int sk = 0; //
for(Pair<EntityPlayer, ResourceLocation> p : players) { // int sk = 0;
if(sk < upperPlayer) { // for(Pair<EntityPlayer, ResourceLocation> p : players) {
sk++; // if(sk < upperPlayer) {
continue; // sk++;
} // continue;
boolean spec = isSpectator(p.first()); // }
// 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()); // 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()); //
// 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)) // drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
Gui.drawScaledCustomSizeModalRect(k2, l2, 40.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()) { // GlStateManager.resetColor();
checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true)); // if(fitting >= checkBoxes.size()) {
@SuppressWarnings("unchecked") // checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true));
List<GuiButton> buttonList = this.buttonList; // @SuppressWarnings("unchecked")
buttonList.add(checkBoxes.get(checkBoxes.size() - 1)); // List<GuiButton> buttonList = this.buttonList;
} // buttonList.add(checkBoxes.get(checkBoxes.size() - 1));
checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID())); // }
// checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID()));
l2 += 16 + 5; //
fitting++; // l2 += 16 + 5;
if(l2 + 32 > lowerBound) { // fitting++;
break; // if(l2 + 32 > lowerBound) {
} // break;
} // }
// }
int dw = Mouse.getDWheel(); //
if(dw > 0) { // int dw = Mouse.getDWheel();
dw = -1; // if(dw > 0) {
} else if(dw < 0) { // dw = -1;
dw = 1; // } else if(dw < 0) {
} // dw = 1;
// }
upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0); //
// upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0);
if(fitting < playerCount) { //
float visiblePerc = ((float) fitting) / playerCount; // if(fitting < playerCount) {
int barHeight = (int) (visiblePerc * (height - 32 - 32)); // float visiblePerc = ((float) fitting) / playerCount;
// int barHeight = (int) (visiblePerc * (height - 32 - 32));
float posPerc = ((float) upperPlayer) / playerCount; //
int barY = (int) (posPerc * (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()); // 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) { // int i = 0;
checkBox.drawButton(mc, mouseX, mouseY); // for(GuiCheckBox checkBox : checkBoxes) {
i++; // checkBox.drawButton(mc, mouseX, mouseY);
if(i >= fitting) break; // i++;
} // if(i >= fitting) break;
// }
hideAllBox.drawButton(mc, mouseX, mouseY); //
showAllBox.drawButton(mc, mouseX, mouseY); // hideAllBox.drawButton(mc, mouseX, mouseY);
rememberHidden.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(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(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); // 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(); // //this is necessary to reset the GL parameters for further GUI rendering
} // GlStateManager.enableBlend();
// }
private PlayerVisibility getVisibilityInstance() { //
Set<UUID> hidden = PlayerHandler.getHiddenPlayers(); // private void saveOnQuit() {
return new PlayerVisibility(hidden.toArray(new UUID[hidden.size()])); // try {
} // // TODO
//// if(rememberHidden.isChecked()) {
//// if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return;
private void saveOnQuit() { //// ReplayHandler.getReplayFile().writeInvisiblePlayers(PlayerHandler.getHiddenPlayers());
if(rememberHidden.isChecked()) { //// } else {
if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return; //// if(initialHiddenPlayers.isEmpty()) return;
try { //// ReplayHandler.getReplayFile().writeInvisiblePlayers(Collections.<UUID>emptySet());
File f = File.createTempFile(ReplayFile.ENTRY_VISIBILITY, "json"); //// }
ReplayFileIO.write(getVisibilityInstance(), f); // } catch(Exception e) {
ReplayMod.replayFileAppender.registerModifiedFile(f, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); // e.printStackTrace();
} catch(Exception e) { // }
e.printStackTrace(); // }
} //
} else { // @Override
if(initialHiddenPlayers.isEmpty()) return; // public void keyTyped(char typedChar, int keyCode) throws IOException {
ReplayMod.replayFileAppender.registerModifiedFile(null, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile()); // if(keyCode == Keyboard.KEY_ESCAPE) {
} // saveOnQuit();
} // super.keyTyped(typedChar, keyCode);
// }
@Override // }
public void keyTyped(char typedChar, int keyCode) throws IOException { //
if(keyCode == Keyboard.KEY_ESCAPE) { // private class PlayerComparator implements Comparator<EntityPlayer> {
saveOnQuit(); //
super.keyTyped(typedChar, keyCode); // @Override
} // public int compare(EntityPlayer o1, EntityPlayer o2) {
} // if(isSpectator(o1) && !isSpectator(o2)) {
// return 1;
private class PlayerComparator implements Comparator<EntityPlayer> { // } else if(isSpectator(o2) && !isSpectator(o1)) {
// return -1;
@Override // } else {
public int compare(EntityPlayer o1, EntityPlayer o2) { // return o1.getName().compareToIgnoreCase(o2.getName());
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; 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.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener; import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener;
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; 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.holders.GuiEntryListEntry;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.settings.EncodingPreset; import eu.crushedpixel.replaymod.settings.EncodingPreset;
import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.settings.RenderOptions;
import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.MouseUtils;
@@ -29,7 +27,7 @@ import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoOverlay { public class GuiRenderSettings extends GuiScreen {
private final Minecraft mc = Minecraft.getMinecraft(); private final Minecraft mc = Minecraft.getMinecraft();
@@ -542,7 +540,8 @@ public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoO
if(FMLClientHandler.instance().hasOptifine()) { if(FMLClientHandler.instance().hasOptifine()) {
mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine"))); mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine")));
} else { } else {
ReplayHandler.startPath(options, true); // TODO
// ReplayHandler.startPath(options, true);
} }
} }

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui; package eu.crushedpixel.replaymod.gui;
import eu.crushedpixel.replaymod.ReplayMod; import com.replaymod.core.ReplayMod;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;

View File

@@ -1,7 +1,5 @@
package eu.crushedpixel.replaymod.gui; 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.RecordingOptions;
import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
@@ -12,8 +10,6 @@ import net.minecraftforge.fml.client.FMLClientHandler;
import java.awt.*; import java.awt.*;
import java.io.IOException; import java.io.IOException;
import static eu.crushedpixel.replaymod.gui.GuiConstants.*;
public class GuiReplaySettings extends GuiScreen { public class GuiReplaySettings extends GuiScreen {
protected String screenTitle = I18n.format("replaymod.gui.settings.title"); protected String screenTitle = I18n.format("replaymod.gui.settings.title");
private GuiScreen parentGuiScreen; private GuiScreen parentGuiScreen;
@@ -38,23 +34,23 @@ public class GuiReplaySettings extends GuiScreen {
int xPos = this.width / 2 - 155 + i % 2 * 160; int xPos = this.width / 2 - 155 + i % 2 * 160;
int yPos = this.height / 6 + 24 * (i >> 1); int yPos = this.height / 6 + 24 * (i >> 1);
// TODO
if(o == RecordingOptions.notifications) { // if(o == RecordingOptions.notifications) {
GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o); // GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o);
buttonList.add(sendChatButton); // buttonList.add(sendChatButton);
//
} else if(o == RecordingOptions.recordServer) { // } else if(o == RecordingOptions.recordServer) {
GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o); // GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o);
buttonList.add(recordServerButton); // buttonList.add(recordServerButton);
//
} else if(o == RecordingOptions.recordSingleplayer) { // } else if(o == RecordingOptions.recordSingleplayer) {
GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o); // GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o);
buttonList.add(recordSPButton); // buttonList.add(recordSPButton);
//
} else if(o == RecordingOptions.indicator) { // } else if(o == RecordingOptions.indicator) {
GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o); // GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o);
buttonList.add(showIndicatorButton); // buttonList.add(showIndicatorButton);
} // }
++i; ++i;
} }
@@ -69,14 +65,15 @@ public class GuiReplaySettings extends GuiScreen {
int xPos = this.width / 2 - 155 + i % 2 * 160; int xPos = this.width / 2 - 155 + i % 2 * 160;
int yPos = this.height / 6 + 24 * (i >> 1); int yPos = this.height / 6 + 24 * (i >> 1);
if(o == ReplayOptions.linear) { // TODO
GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o, // if(o == ReplayOptions.linear) {
I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic")); // GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o,
buttonList.add(linearButton); // 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)); // } else {
} // buttonList.add(new GuiSettingsOnOffButton(0, xPos, yPos, 150, 20, o));
// }
++i; ++i;
} }

View File

@@ -1,12 +1,11 @@
package eu.crushedpixel.replaymod.gui; package eu.crushedpixel.replaymod.gui;
import eu.crushedpixel.replaymod.ReplayMod; import com.replaymod.core.ReplayMod;
import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton; import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
import net.minecraftforge.fml.client.FMLClientHandler;
public class GuiReplaySpeedSlider extends GuiAdvancedButton { public class GuiReplaySpeedSlider extends GuiAdvancedButton {
@@ -74,7 +73,7 @@ public class GuiReplaySpeedSlider extends GuiAdvancedButton {
l = packedFGColour; l = packedFGColour;
} else if(!this.enabled) { } else if(!this.enabled) {
l = 10526880; l = 10526880;
} else if(this.hovered && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { } else if(this.hovered) {
l = 16777120; l = 16777120;
} }

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.elements; 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.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.elements; 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 eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;

View File

@@ -1,11 +1,12 @@
package eu.crushedpixel.replaymod.gui.elements; package eu.crushedpixel.replaymod.gui.elements;
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
import eu.crushedpixel.replaymod.utils.OpenGLUtils; import eu.crushedpixel.replaymod.utils.OpenGLUtils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import static com.replaymod.core.ReplayMod.TEXTURE;
public class GuiArrowButton extends GuiAdvancedButton { public class GuiArrowButton extends GuiAdvancedButton {
private static final int TEXTURE_X = 40; private static final int TEXTURE_X = 40;
@@ -42,7 +43,7 @@ public class GuiArrowButton extends GuiAdvancedButton {
try { try {
super.draw(mc, mouseX, mouseY, hovering); super.draw(mc, mouseX, mouseY, hovering);
mc.getTextureManager().bindTexture(GuiReplayOverlay.replay_gui); mc.getTextureManager().bindTexture(TEXTURE);
OpenGLUtils.drawRotatedRectWithCustomSizedTexture(xPosition+4, yPosition+4, dir.getRotation(), OpenGLUtils.drawRotatedRectWithCustomSizedTexture(xPosition+4, yPosition+4, dir.getRotation(),
TEXTURE_X, TEXTURE_Y, TEXTURE_WIDTH, TEXTURE_HEIGHT, 128, 128); TEXTURE_X, TEXTURE_Y, TEXTURE_WIDTH, TEXTURE_HEIGHT, 128, 128);

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.elements; 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.gui.elements.listeners.SelectionListener;
import eu.crushedpixel.replaymod.holders.GuiEntryListEntry; import eu.crushedpixel.replaymod.holders.GuiEntryListEntry;
import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.MouseUtils;

View File

@@ -6,8 +6,8 @@ import net.minecraft.client.renderer.GlStateManager;
import java.awt.*; import java.awt.*;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; import static com.replaymod.core.ReplayMod.TEXTURE;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
import static org.lwjgl.opengl.GL11.GL_BLEND; import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.glEnable; import static org.lwjgl.opengl.GL11.glEnable;
@@ -105,7 +105,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
@Override @Override
public void draw(Minecraft mc, int mouseX, int mouseY) { public void draw(Minecraft mc, int mouseX, int mouseY) {
GlStateManager.resetColor(); GlStateManager.resetColor();
mc.renderEngine.bindTexture(replay_gui); mc.renderEngine.bindTexture(TEXTURE);
glEnable(GL_BLEND); glEnable(GL_BLEND);
// Background // Background
@@ -157,7 +157,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
if(!enabled) { if(!enabled) {
GlStateManager.color(Color.GRAY.getRed()/255f, Color.GRAY.getGreen()/255f, Color.GRAY.getBlue()/255f, 1f); 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); glEnable(GL_BLEND);
drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE); drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE);

View File

@@ -1,39 +1,39 @@
package eu.crushedpixel.replaymod.gui.elements; package eu.crushedpixel.replaymod.gui.elements;
import eu.crushedpixel.replaymod.ReplayMod; import com.replaymod.core.SettingsRegistry;
import eu.crushedpixel.replaymod.settings.ReplaySettings;
public class GuiSettingsOnOffButton extends GuiOnOffButton { 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) { public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry,
super(buttonId, x, y, width, height, toChange.getName()+": "); SettingsRegistry.SettingKey<Boolean> toChange) {
super(buttonId, x, y, width, height, toChange.getDisplayString()+": ");
this.settingsRegistry = settingsRegistry;
this.toChange = toChange; this.toChange = toChange;
if(toChange.getValue() instanceof Boolean) { this.setValue(settingsRegistry.get(toChange) ? 0 : 1);
this.setValue((Boolean) toChange.getValue() ? 0 : 1);
}
} }
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange, String onValue, String offValue) { public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry,
super(buttonId, x, y, width, height, toChange.getName()+": ", onValue, offValue); SettingsRegistry.SettingKey<Boolean> toChange, String onValue, String offValue) {
super(buttonId, x, y, width, height, toChange.getDisplayString()+": ", onValue, offValue);
this.settingsRegistry = settingsRegistry;
this.toChange = toChange; this.toChange = toChange;
if(toChange.getValue() instanceof Boolean) { this.setValue(settingsRegistry.get(toChange) ? 0 : 1);
this.setValue((Boolean) toChange.getValue() ? 0 : 1);
}
} }
@Override @Override
public void toggle() { public void toggle() {
super.toggle(); super.toggle();
toChange.setValue(isOn()); settingsRegistry.set(toChange, isOn());
ReplayMod.replaySettings.rewriteSettings(); settingsRegistry.save();
} }
@Override @Override
public void setValue(int value) { public void setValue(int value) {
super.setValue(value); super.setValue(value);
toChange.setValue(isOn()); settingsRegistry.set(toChange, isOn());
ReplayMod.replaySettings.rewriteSettings(); settingsRegistry.save();
} }
} }

View File

@@ -1,13 +1,6 @@
package eu.crushedpixel.replaymod.gui.elements.timelines; package eu.crushedpixel.replaymod.gui.elements.timelines;
import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.holders.Keyframe;
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;
public class GuiKeyframeTimeline extends GuiTimeline { public class GuiKeyframeTimeline extends GuiTimeline {
private static final int KEYFRAME_PLACE_X = 74; private static final int KEYFRAME_PLACE_X = 74;
@@ -31,230 +24,231 @@ public class GuiKeyframeTimeline extends GuiTimeline {
this.placeKeyframes = showPlaceKeyframes; this.placeKeyframes = showPlaceKeyframes;
} }
@Override // TODO
public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) { // @Override
if(!enabled) return false; // public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) {
// if(!enabled) return false;
long time = getTimeAt(mouseX, mouseY); //
if(time == -1) { // long time = getTimeAt(mouseX, mouseY);
return false; // if(time == -1) {
} // return false;
// }
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); //
// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
Keyframe closest; //
if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) { // Keyframe closest;
closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); // if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) {
} else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) { // closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance); // } else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) {
} else { // closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
closest = null; // } else {
} // closest = null;
// }
//left mouse button //
if(button == 0) { // //left mouse button
ReplayHandler.selectKeyframe(closest); //can be null, deselects keyframe // 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 we clicked on a key frame, then continue monitoring the mouse for movements
if(closest != null) { // long currentTime = System.currentTimeMillis();
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead // if(closest != null) {
mc.displayGuiScreen(GuiEditKeyframe.create(closest)); // if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
this.clickedKeyFrame = null; // mc.displayGuiScreen(GuiEditKeyframe.create(closest));
} else { // this.clickedKeyFrame = null;
this.clickedKeyFrame = closest; // } else {
this.dragging = false; // this.clickedKeyFrame = closest;
} // this.dragging = false;
} else { // If we didn't then just update the cursor // }
ReplayHandler.setRealTimelineCursor((int) time); // } else { // If we didn't then just update the cursor
this.dragging = true; // ReplayHandler.setRealTimelineCursor((int) time);
} // this.dragging = true;
this.clickTime = currentTime; // }
// this.clickTime = currentTime;
} else if(button == 1) { //
if(closest != null) { // } else if(button == 1) {
if(closest.getValue() instanceof AdvancedPosition) { // if(closest != null) {
AdvancedPosition pos = (AdvancedPosition)closest.getValue(); // if(closest.getValue() instanceof AdvancedPosition) {
ReplayHandler.getCameraEntity().movePath(pos); // AdvancedPosition pos = (AdvancedPosition)closest.getValue();
} else if(closest.getValue() instanceof TimestampValue) { // ReplayHandler.getCameraEntity().movePath(pos);
ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt()); // } else if(closest.getValue() instanceof TimestampValue) {
} // ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt());
} // }
} // }
// }
return isHovering(mouseX, mouseY); //
} // return isHovering(mouseX, mouseY);
// }
@Override //
public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) { // @Override
if(!enabled) return; // public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) {
long time = getTimeAt(mouseX, mouseY); // if(!enabled) return;
if (time != -1) { // long time = getTimeAt(mouseX, mouseY);
if (clickedKeyFrame != null) { // if (time != -1) {
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width)); // if (clickedKeyFrame != 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(clickedKeyFrame.getRealTimestamp() - time) > tolerance) {
ReplayHandler.getPositionKeyframes().sort(); // clickedKeyFrame.setRealTimestamp((int) time);
ReplayHandler.getTimeKeyframes().sort(); // ReplayHandler.getPositionKeyframes().sort();
dragging = true; // ReplayHandler.getTimeKeyframes().sort();
} // dragging = true;
} else if (dragging) { // }
ReplayHandler.setRealTimelineCursor((int) time); // } else if (dragging) {
} // ReplayHandler.setRealTimelineCursor((int) time);
} // }
} // }
// }
@Override //
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) { // @Override
mouseDrag(mc, mouseX, mouseY, button); // public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
clickedKeyFrame = null; // mouseDrag(mc, mouseX, mouseY, button);
dragging = false; // clickedKeyFrame = null;
} // dragging = false;
// }
@Override //
public void draw(Minecraft mc, int mouseX, int mouseY) { // @Override
super.draw(mc, mouseX, mouseY); // public void draw(Minecraft mc, int mouseX, int mouseY) {
// super.draw(mc, mouseX, mouseY);
int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT; //
// int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
long leftTime = Math.round(timeStart * timelineLength); //
long rightTime = Math.round((timeStart + zoom) * timelineLength); // long leftTime = Math.round(timeStart * timelineLength);
// long rightTime = Math.round((timeStart + zoom) * timelineLength);
double segmentLength = timelineLength * zoom; //
// double segmentLength = timelineLength * zoom;
//iterate over keyframes to find spectator segments //
if(placeKeyframes) { // //iterate over keyframes to find spectator segments
ListIterator<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator(); // if(placeKeyframes) {
while(iterator.hasNext()) { // ListIterator<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator();
Keyframe<AdvancedPosition> kf = iterator.next(); // while(iterator.hasNext()) {
// Keyframe<AdvancedPosition> kf = iterator.next();
if(!(kf.getValue() instanceof SpectatorData)) //
continue; // if(!(kf.getValue() instanceof SpectatorData))
// continue;
int i = iterator.nextIndex(); //
int nextSpectatorKeyframeRealTime = -1; // int i = iterator.nextIndex();
// int nextSpectatorKeyframeRealTime = -1;
if (iterator.hasNext()) { //
Keyframe<AdvancedPosition> kf2 = iterator.next(); // if (iterator.hasNext()) {
// Keyframe<AdvancedPosition> kf2 = iterator.next();
if(kf2.getValue() instanceof SpectatorData) { //
SpectatorData spectatorData1 = (SpectatorData)kf.getValue(); // if(kf2.getValue() instanceof SpectatorData) {
SpectatorData spectatorData2 = (SpectatorData)kf2.getValue(); // SpectatorData spectatorData1 = (SpectatorData)kf.getValue();
// SpectatorData spectatorData2 = (SpectatorData)kf2.getValue();
if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) { //
nextSpectatorKeyframeRealTime = kf2.getRealTimestamp(); // if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) {
} // nextSpectatorKeyframeRealTime = kf2.getRealTimestamp();
} // }
} // }
// }
int i2 = iterator.previousIndex(); //
// int i2 = iterator.previousIndex();
while(i2 >= i) { //
iterator.previous(); // while(i2 >= i) {
i2--; // iterator.previous();
} // i2--;
// }
if(nextSpectatorKeyframeRealTime != -1) { //
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); // if(nextSpectatorKeyframeRealTime != -1) {
int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength); // int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
// int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength);
int color = ((SpectatorData)kf.getValue()).getSpectatingMethod().getColor(); //
// 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); // 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); //
} // GlStateManager.color(1, 1, 1, 1);
} // }
} // }
// }
//iterate over time keyframes to find negative replay speeds //
if(timeKeyframes) { // //iterate over time keyframes to find negative replay speeds
ListIterator<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator(); // if(timeKeyframes) {
while(iterator.hasNext()) { // ListIterator<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator();
Keyframe<TimestampValue> kf = iterator.next(); // while(iterator.hasNext()) {
// Keyframe<TimestampValue> kf = iterator.next();
int i = iterator.nextIndex(); //
int nextTimeKeyframeRealTime = -1; // int i = iterator.nextIndex();
// int nextTimeKeyframeRealTime = -1;
if (iterator.hasNext()) { //
Keyframe<TimestampValue> kf2 = iterator.next(); // if (iterator.hasNext()) {
if(kf.getValue().asInt() > kf2.getValue().asInt()) { // Keyframe<TimestampValue> kf2 = iterator.next();
nextTimeKeyframeRealTime = kf2.getRealTimestamp(); // if(kf.getValue().asInt() > kf2.getValue().asInt()) {
} // nextTimeKeyframeRealTime = kf2.getRealTimestamp();
} // }
// }
int i2 = iterator.previousIndex(); //
// int i2 = iterator.previousIndex();
while(i2 >= i) { //
iterator.previous(); // while(i2 >= i) {
i2--; // iterator.previous();
} // i2--;
// }
if(nextTimeKeyframeRealTime != -1) { //
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); // if(nextTimeKeyframeRealTime != -1) {
int nextX = getKeyframeX(nextTimeKeyframeRealTime, leftTime, bodyWidth, segmentLength); // 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); // 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); //
// drawTimelineCursor(leftTime, rightTime, bodyWidth);
//
//Draw Keyframe logos //
for (Keyframe kf : ReplayHandler.getAllKeyframes()) { // //Draw Keyframe logos
if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe())) // for (Keyframe kf : ReplayHandler.getAllKeyframes()) {
drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength); // 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); // 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; // private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
double fractionOfSegment = positionInSegment / segmentLength; // long positionInSegment = timestamp - leftTime;
return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth); // 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) { // private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
int textureX; // if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) {
int textureY; // int textureX;
int y = positionY; // int textureY;
// int y = positionY;
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength); //
// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
if(kf.getValue() instanceof AdvancedPosition) { //
if(!placeKeyframes) return; // if(kf.getValue() instanceof AdvancedPosition) {
textureX = KEYFRAME_PLACE_X; // if(!placeKeyframes) return;
textureY = KEYFRAME_PLACE_Y; // textureX = KEYFRAME_PLACE_X;
y += 0; // textureY = KEYFRAME_PLACE_Y;
// y += 0;
//If Spectator Keyframe, use different texture //
if(kf.getValue() instanceof SpectatorData) { // //If Spectator Keyframe, use different texture
textureX = KEYFRAME_SPEC_X; // if(kf.getValue() instanceof SpectatorData) {
textureY = KEYFRAME_SPEC_Y; // textureX = KEYFRAME_SPEC_X;
} // textureY = KEYFRAME_SPEC_Y;
} else if(kf.getValue() instanceof TimestampValue) { // }
if(!timeKeyframes) return; // } else if(kf.getValue() instanceof TimestampValue) {
textureX = KEYFRAME_TIME_X; // if(!timeKeyframes) return;
textureY = KEYFRAME_TIME_Y; // textureX = KEYFRAME_TIME_X;
y += 5; // textureY = KEYFRAME_TIME_Y;
} else { // y += 5;
throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass()); // } else {
} // throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass());
// }
if (ReplayHandler.isSelected(kf)) { //
textureX += 5; // if (ReplayHandler.isSelected(kf)) {
} // textureX += 5;
// }
rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5); //
} // rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5);
} // }
// }
} }

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.elements.timelines; 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.gui.elements.GuiElement;
import eu.crushedpixel.replaymod.utils.RoundUtils; import eu.crushedpixel.replaymod.utils.RoundUtils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -11,8 +11,8 @@ import net.minecraft.client.renderer.GlStateManager;
import java.awt.*; import java.awt.*;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE; import static com.replaymod.core.ReplayMod.TEXTURE;
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui; import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
import static org.lwjgl.opengl.GL11.GL_BLEND; import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.glEnable; 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 * 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. * 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 positionX;
protected final int positionY; protected final int positionY;
@@ -280,7 +280,7 @@ public class GuiTimeline extends Gui implements GuiElement {
if(!enabled) { if(!enabled) {
GlStateManager.color(Color.GRAY.getRed() / 255f, Color.GRAY.getGreen() / 255f, Color.GRAY.getBlue() / 255f, 1f); 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); glEnable(GL_BLEND);
drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE); 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.GuiPasswordField;
import de.johni0702.minecraft.gui.element.GuiTextField; import de.johni0702.minecraft.gui.element.GuiTextField;
import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.CustomLayout;
import eu.crushedpixel.replaymod.ReplayMod; import com.replaymod.core.ReplayMod;
import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.GuiConstants;
public class GuiLoginPrompt extends AbstractGuiScreen<GuiLoginPrompt> { 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.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; 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.api.ApiException;
import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.GuiConstants;
import eu.crushedpixel.replaymod.utils.EmailAddressUtils; import eu.crushedpixel.replaymod.utils.EmailAddressUtils;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.online; 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.SearchQuery;
import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.api.replay.holders.Category;
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; 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.api.replay.pagination.SearchPagination;
import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.GuiConstants;
import eu.crushedpixel.replaymod.gui.elements.*; import eu.crushedpixel.replaymod.gui.elements.*;
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry; import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry;
import net.minecraft.client.gui.*; import net.minecraft.client.gui.*;
import net.minecraft.client.resources.I18n; 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) { } else if(button.id == GuiConstants.CENTER_LOGOUT_BUTTON) {
mc.displayGuiScreen(getYesNoGui(this, LOGOUT_CALLBACK_ID)); mc.displayGuiScreen(getYesNoGui(this, LOGOUT_CALLBACK_ID));
} else if(button.id == GuiConstants.CENTER_MANAGER_BUTTON) { } 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) { } else if(button.id == GuiConstants.CENTER_RECENT_BUTTON) {
disableTopBarButton(button.id); disableTopBarButton(button.id);
showOnlineRecent(); showOnlineRecent();

View File

@@ -1,15 +1,14 @@
package eu.crushedpixel.replaymod.gui.online; package eu.crushedpixel.replaymod.gui.online;
import com.mojang.realmsclient.gui.ChatFormatting; import com.mojang.realmsclient.gui.ChatFormatting;
import com.replaymod.core.ReplayMod;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.CustomLayout;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import java.io.File; import java.io.File;
@@ -49,7 +48,8 @@ public class GuiReplayDownloading extends AbstractGuiScreen<GuiReplayDownloading
@Override @Override
public void run() { public void run() {
try { try {
ReplayHandler.startReplay(replayFile); // TODO
// ReplayHandler.startReplay(replayFile);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); 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.GuiDropdown;
import eu.crushedpixel.replaymod.gui.elements.GuiString; import eu.crushedpixel.replaymod.gui.elements.GuiString;
import eu.crushedpixel.replaymod.holders.GuiEntryListValueEntry; 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 eu.crushedpixel.replaymod.utils.ReplayFileIO;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
@@ -55,7 +53,7 @@ public class GuiReplayInstanceChooser extends GuiScreen {
for(File file : files) { for(File file : files) {
try { try {
String extension = FilenameUtils.getExtension(file.getAbsolutePath()); 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 filename = FilenameUtils.getBaseName(file.getAbsolutePath());
String[] split = filename.split("_"); 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 no modified versions of the replay were found, start the downloaded one
if(chooseableFiles.isEmpty()) { if(chooseableFiles.isEmpty()) {
ReplayHandler.startReplay(downloadedFile); // TODO
// ReplayHandler.startReplay(downloadedFile);
return; return;
} }
@@ -103,7 +102,8 @@ public class GuiReplayInstanceChooser extends GuiScreen {
public void run() { public void run() {
try { try {
File file = fileDropdown.getElement(fileDropdown.getSelectionIndex()).getValue(); File file = fileDropdown.getElement(fileDropdown.getSelectionIndex()).getValue();
ReplayHandler.startReplay(file); //TODO
// ReplayHandler.startReplay(file);
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -1,16 +1,22 @@
package eu.crushedpixel.replaymod.gui.online; 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.FileUploader;
import eu.crushedpixel.replaymod.api.replay.holders.Category; import eu.crushedpixel.replaymod.api.replay.holders.Category;
import eu.crushedpixel.replaymod.gui.GuiConstants; import eu.crushedpixel.replaymod.gui.GuiConstants;
import eu.crushedpixel.replaymod.gui.elements.*; import eu.crushedpixel.replaymod.gui.elements.*;
import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener; import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener;
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import com.replaymod.replay.gui.screen.GuiReplayViewer;
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
import eu.crushedpixel.replaymod.registry.KeybindRegistry; import eu.crushedpixel.replaymod.registry.KeybindRegistry;
import eu.crushedpixel.replaymod.registry.ResourceHelper; 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.Minecraft;
import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
@@ -35,7 +41,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@@ -84,15 +89,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener {
boolean correctFile = false; boolean correctFile = false;
this.replayFile = file; this.replayFile = file;
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ReplayFile.ZIP_FILE_EXTENSION)) { if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(".zip")) {
ReplayFile archive = null; ReplayFile archive = null;
try { try {
archive = new ReplayFile(file); archive = new ZipReplayFile(new ReplayStudio(), file);
metaData = archive.metadata().get(); metaData = archive.getMetaData();
BufferedImage img = archive.thumb().get(); Optional<BufferedImage> img = archive.getThumb();
if(img != null) { if(img.isPresent()) {
thumb = ImageUtils.scaleImage(img, new Dimension(1280, 720)); thumb = ImageUtils.scaleImage(img.get(), new Dimension(1280, 720));
hasThumbnail = true; hasThumbnail = true;
} }
@@ -307,21 +312,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener {
if(hideServerIP.isChecked()) { if(hideServerIP.isChecked()) {
File tmp = File.createTempFile("replay_hidden_ip", "mcpr"); File tmp = File.createTempFile("replay_hidden_ip", "mcpr");
File tmpMeta = File.createTempFile("metadata", "json");
ReplayMetaData newMetaData = metaData.copy(); ReplayMetaData newMetaData = new ReplayMetaData(metaData);
newMetaData.removeServer(); newMetaData.setServerName(null);
ReplayFileIO.write(newMetaData, tmpMeta); ReplayFile replay = new ZipReplayFile(new ReplayStudio(), replayFile);
replay.writeMetaData(newMetaData);
HashMap<String, File> toAdd = new HashMap<String, File>(); replay.saveTo(tmp);
toAdd.put(ReplayFile.ENTRY_METADATA, tmpMeta);
FileUtils.copyFile(replayFile, tmp);
ReplayFileIO.addFilesToZip(tmp, toAdd);
uploader.uploadFile(GuiUploadFile.this, name, tags, tmp, category, desc); uploader.uploadFile(GuiUploadFile.this, name, tags, tmp, category, desc);
FileUtils.deleteQuietly(tmpMeta);
FileUtils.deleteQuietly(tmp); FileUtils.deleteQuietly(tmp);
} else { } else {
uploader.uploadFile(GuiUploadFile.this, name, tags, replayFile, category, desc); 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; 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.GuiConstants;
import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar; import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;

View File

@@ -1,6 +1,6 @@
package eu.crushedpixel.replaymod.gui.replayeditor; 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.GuiConstants;
import eu.crushedpixel.replaymod.gui.elements.GuiDropdown; import eu.crushedpixel.replaymod.gui.elements.GuiDropdown;
import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry; 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;
}

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