Added Spectator Keyframes and handles them properly in both normal and rendered Replay Paths
This commit is contained in:
@@ -214,7 +214,9 @@ public class GuiReplayOverlay extends Gui {
|
||||
if(cam != null) {
|
||||
Position position = new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch,
|
||||
cam.rotationYaw % 360, ReplayHandler.getCameraTilt());
|
||||
ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), position));
|
||||
|
||||
if(ReplayHandler.isCamera()) ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), position));
|
||||
else ReplayHandler.addKeyframe(new PositionKeyframe(ReplayHandler.getRealTimelineCursor(), cam.getEntityId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.holders;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
@@ -8,6 +9,10 @@ public class Position {
|
||||
private double x, y, z;
|
||||
private float pitch, yaw, roll;
|
||||
|
||||
public Position(int entityID) {
|
||||
this(Minecraft.getMinecraft().theWorld.getEntityByID(entityID));
|
||||
}
|
||||
|
||||
public Position(Entity e) {
|
||||
this.x = e.posX;
|
||||
this.y = e.posY;
|
||||
|
||||
@@ -5,10 +5,11 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
public class PositionKeyframe extends Keyframe {
|
||||
|
||||
private Position position;
|
||||
private Integer spectatedEntityID = null;
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
return new PositionKeyframe(this.getRealTimestamp(), this.getPosition());
|
||||
return new PositionKeyframe(this.getRealTimestamp(), this.getPosition(), this.getSpectatedEntityID());
|
||||
}
|
||||
|
||||
public PositionKeyframe(int realTime, Position position) {
|
||||
@@ -16,12 +17,24 @@ public class PositionKeyframe extends Keyframe {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public PositionKeyframe(int realTime, Position position, int spectatedEntityID) {
|
||||
super(realTime);
|
||||
this.position = position;
|
||||
this.spectatedEntityID = spectatedEntityID;
|
||||
}
|
||||
|
||||
public PositionKeyframe(int realTime, int spectatedEntityID) {
|
||||
this(realTime, new Position(spectatedEntityID), spectatedEntityID);
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(Position position) { this.position = position; }
|
||||
|
||||
public Integer getSpectatedEntityID() { return spectatedEntityID; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o2) {
|
||||
if(o2 == null) return false;
|
||||
@@ -35,6 +48,7 @@ public class PositionKeyframe extends Keyframe {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(getPosition())
|
||||
.append(getRealTimestamp())
|
||||
.append(getSpectatedEntityID())
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,55 @@ public class SpectatorRenderer {
|
||||
return (EntityPlayer)current;
|
||||
}
|
||||
|
||||
public void renderSpectatorHand(EntityPlayer entityPlayer, float partialTicks, int renderPass) {
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_PROJECTION);
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
float f1 = 0.07F;
|
||||
|
||||
if(this.mc.gameSettings.anaglyph) {
|
||||
GlStateManager.translate((float)(-(renderPass * 2 - 1)) * f1, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
Project.gluPerspective(mc.entityRenderer.getFOVModifier(partialTicks, false),
|
||||
(float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, mc.entityRenderer.farPlaneDistance * 2.0F);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
if(this.mc.gameSettings.anaglyph) {
|
||||
GlStateManager.translate((float)(renderPass * 2 - 1) * 0.1F, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
mc.entityRenderer.hurtCameraEffect(partialTicks);
|
||||
|
||||
if(this.mc.gameSettings.viewBobbing) {
|
||||
mc.entityRenderer.setupViewBobbing(partialTicks);
|
||||
}
|
||||
|
||||
boolean sleeping = this.mc.getRenderViewEntity() instanceof EntityLivingBase &&
|
||||
((EntityLivingBase)this.mc.getRenderViewEntity()).isPlayerSleeping();
|
||||
|
||||
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping && !this.mc.gameSettings.hideGUI) {
|
||||
mc.entityRenderer.enableLightmap();
|
||||
renderItemInFirstPerson(partialTicks);
|
||||
mc.entityRenderer.disableLightmap();
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping) {
|
||||
renderOverlays(partialTicks, entityPlayer);
|
||||
mc.entityRenderer.hurtCameraEffect(partialTicks);
|
||||
}
|
||||
|
||||
if(this.mc.gameSettings.viewBobbing) {
|
||||
mc.entityRenderer.setupViewBobbing(partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void renderHandEvent(RenderHandEvent event) {
|
||||
if(!ReplayHandler.isInReplay() || ReplayHandler.isCamera()) {
|
||||
@@ -45,54 +94,8 @@ public class SpectatorRenderer {
|
||||
EntityPlayer entityPlayer = getSpectatedPlayer();
|
||||
if(entityPlayer == null) return;
|
||||
|
||||
renderSpectatorHand(entityPlayer, event.partialTicks, event.renderPass);
|
||||
event.setCanceled(true);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_PROJECTION);
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
float f1 = 0.07F;
|
||||
|
||||
if(this.mc.gameSettings.anaglyph) {
|
||||
GlStateManager.translate((float)(-(event.renderPass * 2 - 1)) * f1, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
Project.gluPerspective(mc.entityRenderer.getFOVModifier(event.partialTicks, false),
|
||||
(float)this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, mc.entityRenderer.farPlaneDistance * 2.0F);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
if(this.mc.gameSettings.anaglyph) {
|
||||
GlStateManager.translate((float)(event.renderPass * 2 - 1) * 0.1F, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
mc.entityRenderer.hurtCameraEffect(event.partialTicks);
|
||||
|
||||
if(this.mc.gameSettings.viewBobbing) {
|
||||
mc.entityRenderer.setupViewBobbing(event.partialTicks);
|
||||
}
|
||||
|
||||
boolean sleeping = this.mc.getRenderViewEntity() instanceof EntityLivingBase &&
|
||||
((EntityLivingBase)this.mc.getRenderViewEntity()).isPlayerSleeping();
|
||||
|
||||
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping && !this.mc.gameSettings.hideGUI) {
|
||||
mc.entityRenderer.enableLightmap();
|
||||
renderItemInFirstPerson(event.partialTicks);
|
||||
mc.entityRenderer.disableLightmap();
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
if(this.mc.gameSettings.thirdPersonView == 0 && !sleeping) {
|
||||
renderOverlays(event.partialTicks, entityPlayer);
|
||||
mc.entityRenderer.hurtCameraEffect(event.partialTicks);
|
||||
}
|
||||
|
||||
if(this.mc.gameSettings.viewBobbing) {
|
||||
mc.entityRenderer.setupViewBobbing(event.partialTicks);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void renderItemInFirstPerson(float partialTicks) {
|
||||
|
||||
@@ -71,8 +71,13 @@ public class ReplayHandler {
|
||||
}
|
||||
|
||||
public static void spectateEntity(Entity e) {
|
||||
currentEntity = e;
|
||||
mc.setRenderViewEntity(currentEntity);
|
||||
if(e == null) {
|
||||
spectateCamera();
|
||||
}
|
||||
else {
|
||||
currentEntity = e;
|
||||
mc.setRenderViewEntity(currentEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public static void spectateCamera() {
|
||||
|
||||
@@ -221,6 +221,18 @@ public class ReplayProcess {
|
||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
|
||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime);
|
||||
|
||||
|
||||
boolean spectating = false;
|
||||
|
||||
//if it's between two spectator keyframes sharing the same entity, spectate this entity
|
||||
if(lastPos != null && nextPos != null) {
|
||||
if(lastPos.getSpectatedEntityID() != null && nextPos.getSpectatedEntityID() != null) {
|
||||
if(lastPos.getSpectatedEntityID().equals(nextPos.getSpectatedEntityID())) {
|
||||
spectating = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReplayHandler.setRealTimelineCursor(curRealReplayTime);
|
||||
|
||||
int lastPosStamp = 0;
|
||||
@@ -292,17 +304,27 @@ public class ReplayProcess {
|
||||
float splinePos = ((float) ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc) / (float) (posCount - 1);
|
||||
float timePos = ((float) ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1);
|
||||
|
||||
Position pos = null;
|
||||
if(posCount > 1) {
|
||||
if(!linear) {
|
||||
pos = motionSpline.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
if(!spectating) {
|
||||
ReplayHandler.spectateCamera();
|
||||
Position pos = null;
|
||||
if(posCount > 1) {
|
||||
if(!linear) {
|
||||
pos = motionSpline.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
} else {
|
||||
pos = motionLinear.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
}
|
||||
} else {
|
||||
pos = motionLinear.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
if(posCount == 1) {
|
||||
pos = ReplayHandler.getFirstPositionKeyframe().getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
if(pos != null) {
|
||||
ReplayHandler.setCameraTilt(pos.getRoll());
|
||||
ReplayHandler.getCameraEntity().movePath(pos);
|
||||
}
|
||||
} else {
|
||||
if(posCount == 1) {
|
||||
pos = ReplayHandler.getFirstPositionKeyframe().getPosition();
|
||||
}
|
||||
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getSpectatedEntityID()));
|
||||
}
|
||||
|
||||
Integer curTimestamp = null;
|
||||
@@ -310,11 +332,6 @@ public class ReplayProcess {
|
||||
curTimestamp = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
|
||||
}
|
||||
|
||||
if(pos != null) {
|
||||
ReplayHandler.setCameraTilt(pos.getRoll());
|
||||
ReplayHandler.getCameraEntity().movePath(pos);
|
||||
}
|
||||
|
||||
if(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed);
|
||||
//if(curSpeed > 0)
|
||||
lastSpeed = curSpeed;
|
||||
|
||||
@@ -198,12 +198,13 @@ public class VideoRenderer {
|
||||
|
||||
Position pos;
|
||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(videoTime);
|
||||
PositionKeyframe nextPos = null;
|
||||
if (movement == null || lastPos == null) {
|
||||
// Stay at one position, no movement
|
||||
pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition();
|
||||
} else {
|
||||
// Position interpolation
|
||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(videoTime);
|
||||
nextPos = ReplayHandler.getNextPositionKeyframe(videoTime);
|
||||
|
||||
int lastPosStamp = lastPos.getRealTimestamp();
|
||||
int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp();
|
||||
@@ -215,13 +216,32 @@ public class VideoRenderer {
|
||||
float totalPct = (ReplayHandler.getKeyframeIndex(lastPos) + diffPct) / (posCount-1);
|
||||
pos = movement.getPoint(Math.max(0, Math.min(1, totalPct)));
|
||||
}
|
||||
ReplayHandler.setCameraTilt(pos.getRoll());
|
||||
ReplayHandler.getCameraEntity().movePath(pos);
|
||||
|
||||
// Make sure we're spectating the camera entity
|
||||
// We do not use .spectateCamera() as that method sets the position of the camera to the previous
|
||||
// entity, overriding our calculations
|
||||
ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity());
|
||||
boolean spectating = false;
|
||||
|
||||
//if it's between two spectator keyframes sharing the same entity, spectate this entity
|
||||
if(lastPos != null && nextPos != null) {
|
||||
if(lastPos.getSpectatedEntityID() != null && nextPos.getSpectatedEntityID() != null) {
|
||||
if(lastPos.getSpectatedEntityID().equals(nextPos.getSpectatedEntityID())) {
|
||||
spectating = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!spectating) {
|
||||
// Make sure we're spectating the camera entity
|
||||
// We do not use .spectateCamera() as that method sets the position of the camera to the previous
|
||||
// entity, overriding our calculations
|
||||
ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity());
|
||||
|
||||
if(pos != null) {
|
||||
ReplayHandler.setCameraTilt(pos.getRoll());
|
||||
ReplayHandler.getCameraEntity().movePath(pos);
|
||||
}
|
||||
} else {
|
||||
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getSpectatedEntityID()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateTime(Timer timer, int framesDone) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package eu.crushedpixel.replaymod.video.entity;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.EffectRenderer;
|
||||
import net.minecraft.client.renderer.*;
|
||||
@@ -7,6 +9,7 @@ import net.minecraft.client.renderer.culling.ClippingHelperImpl;
|
||||
import net.minecraft.client.renderer.culling.ICamera;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.EnumWorldBlockLayer;
|
||||
import net.minecraft.util.MathHelper;
|
||||
@@ -172,6 +175,9 @@ public abstract class CustomEntityRenderer {
|
||||
}
|
||||
|
||||
net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(renderglobal, partialTicks);
|
||||
|
||||
if(!ReplayHandler.isCamera() && ReplayHandler.getCurrentEntity() instanceof EntityPlayer)
|
||||
ReplayMod.spectatorRenderer.renderSpectatorHand((EntityPlayer)ReplayHandler.getCurrentEntity(), partialTicks, renderPass);
|
||||
}
|
||||
|
||||
protected void setupCameraTransform(float partialTicks) {
|
||||
|
||||
Reference in New Issue
Block a user