Add camera movement
This commit is contained in:
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.replaymod.replay;
|
package com.replaymod.replay;
|
||||||
|
|
||||||
import com.replaymod.core.utils.WrappedTimer;
|
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.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.settings.GameSettings;
|
import net.minecraft.client.settings.GameSettings;
|
||||||
@@ -64,7 +66,21 @@ public class InputReplayTimer extends WrappedTimer {
|
|||||||
|
|
||||||
int wheel = Mouse.getEventDWheel();
|
int wheel = Mouse.getEventDWheel();
|
||||||
if (wheel != 0) {
|
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) {
|
if (mc.currentScreen == null) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.replaymod.replay;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.replaymod.replay.camera.CameraEntity;
|
||||||
import com.replaymod.replay.events.ReplayCloseEvent;
|
import com.replaymod.replay.events.ReplayCloseEvent;
|
||||||
import com.replaymod.replay.events.ReplayOpenEvent;
|
import com.replaymod.replay.events.ReplayOpenEvent;
|
||||||
import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
|
import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
|
||||||
@@ -72,7 +73,7 @@ public class ReplayHandler {
|
|||||||
*/
|
*/
|
||||||
private AdvancedPosition targetCameraPosition;
|
private AdvancedPosition targetCameraPosition;
|
||||||
|
|
||||||
protected UUID spectating;
|
private UUID spectating;
|
||||||
|
|
||||||
public ReplayHandler(ReplayFile replayFile, boolean asyncMode) throws IOException {
|
public ReplayHandler(ReplayFile replayFile, boolean asyncMode) throws IOException {
|
||||||
Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread.");
|
Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread.");
|
||||||
@@ -212,7 +213,7 @@ public class ReplayHandler {
|
|||||||
|
|
||||||
if (mc.getRenderViewEntity() != e) {
|
if (mc.getRenderViewEntity() != e) {
|
||||||
mc.setRenderViewEntity(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;
|
return mc.thePlayer instanceof CameraEntity ? (CameraEntity) mc.thePlayer : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getSpectatedUUID() {
|
||||||
|
return spectating;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTargetPosition(AdvancedPosition pos) {
|
public void setTargetPosition(AdvancedPosition pos) {
|
||||||
targetCameraPosition = pos;
|
targetCameraPosition = pos;
|
||||||
}
|
}
|
||||||
@@ -247,7 +252,7 @@ public class ReplayHandler {
|
|||||||
public void moveCameraToTargetPosition() {
|
public void moveCameraToTargetPosition() {
|
||||||
CameraEntity cam = getCameraEntity();
|
CameraEntity cam = getCameraEntity();
|
||||||
if (cam != null && targetCameraPosition != null) {
|
if (cam != null && targetCameraPosition != null) {
|
||||||
cam.moveAbsolute(targetCameraPosition);
|
cam.setCameraPosRot(targetCameraPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.replaymod.replay;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.common.util.concurrent.ListenableFutureTask;
|
import com.google.common.util.concurrent.ListenableFutureTask;
|
||||||
|
import com.replaymod.replay.camera.CameraEntity;
|
||||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.holders.PacketData;
|
import eu.crushedpixel.replaymod.holders.PacketData;
|
||||||
import com.replaymod.core.utils.Restrictions;
|
import com.replaymod.core.utils.Restrictions;
|
||||||
@@ -425,7 +426,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CameraEntity cent = replayHandler.getCameraEntity();
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
}.call();
|
}.call();
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.replaymod.replay.camera;
|
||||||
|
|
||||||
|
public interface CameraController {
|
||||||
|
void update(float partialTicksPassed);
|
||||||
|
|
||||||
|
void increaseSpeed();
|
||||||
|
void decreaseSpeed();
|
||||||
|
}
|
||||||
217
src/main/java/com/replaymod/replay/camera/CameraEntity.java
Executable file
217
src/main/java/com/replaymod/replay/camera/CameraEntity.java
Executable file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.crushedpixel.replaymod.mixin;
|
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.renderer.SpectatorRenderer;
|
||||||
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
import eu.crushedpixel.replaymod.settings.RenderOptions;
|
||||||
import eu.crushedpixel.replaymod.video.EntityRendererHandler;
|
import eu.crushedpixel.replaymod.video.EntityRendererHandler;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.crushedpixel.replaymod.mixin;
|
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.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiSpectator;
|
import net.minecraft.client.gui.GuiSpectator;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.crushedpixel.replaymod.mixin;
|
package eu.crushedpixel.replaymod.mixin;
|
||||||
|
|
||||||
import com.replaymod.replay.CameraEntity;
|
import com.replaymod.replay.camera.CameraEntity;
|
||||||
import com.replaymod.replay.ReplayModReplay;
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.entity.EntityPlayerSP;
|
import net.minecraft.client.entity.EntityPlayerSP;
|
||||||
|
|||||||
Reference in New Issue
Block a user