mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 06:24:59 +01:00
Lerp entity steps
This commit is contained in:
parent
73f7259b6d
commit
26b7b5a73e
9 changed files with 105 additions and 6 deletions
|
@ -35,7 +35,12 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveEntityPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.geysermc.geyser.api.entity.type.GeyserEntity;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
|
||||
|
@ -55,7 +60,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEnt
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
@ -218,11 +227,15 @@ public class Entity implements GeyserEntity {
|
|||
valid = false;
|
||||
}
|
||||
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
protected void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(relX, relY, relZ, yaw, pitch, getHeadYaw(), isOnGround);
|
||||
}
|
||||
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
moveRelativeRaw(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
protected void moveRelativeRaw(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
|
||||
|
||||
MoveEntityDeltaPacket moveEntityPacket = new MoveEntityDeltaPacket();
|
||||
|
@ -266,6 +279,10 @@ public class Entity implements GeyserEntity {
|
|||
}
|
||||
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
moveAbsoluteRaw(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
protected void moveAbsoluteRaw(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
setPosition(position);
|
||||
// Setters are intentional so it can be overridden in places like AbstractArrowEntity
|
||||
setYaw(yaw);
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
|
|||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
|
@ -69,7 +70,7 @@ import java.util.*;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class LivingEntity extends Entity {
|
||||
public class LivingEntity extends Entity implements Tickable {
|
||||
|
||||
protected ItemData helmet = ItemData.AIR;
|
||||
protected ItemData chestplate = ItemData.AIR;
|
||||
|
@ -102,6 +103,11 @@ public class LivingEntity extends Entity {
|
|||
@Setter(AccessLevel.NONE)
|
||||
private float attributeScale;
|
||||
|
||||
private float lerpX;
|
||||
private float lerpY;
|
||||
private float lerpZ;
|
||||
private int lerpSteps;
|
||||
|
||||
public LivingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
@ -277,6 +283,40 @@ public class LivingEntity extends Entity {
|
|||
return new AttributeData(GeyserAttributeType.HEALTH.getBedrockIdentifier(), 0f, this.maxHealth, (float) Math.ceil(this.health), this.maxHealth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
lerpSteps();
|
||||
}
|
||||
|
||||
protected void lerpSteps() {
|
||||
if (this.lerpSteps > 0) {
|
||||
float time = 1.0f / this.lerpSteps;
|
||||
float lerpXTotal = lerp(time, this.position.getX(), this.lerpX);
|
||||
float lerpYTotal = lerp(time, this.position.getY(), this.lerpY);
|
||||
float lerpZTotal = lerp(time, this.position.getZ(), this.lerpZ);
|
||||
setPosition(Vector3f.from(lerpXTotal, lerpYTotal, lerpZTotal));
|
||||
|
||||
MoveEntityDeltaPacket moveEntityPacket = new MoveEntityDeltaPacket();
|
||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||
moveEntityPacket.setX(position.getX());
|
||||
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X);
|
||||
moveEntityPacket.setY(position.getY());
|
||||
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Y);
|
||||
moveEntityPacket.setZ(position.getZ());
|
||||
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Z);
|
||||
if (this.onGround) {
|
||||
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND);
|
||||
}
|
||||
session.sendUpstreamPacket(moveEntityPacket);
|
||||
|
||||
this.lerpSteps--;
|
||||
}
|
||||
}
|
||||
|
||||
private static float lerp(float time, float a, float b) {
|
||||
return a + time * (b - a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return this.valid && health > 0f;
|
||||
|
@ -304,7 +344,27 @@ public class LivingEntity extends Entity {
|
|||
clientVehicle.getVehicleComponent().moveRelative(relX, relY, relZ);
|
||||
}
|
||||
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
// Logic analogous to Java Edition 1.21.
|
||||
if (relX != 0 || relY != 0 || relZ != 0) {
|
||||
this.lerpX = this.position.getX() + (float) relX;
|
||||
this.lerpY = this.position.getY() + (float) relY;
|
||||
this.lerpZ = this.position.getZ() + (float) relZ;
|
||||
this.lerpSteps = 3;
|
||||
}
|
||||
|
||||
// Rotation lerping does not seem to be an issue with Bedrock Edition as of 1.21.22
|
||||
|
||||
super.moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
this.lerpX = position.getX();
|
||||
this.lerpY = position.getY();
|
||||
this.lerpZ = position.getZ();
|
||||
this.lerpSteps = 3;
|
||||
|
||||
super.moveAbsolute(this.position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,6 +101,8 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle {
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
PlayerEntity player = getPlayerPassenger();
|
||||
if (player == null) {
|
||||
return;
|
||||
|
|
|
@ -101,6 +101,8 @@ public class SnifferEntity extends AnimalEntity implements Tickable {
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
// The java client renders digging particles on its own, but bedrock does not
|
||||
if (digTicks > 0 && --digTicks < DIG_START && digTicks % 5 == 0) {
|
||||
Vector3f rot = Vector3f.createDirectionDeg(0, -getYaw()).mul(2.25f);
|
||||
|
|
|
@ -148,6 +148,8 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
PlayerEntity player = getPlayerPassenger();
|
||||
if (player == null) {
|
||||
return;
|
||||
|
|
|
@ -162,6 +162,8 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
effectTick();
|
||||
if (!getFlag(EntityFlag.NO_AI) && isAlive()) {
|
||||
pushSegment();
|
||||
|
|
|
@ -75,6 +75,18 @@ public class ShulkerEntity extends GolemEntity {
|
|||
}
|
||||
}
|
||||
|
||||
// As of 1.21, Java Edition does not lerp shulker steps.
|
||||
|
||||
@Override
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
moveRelativeRaw(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
moveAbsoluteRaw(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnemy() {
|
||||
return true;
|
||||
|
|
|
@ -73,6 +73,8 @@ public class WardenEntity extends MonsterEntity implements Tickable {
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (++tickCount % heartBeatDelay == 0 && !silent) {
|
||||
// We have to do these calculations because they're clientside on Java Edition but we mute entities
|
||||
// to prevent hearing their step sounds
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.java.entity;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityMotionPacket;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
|
@ -34,6 +33,7 @@ import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityMotionPacket;
|
||||
|
||||
@Translator(packet = ClientboundSetEntityMotionPacket.class)
|
||||
public class JavaSetEntityMotionTranslator extends PacketTranslator<ClientboundSetEntityMotionPacket> {
|
||||
|
|
Loading…
Reference in a new issue