Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 00:00:41 +01:00
Rotation fixes (#2396)
* Should fix some rotation issues * Some more changes * Small changes * Fixed merge conflicts and updated other classes that changed * Added translation for the LookAt packet
Dieser Commit ist enthalten in:
Ursprung
4cb18ebf5b
Commit
2f54bf0e14
@ -70,8 +70,8 @@ public class AbstractArrowEntity extends Entity {
|
|||||||
super.setMotion(motion);
|
super.setMotion(motion);
|
||||||
|
|
||||||
double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ());
|
double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ());
|
||||||
this.yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ()));
|
setYaw((float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ())));
|
||||||
this.pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed));
|
setPitch((float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed)));
|
||||||
this.headYaw = yaw;
|
setHeadYaw(getYaw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@ public class BoatEntity extends Entity {
|
|||||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||||
// We don't include the rotation (y) as it causes the boat to appear sideways
|
// We don't include the rotation (y) as it causes the boat to appear sideways
|
||||||
setPosition(position.add(0d, this.definition.offset(), 0d));
|
setPosition(position.add(0d, this.definition.offset(), 0d));
|
||||||
this.yaw = yaw + 90;
|
setYaw(yaw + 90);
|
||||||
this.headYaw = yaw + 90;
|
setHeadYaw(yaw + 90);
|
||||||
setOnGround(isOnGround);
|
setOnGround(isOnGround);
|
||||||
|
|
||||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||||
|
@ -204,7 +204,7 @@ public class Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||||
moveRelative(relX, relY, relZ, yaw, pitch, this.headYaw, 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) {
|
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||||
@ -225,7 +225,7 @@ public class Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
|
public void moveAbsolute(Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
|
||||||
moveAbsolute(position, yaw, pitch, this.headYaw, isOnGround, teleported);
|
moveAbsolute(position, yaw, pitch, getHeadYaw(), isOnGround, teleported);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||||
@ -254,7 +254,8 @@ public class Entity {
|
|||||||
* @param isOnGround Whether the entity is currently on the ground.
|
* @param isOnGround Whether the entity is currently on the ground.
|
||||||
*/
|
*/
|
||||||
public void teleport(Vector3f position, float yaw, float pitch, boolean isOnGround) {
|
public void teleport(Vector3f position, float yaw, float pitch, boolean isOnGround) {
|
||||||
moveAbsolute(position, yaw, pitch, isOnGround, false);
|
// teleport will always set the headYaw to yaw
|
||||||
|
moveAbsolute(position, yaw, pitch, yaw, isOnGround, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,7 +263,7 @@ public class Entity {
|
|||||||
* @param headYaw The new head rotation of the entity.
|
* @param headYaw The new head rotation of the entity.
|
||||||
*/
|
*/
|
||||||
public void updateHeadLookRotation(float headYaw) {
|
public void updateHeadLookRotation(float headYaw) {
|
||||||
moveRelative(0, 0, 0, headYaw, pitch, this.headYaw, onGround);
|
moveRelative(0, 0, 0, getYaw(), getPitch(), headYaw, isOnGround());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,7 +276,7 @@ public class Entity {
|
|||||||
* @param isOnGround Whether the entity is currently on the ground.
|
* @param isOnGround Whether the entity is currently on the ground.
|
||||||
*/
|
*/
|
||||||
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||||
moveRelative(moveX, moveY, moveZ, this.yaw, pitch, yaw, isOnGround);
|
moveRelative(moveX, moveY, moveZ, yaw, pitch, getHeadYaw(), isOnGround);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,12 +437,12 @@ public class Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* x = Pitch, y = HeadYaw, z = Yaw
|
* x = Pitch, y = Yaw, z = HeadYaw
|
||||||
*
|
*
|
||||||
* @return the bedrock rotation
|
* @return the bedrock rotation
|
||||||
*/
|
*/
|
||||||
public Vector3f getBedrockRotation() {
|
public Vector3f getBedrockRotation() {
|
||||||
return Vector3f.from(pitch, headYaw, yaw);
|
return Vector3f.from(getPitch(), getYaw(), getHeadYaw());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,6 +72,6 @@ public class FireballEntity extends ThrowableEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
moveAbsoluteImmediate(tickMovement(position), yaw, pitch, headYaw, false, false);
|
moveAbsoluteImmediate(tickMovement(position), getYaw(), getPitch(), getHeadYaw(), false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||||||
float gravity = getGravity();
|
float gravity = getGravity();
|
||||||
motion = motion.down(gravity);
|
motion = motion.down(gravity);
|
||||||
|
|
||||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||||
|
|
||||||
float drag = getDrag();
|
float drag = getDrag();
|
||||||
motion = motion.mul(drag);
|
motion = motion.mul(drag);
|
||||||
@ -160,7 +160,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getGravity() {
|
protected float getGravity() {
|
||||||
if (!isInWater() && !onGround) {
|
if (!isInWater() && !isOnGround()) {
|
||||||
return 0.03f;
|
return 0.03f;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -76,10 +76,10 @@ public class ItemEntity extends ThrowableEntity {
|
|||||||
if (isInWater()) {
|
if (isInWater()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
|
if (!isOnGround() || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
|
||||||
float gravity = getGravity();
|
float gravity = getGravity();
|
||||||
motion = motion.down(gravity);
|
motion = motion.down(gravity);
|
||||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||||
float drag = getDrag();
|
float drag = getDrag();
|
||||||
motion = motion.mul(drag, 0.98f, drag);
|
motion = motion.mul(drag, 0.98f, drag);
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ public class ItemEntity extends ThrowableEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getGravity() {
|
protected float getGravity() {
|
||||||
if (getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater()) {
|
if (getFlag(EntityFlag.HAS_GRAVITY) && !isOnGround() && !isInWater()) {
|
||||||
// Gravity can change if the item is in water/lava, but
|
// Gravity can change if the item is in water/lava, but
|
||||||
// the server calculates the motion & position for us
|
// the server calculates the motion & position for us
|
||||||
return 0.04f;
|
return 0.04f;
|
||||||
@ -134,7 +134,7 @@ public class ItemEntity extends ThrowableEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getDrag() {
|
protected float getDrag() {
|
||||||
if (onGround) {
|
if (isOnGround()) {
|
||||||
Vector3i groundBlockPos = position.toInt().down(1);
|
Vector3i groundBlockPos = position.toInt().down(1);
|
||||||
int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos);
|
int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos);
|
||||||
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
|
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
|
||||||
|
@ -66,7 +66,7 @@ public class MinecartEntity extends Entity {
|
|||||||
@Override
|
@Override
|
||||||
public Vector3f getBedrockRotation() {
|
public Vector3f getBedrockRotation() {
|
||||||
// Note: minecart rotation on rails does not care about the actual rotation value
|
// Note: minecart rotation on rails does not care about the actual rotation value
|
||||||
return Vector3f.from(0, yaw, 0);
|
return Vector3f.from(0, getYaw(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,7 +56,7 @@ public class ThrowableEntity extends Entity implements Tickable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||||
float drag = getDrag();
|
float drag = getDrag();
|
||||||
float gravity = getGravity();
|
float gravity = getGravity();
|
||||||
motion = motion.mul(drag).down(gravity);
|
motion = motion.mul(drag).down(gravity);
|
||||||
@ -89,20 +89,20 @@ public class ThrowableEntity extends Entity implements Tickable {
|
|||||||
}
|
}
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
|
|
||||||
if (this.yaw != yaw) {
|
if (getYaw() != yaw) {
|
||||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
|
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
|
||||||
moveEntityDeltaPacket.setYaw(yaw);
|
moveEntityDeltaPacket.setYaw(yaw);
|
||||||
this.yaw = yaw;
|
setYaw(yaw);
|
||||||
}
|
}
|
||||||
if (this.pitch != pitch) {
|
if (getPitch() != pitch) {
|
||||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH);
|
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH);
|
||||||
moveEntityDeltaPacket.setPitch(pitch);
|
moveEntityDeltaPacket.setPitch(pitch);
|
||||||
this.pitch = pitch;
|
setPitch(pitch);
|
||||||
}
|
}
|
||||||
if (this.headYaw != headYaw) {
|
if (getHeadYaw() != headYaw) {
|
||||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
|
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
|
||||||
moveEntityDeltaPacket.setHeadYaw(headYaw);
|
moveEntityDeltaPacket.setHeadYaw(headYaw);
|
||||||
this.headYaw = headYaw;
|
setHeadYaw(headYaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!moveEntityDeltaPacket.getFlags().isEmpty()) {
|
if (!moveEntityDeltaPacket.getFlags().isEmpty()) {
|
||||||
|
@ -42,6 +42,7 @@ import org.geysermc.geyser.entity.EntityDefinitions;
|
|||||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.util.InteractionResult;
|
import org.geysermc.geyser.util.InteractionResult;
|
||||||
|
import org.geysermc.geyser.util.MathUtils;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -87,8 +88,6 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void spawnEntity() {
|
public void spawnEntity() {
|
||||||
this.pitch = yaw;
|
|
||||||
this.headYaw = yaw;
|
|
||||||
super.spawnEntity();
|
super.spawnEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,9 +204,9 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
// Indicate that rotation should be checked
|
// Indicate that rotation should be checked
|
||||||
setFlag(EntityFlag.BRIBED, true);
|
setFlag(EntityFlag.BRIBED, true);
|
||||||
|
|
||||||
int rotationX = getRotation(rotation.getPitch());
|
int rotationX = MathUtils.wrapDegreesToInt(rotation.getPitch());
|
||||||
int rotationY = getRotation(rotation.getYaw());
|
int rotationY = MathUtils.wrapDegreesToInt(rotation.getYaw());
|
||||||
int rotationZ = getRotation(rotation.getRoll());
|
int rotationZ = MathUtils.wrapDegreesToInt(rotation.getRoll());
|
||||||
// The top bit acts like binary and determines if each rotation goes above 100
|
// The top bit acts like binary and determines if each rotation goes above 100
|
||||||
// We don't do this for the negative values out of concerns of the number being too big
|
// We don't do this for the negative values out of concerns of the number being too big
|
||||||
int topBit = (Math.abs(rotationX) >= 100 ? 4 : 0) + (Math.abs(rotationY) >= 100 ? 2 : 0) + (Math.abs(rotationZ) >= 100 ? 1 : 0);
|
int topBit = (Math.abs(rotationX) >= 100 ? 4 : 0) + (Math.abs(rotationY) >= 100 ? 2 : 0) + (Math.abs(rotationZ) >= 100 ? 1 : 0);
|
||||||
@ -319,7 +318,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
// Create the second entity. It doesn't need to worry about the items, but it does need to worry about
|
// Create the second entity. It doesn't need to worry about the items, but it does need to worry about
|
||||||
// the metadata as it will hold the name tag.
|
// the metadata as it will hold the name tag.
|
||||||
secondEntity = new ArmorStandEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null,
|
secondEntity = new ArmorStandEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null,
|
||||||
EntityDefinitions.ARMOR_STAND, position, motion, yaw, pitch, headYaw);
|
EntityDefinitions.ARMOR_STAND, position, motion, getYaw(), getPitch(), getHeadYaw());
|
||||||
secondEntity.primaryEntity = false;
|
secondEntity.primaryEntity = false;
|
||||||
if (!this.positionRequiresOffset) {
|
if (!this.positionRequiresOffset) {
|
||||||
// Ensure the offset is applied for the 0 scale
|
// Ensure the offset is applied for the 0 scale
|
||||||
@ -375,17 +374,6 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getRotation(float rotation) {
|
|
||||||
rotation = rotation % 360f;
|
|
||||||
if (rotation < -180f) {
|
|
||||||
rotation += 360f;
|
|
||||||
} else if (rotation >= 180f) {
|
|
||||||
// 181 -> -179
|
|
||||||
rotation = -(180 - (rotation - 180));
|
|
||||||
}
|
|
||||||
return (int) rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this armor stand is not a marker, set its bounding box size and scale.
|
* If this armor stand is not a marker, set its bounding box size and scale.
|
||||||
*/
|
*/
|
||||||
@ -439,9 +427,14 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||||
moveEntityPacket.setPosition(position);
|
moveEntityPacket.setPosition(position);
|
||||||
moveEntityPacket.setRotation(Vector3f.from(yaw, yaw, yaw));
|
moveEntityPacket.setRotation(getBedrockRotation());
|
||||||
moveEntityPacket.setOnGround(onGround);
|
moveEntityPacket.setOnGround(isOnGround());
|
||||||
moveEntityPacket.setTeleported(false);
|
moveEntityPacket.setTeleported(false);
|
||||||
session.sendUpstreamPacket(moveEntityPacket);
|
session.sendUpstreamPacket(moveEntityPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3f getBedrockRotation() {
|
||||||
|
return Vector3f.from(getYaw(), getYaw(), getYaw());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ public class SquidEntity extends WaterEntity implements Tickable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector3f getBedrockRotation() {
|
public Vector3f getBedrockRotation() {
|
||||||
return Vector3f.from(pitch, yaw, yaw);
|
return Vector3f.from(getPitch(), getYaw(), getYaw());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -130,7 +130,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||||||
|
|
||||||
for (int i = 0; i < segmentHistory.length; i++) {
|
for (int i = 0; i < segmentHistory.length; i++) {
|
||||||
segmentHistory[i] = new Segment();
|
segmentHistory[i] = new Segment();
|
||||||
segmentHistory[i].yaw = headYaw;
|
segmentHistory[i].yaw = getHeadYaw();
|
||||||
segmentHistory[i].y = position.getY();
|
segmentHistory[i].y = position.getY();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||||||
* Updates the positions of the Ender Dragon's multiple bounding boxes
|
* Updates the positions of the Ender Dragon's multiple bounding boxes
|
||||||
*/
|
*/
|
||||||
private void updateBoundingBoxes() {
|
private void updateBoundingBoxes() {
|
||||||
Vector3f facingDir = Vector3f.createDirectionDeg(0, headYaw);
|
Vector3f facingDir = Vector3f.createDirectionDeg(0, getHeadYaw());
|
||||||
Segment baseSegment = getSegment(5);
|
Segment baseSegment = getSegment(5);
|
||||||
// Used to angle the head, neck, and tail when the dragon flies up/down
|
// Used to angle the head, neck, and tail when the dragon flies up/down
|
||||||
float pitch = (float) Math.toRadians(10 * (baseSegment.getY() - getSegment(10).getY()));
|
float pitch = (float) Math.toRadians(10 * (baseSegment.getY() - getSegment(10).getY()));
|
||||||
@ -187,7 +187,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||||||
neck.setPosition(facingDir.up(pitchY).mul(pitchXZ, 1, -pitchXZ).mul(5.5f).up(headDuck));
|
neck.setPosition(facingDir.up(pitchY).mul(pitchXZ, 1, -pitchXZ).mul(5.5f).up(headDuck));
|
||||||
body.setPosition(facingDir.mul(0.5f, 0f, -0.5f));
|
body.setPosition(facingDir.mul(0.5f, 0f, -0.5f));
|
||||||
|
|
||||||
Vector3f wingPos = Vector3f.createDirectionDeg(0, 90f - headYaw).mul(4.5f).up(2f);
|
Vector3f wingPos = Vector3f.createDirectionDeg(0, 90f - getHeadYaw()).mul(4.5f).up(2f);
|
||||||
rightWing.setPosition(wingPos);
|
rightWing.setPosition(wingPos);
|
||||||
leftWing.setPosition(wingPos.mul(-1, 1, -1)); // Mirror horizontally
|
leftWing.setPosition(wingPos.mul(-1, 1, -1)); // Mirror horizontally
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||||||
float distance = (i + 1) * 2f;
|
float distance = (i + 1) * 2f;
|
||||||
// Curls the tail when the dragon turns
|
// Curls the tail when the dragon turns
|
||||||
Segment targetSegment = getSegment(12 + 2 * i);
|
Segment targetSegment = getSegment(12 + 2 * i);
|
||||||
float angle = headYaw + targetSegment.yaw - baseSegment.yaw;
|
float angle = getHeadYaw() + targetSegment.yaw - baseSegment.yaw;
|
||||||
|
|
||||||
float tailYOffset = targetSegment.y - baseSegment.y - (distance + 1.5f) * pitchY + 1.5f;
|
float tailYOffset = targetSegment.y - baseSegment.y - (distance + 1.5f) * pitchY + 1.5f;
|
||||||
tail[i].setPosition(Vector3f.createDirectionDeg(0, angle).mul(distance).add(tailBase).mul(-pitchXZ, 1, pitchXZ).up(tailYOffset));
|
tail[i].setPosition(Vector3f.createDirectionDeg(0, angle).mul(distance).add(tailBase).mul(-pitchXZ, 1, pitchXZ).up(tailYOffset));
|
||||||
@ -306,7 +306,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||||||
*/
|
*/
|
||||||
private void pushSegment() {
|
private void pushSegment() {
|
||||||
latestSegment = (latestSegment + 1) % segmentHistory.length;
|
latestSegment = (latestSegment + 1) % segmentHistory.length;
|
||||||
segmentHistory[latestSegment].yaw = headYaw;
|
segmentHistory[latestSegment].yaw = getHeadYaw();
|
||||||
segmentHistory[latestSegment].y = position.getY();
|
segmentHistory[latestSegment].y = position.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ public class PlayerEntity extends LivingEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateHeadLookRotation(float headYaw) {
|
public void updateHeadLookRotation(float headYaw) {
|
||||||
moveRelative(0, 0, 0, yaw, pitch, headYaw, onGround);
|
moveRelative(0, 0, 0, getYaw(), getPitch(), headYaw, isOnGround());
|
||||||
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
||||||
movePlayerPacket.setRuntimeEntityId(geyserId);
|
movePlayerPacket.setRuntimeEntityId(geyserId);
|
||||||
movePlayerPacket.setPosition(position);
|
movePlayerPacket.setPosition(position);
|
||||||
@ -233,9 +233,11 @@ public class PlayerEntity extends LivingEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void updateRotation(float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||||
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
|
// the method below is called by super.updateRotation(yaw, pitch, isOnGround).
|
||||||
super.updateRotation(yaw, pitch, isOnGround);
|
// but we have to be able to set the headYaw, so we call the method below directly.
|
||||||
|
super.moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
|
||||||
|
|
||||||
// Both packets need to be sent or else player head rotation isn't correctly updated
|
// Both packets need to be sent or else player head rotation isn't correctly updated
|
||||||
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
||||||
movePlayerPacket.setRuntimeEntityId(geyserId);
|
movePlayerPacket.setRuntimeEntityId(geyserId);
|
||||||
@ -252,6 +254,11 @@ public class PlayerEntity extends LivingEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
|
||||||
|
updateRotation(yaw, pitch, getHeadYaw(), isOnGround);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(Vector3f position) {
|
public void setPosition(Vector3f position) {
|
||||||
super.setPosition(position.add(0, definition.offset(), 0));
|
super.setPosition(position.add(0, definition.offset(), 0));
|
||||||
@ -300,7 +307,7 @@ public class PlayerEntity extends LivingEntity {
|
|||||||
}
|
}
|
||||||
// The parrot is a separate entity in Bedrock, but part of the player entity in Java //TODO is a UUID provided in NBT?
|
// The parrot is a separate entity in Bedrock, but part of the player entity in Java //TODO is a UUID provided in NBT?
|
||||||
ParrotEntity parrot = new ParrotEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(),
|
ParrotEntity parrot = new ParrotEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(),
|
||||||
null, EntityDefinitions.PARROT, position, motion, yaw, pitch, headYaw);
|
null, EntityDefinitions.PARROT, position, motion, getYaw(), getPitch(), getHeadYaw());
|
||||||
parrot.spawnEntity();
|
parrot.spawnEntity();
|
||||||
parrot.getDirtyMetadata().put(EntityData.VARIANT, tag.get("Variant").getValue());
|
parrot.getDirtyMetadata().put(EntityData.VARIANT, tag.get("Variant").getValue());
|
||||||
// Different position whether the parrot is left or right
|
// Different position whether the parrot is left or right
|
||||||
|
@ -81,8 +81,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
|
|||||||
// This isn't needed, but it makes the packets closer to vanilla
|
// This isn't needed, but it makes the packets closer to vanilla
|
||||||
// It also means you can't "lag back" while only looking, in theory
|
// It also means you can't "lag back" while only looking, in theory
|
||||||
if (!positionChanged && rotationChanged) {
|
if (!positionChanged && rotationChanged) {
|
||||||
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(
|
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(packet.isOnGround(), yaw, pitch);
|
||||||
packet.isOnGround(), packet.getRotation().getY(), packet.getRotation().getX());
|
|
||||||
|
|
||||||
entity.setYaw(yaw);
|
entity.setYaw(yaw);
|
||||||
entity.setPitch(pitch);
|
entity.setPitch(pitch);
|
||||||
@ -101,8 +100,11 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
|
|||||||
Packet movePacket;
|
Packet movePacket;
|
||||||
if (rotationChanged) {
|
if (rotationChanged) {
|
||||||
// Send rotation updates as well
|
// Send rotation updates as well
|
||||||
movePacket = new ServerboundMovePlayerPosRotPacket(packet.isOnGround(), position.getX(), position.getY(), position.getZ(),
|
movePacket = new ServerboundMovePlayerPosRotPacket(
|
||||||
packet.getRotation().getY(), packet.getRotation().getX());
|
packet.isOnGround(),
|
||||||
|
position.getX(), position.getY(), position.getZ(),
|
||||||
|
yaw, pitch
|
||||||
|
);
|
||||||
entity.setYaw(yaw);
|
entity.setYaw(yaw);
|
||||||
entity.setPitch(pitch);
|
entity.setPitch(pitch);
|
||||||
entity.setHeadYaw(headYaw);
|
entity.setHeadYaw(headYaw);
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.translator.protocol.java.entity.player;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerLookAtPacket;
|
||||||
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
|
import org.geysermc.geyser.util.MathUtils;
|
||||||
|
|
||||||
|
@Translator(packet = ClientboundPlayerLookAtPacket.class)
|
||||||
|
public class JavaPlayerLookAtTranslator extends PacketTranslator<ClientboundPlayerLookAtPacket> {
|
||||||
|
@Override
|
||||||
|
public void translate(GeyserSession session, ClientboundPlayerLookAtPacket packet) {
|
||||||
|
var targetPosition = targetPosition(session, packet);
|
||||||
|
var selfPosition = session.getPlayerEntity().getPosition();
|
||||||
|
|
||||||
|
var xDelta = targetPosition.getX() - selfPosition.getX();
|
||||||
|
var yDelta = targetPosition.getY() - selfPosition.getY();
|
||||||
|
var zDelta = targetPosition.getZ() - selfPosition.getZ();
|
||||||
|
var sqrt = Math.sqrt(xDelta * xDelta + zDelta * zDelta);
|
||||||
|
|
||||||
|
var yaw = MathUtils.wrapDegrees(-Math.toDegrees(Math.atan2(yDelta, sqrt)));
|
||||||
|
var pitch = MathUtils.wrapDegrees(Math.toDegrees(Math.atan2(zDelta, xDelta)) - 90.0);
|
||||||
|
|
||||||
|
var self = session.getPlayerEntity();
|
||||||
|
// headYaw is also set to yaw in this packet
|
||||||
|
self.updateRotation(yaw, pitch, yaw, self.isOnGround());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3f targetPosition(GeyserSession session, ClientboundPlayerLookAtPacket packet) {
|
||||||
|
if (packet.getTargetEntityOrigin() != null) {
|
||||||
|
var entityId = packet.getTargetEntityId();
|
||||||
|
var target = session.getEntityCache().getEntityByJavaId(entityId);
|
||||||
|
if (target != null) {
|
||||||
|
return switch (packet.getTargetEntityOrigin()) {
|
||||||
|
case FEET -> target.getPosition();
|
||||||
|
case EYES -> target.getPosition().add(0, target.getBoundingBoxHeight(), 0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
|
||||||
|
}
|
||||||
|
}
|
@ -74,7 +74,7 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
|
|||||||
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
||||||
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
|
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
|
||||||
movePlayerPacket.setPosition(entity.getPosition());
|
movePlayerPacket.setPosition(entity.getPosition());
|
||||||
movePlayerPacket.setRotation(Vector3f.from(packet.getPitch(), packet.getYaw(), 0));
|
movePlayerPacket.setRotation(entity.getBedrockRotation());
|
||||||
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
|
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
|
||||||
|
|
||||||
session.sendUpstreamPacket(movePlayerPacket);
|
session.sendUpstreamPacket(movePlayerPacket);
|
||||||
@ -114,17 +114,15 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
|
|||||||
double newZ = packet.getZ() +
|
double newZ = packet.getZ() +
|
||||||
(packet.getRelative().contains(PositionElement.Z) ? entity.getPosition().getZ() : 0);
|
(packet.getRelative().contains(PositionElement.Z) ? entity.getPosition().getZ() : 0);
|
||||||
|
|
||||||
float newPitch = packet.getPitch() +
|
float newPitch = packet.getPitch() + (packet.getRelative().contains(PositionElement.PITCH) ? entity.getPitch() : 0);
|
||||||
(packet.getRelative().contains(PositionElement.PITCH) ? entity.getBedrockRotation().getX() : 0);
|
float newYaw = packet.getYaw() + (packet.getRelative().contains(PositionElement.YAW) ? entity.getYaw() : 0);
|
||||||
float newYaw = packet.getYaw() +
|
|
||||||
(packet.getRelative().contains(PositionElement.YAW) ? entity.getBedrockRotation().getY() : 0);
|
|
||||||
|
|
||||||
int id = packet.getTeleportId();
|
int id = packet.getTeleportId();
|
||||||
|
|
||||||
session.getGeyser().getLogger().debug("Teleport (" + id + ") from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
|
session.getGeyser().getLogger().debug("Teleport (" + id + ") from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
|
||||||
|
|
||||||
Vector3f lastPlayerPosition = entity.getPosition().down(EntityDefinitions.PLAYER.offset());
|
Vector3f lastPlayerPosition = entity.getPosition().down(EntityDefinitions.PLAYER.offset());
|
||||||
float lastPlayerPitch = entity.getBedrockRotation().getX();
|
float lastPlayerPitch = entity.getPitch();
|
||||||
Vector3f teleportDestination = Vector3f.from(newX, newY, newZ);
|
Vector3f teleportDestination = Vector3f.from(newX, newY, newZ);
|
||||||
entity.moveAbsolute(teleportDestination, newYaw, newPitch, true, true);
|
entity.moveAbsolute(teleportDestination, newYaw, newPitch, true, true);
|
||||||
|
|
||||||
|
@ -26,9 +26,26 @@
|
|||||||
package org.geysermc.geyser.util;
|
package org.geysermc.geyser.util;
|
||||||
|
|
||||||
public class MathUtils {
|
public class MathUtils {
|
||||||
|
|
||||||
public static final double SQRT_OF_TWO = Math.sqrt(2);
|
public static final double SQRT_OF_TWO = Math.sqrt(2);
|
||||||
|
|
||||||
|
public static float wrapDegrees(float degrees) {
|
||||||
|
degrees = degrees % 360.0f;
|
||||||
|
if (degrees < -180.0f) {
|
||||||
|
degrees += 360.0f;
|
||||||
|
} else if (degrees >= 180.0f) {
|
||||||
|
degrees -= 360.0f;
|
||||||
|
}
|
||||||
|
return degrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float wrapDegrees(double degrees) {
|
||||||
|
return wrapDegrees((float) degrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int wrapDegreesToInt(float degrees) {
|
||||||
|
return (int) wrapDegrees(degrees);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Round the given float to the next whole number
|
* Round the given float to the next whole number
|
||||||
*
|
*
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren