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:
@@ -119,7 +119,7 @@ jar {
|
||||
manifest {
|
||||
attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
'TweakOrder': '0',
|
||||
'MixinConfigs': 'mixins.replaymod.json',
|
||||
'MixinConfigs': 'mixins.replaymod.json,mixins.recording.replaymod.json',
|
||||
'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin',
|
||||
'FMLAT': 'replaymod_at.cfg'
|
||||
}
|
||||
|
||||
Binary file not shown.
60
src/main/java/com/replaymod/core/KeyBindingRegistry.java
Normal file
60
src/main/java/com/replaymod/core/KeyBindingRegistry.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,30 @@
|
||||
package eu.crushedpixel.replaymod;
|
||||
package com.replaymod.core;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||
import com.replaymod.replay.ReplaySender;
|
||||
import eu.crushedpixel.replaymod.api.ApiClient;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
|
||||
import eu.crushedpixel.replaymod.events.handlers.*;
|
||||
import eu.crushedpixel.replaymod.events.handlers.CrosshairRenderHandler;
|
||||
import eu.crushedpixel.replaymod.events.handlers.GuiEventHandler;
|
||||
import eu.crushedpixel.replaymod.events.handlers.MouseInputHandler;
|
||||
import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener;
|
||||
import eu.crushedpixel.replaymod.events.handlers.keyboard.KeyInputHandler;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiReplayDownloading;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.holders.KeyframeSet;
|
||||
import eu.crushedpixel.replaymod.localization.LocalizedResourcePack;
|
||||
import eu.crushedpixel.replaymod.online.authentication.ConfigurationAuthData;
|
||||
import eu.crushedpixel.replaymod.online.urischeme.UriScheme;
|
||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||
import eu.crushedpixel.replaymod.registry.*;
|
||||
import eu.crushedpixel.replaymod.renderer.CustomObjectRenderer;
|
||||
import eu.crushedpixel.replaymod.renderer.InvisibilityRender;
|
||||
import eu.crushedpixel.replaymod.renderer.PathPreviewRenderer;
|
||||
import eu.crushedpixel.replaymod.renderer.SpectatorRenderer;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
||||
import eu.crushedpixel.replaymod.settings.EncodingPreset;
|
||||
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||
import eu.crushedpixel.replaymod.sound.SoundHandler;
|
||||
import eu.crushedpixel.replaymod.timer.ReplayTimer;
|
||||
import eu.crushedpixel.replaymod.utils.OpenGLUtils;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import eu.crushedpixel.replaymod.utils.TooltipRenderer;
|
||||
import eu.crushedpixel.replaymod.video.rendering.Pipelines;
|
||||
import lombok.Getter;
|
||||
@@ -38,6 +34,7 @@ import net.minecraft.client.resources.IResourcePack;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
@@ -50,6 +47,7 @@ import net.minecraftforge.fml.common.ModContainer;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -61,14 +59,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
import static org.apache.commons.io.FileUtils.forceDelete;
|
||||
import static org.apache.commons.io.FileUtils.listFiles;
|
||||
|
||||
@Mod(modid = ReplayMod.MODID, useMetadata = true)
|
||||
@Mod(modid = ReplayMod.MOD_ID, useMetadata = true)
|
||||
public class ReplayMod {
|
||||
|
||||
public static ModContainer getContainer() {
|
||||
return Loader.instance().getIndexedModList().get(MODID);
|
||||
return Loader.instance().getIndexedModList().get(MOD_ID);
|
||||
}
|
||||
|
||||
@Getter(lazy = true)
|
||||
@@ -85,14 +80,16 @@ public class ReplayMod {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public static final String MODID = "replaymod";
|
||||
public static final String MOD_ID = "replaymod";
|
||||
|
||||
public static final ResourceLocation TEXTURE = new ResourceLocation("replaymod", "replay_gui.png");
|
||||
public static final int TEXTURE_SIZE = 128;
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
public static GuiEventHandler guiEventHandler;
|
||||
public static GuiReplayOverlay overlay;
|
||||
public static ReplaySettings replaySettings;
|
||||
public static Configuration config;
|
||||
public static boolean firstMainMenu = true;
|
||||
public static RecordingHandler recordingHandler;
|
||||
public static ChatMessageHandler chatMessageHandler = new ChatMessageHandler();
|
||||
public static KeyInputHandler keyInputHandler = new KeyInputHandler();
|
||||
public static MouseInputHandler mouseInputHandler = new MouseInputHandler();
|
||||
@@ -111,13 +108,30 @@ public class ReplayMod {
|
||||
public static CrosshairRenderHandler crosshairRenderHandler;
|
||||
public static ApiClient apiClient;
|
||||
|
||||
private final KeyBindingRegistry keyBindingRegistry = new KeyBindingRegistry();
|
||||
private final SettingsRegistry settingsRegistry = new SettingsRegistry();
|
||||
|
||||
@Getter
|
||||
private static boolean latestModVersion = true;
|
||||
|
||||
// The instance of your mod that Forge uses.
|
||||
@Instance(value = "ReplayModID")
|
||||
@Instance(MOD_ID)
|
||||
public static ReplayMod instance;
|
||||
|
||||
public KeyBindingRegistry getKeyBindingRegistry() {
|
||||
return keyBindingRegistry;
|
||||
}
|
||||
|
||||
public SettingsRegistry getSettingsRegistry() {
|
||||
return settingsRegistry;
|
||||
}
|
||||
|
||||
public File getReplayFolder() throws IOException {
|
||||
File folder = new File(replaySettings.getRecordingPath());
|
||||
FileUtils.forceMkdir(folder);
|
||||
return folder;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
try {
|
||||
@@ -137,6 +151,7 @@ public class ReplayMod {
|
||||
|
||||
config = new Configuration(event.getSuggestedConfigurationFile());
|
||||
config.load();
|
||||
settingsRegistry.setConfiguration(config);
|
||||
ConfigurationAuthData authData = new ConfigurationAuthData(config);
|
||||
apiClient = new ApiClient(authData);
|
||||
authData.load(apiClient);
|
||||
@@ -144,7 +159,6 @@ public class ReplayMod {
|
||||
uploadedFileHandler = new UploadedFileHandler(event.getModConfigurationDirectory());
|
||||
|
||||
replaySettings = new ReplaySettings();
|
||||
replaySettings.readValues();
|
||||
|
||||
downloadedFileHandler = new DownloadedFileHandler();
|
||||
favoritedFileHandler = new FavoritedFileHandler();
|
||||
@@ -164,27 +178,22 @@ public class ReplayMod {
|
||||
@EventHandler
|
||||
public void init(FMLInitializationEvent event) {
|
||||
mc.timer = new ReplayTimer();
|
||||
overlay = new GuiReplayOverlay();
|
||||
|
||||
FMLCommonHandler.instance().bus().register(new ConnectionEventHandler());
|
||||
MinecraftForge.EVENT_BUS.register(guiEventHandler = new GuiEventHandler());
|
||||
|
||||
FMLCommonHandler.instance().bus().register(keyInputHandler);
|
||||
FMLCommonHandler.instance().bus().register(keyBindingRegistry);
|
||||
FMLCommonHandler.instance().bus().register(mouseInputHandler);
|
||||
MinecraftForge.EVENT_BUS.register(mouseInputHandler);
|
||||
|
||||
recordingHandler = new RecordingHandler();
|
||||
FMLCommonHandler.instance().bus().register(recordingHandler);
|
||||
MinecraftForge.EVENT_BUS.register(recordingHandler);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void postInit(FMLPostInitializationEvent event) throws IOException {
|
||||
settingsRegistry.save(); // Save default values to disk
|
||||
|
||||
if(!FMLClientHandler.instance().hasOptifine())
|
||||
GameSettings.Options.RENDER_DISTANCE.setValueMax(64f);
|
||||
|
||||
overlay.register();
|
||||
|
||||
TickAndRenderListener tarl = new TickAndRenderListener();
|
||||
FMLCommonHandler.instance().bus().register(tarl);
|
||||
MinecraftForge.EVENT_BUS.register(tarl);
|
||||
@@ -212,9 +221,6 @@ public class ReplayMod {
|
||||
skinMap.put("default", new InvisibilityRender(mc.getRenderManager()));
|
||||
skinMap.put("slim", new InvisibilityRender(mc.getRenderManager(), true));
|
||||
|
||||
//clean up replay_recordings folder
|
||||
removeTmcprFiles();
|
||||
|
||||
Thread localizedResourcePackLoader = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -330,36 +336,42 @@ public class ReplayMod {
|
||||
}
|
||||
|
||||
System.out.println("Loading replay...");
|
||||
ReplayHandler.startReplay(file, false);
|
||||
|
||||
int index = 0;
|
||||
if (path != null) {
|
||||
for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) {
|
||||
if (set.getName().equals(path)) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (index >= ReplayHandler.getKeyframeRepository().length) {
|
||||
throw new IllegalArgumentException("No path named \"" + path + "\".");
|
||||
}
|
||||
} else if (ReplayHandler.getKeyframeRepository().length == 0) {
|
||||
throw new IllegalArgumentException("Replay file has no paths defined.");
|
||||
}
|
||||
ReplayHandler.useKeyframePresetFromRepository(index);
|
||||
|
||||
System.out.println("Rendering started...");
|
||||
try {
|
||||
ReplayProcess.startReplayProcess(options, true);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
FMLCommonHandler.instance().exitJava(1, false);
|
||||
}
|
||||
if (mc.hasCrashed) {
|
||||
System.out.println(mc.crashReporter.getCompleteReport());
|
||||
}
|
||||
System.out.println("Rendering done. Shutting down...");
|
||||
mc.shutdown();
|
||||
// TODO
|
||||
// try {
|
||||
// ReplayHandler.startReplay(file, false);
|
||||
// } catch (Throwable t) {
|
||||
// t.printStackTrace();
|
||||
// FMLCommonHandler.instance().exitJava(1, false);
|
||||
// }
|
||||
//
|
||||
// int index = 0;
|
||||
// if (path != null) {
|
||||
// for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) {
|
||||
// if (set.getName().equals(path)) {
|
||||
// break;
|
||||
// }
|
||||
// index++;
|
||||
// }
|
||||
// if (index >= ReplayHandler.getKeyframeRepository().length) {
|
||||
// throw new IllegalArgumentException("No path named \"" + path + "\".");
|
||||
// }
|
||||
// } else if (ReplayHandler.getKeyframeRepository().length == 0) {
|
||||
// throw new IllegalArgumentException("Replay file has no paths defined.");
|
||||
// }
|
||||
// ReplayHandler.useKeyframePresetFromRepository(index);
|
||||
//
|
||||
// System.out.println("Rendering started...");
|
||||
// try {
|
||||
// ReplayProcess.startReplayProcess(options, true);
|
||||
// } catch (Throwable t) {
|
||||
// t.printStackTrace();
|
||||
// FMLCommonHandler.instance().exitJava(1, false);
|
||||
// }
|
||||
// if (mc.hasCrashed) {
|
||||
// System.out.println(mc.crashReporter.getCompleteReport());
|
||||
// }
|
||||
// System.out.println("Rendering done. Shutting down...");
|
||||
// mc.shutdown();
|
||||
}
|
||||
}, null));
|
||||
}
|
||||
@@ -422,7 +434,8 @@ public class ReplayMod {
|
||||
new GuiReplayDownloading(info).display();
|
||||
} else {
|
||||
try {
|
||||
ReplayHandler.startReplay(file);
|
||||
// TODO
|
||||
// ReplayHandler.startReplay(file);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -434,16 +447,4 @@ public class ReplayMod {
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTmcprFiles() {
|
||||
try {
|
||||
File folder = ReplayFileIO.getReplayFolder();
|
||||
|
||||
for (File file : listFiles(folder, new String[]{ReplayFile.TEMP_FILE_EXTENSION.substring(1)}, false)) {
|
||||
forceDelete(file);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
133
src/main/java/com/replaymod/core/SettingsRegistry.java
Normal file
133
src/main/java/com/replaymod/core/SettingsRegistry.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
src/main/java/com/replaymod/core/gui/GuiReplaySettings.java
Normal file
75
src/main/java/com/replaymod/core/gui/GuiReplaySettings.java
Normal 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;
|
||||
}
|
||||
}
|
||||
7
src/main/java/com/replaymod/extras/Extra.java
Normal file
7
src/main/java/com/replaymod/extras/Extra.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package com.replaymod.extras;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
|
||||
public interface Extra {
|
||||
void register(ReplayMod mod) throws Exception;
|
||||
}
|
||||
101
src/main/java/com/replaymod/extras/HotkeyButtons.java
Normal file
101
src/main/java/com/replaymod/extras/HotkeyButtons.java
Normal 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));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/main/java/com/replaymod/extras/ReplayModExtras.java
Normal file
44
src/main/java/com/replaymod/extras/ReplayModExtras.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
17
src/main/java/com/replaymod/recording/Setting.java
Normal file
17
src/main/java/com/replaymod/recording/Setting.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
package eu.crushedpixel.replaymod.gui.overlay;
|
||||
package com.replaymod.recording.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE;
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
||||
|
||||
/**
|
||||
* Renders overlay during recording.
|
||||
@@ -22,6 +23,14 @@ public class GuiRecordingOverlay {
|
||||
this.mc = mc;
|
||||
}
|
||||
|
||||
public void register() {
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
MinecraftForge.EVENT_BUS.unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the recording icon and text in the top left corner of the screen.
|
||||
* @param event Rendered post game overlay
|
||||
@@ -32,7 +41,7 @@ public class GuiRecordingOverlay {
|
||||
if(ReplayMod.replaySettings.showRecordingIndicator()) {
|
||||
FontRenderer fontRenderer = mc.fontRendererObj;
|
||||
fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff);
|
||||
mc.renderEngine.bindTexture(replay_gui);
|
||||
mc.renderEngine.bindTexture(TEXTURE);
|
||||
GlStateManager.resetColor();
|
||||
GlStateManager.enableAlpha();
|
||||
Gui.drawModalRectWithCustomSizedTexture(10, 10, 58, 20, 16, 16, TEXTURE_SIZE, TEXTURE_SIZE);
|
||||
@@ -1,79 +1,53 @@
|
||||
package eu.crushedpixel.replaymod.recording;
|
||||
package com.replaymod.recording.handler;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.recording.Setting;
|
||||
import com.replaymod.recording.gui.GuiRecordingOverlay;
|
||||
import com.replaymod.recording.packet.PacketListener;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import de.johni0702.replaystudio.replay.ZipReplayFile;
|
||||
import de.johni0702.replaystudio.studio.ReplayStudio;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler.ChatMessageType;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiRecordingOverlay;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.WorldType;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;
|
||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Handles connection events and initiates recording if enabled.
|
||||
*/
|
||||
public class ConnectionEventHandler {
|
||||
|
||||
private static final String packetHandlerKey = "packet_handler";
|
||||
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
||||
private static PacketListener packetListener = null;
|
||||
private static boolean isRecording = false;
|
||||
private final GuiRecordingOverlay guiOverlay = new GuiRecordingOverlay(Minecraft.getMinecraft());
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private final Logger logger;
|
||||
private final ReplayMod core;
|
||||
|
||||
public static boolean isRecording() {
|
||||
return isRecording;
|
||||
}
|
||||
private RecordingEventHandler recordingEventHandler;
|
||||
private PacketListener packetListener;
|
||||
private GuiRecordingOverlay guiOverlay;
|
||||
|
||||
public static void notifyServerPaused() {
|
||||
if (packetListener != null) {
|
||||
packetListener.serverWasPaused = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertPacket(Packet packet) {
|
||||
if(!isRecording || packetListener == null) {
|
||||
String reason = isRecording ? " (recording)" : " (null)";
|
||||
logger.error("Invalid attempt to insert Packet!" + reason);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
packetListener.saveOnly(packet);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMarker() {
|
||||
if(!isRecording || packetListener == null) {
|
||||
String reason = isRecording ? " (recording)" : " (null)";
|
||||
logger.error("Invalid attempt to insert MarkerKeyframe!" + reason);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
packetListener.addMarker();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public ConnectionEventHandler(Logger logger, ReplayMod core) {
|
||||
this.logger = logger;
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onConnectedToServerEvent(ClientConnectedToServerEvent event) {
|
||||
ReplayMod.chatMessageHandler.initialize();
|
||||
ReplayMod.recordingHandler.resetVars();
|
||||
|
||||
try {
|
||||
if(event.isLocal) {
|
||||
@@ -81,16 +55,17 @@ public class ConnectionEventHandler {
|
||||
logger.info("Debug World recording is not supported.");
|
||||
return;
|
||||
}
|
||||
if(!ReplayMod.replaySettings.isEnableRecordingSingleplayer()) {
|
||||
if(!core.getSettingsRegistry().get(Setting.RECORD_SINGLEPLAYER)) {
|
||||
logger.info("Singleplayer Recording is disabled");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!ReplayMod.replaySettings.isEnableRecordingServer()) {
|
||||
if(!core.getSettingsRegistry().get(Setting.RECORD_SERVER)) {
|
||||
logger.info("Multiplayer Recording is disabled");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NetworkManager nm = event.manager;
|
||||
String worldName;
|
||||
if(event.isLocal) {
|
||||
@@ -101,17 +76,22 @@ public class ConnectionEventHandler {
|
||||
Channel channel = nm.channel();
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
|
||||
File folder = ReplayFileIO.getReplayFolder();
|
||||
File folder = core.getReplayFolder();
|
||||
|
||||
String fileName = sdf.format(Calendar.getInstance().getTime());
|
||||
File currentFile = new File(folder, fileName + ReplayFile.TEMP_FILE_EXTENSION);
|
||||
String name = sdf.format(Calendar.getInstance().getTime());
|
||||
File currentFile = new File(folder, name + ".mcpr");
|
||||
ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), currentFile);
|
||||
|
||||
packetListener = new PacketListener(replayFile, name, worldName, System.currentTimeMillis(), event.isLocal);
|
||||
pipeline.addBefore(packetHandlerKey, "replay_recorder", packetListener);
|
||||
|
||||
recordingEventHandler = new RecordingEventHandler(packetListener);
|
||||
recordingEventHandler.register();
|
||||
|
||||
guiOverlay = new GuiRecordingOverlay(mc);
|
||||
guiOverlay.register();
|
||||
|
||||
pipeline.addBefore(packetHandlerKey, "replay_recorder", packetListener = new PacketListener
|
||||
(currentFile, fileName, worldName, System.currentTimeMillis(), event.isLocal));
|
||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingstarted", ChatMessageType.INFORMATION);
|
||||
isRecording = true;
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(guiOverlay);
|
||||
} catch(Exception e) {
|
||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.recordingfailed", ChatMessageType.WARNING);
|
||||
e.printStackTrace();
|
||||
@@ -120,11 +100,18 @@ public class ConnectionEventHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) {
|
||||
if (isRecording) {
|
||||
isRecording = false;
|
||||
MinecraftForge.EVENT_BUS.unregister(guiOverlay);
|
||||
if (packetListener != null) {
|
||||
guiOverlay.unregister();
|
||||
guiOverlay = null;
|
||||
recordingEventHandler.unregister();
|
||||
recordingEventHandler = null;
|
||||
packetListener = null;
|
||||
|
||||
ReplayMod.chatMessageHandler.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public PacketListener getPacketListener() {
|
||||
return packetListener;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
package com.replaymod.recording.handler;
|
||||
|
||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||
import com.replaymod.recording.packet.PacketListener;
|
||||
import eu.crushedpixel.replaymod.utils.Objects;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -13,39 +13,60 @@ import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.*;
|
||||
import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerUseItemEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent.ItemPickupEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;
|
||||
|
||||
public class RecordingHandler {
|
||||
public class RecordingEventHandler {
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private Double lastX = null, lastY = null, lastZ = null;
|
||||
private final PacketListener packetListener;
|
||||
|
||||
private Double lastX, lastY, lastZ;
|
||||
private ItemStack[] playerItems = new ItemStack[5];
|
||||
private int ticksSinceLastCorrection = 0;
|
||||
private boolean wasSleeping = false;
|
||||
private int ticksSinceLastCorrection;
|
||||
private boolean wasSleeping;
|
||||
private int lastRiding = -1;
|
||||
private Integer rotationYawHeadBefore = null;
|
||||
private Integer rotationYawHeadBefore;
|
||||
|
||||
public RecordingEventHandler(PacketListener packetListener) {
|
||||
this.packetListener = packetListener;
|
||||
}
|
||||
|
||||
public void register() {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
((RecordingEventSender) mc.renderGlobal).setRecordingEventHandler(this);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
MinecraftForge.EVENT_BUS.unregister(this);
|
||||
RecordingEventSender recordingEventSender = ((RecordingEventSender) mc.renderGlobal);
|
||||
if (recordingEventSender.getRecordingEventHandler() == this) {
|
||||
recordingEventSender.setRecordingEventHandler(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPlayerJoin() {
|
||||
try {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
|
||||
ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer));
|
||||
packetListener.save(spawnPlayer(mc.thePlayer));
|
||||
} catch(Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPlayerRespawn() {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
ConnectionEventHandler.insertPacket(spawnPlayer(mc.thePlayer));
|
||||
packetListener.save(spawnPlayer(mc.thePlayer));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -81,18 +102,10 @@ public class RecordingHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void resetVars() {
|
||||
lastX = lastY = lastZ = null;
|
||||
rotationYawHeadBefore = null;
|
||||
playerItems = new ItemStack[5];
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPlayerTick(PlayerTickEvent e) {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
if(e.player != mc.thePlayer) return;
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
|
||||
boolean force = false;
|
||||
if(lastX == null || lastY == null || lastZ == null) {
|
||||
@@ -133,7 +146,7 @@ public class RecordingHandler {
|
||||
newYaw, newPitch, e.player.onGround);
|
||||
}
|
||||
|
||||
ConnectionEventHandler.insertPacket(packet);
|
||||
packetListener.save(packet);
|
||||
|
||||
//HEAD POS
|
||||
int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F));
|
||||
@@ -148,13 +161,13 @@ public class RecordingHandler {
|
||||
|
||||
head.readPacketData(pb1);
|
||||
|
||||
ConnectionEventHandler.insertPacket(head);
|
||||
packetListener.save(head);
|
||||
|
||||
rotationYawHeadBefore = rotationYawHead;
|
||||
}
|
||||
|
||||
S12PacketEntityVelocity vel = new S12PacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ);
|
||||
ConnectionEventHandler.insertPacket(vel);
|
||||
packetListener.save(vel);
|
||||
|
||||
//Animation Packets
|
||||
//Swing Animation
|
||||
@@ -169,7 +182,7 @@ public class RecordingHandler {
|
||||
|
||||
pac.readPacketData(pb);
|
||||
|
||||
ConnectionEventHandler.insertPacket(pac);
|
||||
packetListener.save(pac);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -179,13 +192,13 @@ public class RecordingHandler {
|
||||
found.add(pe.getPotionID());
|
||||
if(lastEffects.contains(found)) continue;
|
||||
S1DPacketEntityEffect pee = new S1DPacketEntityEffect(entityID, pe);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
for(int id : lastEffects) {
|
||||
if(!found.contains(id)) {
|
||||
S1EPacketRemoveEntityEffect pre = new S1EPacketRemoveEntityEffect(entityID, new PotionEffect(id, 0));
|
||||
ConnectionEventHandler.insertPacket(pre);
|
||||
packetListener.save(pre);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,31 +209,31 @@ public class RecordingHandler {
|
||||
if(playerItems[0] != mc.thePlayer.getHeldItem()) {
|
||||
playerItems[0] = mc.thePlayer.getHeldItem();
|
||||
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 0, playerItems[0]);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
if(playerItems[1] != mc.thePlayer.inventory.armorInventory[0]) {
|
||||
playerItems[1] = mc.thePlayer.inventory.armorInventory[0];
|
||||
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 1, playerItems[1]);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
if(playerItems[2] != mc.thePlayer.inventory.armorInventory[1]) {
|
||||
playerItems[2] = mc.thePlayer.inventory.armorInventory[1];
|
||||
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 2, playerItems[2]);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
if(playerItems[3] != mc.thePlayer.inventory.armorInventory[2]) {
|
||||
playerItems[3] = mc.thePlayer.inventory.armorInventory[2];
|
||||
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 3, playerItems[3]);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
if(playerItems[4] != mc.thePlayer.inventory.armorInventory[3]) {
|
||||
playerItems[4] = mc.thePlayer.inventory.armorInventory[3];
|
||||
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 4, playerItems[4]);
|
||||
ConnectionEventHandler.insertPacket(pee);
|
||||
packetListener.save(pee);
|
||||
}
|
||||
|
||||
//Leaving Ride
|
||||
@@ -244,7 +257,7 @@ public class RecordingHandler {
|
||||
|
||||
pea.readPacketData(pbuf);
|
||||
|
||||
ConnectionEventHandler.insertPacket(pea);
|
||||
packetListener.save(pea);
|
||||
}
|
||||
|
||||
//Sleeping
|
||||
@@ -259,7 +272,7 @@ public class RecordingHandler {
|
||||
|
||||
pac.readPacketData(pb);
|
||||
|
||||
ConnectionEventHandler.insertPacket(pac);
|
||||
packetListener.save(pac);
|
||||
|
||||
wasSleeping = false;
|
||||
}
|
||||
@@ -271,9 +284,8 @@ public class RecordingHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPickupItem(ItemPickupEvent event) {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
ConnectionEventHandler.insertPacket(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
|
||||
packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -281,7 +293,6 @@ public class RecordingHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onStartEating(PlayerUseItemEvent.Start event) {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
if(!event.entityPlayer.isEating()) return;
|
||||
S0BPacketAnimation packet = new S0BPacketAnimation();
|
||||
@@ -294,7 +305,7 @@ public class RecordingHandler {
|
||||
|
||||
packet.readPacketData(pb);
|
||||
|
||||
ConnectionEventHandler.insertPacket(packet);
|
||||
packetListener.save(packet);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -302,13 +313,11 @@ public class RecordingHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onSleep(PlayerSleepInBedEvent event) {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
if(event.entityPlayer != mc.thePlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println(event.getResult());
|
||||
S0APacketUseBed pub = new S0APacketUseBed();
|
||||
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
@@ -319,7 +328,7 @@ public class RecordingHandler {
|
||||
|
||||
pub.readPacketData(pbuf);
|
||||
|
||||
ConnectionEventHandler.insertPacket(pub);
|
||||
packetListener.save(pub);
|
||||
|
||||
wasSleeping = true;
|
||||
|
||||
@@ -330,7 +339,6 @@ public class RecordingHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void enterMinecart(MinecartInteractEvent event) {
|
||||
if(!ConnectionEventHandler.isRecording()) return;
|
||||
try {
|
||||
if(event.player != mc.thePlayer) {
|
||||
return;
|
||||
@@ -347,7 +355,7 @@ public class RecordingHandler {
|
||||
|
||||
pea.readPacketData(pbuf);
|
||||
|
||||
ConnectionEventHandler.insertPacket(pea);
|
||||
packetListener.save(pea);
|
||||
|
||||
lastRiding = event.minecart.getEntityId();
|
||||
} catch(Exception e) {
|
||||
@@ -355,15 +363,26 @@ public class RecordingHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) {
|
||||
EntityPlayer thePlayer = mc.thePlayer;
|
||||
if (thePlayer != null && breakerId == thePlayer.getEntityId()) {
|
||||
packetListener.save(new S25PacketBlockBreakAnim(breakerId, pos, progress));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void checkForGamePaused(TickEvent.RenderTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.START) return;
|
||||
if (!ConnectionEventHandler.isRecording()) return;
|
||||
if (mc.isIntegratedServerRunning()) {
|
||||
IntegratedServer server = mc.getIntegratedServer();
|
||||
if (server != null && server.isGamePaused) {
|
||||
ConnectionEventHandler.notifyServerPaused();
|
||||
packetListener.serverWasPaused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface RecordingEventSender {
|
||||
void setRecordingEventHandler(RecordingEventHandler recordingEventHandler);
|
||||
RecordingEventHandler getRecordingEventHandler();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package eu.crushedpixel.replaymod.mixin;
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||
import com.replaymod.recording.handler.RecordingEventHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.S07PacketRespawn;
|
||||
import net.minecraft.network.play.server.S38PacketPlayerListItem;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@@ -16,6 +16,13 @@ import java.util.List;
|
||||
@Mixin(NetHandlerPlayClient.class)
|
||||
public abstract class MixinNetHandlerPlayClient {
|
||||
|
||||
@Shadow
|
||||
private Minecraft gameController;
|
||||
|
||||
public RecordingEventHandler getRecordingEventHandler() {
|
||||
return ((RecordingEventHandler.RecordingEventSender) gameController.renderGlobal).getRecordingEventHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the own player entity joining the world.
|
||||
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id
|
||||
@@ -25,12 +32,13 @@ public abstract class MixinNetHandlerPlayClient {
|
||||
*/
|
||||
@Inject(method = "handlePlayerListItem", at=@At("RETURN"))
|
||||
public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) {
|
||||
if (ConnectionEventHandler.isRecording() && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) {
|
||||
RecordingEventHandler handler = getRecordingEventHandler();
|
||||
if (handler != null && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a();
|
||||
for (S38PacketPlayerListItem.AddPlayerData data : dataList) {
|
||||
if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())) {
|
||||
ReplayMod.recordingHandler.onPlayerJoin();
|
||||
handler.onPlayerJoin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,8 +53,9 @@ public abstract class MixinNetHandlerPlayClient {
|
||||
*/
|
||||
@Inject(method = "handleRespawn", at=@At("RETURN"))
|
||||
public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) {
|
||||
if (ConnectionEventHandler.isRecording()) {
|
||||
ReplayMod.recordingHandler.onPlayerRespawn();
|
||||
RecordingEventHandler handler = getRecordingEventHandler();
|
||||
if (handler != null) {
|
||||
handler.onPlayerRespawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
182
src/main/java/com/replaymod/recording/packet/DataListener.java
Executable file
182
src/main/java/com/replaymod/recording/packet/DataListener.java
Executable 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package eu.crushedpixel.replaymod.recording;
|
||||
package com.replaymod.recording.packet;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
|
||||
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.holders.Marker;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.replay.Restrictions;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -35,7 +31,6 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -50,11 +45,11 @@ public class PacketListener extends DataListener {
|
||||
|
||||
private int nextRequestId;
|
||||
|
||||
public PacketListener(File file, String name, String worldName, long startTime, boolean singleplayer) throws FileNotFoundException {
|
||||
public PacketListener(ReplayFile file, String name, String worldName, long startTime, boolean singleplayer) throws IOException {
|
||||
super(file, name, worldName, startTime, singleplayer);
|
||||
}
|
||||
|
||||
public void saveOnly(Packet packet) {
|
||||
public void save(Packet packet) {
|
||||
try {
|
||||
if(packet instanceof S0CPacketSpawnPlayer) {
|
||||
UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c();
|
||||
@@ -101,7 +96,7 @@ public class PacketListener extends DataListener {
|
||||
if (packet instanceof S48PacketResourcePackSend) {
|
||||
S48PacketResourcePackSend p = (S48PacketResourcePackSend) packet;
|
||||
int requestId = handleResourcePack(p);
|
||||
saveOnly(new S48PacketResourcePackSend("replay://" + requestId, ""));
|
||||
save(new S48PacketResourcePackSend("replay://" + requestId, ""));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -216,17 +211,6 @@ public class PacketListener extends DataListener {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public void addMarker() {
|
||||
AdvancedPosition pos = new AdvancedPosition(Minecraft.getMinecraft().getRenderViewEntity());
|
||||
int timestamp = (int) (System.currentTimeMillis() - startTime);
|
||||
|
||||
Keyframe<Marker> marker = new Keyframe<Marker>(timestamp, new Marker(null, pos));
|
||||
|
||||
markers.add(marker);
|
||||
|
||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.addedmarker", ChatMessageHandler.ChatMessageType.INFORMATION);
|
||||
}
|
||||
|
||||
private void downloadResourcePackFuture(int requestId, String url, final String hash) {
|
||||
Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() {
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package eu.crushedpixel.replaymod.recording;
|
||||
package com.replaymod.recording.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -1,14 +1,12 @@
|
||||
package eu.crushedpixel.replaymod.entities;
|
||||
package com.replaymod.replay;
|
||||
|
||||
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
||||
import eu.crushedpixel.replaymod.replay.LesserDataWatcher;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.stats.StatFileWriter;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.MathHelper;
|
||||
@@ -48,12 +46,12 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
private Vec3 dirBefore;
|
||||
private double motion;
|
||||
|
||||
public float roll;
|
||||
|
||||
private long lastCall = 0;
|
||||
|
||||
private boolean speedup = false;
|
||||
|
||||
public static UUID spectating;
|
||||
|
||||
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) {
|
||||
super(mcIn, worldIn, netHandlerPlayClient, statFileWriter);
|
||||
}
|
||||
@@ -133,11 +131,11 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
this.moveAbsolute(pos.getX(), pos.getY(), pos.getZ());
|
||||
rotationPitch = prevRotationPitch = (float)pos.getPitch();
|
||||
rotationYaw = prevRotationYaw = (float)pos.getYaw();
|
||||
roll = (float) pos.getRoll();
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
public void moveAbsolute(double x, double y, double z) {
|
||||
if(ReplayHandler.isInPath()) return;
|
||||
this.lastTickPosX = this.prevPosX = this.posX = x;
|
||||
this.lastTickPosY = this.prevPosY = this.posY = y;
|
||||
this.lastTickPosZ = this.prevPosZ = this.posZ = z;
|
||||
@@ -145,7 +143,6 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
}
|
||||
|
||||
public void moveRelative(double x, double y, double z) {
|
||||
if(ReplayHandler.isInPath()) return;
|
||||
this.lastTickPosX = this.prevPosX = this.posX = this.posX + x;
|
||||
this.lastTickPosY = this.prevPosY = this.posY = this.posY + y;
|
||||
this.lastTickPosZ = this.prevPosZ = this.posZ = this.posZ + z;
|
||||
@@ -155,6 +152,7 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
public void movePath(AdvancedPosition pos) {
|
||||
this.prevRotationPitch = this.rotationPitch = (float)pos.getPitch();
|
||||
this.prevRotationYaw = this.rotationYaw = (float)pos.getYaw();
|
||||
this.roll = (float) pos.getRoll();
|
||||
this.lastTickPosX = this.prevPosX = this.posX = pos.getX();
|
||||
this.lastTickPosY = this.prevPosY = this.posY = pos.getY();
|
||||
this.lastTickPosZ = this.prevPosZ = this.posZ = pos.getZ();
|
||||
@@ -166,7 +164,7 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
posX + width / 2, posY + height, posZ + width / 2));
|
||||
}
|
||||
|
||||
private void updatePos(Entity to) {
|
||||
protected void updatePos(Entity to) {
|
||||
prevPosX = to.prevPosX;
|
||||
prevPosY = to.prevPosY;
|
||||
prevPosZ = to.prevPosZ;
|
||||
@@ -188,9 +186,6 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
|
||||
@Override
|
||||
public void setAngles(float yaw, float pitch) {
|
||||
if (ReplayHandler.isInPath()) {
|
||||
return; // Disallow camera movement by mouse during path preview
|
||||
}
|
||||
this.rotationYaw = (float) ((double) this.rotationYaw + (double) yaw * 0.15D);
|
||||
this.rotationPitch = (float) ((double) this.rotationPitch - (double) pitch * 0.15D);
|
||||
this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F);
|
||||
@@ -202,6 +197,7 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
public void onUpdate() {
|
||||
Entity view = mc.getRenderViewEntity();
|
||||
if (view != null) {
|
||||
UUID spectating = ReplayModReplay.instance.getReplayHandler().spectating;
|
||||
if (spectating != null && (view.getUniqueID() != spectating || view.worldObj != worldObj)) {
|
||||
view = worldObj.getPlayerEntityByUUID(spectating);
|
||||
if (view != null) {
|
||||
@@ -263,20 +259,6 @@ public class CameraEntity extends EntityPlayerSP {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void spectate(Entity e) {
|
||||
if (e == null || e == this) {
|
||||
spectating = null;
|
||||
e = this;
|
||||
} else if (e instanceof EntityPlayer) {
|
||||
spectating = e.getUniqueID();
|
||||
}
|
||||
|
||||
if (mc.getRenderViewEntity() != e) {
|
||||
mc.setRenderViewEntity(e);
|
||||
updatePos(e);
|
||||
}
|
||||
}
|
||||
|
||||
public enum MoveDirection {
|
||||
UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD
|
||||
}
|
||||
349
src/main/java/com/replaymod/replay/ReplayHandler.java
Executable file
349
src/main/java/com/replaymod/replay/ReplayHandler.java
Executable 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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/replaymod/replay/ReplayModReplay.java
Normal file
58
src/main/java/com/replaymod/replay/ReplayModReplay.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
package com.replaymod.replay;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.holders.PacketData;
|
||||
import eu.crushedpixel.replaymod.replay.Restrictions;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -67,6 +67,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
S39PacketPlayerAbilities.class,
|
||||
S45PacketTitle.class);
|
||||
|
||||
/**
|
||||
* The replay handler responsible for the current replay.
|
||||
*/
|
||||
private final ReplayHandler replayHandler;
|
||||
|
||||
/**
|
||||
* Whether to work in async mode.
|
||||
*
|
||||
@@ -156,10 +161,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
* @param asyncMode {@code true} for async mode, {@code false} otherwise
|
||||
* @see #asyncMode
|
||||
*/
|
||||
public ReplaySender(ReplayFile file, boolean asyncMode) {
|
||||
public ReplaySender(ReplayHandler replayHandler, ReplayFile file, boolean asyncMode) throws IOException {
|
||||
this.replayHandler = replayHandler;
|
||||
this.replayFile = file;
|
||||
this.asyncMode = asyncMode;
|
||||
this.replayLength = file.metadata().get().getDuration();
|
||||
this.replayLength = file.getMetaData().getDuration();
|
||||
|
||||
if (asyncMode) {
|
||||
new Thread(asyncSender, "replaymod-async-sender").start();
|
||||
@@ -296,7 +302,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
if (p instanceof S3FPacketCustomPayload) {
|
||||
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
|
||||
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) {
|
||||
final String unknown = ReplayHandler.getRestrictions().handle(packet);
|
||||
final String unknown = replayHandler.getRestrictions().handle(packet);
|
||||
if (unknown == null) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -306,7 +312,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
mc.addScheduledTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReplayHandler.endReplay();
|
||||
try {
|
||||
replayHandler.endReplay();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mc.displayGuiScreen(new GuiErrorScreen(
|
||||
I18n.format("replaymod.error.unknownrestriction1"),
|
||||
I18n.format("replaymod.error.unknownrestriction2", unknown)
|
||||
@@ -327,12 +337,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
if(BAD_PACKETS.contains(p.getClass())) return null;
|
||||
|
||||
if(ReplayProcess.isVideoRecording() && ReplayHandler.isInPath()) {
|
||||
if(p instanceof S29PacketSoundEffect) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
convertLegacyEntityIds(p);
|
||||
|
||||
if(p instanceof S48PacketResourcePackSend) {
|
||||
@@ -340,13 +344,13 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
String url = packet.func_179783_a();
|
||||
if (url.startsWith("replay://")) {
|
||||
int id = Integer.parseInt(url.substring("replay://".length()));
|
||||
Map<Integer, String> index = replayFile.resourcePackIndex().get();
|
||||
Map<Integer, String> index = replayFile.getResourcePackIndex();
|
||||
if (index != null) {
|
||||
String hash = index.get(id);
|
||||
if (hash != null) {
|
||||
File file = new File(tempResourcePackFolder, hash + ".zip");
|
||||
if (!file.exists()) {
|
||||
IOUtils.copy(replayFile.resourcePack(hash).get(), new FileOutputStream(file));
|
||||
IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file));
|
||||
}
|
||||
mc.getResourcePackRepository().func_177319_a(file);
|
||||
}
|
||||
@@ -387,9 +391,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
mc.displayGuiScreen(null);
|
||||
}
|
||||
|
||||
if(ReplayHandler.isInPath()) return null;
|
||||
if(replayHandler.shouldSuppressCameraMovements()) return null;
|
||||
|
||||
CameraEntity cent = ReplayHandler.getCameraEntity();
|
||||
CameraEntity cent = replayHandler.getCameraEntity();
|
||||
|
||||
for (Object relative : ppl.func_179834_f()) {
|
||||
if (relative == S08PacketPlayerPosLook.EnumFlags.X
|
||||
@@ -419,7 +423,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
CameraEntity cent = ReplayHandler.getCameraEntity();
|
||||
CameraEntity cent = replayHandler.getCameraEntity();
|
||||
cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e());
|
||||
return null;
|
||||
}
|
||||
@@ -461,7 +465,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
replayFile.close();
|
||||
FileUtils.deleteDirectory(tempResourcePackFolder);
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
@@ -522,7 +525,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
while (!terminate) {
|
||||
synchronized (ReplaySender.this) {
|
||||
if (dis == null) {
|
||||
dis = new DataInputStream(replayFile.recording().get());
|
||||
dis = new DataInputStream(replayFile.getPacketData());
|
||||
}
|
||||
// Packet loop
|
||||
while (true) {
|
||||
@@ -580,7 +583,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
if (isHurrying() && lastTimeStamp > desiredTimeStamp && !startFromBeginning) {
|
||||
desiredTimeStamp = -1;
|
||||
|
||||
ReplayHandler.moveCameraToLastPosition();
|
||||
replayHandler.moveCameraToTargetPosition();
|
||||
|
||||
// Pause after jumping
|
||||
setReplaySpeed(0);
|
||||
@@ -605,7 +608,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
startFromBeginning = false;
|
||||
nextPacket = null;
|
||||
lastPacketSent = System.currentTimeMillis();
|
||||
ReplayHandler.restartReplay();
|
||||
replayHandler.restartedReplay();
|
||||
if (dis != null) {
|
||||
dis.close();
|
||||
dis = null;
|
||||
@@ -659,8 +662,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
protected Packet processPacketAsync(Packet p) {
|
||||
//If hurrying, ignore some packets, unless during Replay Path and *not* in short hurries
|
||||
if(!ReplayHandler.isInPath() && desiredTimeStamp - lastTimeStamp > 1000) {
|
||||
//If hurrying, ignore some packets, except for short durations
|
||||
if(desiredTimeStamp - lastTimeStamp > 1000) {
|
||||
if(p instanceof S2APacketParticles) return null;
|
||||
|
||||
if(p instanceof S0EPacketSpawnObject) {
|
||||
@@ -700,11 +703,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
startFromBeginning = false;
|
||||
nextPacket = null;
|
||||
ReplayHandler.restartReplay();
|
||||
replayHandler.restartedReplay();
|
||||
}
|
||||
|
||||
if (dis == null) {
|
||||
dis = new DataInputStream(replayFile.recording().get());
|
||||
dis = new DataInputStream(replayFile.getPacketData());
|
||||
}
|
||||
|
||||
while (true) { // Send packets
|
||||
17
src/main/java/com/replaymod/replay/Setting.java
Normal file
17
src/main/java/com/replaymod/replay/Setting.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements.timelines;
|
||||
package com.replaymod.replay.gui.overlay;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiEditKeyframe;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.holders.Marker;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import de.johni0702.replaystudio.data.Marker;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline;
|
||||
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -16,13 +16,16 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
private static final int KEYFRAME_MARKER_X = 109;
|
||||
private static final int KEYFRAME_MARKER_Y = 20;
|
||||
|
||||
private Keyframe<Marker> clickedKeyFrame;
|
||||
private final ReplayHandler replayHandler;
|
||||
private Marker selectedMarker;
|
||||
private Marker clickedMarker;
|
||||
private long clickTime;
|
||||
private boolean dragging;
|
||||
|
||||
public GuiMarkerTimeline(int positionX, int positionY, int width, int height, boolean showMarkers) {
|
||||
public GuiMarkerTimeline(ReplayHandler replayHandler, int positionX, int positionY, int width, int height) {
|
||||
super(positionX, positionY, width, height);
|
||||
this.showMarkers = showMarkers;
|
||||
this.replayHandler = replayHandler;
|
||||
this.showMarkers = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,30 +39,33 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
Keyframe<Marker> closest = null;
|
||||
Marker closest = null;
|
||||
if(mouseY >= positionY + BORDER_TOP + 10) {
|
||||
closest = ReplayHandler.getMarkerKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
|
||||
long distance = tolerance;
|
||||
for (Marker m : replayHandler.getMarkers()) {
|
||||
long d = Math.abs(m.getTime() - time);
|
||||
if (d <= distance) {
|
||||
closest = m;
|
||||
distance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//left mouse button
|
||||
if(button == 0) {
|
||||
ReplayHandler.selectKeyframe(closest);
|
||||
|
||||
if(closest == null) { //if no keyframe clicked, jump in time
|
||||
ReplayMod.overlay.performJump(getTimeAt(mouseX, mouseY));
|
||||
replayHandler.doJump((int) getTimeAt(mouseX, mouseY), true);
|
||||
} else {
|
||||
selectedMarker = closest;
|
||||
// If we clicked on a key frame, then continue monitoring the mouse for movements
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(closest != null) {
|
||||
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
|
||||
mc.displayGuiScreen(GuiEditKeyframe.create(closest));
|
||||
this.clickedKeyFrame = null;
|
||||
} else {
|
||||
this.clickedKeyFrame = closest;
|
||||
this.dragging = false;
|
||||
}
|
||||
} else { // If we didn't then just update the cursor
|
||||
this.dragging = true;
|
||||
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
|
||||
// mc.displayGuiScreen(GuiEditKeyframe.create(closest));
|
||||
// TODO Edit Gui
|
||||
this.clickedMarker = null;
|
||||
} else {
|
||||
this.clickedMarker = closest;
|
||||
this.dragging = false;
|
||||
}
|
||||
this.clickTime = currentTime;
|
||||
}
|
||||
@@ -67,10 +73,13 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
} else if(button == 1) {
|
||||
if(closest != null) {
|
||||
//Jump to clicked Marker Keyframe (explicitly force to jump to this position)
|
||||
ReplayHandler.setLastPosition(closest.getValue().getPosition(), true);
|
||||
replayHandler.setTargetPosition(new AdvancedPosition(
|
||||
closest.getX(), closest.getY(), closest.getZ(),
|
||||
closest.getPitch(), closest.getYaw(), closest.getRoll()
|
||||
));
|
||||
|
||||
//perform the jump, telling the Overlay not to override the last position value
|
||||
ReplayMod.overlay.performJump(closest.getRealTimestamp(), false);
|
||||
replayHandler.doJump(closest.getTime(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,11 +91,11 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
if(!enabled) return;
|
||||
long time = getTimeAt(mouseX, mouseY);
|
||||
if (time != -1) {
|
||||
if (clickedKeyFrame != null) {
|
||||
if (clickedMarker != null) {
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) {
|
||||
clickedKeyFrame.setRealTimestamp((int) time);
|
||||
if (dragging || Math.abs(clickedMarker.getTime() - time) > tolerance) {
|
||||
clickedMarker.setTime((int) time);
|
||||
dragging = true;
|
||||
}
|
||||
}
|
||||
@@ -96,8 +105,11 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
@Override
|
||||
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
mouseDrag(mc, mouseX, mouseY, button);
|
||||
clickedKeyFrame = null;
|
||||
dragging = false;
|
||||
clickedMarker = null;
|
||||
if (dragging) {
|
||||
replayHandler.saveMarkers();
|
||||
dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,17 +126,12 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
drawTimelineCursor(leftTime, rightTime, bodyWidth);
|
||||
|
||||
//Draw Keyframe logos
|
||||
for(Keyframe<Marker> kf : ReplayHandler.getMarkerKeyframes()) {
|
||||
if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe()))
|
||||
drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength);
|
||||
}
|
||||
|
||||
if(ReplayHandler.getSelectedKeyframe() != null && ReplayHandler.getSelectedKeyframe().getValue() instanceof Marker) {
|
||||
drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength);
|
||||
for (Marker marker : replayHandler.getMarkers()) {
|
||||
drawMarker(marker, bodyWidth, leftTime, rightTime, segmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
|
||||
private int getMarkerX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
|
||||
long positionInSegment = timestamp - leftTime;
|
||||
double fractionOfSegment = positionInSegment / segmentLength;
|
||||
return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
|
||||
@@ -139,12 +146,12 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
long leftTime = Math.round(timeStart * timelineLength);
|
||||
double segmentLength = timelineLength * zoom;
|
||||
|
||||
for(Keyframe<Marker> marker : ReplayHandler.getMarkerKeyframes()) {
|
||||
int keyframeX = getKeyframeX(marker.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
for (Marker marker : replayHandler.getMarkers()) {
|
||||
int markerX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength);
|
||||
|
||||
if(MouseUtils.isMouseWithinBounds(keyframeX - 2, this.positionY + BORDER_TOP + 10 + 1, 5, 5)) {
|
||||
if(MouseUtils.isMouseWithinBounds(markerX - 2, this.positionY + BORDER_TOP + 10 + 1, 5, 5)) {
|
||||
Point mouse = MouseUtils.getMousePos();
|
||||
String markerName = marker.getValue().getName();
|
||||
String markerName = marker.getName();
|
||||
if(markerName == null || markerName.isEmpty()) markerName = I18n.format("replaymod.gui.ingame.unnamedmarker");
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouse.getX(), mouse.getY(), markerName, null, Color.WHITE);
|
||||
|
||||
@@ -157,15 +164,15 @@ public class GuiMarkerTimeline extends GuiTimeline {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
|
||||
if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) {
|
||||
private void drawMarker(Marker marker, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
|
||||
if (marker.getTime() <= rightTime && marker.getTime() >= leftTime) {
|
||||
int textureX = KEYFRAME_MARKER_X;
|
||||
int textureY = KEYFRAME_MARKER_Y;
|
||||
int y = positionY+10;
|
||||
|
||||
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
int keyframeX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength);
|
||||
|
||||
if (ReplayHandler.isSelected(kf)) {
|
||||
if (selectedMarker == marker) {
|
||||
textureX += 5;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.crushedpixel.replaymod.gui.replayviewer;
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiErrorScreen;
|
||||
@@ -57,7 +56,7 @@ public class GuiRenameReplay extends GuiScreen {
|
||||
} else if(button.id == 0) {
|
||||
File folder = ReplayFileIO.getReplayFolder();
|
||||
|
||||
File initRenamed = new File(folder, (this.replayNameInput.getText().trim() + ReplayFile.ZIP_FILE_EXTENSION).replaceAll("[^a-zA-Z0-9\\.\\- ]", "_"));
|
||||
File initRenamed = new File(folder, (this.replayNameInput.getText().trim() + ".zip").replaceAll("[^a-zA-Z0-9\\.\\- ]", "_"));
|
||||
File renamed = ReplayFileIO.getNextFreeFile(initRenamed);
|
||||
try {
|
||||
FileUtils.moveFile(file, renamed);
|
||||
@@ -1,18 +1,21 @@
|
||||
package eu.crushedpixel.replaymod.gui.replayviewer;
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.mojang.realmsclient.util.Pair;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.gui.GuiReplaySettings;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import de.johni0702.replaystudio.replay.ReplayMetaData;
|
||||
import de.johni0702.replaystudio.replay.ZipReplayFile;
|
||||
import de.johni0702.replaystudio.studio.ReplayStudio;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
import eu.crushedpixel.replaymod.registry.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -34,6 +37,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
@@ -45,6 +49,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
private static final int DELETE_BUTTON_ID = 9005;
|
||||
private static final int SETTINGS_BUTTON_ID = 9006;
|
||||
private static final int CANCEL_BUTTON_ID = 9007;
|
||||
private final ReplayModReplay mod;
|
||||
private boolean initialized;
|
||||
private GuiReplayListExtended replayGuiList;
|
||||
private List<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>();
|
||||
@@ -58,6 +63,10 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
private Thread fileReloader;
|
||||
|
||||
public GuiReplayViewer(ReplayModReplay mod) {
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
private class FileReloaderThread extends Thread {
|
||||
private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry();
|
||||
|
||||
@@ -74,26 +83,26 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
for(final File file : ReplayFileIO.getAllReplayFiles()) {
|
||||
if(interrupted()) break;
|
||||
try {
|
||||
ReplayFile replayFile = new ReplayFile(file);
|
||||
final ReplayMetaData metaData = replayFile.metadata().get();
|
||||
BufferedImage img = replayFile.thumb().get();
|
||||
ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file);
|
||||
final ReplayMetaData metaData = replayFile.getMetaData();
|
||||
Optional<BufferedImage> thumb = replayFile.getThumb();
|
||||
|
||||
replayFile.close();
|
||||
|
||||
File tmp = null;
|
||||
if(img != null) {
|
||||
img = ImageUtils.scaleImage(img, new Dimension(1280, 720));
|
||||
if(thumb.isPresent()) {
|
||||
BufferedImage img = ImageUtils.scaleImage(thumb.get(), new Dimension(1280, 720));
|
||||
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg");
|
||||
tmp.deleteOnExit();
|
||||
|
||||
ImageIO.write(img, "jpg", tmp);
|
||||
}
|
||||
|
||||
final File thumb = tmp;
|
||||
final File thumbFile = tmp;
|
||||
loadedReplaysQueue.offer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addEntry(file, metaData, thumb);
|
||||
addEntry(file, metaData, thumbFile);
|
||||
}
|
||||
});
|
||||
} catch(Exception e) {
|
||||
@@ -213,7 +222,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
this.mc.displayGuiScreen(guiyesno);
|
||||
}
|
||||
} else if(button.id == SETTINGS_BUTTON_ID) {
|
||||
this.mc.displayGuiScreen(new GuiReplaySettings(this));
|
||||
new GuiReplaySettings(this, ReplayMod.instance.getSettingsRegistry()).display();
|
||||
} else if(button.id == RENAME_BUTTON_ID) {
|
||||
File file = replayFileList.get(replayGuiList.selected).first().first();
|
||||
this.mc.displayGuiScreen(new GuiRenameReplay(this, file));
|
||||
@@ -306,7 +315,7 @@ public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
mc.displayGuiScreen(null);
|
||||
|
||||
try {
|
||||
ReplayHandler.startReplay(replayFileList.get(id).first().first());
|
||||
mod.startReplay(replayFileList.get(id).first().first());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package eu.crushedpixel.replaymod.gui.replayviewer;
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
||||
import net.minecraft.client.Minecraft;
|
||||
111
src/main/java/com/replaymod/replay/handler/GuiHandler.java
Normal file
111
src/main/java/com/replaymod/replay/handler/GuiHandler.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,21 +83,21 @@ public abstract class AbstractGuiScreen<T extends AbstractGuiScreen<T>> extends
|
||||
final GuiElement tooltip = forEach(GuiElement.class).getTooltip(renderInfo);
|
||||
if (tooltip != null) {
|
||||
final ReadableDimension tooltipSize = tooltip.getMinSize();
|
||||
int dx, dy;
|
||||
int x, y;
|
||||
if (renderInfo.mouseX + 8 + tooltipSize.getWidth() < screenSize.getWidth()) {
|
||||
dx = 8;
|
||||
x = renderInfo.mouseX + 8;
|
||||
} else {
|
||||
dx = -8;
|
||||
x = screenSize.getWidth() - tooltipSize.getWidth() - 1;
|
||||
}
|
||||
if (renderInfo.mouseY + 8 + tooltipSize.getHeight() < screenSize.getHeight()) {
|
||||
dy = 8;
|
||||
y = renderInfo.mouseY + 8;
|
||||
} else {
|
||||
dy = -8;
|
||||
y = screenSize.getHeight() - tooltipSize.getHeight() - 1;
|
||||
}
|
||||
final ReadablePoint position = new Point(renderInfo.mouseX + dx, renderInfo.mouseY + dy);
|
||||
final ReadablePoint position = new Point(x, y);
|
||||
try {
|
||||
OffsetGuiRenderer eRenderer = new OffsetGuiRenderer(renderer, position, tooltipSize);
|
||||
tooltip.draw(eRenderer, tooltipSize, renderInfo.offsetMouse(position.getX(), position.getY()));
|
||||
tooltip.draw(eRenderer, tooltipSize, renderInfo);
|
||||
} catch (Exception ex) {
|
||||
CrashReport crashReport = CrashReport.makeCrashReport(ex, "Rendering Gui Tooltip");
|
||||
renderInfo.addTo(crashReport);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,14 @@ import de.johni0702.minecraft.gui.RenderInfo;
|
||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.Point;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
public abstract class AbstractGuiElement<T extends AbstractGuiElement<T>> implements GuiElement<T> {
|
||||
protected static final ResourceLocation TEXTURE = new ResourceLocation("guiapi", "gui.png");
|
||||
|
||||
@Getter
|
||||
private final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public abstract class AbstractGuiToggleButton<V, T extends AbstractGuiToggleButt
|
||||
@Override
|
||||
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
|
||||
String orgLabel = getLabel();
|
||||
setLabel(orgLabel + values[selected]);
|
||||
setLabel(orgLabel + ": " + values[selected]);
|
||||
super.draw(renderer, size, renderInfo);
|
||||
setLabel(orgLabel);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -35,15 +35,32 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class CustomLayout<T extends GuiContainer<T>> implements Layout {
|
||||
private final Layout parent;
|
||||
private Map<GuiElement, Pair<Point, Dimension>> result = Maps.newHashMap();
|
||||
|
||||
public CustomLayout() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public CustomLayout(Layout parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> layOut(GuiContainer container, ReadableDimension size) {
|
||||
result.clear();
|
||||
Collection<GuiElement> elements = container.getChildren();
|
||||
for (GuiElement element : elements) {
|
||||
result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize())));
|
||||
if (parent == null) {
|
||||
Collection<GuiElement> elements = container.getChildren();
|
||||
for (GuiElement element : elements) {
|
||||
result.put(element, Pair.of(new Point(0, 0), new Dimension(element.getMinSize())));
|
||||
}
|
||||
} else {
|
||||
Map<GuiElement, Pair<ReadablePoint, ReadableDimension>> elements = parent.layOut(container, size);
|
||||
for (Map.Entry<GuiElement, Pair<ReadablePoint, ReadableDimension>> entry : elements.entrySet()) {
|
||||
Pair<ReadablePoint, ReadableDimension> pair = entry.getValue();
|
||||
result.put(entry.getKey(), Pair.of(new Point(pair.getLeft()), new Dimension(pair.getRight())));
|
||||
}
|
||||
}
|
||||
|
||||
layout((T) container, size.getWidth(), size.getHeight());
|
||||
|
||||
@@ -27,7 +27,6 @@ import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||
import de.johni0702.minecraft.gui.element.GuiElement;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -40,11 +39,13 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class GridLayout implements Layout {
|
||||
private static final Data DEFAULT_DATA = new Data();
|
||||
|
||||
private final int columns;
|
||||
@Accessors(chain = true)
|
||||
@Getter
|
||||
@Setter
|
||||
private int columns;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@Getter
|
||||
|
||||
@@ -67,7 +67,9 @@ public class HorizontalLayout implements Layout {
|
||||
GuiElement element = entry.getKey();
|
||||
Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA;
|
||||
Dimension elementSize = new Dimension(element.getMinSize());
|
||||
elementSize.setHeight(Math.min(size.getHeight(), element.getMaxSize().getHeight()));
|
||||
ReadableDimension elementMaxSize = element.getMaxSize();
|
||||
elementSize.setWidth(Math.min(size.getWidth() - x, Math.min(elementSize.getWidth(), elementMaxSize.getWidth())));
|
||||
elementSize.setHeight(Math.min(size.getHeight(), elementMaxSize.getHeight()));
|
||||
int remainingHeight = size.getHeight() - elementSize.getHeight();
|
||||
int y = (int) (data.alignment * remainingHeight);
|
||||
map.put(element, Pair.<ReadablePoint, ReadableDimension>of(new Point(x, y), elementSize));
|
||||
|
||||
@@ -67,6 +67,8 @@ public class VerticalLayout implements Layout {
|
||||
GuiElement element = entry.getKey();
|
||||
Data data = entry.getValue() instanceof Data ? (Data) entry.getValue() : DEFAULT_DATA;
|
||||
Dimension elementSize = new Dimension(element.getMinSize());
|
||||
ReadableDimension elementMaxSize = element.getMaxSize();
|
||||
elementSize.setHeight(Math.min(size.getHeight() - y, Math.min(elementSize.getHeight(), elementMaxSize.getHeight())));
|
||||
elementSize.setWidth(Math.min(size.getWidth(), element.getMaxSize().getWidth()));
|
||||
int remainingWidth = size.getWidth() - elementSize.getWidth();
|
||||
int x = (int) (data.alignment * remainingWidth);
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.ReplayModApiMethods;
|
||||
import eu.crushedpixel.replaymod.api.replay.SearchQuery;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.*;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
package eu.crushedpixel.replaymod.api;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class GsonApiClient {
|
||||
|
||||
private static final JsonParser parser = new JsonParser();
|
||||
|
||||
public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException {
|
||||
String apiResult = SimpleApiClient.invoke(query);
|
||||
return wrapWithJson(apiResult);
|
||||
}
|
||||
|
||||
public static JsonElement invokeJson(String url) throws IOException, ApiException {
|
||||
String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace(""", "\\\""));
|
||||
return wrapWithJson(apiResult);
|
||||
}
|
||||
|
||||
private static JsonElement wrapWithJson(String apiResult) {
|
||||
return parser.parse(apiResult);
|
||||
}
|
||||
}
|
||||
package eu.crushedpixel.replaymod.api;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class GsonApiClient {
|
||||
|
||||
private static final JsonParser parser = new JsonParser();
|
||||
|
||||
public static JsonElement invoke(QueryBuilder query) throws IOException, ApiException {
|
||||
String apiResult = SimpleApiClient.invoke(query);
|
||||
return wrapWithJson(apiResult);
|
||||
}
|
||||
|
||||
public static JsonElement invokeJson(String url) throws IOException, ApiException {
|
||||
String apiResult = StringEscapeUtils.unescapeHtml4(SimpleApiClient.invokeUrl(url).replace(""", "\\\""));
|
||||
return wrapWithJson(apiResult);
|
||||
}
|
||||
|
||||
private static JsonElement wrapWithJson(String apiResult) {
|
||||
return parser.parse(apiResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,123 +1,123 @@
|
||||
package eu.crushedpixel.replaymod.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.ApiError;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleApiClient {
|
||||
|
||||
private static final JsonParser jsonParser = new JsonParser();
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* Returns a Json String from the given QueryBuilder
|
||||
*
|
||||
* @param query The QueryBuilder to use
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(QueryBuilder query) throws IOException, ApiException {
|
||||
return invokeImpl(query.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the given URL
|
||||
*
|
||||
* @param url The URL to parse the Json from
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invokeUrl(String url) throws IOException, ApiException {
|
||||
return invokeImpl(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the API
|
||||
*
|
||||
* @param method The apiMethod to be called
|
||||
* @param paramMap The parameters to apply
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(String method, Map<String, Object> paramMap) throws IOException, ApiException {
|
||||
return invokeImpl(method, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the API
|
||||
*
|
||||
* @param method The apiMethod to be called
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(String method) throws IOException, ApiException {
|
||||
return invokeImpl(method, null);
|
||||
}
|
||||
|
||||
private static String invokeImpl(String urlString) throws IOException, ApiException {
|
||||
|
||||
// read response
|
||||
String responseContent = null;
|
||||
InputStream is = null;
|
||||
HttpURLConnection httpUrlConnection = null;
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
httpUrlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
httpUrlConnection.setRequestMethod("GET");
|
||||
|
||||
// give it 15 seconds to respond
|
||||
httpUrlConnection.setReadTimeout(15 * 1000);
|
||||
httpUrlConnection.connect();
|
||||
|
||||
int responseCode = httpUrlConnection.getResponseCode();
|
||||
|
||||
if(responseCode != 200) {
|
||||
is = httpUrlConnection.getErrorStream();
|
||||
if(is != null) {
|
||||
responseContent = IOUtils.toString(is, "UTF-8");
|
||||
} else {
|
||||
responseContent = "";
|
||||
}
|
||||
try {
|
||||
JsonObject response = jsonParser.parse(responseContent).getAsJsonObject();
|
||||
throw new ApiException(gson.fromJson(response, ApiError.class));
|
||||
} catch(JsonParseException e) {
|
||||
throw new ApiException(responseContent);
|
||||
}
|
||||
}
|
||||
|
||||
is = httpUrlConnection.getInputStream();
|
||||
|
||||
responseContent = IOUtils.toString(is, "UTF-8");
|
||||
|
||||
} finally {
|
||||
if(is != null) {
|
||||
is.close();
|
||||
}
|
||||
if(httpUrlConnection != null) {
|
||||
httpUrlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return responseContent;
|
||||
}
|
||||
|
||||
private static String invokeImpl(String method, Map<String, Object> paramMap) throws IOException, ApiException {
|
||||
QueryBuilder queryBuilder = new QueryBuilder(method);
|
||||
queryBuilder.put(paramMap);
|
||||
return invokeImpl(queryBuilder.toString());
|
||||
}
|
||||
}
|
||||
package eu.crushedpixel.replaymod.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.ApiError;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleApiClient {
|
||||
|
||||
private static final JsonParser jsonParser = new JsonParser();
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* Returns a Json String from the given QueryBuilder
|
||||
*
|
||||
* @param query The QueryBuilder to use
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(QueryBuilder query) throws IOException, ApiException {
|
||||
return invokeImpl(query.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the given URL
|
||||
*
|
||||
* @param url The URL to parse the Json from
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invokeUrl(String url) throws IOException, ApiException {
|
||||
return invokeImpl(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the API
|
||||
*
|
||||
* @param method The apiMethod to be called
|
||||
* @param paramMap The parameters to apply
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(String method, Map<String, Object> paramMap) throws IOException, ApiException {
|
||||
return invokeImpl(method, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String from the API
|
||||
*
|
||||
* @param method The apiMethod to be called
|
||||
* @return A Json String from the API
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public static String invoke(String method) throws IOException, ApiException {
|
||||
return invokeImpl(method, null);
|
||||
}
|
||||
|
||||
private static String invokeImpl(String urlString) throws IOException, ApiException {
|
||||
|
||||
// read response
|
||||
String responseContent = null;
|
||||
InputStream is = null;
|
||||
HttpURLConnection httpUrlConnection = null;
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
httpUrlConnection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
httpUrlConnection.setRequestMethod("GET");
|
||||
|
||||
// give it 15 seconds to respond
|
||||
httpUrlConnection.setReadTimeout(15 * 1000);
|
||||
httpUrlConnection.connect();
|
||||
|
||||
int responseCode = httpUrlConnection.getResponseCode();
|
||||
|
||||
if(responseCode != 200) {
|
||||
is = httpUrlConnection.getErrorStream();
|
||||
if(is != null) {
|
||||
responseContent = IOUtils.toString(is, "UTF-8");
|
||||
} else {
|
||||
responseContent = "";
|
||||
}
|
||||
try {
|
||||
JsonObject response = jsonParser.parse(responseContent).getAsJsonObject();
|
||||
throw new ApiException(gson.fromJson(response, ApiError.class));
|
||||
} catch(JsonParseException e) {
|
||||
throw new ApiException(responseContent);
|
||||
}
|
||||
}
|
||||
|
||||
is = httpUrlConnection.getInputStream();
|
||||
|
||||
responseContent = IOUtils.toString(is, "UTF-8");
|
||||
|
||||
} finally {
|
||||
if(is != null) {
|
||||
is.close();
|
||||
}
|
||||
if(httpUrlConnection != null) {
|
||||
httpUrlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
return responseContent;
|
||||
}
|
||||
|
||||
private static String invokeImpl(String method, Map<String, Object> paramMap) throws IOException, ApiException {
|
||||
QueryBuilder queryBuilder = new QueryBuilder(method);
|
||||
queryBuilder.put(paramMap);
|
||||
return invokeImpl(queryBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.crushedpixel.replaymod.api.replay;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.ApiError;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.Category;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package eu.crushedpixel.replaymod.api.replay;
|
||||
|
||||
public class ReplayModApiMethods {
|
||||
|
||||
public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/";
|
||||
|
||||
public static final String register = REPLAYMOD_BASE_URL+"register";
|
||||
public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey";
|
||||
public static final String login = REPLAYMOD_BASE_URL+"login";
|
||||
public static final String logout = REPLAYMOD_BASE_URL+"logout";
|
||||
public static final String file_details = REPLAYMOD_BASE_URL+"file_details";
|
||||
public static final String upload_file = REPLAYMOD_BASE_URL+"upload_file";
|
||||
public static final String download_file = REPLAYMOD_BASE_URL+"download_file";
|
||||
public static final String get_thumbnail = REPLAYMOD_BASE_URL+"get_thumbnail";
|
||||
public static final String remove_file = REPLAYMOD_BASE_URL+"remove_file";
|
||||
public static final String rate_file = REPLAYMOD_BASE_URL+"rate_file";
|
||||
public static final String get_ratings = REPLAYMOD_BASE_URL+"get_ratings";
|
||||
public static final String fav_file = REPLAYMOD_BASE_URL+"fav_file";
|
||||
public static final String get_favorites = REPLAYMOD_BASE_URL+"get_favorites";
|
||||
public static final String check_auth = REPLAYMOD_BASE_URL+"check_auth";
|
||||
public static final String get_language = REPLAYMOD_BASE_URL+"get_language";
|
||||
public static final String search = REPLAYMOD_BASE_URL+"search";
|
||||
public static final String up_to_date = REPLAYMOD_BASE_URL+"up_to_date";
|
||||
}
|
||||
package eu.crushedpixel.replaymod.api.replay;
|
||||
|
||||
public class ReplayModApiMethods {
|
||||
|
||||
public static final String REPLAYMOD_BASE_URL = "http://ReplayMod.com/api/";
|
||||
|
||||
public static final String register = REPLAYMOD_BASE_URL+"register";
|
||||
public static final String check_authkey = REPLAYMOD_BASE_URL+"check_authkey";
|
||||
public static final String login = REPLAYMOD_BASE_URL+"login";
|
||||
public static final String logout = REPLAYMOD_BASE_URL+"logout";
|
||||
public static final String file_details = REPLAYMOD_BASE_URL+"file_details";
|
||||
public static final String upload_file = REPLAYMOD_BASE_URL+"upload_file";
|
||||
public static final String download_file = REPLAYMOD_BASE_URL+"download_file";
|
||||
public static final String get_thumbnail = REPLAYMOD_BASE_URL+"get_thumbnail";
|
||||
public static final String remove_file = REPLAYMOD_BASE_URL+"remove_file";
|
||||
public static final String rate_file = REPLAYMOD_BASE_URL+"rate_file";
|
||||
public static final String get_ratings = REPLAYMOD_BASE_URL+"get_ratings";
|
||||
public static final String fav_file = REPLAYMOD_BASE_URL+"fav_file";
|
||||
public static final String get_favorites = REPLAYMOD_BASE_URL+"get_favorites";
|
||||
public static final String check_auth = REPLAYMOD_BASE_URL+"check_auth";
|
||||
public static final String get_language = REPLAYMOD_BASE_URL+"get_language";
|
||||
public static final String search = REPLAYMOD_BASE_URL+"search";
|
||||
public static final String up_to_date = REPLAYMOD_BASE_URL+"up_to_date";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.api.replay.holders;
|
||||
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
import de.johni0702.replaystudio.replay.ReplayMetaData;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.api.replay.pagination;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.api.replay.pagination;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.api.replay.pagination;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.SearchQuery;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
package eu.crushedpixel.replaymod.assets;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class AssetRepository {
|
||||
@@ -62,40 +56,29 @@ public class AssetRepository {
|
||||
}
|
||||
|
||||
public void saveAssets() {
|
||||
try {
|
||||
ReplayFile replayFile = new ReplayFile(ReplayHandler.getReplayFile());
|
||||
|
||||
Enumeration<? extends ZipEntry> entries = replayFile.entries();
|
||||
while(entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if(entry.getName().startsWith(ReplayFile.ENTRY_ASSET_FOLDER)) {
|
||||
ReplayMod.replayFileAppender.registerModifiedFile(null, entry.getName(), ReplayHandler.getReplayFile());
|
||||
}
|
||||
}
|
||||
|
||||
replayFile.close();
|
||||
|
||||
ReplayMod.replayFileAppender.deleteAllFilesByFolder(ReplayFile.ENTRY_ASSET_FOLDER, ReplayHandler.getReplayFile());
|
||||
|
||||
for(Map.Entry<UUID, ReplayAsset> e : replayAssets.entrySet()) {
|
||||
UUID uuid = e.getKey();
|
||||
ReplayAsset asset = e.getValue();
|
||||
try {
|
||||
String filepath = ReplayFile.ENTRY_ASSET_FOLDER + uuid.toString()+ "_" + asset.getDisplayString() + "." + asset.getSavedFileExtension();
|
||||
|
||||
File toAdd = File.createTempFile("ASSET_"+asset.getDisplayString(), asset.getSavedFileExtension());
|
||||
FileOutputStream fos = new FileOutputStream(toAdd);
|
||||
asset.writeToStream(fos);
|
||||
|
||||
|
||||
ReplayMod.replayFileAppender.registerModifiedFile(toAdd, filepath, ReplayHandler.getReplayFile());
|
||||
} catch(IOException io) {
|
||||
io.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// TODO
|
||||
// try {
|
||||
// ReplayFile replayFile = ReplayHandler.getReplayFile();
|
||||
//
|
||||
// for (ReplayAssetEntry entry : replayFile.getAssets()) {
|
||||
// if (!replayAssets.containsKey(entry.getUuid())) {
|
||||
// replayFile.removeAsset(entry.getUuid());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for(Map.Entry<UUID, ReplayAsset> e : replayAssets.entrySet()) {
|
||||
// UUID uuid = e.getKey();
|
||||
// ReplayAsset asset = e.getValue();
|
||||
// String extension = asset.getSavedFileExtension();
|
||||
// String name = asset.getAssetName();
|
||||
//
|
||||
// try (OutputStream out = replayFile.writeAsset(new ReplayAssetEntry(uuid, extension, name))) {
|
||||
// asset.writeToStream(out);
|
||||
// }
|
||||
// }
|
||||
// } catch(IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
|
||||
public static ReplayAsset assetFromFileName(String filename) {
|
||||
|
||||
@@ -3,7 +3,6 @@ package eu.crushedpixel.replaymod.assets;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListEntry;
|
||||
import eu.crushedpixel.replaymod.holders.Transformations;
|
||||
import eu.crushedpixel.replaymod.registry.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -55,19 +54,20 @@ public class CustomImageObject implements GuiEntryListEntry {
|
||||
|
||||
//if no asset repository available, simply accept the UUID and it will load the image later
|
||||
//when calling getResourceLocation for the first time
|
||||
if(ReplayHandler.getAssetRepository() == null) {
|
||||
this.linkedAsset = assetUUID;
|
||||
return;
|
||||
}
|
||||
|
||||
ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID);
|
||||
|
||||
if(asset instanceof ReplayImageAsset) {
|
||||
this.linkedAsset = assetUUID;
|
||||
setImage(((ReplayImageAsset)asset).getObject());
|
||||
} else if(asset != null) {
|
||||
throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset");
|
||||
}
|
||||
// TODO
|
||||
// if(ReplayHandler.getAssetRepository() == null) {
|
||||
// this.linkedAsset = assetUUID;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(assetUUID);
|
||||
//
|
||||
// if(asset instanceof ReplayImageAsset) {
|
||||
// this.linkedAsset = assetUUID;
|
||||
// setImage(((ReplayImageAsset)asset).getObject());
|
||||
// } else if(asset != null) {
|
||||
// throw new UnsupportedOperationException("A CustomImageObject requires a ReplayImageAsset");
|
||||
// }
|
||||
}
|
||||
|
||||
public void setImage(final BufferedImage bufferedImage) throws IOException {
|
||||
@@ -103,14 +103,15 @@ public class CustomImageObject implements GuiEntryListEntry {
|
||||
|
||||
public ResourceLocation getResourceLocation() {
|
||||
if(resourceLocation == null) {
|
||||
ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset);
|
||||
if(asset instanceof ReplayImageAsset) {
|
||||
try {
|
||||
setImage(((ReplayImageAsset) asset).getObject());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// ReplayAsset asset = ReplayHandler.getAssetRepository().getAssetByUUID(linkedAsset);
|
||||
// if(asset instanceof ReplayImageAsset) {
|
||||
// try {
|
||||
// setImage(((ReplayImageAsset) asset).getObject());
|
||||
// } catch(Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.assets;
|
||||
|
||||
import eu.crushedpixel.replaymod.registry.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.BoundingUtils;
|
||||
import eu.crushedpixel.replaymod.utils.BufferedImageUtils;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -67,11 +66,12 @@ public class ReplayImageAsset implements ReplayAsset<BufferedImage> {
|
||||
this.bufferedImageHashCode = BufferedImageUtils.hashCode(object);
|
||||
ResourceHelper.freeResource(previewResource);
|
||||
|
||||
for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) {
|
||||
if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) {
|
||||
object.setImage(this.object);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// for(CustomImageObject object : ReplayHandler.getCustomImageObjects()) {
|
||||
// if(object.getLinkedAsset() != null && object.getLinkedAsset().equals(ReplayHandler.getAssetRepository().getUUIDForAsset(this))) {
|
||||
// object.setImage(this.object);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.chat;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
@@ -17,6 +17,7 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
|
||||
public LoadingPlugin() {
|
||||
MixinBootstrap.init();
|
||||
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replaymod.json");
|
||||
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.recording.replaymod.json");
|
||||
|
||||
CodeSource codeSource = getClass().getProtectionDomain().getCodeSource();
|
||||
if (codeSource != null) {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package eu.crushedpixel.replaymod.events;
|
||||
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
|
||||
public class ReplayExitEvent extends Event {
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
@@ -13,18 +11,20 @@ public class CrosshairRenderHandler {
|
||||
@SubscribeEvent
|
||||
public void preCrosshairRender(RenderGameOverlayEvent.Pre event) {
|
||||
//Crosshair should only render if hovered Entity can actually be spectated
|
||||
if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
|
||||
boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity);
|
||||
event.setCanceled(cancel);
|
||||
}
|
||||
// TODO
|
||||
// if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
|
||||
// boolean cancel = !SpectatingHandler.canSpectate(mc.pointedEntity);
|
||||
// event.setCanceled(cancel);
|
||||
// }
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void preChatRender(RenderGameOverlayEvent.Pre event) {
|
||||
if(ReplayHandler.isInReplay() && ReplayHandler.isCamera() && event.type == RenderGameOverlayEvent.ElementType.CHAT) {
|
||||
//when a crosshair was displayed, the background of the lowest line of chat would be opaque
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
// TODO
|
||||
// if(ReplayHandler.isInReplay() && ReplayHandler.isCameraView() && event.type == RenderGameOverlayEvent.ElementType.CHAT) {
|
||||
// //when a crosshair was displayed, the background of the lowest line of chat would be opaque
|
||||
// GlStateManager.enableTexture2D();
|
||||
// GlStateManager.disableBlend();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.gui.GuiReplaySettings;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiLoginPrompt;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiReplayCenter;
|
||||
import eu.crushedpixel.replaymod.gui.replayeditor.GuiReplayEditor;
|
||||
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||
import eu.crushedpixel.replaymod.studio.VersionValidator;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
@@ -26,7 +23,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.lwjgl.util.Point;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiEventHandler {
|
||||
@@ -54,19 +50,20 @@ public class GuiEventHandler {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(ReplayHandler.isInReplay()) ReplayHandler.setInReplay(false);
|
||||
}
|
||||
|
||||
if(!ReplayMod.apiClient.isLoggedIn()) return;
|
||||
|
||||
if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) {
|
||||
if(ReplayHandler.isInReplay()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
// TODO
|
||||
// if(ReplayHandler.isInReplay()) {
|
||||
// event.setCanceled(true);
|
||||
// }
|
||||
} else if(event.gui instanceof GuiDisconnected) {
|
||||
if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
// TODO
|
||||
// if(!ReplayHandler.isInReplay() && System.currentTimeMillis() - ReplayHandler.lastExit < 5000) {
|
||||
// event.setCanceled(true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,20 +118,7 @@ public class GuiEventHandler {
|
||||
public void onInit(InitGuiEvent event) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = event.buttonList;
|
||||
if(event.gui instanceof GuiIngameMenu && ReplayHandler.isInReplay()) {
|
||||
ReplayMod.replaySender.setReplaySpeed(0);
|
||||
for(GuiButton b : new ArrayList<GuiButton>(buttonList)) {
|
||||
if(b.id == 1) {
|
||||
b.displayString = I18n.format("replaymod.gui.exit");
|
||||
b.yPosition -= 24 * 2;
|
||||
b.id = GuiConstants.EXIT_REPLAY_BUTTON;
|
||||
} else if(b.id >= 5 && b.id <= 7) {
|
||||
buttonList.remove(b);
|
||||
} else if(b.id != 4) {
|
||||
b.yPosition -= 24 * 2;
|
||||
}
|
||||
}
|
||||
} else if(event.gui instanceof GuiMainMenu) {
|
||||
if(event.gui instanceof GuiMainMenu) {
|
||||
int i1 = event.gui.height / 4 + 24 + 10;
|
||||
|
||||
for(GuiButton b : buttonList) {
|
||||
@@ -171,9 +155,7 @@ public class GuiEventHandler {
|
||||
public void onButton(ActionPerformedEvent event) {
|
||||
if(!event.button.enabled) return;
|
||||
if(event.gui instanceof GuiMainMenu) {
|
||||
if(event.button.id == GuiConstants.REPLAY_MANAGER_BUTTON_ID) {
|
||||
mc.displayGuiScreen(new GuiReplayViewer());
|
||||
} else if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) {
|
||||
if(event.button.id == GuiConstants.REPLAY_CENTER_BUTTON_ID) {
|
||||
if(ReplayMod.apiClient.isLoggedIn()) {
|
||||
mc.displayGuiScreen(new GuiReplayCenter());
|
||||
} else {
|
||||
@@ -183,17 +165,7 @@ public class GuiEventHandler {
|
||||
mc.displayGuiScreen(new GuiReplayEditor());
|
||||
}
|
||||
} else if(event.gui instanceof GuiOptions && event.button.id == GuiConstants.REPLAY_OPTIONS_BUTTON_ID) {
|
||||
mc.displayGuiScreen(new GuiReplaySettings(event.gui));
|
||||
}
|
||||
|
||||
if(ReplayHandler.isInReplay() && event.gui instanceof GuiIngameMenu && event.button.id == GuiConstants.EXIT_REPLAY_BUTTON) {
|
||||
if(ReplayHandler.isInPath()) ReplayProcess.stopReplayProcess(false);
|
||||
|
||||
event.button.enabled = false;
|
||||
|
||||
mc.displayGuiScreen(new GuiMainMenu());
|
||||
|
||||
ReplayHandler.endReplay();
|
||||
new GuiReplaySettings(event.gui, ReplayMod.instance.getSettingsRegistry()).display();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import net.minecraftforge.client.event.MouseEvent;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
public class MinecraftTicker {
|
||||
|
||||
public static void runMouseKeyboardTick(Minecraft mc) {
|
||||
ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent());
|
||||
// TODO
|
||||
// ReplayMod.mouseInputHandler.mouseEvent(new MouseEvent());
|
||||
if(mc.thePlayer == null) return;
|
||||
try {
|
||||
mc.mcProfiler.endStartSection("mouse");
|
||||
|
||||
@@ -1,51 +1,45 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.client.event.MouseEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
public class MouseInputHandler {
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private boolean rightDown = false;
|
||||
private boolean leftDown = false;
|
||||
|
||||
@SubscribeEvent
|
||||
public void mouseEvent(MouseEvent event) {
|
||||
if(!ReplayHandler.isInReplay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.dwheel != 0 && mc.currentScreen == null) {
|
||||
boolean increase = event.dwheel > 0;
|
||||
CameraEntity.modifyCameraSpeed(increase);
|
||||
}
|
||||
|
||||
if(Mouse.isButtonDown(0)) {
|
||||
if(!leftDown) {
|
||||
leftDown = true;
|
||||
if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) {
|
||||
if(SpectatingHandler.canSpectate(mc.pointedEntity))
|
||||
ReplayHandler.spectateEntity(mc.pointedEntity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
leftDown = false;
|
||||
}
|
||||
|
||||
if(Mouse.isButtonDown(1)) {
|
||||
if(!rightDown) {
|
||||
rightDown = true;
|
||||
if(mc.pointedEntity != null && ReplayHandler.isCamera() && mc.currentScreen == null) {
|
||||
if(SpectatingHandler.canSpectate(mc.pointedEntity))
|
||||
ReplayHandler.spectateEntity(mc.pointedEntity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rightDown = false;
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// private final Minecraft mc = Minecraft.getMinecraft();
|
||||
// private boolean rightDown = false;
|
||||
// private boolean leftDown = false;
|
||||
//
|
||||
// @SubscribeEvent
|
||||
// public void mouseEvent(MouseEvent event) {
|
||||
// if(!ReplayHandler.isInReplay()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(event.dwheel != 0 && mc.currentScreen == null) {
|
||||
// boolean increase = event.dwheel > 0;
|
||||
// CameraEntity.modifyCameraSpeed(increase);
|
||||
// }
|
||||
//
|
||||
// if(Mouse.isButtonDown(0)) {
|
||||
// if(!leftDown) {
|
||||
// leftDown = true;
|
||||
// if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) {
|
||||
// if(SpectatingHandler.canSpectate(mc.pointedEntity))
|
||||
// ReplayHandler.spectateEntity(mc.pointedEntity);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// leftDown = false;
|
||||
// }
|
||||
//
|
||||
// if(Mouse.isButtonDown(1)) {
|
||||
// if(!rightDown) {
|
||||
// rightDown = true;
|
||||
// if(mc.pointedEntity != null && ReplayHandler.isCameraView() && mc.currentScreen == null) {
|
||||
// if(SpectatingHandler.canSpectate(mc.pointedEntity))
|
||||
// ReplayHandler.spectateEntity(mc.pointedEntity);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// rightDown = false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||
import eu.crushedpixel.replaymod.video.ReplayScreenshot;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.client.event.MouseEvent;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
|
||||
public class TickAndRenderListener {
|
||||
|
||||
@@ -30,75 +22,78 @@ public class TickAndRenderListener {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderWorld(RenderWorldLastEvent event) throws Exception {
|
||||
if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel
|
||||
if (ReplayProcess.isVideoRecording()) return; // If recording, cancel
|
||||
|
||||
if(requestScreenshot == 1) {
|
||||
mc.addScheduledTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION);
|
||||
ReplayScreenshot.prepareScreenshot();
|
||||
requestScreenshot = 2;
|
||||
}
|
||||
});
|
||||
} else if(requestScreenshot == 2) {
|
||||
mc.addScheduledTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReplayScreenshot.saveScreenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false);
|
||||
if(ReplayHandler.isCamera()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity());
|
||||
|
||||
if(mc.isGamePaused() && ReplayHandler.isInPath()) {
|
||||
mc.isGamePaused = false;
|
||||
}
|
||||
// TODO
|
||||
// if(!ReplayHandler.isInReplay()) return; //If not in Replay, cancel
|
||||
// if (ReplayProcess.isVideoRecording()) return; // If recording, cancel
|
||||
//
|
||||
// if(requestScreenshot == 1) {
|
||||
// mc.addScheduledTask(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// ReplayMod.chatMessageHandler.addLocalizedChatMessage("replaymod.chat.savingthumb", ChatMessageHandler.ChatMessageType.INFORMATION);
|
||||
// ReplayScreenshot.prepareScreenshot();
|
||||
// requestScreenshot = 2;
|
||||
// }
|
||||
// });
|
||||
// } else if(requestScreenshot == 2) {
|
||||
// mc.addScheduledTask(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// ReplayScreenshot.saveScreenshot();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// if(ReplayHandler.isInPath()) ReplayProcess.tickReplay(false);
|
||||
// if(ReplayHandler.isCameraView()) mc.setRenderViewEntity(ReplayHandler.getCameraEntity());
|
||||
//
|
||||
// if(mc.isGamePaused() && ReplayHandler.isInPath()) {
|
||||
// mc.isGamePaused = false;
|
||||
// }
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderTick(TickEvent.RenderTickEvent event) {
|
||||
if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return;
|
||||
|
||||
if(ReplayHandler.getCameraEntity() != null)
|
||||
ReplayHandler.getCameraEntity().updateMovement();
|
||||
if(ReplayHandler.isInPath()) {
|
||||
ReplayProcess.tickReplay(true);
|
||||
} else onMouseMove(new MouseEvent());
|
||||
|
||||
FMLCommonHandler.instance().fireKeyInput();
|
||||
// TODO
|
||||
// if(!ReplayHandler.isInReplay() || ReplayProcess.isVideoRecording()) return;
|
||||
//
|
||||
// if(ReplayHandler.getCameraEntity() != null)
|
||||
// ReplayHandler.getCameraEntity().updateMovement();
|
||||
// if(ReplayHandler.isInPath()) {
|
||||
// ReplayProcess.tickReplay(true);
|
||||
// } else onMouseMove(new MouseEvent());
|
||||
//
|
||||
// FMLCommonHandler.instance().fireKeyInput();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onMouseMove(MouseEvent event) {
|
||||
if(!ReplayHandler.isInReplay()) return;
|
||||
|
||||
mc.mcProfiler.startSection("mouse");
|
||||
|
||||
if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) {
|
||||
Mouse.setGrabbed(false);
|
||||
Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2);
|
||||
Mouse.setGrabbed(true);
|
||||
}
|
||||
|
||||
if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) {
|
||||
mc.mouseHelper.mouseXYChange();
|
||||
float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F;
|
||||
float f2 = f1 * f1 * f1 * 8.0F;
|
||||
float f3 = (float) mc.mouseHelper.deltaX * f2;
|
||||
float f4 = (float) mc.mouseHelper.deltaY * f2;
|
||||
byte b0 = 1;
|
||||
|
||||
if(mc.gameSettings.invertMouse) {
|
||||
b0 = -1;
|
||||
}
|
||||
|
||||
if(ReplayHandler.getCameraEntity() != null) {
|
||||
ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// if(!ReplayHandler.isInReplay()) return;
|
||||
//
|
||||
// mc.mcProfiler.startSection("mouse");
|
||||
//
|
||||
// if(Minecraft.isRunningOnMac && mc.inGameHasFocus && !Mouse.isInsideWindow()) {
|
||||
// Mouse.setGrabbed(false);
|
||||
// Mouse.setCursorPosition(Display.getWidth() / 2, Display.getHeight() / 2);
|
||||
// Mouse.setGrabbed(true);
|
||||
// }
|
||||
//
|
||||
// if(mc.inGameHasFocus && !(ReplayHandler.isInPath())) {
|
||||
// mc.mouseHelper.mouseXYChange();
|
||||
// float f1 = mc.gameSettings.mouseSensitivity * 0.6F + 0.2F;
|
||||
// float f2 = f1 * f1 * f1 * 8.0F;
|
||||
// float f3 = (float) mc.mouseHelper.deltaX * f2;
|
||||
// float f4 = (float) mc.mouseHelper.deltaY * f2;
|
||||
// byte b0 = 1;
|
||||
//
|
||||
// if(mc.gameSettings.invertMouse) {
|
||||
// b0 = -1;
|
||||
// }
|
||||
//
|
||||
// if(ReplayHandler.getCameraEntity() != null) {
|
||||
// ReplayHandler.getCameraEntity().setAngles(f3, f4 * (float) b0);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
package eu.crushedpixel.replaymod.events.handlers.keyboard;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection;
|
||||
import eu.crushedpixel.replaymod.events.handlers.TickAndRenderListener;
|
||||
import eu.crushedpixel.replaymod.gui.GuiAssetManager;
|
||||
import eu.crushedpixel.replaymod.gui.GuiKeyframeRepository;
|
||||
import eu.crushedpixel.replaymod.gui.GuiMouseInput;
|
||||
import eu.crushedpixel.replaymod.gui.GuiObjectManager;
|
||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
|
||||
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.InputEvent;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
public class KeyInputHandler {
|
||||
|
||||
@@ -25,200 +11,200 @@ public class KeyInputHandler {
|
||||
private long prevKeysDown = Sys.getTime();
|
||||
|
||||
public void onKeyInput() throws Exception {
|
||||
if(!ReplayHandler.isInReplay()) return;
|
||||
|
||||
KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
|
||||
|
||||
boolean speedup = false;
|
||||
|
||||
if(mc.currentScreen == null) {
|
||||
boolean forward = false, backward = false, left = false, right = false, up = false, down = false;
|
||||
|
||||
if(!ReplayHandler.isInPath()) {
|
||||
for(KeyBinding kb : keyBindings) {
|
||||
if(!kb.isKeyDown()) continue;
|
||||
if(ReplayHandler.isCamera()) {
|
||||
if(kb.getKeyDescription().equals("key.forward")) {
|
||||
forward = true;
|
||||
speedup = true;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.back")) {
|
||||
backward = true;
|
||||
speedup = true;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.jump")) {
|
||||
up = true;
|
||||
speedup = true;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.left")) {
|
||||
left = true;
|
||||
speedup = true;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.right")) {
|
||||
right = true;
|
||||
speedup = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.sneak")) {
|
||||
if(ReplayHandler.isCamera()) {
|
||||
down = true;
|
||||
speedup = true;
|
||||
}
|
||||
ReplayHandler.spectateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
forwardCameraMovement(forward, backward, left, right, up, down);
|
||||
}
|
||||
}
|
||||
|
||||
if(ReplayHandler.getCameraEntity() != null) {
|
||||
if(speedup) {
|
||||
ReplayHandler.getCameraEntity().speedUp();
|
||||
prevKeysDown = Sys.getTime();
|
||||
} else {
|
||||
if(Sys.getTime() - prevKeysDown > 100) {
|
||||
ReplayHandler.getCameraEntity().stopSpeedUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void keyInput(InputEvent.KeyInputEvent event) {
|
||||
try {
|
||||
onKeyInput();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for(KeyBinding kb : keyBindings) {
|
||||
if(!kb.isKeyDown()) continue;
|
||||
|
||||
handleCustomKeybindings(kb, found, -1);
|
||||
found = true;
|
||||
}
|
||||
|
||||
if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return;
|
||||
|
||||
for(StaticKeybinding staticKeybinding : KeybindRegistry.staticKeybindings) {
|
||||
if(!Keyboard.isKeyDown(staticKeybinding.getKeyCode())) {
|
||||
staticKeybinding.setDown(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(staticKeybinding.isDown()) return;
|
||||
staticKeybinding.setDown(true);
|
||||
|
||||
switch(staticKeybinding.getId()) {
|
||||
case KeybindRegistry.STATIC_DELETE_KEYFRAME:
|
||||
if(ReplayHandler.getSelectedKeyframe() != null) ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void forwardCameraMovement(boolean forward, boolean backward, boolean left, boolean right, boolean up, boolean down) {
|
||||
if(forward && !backward) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD);
|
||||
} else if(backward && !forward) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD);
|
||||
}
|
||||
|
||||
if(left && !right) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT);
|
||||
} else if(right && !left) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT);
|
||||
}
|
||||
|
||||
if(up && !down) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP);
|
||||
} else if(down && !up) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN);
|
||||
}
|
||||
// TODO
|
||||
// if(!ReplayHandler.isInReplay()) return;
|
||||
//
|
||||
// KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
|
||||
//
|
||||
// boolean speedup = false;
|
||||
//
|
||||
// if(mc.currentScreen == null) {
|
||||
// boolean forward = false, backward = false, left = false, right = false, up = false, down = false;
|
||||
//
|
||||
// if(!ReplayHandler.isInPath()) {
|
||||
// for(KeyBinding kb : keyBindings) {
|
||||
// if(!kb.isKeyDown()) continue;
|
||||
// if(ReplayHandler.isCameraView()) {
|
||||
// if(kb.getKeyDescription().equals("key.forward")) {
|
||||
// forward = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals("key.back")) {
|
||||
// backward = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals("key.jump")) {
|
||||
// up = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals("key.left")) {
|
||||
// left = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals("key.right")) {
|
||||
// right = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals("key.sneak")) {
|
||||
// if(ReplayHandler.isCameraView()) {
|
||||
// down = true;
|
||||
// speedup = true;
|
||||
// }
|
||||
// ReplayHandler.spectateCamera();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// forwardCameraMovement(forward, backward, left, right, up, down);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(ReplayHandler.getCameraEntity() != null) {
|
||||
// if(speedup) {
|
||||
// ReplayHandler.getCameraEntity().speedUp();
|
||||
// prevKeysDown = Sys.getTime();
|
||||
// } else {
|
||||
// if(Sys.getTime() - prevKeysDown > 100) {
|
||||
// ReplayHandler.getCameraEntity().stopSpeedUp();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
//
|
||||
// @SubscribeEvent
|
||||
// public void keyInput(InputEvent.KeyInputEvent event) {
|
||||
// try {
|
||||
// onKeyInput();
|
||||
// } catch(Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
|
||||
//
|
||||
// boolean found = false;
|
||||
//
|
||||
// for(KeyBinding kb : keyBindings) {
|
||||
// if(!kb.isKeyDown()) continue;
|
||||
//
|
||||
// handleCustomKeybindings(kb, found, -1);
|
||||
// found = true;
|
||||
// }
|
||||
//
|
||||
// if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return;
|
||||
//
|
||||
// for(StaticKeybinding staticKeybinding : KeybindRegistry.staticKeybindings) {
|
||||
// if(!Keyboard.isKeyDown(staticKeybinding.getKeyCode())) {
|
||||
// staticKeybinding.setDown(false);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(staticKeybinding.isDown()) return;
|
||||
// staticKeybinding.setDown(true);
|
||||
//
|
||||
// switch(staticKeybinding.getId()) {
|
||||
// case KeybindRegistry.STATIC_DELETE_KEYFRAME:
|
||||
// if(ReplayHandler.getSelectedKeyframe() != null) ReplayHandler.removeKeyframe(ReplayHandler.getSelectedKeyframe());
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void forwardCameraMovement(boolean forward, boolean backward, boolean left, boolean right, boolean up, boolean down) {
|
||||
// if(forward && !backward) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD);
|
||||
// } else if(backward && !forward) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD);
|
||||
// }
|
||||
//
|
||||
// if(left && !right) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT);
|
||||
// } else if(right && !left) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT);
|
||||
// }
|
||||
//
|
||||
// if(up && !down) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP);
|
||||
// } else if(down && !up) {
|
||||
// ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN);
|
||||
// }
|
||||
// }
|
||||
|
||||
public void handleCustomKeybindings(KeyBinding kb, boolean found, int keyCode) {
|
||||
//Custom registered handlers
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
||||
if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) {
|
||||
ReplayHandler.toggleMarker();
|
||||
} else if(ConnectionEventHandler.isRecording()) {
|
||||
ConnectionEventHandler.addMarker();
|
||||
}
|
||||
}
|
||||
|
||||
if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return;
|
||||
|
||||
if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command"))
|
||||
&& (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
||||
mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay));
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayMod.overlay.togglePlayPause();
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_CLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? 0.2f : 1);
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_COUNTERCLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? -0.2f : -1);
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_RESET_TILT) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayHandler.setCameraTilt(0);
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
|
||||
TickAndRenderListener.requestScreenshot();
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
|
||||
PlayerHandler.openPlayerOverview();
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled());
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback());
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SYNC_TIMELINE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayHandler.syncTimeCursor(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_KEYFRAME_PRESETS) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository()));
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview());
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
mc.displayGuiScreen(new GuiAssetManager());
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
mc.displayGuiScreen(new GuiObjectManager());
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
ReplayMod.replaySettings.toggleInterpolation();
|
||||
}
|
||||
// TODO: Transfer to new key binding registry
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ADD_MARKER) && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
||||
// if(ReplayHandler.isInReplay() && (mc.currentScreen == null || mc.currentScreen instanceof GuiMouseInput)) {
|
||||
// ReplayHandler.toggleMarker();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(!ReplayHandler.isInReplay() || (mc.currentScreen != null && !(mc.currentScreen instanceof GuiMouseInput))) return;
|
||||
//
|
||||
// if((kb.getKeyDescription().equals("key.chat") || kb.getKeyDescription().equals("key.command"))
|
||||
// && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
||||
// mc.displayGuiScreen(new GuiMouseInput(ReplayMod.overlay));
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAY_PAUSE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayMod.overlay.togglePlayPause();
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_CLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? 0.2f : 1);
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ROLL_COUNTERCLOCKWISE) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayHandler.addCameraTilt(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) ? -0.2f : -1);
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_RESET_TILT) && (kb.isKeyDown() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayHandler.setCameraTilt(0);
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
|
||||
// TickAndRenderListener.requestScreenshot();
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found && !ReplayHandler.isInPath()) {
|
||||
// PlayerHandler.openPlayerOverview();
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled());
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_CLEAR_KEYFRAMES) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayHandler.resetKeyframes(false, ReplayMod.replaySettings.showClearKeyframesCallback());
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SYNC_TIMELINE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayHandler.syncTimeCursor(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_KEYFRAME_PRESETS) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// mc.displayGuiScreen(new GuiKeyframeRepository(ReplayHandler.getKeyframeRepository()));
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PATH_PREVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayMod.replaySettings.setShowPathPreview(!ReplayMod.replaySettings.showPathPreview());
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_ASSET_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// mc.displayGuiScreen(new GuiAssetManager());
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_OBJECT_MANAGER) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// mc.displayGuiScreen(new GuiObjectManager());
|
||||
// }
|
||||
//
|
||||
// if(kb.getKeyDescription().equals(KeybindRegistry.KEY_TOGGLE_INTERPOLATION) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !ReplayHandler.isInPath()) {
|
||||
// ReplayMod.replaySettings.toggleInterpolation();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import eu.crushedpixel.replaymod.assets.ReplayAsset;
|
||||
import eu.crushedpixel.replaymod.gui.elements.*;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.FileChooseListener;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -22,7 +20,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOverlay {
|
||||
public class GuiAssetManager extends GuiScreen {
|
||||
|
||||
private String screenTitle;
|
||||
|
||||
@@ -43,8 +41,10 @@ public class GuiAssetManager extends GuiScreen implements GuiReplayOverlay.NoOve
|
||||
private ReplayAsset currentAsset;
|
||||
|
||||
public GuiAssetManager() {
|
||||
this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository());
|
||||
this.assetRepository = ReplayHandler.getAssetRepository();
|
||||
// TODO
|
||||
initialRepository = null;
|
||||
// this.initialRepository = new AssetRepository(ReplayHandler.getAssetRepository());
|
||||
// this.assetRepository = ReplayHandler.getAssetRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.*;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.NumberValueChangeListener;
|
||||
import eu.crushedpixel.replaymod.holders.*;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.interpolation.KeyframeList;
|
||||
import eu.crushedpixel.replaymod.interpolation.KeyframeValue;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
import eu.crushedpixel.replaymod.utils.RoundUtils;
|
||||
import eu.crushedpixel.replaymod.utils.TimestampUtils;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.util.Point;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static GuiEditKeyframe create(Keyframe kf) {
|
||||
if(kf.getValue() instanceof Marker) return new GuiEditKeyframeMarker(kf);
|
||||
if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf);
|
||||
if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf);
|
||||
if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf);
|
||||
// TODO
|
||||
// if(kf.getValue() instanceof TimestampValue) return new GuiEditKeyframeTime(kf);
|
||||
// if(kf.getValue() instanceof SpectatorData) return new GuiEditKeyframeSpectator(kf);
|
||||
// if(kf.getValue() instanceof AdvancedPosition) return new GuiEditKeyframePosition(kf);
|
||||
throw new UnsupportedOperationException("Keyframe type unknown: " + kf);
|
||||
}
|
||||
|
||||
@@ -156,13 +151,14 @@ public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
if(!save) {
|
||||
ReplayHandler.removeKeyframe(keyframe);
|
||||
ReplayHandler.addKeyframe(keyframeBackup);
|
||||
ReplayHandler.selectKeyframe(keyframeBackup);
|
||||
}
|
||||
ReplayHandler.fireKeyframesModifyEvent();
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
// TODO
|
||||
// if(!save) {
|
||||
// ReplayHandler.removeKeyframe(keyframe);
|
||||
// ReplayHandler.addKeyframe(keyframeBackup);
|
||||
// ReplayHandler.selectKeyframe(keyframeBackup);
|
||||
// }
|
||||
// ReplayHandler.fireKeyframesModifyEvent();
|
||||
// Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -218,300 +214,301 @@ public abstract class GuiEditKeyframe<T extends KeyframeValue> extends GuiScreen
|
||||
|
||||
protected void drawScreen0() {}
|
||||
|
||||
private static class GuiEditKeyframeMarker extends GuiEditKeyframe<Marker> {
|
||||
private GuiAdvancedTextField markerNameInput;
|
||||
|
||||
public GuiEditKeyframeMarker(Keyframe<Marker> keyframe) {
|
||||
super(keyframe, ReplayHandler.getMarkerKeyframes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
if (!initialized) {
|
||||
String name = keyframe.getValue().getName();
|
||||
if (name == null) name = "";
|
||||
markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20);
|
||||
markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername");
|
||||
markerNameInput.setText(name);
|
||||
|
||||
inputs.addPart(markerNameInput);
|
||||
|
||||
new KeyframeValueChangeListener(this);
|
||||
}
|
||||
|
||||
markerNameInput.xPosition = width/2 - 100;
|
||||
markerNameInput.yPosition = height/2-10;
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
keyframe.getValue().setName(markerNameInput.getText().trim());
|
||||
super.onGuiClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private static class GuiEditKeyframeTime extends GuiEditKeyframe<TimestampValue> {
|
||||
private GuiNumberInput kfMin, kfSec, kfMs;
|
||||
|
||||
public GuiEditKeyframeTime(Keyframe<TimestampValue> keyframe) {
|
||||
super(keyframe, ReplayHandler.getTimeKeyframes());
|
||||
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
if (!initialized) {
|
||||
int time = keyframe.getValue().asInt();
|
||||
|
||||
kfMin = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, null, (double)TimestampUtils.timestampToWholeMinutes(time), false, "", 1);
|
||||
kfSec = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 25, 0d, 59d, (double)TimestampUtils.getSecondsFromTimestamp(time), false, "", 1);
|
||||
kfMs = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(time), false, "", 1);
|
||||
|
||||
inputs.addPart(kfMin);
|
||||
inputs.addPart(kfSec);
|
||||
inputs.addPart(kfMs);
|
||||
|
||||
KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
|
||||
@Override
|
||||
public void onValueChange(double value) {
|
||||
keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp(
|
||||
kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue())));
|
||||
|
||||
super.onValueChange(value);
|
||||
}
|
||||
};
|
||||
|
||||
kfMin.addValueChangeListener(listener);
|
||||
kfSec.addValueChangeListener(listener);
|
||||
kfMs.addValueChangeListener(listener);
|
||||
}
|
||||
|
||||
kfMin.xPosition = min.xPosition;
|
||||
kfSec.xPosition = sec.xPosition;
|
||||
kfMs.xPosition = ms.xPosition;
|
||||
|
||||
kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20;
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawScreen0() {
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, kfMin.yPosition + 7, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.seconds"), kfSec.xPosition + kfSec.width + 5, kfSec.yPosition + 7, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.milliseconds"), kfMs.xPosition + kfMs.width + 5, kfMs.yPosition + 7, Color.WHITE.getRGB());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class GuiEditKeyframePosition extends GuiEditKeyframe<AdvancedPosition> {
|
||||
private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll;
|
||||
private ComposedElement posInputs;
|
||||
|
||||
public GuiEditKeyframePosition(Keyframe<AdvancedPosition> keyframe) {
|
||||
super(keyframe, ReplayHandler.getPositionKeyframes());
|
||||
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
if (!initialized) {
|
||||
AdvancedPosition pos = keyframe.getValue();
|
||||
xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true);
|
||||
yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true);
|
||||
zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true);
|
||||
yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true);
|
||||
pitch = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, -90d, 90d, RoundUtils.round2Decimals(pos.getPitch()), true);
|
||||
roll = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getRoll()), true);
|
||||
|
||||
posInputs = new ComposedElement(xCoord, yCoord, zCoord, yaw, pitch, roll);
|
||||
inputs.addPart(posInputs);
|
||||
|
||||
KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
|
||||
@Override
|
||||
public void onValueChange(double value) {
|
||||
keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(),
|
||||
zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(),
|
||||
(float) roll.getPreciseValue()));
|
||||
|
||||
super.onValueChange(value);
|
||||
}
|
||||
};
|
||||
|
||||
xCoord.addValueChangeListener(listener);
|
||||
yCoord.addValueChangeListener(listener);
|
||||
zCoord.addValueChangeListener(listener);
|
||||
pitch.addValueChangeListener(listener);
|
||||
yaw.addValueChangeListener(listener);
|
||||
roll.addValueChangeListener(listener);
|
||||
}
|
||||
|
||||
int w = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.xpos")),
|
||||
Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.ypos")),
|
||||
fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos"))));
|
||||
w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")),
|
||||
Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.campitch")),
|
||||
fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camroll"))));
|
||||
|
||||
totalWidth = w +100+w2+100+5+5+10;
|
||||
left = (this.width - totalWidth)/2;
|
||||
|
||||
int x = w + left + 5;
|
||||
int i = 0;
|
||||
for(GuiElement input : posInputs.getParts()) {
|
||||
if(input instanceof GuiTextField) {
|
||||
GuiTextField textField = (GuiTextField)input;
|
||||
textField.xPosition = i < 3 ? x : left+totalWidth-100;
|
||||
textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawScreen0() {
|
||||
if (keyframe.getValue() instanceof SpectatorData) return;
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.zpos"), left, virtualY + 87, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camyaw"), left + totalWidth - 100 - 5 - w2, virtualY + 27, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.campitch"), left + totalWidth - 100 - 5 - w2, virtualY + 57, Color.WHITE.getRGB());
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camroll"), left + totalWidth - 100 - 5 - w2, virtualY + 87, Color.WHITE.getRGB());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class GuiEditKeyframeSpectator extends GuiEditKeyframe<AdvancedPosition> {
|
||||
private GuiToggleButton perspectiveButton;
|
||||
|
||||
private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString;
|
||||
private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput,
|
||||
shoulderYawOffsetInput, shoulderSmoothnessInput;
|
||||
|
||||
private ComposedElement spectatorCamSettings;
|
||||
private ComposedElement shoulderCamSettings;
|
||||
|
||||
private DelegatingElement perspectiveSettings = new DelegatingElement() {
|
||||
@Override
|
||||
public GuiElement delegate() {
|
||||
switch(perspectiveButton.getValue()) {
|
||||
case 0:
|
||||
return spectatorCamSettings;
|
||||
case 1:
|
||||
return shoulderCamSettings;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public GuiEditKeyframeSpectator(Keyframe<AdvancedPosition> keyframe) {
|
||||
super(keyframe, ReplayHandler.getPositionKeyframes());
|
||||
screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
if (!initialized) {
|
||||
SpectatorData data = (SpectatorData)keyframe.getValue();
|
||||
|
||||
perspectiveButton = new GuiToggleButton(0, 0, 0, 200, 20, I18n.format("replaymod.gui.editkeyframe.spec.method")+": ", new String[]{
|
||||
I18n.format("replaymod.gui.editkeyframe.spec.method.firstperson"),
|
||||
I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder")});
|
||||
|
||||
perspectiveButton.setValue(Arrays.asList(SpectatorData.SpectatingMethod.values()).indexOf(data.getSpectatingMethod()));
|
||||
|
||||
spectatorCamSettings = new ComposedElement();
|
||||
|
||||
//create elements in shoulderCamSettings
|
||||
shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance"));
|
||||
shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch"));
|
||||
shoulderYawString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.yaw"));
|
||||
shoulderSmoothnessString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.smoothness"));
|
||||
|
||||
shoulderDistanceInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0d, 30d, data.getThirdPersonInfo().shoulderCamDistance, true, "", 0.1);
|
||||
shoulderPitchOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, -90d, 90d, data.getThirdPersonInfo().shoulderCamPitchOffset, false, "°", 1);
|
||||
shoulderYawOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, null, null, data.getThirdPersonInfo().shoulderCamYawOffset, false, "°", 1);
|
||||
shoulderSmoothnessInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0.1d, 3d, data.getThirdPersonInfo().shoulderCamSmoothness, true, "", 0.1);
|
||||
|
||||
shoulderCamSettings = new ComposedElement(
|
||||
shoulderDistanceString, shoulderDistanceInput,
|
||||
shoulderPitchString, shoulderPitchOffsetInput,
|
||||
shoulderYawString, shoulderYawOffsetInput,
|
||||
shoulderSmoothnessString, shoulderSmoothnessInput);
|
||||
|
||||
inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings));
|
||||
}
|
||||
|
||||
perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2;
|
||||
perspectiveButton.yPosition = this.virtualY + 20;
|
||||
|
||||
int verticalSpacing = 20 + 5;
|
||||
int totalWidth = 300;
|
||||
int elementWidth = 145;
|
||||
int horizontalSpacing = 10;
|
||||
|
||||
int y = perspectiveButton.yPos() + verticalSpacing;
|
||||
|
||||
int i = 0;
|
||||
for(GuiElement el : shoulderCamSettings.getParts()) {
|
||||
el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing));
|
||||
el.width(elementWidth);
|
||||
|
||||
el.yPos(y + ((i+1)%2)*7);
|
||||
|
||||
if(i%2 == 1) {
|
||||
y += verticalSpacing;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
SpectatorData data = (SpectatorData)keyframe.getValue();
|
||||
data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]);
|
||||
data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue();
|
||||
data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue();
|
||||
data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue();
|
||||
data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue();
|
||||
super.onGuiClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private static class KeyframeValueChangeListener implements NumberValueChangeListener {
|
||||
|
||||
private GuiEditKeyframe parent;
|
||||
|
||||
public KeyframeValueChangeListener(GuiEditKeyframe parent) {
|
||||
this.parent = parent;
|
||||
|
||||
parent.min.addValueChangeListener(this);
|
||||
parent.sec.addValueChangeListener(this);
|
||||
parent.ms.addValueChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChange(double value) {
|
||||
int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue());
|
||||
parent.keyframe.setRealTimestamp(realTimestamp);
|
||||
|
||||
ReplayHandler.fireKeyframesModifyEvent();
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// private static class GuiEditKeyframeMarker extends GuiEditKeyframe<Marker> {
|
||||
// private GuiAdvancedTextField markerNameInput;
|
||||
//
|
||||
// public GuiEditKeyframeMarker(Keyframe<Marker> keyframe) {
|
||||
// super(keyframe, ReplayHandler.getMarkerKeyframes());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initGui() {
|
||||
// super.initGui();
|
||||
//
|
||||
// if (!initialized) {
|
||||
// String name = keyframe.getValue().getName();
|
||||
// if (name == null) name = "";
|
||||
// markerNameInput = new GuiAdvancedTextField(fontRendererObj, 0, 0, 200, 20);
|
||||
// markerNameInput.hint = I18n.format("replaymod.gui.editkeyframe.markername");
|
||||
// markerNameInput.setText(name);
|
||||
//
|
||||
// inputs.addPart(markerNameInput);
|
||||
//
|
||||
// new KeyframeValueChangeListener(this);
|
||||
// }
|
||||
//
|
||||
// markerNameInput.xPosition = width/2 - 100;
|
||||
// markerNameInput.yPosition = height/2-10;
|
||||
//
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onGuiClosed() {
|
||||
// keyframe.getValue().setName(markerNameInput.getText().trim());
|
||||
// super.onGuiClosed();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static class GuiEditKeyframeTime extends GuiEditKeyframe<TimestampValue> {
|
||||
// private GuiNumberInput kfMin, kfSec, kfMs;
|
||||
//
|
||||
// public GuiEditKeyframeTime(Keyframe<TimestampValue> keyframe) {
|
||||
// super(keyframe, ReplayHandler.getTimeKeyframes());
|
||||
// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.time");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initGui() {
|
||||
// super.initGui();
|
||||
//
|
||||
// if (!initialized) {
|
||||
// int time = keyframe.getValue().asInt();
|
||||
//
|
||||
// kfMin = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 30, 0d, null, (double)TimestampUtils.timestampToWholeMinutes(time), false, "", 1);
|
||||
// kfSec = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 25, 0d, 59d, (double)TimestampUtils.getSecondsFromTimestamp(time), false, "", 1);
|
||||
// kfMs = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 35, 0d, 999d, (double)TimestampUtils.getMillisecondsFromTimestamp(time), false, "", 1);
|
||||
//
|
||||
// inputs.addPart(kfMin);
|
||||
// inputs.addPart(kfSec);
|
||||
// inputs.addPart(kfMs);
|
||||
//
|
||||
// KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
|
||||
// @Override
|
||||
// public void onValueChange(double value) {
|
||||
// keyframe.setValue(new TimestampValue(TimestampUtils.calculateTimestamp(
|
||||
// kfMin.getIntValue(), kfSec.getIntValue(), kfMs.getIntValue())));
|
||||
//
|
||||
// super.onValueChange(value);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// kfMin.addValueChangeListener(listener);
|
||||
// kfSec.addValueChangeListener(listener);
|
||||
// kfMs.addValueChangeListener(listener);
|
||||
// }
|
||||
//
|
||||
// kfMin.xPosition = min.xPosition;
|
||||
// kfSec.xPosition = sec.xPosition;
|
||||
// kfMs.xPosition = ms.xPosition;
|
||||
//
|
||||
// kfMin.yPosition = kfSec.yPosition = kfMs.yPosition = min.yPosition - 10 - 20;
|
||||
//
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void drawScreen0() {
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.timestamp")+":", (width-w3)/2, kfMin.yPosition + 7, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.minutes"), kfMin.xPosition + kfMin.width + 5, kfMin.yPosition + 7, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.seconds"), kfSec.xPosition + kfSec.width + 5, kfSec.yPosition + 7, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.milliseconds"), kfMs.xPosition + kfMs.width + 5, kfMs.yPosition + 7, Color.WHITE.getRGB());
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static class GuiEditKeyframePosition extends GuiEditKeyframe<AdvancedPosition> {
|
||||
// private GuiNumberInput xCoord, yCoord, zCoord, pitch, yaw, roll;
|
||||
// private ComposedElement posInputs;
|
||||
//
|
||||
// public GuiEditKeyframePosition(Keyframe<AdvancedPosition> keyframe) {
|
||||
// super(keyframe, ReplayHandler.getPositionKeyframes());
|
||||
// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.pos");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initGui() {
|
||||
// super.initGui();
|
||||
//
|
||||
// if (!initialized) {
|
||||
// AdvancedPosition pos = keyframe.getValue();
|
||||
// xCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getX()), true);
|
||||
// yCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getY()), true);
|
||||
// zCoord = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getZ()), true);
|
||||
// yaw = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getYaw()), true);
|
||||
// pitch = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, -90d, 90d, RoundUtils.round2Decimals(pos.getPitch()), true);
|
||||
// roll = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 100, null, null, RoundUtils.round2Decimals(pos.getRoll()), true);
|
||||
//
|
||||
// posInputs = new ComposedElement(xCoord, yCoord, zCoord, yaw, pitch, roll);
|
||||
// inputs.addPart(posInputs);
|
||||
//
|
||||
// KeyframeValueChangeListener listener = new KeyframeValueChangeListener(this) {
|
||||
// @Override
|
||||
// public void onValueChange(double value) {
|
||||
// keyframe.setValue(new AdvancedPosition(xCoord.getPreciseValue(), yCoord.getPreciseValue(),
|
||||
// zCoord.getPreciseValue(), new Float(pitch.getPreciseValue()), (float) yaw.getPreciseValue(),
|
||||
// (float) roll.getPreciseValue()));
|
||||
//
|
||||
// super.onValueChange(value);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// xCoord.addValueChangeListener(listener);
|
||||
// yCoord.addValueChangeListener(listener);
|
||||
// zCoord.addValueChangeListener(listener);
|
||||
// pitch.addValueChangeListener(listener);
|
||||
// yaw.addValueChangeListener(listener);
|
||||
// roll.addValueChangeListener(listener);
|
||||
// }
|
||||
//
|
||||
// int w = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.xpos")),
|
||||
// Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.ypos")),
|
||||
// fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.zpos"))));
|
||||
// w2 = Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camyaw")),
|
||||
// Math.max(fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.campitch")),
|
||||
// fontRendererObj.getStringWidth(I18n.format("replaymod.gui.editkeyframe.camroll"))));
|
||||
//
|
||||
// totalWidth = w +100+w2+100+5+5+10;
|
||||
// left = (this.width - totalWidth)/2;
|
||||
//
|
||||
// int x = w + left + 5;
|
||||
// int i = 0;
|
||||
// for(GuiElement input : posInputs.getParts()) {
|
||||
// if(input instanceof GuiTextField) {
|
||||
// GuiTextField textField = (GuiTextField)input;
|
||||
// textField.xPosition = i < 3 ? x : left+totalWidth-100;
|
||||
// textField.yPosition = i < 3 ? virtualY + 20 + i*30 : virtualY + 20 + (i-3)*30;
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void drawScreen0() {
|
||||
// if (keyframe.getValue() instanceof SpectatorData) return;
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.xpos"), left, virtualY + 27, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.ypos"), left, virtualY + 57, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.zpos"), left, virtualY + 87, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camyaw"), left + totalWidth - 100 - 5 - w2, virtualY + 27, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.campitch"), left + totalWidth - 100 - 5 - w2, virtualY + 57, Color.WHITE.getRGB());
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.editkeyframe.camroll"), left + totalWidth - 100 - 5 - w2, virtualY + 87, Color.WHITE.getRGB());
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static class GuiEditKeyframeSpectator extends GuiEditKeyframe<AdvancedPosition> {
|
||||
// private GuiToggleButton perspectiveButton;
|
||||
//
|
||||
// private GuiString shoulderDistanceString, shoulderPitchString, shoulderYawString, shoulderSmoothnessString;
|
||||
// private GuiDraggingNumberInput shoulderDistanceInput, shoulderPitchOffsetInput,
|
||||
// shoulderYawOffsetInput, shoulderSmoothnessInput;
|
||||
//
|
||||
// private ComposedElement spectatorCamSettings;
|
||||
// private ComposedElement shoulderCamSettings;
|
||||
//
|
||||
// private DelegatingElement perspectiveSettings = new DelegatingElement() {
|
||||
// @Override
|
||||
// public GuiElement delegate() {
|
||||
// switch(perspectiveButton.getValue()) {
|
||||
// case 0:
|
||||
// return spectatorCamSettings;
|
||||
// case 1:
|
||||
// return shoulderCamSettings;
|
||||
// default:
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// public GuiEditKeyframeSpectator(Keyframe<AdvancedPosition> keyframe) {
|
||||
// super(keyframe, ReplayHandler.getPositionKeyframes());
|
||||
// screenTitle = I18n.format("replaymod.gui.editkeyframe.title.spec");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initGui() {
|
||||
// super.initGui();
|
||||
//
|
||||
// if (!initialized) {
|
||||
// SpectatorData data = (SpectatorData)keyframe.getValue();
|
||||
//
|
||||
// perspectiveButton = new GuiToggleButton(0, 0, 0, 200, 20, I18n.format("replaymod.gui.editkeyframe.spec.method")+": ", new String[]{
|
||||
// I18n.format("replaymod.gui.editkeyframe.spec.method.firstperson"),
|
||||
// I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder")});
|
||||
//
|
||||
// perspectiveButton.setValue(Arrays.asList(SpectatorData.SpectatingMethod.values()).indexOf(data.getSpectatingMethod()));
|
||||
//
|
||||
// spectatorCamSettings = new ComposedElement();
|
||||
//
|
||||
// //create elements in shoulderCamSettings
|
||||
// shoulderDistanceString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.distance"));
|
||||
// shoulderPitchString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.pitch"));
|
||||
// shoulderYawString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.yaw"));
|
||||
// shoulderSmoothnessString = new GuiString(0, 0, Color.WHITE, I18n.format("replaymod.gui.editkeyframe.spec.method.shoulder.smoothness"));
|
||||
//
|
||||
// shoulderDistanceInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0d, 30d, data.getThirdPersonInfo().shoulderCamDistance, true, "", 0.1);
|
||||
// shoulderPitchOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, -90d, 90d, data.getThirdPersonInfo().shoulderCamPitchOffset, false, "°", 1);
|
||||
// shoulderYawOffsetInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, null, null, data.getThirdPersonInfo().shoulderCamYawOffset, false, "°", 1);
|
||||
// shoulderSmoothnessInput = new GuiDraggingNumberInput(fontRendererObj, 0, 0, 0, 0.1d, 3d, data.getThirdPersonInfo().shoulderCamSmoothness, true, "", 0.1);
|
||||
//
|
||||
// shoulderCamSettings = new ComposedElement(
|
||||
// shoulderDistanceString, shoulderDistanceInput,
|
||||
// shoulderPitchString, shoulderPitchOffsetInput,
|
||||
// shoulderYawString, shoulderYawOffsetInput,
|
||||
// shoulderSmoothnessString, shoulderSmoothnessInput);
|
||||
//
|
||||
// inputs.addPart(new ComposedElement(perspectiveButton, perspectiveSettings));
|
||||
// }
|
||||
//
|
||||
// perspectiveButton.xPosition = (this.width-perspectiveButton.width())/2;
|
||||
// perspectiveButton.yPosition = this.virtualY + 20;
|
||||
//
|
||||
// int verticalSpacing = 20 + 5;
|
||||
// int totalWidth = 300;
|
||||
// int elementWidth = 145;
|
||||
// int horizontalSpacing = 10;
|
||||
//
|
||||
// int y = perspectiveButton.yPos() + verticalSpacing;
|
||||
//
|
||||
// int i = 0;
|
||||
// for(GuiElement el : shoulderCamSettings.getParts()) {
|
||||
// el.xPos((width-totalWidth)/2 + (i%2)*(elementWidth + horizontalSpacing));
|
||||
// el.width(elementWidth);
|
||||
//
|
||||
// el.yPos(y + ((i+1)%2)*7);
|
||||
//
|
||||
// if(i%2 == 1) {
|
||||
// y += verticalSpacing;
|
||||
// }
|
||||
// i++;
|
||||
// }
|
||||
//
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onGuiClosed() {
|
||||
// SpectatorData data = (SpectatorData)keyframe.getValue();
|
||||
// data.setSpectatingMethod(SpectatorData.SpectatingMethod.values()[perspectiveButton.getValue()]);
|
||||
// data.getThirdPersonInfo().shoulderCamDistance = shoulderDistanceInput.getPreciseValue();
|
||||
// data.getThirdPersonInfo().shoulderCamPitchOffset = shoulderPitchOffsetInput.getIntValue();
|
||||
// data.getThirdPersonInfo().shoulderCamYawOffset = shoulderYawOffsetInput.getIntValue();
|
||||
// data.getThirdPersonInfo().shoulderCamSmoothness = shoulderSmoothnessInput.getPreciseValue();
|
||||
// super.onGuiClosed();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static class KeyframeValueChangeListener implements NumberValueChangeListener {
|
||||
//
|
||||
// private GuiEditKeyframe parent;
|
||||
//
|
||||
// public KeyframeValueChangeListener(GuiEditKeyframe parent) {
|
||||
// this.parent = parent;
|
||||
//
|
||||
// parent.min.addValueChangeListener(this);
|
||||
// parent.sec.addValueChangeListener(this);
|
||||
// parent.ms.addValueChangeListener(this);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onValueChange(double value) {
|
||||
// int realTimestamp = TimestampUtils.calculateTimestamp(parent.min.getIntValue(), parent.sec.getIntValue(), parent.ms.getIntValue());
|
||||
// parent.keyframe.setRealTimestamp(realTimestamp);
|
||||
//
|
||||
// ReplayHandler.fireKeyframesModifyEvent();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiEntryList;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.holders.KeyframeSet;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.CameraPathValidator;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -22,7 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay.NoOverlay {
|
||||
public class GuiKeyframeRepository extends GuiScreen {
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@@ -133,39 +129,40 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay
|
||||
|
||||
@Override
|
||||
public void actionPerformed(GuiButton button) {
|
||||
if(!button.enabled) return;
|
||||
switch(button.id) {
|
||||
case GuiConstants.KEYFRAME_REPOSITORY_ADD_BUTTON:
|
||||
List<Keyframe> kfs = new ArrayList<Keyframe>(ReplayHandler.getAllKeyframes());
|
||||
|
||||
Keyframe[] keyframes = kfs.toArray(new Keyframe[ReplayHandler.getAllKeyframes().size()]);
|
||||
KeyframeSet newSet = new KeyframeSet(I18n.format("replaymod.gui.keyframerepository.preset.defaultname"), keyframes, ReplayHandler.getCustomImageObjects());
|
||||
|
||||
try {
|
||||
CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes());
|
||||
} catch(CameraPathValidator.InvalidCameraPathException e) {
|
||||
message = e.getLocalizedMessage();
|
||||
break;
|
||||
}
|
||||
|
||||
if(keyframeSetList.getCopyOfElements().contains(newSet)) {
|
||||
message = I18n.format("replaymod.gui.keyframerepository.duplicate");
|
||||
break;
|
||||
}
|
||||
message = null;
|
||||
|
||||
keyframeSetList.addElement(newSet);
|
||||
keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1);
|
||||
break;
|
||||
case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON:
|
||||
keyframeSetList.removeElement(keyframeSetList.getSelectionIndex());
|
||||
break;
|
||||
case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON:
|
||||
ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex()));
|
||||
saveOnQuit();
|
||||
mc.displayGuiScreen(null);
|
||||
break;
|
||||
}
|
||||
// TODO
|
||||
// if(!button.enabled) return;
|
||||
// switch(button.id) {
|
||||
// case GuiConstants.KEYFRAME_REPOSITORY_ADD_BUTTON:
|
||||
// List<Keyframe> kfs = new ArrayList<Keyframe>(ReplayHandler.getAllKeyframes());
|
||||
//
|
||||
// Keyframe[] keyframes = kfs.toArray(new Keyframe[ReplayHandler.getAllKeyframes().size()]);
|
||||
// KeyframeSet newSet = new KeyframeSet(I18n.format("replaymod.gui.keyframerepository.preset.defaultname"), keyframes, ReplayHandler.getCustomImageObjects());
|
||||
//
|
||||
// try {
|
||||
// CameraPathValidator.validateCameraPath(ReplayHandler.getPositionKeyframes(), ReplayHandler.getTimeKeyframes());
|
||||
// } catch(CameraPathValidator.InvalidCameraPathException e) {
|
||||
// message = e.getLocalizedMessage();
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if(keyframeSetList.getCopyOfElements().contains(newSet)) {
|
||||
// message = I18n.format("replaymod.gui.keyframerepository.duplicate");
|
||||
// break;
|
||||
// }
|
||||
// message = null;
|
||||
//
|
||||
// keyframeSetList.addElement(newSet);
|
||||
// keyframeSetList.setSelectionIndex(keyframeSetList.getEntryCount()-1);
|
||||
// break;
|
||||
// case GuiConstants.KEYFRAME_REPOSITORY_REMOVE_BUTTON:
|
||||
// keyframeSetList.removeElement(keyframeSetList.getSelectionIndex());
|
||||
// break;
|
||||
// case GuiConstants.KEYFRAME_REPOSITORY_LOAD_BUTTON:
|
||||
// ReplayHandler.useKeyframePreset(keyframeSetList.getElement(keyframeSetList.getSelectionIndex()));
|
||||
// saveOnQuit();
|
||||
// mc.displayGuiScreen(null);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +238,8 @@ public class GuiKeyframeRepository extends GuiScreen implements GuiReplayOverlay
|
||||
if(initialKeyframeSets.equals(copy)) return;
|
||||
|
||||
this.keyframeRepository = copy.toArray(new KeyframeSet[copy.size()]);
|
||||
ReplayHandler.setKeyframeRepository(keyframeRepository, true);
|
||||
// TODO
|
||||
// ReplayHandler.setKeyframeRepository(keyframeRepository, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,347 +1,314 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import com.mojang.realmsclient.util.Pair;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.holders.PlayerVisibility;
|
||||
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import eu.crushedpixel.replaymod.utils.SkinProvider;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EnumPlayerModelParts;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.client.config.GuiCheckBox;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiPlayerOverview extends GuiScreen implements GuiReplayOverlay.NoOverlay {
|
||||
public class GuiPlayerOverview extends GuiScreen {
|
||||
|
||||
public static boolean defaultSave = false;
|
||||
|
||||
private List<Pair<EntityPlayer, ResourceLocation>> players;
|
||||
private List<GuiCheckBox> checkBoxes;
|
||||
|
||||
private GuiCheckBox hideAllBox, showAllBox;
|
||||
private GuiCheckBox rememberHidden;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private int playerCount;
|
||||
private int upperPlayer = 0;
|
||||
|
||||
private int lowerBound;
|
||||
|
||||
private boolean drag = false;
|
||||
private int lastY = 0;
|
||||
private int fitting = 0;
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private final String screenTitle = I18n.format("replaymod.input.playeroverview");
|
||||
|
||||
private final Set<UUID> initialHiddenPlayers;
|
||||
|
||||
public GuiPlayerOverview(List<EntityPlayer> players) {
|
||||
initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers());
|
||||
|
||||
Collections.sort(players, new PlayerComparator());
|
||||
|
||||
this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
|
||||
this.checkBoxes = new ArrayList<GuiCheckBox>();
|
||||
|
||||
for(final EntityPlayer p : players) {
|
||||
final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID());
|
||||
this.players.add(Pair.of(p, loc));
|
||||
}
|
||||
|
||||
playerCount = players.size();
|
||||
|
||||
ReplayMod.replaySender.setReplaySpeed(0);
|
||||
}
|
||||
|
||||
private boolean isSpectator(EntityPlayer e) {
|
||||
return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
|
||||
throws IOException {
|
||||
|
||||
if(fitting < playerCount) {
|
||||
float visiblePerc = (float) fitting / (float) playerCount;
|
||||
|
||||
int h = this.height - 32 - 32;
|
||||
int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h);
|
||||
|
||||
int lower = Math.round(32 + offset + (h * visiblePerc)) - 2;
|
||||
|
||||
int k2 = (int) (this.width * 0.3);
|
||||
|
||||
if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) {
|
||||
lastY = mouseY;
|
||||
drag = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
int k2 = (int) (this.width * 0.3);
|
||||
|
||||
if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) {
|
||||
int off = mouseY - upperBound;
|
||||
int p = (off / 21) + upperPlayer;
|
||||
ReplayHandler.spectateEntity(players.get(p).first());
|
||||
mc.displayGuiScreen(null);
|
||||
}
|
||||
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClickMove(int mouseX, int mouseY,
|
||||
int clickedMouseButton, long timeSinceLastClick) {
|
||||
|
||||
if(drag) {
|
||||
float step = 1f / (float) playerCount;
|
||||
|
||||
int diff = mouseY - lastY;
|
||||
int h = this.height - 32 - 32;
|
||||
|
||||
float percDiff = (float) diff / (float) h;
|
||||
if(Math.abs(percDiff) > Math.abs(step)) {
|
||||
int s = (int) (percDiff / step);
|
||||
lastY = mouseY;
|
||||
upperPlayer += s;
|
||||
if(upperPlayer > playerCount - fitting) {
|
||||
upperPlayer = playerCount - fitting;
|
||||
} else if(upperPlayer < 0) {
|
||||
upperPlayer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||
drag = false;
|
||||
|
||||
for(GuiCheckBox checkBox : checkBoxes) {
|
||||
checkBox.mouseReleased(mouseX, mouseY);
|
||||
}
|
||||
|
||||
super.mouseReleased(mouseX, mouseY, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
upperPlayer = 0;
|
||||
lowerBound = this.height - 10;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = this.buttonList;
|
||||
|
||||
int i = 0;
|
||||
for(GuiCheckBox checkBox : checkBoxes) {
|
||||
checkBox.xPosition = (int)(this.width*0.7)-5;
|
||||
buttonList.add(checkBox);
|
||||
i++;
|
||||
if(i >= fitting) break;
|
||||
}
|
||||
|
||||
if(!initialized) {
|
||||
hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false);
|
||||
showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true);
|
||||
rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave);
|
||||
}
|
||||
|
||||
hideAllBox.xPosition = (int)(this.width*0.7)-5;
|
||||
showAllBox.xPosition = (int)(this.width*0.7)-20;
|
||||
hideAllBox.yPosition = showAllBox.yPosition = 45;
|
||||
|
||||
rememberHidden.xPosition = (int)(this.width*0.3);
|
||||
rememberHidden.yPosition = 45;
|
||||
|
||||
buttonList.add(hideAllBox);
|
||||
buttonList.add(showAllBox);
|
||||
buttonList.add(rememberHidden);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) throws IOException {
|
||||
if(button == showAllBox) {
|
||||
showAllBox.setIsChecked(true);
|
||||
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
PlayerHandler.showPlayer(p.first());
|
||||
}
|
||||
} else if(button == hideAllBox) {
|
||||
hideAllBox.setIsChecked(false);
|
||||
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
PlayerHandler.hidePlayer(p.first());
|
||||
}
|
||||
}
|
||||
|
||||
if(!(button instanceof GuiCheckBox)) return;
|
||||
if(button.id >= fitting) return;
|
||||
if(!checkBoxes.contains(button)) return;
|
||||
PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked());
|
||||
}
|
||||
|
||||
private static final int upperBound = 65;
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB());
|
||||
int k2 = (int)(this.width * 0.3);
|
||||
int l2 = upperBound;
|
||||
|
||||
drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680);
|
||||
|
||||
drawString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.spectate"), k2 - 10, 30, Color.WHITE.getRGB());
|
||||
|
||||
String visibleString = I18n.format("replaymod.gui.playeroverview.visible");
|
||||
drawString(fontRendererObj, visibleString, (int) (this.width * 0.7) + 10 - fontRendererObj.getStringWidth(visibleString), 30, Color.WHITE.getRGB());
|
||||
|
||||
fitting = 0;
|
||||
|
||||
int sk = 0;
|
||||
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
if(sk < upperPlayer) {
|
||||
sk++;
|
||||
continue;
|
||||
}
|
||||
boolean spec = isSpectator(p.first());
|
||||
|
||||
this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2),
|
||||
spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB());
|
||||
|
||||
mc.getTextureManager().bindTexture(p.second());
|
||||
|
||||
drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||
if(p.first().func_175148_a(EnumPlayerModelParts.HAT))
|
||||
Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||
|
||||
GlStateManager.resetColor();
|
||||
if(fitting >= checkBoxes.size()) {
|
||||
checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true));
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = this.buttonList;
|
||||
buttonList.add(checkBoxes.get(checkBoxes.size() - 1));
|
||||
}
|
||||
checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID()));
|
||||
|
||||
l2 += 16 + 5;
|
||||
fitting++;
|
||||
if(l2 + 32 > lowerBound) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int dw = Mouse.getDWheel();
|
||||
if(dw > 0) {
|
||||
dw = -1;
|
||||
} else if(dw < 0) {
|
||||
dw = 1;
|
||||
}
|
||||
|
||||
upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0);
|
||||
|
||||
if(fitting < playerCount) {
|
||||
float visiblePerc = ((float) fitting) / playerCount;
|
||||
int barHeight = (int) (visiblePerc * (height - 32 - 32));
|
||||
|
||||
float posPerc = ((float) upperPlayer) / playerCount;
|
||||
int barY = (int) (posPerc * (height - 32 - 32));
|
||||
|
||||
drawRect(k2 - 18, upperBound - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB());
|
||||
drawRect(k2 - 16, upperBound+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB());
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for(GuiCheckBox checkBox : checkBoxes) {
|
||||
checkBox.drawButton(mc, mouseX, mouseY);
|
||||
i++;
|
||||
if(i >= fitting) break;
|
||||
}
|
||||
|
||||
hideAllBox.drawButton(mc, mouseX, mouseY);
|
||||
showAllBox.drawButton(mc, mouseX, mouseY);
|
||||
rememberHidden.drawButton(mc, mouseX, mouseY);
|
||||
|
||||
if(hideAllBox.isMouseOver()) {
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.hideall"), this, Color.WHITE);
|
||||
}
|
||||
|
||||
if(showAllBox.isMouseOver()) {
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.showall"), this, Color.WHITE);
|
||||
}
|
||||
|
||||
if(rememberHidden.isMouseOver()) {
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.remembersettings.description"), this, Color.WHITE);
|
||||
}
|
||||
|
||||
//this is necessary to reset the GL parameters for further GUI rendering
|
||||
GlStateManager.enableBlend();
|
||||
}
|
||||
|
||||
private PlayerVisibility getVisibilityInstance() {
|
||||
Set<UUID> hidden = PlayerHandler.getHiddenPlayers();
|
||||
return new PlayerVisibility(hidden.toArray(new UUID[hidden.size()]));
|
||||
}
|
||||
|
||||
|
||||
private void saveOnQuit() {
|
||||
if(rememberHidden.isChecked()) {
|
||||
if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return;
|
||||
try {
|
||||
File f = File.createTempFile(ReplayFile.ENTRY_VISIBILITY, "json");
|
||||
ReplayFileIO.write(getVisibilityInstance(), f);
|
||||
ReplayMod.replayFileAppender.registerModifiedFile(f, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
if(initialHiddenPlayers.isEmpty()) return;
|
||||
ReplayMod.replayFileAppender.registerModifiedFile(null, ReplayFile.ENTRY_VISIBILITY, ReplayHandler.getReplayFile());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char typedChar, int keyCode) throws IOException {
|
||||
if(keyCode == Keyboard.KEY_ESCAPE) {
|
||||
saveOnQuit();
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
private class PlayerComparator implements Comparator<EntityPlayer> {
|
||||
|
||||
@Override
|
||||
public int compare(EntityPlayer o1, EntityPlayer o2) {
|
||||
if(isSpectator(o1) && !isSpectator(o2)) {
|
||||
return 1;
|
||||
} else if(isSpectator(o2) && !isSpectator(o1)) {
|
||||
return -1;
|
||||
} else {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// private List<Pair<EntityPlayer, ResourceLocation>> players;
|
||||
// private List<GuiCheckBox> checkBoxes;
|
||||
//
|
||||
// private GuiCheckBox hideAllBox, showAllBox;
|
||||
// private GuiCheckBox rememberHidden;
|
||||
//
|
||||
// private boolean initialized = false;
|
||||
//
|
||||
// private int playerCount;
|
||||
// private int upperPlayer = 0;
|
||||
//
|
||||
// private int lowerBound;
|
||||
//
|
||||
// private boolean drag = false;
|
||||
// private int lastY = 0;
|
||||
// private int fitting = 0;
|
||||
//
|
||||
// private final Minecraft mc = Minecraft.getMinecraft();
|
||||
//
|
||||
// private final String screenTitle = I18n.format("replaymod.input.playeroverview");
|
||||
//
|
||||
// private final Set<UUID> initialHiddenPlayers;
|
||||
//
|
||||
// public GuiPlayerOverview(List<EntityPlayer> players) {
|
||||
// initialHiddenPlayers = new HashSet<UUID>(PlayerHandler.getHiddenPlayers());
|
||||
//
|
||||
// Collections.sort(players, new PlayerComparator());
|
||||
//
|
||||
// this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
|
||||
// this.checkBoxes = new ArrayList<GuiCheckBox>();
|
||||
//
|
||||
// for(final EntityPlayer p : players) {
|
||||
// final ResourceLocation loc = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID());
|
||||
// this.players.add(Pair.of(p, loc));
|
||||
// }
|
||||
//
|
||||
// playerCount = players.size();
|
||||
//
|
||||
// ReplayMod.replaySender.setReplaySpeed(0);
|
||||
// }
|
||||
//
|
||||
// private boolean isSpectator(EntityPlayer e) {
|
||||
// return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
|
||||
// throws IOException {
|
||||
//
|
||||
// if(fitting < playerCount) {
|
||||
// float visiblePerc = (float) fitting / (float) playerCount;
|
||||
//
|
||||
// int h = this.height - 32 - 32;
|
||||
// int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h);
|
||||
//
|
||||
// int lower = Math.round(32 + offset + (h * visiblePerc)) - 2;
|
||||
//
|
||||
// int k2 = (int) (this.width * 0.3);
|
||||
//
|
||||
// if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) {
|
||||
// lastY = mouseY;
|
||||
// drag = true;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// int k2 = (int) (this.width * 0.3);
|
||||
//
|
||||
// if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= upperBound && mouseY <= lowerBound) {
|
||||
// int off = mouseY - upperBound;
|
||||
// int p = (off / 21) + upperPlayer;
|
||||
// // TODO
|
||||
//// ReplayHandler.spectateEntity(players.get(p).first());
|
||||
// mc.displayGuiScreen(null);
|
||||
// }
|
||||
//
|
||||
// super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void mouseClickMove(int mouseX, int mouseY,
|
||||
// int clickedMouseButton, long timeSinceLastClick) {
|
||||
//
|
||||
// if(drag) {
|
||||
// float step = 1f / (float) playerCount;
|
||||
//
|
||||
// int diff = mouseY - lastY;
|
||||
// int h = this.height - 32 - 32;
|
||||
//
|
||||
// float percDiff = (float) diff / (float) h;
|
||||
// if(Math.abs(percDiff) > Math.abs(step)) {
|
||||
// int s = (int) (percDiff / step);
|
||||
// lastY = mouseY;
|
||||
// upperPlayer += s;
|
||||
// if(upperPlayer > playerCount - fitting) {
|
||||
// upperPlayer = playerCount - fitting;
|
||||
// } else if(upperPlayer < 0) {
|
||||
// upperPlayer = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||
// drag = false;
|
||||
//
|
||||
// for(GuiCheckBox checkBox : checkBoxes) {
|
||||
// checkBox.mouseReleased(mouseX, mouseY);
|
||||
// }
|
||||
//
|
||||
// super.mouseReleased(mouseX, mouseY, state);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initGui() {
|
||||
// upperPlayer = 0;
|
||||
// lowerBound = this.height - 10;
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// List<GuiButton> buttonList = this.buttonList;
|
||||
//
|
||||
// int i = 0;
|
||||
// for(GuiCheckBox checkBox : checkBoxes) {
|
||||
// checkBox.xPosition = (int)(this.width*0.7)-5;
|
||||
// buttonList.add(checkBox);
|
||||
// i++;
|
||||
// if(i >= fitting) break;
|
||||
// }
|
||||
//
|
||||
// if(!initialized) {
|
||||
// hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false);
|
||||
// showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true);
|
||||
// rememberHidden = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_REMEMBER, 0, 0, I18n.format("replaymod.gui.playeroverview.remembersettings"), defaultSave);
|
||||
// }
|
||||
//
|
||||
// hideAllBox.xPosition = (int)(this.width*0.7)-5;
|
||||
// showAllBox.xPosition = (int)(this.width*0.7)-20;
|
||||
// hideAllBox.yPosition = showAllBox.yPosition = 45;
|
||||
//
|
||||
// rememberHidden.xPosition = (int)(this.width*0.3);
|
||||
// rememberHidden.yPosition = 45;
|
||||
//
|
||||
// buttonList.add(hideAllBox);
|
||||
// buttonList.add(showAllBox);
|
||||
// buttonList.add(rememberHidden);
|
||||
//
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void actionPerformed(GuiButton button) throws IOException {
|
||||
// if(button == showAllBox) {
|
||||
// showAllBox.setIsChecked(true);
|
||||
// for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
// PlayerHandler.showPlayer(p.first());
|
||||
// }
|
||||
// } else if(button == hideAllBox) {
|
||||
// hideAllBox.setIsChecked(false);
|
||||
// for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
// PlayerHandler.hidePlayer(p.first());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(!(button instanceof GuiCheckBox)) return;
|
||||
// if(button.id >= fitting) return;
|
||||
// if(!checkBoxes.contains(button)) return;
|
||||
// PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked());
|
||||
// }
|
||||
//
|
||||
// private static final int upperBound = 65;
|
||||
//
|
||||
// @Override
|
||||
// public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
// this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB());
|
||||
// int k2 = (int)(this.width * 0.3);
|
||||
// int l2 = upperBound;
|
||||
//
|
||||
// drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680);
|
||||
//
|
||||
// drawString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.spectate"), k2 - 10, 30, Color.WHITE.getRGB());
|
||||
//
|
||||
// String visibleString = I18n.format("replaymod.gui.playeroverview.visible");
|
||||
// drawString(fontRendererObj, visibleString, (int) (this.width * 0.7) + 10 - fontRendererObj.getStringWidth(visibleString), 30, Color.WHITE.getRGB());
|
||||
//
|
||||
// fitting = 0;
|
||||
//
|
||||
// int sk = 0;
|
||||
// for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||
// if(sk < upperPlayer) {
|
||||
// sk++;
|
||||
// continue;
|
||||
// }
|
||||
// boolean spec = isSpectator(p.first());
|
||||
//
|
||||
// this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2),
|
||||
// spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB());
|
||||
//
|
||||
// mc.getTextureManager().bindTexture(p.second());
|
||||
//
|
||||
// drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||
// if(p.first().func_175148_a(EnumPlayerModelParts.HAT))
|
||||
// Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||
//
|
||||
// GlStateManager.resetColor();
|
||||
// if(fitting >= checkBoxes.size()) {
|
||||
// checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true));
|
||||
// @SuppressWarnings("unchecked")
|
||||
// List<GuiButton> buttonList = this.buttonList;
|
||||
// buttonList.add(checkBoxes.get(checkBoxes.size() - 1));
|
||||
// }
|
||||
// checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getUniqueID()));
|
||||
//
|
||||
// l2 += 16 + 5;
|
||||
// fitting++;
|
||||
// if(l2 + 32 > lowerBound) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int dw = Mouse.getDWheel();
|
||||
// if(dw > 0) {
|
||||
// dw = -1;
|
||||
// } else if(dw < 0) {
|
||||
// dw = 1;
|
||||
// }
|
||||
//
|
||||
// upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0);
|
||||
//
|
||||
// if(fitting < playerCount) {
|
||||
// float visiblePerc = ((float) fitting) / playerCount;
|
||||
// int barHeight = (int) (visiblePerc * (height - 32 - 32));
|
||||
//
|
||||
// float posPerc = ((float) upperPlayer) / playerCount;
|
||||
// int barY = (int) (posPerc * (height - 32 - 32));
|
||||
//
|
||||
// drawRect(k2 - 18, upperBound - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB());
|
||||
// drawRect(k2 - 16, upperBound+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB());
|
||||
// }
|
||||
//
|
||||
// int i = 0;
|
||||
// for(GuiCheckBox checkBox : checkBoxes) {
|
||||
// checkBox.drawButton(mc, mouseX, mouseY);
|
||||
// i++;
|
||||
// if(i >= fitting) break;
|
||||
// }
|
||||
//
|
||||
// hideAllBox.drawButton(mc, mouseX, mouseY);
|
||||
// showAllBox.drawButton(mc, mouseX, mouseY);
|
||||
// rememberHidden.drawButton(mc, mouseX, mouseY);
|
||||
//
|
||||
// if(hideAllBox.isMouseOver()) {
|
||||
// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.hideall"), this, Color.WHITE);
|
||||
// }
|
||||
//
|
||||
// if(showAllBox.isMouseOver()) {
|
||||
// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.showall"), this, Color.WHITE);
|
||||
// }
|
||||
//
|
||||
// if(rememberHidden.isMouseOver()) {
|
||||
// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.playeroverview.remembersettings.description"), this, Color.WHITE);
|
||||
// }
|
||||
//
|
||||
// //this is necessary to reset the GL parameters for further GUI rendering
|
||||
// GlStateManager.enableBlend();
|
||||
// }
|
||||
//
|
||||
// private void saveOnQuit() {
|
||||
// try {
|
||||
// // TODO
|
||||
//// if(rememberHidden.isChecked()) {
|
||||
//// if(initialHiddenPlayers.equals(PlayerHandler.getHiddenPlayers())) return;
|
||||
//// ReplayHandler.getReplayFile().writeInvisiblePlayers(PlayerHandler.getHiddenPlayers());
|
||||
//// } else {
|
||||
//// if(initialHiddenPlayers.isEmpty()) return;
|
||||
//// ReplayHandler.getReplayFile().writeInvisiblePlayers(Collections.<UUID>emptySet());
|
||||
//// }
|
||||
// } catch(Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void keyTyped(char typedChar, int keyCode) throws IOException {
|
||||
// if(keyCode == Keyboard.KEY_ESCAPE) {
|
||||
// saveOnQuit();
|
||||
// super.keyTyped(typedChar, keyCode);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private class PlayerComparator implements Comparator<EntityPlayer> {
|
||||
//
|
||||
// @Override
|
||||
// public int compare(EntityPlayer o1, EntityPlayer o2) {
|
||||
// if(isSpectator(o1) && !isSpectator(o2)) {
|
||||
// return 1;
|
||||
// } else if(isSpectator(o2) && !isSpectator(o1)) {
|
||||
// return -1;
|
||||
// } else {
|
||||
// return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.*;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener;
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListEntry;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.settings.EncodingPreset;
|
||||
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
@@ -29,7 +27,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoOverlay {
|
||||
public class GuiRenderSettings extends GuiScreen {
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
@@ -542,7 +540,8 @@ public class GuiRenderSettings extends GuiScreen implements GuiReplayOverlay.NoO
|
||||
if(FMLClientHandler.instance().hasOptifine()) {
|
||||
mc.displayGuiScreen(new GuiErrorScreen(I18n.format("replaymod.gui.rendering.error.title"), I18n.format("replaymod.gui.rendering.error.optifine")));
|
||||
} else {
|
||||
ReplayHandler.startPath(options, true);
|
||||
// TODO
|
||||
// ReplayHandler.startPath(options, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiSettingsOnOffButton;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiToggleButton;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings.RecordingOptions;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings.ReplayOptions;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
@@ -12,8 +10,6 @@ import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static eu.crushedpixel.replaymod.gui.GuiConstants.*;
|
||||
|
||||
public class GuiReplaySettings extends GuiScreen {
|
||||
protected String screenTitle = I18n.format("replaymod.gui.settings.title");
|
||||
private GuiScreen parentGuiScreen;
|
||||
@@ -38,23 +34,23 @@ public class GuiReplaySettings extends GuiScreen {
|
||||
|
||||
int xPos = this.width / 2 - 155 + i % 2 * 160;
|
||||
int yPos = this.height / 6 + 24 * (i >> 1);
|
||||
|
||||
if(o == RecordingOptions.notifications) {
|
||||
GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o);
|
||||
buttonList.add(sendChatButton);
|
||||
|
||||
} else if(o == RecordingOptions.recordServer) {
|
||||
GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o);
|
||||
buttonList.add(recordServerButton);
|
||||
|
||||
} else if(o == RecordingOptions.recordSingleplayer) {
|
||||
GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o);
|
||||
buttonList.add(recordSPButton);
|
||||
|
||||
} else if(o == RecordingOptions.indicator) {
|
||||
GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o);
|
||||
buttonList.add(showIndicatorButton);
|
||||
}
|
||||
// TODO
|
||||
// if(o == RecordingOptions.notifications) {
|
||||
// GuiToggleButton sendChatButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_SEND_CHAT, xPos, yPos, 150, 20, o);
|
||||
// buttonList.add(sendChatButton);
|
||||
//
|
||||
// } else if(o == RecordingOptions.recordServer) {
|
||||
// GuiToggleButton recordServerButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSERVER_ID, xPos, yPos, 150, 20, o);
|
||||
// buttonList.add(recordServerButton);
|
||||
//
|
||||
// } else if(o == RecordingOptions.recordSingleplayer) {
|
||||
// GuiToggleButton recordSPButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_RECORDSP_ID, xPos, yPos, 150, 20, o);
|
||||
// buttonList.add(recordSPButton);
|
||||
//
|
||||
// } else if(o == RecordingOptions.indicator) {
|
||||
// GuiToggleButton showIndicatorButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_INDICATOR_ID, xPos, yPos, 150, 20, o);
|
||||
// buttonList.add(showIndicatorButton);
|
||||
// }
|
||||
|
||||
++i;
|
||||
}
|
||||
@@ -69,14 +65,15 @@ public class GuiReplaySettings extends GuiScreen {
|
||||
int xPos = this.width / 2 - 155 + i % 2 * 160;
|
||||
int yPos = this.height / 6 + 24 * (i >> 1);
|
||||
|
||||
if(o == ReplayOptions.linear) {
|
||||
GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o,
|
||||
I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic"));
|
||||
buttonList.add(linearButton);
|
||||
|
||||
} else {
|
||||
buttonList.add(new GuiSettingsOnOffButton(0, xPos, yPos, 150, 20, o));
|
||||
}
|
||||
// TODO
|
||||
// if(o == ReplayOptions.linear) {
|
||||
// GuiToggleButton linearButton = new GuiSettingsOnOffButton(REPLAY_SETTINGS_FORCE_LINEAR, xPos, yPos, 150, 20, o,
|
||||
// I18n.format("replaymod.gui.settings.interpolation.linear"), I18n.format("replaymod.gui.settings.interpolation.cubic"));
|
||||
// buttonList.add(linearButton);
|
||||
//
|
||||
// } else {
|
||||
// buttonList.add(new GuiSettingsOnOffButton(0, xPos, yPos, 150, 20, o));
|
||||
// }
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
|
||||
public class GuiReplaySpeedSlider extends GuiAdvancedButton {
|
||||
|
||||
@@ -74,7 +73,7 @@ public class GuiReplaySpeedSlider extends GuiAdvancedButton {
|
||||
l = packedFGColour;
|
||||
} else if(!this.enabled) {
|
||||
l = 10526880;
|
||||
} else if(this.hovered && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
||||
} else if(this.hovered) {
|
||||
l = 16777120;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.CheckBoxListener;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.fml.client.config.GuiCheckBox;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay;
|
||||
import eu.crushedpixel.replaymod.utils.OpenGLUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE;
|
||||
|
||||
public class GuiArrowButton extends GuiAdvancedButton {
|
||||
|
||||
private static final int TEXTURE_X = 40;
|
||||
@@ -42,7 +43,7 @@ public class GuiArrowButton extends GuiAdvancedButton {
|
||||
try {
|
||||
super.draw(mc, mouseX, mouseY, hovering);
|
||||
|
||||
mc.getTextureManager().bindTexture(GuiReplayOverlay.replay_gui);
|
||||
mc.getTextureManager().bindTexture(TEXTURE);
|
||||
|
||||
OpenGLUtils.drawRotatedRectWithCustomSizedTexture(xPosition+4, yPosition+4, dir.getRotation(),
|
||||
TEXTURE_X, TEXTURE_Y, TEXTURE_WIDTH, TEXTURE_HEIGHT, 128, 128);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListEntry;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
|
||||
@@ -6,8 +6,8 @@ import net.minecraft.client.renderer.GlStateManager;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE;
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
||||
import static org.lwjgl.opengl.GL11.GL_BLEND;
|
||||
import static org.lwjgl.opengl.GL11.glEnable;
|
||||
|
||||
@@ -105,7 +105,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
|
||||
@Override
|
||||
public void draw(Minecraft mc, int mouseX, int mouseY) {
|
||||
GlStateManager.resetColor();
|
||||
mc.renderEngine.bindTexture(replay_gui);
|
||||
mc.renderEngine.bindTexture(TEXTURE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// Background
|
||||
@@ -157,7 +157,7 @@ public class GuiScrollbar extends Gui implements GuiElement {
|
||||
if(!enabled) {
|
||||
GlStateManager.color(Color.GRAY.getRed()/255f, Color.GRAY.getGreen()/255f, Color.GRAY.getBlue()/255f, 1f);
|
||||
}
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(replay_gui);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE);
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||
import com.replaymod.core.SettingsRegistry;
|
||||
|
||||
public class GuiSettingsOnOffButton extends GuiOnOffButton {
|
||||
|
||||
private ReplaySettings.ValueEnum toChange;
|
||||
private SettingsRegistry settingsRegistry;
|
||||
private SettingsRegistry.SettingKey<Boolean> toChange;
|
||||
|
||||
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange) {
|
||||
super(buttonId, x, y, width, height, toChange.getName()+": ");
|
||||
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry,
|
||||
SettingsRegistry.SettingKey<Boolean> toChange) {
|
||||
super(buttonId, x, y, width, height, toChange.getDisplayString()+": ");
|
||||
this.settingsRegistry = settingsRegistry;
|
||||
this.toChange = toChange;
|
||||
if(toChange.getValue() instanceof Boolean) {
|
||||
this.setValue((Boolean) toChange.getValue() ? 0 : 1);
|
||||
}
|
||||
this.setValue(settingsRegistry.get(toChange) ? 0 : 1);
|
||||
}
|
||||
|
||||
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, ReplaySettings.ValueEnum toChange, String onValue, String offValue) {
|
||||
super(buttonId, x, y, width, height, toChange.getName()+": ", onValue, offValue);
|
||||
public GuiSettingsOnOffButton(int buttonId, int x, int y, int width, int height, SettingsRegistry settingsRegistry,
|
||||
SettingsRegistry.SettingKey<Boolean> toChange, String onValue, String offValue) {
|
||||
super(buttonId, x, y, width, height, toChange.getDisplayString()+": ", onValue, offValue);
|
||||
this.settingsRegistry = settingsRegistry;
|
||||
this.toChange = toChange;
|
||||
if(toChange.getValue() instanceof Boolean) {
|
||||
this.setValue((Boolean) toChange.getValue() ? 0 : 1);
|
||||
}
|
||||
this.setValue(settingsRegistry.get(toChange) ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
super.toggle();
|
||||
toChange.setValue(isOn());
|
||||
ReplayMod.replaySettings.rewriteSettings();
|
||||
settingsRegistry.set(toChange, isOn());
|
||||
settingsRegistry.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(int value) {
|
||||
super.setValue(value);
|
||||
toChange.setValue(isOn());
|
||||
ReplayMod.replaySettings.rewriteSettings();
|
||||
settingsRegistry.set(toChange, isOn());
|
||||
settingsRegistry.save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements.timelines;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiEditKeyframe;
|
||||
import eu.crushedpixel.replaymod.holders.*;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
|
||||
import java.util.ListIterator;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
|
||||
public class GuiKeyframeTimeline extends GuiTimeline {
|
||||
private static final int KEYFRAME_PLACE_X = 74;
|
||||
@@ -31,230 +24,231 @@ public class GuiKeyframeTimeline extends GuiTimeline {
|
||||
this.placeKeyframes = showPlaceKeyframes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
if(!enabled) return false;
|
||||
|
||||
long time = getTimeAt(mouseX, mouseY);
|
||||
if(time == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
Keyframe closest;
|
||||
if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) {
|
||||
closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
|
||||
} else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) {
|
||||
closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
|
||||
} else {
|
||||
closest = null;
|
||||
}
|
||||
|
||||
//left mouse button
|
||||
if(button == 0) {
|
||||
ReplayHandler.selectKeyframe(closest); //can be null, deselects keyframe
|
||||
|
||||
// If we clicked on a key frame, then continue monitoring the mouse for movements
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(closest != null) {
|
||||
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
|
||||
mc.displayGuiScreen(GuiEditKeyframe.create(closest));
|
||||
this.clickedKeyFrame = null;
|
||||
} else {
|
||||
this.clickedKeyFrame = closest;
|
||||
this.dragging = false;
|
||||
}
|
||||
} else { // If we didn't then just update the cursor
|
||||
ReplayHandler.setRealTimelineCursor((int) time);
|
||||
this.dragging = true;
|
||||
}
|
||||
this.clickTime = currentTime;
|
||||
|
||||
} else if(button == 1) {
|
||||
if(closest != null) {
|
||||
if(closest.getValue() instanceof AdvancedPosition) {
|
||||
AdvancedPosition pos = (AdvancedPosition)closest.getValue();
|
||||
ReplayHandler.getCameraEntity().movePath(pos);
|
||||
} else if(closest.getValue() instanceof TimestampValue) {
|
||||
ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isHovering(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
if(!enabled) return;
|
||||
long time = getTimeAt(mouseX, mouseY);
|
||||
if (time != -1) {
|
||||
if (clickedKeyFrame != null) {
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) {
|
||||
clickedKeyFrame.setRealTimestamp((int) time);
|
||||
ReplayHandler.getPositionKeyframes().sort();
|
||||
ReplayHandler.getTimeKeyframes().sort();
|
||||
dragging = true;
|
||||
}
|
||||
} else if (dragging) {
|
||||
ReplayHandler.setRealTimelineCursor((int) time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
mouseDrag(mc, mouseX, mouseY, button);
|
||||
clickedKeyFrame = null;
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Minecraft mc, int mouseX, int mouseY) {
|
||||
super.draw(mc, mouseX, mouseY);
|
||||
|
||||
int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
|
||||
|
||||
long leftTime = Math.round(timeStart * timelineLength);
|
||||
long rightTime = Math.round((timeStart + zoom) * timelineLength);
|
||||
|
||||
double segmentLength = timelineLength * zoom;
|
||||
|
||||
//iterate over keyframes to find spectator segments
|
||||
if(placeKeyframes) {
|
||||
ListIterator<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator();
|
||||
while(iterator.hasNext()) {
|
||||
Keyframe<AdvancedPosition> kf = iterator.next();
|
||||
|
||||
if(!(kf.getValue() instanceof SpectatorData))
|
||||
continue;
|
||||
|
||||
int i = iterator.nextIndex();
|
||||
int nextSpectatorKeyframeRealTime = -1;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
Keyframe<AdvancedPosition> kf2 = iterator.next();
|
||||
|
||||
if(kf2.getValue() instanceof SpectatorData) {
|
||||
SpectatorData spectatorData1 = (SpectatorData)kf.getValue();
|
||||
SpectatorData spectatorData2 = (SpectatorData)kf2.getValue();
|
||||
|
||||
if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) {
|
||||
nextSpectatorKeyframeRealTime = kf2.getRealTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i2 = iterator.previousIndex();
|
||||
|
||||
while(i2 >= i) {
|
||||
iterator.previous();
|
||||
i2--;
|
||||
}
|
||||
|
||||
if(nextSpectatorKeyframeRealTime != -1) {
|
||||
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength);
|
||||
|
||||
int color = ((SpectatorData)kf.getValue()).getSpectatingMethod().getColor();
|
||||
|
||||
drawRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 1, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1),
|
||||
positionY + BORDER_TOP + 4, color);
|
||||
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//iterate over time keyframes to find negative replay speeds
|
||||
if(timeKeyframes) {
|
||||
ListIterator<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator();
|
||||
while(iterator.hasNext()) {
|
||||
Keyframe<TimestampValue> kf = iterator.next();
|
||||
|
||||
int i = iterator.nextIndex();
|
||||
int nextTimeKeyframeRealTime = -1;
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
Keyframe<TimestampValue> kf2 = iterator.next();
|
||||
if(kf.getValue().asInt() > kf2.getValue().asInt()) {
|
||||
nextTimeKeyframeRealTime = kf2.getRealTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
int i2 = iterator.previousIndex();
|
||||
|
||||
while(i2 >= i) {
|
||||
iterator.previous();
|
||||
i2--;
|
||||
}
|
||||
|
||||
if(nextTimeKeyframeRealTime != -1) {
|
||||
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
int nextX = getKeyframeX(nextTimeKeyframeRealTime, leftTime, bodyWidth, segmentLength);
|
||||
|
||||
drawGradientRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 6, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1),
|
||||
positionY + BORDER_TOP + 9, 0xFFFF0000, 0xFFFF0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawTimelineCursor(leftTime, rightTime, bodyWidth);
|
||||
|
||||
|
||||
//Draw Keyframe logos
|
||||
for (Keyframe kf : ReplayHandler.getAllKeyframes()) {
|
||||
if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe()))
|
||||
drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength);
|
||||
}
|
||||
|
||||
if(ReplayHandler.getSelectedKeyframe() != null && !(ReplayHandler.getSelectedKeyframe().getValue() instanceof Marker)) {
|
||||
drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
|
||||
long positionInSegment = timestamp - leftTime;
|
||||
double fractionOfSegment = positionInSegment / segmentLength;
|
||||
return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
|
||||
}
|
||||
|
||||
private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
|
||||
if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) {
|
||||
int textureX;
|
||||
int textureY;
|
||||
int y = positionY;
|
||||
|
||||
int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
|
||||
if(kf.getValue() instanceof AdvancedPosition) {
|
||||
if(!placeKeyframes) return;
|
||||
textureX = KEYFRAME_PLACE_X;
|
||||
textureY = KEYFRAME_PLACE_Y;
|
||||
y += 0;
|
||||
|
||||
//If Spectator Keyframe, use different texture
|
||||
if(kf.getValue() instanceof SpectatorData) {
|
||||
textureX = KEYFRAME_SPEC_X;
|
||||
textureY = KEYFRAME_SPEC_Y;
|
||||
}
|
||||
} else if(kf.getValue() instanceof TimestampValue) {
|
||||
if(!timeKeyframes) return;
|
||||
textureX = KEYFRAME_TIME_X;
|
||||
textureY = KEYFRAME_TIME_Y;
|
||||
y += 5;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass());
|
||||
}
|
||||
|
||||
if (ReplayHandler.isSelected(kf)) {
|
||||
textureX += 5;
|
||||
}
|
||||
|
||||
rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// @Override
|
||||
// public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
// if(!enabled) return false;
|
||||
//
|
||||
// long time = getTimeAt(mouseX, mouseY);
|
||||
// if(time == -1) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
//
|
||||
// Keyframe closest;
|
||||
// if(mouseY >= positionY + BORDER_TOP + 5 && timeKeyframes) {
|
||||
// closest = ReplayHandler.getTimeKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
|
||||
// } else if(mouseY >= positionY + BORDER_TOP && placeKeyframes) {
|
||||
// closest = ReplayHandler.getPositionKeyframes().getClosestKeyframeForTimestamp((int) time, tolerance);
|
||||
// } else {
|
||||
// closest = null;
|
||||
// }
|
||||
//
|
||||
// //left mouse button
|
||||
// if(button == 0) {
|
||||
// ReplayHandler.selectKeyframe(closest); //can be null, deselects keyframe
|
||||
//
|
||||
// // If we clicked on a key frame, then continue monitoring the mouse for movements
|
||||
// long currentTime = System.currentTimeMillis();
|
||||
// if(closest != null) {
|
||||
// if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
|
||||
// mc.displayGuiScreen(GuiEditKeyframe.create(closest));
|
||||
// this.clickedKeyFrame = null;
|
||||
// } else {
|
||||
// this.clickedKeyFrame = closest;
|
||||
// this.dragging = false;
|
||||
// }
|
||||
// } else { // If we didn't then just update the cursor
|
||||
// ReplayHandler.setRealTimelineCursor((int) time);
|
||||
// this.dragging = true;
|
||||
// }
|
||||
// this.clickTime = currentTime;
|
||||
//
|
||||
// } else if(button == 1) {
|
||||
// if(closest != null) {
|
||||
// if(closest.getValue() instanceof AdvancedPosition) {
|
||||
// AdvancedPosition pos = (AdvancedPosition)closest.getValue();
|
||||
// ReplayHandler.getCameraEntity().movePath(pos);
|
||||
// } else if(closest.getValue() instanceof TimestampValue) {
|
||||
// ReplayMod.overlay.performJump(((TimestampValue)closest.getValue()).asInt());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return isHovering(mouseX, mouseY);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
// if(!enabled) return;
|
||||
// long time = getTimeAt(mouseX, mouseY);
|
||||
// if (time != -1) {
|
||||
// if (clickedKeyFrame != null) {
|
||||
// int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
//
|
||||
// if (dragging || Math.abs(clickedKeyFrame.getRealTimestamp() - time) > tolerance) {
|
||||
// clickedKeyFrame.setRealTimestamp((int) time);
|
||||
// ReplayHandler.getPositionKeyframes().sort();
|
||||
// ReplayHandler.getTimeKeyframes().sort();
|
||||
// dragging = true;
|
||||
// }
|
||||
// } else if (dragging) {
|
||||
// ReplayHandler.setRealTimelineCursor((int) time);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
// mouseDrag(mc, mouseX, mouseY, button);
|
||||
// clickedKeyFrame = null;
|
||||
// dragging = false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void draw(Minecraft mc, int mouseX, int mouseY) {
|
||||
// super.draw(mc, mouseX, mouseY);
|
||||
//
|
||||
// int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
|
||||
//
|
||||
// long leftTime = Math.round(timeStart * timelineLength);
|
||||
// long rightTime = Math.round((timeStart + zoom) * timelineLength);
|
||||
//
|
||||
// double segmentLength = timelineLength * zoom;
|
||||
//
|
||||
// //iterate over keyframes to find spectator segments
|
||||
// if(placeKeyframes) {
|
||||
// ListIterator<Keyframe<AdvancedPosition>> iterator = ReplayHandler.getPositionKeyframes().listIterator();
|
||||
// while(iterator.hasNext()) {
|
||||
// Keyframe<AdvancedPosition> kf = iterator.next();
|
||||
//
|
||||
// if(!(kf.getValue() instanceof SpectatorData))
|
||||
// continue;
|
||||
//
|
||||
// int i = iterator.nextIndex();
|
||||
// int nextSpectatorKeyframeRealTime = -1;
|
||||
//
|
||||
// if (iterator.hasNext()) {
|
||||
// Keyframe<AdvancedPosition> kf2 = iterator.next();
|
||||
//
|
||||
// if(kf2.getValue() instanceof SpectatorData) {
|
||||
// SpectatorData spectatorData1 = (SpectatorData)kf.getValue();
|
||||
// SpectatorData spectatorData2 = (SpectatorData)kf2.getValue();
|
||||
//
|
||||
// if(spectatorData1.getSpectatedEntityID() == spectatorData2.getSpectatedEntityID()) {
|
||||
// nextSpectatorKeyframeRealTime = kf2.getRealTimestamp();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int i2 = iterator.previousIndex();
|
||||
//
|
||||
// while(i2 >= i) {
|
||||
// iterator.previous();
|
||||
// i2--;
|
||||
// }
|
||||
//
|
||||
// if(nextSpectatorKeyframeRealTime != -1) {
|
||||
// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
// int nextX = getKeyframeX(nextSpectatorKeyframeRealTime, leftTime, bodyWidth, segmentLength);
|
||||
//
|
||||
// int color = ((SpectatorData)kf.getValue()).getSpectatingMethod().getColor();
|
||||
//
|
||||
// drawRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 1, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1),
|
||||
// positionY + BORDER_TOP + 4, color);
|
||||
//
|
||||
// GlStateManager.color(1, 1, 1, 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //iterate over time keyframes to find negative replay speeds
|
||||
// if(timeKeyframes) {
|
||||
// ListIterator<Keyframe<TimestampValue>> iterator = ReplayHandler.getTimeKeyframes().listIterator();
|
||||
// while(iterator.hasNext()) {
|
||||
// Keyframe<TimestampValue> kf = iterator.next();
|
||||
//
|
||||
// int i = iterator.nextIndex();
|
||||
// int nextTimeKeyframeRealTime = -1;
|
||||
//
|
||||
// if (iterator.hasNext()) {
|
||||
// Keyframe<TimestampValue> kf2 = iterator.next();
|
||||
// if(kf.getValue().asInt() > kf2.getValue().asInt()) {
|
||||
// nextTimeKeyframeRealTime = kf2.getRealTimestamp();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int i2 = iterator.previousIndex();
|
||||
//
|
||||
// while(i2 >= i) {
|
||||
// iterator.previous();
|
||||
// i2--;
|
||||
// }
|
||||
//
|
||||
// if(nextTimeKeyframeRealTime != -1) {
|
||||
// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
// int nextX = getKeyframeX(nextTimeKeyframeRealTime, leftTime, bodyWidth, segmentLength);
|
||||
//
|
||||
// drawGradientRect(Math.max(keyframeX + 2, positionX+BORDER_LEFT), positionY + BORDER_TOP + 6, Math.min(nextX - 2, positionX+width-BORDER_RIGHT+1),
|
||||
// positionY + BORDER_TOP + 9, 0xFFFF0000, 0xFFFF0000);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// drawTimelineCursor(leftTime, rightTime, bodyWidth);
|
||||
//
|
||||
//
|
||||
// //Draw Keyframe logos
|
||||
// for (Keyframe kf : ReplayHandler.getAllKeyframes()) {
|
||||
// if (kf != null && !kf.equals(ReplayHandler.getSelectedKeyframe()))
|
||||
// drawKeyframe(kf, bodyWidth, leftTime, rightTime, segmentLength);
|
||||
// }
|
||||
//
|
||||
// if(ReplayHandler.getSelectedKeyframe() != null) {
|
||||
// drawKeyframe(ReplayHandler.getSelectedKeyframe(), bodyWidth, leftTime, rightTime, segmentLength);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private int getKeyframeX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
|
||||
// long positionInSegment = timestamp - leftTime;
|
||||
// double fractionOfSegment = positionInSegment / segmentLength;
|
||||
// return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
|
||||
// }
|
||||
//
|
||||
// private void drawKeyframe(Keyframe kf, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
|
||||
// if (kf.getRealTimestamp() <= rightTime && kf.getRealTimestamp() >= leftTime) {
|
||||
// int textureX;
|
||||
// int textureY;
|
||||
// int y = positionY;
|
||||
//
|
||||
// int keyframeX = getKeyframeX(kf.getRealTimestamp(), leftTime, bodyWidth, segmentLength);
|
||||
//
|
||||
// if(kf.getValue() instanceof AdvancedPosition) {
|
||||
// if(!placeKeyframes) return;
|
||||
// textureX = KEYFRAME_PLACE_X;
|
||||
// textureY = KEYFRAME_PLACE_Y;
|
||||
// y += 0;
|
||||
//
|
||||
// //If Spectator Keyframe, use different texture
|
||||
// if(kf.getValue() instanceof SpectatorData) {
|
||||
// textureX = KEYFRAME_SPEC_X;
|
||||
// textureY = KEYFRAME_SPEC_Y;
|
||||
// }
|
||||
// } else if(kf.getValue() instanceof TimestampValue) {
|
||||
// if(!timeKeyframes) return;
|
||||
// textureX = KEYFRAME_TIME_X;
|
||||
// textureY = KEYFRAME_TIME_Y;
|
||||
// y += 5;
|
||||
// } else {
|
||||
// throw new UnsupportedOperationException("Unknown keyframe type: " + kf.getClass());
|
||||
// }
|
||||
//
|
||||
// if (ReplayHandler.isSelected(kf)) {
|
||||
// textureX += 5;
|
||||
// }
|
||||
//
|
||||
// rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.elements.timelines;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiElement;
|
||||
import eu.crushedpixel.replaymod.utils.RoundUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -11,8 +11,8 @@ import net.minecraft.client.renderer.GlStateManager;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.TEXTURE_SIZE;
|
||||
import static eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay.replay_gui;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE;
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
||||
import static org.lwjgl.opengl.GL11.GL_BLEND;
|
||||
import static org.lwjgl.opengl.GL11.glEnable;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
* This draws the time at big markers above the timeline. Therefore extra space in negative y direction
|
||||
* should be kept empty if markers are desired.
|
||||
*/
|
||||
public boolean showMarkers;
|
||||
public boolean showMarkers; // TODO: Rename to not be confused with Marker
|
||||
|
||||
protected final int positionX;
|
||||
protected final int positionY;
|
||||
@@ -280,7 +280,7 @@ public class GuiTimeline extends Gui implements GuiElement {
|
||||
if(!enabled) {
|
||||
GlStateManager.color(Color.GRAY.getRed() / 255f, Color.GRAY.getGreen() / 255f, Color.GRAY.getBlue() / 255f, 1f);
|
||||
}
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(replay_gui);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
drawModalRectWithCustomSizedTexture(x, y, u, v, width, height, TEXTURE_SIZE, TEXTURE_SIZE);
|
||||
|
||||
@@ -6,7 +6,7 @@ import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.element.GuiPasswordField;
|
||||
import de.johni0702.minecraft.gui.element.GuiTextField;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
|
||||
public class GuiLoginPrompt extends AbstractGuiScreen<GuiLoginPrompt> {
|
||||
|
||||
@@ -7,7 +7,7 @@ import de.johni0702.minecraft.gui.element.*;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.ApiException;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.utils.EmailAddressUtils;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.SearchQuery;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.Category;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
@@ -12,7 +12,6 @@ import eu.crushedpixel.replaymod.api.replay.pagination.Pagination;
|
||||
import eu.crushedpixel.replaymod.api.replay.pagination.SearchPagination;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.elements.*;
|
||||
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry;
|
||||
import net.minecraft.client.gui.*;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -265,7 +264,8 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
} else if(button.id == GuiConstants.CENTER_LOGOUT_BUTTON) {
|
||||
mc.displayGuiScreen(getYesNoGui(this, LOGOUT_CALLBACK_ID));
|
||||
} else if(button.id == GuiConstants.CENTER_MANAGER_BUTTON) {
|
||||
mc.displayGuiScreen(new GuiReplayViewer());
|
||||
// TODO
|
||||
// mc.displayGuiScreen(new GuiReplayViewer(mod));
|
||||
} else if(button.id == GuiConstants.CENTER_RECENT_BUTTON) {
|
||||
disableTopBarButton(button.id);
|
||||
showOnlineRecent();
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import com.mojang.realmsclient.gui.ChatFormatting;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
|
||||
import de.johni0702.minecraft.gui.element.GuiButton;
|
||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -49,7 +48,8 @@ public class GuiReplayDownloading extends AbstractGuiScreen<GuiReplayDownloading
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ReplayHandler.startReplay(replayFile);
|
||||
// TODO
|
||||
// ReplayHandler.startReplay(replayFile);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import eu.crushedpixel.replaymod.gui.elements.GuiAdvancedButton;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiDropdown;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiString;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListValueEntry;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -55,7 +53,7 @@ public class GuiReplayInstanceChooser extends GuiScreen {
|
||||
for(File file : files) {
|
||||
try {
|
||||
String extension = FilenameUtils.getExtension(file.getAbsolutePath());
|
||||
if(!("." + extension).equals(ReplayFile.ZIP_FILE_EXTENSION)) continue;
|
||||
if(!"zip".equals(extension)) continue;
|
||||
|
||||
String filename = FilenameUtils.getBaseName(file.getAbsolutePath());
|
||||
String[] split = filename.split("_");
|
||||
@@ -72,7 +70,8 @@ public class GuiReplayInstanceChooser extends GuiScreen {
|
||||
|
||||
//if no modified versions of the replay were found, start the downloaded one
|
||||
if(chooseableFiles.isEmpty()) {
|
||||
ReplayHandler.startReplay(downloadedFile);
|
||||
// TODO
|
||||
// ReplayHandler.startReplay(downloadedFile);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,7 +102,8 @@ public class GuiReplayInstanceChooser extends GuiScreen {
|
||||
public void run() {
|
||||
try {
|
||||
File file = fileDropdown.getElement(fileDropdown.getSelectionIndex()).getValue();
|
||||
ReplayHandler.startReplay(file);
|
||||
//TODO
|
||||
// ReplayHandler.startReplay(file);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.google.common.base.Optional;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import de.johni0702.replaystudio.replay.ReplayMetaData;
|
||||
import de.johni0702.replaystudio.replay.ZipReplayFile;
|
||||
import de.johni0702.replaystudio.studio.ReplayStudio;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.replay.FileUploader;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.Category;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.elements.*;
|
||||
import eu.crushedpixel.replaymod.gui.elements.listeners.ProgressUpdateListener;
|
||||
import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer;
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
import com.replaymod.replay.gui.screen.GuiReplayViewer;
|
||||
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
|
||||
import eu.crushedpixel.replaymod.registry.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.utils.*;
|
||||
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
import eu.crushedpixel.replaymod.utils.RegexUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
@@ -35,7 +41,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -84,15 +89,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener {
|
||||
boolean correctFile = false;
|
||||
this.replayFile = file;
|
||||
|
||||
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(ReplayFile.ZIP_FILE_EXTENSION)) {
|
||||
if(("." + FilenameUtils.getExtension(file.getAbsolutePath())).equals(".zip")) {
|
||||
ReplayFile archive = null;
|
||||
try {
|
||||
archive = new ReplayFile(file);
|
||||
archive = new ZipReplayFile(new ReplayStudio(), file);
|
||||
|
||||
metaData = archive.metadata().get();
|
||||
BufferedImage img = archive.thumb().get();
|
||||
if(img != null) {
|
||||
thumb = ImageUtils.scaleImage(img, new Dimension(1280, 720));
|
||||
metaData = archive.getMetaData();
|
||||
Optional<BufferedImage> img = archive.getThumb();
|
||||
if(img.isPresent()) {
|
||||
thumb = ImageUtils.scaleImage(img.get(), new Dimension(1280, 720));
|
||||
hasThumbnail = true;
|
||||
}
|
||||
|
||||
@@ -307,21 +312,15 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener {
|
||||
|
||||
if(hideServerIP.isChecked()) {
|
||||
File tmp = File.createTempFile("replay_hidden_ip", "mcpr");
|
||||
File tmpMeta = File.createTempFile("metadata", "json");
|
||||
|
||||
ReplayMetaData newMetaData = metaData.copy();
|
||||
newMetaData.removeServer();
|
||||
ReplayFileIO.write(newMetaData, tmpMeta);
|
||||
|
||||
HashMap<String, File> toAdd = new HashMap<String, File>();
|
||||
toAdd.put(ReplayFile.ENTRY_METADATA, tmpMeta);
|
||||
|
||||
FileUtils.copyFile(replayFile, tmp);
|
||||
ReplayFileIO.addFilesToZip(tmp, toAdd);
|
||||
ReplayMetaData newMetaData = new ReplayMetaData(metaData);
|
||||
newMetaData.setServerName(null);
|
||||
ReplayFile replay = new ZipReplayFile(new ReplayStudio(), replayFile);
|
||||
replay.writeMetaData(newMetaData);
|
||||
replay.saveTo(tmp);
|
||||
|
||||
uploader.uploadFile(GuiUploadFile.this, name, tags, tmp, category, desc);
|
||||
|
||||
FileUtils.deleteQuietly(tmpMeta);
|
||||
FileUtils.deleteQuietly(tmp);
|
||||
} else {
|
||||
uploader.uploadFile(GuiUploadFile.this, name, tags, replayFile, category, desc);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.replayeditor;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiProgressBar;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.gui.replayeditor;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiDropdown;
|
||||
import eu.crushedpixel.replaymod.holders.GuiEntryListStringEntry;
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user