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) {
|
if(cam != null) {
|
||||||
Position position = new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch,
|
Position position = new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch,
|
||||||
cam.rotationYaw % 360, ReplayHandler.getCameraTilt());
|
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;
|
package eu.crushedpixel.replaymod.holders;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
|
||||||
@@ -8,6 +9,10 @@ public class Position {
|
|||||||
private double x, y, z;
|
private double x, y, z;
|
||||||
private float pitch, yaw, roll;
|
private float pitch, yaw, roll;
|
||||||
|
|
||||||
|
public Position(int entityID) {
|
||||||
|
this(Minecraft.getMinecraft().theWorld.getEntityByID(entityID));
|
||||||
|
}
|
||||||
|
|
||||||
public Position(Entity e) {
|
public Position(Entity e) {
|
||||||
this.x = e.posX;
|
this.x = e.posX;
|
||||||
this.y = e.posY;
|
this.y = e.posY;
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
|||||||
public class PositionKeyframe extends Keyframe {
|
public class PositionKeyframe extends Keyframe {
|
||||||
|
|
||||||
private Position position;
|
private Position position;
|
||||||
|
private Integer spectatedEntityID = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() {
|
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) {
|
public PositionKeyframe(int realTime, Position position) {
|
||||||
@@ -16,12 +17,24 @@ public class PositionKeyframe extends Keyframe {
|
|||||||
this.position = position;
|
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() {
|
public Position getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Position position) { this.position = position; }
|
public void setPosition(Position position) { this.position = position; }
|
||||||
|
|
||||||
|
public Integer getSpectatedEntityID() { return spectatedEntityID; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o2) {
|
public boolean equals(Object o2) {
|
||||||
if(o2 == null) return false;
|
if(o2 == null) return false;
|
||||||
@@ -35,6 +48,7 @@ public class PositionKeyframe extends Keyframe {
|
|||||||
return new HashCodeBuilder(17, 37)
|
return new HashCodeBuilder(17, 37)
|
||||||
.append(getPosition())
|
.append(getPosition())
|
||||||
.append(getRealTimestamp())
|
.append(getRealTimestamp())
|
||||||
|
.append(getSpectatedEntityID())
|
||||||
.toHashCode();
|
.toHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,55 @@ public class SpectatorRenderer {
|
|||||||
return (EntityPlayer)current;
|
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
|
@SubscribeEvent
|
||||||
public void renderHandEvent(RenderHandEvent event) {
|
public void renderHandEvent(RenderHandEvent event) {
|
||||||
if(!ReplayHandler.isInReplay() || ReplayHandler.isCamera()) {
|
if(!ReplayHandler.isInReplay() || ReplayHandler.isCamera()) {
|
||||||
@@ -45,54 +94,8 @@ public class SpectatorRenderer {
|
|||||||
EntityPlayer entityPlayer = getSpectatedPlayer();
|
EntityPlayer entityPlayer = getSpectatedPlayer();
|
||||||
if(entityPlayer == null) return;
|
if(entityPlayer == null) return;
|
||||||
|
|
||||||
|
renderSpectatorHand(entityPlayer, event.partialTicks, event.renderPass);
|
||||||
event.setCanceled(true);
|
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) {
|
public void renderItemInFirstPerson(float partialTicks) {
|
||||||
|
|||||||
@@ -71,8 +71,13 @@ public class ReplayHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void spectateEntity(Entity e) {
|
public static void spectateEntity(Entity e) {
|
||||||
currentEntity = e;
|
if(e == null) {
|
||||||
mc.setRenderViewEntity(currentEntity);
|
spectateCamera();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentEntity = e;
|
||||||
|
mc.setRenderViewEntity(currentEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void spectateCamera() {
|
public static void spectateCamera() {
|
||||||
|
|||||||
@@ -221,6 +221,18 @@ public class ReplayProcess {
|
|||||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
|
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
|
||||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(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);
|
ReplayHandler.setRealTimelineCursor(curRealReplayTime);
|
||||||
|
|
||||||
int lastPosStamp = 0;
|
int lastPosStamp = 0;
|
||||||
@@ -292,17 +304,27 @@ public class ReplayProcess {
|
|||||||
float splinePos = ((float) ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc) / (float) (posCount - 1);
|
float splinePos = ((float) ReplayHandler.getKeyframeIndex(lastPos) + currentPosStepPerc) / (float) (posCount - 1);
|
||||||
float timePos = ((float) ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1);
|
float timePos = ((float) ReplayHandler.getKeyframeIndex(lastTime) + currentTimeStepPerc) / (float) (timeCount - 1);
|
||||||
|
|
||||||
Position pos = null;
|
if(!spectating) {
|
||||||
if(posCount > 1) {
|
ReplayHandler.spectateCamera();
|
||||||
if(!linear) {
|
Position pos = null;
|
||||||
pos = motionSpline.getPoint(Math.max(0, Math.min(1, splinePos)));
|
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 {
|
} 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 {
|
} else {
|
||||||
if(posCount == 1) {
|
ReplayHandler.spectateEntity(mc.theWorld.getEntityByID(lastPos.getSpectatedEntityID()));
|
||||||
pos = ReplayHandler.getFirstPositionKeyframe().getPosition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer curTimestamp = null;
|
Integer curTimestamp = null;
|
||||||
@@ -310,11 +332,6 @@ public class ReplayProcess {
|
|||||||
curTimestamp = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
|
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(!isVideoRecording()) ReplayMod.replaySender.setReplaySpeed(curSpeed);
|
||||||
//if(curSpeed > 0)
|
//if(curSpeed > 0)
|
||||||
lastSpeed = curSpeed;
|
lastSpeed = curSpeed;
|
||||||
|
|||||||
@@ -198,12 +198,13 @@ public class VideoRenderer {
|
|||||||
|
|
||||||
Position pos;
|
Position pos;
|
||||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(videoTime);
|
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(videoTime);
|
||||||
|
PositionKeyframe nextPos = null;
|
||||||
if (movement == null || lastPos == null) {
|
if (movement == null || lastPos == null) {
|
||||||
// Stay at one position, no movement
|
// Stay at one position, no movement
|
||||||
pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition();
|
pos = ReplayHandler.getNextPositionKeyframe(-1).getPosition();
|
||||||
} else {
|
} else {
|
||||||
// Position interpolation
|
// Position interpolation
|
||||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(videoTime);
|
nextPos = ReplayHandler.getNextPositionKeyframe(videoTime);
|
||||||
|
|
||||||
int lastPosStamp = lastPos.getRealTimestamp();
|
int lastPosStamp = lastPos.getRealTimestamp();
|
||||||
int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp();
|
int nextPosStamp = (nextPos == null ? lastPos : nextPos).getRealTimestamp();
|
||||||
@@ -215,13 +216,32 @@ public class VideoRenderer {
|
|||||||
float totalPct = (ReplayHandler.getKeyframeIndex(lastPos) + diffPct) / (posCount-1);
|
float totalPct = (ReplayHandler.getKeyframeIndex(lastPos) + diffPct) / (posCount-1);
|
||||||
pos = movement.getPoint(Math.max(0, Math.min(1, totalPct)));
|
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
|
boolean spectating = false;
|
||||||
// We do not use .spectateCamera() as that method sets the position of the camera to the previous
|
|
||||||
// entity, overriding our calculations
|
//if it's between two spectator keyframes sharing the same entity, spectate this entity
|
||||||
ReplayHandler.spectateEntity(ReplayHandler.getCameraEntity());
|
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) {
|
private void updateTime(Timer timer, int framesDone) {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package eu.crushedpixel.replaymod.video.entity;
|
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.Minecraft;
|
||||||
import net.minecraft.client.particle.EffectRenderer;
|
import net.minecraft.client.particle.EffectRenderer;
|
||||||
import net.minecraft.client.renderer.*;
|
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.culling.ICamera;
|
||||||
import net.minecraft.client.renderer.texture.TextureMap;
|
import net.minecraft.client.renderer.texture.TextureMap;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.util.AxisAlignedBB;
|
import net.minecraft.util.AxisAlignedBB;
|
||||||
import net.minecraft.util.EnumWorldBlockLayer;
|
import net.minecraft.util.EnumWorldBlockLayer;
|
||||||
import net.minecraft.util.MathHelper;
|
import net.minecraft.util.MathHelper;
|
||||||
@@ -172,6 +175,9 @@ public abstract class CustomEntityRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(renderglobal, partialTicks);
|
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) {
|
protected void setupCameraTransform(float partialTicks) {
|
||||||
|
|||||||
Reference in New Issue
Block a user