add camera system

This commit is contained in:
Sen 2025-08-06 19:07:15 +02:00
parent e0a031c5d0
commit a76c0c66e1
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
17 changed files with 464 additions and 207 deletions

View file

@ -0,0 +1,91 @@
package common.entity.item;
import common.entity.types.EntityWeatherEffect;
import common.util.ExtMath;
import common.world.World;
public class EntityCamera extends EntityWeatherEffect {
public static enum CameraType {
STATIC,
ROTATABLE,
MOVEABLE,
PLANE,
FREE;
}
public final double baseX;
public final double baseY;
public final double baseZ;
public final int radius;
public final float speed;
public final CameraType type;
public final boolean fixed;
public EntityCamera(World worldIn, double x, double y, double z, float yaw, float pitch, int radius, float speed, CameraType type, boolean fixed) {
super(worldIn);
this.setSize(0.1F, 0.1F);
this.setPosition(x, y, z);
this.setRotation(type == CameraType.PLANE || type == CameraType.MOVEABLE ? 0.0f : yaw, pitch);
this.noClip = true;
this.baseX = this.prevX = x;
this.baseY = this.prevY = y;
this.baseZ = this.prevZ = z;
this.radius = radius;
this.speed = speed;
this.type = type;
this.fixed = fixed;
}
public void onUpdate() {
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
this.prevPitch = this.rotPitch;
this.prevYaw = this.rotYaw;
this.setPositionClamped(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
// this.motionX = this.motionY = this.motionZ = 0.0D;
}
public float getEyeHeight() {
return 0.0F;
}
public void setMovement(float strafe, float forward, boolean jumping, boolean sneaking) {
if(this.type != CameraType.MOVEABLE && this.type != CameraType.PLANE && this.type != CameraType.FREE)
return;
double x = strafe > 0.5f ? 1.0f : (strafe < -0.5f ? -1.0 : 0.0);
double y = this.type == CameraType.PLANE ? 0.0 : (jumping ? (sneaking ? 0.0 : 1.0) : (sneaking ? -1.0 : 0.0));
double z = forward > 0.5f ? 1.0f : (forward < -0.5f ? -1.0 : 0.0);
if(this.type == CameraType.FREE) {
this.motionX = this.motionZ = 0.0;
this.moveFlying((float)x, (float)z, 1.0f);
this.setVelocity(this.motionX * this.speed, y * this.speed, this.motionZ * this.speed);
}
else {
this.setVelocity(x * (double)this.speed, y * (double)this.speed, z * (double)this.speed);
}
}
public void setPositionClamped(double x, double y, double z)
{
if(this.type == CameraType.MOVEABLE || this.type == CameraType.PLANE || this.type == CameraType.FREE)
this.setPosition(ExtMath.clampd(x, this.baseX - (double)this.radius, this.baseX + (double)this.radius),
this.type == CameraType.PLANE ? this.baseY : ExtMath.clampd(y, this.baseY - (double)this.radius, this.baseY + (double)this.radius),
ExtMath.clampd(z, this.baseZ - (double)this.radius, this.baseZ + (double)this.radius));
}
public void setAnglesClamped(float yaw, float pitch)
{
if(this.type == CameraType.ROTATABLE || this.type == CameraType.FREE)
this.setAngles(yaw, pitch);
}
public void setRotationClamped(float yaw, float pitch)
{
if(this.type == CameraType.ROTATABLE || this.type == CameraType.FREE)
this.setRotation(yaw, pitch);
}
}

View file

@ -91,7 +91,7 @@ public abstract class EntityHoveringNPC extends EntityNPC
// return 1.0F;
// }
public void onUpdateWalkingPlayer()
public void syncMovement()
{
boolean flag = this.isHovering();
@ -109,12 +109,12 @@ public abstract class EntityHoveringNPC extends EntityNPC
this.serverHoverState = flag;
}
super.onUpdateWalkingPlayer();
super.syncMovement();
}
public void onLivingUpdate()
{
if(this.client != null) {
if(this.client != null && this.client.isRenderViewEntity(this)) {
if(this.client.isJumping() && this.client.isSprinting() && this.client.getMoveForward() == 0.0f && this.client.getMoveStrafe() == 0.0f)
this.setHovering(true);
if(this.isFlying() || (!this.client.isJumping() && this.client.isSneaking() && this.onGround))

View file

@ -1557,16 +1557,26 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
{
// super.onUpdate();
this.updatePlayer();
if (this.isRiding())
{
this.client.addToSendQueue(new CPacketPlayerLook(this.rotYaw, this.rotPitch, this.onGround));
this.client.addToSendQueue(new CPacketInput(this.moveStrafe, this.moveForward, this.client.isJumping(), this.client.isSneaking()));
}
else
{
this.onUpdateWalkingPlayer();
}
if(this.client.isRenderViewEntity(this)) {
if (this.isRiding())
{
this.client.addToSendQueue(new CPacketPlayerLook(this.rotYaw, this.rotPitch, this.onGround));
this.client.addToSendQueue(new CPacketInput(this.moveStrafe, this.moveForward, this.client.isJumping(), this.client.isSneaking(), false));
}
else
{
this.syncMovement();
}
}
else if (this.vehicle == null)
{
this.client.addToSendQueue(new CPacketPlayer(this.onGround));
}
else
{
this.client.addToSendQueue(new CPacketPlayerPosLook(this.motionX, -99999999.0D, this.motionZ, this.rotYaw, this.rotPitch, this.onGround));
}
}
return;
}
@ -1904,7 +1914,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
*/
public boolean isSneaking()
{
return this.client != null ? this.client.isSneaking() : super.isSneaking();
return this.client != null && this.client.isRenderViewEntity(this) ? this.client.isSneaking() : super.isSneaking();
}
public void updateEntityActionState()
@ -1917,15 +1927,23 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
this.headYaw = this.rotYaw;
// super.updateEntityActionState();
if (this.client != null && this.client.isRenderViewEntity(this))
if (this.client != null)
{
this.moveStrafe = this.client.getMoveStrafe();
this.moveForward = this.client.getMoveForward();
this.jumping = this.client.isJumping();
this.prevRenderArmYaw = this.renderArmYaw;
this.prevRenderArmPitch = this.renderArmPitch;
this.renderArmPitch = (float)((double)this.renderArmPitch + (double)(this.rotPitch - this.renderArmPitch) * 0.5D);
this.renderArmYaw = (float)((double)this.renderArmYaw + (double)(this.rotYaw - this.renderArmYaw) * 0.5D);
if(this.client.isRenderViewEntity(this)) {
this.moveStrafe = this.client.getMoveStrafe();
this.moveForward = this.client.getMoveForward();
this.jumping = this.client.isJumping();
this.prevRenderArmYaw = this.renderArmYaw;
this.prevRenderArmPitch = this.renderArmPitch;
this.renderArmPitch = (float)((double)this.renderArmPitch + (double)(this.rotPitch - this.renderArmPitch) * 0.5D);
this.renderArmYaw = (float)((double)this.renderArmYaw + (double)(this.rotYaw - this.renderArmYaw) * 0.5D);
}
else {
this.moveStrafe = 0.0f;
this.moveForward = 0.0f;
this.jumping = false;
this.setSprinting(false);
}
}
}
@ -2001,13 +2019,14 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
// --this.portalTimer;
// }
boolean flag = this.client.isJumping();
boolean flag1 = this.client.isSneaking();
boolean jump = this.client.isJumping();
boolean sneak = this.client.isSneaking();
float f = 0.8F;
boolean flag2 = this.client.getMoveForward() >= f;
boolean moving = this.client.getMoveForward() >= f;
this.client.updatePlayerMoveState();
boolean current = this.client.isRenderViewEntity(this);
if (this.isUsingItem() && !this.isRiding())
if (current && this.isUsingItem() && !this.isRiding())
{
this.client.setMoveStrafe(this.client.getMoveStrafe() * 0.2F);
this.client.setMoveForward(this.client.getMoveForward() * 0.2F);
@ -2020,7 +2039,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
this.pushOutOfBlocks(this.posX + (double)this.width * 0.35D, this.getEntityBoundingBox().minY + 0.5D, this.posZ + (double)this.width * 0.35D);
boolean canSprint = true; // (float)this.getFoodStats().getFoodLevel() > 6.0F || this.allowFlying;
if (this.onGround && !flag1 && !flag2 && this.client.getMoveForward() >= f && !this.isSprinting() && canSprint && !this.isUsingItem() && !this.hasEffect(Effect.BLINDNESS))
if (current && this.onGround && !sneak && !moving && this.client.getMoveForward() >= f && !this.isSprinting() && canSprint && !this.isUsingItem() && !this.hasEffect(Effect.BLINDNESS))
{
if (this.sprintToggleTimer <= 0 && !this.client.isSprinting())
{
@ -2032,12 +2051,12 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
}
}
if (!this.isSprinting() && this.client.getMoveForward() >= f && canSprint && !this.isUsingItem() && !this.hasEffect(Effect.BLINDNESS) && this.client.isSprinting())
if (current && !this.isSprinting() && this.client.getMoveForward() >= f && canSprint && !this.isUsingItem() && !this.hasEffect(Effect.BLINDNESS) && this.client.isSprinting())
{
this.setSprinting(true);
}
if (this.isSprinting() && (this.client.getMoveForward() < f || this.collidedHorizontally || !canSprint))
if (current && this.isSprinting() && (this.client.getMoveForward() < f || this.collidedHorizontally || !canSprint))
{
this.setSprinting(false);
}
@ -2052,7 +2071,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
this.client.addToSendQueue(new CPacketAction(CPacketAction.Action.START_FLYING));
}
}
else if (!flag && this.client.isJumping())
else if (current && !jump && this.client.isJumping())
{
if (this.flyToggleTimer == 0)
{
@ -2072,7 +2091,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
}
// this.firstEffectUpdate = false;
if (this.isFlying() && this.client.isRenderViewEntity(this))
if (current && this.isFlying())
{
if (this.client.isSneaking())
{
@ -2087,7 +2106,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
}
}
if (this.isRidingHorse())
if (current && this.isRidingHorse())
{
if (this.horseJumpPowerCounter < 0)
{
@ -2099,17 +2118,17 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
}
}
if (flag && !this.client.isJumping())
if (jump && !this.client.isJumping())
{
this.horseJumpPowerCounter = -10;
this.sendHorseJump();
}
else if (!flag && this.client.isJumping())
else if (!jump && this.client.isJumping())
{
this.horseJumpPowerCounter = 0;
this.horseJumpPower = 0.0F;
}
else if (flag)
else if (jump)
{
++this.horseJumpPowerCounter;
@ -2282,7 +2301,7 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
/**
* called every tick when the player is on foot. Performs all the things that normally happen during movement.
*/
public void onUpdateWalkingPlayer()
public void syncMovement()
{
boolean flag = this.isSprinting();
@ -2316,56 +2335,53 @@ public abstract class EntityNPC extends EntityLiving implements IInventory
this.serverSneakState = flag1;
}
if (this.client.isRenderViewEntity(this))
{
double d0 = this.posX - this.lastReportedPosX;
double d1 = this.getEntityBoundingBox().minY - this.lastReportedPosY;
double d2 = this.posZ - this.lastReportedPosZ;
double d3 = (double)(this.rotYaw - this.lastReportedYaw);
double d4 = (double)(this.rotPitch - this.lastReportedPitch);
boolean flag2 = d0 * d0 + d1 * d1 + d2 * d2 > 9.0E-4D || this.positionUpdateTicks >= 20;
boolean flag3 = d3 != 0.0D || d4 != 0.0D;
double d0 = this.posX - this.lastReportedPosX;
double d1 = this.getEntityBoundingBox().minY - this.lastReportedPosY;
double d2 = this.posZ - this.lastReportedPosZ;
double d3 = (double)(this.rotYaw - this.lastReportedYaw);
double d4 = (double)(this.rotPitch - this.lastReportedPitch);
boolean flag2 = d0 * d0 + d1 * d1 + d2 * d2 > 9.0E-4D || this.positionUpdateTicks >= 20;
boolean flag3 = d3 != 0.0D || d4 != 0.0D;
if (this.vehicle == null)
if (this.vehicle == null)
{
if (flag2 && flag3)
{
if (flag2 && flag3)
{
this.client.addToSendQueue(new CPacketPlayerPosLook(this.posX, this.getEntityBoundingBox().minY, this.posZ, this.rotYaw, this.rotPitch, this.onGround));
}
else if (flag2)
{
this.client.addToSendQueue(new CPacketPlayerPosition(this.posX, this.getEntityBoundingBox().minY, this.posZ, this.onGround));
}
else if (flag3)
{
this.client.addToSendQueue(new CPacketPlayerLook(this.rotYaw, this.rotPitch, this.onGround));
}
else
{
this.client.addToSendQueue(new CPacketPlayer(this.onGround));
}
this.client.addToSendQueue(new CPacketPlayerPosLook(this.posX, this.getEntityBoundingBox().minY, this.posZ, this.rotYaw, this.rotPitch, this.onGround));
}
else if (flag2)
{
this.client.addToSendQueue(new CPacketPlayerPosition(this.posX, this.getEntityBoundingBox().minY, this.posZ, this.onGround));
}
else if (flag3)
{
this.client.addToSendQueue(new CPacketPlayerLook(this.rotYaw, this.rotPitch, this.onGround));
}
else
{
this.client.addToSendQueue(new CPacketPlayerPosLook(this.motionX, -99999999.0D, this.motionZ, this.rotYaw, this.rotPitch, this.onGround));
flag2 = false;
this.client.addToSendQueue(new CPacketPlayer(this.onGround));
}
}
else
{
this.client.addToSendQueue(new CPacketPlayerPosLook(this.motionX, -99999999.0D, this.motionZ, this.rotYaw, this.rotPitch, this.onGround));
flag2 = false;
}
++this.positionUpdateTicks;
++this.positionUpdateTicks;
if (flag2)
{
this.lastReportedPosX = this.posX;
this.lastReportedPosY = this.getEntityBoundingBox().minY;
this.lastReportedPosZ = this.posZ;
this.positionUpdateTicks = 0;
}
if (flag2)
{
this.lastReportedPosX = this.posX;
this.lastReportedPosY = this.getEntityBoundingBox().minY;
this.lastReportedPosZ = this.posZ;
this.positionUpdateTicks = 0;
}
if (flag3)
{
this.lastReportedYaw = this.rotYaw;
this.lastReportedPitch = this.rotPitch;
}
if (flag3)
{
this.lastReportedYaw = this.rotYaw;
this.lastReportedPitch = this.rotPitch;
}
}

View file

@ -12,17 +12,19 @@ public class CPacketInput implements Packet<IPlayer>
private float forwardSpeed;
private boolean jumping;
private boolean sneaking;
private boolean camera;
public CPacketInput()
{
}
public CPacketInput(float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking)
public CPacketInput(float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking, boolean camera)
{
this.strafeSpeed = strafeSpeed;
this.forwardSpeed = forwardSpeed;
this.jumping = jumping;
this.sneaking = sneaking;
this.camera = camera;
}
public void readPacketData(PacketBuffer buf) throws IOException
@ -32,6 +34,7 @@ public class CPacketInput implements Packet<IPlayer>
byte b0 = buf.readByte();
this.jumping = (b0 & 1) > 0;
this.sneaking = (b0 & 2) > 0;
this.camera = (b0 & 4) > 0;
}
public void writePacketData(PacketBuffer buf) throws IOException
@ -50,6 +53,11 @@ public class CPacketInput implements Packet<IPlayer>
b0 = (byte)(b0 | 2);
}
if (this.camera)
{
b0 = (byte)(b0 | 4);
}
buf.writeByte(b0);
}
@ -77,4 +85,9 @@ public class CPacketInput implements Packet<IPlayer>
{
return this.sneaking;
}
public boolean isCamera()
{
return this.camera;
}
}

