diff --git a/src/main/java/com/replaymod/replay/CameraEntity.java b/src/main/java/com/replaymod/replay/CameraEntity.java deleted file mode 100755 index 94f4dcfa..00000000 --- a/src/main/java/com/replaymod/replay/CameraEntity.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.replaymod.replay; - -import eu.crushedpixel.replaymod.holders.AdvancedPosition; -import eu.crushedpixel.replaymod.replay.LesserDataWatcher; -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.stats.StatFileWriter; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.MathHelper; -import net.minecraft.util.MovingObjectPosition; -import net.minecraft.util.Vec3; -import net.minecraft.world.World; -import org.lwjgl.Sys; - -import java.util.UUID; - -public class CameraEntity extends EntityPlayerSP { - - public static final double SPEED_CHANGE = 0.5; - public static final double LOWER_SPEED = 2; - public static final double UPPER_SPEED = 20; - - private static double MAX_SPEED = 10; - private static double THRESHOLD = MAX_SPEED / 20; - private static double DECAY = MAX_SPEED/3; - - public static void modifyCameraSpeed(boolean increase) { - setCameraMaximumSpeed(getCameraMaximumSpeed() + (increase ? 1 : -1) * SPEED_CHANGE); - } - - public static void setCameraMaximumSpeed(double maxSpeed) { - if(maxSpeed < LOWER_SPEED || maxSpeed > UPPER_SPEED) return; - MAX_SPEED = maxSpeed; - THRESHOLD = MAX_SPEED / 20; - DECAY = 5; - } - - public static double getCameraMaximumSpeed() { - return MAX_SPEED; - } - - private Vec3 direction; - private Vec3 dirBefore; - private double motion; - - public float roll; - - private long lastCall = 0; - - private boolean speedup = false; - - public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) { - super(mcIn, worldIn, netHandlerPlayClient, statFileWriter); - } - - //frac = time since last tick - public void updateMovement() { - - long frac = Sys.getTime() - lastCall; - - if(frac == 0) return; - - double decFac = Math.max(0, 1 - (DECAY * (frac / 1000D))); - - if(speedup) { - if(motion < THRESHOLD) motion = THRESHOLD; - motion /= decFac; - } else { - motion *= decFac; - } - - motion = Math.min(motion, MAX_SPEED); - - lastCall = Sys.getTime(); - - if(direction == null || motion < THRESHOLD) { - return; - } - - Vec3 movement = direction.normalize(); - double factor = motion * (frac / 1000D); - - moveRelative(movement.xCoord * factor, movement.yCoord * factor, movement.zCoord * factor); - } - - public void speedUp() { - speedup = true; - } - - public void stopSpeedUp() { - speedup = false; - } - - public void setMovement(MoveDirection dir) { - switch(dir) { - case BACKWARD: - direction = this.getVectorForRotation(-rotationPitch, rotationYaw - 180); - break; - case DOWN: - direction = this.getVectorForRotation(90, 0); - break; - case FORWARD: - direction = this.getVectorForRotation(rotationPitch, rotationYaw); - break; - case LEFT: - direction = this.getVectorForRotation(0, rotationYaw - 90); - break; - case RIGHT: - direction = this.getVectorForRotation(0, rotationYaw + 90); - break; - case UP: - direction = this.getVectorForRotation(-90, 0); - break; - } - - Vec3 dbf = direction; - - if(dirBefore != null) { - direction = dirBefore.normalize().add(direction); - } - - dirBefore = dbf; - - updateMovement(); - } - - public void moveAbsolute(AdvancedPosition pos) { - 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) { - this.lastTickPosX = this.prevPosX = this.posX = x; - this.lastTickPosY = this.prevPosY = this.posY = y; - this.lastTickPosZ = this.prevPosZ = this.posZ = z; - updateBoundingBox(); - } - - public void moveRelative(double x, double y, double z) { - 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; - updateBoundingBox(); - } - - 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(); - updateBoundingBox(); - } - - private void updateBoundingBox() { - this.setEntityBoundingBox(new AxisAlignedBB(posX - width / 2, posY, posZ - width / 2, - posX + width / 2, posY + height, posZ + width / 2)); - } - - protected void updatePos(Entity to) { - prevPosX = to.prevPosX; - prevPosY = to.prevPosY; - prevPosZ = to.prevPosZ; - prevRotationYaw = to.prevRotationYaw; - prevRotationPitch = to.prevRotationPitch; - posX = to.posX; - posY = to.posY; - posZ = to.posZ; - rotationYaw = to.rotationYaw; - rotationPitch = to.rotationPitch; - } - - @Override - protected void entityInit() { - this.dataWatcher = new LesserDataWatcher(this); - this.setSize(0.6f, 1.8f); - updateBoundingBox(); - } - - @Override - public void setAngles(float yaw, float pitch) { - 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); - this.prevRotationPitch = this.rotationPitch; - this.prevRotationYawHead = this.rotationYawHead = this.prevRotationYaw = this.rotationYaw; - } - - @Override - 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) { - mc.setRenderViewEntity(view); - } else { - mc.setRenderViewEntity(this); - return; - } - } - if (view != this) { - updatePos(view); - } - } - } - - @Override - public void preparePlayerToSpawn() { - if (mc.theWorld != null) { - worldObj = mc.theWorld; - } - super.preparePlayerToSpawn(); - } - - @Override - public boolean isEntityInsideOpaqueBlock() { - return false; - } - - @Override - public boolean isInsideOfMaterial(Material materialIn) { - return false; - } - - @Override - public boolean isInLava() { - return false; - } - - @Override - public boolean isInWater() { - return false; - } - - @Override - public boolean canBePushed() { - return false; - } - - @Override - protected void createRunningParticles() {} - - @Override - public boolean canBeCollidedWith() { - return false; - } - - @Override - public boolean isSpectator() { - return true; - } - - public enum MoveDirection { - UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD - } - - @Override - public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) { - MovingObjectPosition pos = super.rayTrace(p_174822_1_, 1f); - - if(pos != null && pos.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { - pos.typeOfHit = MovingObjectPosition.MovingObjectType.MISS; - } - - return pos; - } -} diff --git a/src/main/java/com/replaymod/replay/InputReplayTimer.java b/src/main/java/com/replaymod/replay/InputReplayTimer.java index 949f42f0..da1bd5fb 100644 --- a/src/main/java/com/replaymod/replay/InputReplayTimer.java +++ b/src/main/java/com/replaymod/replay/InputReplayTimer.java @@ -1,6 +1,8 @@ package com.replaymod.replay; import com.replaymod.core.utils.WrappedTimer; +import com.replaymod.replay.camera.CameraController; +import com.replaymod.replay.camera.CameraEntity; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.settings.GameSettings; @@ -64,7 +66,21 @@ public class InputReplayTimer extends WrappedTimer { int wheel = Mouse.getEventDWheel(); if (wheel != 0) { - // TODO: Update camera movement speed + ReplayHandler replayHandler = mod.getReplayHandler(); + if (replayHandler != null) { + CameraEntity cameraEntity = replayHandler.getCameraEntity(); + if (cameraEntity != null) { + CameraController controller = cameraEntity.getCameraController(); + while (wheel > 0) { + controller.increaseSpeed(); + wheel--; + } + while (wheel < 0) { + controller.decreaseSpeed(); + wheel++; + } + } + } } if (mc.currentScreen == null) { diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index d806649f..788a8089 100755 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -2,6 +2,7 @@ package com.replaymod.replay; import com.google.common.base.Preconditions; import com.mojang.authlib.GameProfile; +import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.events.ReplayCloseEvent; import com.replaymod.replay.events.ReplayOpenEvent; import com.replaymod.replay.gui.overlay.GuiReplayOverlay; @@ -72,7 +73,7 @@ public class ReplayHandler { */ private AdvancedPosition targetCameraPosition; - protected UUID spectating; + private UUID spectating; public ReplayHandler(ReplayFile replayFile, boolean asyncMode) throws IOException { Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread."); @@ -212,7 +213,7 @@ public class ReplayHandler { if (mc.getRenderViewEntity() != e) { mc.setRenderViewEntity(e); - cameraEntity.updatePos(e); + cameraEntity.setCameraPosRot(e); } } @@ -240,6 +241,10 @@ public class ReplayHandler { return mc.thePlayer instanceof CameraEntity ? (CameraEntity) mc.thePlayer : null; } + public UUID getSpectatedUUID() { + return spectating; + } + public void setTargetPosition(AdvancedPosition pos) { targetCameraPosition = pos; } @@ -247,7 +252,7 @@ public class ReplayHandler { public void moveCameraToTargetPosition() { CameraEntity cam = getCameraEntity(); if (cam != null && targetCameraPosition != null) { - cam.moveAbsolute(targetCameraPosition); + cam.setCameraPosRot(targetCameraPosition); } } diff --git a/src/main/java/com/replaymod/replay/ReplaySender.java b/src/main/java/com/replaymod/replay/ReplaySender.java index 449f581d..7dda40a4 100755 --- a/src/main/java/com/replaymod/replay/ReplaySender.java +++ b/src/main/java/com/replaymod/replay/ReplaySender.java @@ -3,6 +3,7 @@ package com.replaymod.replay; import com.google.common.base.Preconditions; import com.google.common.io.Files; import com.google.common.util.concurrent.ListenableFutureTask; +import com.replaymod.replay.camera.CameraEntity; import de.johni0702.replaystudio.replay.ReplayFile; import eu.crushedpixel.replaymod.holders.PacketData; import com.replaymod.core.utils.Restrictions; @@ -425,7 +426,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } CameraEntity cent = replayHandler.getCameraEntity(); - cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e()); + cent.setCameraPosition(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e()); return null; } }.call(); diff --git a/src/main/java/com/replaymod/replay/camera/CameraController.java b/src/main/java/com/replaymod/replay/camera/CameraController.java new file mode 100644 index 00000000..c4aa532d --- /dev/null +++ b/src/main/java/com/replaymod/replay/camera/CameraController.java @@ -0,0 +1,8 @@ +package com.replaymod.replay.camera; + +public interface CameraController { + void update(float partialTicksPassed); + + void increaseSpeed(); + void decreaseSpeed(); +} diff --git a/src/main/java/com/replaymod/replay/camera/CameraEntity.java b/src/main/java/com/replaymod/replay/camera/CameraEntity.java new file mode 100755 index 00000000..5f102e97 --- /dev/null +++ b/src/main/java/com/replaymod/replay/camera/CameraEntity.java @@ -0,0 +1,217 @@ +package com.replaymod.replay.camera; + +import com.replaymod.replay.ReplayModReplay; +import eu.crushedpixel.replaymod.holders.AdvancedPosition; +import lombok.Getter; +import lombok.Setter; +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.stats.StatFileWriter; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.UUID; + +/** + * The camera entity used as the main player entity during replay viewing. + * During a replay {@link Minecraft#thePlayer} should be an instance of this class. + * Camera movement is controlled by a separate {@link CameraController}. + */ +public class CameraEntity extends EntityPlayerSP { + /** + * Roll of this camera in degrees. + */ + public float roll; + + @Getter + @Setter + private CameraController cameraController; + + private long lastControllerUpdate = System.currentTimeMillis(); + + public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) { + super(mcIn, worldIn, netHandlerPlayClient, statFileWriter); + FMLCommonHandler.instance().bus().register(this); + cameraController = new VanillaCameraController(mc, this); + } + + /** + * Moves the camera by the specified delta. + * @param x Delta in X direction + * @param y Delta in Y direction + * @param z Delta in Z direction + */ + public void moveCamera(double x, double y, double z) { + setCameraPosition(posX + x, posY + y, posZ + z); + } + + /** + * Set the camera position. + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + */ + public void setCameraPosition(double x, double y, double z) { + this.lastTickPosX = this.prevPosX = this.posX = x; + this.lastTickPosY = this.prevPosY = this.posY = y; + this.lastTickPosZ = this.prevPosZ = this.posZ = z; + updateBoundingBox(); + } + + /** + * Sets the camera rotation. + * @param yaw Yaw in degrees + * @param pitch Pitch in degrees + * @param roll Roll in degrees + */ + public void setCameraRotation(float yaw, float pitch, float roll) { + this.prevRotationYaw = this.rotationYaw = yaw; + this.prevRotationPitch = this.rotationPitch = pitch; + this.roll = roll; + } + + /** + * Sets the camera position and rotation to that of the specified AdvancedPosition + * @param pos The position and rotation to set + */ + public void setCameraPosRot(AdvancedPosition pos) { + setCameraRotation((float) pos.getYaw(), (float) pos.getPitch(), (float) pos.getRoll()); + setCameraPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + /** + * Sets the camera position and rotation to that of the specified entity. + * @param to The entity whose position to copy + */ + public void setCameraPosRot(Entity to) { + prevPosX = to.prevPosX; + prevPosY = to.prevPosY; + prevPosZ = to.prevPosZ; + prevRotationYaw = to.prevRotationYaw; + prevRotationPitch = to.prevRotationPitch; + posX = to.posX; + posY = to.posY; + posZ = to.posZ; + rotationYaw = to.rotationYaw; + rotationPitch = to.rotationPitch; + lastTickPosX = to.lastTickPosX; + lastTickPosY = to.lastTickPosY; + lastTickPosZ = to.lastTickPosZ; + updateBoundingBox(); + } + + private void updateBoundingBox() { + setEntityBoundingBox(new AxisAlignedBB( + posX - width / 2, posY, posZ - width / 2, + posX + width / 2, posY + height, posZ + width / 2)); + } + + @Override + public void onUpdate() { + Entity view = mc.getRenderViewEntity(); + if (view != null) { + // Make sure we're always spectating the right entity + // This is important if the spectated player respawns as their + // entity is recreated and we have to spectate a new entity + UUID spectating = ReplayModReplay.instance.getReplayHandler().getSpectatedUUID(); + if (spectating != null && (view.getUniqueID() != spectating || view.worldObj != worldObj)) { + view = worldObj.getPlayerEntityByUUID(spectating); + if (view != null) { + mc.setRenderViewEntity(view); + } else { + mc.setRenderViewEntity(this); + return; + } + } + // Move cmera to their position so when we exit the first person view + // we don't jump back to where we entered it + if (view != this) { + setCameraPosRot(view); + } + } + } + + @Override + public void preparePlayerToSpawn() { + // Make sure our world is up-to-date in case of world changes + if (mc.theWorld != null) { + worldObj = mc.theWorld; + } + super.preparePlayerToSpawn(); + } + + @Override + public boolean isEntityInsideOpaqueBlock() { + return false; // Make sure no suffocation overlay is rendered + } + + @Override + public boolean isInsideOfMaterial(Material materialIn) { + return false; // Make sure no overlays are rendered + } + + @Override + public boolean isInLava() { + return false; // Make sure no lava overlay is rendered + } + + @Override + public boolean isInWater() { + return false; // Make sure no water overlay is rendered + } + + @Override + public boolean canBePushed() { + return false; // We are in full control of ourselves + } + + @Override + protected void createRunningParticles() { + // We do not produce any particles, we are a camera + } + + @Override + public boolean canBeCollidedWith() { + return false; // We are a camera, we cannot collide + } + + @Override + public boolean isSpectator() { + return true; // Make sure we're treated as spectator + } + + @Override + public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) { + MovingObjectPosition pos = super.rayTrace(p_174822_1_, 1f); + + // Make sure we can never look at blocks (-> no outline) + if(pos != null && pos.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { + pos.typeOfHit = MovingObjectPosition.MovingObjectType.MISS; + } + + return pos; + } + + @Override + public void setDead() { + super.setDead(); + FMLCommonHandler.instance().bus().unregister(this); + } + + @SubscribeEvent + public void onRenderUpdate(TickEvent.RenderTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + long now = System.currentTimeMillis(); + long timePassed = now - lastControllerUpdate; + cameraController.update(timePassed / 50f); + lastControllerUpdate = now; + } + } +} diff --git a/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java b/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java new file mode 100644 index 00000000..22a52241 --- /dev/null +++ b/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java @@ -0,0 +1,116 @@ +package com.replaymod.replay.camera; + +public class ClassicCameraController implements CameraController { + @Override + public void update(float partialTicksPassed) { + // TODO + } + + @Override + public void increaseSpeed() { + + } + + @Override + public void decreaseSpeed() { + + } + + +// public static final double SPEED_CHANGE = 0.5; +// public static final double LOWER_SPEED = 2; +// public static final double UPPER_SPEED = 20; +// +// private static double MAX_SPEED = 10; +// private static double THRESHOLD = MAX_SPEED / 20; +// private static double DECAY = MAX_SPEED/3; +// +// public static void modifyCameraSpeed(boolean increase) { +// setCameraMaximumSpeed(getCameraMaximumSpeed() + (increase ? 1 : -1) * SPEED_CHANGE); +// } +// +// public static void setCameraMaximumSpeed(double maxSpeed) { +// if(maxSpeed < LOWER_SPEED || maxSpeed > UPPER_SPEED) return; +// MAX_SPEED = maxSpeed; +// THRESHOLD = MAX_SPEED / 20; +// DECAY = 5; +// } +// +// public static double getCameraMaximumSpeed() { +// return MAX_SPEED; +// } +// +// private Vec3 direction; +// private Vec3 dirBefore; +// private double motion; +// private long lastCall = 0; +// +// private boolean speedup = false; +// +// //frac = time since last tick +// public void updateMovement() { +// +// long frac = Sys.getTime() - lastCall; +// +// if(frac == 0) return; +// +// double decFac = Math.max(0, 1 - (DECAY * (frac / 1000D))); +// +// if(speedup) { +// if(motion < THRESHOLD) motion = THRESHOLD; +// motion /= decFac; +// } else { +// motion *= decFac; +// } +// +// motion = Math.min(motion, MAX_SPEED); +// +// lastCall = Sys.getTime(); +// +// if(direction == null || motion < THRESHOLD) { +// return; +// } +// +// Vec3 movement = direction.normalize(); +// double factor = motion * (frac / 1000D); +// +// moveCamera(movement.xCoord * factor, movement.yCoord * factor, movement.zCoord * factor); +// } +// +// public void setMovement(MoveDirection dir) { +// switch(dir) { +// case BACKWARD: +// direction = this.getVectorForRotation(-rotationPitch, rotationYaw - 180); +// break; +// case DOWN: +// direction = this.getVectorForRotation(90, 0); +// break; +// case FORWARD: +// direction = this.getVectorForRotation(rotationPitch, rotationYaw); +// break; +// case LEFT: +// direction = this.getVectorForRotation(0, rotationYaw - 90); +// break; +// case RIGHT: +// direction = this.getVectorForRotation(0, rotationYaw + 90); +// break; +// case UP: +// direction = this.getVectorForRotation(-90, 0); +// break; +// } +// +// Vec3 dbf = direction; +// +// if(dirBefore != null) { +// direction = dirBefore.normalize().add(direction); +// } +// +// dirBefore = dbf; +// +// updateMovement(); +// } +// +// public enum MoveDirection { +// UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD +// } +} diff --git a/src/main/java/com/replaymod/replay/camera/VanillaCameraController.java b/src/main/java/com/replaymod/replay/camera/VanillaCameraController.java new file mode 100644 index 00000000..15aa2d5d --- /dev/null +++ b/src/main/java/com/replaymod/replay/camera/VanillaCameraController.java @@ -0,0 +1,74 @@ +package com.replaymod.replay.camera; + +import com.sun.javafx.geom.Vec3d; +import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; + +/** + * Camera controller performing vanilla creative-like camera movements. + */ +public class VanillaCameraController implements CameraController { + private static final int MAX_SPEED = 1000; + private static final int MIN_SPEED = -1000; + + private static final Vec3d[] DIRECTIONS = new Vec3d[]{ + new Vec3d(0, 0, 1), new Vec3d(0, 0, -1), new Vec3d(1, 0, 0), new Vec3d(-1, 0, 0), + new Vec3d(0, 1, 0), new Vec3d(0, -1, 0), + }; + + private final KeyBinding[] bindings = new KeyBinding[6]; + + private final CameraEntity camera; + + private int speed; + + public VanillaCameraController(Minecraft mc, CameraEntity camera) { + this.camera = camera; + GameSettings gameSettings = mc.gameSettings; + this.bindings[0] = gameSettings.keyBindForward; + this.bindings[1] = gameSettings.keyBindBack; + this.bindings[2] = gameSettings.keyBindLeft; + this.bindings[3] = gameSettings.keyBindRight; + this.bindings[4] = gameSettings.keyBindJump; + this.bindings[5] = gameSettings.keyBindSneak; + } + + @Override + public void update(float partialTicksPassed) { + if (partialTicksPassed == 0) return; + Vec3d direction = new Vec3d(0, 0, 0); + for (int i = 0; i < 6; i++) { // First, get movement direction depending on keys pressed + if (bindings[i].isKeyDown()) { + direction.add(DIRECTIONS[i]); + } + } + if (direction.length() == 0) return; + direction.normalize(); // Normalize, so we don't move quicker if we hold down multiple keys + double yawRadians = Math.toRadians(camera.rotationYaw); + double yawSin = Math.sin(yawRadians), yawCos = Math.cos(yawRadians); + // Rotate by yaw + direction.set( + direction.x * yawCos - direction.z * yawSin, + direction.y, + direction.x * yawSin + direction.z * yawCos + ); + // Adjust for current speed + // We transform speed to blocks per second: x->2^(x/300) + direction.mul(Math.pow(2, speed / 300d)); + // Adjust for time passed + direction.mul(partialTicksPassed / 20); + // Actually move + camera.moveCamera(direction.x, direction.y, direction.z); + } + + @Override + public void increaseSpeed() { + speed = Math.min(MAX_SPEED, speed + 1); + } + + @Override + public void decreaseSpeed() { + speed = Math.max(MIN_SPEED, speed - 1); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java index 74d308b0..a841ea37 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.mixin; -import com.replaymod.replay.CameraEntity; +import com.replaymod.replay.camera.CameraEntity; import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.video.EntityRendererHandler; diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java index 8c5c75f6..5965ad48 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinGuiSpectator.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.mixin; -import com.replaymod.replay.CameraEntity; +import com.replaymod.replay.camera.CameraEntity; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiSpectator; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java index 87a54bf0..fe4a4c82 100644 --- a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinPlayerControllerMP.java @@ -1,6 +1,6 @@ package eu.crushedpixel.replaymod.mixin; -import com.replaymod.replay.CameraEntity; +import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.ReplayModReplay; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP;