From 101a0359d3b287bd50b0d757d0164b8ee2403e2c Mon Sep 17 00:00:00 2001 From: Marius Metzger Date: Sun, 1 Feb 2015 15:44:55 +0100 Subject: [PATCH] Moved Key Events to KeyInputHandler Added Spectator Menu and Mode to Replay --- .../eu/crushedpixel/replaymod/ReplayMod.java | 3 + .../replaymod/entities/CameraEntity.java | 12 +- .../replaymod/events/GuiEventHandler.java | 15 +- .../replaymod/events/GuiReplayOverlay.java | 117 +++------- .../replaymod/events/KeyInputHandler.java | 99 +++++++++ .../replaymod/gui/GuiSpectateSelection.java | 205 ++++++++++++++++++ .../replaymod/gui/online/GuiLoginPrompt.java | 3 + .../replaymod/holders/Position.java | 10 + .../replaymod/registry/KeybindRegistry.java | 9 +- .../replaymod/replay/ReplayHandler.java | 52 +++-- .../replaymod/replay/ReplaySender.java | 4 +- .../screenshot/ReplayScreenshot.java | 2 +- .../replay/spectate/SpectateHandler.java | 34 +++ 13 files changed, 450 insertions(+), 115 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java create mode 100644 src/main/java/eu/crushedpixel/replaymod/gui/GuiSpectateSelection.java rename src/main/java/eu/crushedpixel/replaymod/{ => replay}/screenshot/ReplayScreenshot.java (99%) create mode 100644 src/main/java/eu/crushedpixel/replaymod/replay/spectate/SpectateHandler.java diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index 833ddfcd..685c659a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -14,6 +14,7 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import eu.crushedpixel.replaymod.api.client.ApiClient; import eu.crushedpixel.replaymod.events.GuiEventHandler; import eu.crushedpixel.replaymod.events.GuiReplayOverlay; +import eu.crushedpixel.replaymod.events.KeyInputHandler; import eu.crushedpixel.replaymod.events.RecordingHandler; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; @@ -81,6 +82,8 @@ public class ReplayMod FMLCommonHandler.instance().bus().register(new ConnectionEventHandler()); MinecraftForge.EVENT_BUS.register(new GuiEventHandler()); + FMLCommonHandler.instance().bus().register(new KeyInputHandler()); + recordingHandler = new RecordingHandler(); FMLCommonHandler.instance().bus().register(recordingHandler); MinecraftForge.EVENT_BUS.register(recordingHandler); diff --git a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java index ebff3543..587d5ea2 100644 --- a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java +++ b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java @@ -28,23 +28,19 @@ public class CameraEntity extends EntityPlayer { private double decay = 6; //decays by 75% per second; private long lastCall = 0; - + //frac = time since last tick public void updateMovement() { Minecraft mc = Minecraft.getMinecraft(); if(ReplayHandler.getCameraEntity() != null && mc.thePlayer != null) { //Aligns the particle rotation - mc.thePlayer.rotationPitch = ReplayHandler.getCameraEntity().rotationPitch; - mc.thePlayer.rotationYaw = ReplayHandler.getCameraEntity().rotationYaw; + mc.thePlayer.rotationPitch = mc.getRenderViewEntity().rotationPitch; + mc.thePlayer.rotationYaw = mc.getRenderViewEntity().rotationYaw; //removes water/suffocation/shadow overlays in screen mc.thePlayer.posX = 0; mc.thePlayer.posY = 500; mc.thePlayer.posZ = 0; - - //mc.thePlayer.posX = ReplayHandler.getCameraEntity().posX; - //mc.thePlayer.posY = ReplayHandler.getCameraEntity().posY; - //mc.thePlayer.posZ = ReplayHandler.getCameraEntity().posZ; } if(direction == null || motion < 0.1) { @@ -182,5 +178,5 @@ public class CameraEntity extends EntityPlayer { public boolean isSpectator() { return true; } - + } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java index 79157a48..f52d2946 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java @@ -49,10 +49,14 @@ public class GuiEventHandler { @SubscribeEvent public void onGui(GuiOpenEvent event) { - if(ReplayMod.firstMainMenu && event.gui instanceof GuiMainMenu) { - ReplayMod.firstMainMenu = false; - event.gui = new GuiLoginPrompt(event.gui, event.gui); - return; + if(event.gui instanceof GuiMainMenu) { + if(ReplayMod.firstMainMenu) { + ReplayMod.firstMainMenu = false; + event.gui = new GuiLoginPrompt(event.gui, event.gui); + return; + } else { + ReplayHandler.setSpeed(1f); + } } if(!AuthenticationHandler.isAuthenticated()) return; @@ -76,7 +80,7 @@ public class GuiEventHandler { private static final Color DARK_RED = Color.decode("#DF0101"); private static final Color DARK_GREEN = Color.decode("#01DF01"); - + @SubscribeEvent public void onDraw(DrawScreenEvent e) { if(e.gui instanceof GuiMainMenu) { @@ -147,7 +151,6 @@ public class GuiEventHandler { Thread t = new Thread(new Runnable() { @Override public void run() { - ReplayHandler.setSpeed(1f); ReplayHandler.endReplay(); mc.gameSettings.setOptionFloatValue(Options.GAMMA, ReplayHandler.getInitialGamma()); diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index 3ea69b85..9c6be1ea 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -23,8 +23,10 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.InputEvent.KeyInputEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; @@ -37,6 +39,7 @@ import eu.crushedpixel.replaymod.entities.CameraEntity; import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection; import eu.crushedpixel.replaymod.gui.GuiMouseInput; import eu.crushedpixel.replaymod.gui.GuiReplaySpeedSlider; +import eu.crushedpixel.replaymod.gui.GuiSpectateSelection; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.holders.PositionKeyframe; @@ -45,7 +48,7 @@ import eu.crushedpixel.replaymod.reflection.MCPNames; import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayProcess; -import eu.crushedpixel.replaymod.screenshot.ReplayScreenshot; +import eu.crushedpixel.replaymod.replay.screenshot.ReplayScreenshot; public class GuiReplayOverlay extends Gui { @@ -80,10 +83,14 @@ public class GuiReplayOverlay extends Gui { private boolean mouseDown = false; - private boolean requestScreenshot = false; + private static boolean requestScreenshot = false; private Field drawBlockOutline; + public static void requestScreenshot() { + requestScreenshot = true; + } + public GuiReplayOverlay() { try { drawBlockOutline = EntityRenderer.class.getDeclaredField(MCPNames.field("field_175073_D")); @@ -105,20 +112,33 @@ public class GuiReplayOverlay extends Gui { if(ReplayHandler.getCameraEntity() != null) ReplayHandler.getCameraEntity().updateMovement(); onMouseMove(new MouseEvent()); - onKeyInput(new KeyInputEvent()); + FMLCommonHandler.instance().bus().post(new InputEvent.KeyInputEvent()); if(ReplayHandler.isReplaying()) ReplayProcess.tickReplay(); } + private double lastX, lastY, lastZ; + private float lastPitch, lastYaw; + @SubscribeEvent public void onRenderWorld(RenderWorldLastEvent event) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException { if(!ReplayHandler.replayActive()) return; - ReplayHandler.setCameraEntity(ReplayHandler.getCameraEntity()); + if(ReplayHandler.isCamera()) ReplayHandler.setCameraEntity(ReplayHandler.getCameraEntity()); if(ReplayHandler.replayActive() && ReplayHandler.isPaused()) { if(mc != null && mc.thePlayer != null) MinecraftTicker.runMouseKeyboardTick(mc); } + if(mc.getRenderViewEntity() == mc.thePlayer) { + ReplayHandler.spectateCamera(); + ReplayHandler.getCameraEntity().movePath(new Position(lastX, lastY, lastZ, lastPitch, lastYaw)); + } else if(!ReplayHandler.isCamera()) { + lastX = mc.getRenderViewEntity().posX; + lastY = mc.getRenderViewEntity().posY; + lastZ = mc.getRenderViewEntity().posZ; + lastPitch = mc.getRenderViewEntity().rotationPitch; + lastYaw = mc.getRenderViewEntity().rotationYaw; + } if(requestScreenshot) { requestScreenshot = false; ReplayScreenshot.saveScreenshot(mc.getFramebuffer()); @@ -135,11 +155,11 @@ public class GuiReplayOverlay extends Gui { @SubscribeEvent public void onRenderGui(RenderGameOverlayEvent.Post event) throws IllegalArgumentException, IllegalAccessException { - if(!ReplayHandler.replayActive()) { + if(!ReplayHandler.replayActive() || FMLClientHandler.instance().isGUIOpen(GuiSpectateSelection.class)) { return; } - ReplayGuiRegistry.hide(); + if(!ReplayGuiRegistry.hidden) ReplayGuiRegistry.hide(); if(event.type == ElementType.PLAYER_LIST) { if(event.isCancelable()) { @@ -147,7 +167,7 @@ public class GuiReplayOverlay extends Gui { } return; } - + GL11.glEnable(GL11.GL_BLEND); drawBlockOutline.set(Minecraft.getMinecraft().entityRenderer, false); @@ -259,7 +279,7 @@ public class GuiReplayOverlay extends Gui { mc.renderEngine.bindTexture(keyframeLocation); - if(hover && Mouse.isButtonDown(0) && isClick()) { + if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { if(ReplayHandler.getSelected() == null || !(ReplayHandler.getSelected() instanceof PositionKeyframe)) { addPlaceKeyframe(); } else { @@ -300,7 +320,7 @@ public class GuiReplayOverlay extends Gui { mc.renderEngine.bindTexture(keyframeLocation); - if(hover && Mouse.isButtonDown(0) && isClick()) { + if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { if(ReplayHandler.getSelected() == null || !(ReplayHandler.getSelected() instanceof TimeKeyframe)) { addTimeKeyframe(); } else { @@ -455,7 +475,7 @@ public class GuiReplayOverlay extends Gui { slider_end_width, slider_height, 64, 64); //Slider dragging - if(Mouse.isButtonDown(0) && (mouseX >= slider_min && mouseX <= sl_max && mouseY >= sl_y && mouseY <= sl_y+slider_height || wasSliding)) { + if(Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class) && (mouseX >= slider_min && mouseX <= sl_max && mouseY >= sl_y && mouseY <= sl_y+slider_height || wasSliding)) { wasSliding = true; float dx = ((float)Mouse.getDX() * (float)new ScaledResolution(mc, mc.displayWidth, mc.displayHeight).getScaledWidth() / mc.displayWidth); this.pos_left = Math.min(1f-this.zoom_scale, Math.max(0f, this.pos_left+(dx/(float)tlWidth))); @@ -482,7 +502,7 @@ public class GuiReplayOverlay extends Gui { this.drawModalRectWithCustomSizedTexture(maxX+2, y+1, px, plus_y, 9, 9, 64, 64); - if(hover && Mouse.isButtonDown(0)) { + if(hover && Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { zoomIn(); } @@ -502,7 +522,7 @@ public class GuiReplayOverlay extends Gui { this.drawModalRectWithCustomSizedTexture(maxX+2, y+9+3, mx, minus_y, 9, 9, 64, 64); - if(hover && Mouse.isButtonDown(0)) { + if(hover && Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { zoomOut(); } @@ -573,7 +593,7 @@ public class GuiReplayOverlay extends Gui { } //handle Mouse clicks on realTimeLine - if(Mouse.isButtonDown(0) && !wasSliding && mouseX >= minX+tl_begin_width && mouseX <= maxX-tl_end_width && + if(Mouse.isButtonDown(0) && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class) && !wasSliding && mouseX >= minX+tl_begin_width && mouseX <= maxX-tl_end_width && mouseY >= y && mouseY <= y+22) { //calculate real time and set cursor accordingly @@ -679,7 +699,7 @@ public class GuiReplayOverlay extends Gui { this.drawModalRectWithCustomSizedTexture(r_ppButtonX, r_ppButtonY, dx, dy, 20, 20, 64, 64); //Handling the click on the Replay starter - if(hover && Mouse.isButtonDown(0) && isClick()) { + if(hover && Mouse.isButtonDown(0) && isClick() && FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { if(ReplayHandler.isReplaying()) { ReplayHandler.interruptReplay(); } else { @@ -796,73 +816,4 @@ public class GuiReplayOverlay extends Gui { } } - - @SubscribeEvent - public void onKeyInput(KeyInputEvent event) { - - if(!ReplayHandler.replayActive()) return; - if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) { - return; - } - - KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; - for(KeyBinding kb : keyBindings) { - if(!kb.isKeyDown()) { - continue; - } - try { - - if(kb.getKeyDescription().equals("key.forward")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD); - continue; - } - - if(kb.getKeyDescription().equals("key.back")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD); - continue; - } - - if(kb.getKeyDescription().equals("key.jump")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP); - continue; - } - - if(kb.getKeyDescription().equals("key.sneak")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN); - continue; - } - - if(kb.getKeyDescription().equals("key.left")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT); - continue; - } - - if(kb.getKeyDescription().equals("key.right")) { - ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT); - continue; - } - - if(kb.getKeyDescription().equals("key.chat")) { - mc.displayGuiScreen(new GuiMouseInput()); - continue; - } - - //Custom registered handlers - if(kb.getKeyDescription().equals("key.thumbnail") && kb.isPressed()) { - ReplayScreenshot.prepareScreenshot(); - requestScreenshot = true; - continue; - } - - if(kb.getKeyDescription().equals("key.lighting") && kb.isPressed()) { - ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled()); - continue; - } - - } catch(Exception e) { - e.printStackTrace(); - } - - } - } } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java new file mode 100644 index 00000000..d0f3848f --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/events/KeyInputHandler.java @@ -0,0 +1,99 @@ +package eu.crushedpixel.replaymod.events; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.fml.client.FMLClientHandler; +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.registry.KeybindRegistry; +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import eu.crushedpixel.replaymod.replay.screenshot.ReplayScreenshot; +import eu.crushedpixel.replaymod.replay.spectate.SpectateHandler; + +public class KeyInputHandler { + + private Minecraft mc = Minecraft.getMinecraft(); + + @SubscribeEvent + public void onKeyInput(KeyInputEvent event) { + + if(!ReplayHandler.replayActive()) return; + if(mc.currentScreen != null) { + return; + } + + KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings; + for(KeyBinding kb : keyBindings) { + if(!kb.isKeyDown()) { + continue; + } + try { + + if(ReplayHandler.isCamera()) { + if(kb.getKeyDescription().equals("key.forward")) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD); + continue; + } + + if(kb.getKeyDescription().equals("key.back")) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD); + continue; + } + + if(kb.getKeyDescription().equals("key.jump")) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP); + continue; + } + + if(kb.getKeyDescription().equals("key.left")) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT); + continue; + } + + if(kb.getKeyDescription().equals("key.right")) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT); + continue; + } + } + if(kb.getKeyDescription().equals("key.sneak")) { + if(ReplayHandler.isCamera()) { + ReplayHandler.getCameraEntity().setMovement(MoveDirection.DOWN); + } else { + ReplayHandler.spectateCamera(); + } + continue; + } + + if(kb.getKeyDescription().equals("key.chat")) { + mc.displayGuiScreen(new GuiMouseInput()); + continue; + } + + //Custom registered handlers + if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && kb.isPressed()) { + ReplayScreenshot.prepareScreenshot(); + GuiReplayOverlay.requestScreenshot(); + continue; + } + + if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SPECTATE) && kb.isPressed()) { + SpectateHandler.openSpectateSelection(); + continue; + } + + if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && kb.isPressed()) { + ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled()); + continue; + } + + } catch(Exception e) { + e.printStackTrace(); + } + + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/GuiSpectateSelection.java b/src/main/java/eu/crushedpixel/replaymod/gui/GuiSpectateSelection.java new file mode 100644 index 00000000..3cc78735 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/gui/GuiSpectateSelection.java @@ -0,0 +1,205 @@ +package eu.crushedpixel.replaymod.gui; + +import java.awt.Color; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +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.common.versioning.ComparableVersion; + +import com.mojang.realmsclient.util.Pair; + +import eu.crushedpixel.replaymod.replay.ReplayHandler; + +public class GuiSpectateSelection extends GuiScreen { + + private List> players; + private int playerCount; + private int upperPlayer = 0; + + private int upperBound = 30; + private int lowerBound; + + private double prevSpeed; + + private class PlayerComparator implements Comparator { + + @Override + public int compare(EntityPlayer o1, EntityPlayer o2) { + if(isSpectator(o1) && !isSpectator(o2)) { + return 1; + } else if(isSpectator(o2) && !isSpectator(o1)) { + return -1; + } else { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + } + + } + + private boolean isSpectator(EntityPlayer e) { + return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null; + } + + public GuiSpectateSelection(List players) { + this.prevSpeed = ReplayHandler.getSpeed(); + + players.sort(new PlayerComparator()); + + this.players = new ArrayList>(); + + for(EntityPlayer p : players) { + ResourceLocation loc = new ResourceLocation("/temp-skins/"+p.getGameProfile().getName()); + AbstractClientPlayer.getDownloadImageSkin(loc, p.getName()); + this.players.add(Pair.of(p, loc)); + } + + playerCount = players.size(); + + ReplayHandler.setSpeed(0); + } + + private boolean drag = false; + + @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.4); + + if(mouseX >= k2-16 && mouseX <= k2-12 && mouseY >= 32-2+offset && mouseY <= lower) { + lastY = mouseY; + drag = true; + return; + } + } + int k2 = (int)(this.width*0.4); + int l2 = 30; + + if(mouseX >= k2 && mouseX <= (this.width*0.6) && mouseY >= 30 && mouseY <= lowerBound) { + int off = mouseY-30; + int p = (off/21) + upperPlayer; + ReplayHandler.spectateEntity(players.get(p).first()); + ReplayHandler.setSpeed(prevSpeed); + mc.displayGuiScreen(null); + } + } + + private int lastY = 0; + + @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 + public void onGuiClosed() { + ReplayHandler.setSpeed(prevSpeed); + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + drag = false; + + super.mouseReleased(mouseX, mouseY, state); + } + + @Override + public void initGui() { + upperPlayer = 0; + lowerBound = this.height-10; + } + + private int fitting = 0; + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.drawCenteredString(fontRendererObj, "Spectate Player", this.width/2, 5, Color.WHITE.getRGB()); + int k2 = (int)(this.width*0.4); + int l2 = 30; + + drawGradientRect(k2-10, l2-10, (int)(this.width*0.6)+20, this.height-30-2+10, -1072689136, -804253680); + + fitting = 0; + + int sk = 0; + for(Pair p : players) { + if(sk < upperPlayer) { + sk++; + continue; + } + boolean spec = isSpectator(p.first()); + + this.drawString(fontRendererObj, p.first().getName(), k2+16+5, l2+8-(fontRendererObj.FONT_HEIGHT/2), + spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB()); + + mc.getTextureManager().bindTexture(p.second()); + + this.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(); + + l2 += 16+5; + fitting++; + if(l2+32 > lowerBound) { + break; + } + } + + 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)); + + this.drawRect(k2-18, 30-2, k2-10, this.height-30-2, Color.BLACK.getRGB()); + this.drawRect(k2-16, 32-2+offset, k2-12, lower-2, Color.LIGHT_GRAY.getRGB()); + } else { + + } + + super.drawScreen(mouseX, mouseY, partialTicks); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java index c78f7a25..79b2a99e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiLoginPrompt.java @@ -119,6 +119,9 @@ public class GuiLoginPrompt extends GuiScreen { case LOGGING_IN: drawCenteredString(fontRendererObj, "Logging in...", this.width/2, 92, Color.WHITE.getRGB()); break; + case NO_CONNECTION: + drawCenteredString(fontRendererObj, "Could not connect to ReplayMod.com", this.width/2, 92, Color.RED.getRGB()); + break; } super.drawScreen(mouseX, mouseY, partialTicks); } diff --git a/src/main/java/eu/crushedpixel/replaymod/holders/Position.java b/src/main/java/eu/crushedpixel/replaymod/holders/Position.java index 0a02ce82..51df03c0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/holders/Position.java +++ b/src/main/java/eu/crushedpixel/replaymod/holders/Position.java @@ -1,10 +1,20 @@ package eu.crushedpixel.replaymod.holders; +import net.minecraft.entity.Entity; + public class Position { private double x, y, z; private float pitch, yaw; + public Position(Entity e) { + this.x = e.posX; + this.y = e.posY; + this.z = e.posZ; + this.pitch = e.rotationPitch; + this.yaw = e.rotationYaw; + } + public Position(double x, double y, double z, float pitch, float yaw) { this.x = x; this.y = y; diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java index cf149abd..b6d291f4 100644 --- a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java @@ -13,11 +13,16 @@ public class KeybindRegistry { private static Minecraft mc = Minecraft.getMinecraft(); + public static final String KEY_LIGHTING = "Toggle Lighting"; + public static final String KEY_THUMBNAIL = "Create Thumbnail"; + public static final String KEY_SPECTATE = "Spectate Entity"; + public static void initialize() { List bindings = new ArrayList(Arrays.asList(mc.gameSettings.keyBindings)); - bindings.add(new KeyBinding("key.lighting", Keyboard.KEY_V, "category.replaymod")); - bindings.add(new KeyBinding("key.thumbnail", Keyboard.KEY_B, "category.replaymod")); + bindings.add(new KeyBinding(KEY_LIGHTING, Keyboard.KEY_V, "Replay Mod")); + bindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_B, "Replay Mod")); + bindings.add(new KeyBinding(KEY_SPECTATE, Keyboard.KEY_C, "Replay Mod")); mc.gameSettings.keyBindings = bindings.toArray(new KeyBinding[bindings.size()]); } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index f44d90eb..85bc3d1e 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -12,6 +12,7 @@ import java.util.UUID; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.entity.Entity; import net.minecraft.network.EnumPacketDirection; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.INetHandlerPlayClient; @@ -26,6 +27,7 @@ import eu.crushedpixel.replaymod.holders.KeyframeComparator; import eu.crushedpixel.replaymod.holders.Position; import eu.crushedpixel.replaymod.holders.PositionKeyframe; import eu.crushedpixel.replaymod.holders.TimeKeyframe; +import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; public class ReplayHandler { @@ -35,7 +37,7 @@ public class ReplayHandler { private static OpenEmbeddedChannel channel; private static int realTimelinePosition = 0; - + private static Keyframe selectedKeyframe; private static boolean isReplaying = false; @@ -49,15 +51,39 @@ public class ReplayHandler { public static long lastExit = 0; private static float gamma = 0f; - + + private static Entity currentEntity = null; + + public static void spectateEntity(Entity e) { + currentEntity = e; + mc.setRenderViewEntity(currentEntity); + } + + public static Entity getSpectatedEntity() { + return currentEntity; + } + + public static void spectateCamera() { + if(currentEntity != null) { + Position prev = new Position(currentEntity); + cameraEntity.movePath(prev); + } + currentEntity = cameraEntity; + mc.setRenderViewEntity(cameraEntity); + } + + public static boolean isCamera() { + return currentEntity == cameraEntity; + } + public static void setInitialGamma(float initial) { gamma = initial; } - + public static float getInitialGamma() { return gamma; } - + public static void setReplaying(boolean replaying) { isReplaying = replaying; } @@ -73,11 +99,11 @@ public class ReplayHandler { public static boolean isReplaying() { return isReplaying; } - + public static void setCameraEntity(CameraEntity entity) { if(entity == null) return; cameraEntity = entity; - mc.setRenderViewEntity(cameraEntity); + spectateCamera(); } public static CameraEntity getCameraEntity() { @@ -135,7 +161,7 @@ public class ReplayHandler { } return size; } - + public static int getTimeKeyframeCount() { int size = 0; for(Keyframe kf : keyframes) { @@ -240,7 +266,7 @@ public class ReplayHandler { public static void resetKeyframes() { keyframes = new ArrayList(); - + selectKeyframe(null); } @@ -249,7 +275,7 @@ public class ReplayHandler { replaySender.jumpToTime(pos); } } - + public static boolean isHurrying() { if(replaySender != null) { return replaySender.isHurrying(); @@ -299,7 +325,7 @@ public class ReplayHandler { } public static void startReplay(File file) throws NoSuchMethodException, SecurityException, NoSuchFieldException { - + ChatMessageRequests.initialize(); mc.ingameGUI.getChatGUI().clearChatMessages(); resetKeyframes(); @@ -372,11 +398,11 @@ public class ReplayHandler { public static Keyframe getSelected() { return selectedKeyframe; } - + public static int getRealTimelineCursor() { return realTimelinePosition; } - + public static void setRealTimelineCursor(int pos) { realTimelinePosition = pos; } @@ -385,7 +411,7 @@ public class ReplayHandler { public static void setLastPosition(Position position) { lastPosition = position; } - + public static Position getLastPosition() { return lastPosition; } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index 14cb4380..fb68e281 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -8,8 +8,8 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.BufferedReader; import java.io.DataInputStream; -import java.io.EOFException; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; @@ -332,7 +332,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { hasRestarted = false; } - } catch(EOFException eof) { + } catch(IOException eof) { setReplaySpeed(0); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/screenshot/ReplayScreenshot.java b/src/main/java/eu/crushedpixel/replaymod/replay/screenshot/ReplayScreenshot.java similarity index 99% rename from src/main/java/eu/crushedpixel/replaymod/screenshot/ReplayScreenshot.java rename to src/main/java/eu/crushedpixel/replaymod/replay/screenshot/ReplayScreenshot.java index 6a03478f..f8318b67 100644 --- a/src/main/java/eu/crushedpixel/replaymod/screenshot/ReplayScreenshot.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/screenshot/ReplayScreenshot.java @@ -1,4 +1,4 @@ -package eu.crushedpixel.replaymod.screenshot; +package eu.crushedpixel.replaymod.replay.screenshot; import java.awt.Dimension; import java.awt.Rectangle; diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/spectate/SpectateHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/spectate/SpectateHandler.java new file mode 100644 index 00000000..2861bbf6 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/replay/spectate/SpectateHandler.java @@ -0,0 +1,34 @@ +package eu.crushedpixel.replaymod.replay.spectate; + +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; + +import com.google.common.base.Predicate; + +import eu.crushedpixel.replaymod.entities.CameraEntity; +import eu.crushedpixel.replaymod.gui.GuiSpectateSelection; +import eu.crushedpixel.replaymod.replay.ReplayHandler; + +public class SpectateHandler { + + private static Minecraft mc = Minecraft.getMinecraft(); + + private static Predicate playerPredicate = new Predicate() { + @Override + public boolean apply(EntityPlayer input) { + if(input instanceof CameraEntity || input == mc.thePlayer) return false; + return true; + } + }; + + public static void openSpectateSelection() { + if(!ReplayHandler.replayActive()) { + return; + } + + List players = mc.theWorld.getEntities(EntityPlayer.class, playerPredicate); + mc.displayGuiScreen(new GuiSpectateSelection(players)); + } +}