View file

@ -14,6 +14,7 @@ public class CPacketPlayer implements Packet<IPlayer>
protected float yaw;
protected float pitch;
protected boolean onGround;
protected boolean camera;
protected boolean moving;
protected boolean rotating;
@ -33,12 +34,14 @@ public class CPacketPlayer implements Packet<IPlayer>
public void readPacketData(PacketBuffer buf) throws IOException
{
this.onGround = buf.readUnsignedByte() != 0;
byte flags = buf.readByte();
this.onGround = (flags & 1) != 0;
this.camera = (flags & 2) != 0;
}
public void writePacketData(PacketBuffer buf) throws IOException
{
buf.writeByte(this.onGround ? 1 : 0);
buf.writeByte((this.onGround ? 1 : 0) | (this.camera ? 2 : 0));
}
public double getPositionX()
@ -85,4 +88,9 @@ public class CPacketPlayer implements Packet<IPlayer>
{
this.moving = isMoving;
}
public boolean isCamera()
{
return this.camera;
}
}

View file

@ -23,6 +23,11 @@ public class CPacketPlayerPosLook extends CPacketPlayer
this.rotating = true;
this.moving = true;
}
public CPacketPlayerPosLook setCamera() {
this.camera = true;
return this;
}
public void readPacketData(PacketBuffer buf) throws IOException
{

View file

@ -2,42 +2,78 @@ package common.packet;
import java.io.IOException;
import common.entity.Entity;
import common.entity.item.EntityCamera;
import common.entity.item.EntityCamera.CameraType;
import common.network.IClientPlayer;
import common.network.Packet;
import common.network.PacketBuffer;
import common.world.World;
public class SPacketCamera implements Packet<IClientPlayer>
{
public int entityId;
public class SPacketCamera implements Packet<IClientPlayer> {
private int radius;
private float speed;
private double posX;
private double posY;
private double posZ;
private float yaw;
private float pitch;
private CameraType type;
private boolean fixed;
public SPacketCamera()
{
}
public SPacketCamera() {
}
public SPacketCamera(Entity entityIn)
{
this.entityId = entityIn.getId();
}
public void readPacketData(PacketBuffer buf) throws IOException
{
this.entityId = buf.readVarInt();
}
public void writePacketData(PacketBuffer buf) throws IOException
{
buf.writeVarInt(this.entityId);
}
public void processPacket(IClientPlayer handler)
{
handler.handleCamera(this);
}
public SPacketCamera(EntityCamera camera) {
if(camera == null)
return;
this.radius = camera.radius;
this.speed = camera.speed;
this.posX = camera.baseX;
this.posY = camera.baseY;
this.posZ = camera.baseZ;
this.yaw = camera.rotYaw;
this.pitch = camera.rotPitch;
this.type = camera.type;
this.fixed = camera.fixed;
}
public Entity getEntity(World worldIn)
{
return worldIn.getEntityByID(this.entityId);
}
public void readPacketData(PacketBuffer buf) throws IOException {
this.type = buf.readEnumOrNull(CameraType.class);
if(this.type != null) {
if(this.type == CameraType.MOVEABLE || this.type == CameraType.PLANE || this.type == CameraType.FREE) {
this.radius = buf.readVarInt();
this.speed = buf.readFloat();
}
this.posX = buf.readDouble();
this.posY = buf.readDouble();
this.posZ = buf.readDouble();
this.yaw = buf.readFloat();
this.pitch = buf.readFloat();
this.fixed = buf.readBoolean();
}
}
public void writePacketData(PacketBuffer buf) throws IOException {
buf.writeEnumOrNull(this.type);
if(this.type != null) {
if(this.type == CameraType.MOVEABLE || this.type == CameraType.PLANE || this.type == CameraType.FREE) {
buf.writeVarInt(this.radius);
buf.writeFloat(this.speed);
}
buf.writeDouble(this.posX);
buf.writeDouble(this.posY);
buf.writeDouble(this.posZ);
buf.writeFloat(this.yaw);
buf.writeFloat(this.pitch);
buf.writeBoolean(this.fixed);
}
}
public void processPacket(IClientPlayer handler) {
handler.handleCamera(this);
}
public EntityCamera getEntity(World world) {
return this.type == null ? null : new EntityCamera(world, this.posX, this.posY, this.posZ, this.yaw, this.pitch, this.radius, this.speed, this.type, this.fixed);
}
}