From 14f53f74299f44e6bb46455f81fd071b997a5b48 Mon Sep 17 00:00:00 2001 From: Marius Metzger Date: Mon, 16 Mar 2015 01:45:36 +0100 Subject: [PATCH] Added Core Mod to redirect the Enchantment Rendering getSystemTime() calls to a the EnchantmentTimer (glow now slows down) --- build.gradle | 10 +- .../eu/crushedpixel/replaymod/ReplayMod.java | 3 +- .../replaymod/coremod/ClassTransformer.java | 89 +++++++++++ .../replaymod/coremod/LoadingPlugin.java | 32 ++++ .../replaymod/events/GuiEventHandler.java | 2 +- .../replaymod/events/GuiReplayOverlay.java | 2 +- .../replaymod/events/KeyInputHandler.java | 2 +- .../replaymod/events/RecordingHandler.java | 9 +- .../replaymod/gui/GuiConstants.java | 3 + .../replaymod/gui/GuiEntryList.java | 121 --------------- .../replaymod/gui/GuiReplaySpeedSlider.java | 1 + .../gui/elements/GuiArrowButton.java | 40 +++++ .../gui/{ => elements}/GuiDropdown.java | 48 ++++-- .../replaymod/gui/elements/GuiEntryList.java | 146 ++++++++++++++++++ .../gui/{ => elements}/GuiMouseInput.java | 2 +- .../gui/{ => elements}/GuiNumberInput.java | 2 +- .../{ => elements}/GuiReplayListEntry.java | 2 +- .../{ => elements}/GuiReplayListExtended.java | 2 +- .../elements/listeners/SelectionListener.java | 7 + .../replaymod/gui/online/GuiReplayCenter.java | 2 +- .../replaymod/gui/online/ReplayFileList.java | 2 +- .../gui/replaystudio/GuiConnectPart.java | 119 +++++++++++--- .../gui/replaystudio/GuiReplayStudio.java | 7 +- .../gui/replaystudio/GuiTrimPart.java | 2 +- .../gui/replayviewer/GuiReplayViewer.java | 2 +- .../gui/replayviewer/ReplayList.java | 2 +- .../recording/ConnectionEventHandler.java | 5 +- .../replaymod/replay/ReplayProcess.java | 7 +- .../replaymod/replay/ReplaySender.java | 25 +-- .../replaymod/timer/EnchantmentTimer.java | 35 +++++ .../{replay => timer}/MCTimerHandler.java | 2 +- 31 files changed, 549 insertions(+), 184 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/coremod/ClassTransformer.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java delete mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/GuiEntryList.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java rename src/main/java/eu/crushedpixel/replaymod/gui/{ => elements}/GuiDropdown.java (76%) create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiEntryList.java rename src/main/java/eu/crushedpixel/replaymod/gui/{ => elements}/GuiMouseInput.java (78%) rename src/main/java/eu/crushedpixel/replaymod/gui/{ => elements}/GuiNumberInput.java (92%) rename src/main/java/eu/crushedpixel/replaymod/gui/{ => elements}/GuiReplayListEntry.java (98%) rename src/main/java/eu/crushedpixel/replaymod/gui/{ => elements}/GuiReplayListExtended.java (99%) create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/elements/listeners/SelectionListener.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java rename src/main/java/eu/crushedpixel/replaymod/{replay => timer}/MCTimerHandler.java (98%) diff --git a/build.gradle b/build.gradle index 71f4d2e7..e6b56606 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { apply plugin: 'forge' -version = "0.4" +version = "0.6" group= "eu.crushedpixel.replaymod" archivesBaseName = "replaymod" @@ -50,6 +50,14 @@ dependencies { } +jar { + //from { configurations.external.collect { it.isDirectory() ? it : zipTree(it) } } + manifest { + attributes 'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin', + 'FMLCorePluginContainsFMLMod': 'false' + } +} + processResources { // this will ensure that this task is redone when the versions change. diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index 1cf8b5b1..c63d0d81 100644 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -59,7 +59,7 @@ public class ReplayMod public static int TP_DISTANCE_LIMIT = 128; public static final ApiClient apiClient = new ApiClient(); - + // The instance of your mod that Forge uses. @Instance(value = "ReplayModID") public static ReplayMod instance; @@ -108,7 +108,6 @@ public class ReplayMod } catch(Exception e) { e.printStackTrace(); } - //ReplayTrimmer.trim(new File("/Users/mariusmetzger/toTrim.mcpr"), new File("/Users/mariusmetzger/trimmed.mcpr"), 1000*60, 2000*60); //if(AuthenticationHandler.isBlacklisted(Minecraft.getMinecraft().getSession().getPlayerID())) { //System.exit(0); diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/ClassTransformer.java b/src/main/java/eu/crushedpixel/replaymod/coremod/ClassTransformer.java new file mode 100644 index 00000000..edad28d0 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/coremod/ClassTransformer.java @@ -0,0 +1,89 @@ +package eu.crushedpixel.replaymod.coremod; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import net.minecraft.launchwrapper.IClassTransformer; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import akka.japi.Pair; + +public class ClassTransformer implements IClassTransformer { + + @Override + public byte[] transform(String name, String transformedName, + byte[] basicClass) { + + if(name.equals("cqh")) { + return patchRenderEffectMethod(name, basicClass, true); + } + + if(name.equals("net.minecraft.client.renderer.entity.RenderItem")) { + return patchRenderEffectMethod(name, basicClass, false); + } + + return basicClass; + } + + public byte[] patchRenderEffectMethod(String name, byte[] bytes, boolean obfuscated) { + System.out.println("REPLAY MOD CORE PATCHER: Inside RenderItem class"); + + String methodName = obfuscated ? "a" : "renderEffect"; + String classDescriptor = obfuscated ? "(Lcxe;)V" : "(Lnet/minecraft/client/resources/model/IBakedModel;)V"; + + String minecraftClass = obfuscated ? "bsu" : "net/minecraft/client/Minecraft"; + String getSystemTime = obfuscated ? "I" : "getSystemTime"; + String sysTimeDesc = "()J"; + + ClassNode classNode = new ClassNode(); + ClassReader classReader = new ClassReader(bytes); + classReader.accept(classNode, 0); + + List> toInsert = new ArrayList>(); + + Iterator iterator = classNode.methods.iterator(); + while(iterator.hasNext()) { + MethodNode m = iterator.next(); + if(m.name.equals(methodName) && m.desc.equals(classDescriptor)) { + System.out.println("REPLAY MOD CORE PATCHER: Inside renderEffect method"); + + Iterator nodeIterator = m.instructions.iterator(); + while(nodeIterator.hasNext()) { + AbstractInsnNode node = nodeIterator.next(); + if(node instanceof MethodInsnNode) { + MethodInsnNode min = (MethodInsnNode)node; + if(min.getOpcode() == Opcodes.INVOKESTATIC &&min.name.equals(getSystemTime) && + min.owner.equals(minecraftClass) && min.desc.equals(sysTimeDesc)) { + MethodInsnNode n = new MethodInsnNode(Opcodes.INVOKESTATIC, + "eu/crushedpixel/replaymod/timer/EnchantmentTimer", "getEnchantmentTime", + min.desc, min.itf); + toInsert.add(new Pair(min, n)); + } + } + } + + for(Pair pair : toInsert) { + m.instructions.insertBefore(pair.first(), pair.second()); + m.instructions.remove(pair.first()); + } + + } + } + + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + + // net.minecraft.client.renderer.entity.RenderItem -> cqh + // private void renderEffect(IBakedModel model) -> private void a(cxe paramcxe) + // float f = (float)(Minecraft.getSystemTime() % 3000L) / 3000.0F / 8.0F; -> float f1 = (float)(bsu.I() % 3000L) / 3000.0F / 8.0F; +} diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java new file mode 100644 index 00000000..551b81f4 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java @@ -0,0 +1,32 @@ +package eu.crushedpixel.replaymod.coremod; + +import java.util.Map; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; + +public class LoadingPlugin implements IFMLLoadingPlugin { + + @Override + public String[] getASMTransformerClass() { + return new String[]{ClassTransformer.class.getName()}; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) {} + + @Override + public String getAccessTransformerClass() { + return null; + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java index 27276e6b..1438df0f 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java @@ -32,9 +32,9 @@ import eu.crushedpixel.replaymod.gui.replaystudio.GuiReplayStudio; import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; -import eu.crushedpixel.replaymod.replay.MCTimerHandler; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.studio.VersionValidator; +import eu.crushedpixel.replaymod.timer.MCTimerHandler; import eu.crushedpixel.replaymod.utils.MouseUtils; import eu.crushedpixel.replaymod.utils.ResourceHelper; import eu.crushedpixel.replaymod.video.VideoWriter; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index 5dfe7068..39832fbf 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -31,9 +31,9 @@ import org.lwjgl.opengl.Display; import org.lwjgl.opengl.GL11; import eu.crushedpixel.replaymod.entities.CameraEntity; -import eu.crushedpixel.replaymod.gui.GuiMouseInput; import eu.crushedpixel.replaymod.gui.GuiReplaySpeedSlider; import eu.crushedpixel.replaymod.gui.GuiSpectateSelection; +import eu.crushedpixel.replaymod.gui.elements.GuiMouseInput; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.holders.PositionKeyframe; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java index 599698ac..4e96a1ca 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java @@ -8,7 +8,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.InputEvent.KeyInputEvent; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection; -import eu.crushedpixel.replaymod.gui.GuiMouseInput; +import eu.crushedpixel.replaymod.gui.elements.GuiMouseInput; import eu.crushedpixel.replaymod.registry.KeybindRegistry; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.spectate.SpectateHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java index 3d5892ba..92df6d1f 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java @@ -138,6 +138,7 @@ public class RecordingHandler { @SubscribeEvent public void onPlayerTick(PlayerTickEvent e) { + if(!ConnectionEventHandler.isRecording()) return; try { if(e.player != mc.thePlayer) return; if(!ConnectionEventHandler.isRecording()) return; @@ -318,6 +319,7 @@ public class RecordingHandler { @SubscribeEvent public void onPickupItem(ItemPickupEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { ConnectionEventHandler.insertPacket(new S0DPacketCollectItem(event.pickedUp.getEntityId(), entityID)); } catch(Exception e) { @@ -327,6 +329,7 @@ public class RecordingHandler { @SubscribeEvent public void onRespawn(PlayerRespawnEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { //destroy entity, then respawn ConnectionEventHandler.insertPacket(new S13PacketDestroyEntities(entityID)); @@ -338,6 +341,7 @@ public class RecordingHandler { @SubscribeEvent public void onHurt(LivingHurtEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { if(event.entity.getEntityId() != mc.thePlayer.getEntityId()) { return; @@ -374,6 +378,7 @@ public class RecordingHandler { @SubscribeEvent public void onDeath(LivingDeathEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { if(event.entity.getEntityId() != mc.thePlayer.getEntityId()) { return; @@ -397,6 +402,7 @@ public class RecordingHandler { @SubscribeEvent public void onStartEating(PlayerUseItemEvent.Start event) { + if(!ConnectionEventHandler.isRecording()) return; try { if(!event.entityPlayer.isEating()) return; S0BPacketAnimation packet = new S0BPacketAnimation(); @@ -419,8 +425,8 @@ public class RecordingHandler { @SubscribeEvent public void onSleep(PlayerSleepInBedEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { - if(event.entityPlayer != mc.thePlayer) { return; }; @@ -449,6 +455,7 @@ public class RecordingHandler { @SubscribeEvent public void enterMinecart(MinecartInteractEvent event) { + if(!ConnectionEventHandler.isRecording()) return; try { if(event.player != mc.thePlayer) { return; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java index 6249af90..f4e543b5 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiConstants.java @@ -39,4 +39,7 @@ public class GuiConstants { public static final int REPLAY_EDITOR_SAVEMODE_BUTTON = 5003; public static final int REPLAY_EDITOR_SAVE_BUTTON = 5004; public static final int REPLAY_EDITOR_BACK_BUTTON = 5005; + + public static final int REPLAY_EDITOR_UP_BUTTON = 5006; + public static final int REPLAY_EDITOR_DOWN_BUTTON = 5007; } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEntryList.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiEntryList.java deleted file mode 100644 index 114c188b..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiEntryList.java +++ /dev/null @@ -1,121 +0,0 @@ -package eu.crushedpixel.replaymod.gui; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -import org.lwjgl.input.Mouse; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiTextField; - -public class GuiEntryList extends GuiTextField { - - private int selectionIndex = -1; - - private Minecraft mc = Minecraft.getMinecraft(); - - private int visibleElements; - public final static int elementHeight = 14; - - private int upperIndex = 0; - - public GuiEntryList(int id, FontRenderer fontRenderer, - int xPos, int yPos, int width, int visibleEntries) { - super(id, fontRenderer, xPos, yPos, width, elementHeight*visibleEntries-1); - this.visibleElements = visibleEntries; - } - - public void setVisibleElements(int rows) { - this.visibleElements = rows; - this.height = elementHeight*visibleElements-1; - } - - @Override - public void drawTextBox() { - super.drawTextBox(); - //drawing the entries - for(int i=0; i-upperIndex visibleElements) { - //handle scroll events - int dw = Mouse.getDWheel(); - if(dw > 0) { - dw = -1; - } else if(dw < 0) { - dw = 1; - } - - upperIndex = Math.max(Math.min(upperIndex+dw, elements.size()-visibleElements), 0); - - float visiblePerc = ((float)visibleElements)/elements.size(); - int barHeight = (int)(visiblePerc*(height-1)); - - float posPerc = ((float)upperIndex)/elements.size(); - int barY = (int)(posPerc*(height-1)); - - drawRect(xPosition+width-3, yPosition, xPosition+width, yPosition+height, Color.DARK_GRAY.getRGB()); - drawRect(xPosition+width-3, yPosition+barY, xPosition+width, yPosition+1+barY+barHeight, -6250336); - } - } - - @Override - public void mouseClicked(int xPos, int yPos, int mouseButton) { - int clickedIndex = (int)Math.floor((yPos-yPosition) / elementHeight) + upperIndex; - if(clickedIndex < elements.size()) selectionIndex = clickedIndex; - } - - @Override - public void setText(String text) {} - - private List elements = new ArrayList(); - - private void select(int index) { - this.selectionIndex = index; - if(selectionIndex < 0) selectionIndex = -1; - } - - public void setElements(List elements) { - this.elements = elements; - if(selectionIndex == -1 && elements.size() > 0) { - selectionIndex = 0; - } - } - - public void clearElements() { - this.elements = new ArrayList(); - selectionIndex = -1; - } - - public void addElement(Object element) { - this.elements.add(element); - if(selectionIndex == -1) { - selectionIndex = 0; - } - } - - public Object getElement(int index) { - return elements.get(index); - } - - public int getSelectionIndex() { - return selectionIndex; - } - -} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java index bb32ec4e..0134af5a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplaySpeedSlider.java @@ -1,6 +1,7 @@ package eu.crushedpixel.replaymod.gui; import eu.crushedpixel.replaymod.ReplayMod; +import eu.crushedpixel.replaymod.gui.elements.GuiMouseInput; import eu.crushedpixel.replaymod.replay.ReplayHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java new file mode 100644 index 00000000..70202efa --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiArrowButton.java @@ -0,0 +1,40 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import java.awt.Color; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; + +public class GuiArrowButton extends GuiButton { + + private Minecraft mc = Minecraft.getMinecraft(); + + private boolean upwards = false; + + public GuiArrowButton(int buttonId, int x, int y, String buttonText, boolean upwards) { + super(buttonId, x, y, buttonText); + + this.upwards = upwards; + width = 20; + height = 20; + } + + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY) { + try { + super.drawButton(mc, mouseX, mouseY); + if(upwards) { + for(int i=0; i<=Math.ceil(height/2)-5; i++) { + drawHorizontalLine(xPosition+width-height+i+4, xPosition+width-i-6, yPosition+height-((height/3)+i+2), Color.BLACK.getRGB()); + } + } else { + for(int i=0; i<=Math.ceil(height/2)-5; i++) { + drawHorizontalLine(xPosition+width-height+i+4, xPosition+width-i-6, yPosition+(height/3)+i+2, Color.BLACK.getRGB()); + } + } + } catch(Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiDropdown.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java similarity index 76% rename from src/main/java/eu/crushedpixel/replaymod/gui/GuiDropdown.java rename to src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java index 78123a84..2b21da16 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiDropdown.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiDropdown.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui; +package eu.crushedpixel.replaymod.gui.elements; import java.awt.Color; import java.util.ArrayList; @@ -6,26 +6,31 @@ import java.util.List; import org.lwjgl.input.Mouse; +import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiTextField; -public class GuiDropdown extends GuiTextField { +public class GuiDropdown extends GuiTextField { private int selectionIndex = -1; private boolean open = false; private Minecraft mc = Minecraft.getMinecraft(); - private final int visibleDropout = 5; + private final int visibleDropout; private final int dropoutElementHeight = 14; - private final int maxDropoutHeight = dropoutElementHeight*visibleDropout; + private final int maxDropoutHeight; + private List selectionListeners = new ArrayList(); + private int upperIndex = 0; public GuiDropdown(int id, FontRenderer fontRenderer, - int xPos, int yPos, int width) { + int xPos, int yPos, int width, int visibleDropout) { super(id, fontRenderer, xPos, yPos, width, 20); + this.visibleDropout = visibleDropout; + this.maxDropoutHeight = dropoutElementHeight*visibleDropout; } @Override @@ -67,7 +72,7 @@ public class GuiDropdown extends GuiTextField { //The elements int y = 0; int i = 0; - for(Object obj : elements) { + for(T obj : elements) { if(i yPosition+height && yPos < yPosition+height+requiredHeight) { int clickedIndex = (int)Math.floor((yPos - (yPosition+height)) / dropoutElementHeight) + upperIndex; this.selectionIndex = clickedIndex; + fireSelectionChangeEvent(); } open = false; } else { @@ -132,14 +138,15 @@ public class GuiDropdown extends GuiTextField { } } - private List elements = new ArrayList(); + private List elements = new ArrayList(); - private void select(int index) { + public void setSelectionIndex(int index) { this.selectionIndex = index; if(selectionIndex < 0) selectionIndex = -1; + fireSelectionChangeEvent(); } - public void setElements(List elements) { + public void setElements(List elements) { this.elements = elements; if(selectionIndex == -1 && elements.size() > 0) { selectionIndex = 0; @@ -147,23 +154,40 @@ public class GuiDropdown extends GuiTextField { } public void clearElements() { - this.elements = new ArrayList(); + this.elements = new ArrayList(); selectionIndex = -1; } - public void addElement(Object element) { + public void addElement(T element) { this.elements.add(element); if(selectionIndex == -1) { selectionIndex = 0; } } - public Object getElement(int index) { + public T getElement(int index) { return elements.get(index); } + public List getAllElements() { + return elements; + } + public int getSelectionIndex() { return selectionIndex; } + private void fireSelectionChangeEvent() { + for(SelectionListener listener : selectionListeners) { + listener.onSelectionChanged(selectionIndex); + } + } + + public void addSelectionListener(SelectionListener listener) { + this.selectionListeners.add(listener); + } + + public void removeSelectionListener(SelectionListener listener) { + this.selectionListeners.remove(listener); + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiEntryList.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiEntryList.java new file mode 100644 index 00000000..7be42ac8 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiEntryList.java @@ -0,0 +1,146 @@ +package eu.crushedpixel.replaymod.gui.elements; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +import org.lwjgl.input.Mouse; + +import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiTextField; + +public class GuiEntryList extends GuiTextField { + + private int selectionIndex = -1; + + private Minecraft mc = Minecraft.getMinecraft(); + + private int visibleElements; + public final static int elementHeight = 14; + + private int upperIndex = 0; + + private List selectionListeners = new ArrayList(); + + public GuiEntryList(int id, FontRenderer fontRenderer, + int xPos, int yPos, int width, int visibleEntries) { + super(id, fontRenderer, xPos, yPos, width, elementHeight*visibleEntries-1); + this.visibleElements = visibleEntries; + } + + public void setVisibleElements(int rows) { + this.visibleElements = rows; + this.height = elementHeight*visibleElements-1; + } + + @Override + public void drawTextBox() { + try { + super.drawTextBox(); + //drawing the entries + for(int i=0; i-upperIndex= elements.size()) break; + + if(i == selectionIndex) { + drawRect(xPosition, yPosition+(i-upperIndex)*elementHeight, xPosition+width, + yPosition+(i+1-upperIndex)*elementHeight-1, Color.GRAY.getRGB()); + } + + drawRect(xPosition, yPosition+(i+1-upperIndex)*elementHeight-1, xPosition+width, + yPosition+(i+1-upperIndex)*elementHeight, -6250336); + drawString(mc.fontRendererObj, mc.fontRendererObj.trimStringToWidth(elements.get(i).toString(), width-4), + xPosition+2, yPosition+(i-upperIndex)*elementHeight+3, Color.WHITE.getRGB()); + } + + //drawing the scroll bar + if(elements.size() > visibleElements) { + //handle scroll events + int dw = Mouse.getDWheel(); + if(dw > 0) { + dw = -1; + } else if(dw < 0) { + dw = 1; + } + + upperIndex = Math.max(Math.min(upperIndex+dw, elements.size()-visibleElements), 0); + + float visiblePerc = ((float)visibleElements)/elements.size(); + int barHeight = (int)(visiblePerc*(height-1)); + + float posPerc = ((float)upperIndex)/elements.size(); + int barY = (int)(posPerc*(height-1)); + + drawRect(xPosition+width-3, yPosition, xPosition+width, yPosition+height, Color.DARK_GRAY.getRGB()); + drawRect(xPosition+width-3, yPosition+barY, xPosition+width, yPosition+1+barY+barHeight, -6250336); + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + @Override + public void mouseClicked(int xPos, int yPos, int mouseButton) { + int clickedIndex = (int)Math.floor((yPos-yPosition) / elementHeight) + upperIndex; + if(clickedIndex < elements.size() && clickedIndex >= 0) { + selectionIndex = clickedIndex; + fireSelectionChangeEvent(); + } + } + + private void fireSelectionChangeEvent() { + for(SelectionListener listener : selectionListeners) { + listener.onSelectionChanged(selectionIndex); + } + } + + @Override + public void setText(String text) {} + + private List elements = new ArrayList(); + + public void setElements(List elements) { + this.elements = elements; + if(selectionIndex == -1 && elements.size() > 0) { + selectionIndex = 0; + } + } + + public void clearElements() { + this.elements = new ArrayList(); + selectionIndex = -1; + } + + public void addElement(T element) { + this.elements.add(element); + if(selectionIndex == -1) { + selectionIndex = 0; + } + } + + public T getElement(int index) { + return elements.get(index); + } + + public int getSelectionIndex() { + return selectionIndex; + } + + public void setSelectionIndex(int index) { + this.selectionIndex = index; + if(selectionIndex < 0) selectionIndex = -1; + fireSelectionChangeEvent(); + } + + public void addSelectionListener(SelectionListener listener) { + this.selectionListeners.add(listener); + } + + public void removeSelectionListener(SelectionListener listener) { + this.selectionListeners.remove(listener); + } + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiMouseInput.java similarity index 78% rename from src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java rename to src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiMouseInput.java index 6d2d6dc2..946b4b96 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiMouseInput.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiMouseInput.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui; +package eu.crushedpixel.replaymod.gui.elements; import org.lwjgl.input.Keyboard; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiNumberInput.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiNumberInput.java similarity index 92% rename from src/main/java/eu/crushedpixel/replaymod/gui/GuiNumberInput.java rename to src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiNumberInput.java index f2040118..fddcd64a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiNumberInput.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiNumberInput.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui; +package eu.crushedpixel.replaymod.gui.elements; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListEntry.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListEntry.java similarity index 98% rename from src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListEntry.java rename to src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListEntry.java index cc8c14be..df265ea1 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListEntry.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListEntry.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui; +package eu.crushedpixel.replaymod.gui.elements; import java.awt.image.BufferedImage; import java.io.File; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListExtended.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListExtended.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListExtended.java rename to src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListExtended.java index b71af102..cf3a2bb6 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/GuiReplayListExtended.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/GuiReplayListExtended.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.gui; +package eu.crushedpixel.replaymod.gui.elements; import java.io.File; import java.util.ArrayList; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/elements/listeners/SelectionListener.java b/src/main/java/eu/crushedpixel/replaymod/gui/elements/listeners/SelectionListener.java new file mode 100644 index 00000000..f19ea412 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/elements/listeners/SelectionListener.java @@ -0,0 +1,7 @@ +package eu.crushedpixel.replaymod.gui.elements.listeners; + +public abstract class SelectionListener { + + public abstract void onSelectionChanged(int selectionIndex); + +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java index 32c84300..437f7251 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiReplayCenter.java @@ -21,7 +21,7 @@ import eu.crushedpixel.replaymod.api.client.SearchPagination; import eu.crushedpixel.replaymod.api.client.SearchQuery; import eu.crushedpixel.replaymod.api.client.holders.FileInfo; import eu.crushedpixel.replaymod.gui.GuiConstants; -import eu.crushedpixel.replaymod.gui.GuiReplayListExtended; +import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/ReplayFileList.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/ReplayFileList.java index cbb660ad..2e500cf1 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/ReplayFileList.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/ReplayFileList.java @@ -1,7 +1,7 @@ package eu.crushedpixel.replaymod.gui.online; import net.minecraft.client.Minecraft; -import eu.crushedpixel.replaymod.gui.GuiReplayListExtended; +import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; public class ReplayFileList extends GuiReplayListExtended { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiConnectPart.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiConnectPart.java index 9b04b592..8c188d5a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiConnectPart.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiConnectPart.java @@ -1,24 +1,42 @@ package eu.crushedpixel.replaymod.gui.replaystudio; +import java.awt.Color; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; import org.apache.commons.io.FilenameUtils; -import eu.crushedpixel.replaymod.gui.GuiEntryList; +import eu.crushedpixel.replaymod.gui.GuiConstants; +import eu.crushedpixel.replaymod.gui.elements.GuiArrowButton; +import eu.crushedpixel.replaymod.gui.elements.GuiDropdown; +import eu.crushedpixel.replaymod.gui.elements.GuiEntryList; +import eu.crushedpixel.replaymod.gui.elements.listeners.SelectionListener; +import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; +import eu.crushedpixel.replaymod.utils.ReplayFileIO; public class GuiConnectPart extends GuiStudioPart { - private Minecraft mc = Minecraft.getMinecraft(); - private static final String DESCRIPTION = "Connects multiple Replays in the same order as the list."; private static final String TITLE = "Connect Replays"; private boolean initialized = false; - private GuiEntryList concatList; + private GuiEntryList concatList; + private GuiDropdown replayDropdown; + + private GuiButton removeButton, addButton; + private GuiArrowButton upButton, downButton; + + private List replayFiles; + private List filesToConcat; public GuiConnectPart(int yPos) { super(yPos); + this.mc = Minecraft.getMinecraft(); fontRendererObj = mc.fontRendererObj; } @@ -40,21 +58,81 @@ public class GuiConnectPart extends GuiStudioPart { @Override public void initGui() { if(!initialized) { - concatList = new GuiEntryList(1, fontRendererObj, 30, yPos, 200, 0); - concatList.addElement(FilenameUtils.getBaseName(GuiReplayStudio.instance.getSelectedFile().getAbsolutePath())); - - concatList.addElement("test1"); - concatList.addElement("test2"); - concatList.addElement("test3"); - concatList.addElement("test4"); - concatList.addElement("test5"); - concatList.addElement("test6"); - concatList.addElement("test7"); - concatList.addElement("test8"); - concatList.addElement("test9"); - concatList.addElement("test10"); - concatList.addElement("test11"); + concatList = new GuiEntryList(1, fontRendererObj, 30, yPos, 150, 0); + filesToConcat = new ArrayList(); + String selectedName = FilenameUtils.getBaseName(GuiReplayStudio.instance.getSelectedFile().getAbsolutePath()); + filesToConcat.add(selectedName); + concatList.setElements(filesToConcat); + + concatList.setSelectionIndex(0); + + replayDropdown = new GuiDropdown(1, fontRendererObj, 250, yPos+5, 0, 4); + + replayDropdown.clearElements(); + replayFiles = ReplayFileIO.getAllReplayFiles(); + int index = -1; + int i=0; + for(File file : replayFiles) { + String name = FilenameUtils.getBaseName(file.getAbsolutePath()); + replayDropdown.addElement(name); + if(name.equals(selectedName)) { + index = i; + } + i++; + } + + replayDropdown.setSelectionPos(index); + + replayDropdown.addSelectionListener(new SelectionListener() { + + @Override + public void onSelectionChanged(int selectionIndex) { + filesToConcat.set(concatList.getSelectionIndex(), (String)replayDropdown.getElement(selectionIndex)); + concatList.setElements(filesToConcat); + + } + }); + + concatList.addSelectionListener(new SelectionListener() { + @Override + public void onSelectionChanged(int selectionIndex) { + String selName = (String)concatList.getElement(selectionIndex); + int i = 0; + for(Object s : replayDropdown.getAllElements()) { + String str = (String)s; + if(str.equals(selName)) { + replayDropdown.setSelectionIndex(i); + break; + } + i++; + } + } + }); + + upButton = new GuiArrowButton(GuiConstants.REPLAY_EDITOR_UP_BUTTON, 195, yPos+40, "", true); + buttonList.add(upButton); + + downButton = new GuiArrowButton(GuiConstants.REPLAY_EDITOR_DOWN_BUTTON, 219, yPos+40, "", false); + buttonList.add(downButton); + + int w = GuiReplayStudio.instance.width-243-20-4; + + removeButton = new GuiButton(1, 243, yPos+40, "Remove"); + buttonList.add(removeButton); + + addButton = new GuiButton(1, 0, yPos+40, "Add"); + buttonList.add(addButton); + } + + int w = GuiReplayStudio.instance.width-243-20-4; + addButton.xPosition = 243+6+(w/2); + + addButton.width = w/2+2; + removeButton.width = w/2+2; + + replayDropdown.width = GuiReplayStudio.instance.width-250-20; + int h = GuiReplayStudio.instance.height-yPos-20; int rows = (int)(h / (float)GuiEntryList.elementHeight); concatList.setVisibleElements(rows); @@ -65,11 +143,16 @@ public class GuiConnectPart extends GuiStudioPart { @Override public void mouseClicked(int mouseX, int mouseY, int mouseButton) { concatList.mouseClicked(mouseX, mouseY, mouseButton); + replayDropdown.mouseClicked(mouseX, mouseY, mouseButton); } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { concatList.drawTextBox(); + replayDropdown.drawTextBox(); + + drawString(fontRendererObj, "Replay:", 200, yPos+5+7, Color.WHITE.getRGB()); + super.drawScreen(mouseX, mouseY, partialTicks); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiReplayStudio.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiReplayStudio.java index a2dec474..06fc6264 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiReplayStudio.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiReplayStudio.java @@ -13,7 +13,7 @@ import net.minecraft.client.gui.GuiScreen; import org.apache.commons.io.FilenameUtils; import eu.crushedpixel.replaymod.gui.GuiConstants; -import eu.crushedpixel.replaymod.gui.GuiDropdown; +import eu.crushedpixel.replaymod.gui.elements.GuiDropdown; import eu.crushedpixel.replaymod.utils.ReplayFileIO; public class GuiReplayStudio extends GuiScreen { @@ -93,7 +93,7 @@ public class GuiReplayStudio extends GuiScreen { int modeWidth = tabButtons.get(0).width; if(!initialized) { - replayDropdown = new GuiDropdown(1, fontRendererObj, 15+2+1+80, 60, this.width-30-8-80-modeWidth-4); + replayDropdown = new GuiDropdown(1, fontRendererObj, 15+2+1+80, 60, this.width-30-8-80-modeWidth-4, 5); refreshReplayDropdown(); } else { replayDropdown.width = this.width-30-8-80-modeWidth-4; @@ -155,6 +155,7 @@ public class GuiReplayStudio extends GuiScreen { @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); currentTab.getStudioPart().drawScreen(mouseX, mouseY, partialTicks); drawCenteredString(fontRendererObj, "§n"+currentTab.getStudioPart().getTitle(), width/2, 92, Color.WHITE.getRGB()); @@ -186,7 +187,7 @@ public class GuiReplayStudio extends GuiScreen { drawCenteredString(fontRendererObj, "Replay Studio", this.width / 2, 10, 16777215); drawString(fontRendererObj, "Replay File:", 30, 67, Color.WHITE.getRGB()); - super.drawScreen(mouseX, mouseY, partialTicks); + replayDropdown.drawTextBox(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiTrimPart.java b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiTrimPart.java index fca82e62..60b1335f 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiTrimPart.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replaystudio/GuiTrimPart.java @@ -8,7 +8,7 @@ import net.minecraft.client.Minecraft; import org.lwjgl.input.Keyboard; -import eu.crushedpixel.replaymod.gui.GuiNumberInput; +import eu.crushedpixel.replaymod.gui.elements.GuiNumberInput; public class GuiTrimPart extends GuiStudioPart { diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java index b6b5762c..f56bcc07 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/GuiReplayViewer.java @@ -33,8 +33,8 @@ import com.google.gson.Gson; import com.mojang.realmsclient.util.Pair; import eu.crushedpixel.replaymod.api.client.holders.FileInfo; -import eu.crushedpixel.replaymod.gui.GuiReplayListExtended; import eu.crushedpixel.replaymod.gui.GuiReplaySettings; +import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java index 92b52af6..106ea6a4 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/replayviewer/ReplayList.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.gui.replayviewer; -import eu.crushedpixel.replaymod.gui.GuiReplayListExtended; +import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; import net.minecraft.client.Minecraft; public class ReplayList extends GuiReplayListExtended { diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java index fac81bc0..5ceedca9 100644 --- a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java @@ -13,8 +13,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map.Entry; +import sun.java2d.SunGraphics2D; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S42PacketCombatEvent; import net.minecraft.server.MinecraftServer; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent; @@ -46,7 +48,8 @@ public class ConnectionEventHandler { public static void insertPacket(Packet packet) { if(!isRecording || packetListener == null) { - System.out.println("Invalid attempt to insert Packet!"); + String reason = isRecording ? " (recording)":" (null)"; + System.out.println("Invalid attempt to insert Packet!"+reason); return; } try { diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java index 9232a6cb..98ae1686 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java @@ -4,6 +4,7 @@ import java.io.File; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.enchantment.Enchantment; import eu.crushedpixel.replaymod.ReplayMod; import eu.crushedpixel.replaymod.chat.ChatMessageRequests; import eu.crushedpixel.replaymod.chat.ChatMessageRequests.ChatMessageType; @@ -14,6 +15,8 @@ import eu.crushedpixel.replaymod.holders.TimeKeyframe; import eu.crushedpixel.replaymod.interpolation.LinearPoint; import eu.crushedpixel.replaymod.interpolation.LinearTimestamp; import eu.crushedpixel.replaymod.interpolation.SplinePoint; +import eu.crushedpixel.replaymod.timer.EnchantmentTimer; +import eu.crushedpixel.replaymod.timer.MCTimerHandler; import eu.crushedpixel.replaymod.video.ScreenCapture; import eu.crushedpixel.replaymod.video.VideoWriter; @@ -67,6 +70,8 @@ public class ReplayProcess { ReplayHandler.setInPath(true); previousReplaySpeed = ReplayHandler.getSpeed(); + EnchantmentTimer.resetRecordingTime(); + TimeKeyframe tf = ReplayHandler.getNextTimeKeyframe(-1); if(tf != null) { int ts = tf.getTimestamp(); @@ -253,7 +258,6 @@ public class ReplayProcess { if(Float.isInfinite(currentTimeStepPerc)) currentTimeStepPerc = 0; float splinePos = ((float)ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc)/(float)(ReplayHandler.getPosKeyframeCount()-1); - float timePos = ((float)ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc)/(float)(ReplayHandler.getTimeKeyframeCount()-1); Position pos = null; @@ -431,6 +435,7 @@ public class ReplayProcess { ReplayHandler.setSpeed((float)curSpeed); if(isVideoRecording()) { MCTimerHandler.updateTimer((1f/ReplayMod.replaySettings.getVideoFramerate())); + EnchantmentTimer.increaseRecordingTime((1000/ReplayMod.replaySettings.getVideoFramerate())); } if(curPos != null) ReplayHandler.setReplayPos(curPos); diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index d0548aa5..345bbc34 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -1,7 +1,5 @@ package eu.crushedpixel.replaymod.replay; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -21,10 +19,8 @@ import net.minecraft.client.gui.GuiDownloadTerrain; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.entity.Entity; import net.minecraft.network.EnumConnectionState; -import net.minecraft.network.EnumPacketDirection; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; -import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.S01PacketJoinGame; import net.minecraft.network.play.server.S02PacketChat; import net.minecraft.network.play.server.S03PacketTimeUpdate; @@ -70,6 +66,7 @@ import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; import eu.crushedpixel.replaymod.recording.ReplayMetaData; import eu.crushedpixel.replaymod.reflection.MCPNames; +import eu.crushedpixel.replaymod.timer.MCTimerHandler; import eu.crushedpixel.replaymod.utils.ReplayFileIO; @Sharable @@ -399,9 +396,12 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { //If hurrying, ignore some packets, unless during Replay Path and *not* in initial hurry if(hurryToTimestamp && (!ReplayHandler.isInPath() || (desiredTimeStamp-currentTimeStamp > 1000))) { if(p instanceof S45PacketTitle || - p instanceof S29PacketSoundEffect || p instanceof S2APacketParticles) return; } + + if(p instanceof S29PacketSoundEffect && ReplayHandler.isInPath() && ReplayProcess.isVideoRecording()) { + return; + } if(p instanceof S03PacketTimeUpdate) { p = TimeHandler.getTimePacket((S03PacketTimeUpdate)p); @@ -437,6 +437,13 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension, difficulty, maxPlayers, worldType, false); } + + if(p instanceof S07PacketRespawn) { + S07PacketRespawn respawn = (S07PacketRespawn)p; + p = new S07PacketRespawn(respawn.func_149082_c(), + respawn.func_149081_d(), respawn.func_149080_f(), GameType.SPECTATOR); + allowMovement = true; + } /* * Proof of concept for some nasty player manipulation ;) @@ -475,12 +482,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { System.out.println(((S0CPacketSpawnPlayer) p).func_148944_c()); } */ - - if(p instanceof S07PacketRespawn) { - allowMovement = true; - } - - + if(p instanceof S08PacketPlayerPosLook) { final S08PacketPlayerPosLook ppl = (S08PacketPlayerPosLook)p; @@ -508,6 +510,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } Entity ent = ReplayHandler.getCameraEntity(); + if(ent == null || !(ent instanceof CameraEntity)) ent = new CameraEntity(mc.theWorld); CameraEntity cent = (CameraEntity)ent; cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e()); diff --git a/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java b/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java new file mode 100644 index 00000000..8f5ea4b0 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/timer/EnchantmentTimer.java @@ -0,0 +1,35 @@ +package eu.crushedpixel.replaymod.timer; + +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import eu.crushedpixel.replaymod.replay.ReplayProcess; + +public class EnchantmentTimer { + + private static long lastRealTime = System.currentTimeMillis(); + private static long lastFakeTime = System.currentTimeMillis(); + + private static long recordingTime = 0; + + public static void resetRecordingTime() { + recordingTime = 0; + } + + public static void increaseRecordingTime(long amount) { + recordingTime += amount; + } + + public static long getEnchantmentTime() { + if(!(ReplayHandler.isInPath() && ReplayProcess.isVideoRecording())) { + if(ReplayHandler.isInReplay()) { + long timeDiff = System.currentTimeMillis() - lastRealTime; + double toAdd = timeDiff*ReplayHandler.getSpeed(); + lastFakeTime = Math.round(lastFakeTime+toAdd); + lastRealTime = System.currentTimeMillis(); + return lastFakeTime; + } + lastFakeTime = lastRealTime = System.currentTimeMillis(); + return lastRealTime; + } + return recordingTime; + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/MCTimerHandler.java b/src/main/java/eu/crushedpixel/replaymod/timer/MCTimerHandler.java similarity index 98% rename from src/main/java/eu/crushedpixel/replaymod/replay/MCTimerHandler.java rename to src/main/java/eu/crushedpixel/replaymod/timer/MCTimerHandler.java index 887d9e09..5b7bdb47 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/MCTimerHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/timer/MCTimerHandler.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.replay; +package eu.crushedpixel.replaymod.timer; import java.lang.reflect.Field;