mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-19 14:59:27 +00:00
Fix: Player pose switching behaviour (#5987)
* More accurate pose switching behaviour. * Revert some change.
This commit is contained in:
@@ -322,15 +322,19 @@ public class AvatarEntity extends LivingEntity {
|
||||
setFlag(EntityFlag.SWIMMING, true);
|
||||
} else {
|
||||
setFlag(EntityFlag.CRAWLING, true);
|
||||
|
||||
// Look at https://github.com/GeyserMC/Geyser/issues/5316, we're fixing this by spoofing player pitch to 0.
|
||||
// Don't do this for session player however, as that teleport them back and messed up their rotation.
|
||||
if (!(this instanceof SessionPlayerEntity)) {
|
||||
updateRotation(this.yaw, 0, this.onGround);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPitch(float pitch) {
|
||||
super.setPitch(getFlag(EntityFlag.CRAWLING) ? 0 : pitch);
|
||||
super.setPitch(getFlag(EntityFlag.CRAWLING) && !(this instanceof SessionPlayerEntity) ? 0 : pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,6 +30,7 @@ import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
@@ -40,6 +41,7 @@ import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -224,4 +226,19 @@ public class PlayerEntity extends AvatarEntity implements GeyserPlayerEntity {
|
||||
public Vector3f position() {
|
||||
return this.position.down(definition.offset());
|
||||
}
|
||||
|
||||
// From 1.21.8 code, should be correct since some pose should be prioritized.
|
||||
public Pose getDesiredPose() {
|
||||
if (this.getBedPosition() != null) {
|
||||
return Pose.SLEEPING;
|
||||
} else if (this.getFlag(EntityFlag.SWIMMING) || this.getFlag(EntityFlag.CRAWLING)) {
|
||||
return Pose.SWIMMING;
|
||||
} else if (this.getFlag(EntityFlag.GLIDING)) {
|
||||
return Pose.FALL_FLYING;
|
||||
} else if (this.getFlag(EntityFlag.DAMAGE_NEARBY_MOBS)) {
|
||||
return Pose.SPIN_ATTACK;
|
||||
} else {
|
||||
return this.getFlag(EntityFlag.SNEAKING) && !session.isFlying() ? Pose.SNEAKING : Pose.STANDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,11 +235,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setGliding(boolean value) {
|
||||
session.setGliding(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setSneaking(boolean value) {
|
||||
if (value) {
|
||||
@@ -250,11 +245,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setSpinAttack(boolean value) {
|
||||
session.setSpinAttack(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since 1.19.40, the client must be re-informed of its bounding box on respawn
|
||||
* See <a href="https://github.com/GeyserMC/Geyser/issues/3370">issue 3370</a>
|
||||
@@ -279,7 +269,11 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
@Override
|
||||
public void setPose(Pose pose) {
|
||||
super.setPose(pose);
|
||||
|
||||
if (pose != session.getPose()) {
|
||||
session.setPose(pose);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
public float getMaxHealth() {
|
||||
|
||||
@@ -635,6 +635,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
/**
|
||||
* If the current player is flying
|
||||
*/
|
||||
@Setter
|
||||
private boolean flying = false;
|
||||
|
||||
/**
|
||||
@@ -1320,26 +1321,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
|
||||
public void stopSneaking(boolean updateMetaData) {
|
||||
disableBlocking();
|
||||
|
||||
setSneaking(false, updateMetaData);
|
||||
}
|
||||
|
||||
public void setSpinAttack(boolean spinAttack) {
|
||||
switchPose(spinAttack, EntityFlag.DAMAGE_NEARBY_MOBS, Pose.SPIN_ATTACK);
|
||||
}
|
||||
|
||||
public void setGliding(boolean gliding) {
|
||||
switchPose(gliding, EntityFlag.GLIDING, Pose.FALL_FLYING);
|
||||
}
|
||||
|
||||
private void setSneaking(boolean sneaking, boolean update) {
|
||||
this.sneaking = sneaking;
|
||||
|
||||
// Update pose and bounding box on our end
|
||||
if (!flying) {
|
||||
// The pose and bounding box should not be updated if the player is flying
|
||||
setSneakingPose(sneaking);
|
||||
}
|
||||
playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
|
||||
collisionManager.updateScaffoldingFlags(false);
|
||||
|
||||
if (update) {
|
||||
@@ -1352,38 +1340,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
}
|
||||
}
|
||||
|
||||
private void setSneakingPose(boolean sneaking) {
|
||||
if (this.pose == Pose.SNEAKING && !sneaking) {
|
||||
this.pose = Pose.STANDING;
|
||||
playerEntity.setBoundingBoxHeight(playerEntity.getDefinition().height());
|
||||
} else if (sneaking) {
|
||||
this.pose = Pose.SNEAKING;
|
||||
playerEntity.setBoundingBoxHeight(1.5f);
|
||||
}
|
||||
playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
|
||||
}
|
||||
|
||||
public void setSwimming(boolean swimming) {
|
||||
if (!swimming && playerEntity.getFlag(EntityFlag.CRAWLING)) {
|
||||
// Do not update bounding box.
|
||||
playerEntity.setFlag(EntityFlag.SWIMMING, false);
|
||||
playerEntity.updateBedrockMetadata();
|
||||
return;
|
||||
}
|
||||
switchPose(swimming, EntityFlag.SWIMMING, Pose.SWIMMING);
|
||||
}
|
||||
|
||||
public void setCrawling(boolean crawling) {
|
||||
switchPose(crawling, EntityFlag.CRAWLING, Pose.SWIMMING);
|
||||
}
|
||||
|
||||
private void switchPose(boolean value, EntityFlag flag, Pose pose) {
|
||||
this.pose = value ? pose : this.pose == pose ? Pose.STANDING : this.pose;
|
||||
playerEntity.setDimensionsFromPose(this.pose);
|
||||
playerEntity.setFlag(flag, value);
|
||||
playerEntity.updateBedrockMetadata();
|
||||
}
|
||||
|
||||
public void setNoClip(boolean noClip) {
|
||||
if (this.noClip == noClip) {
|
||||
return;
|
||||
@@ -1393,16 +1349,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
this.sendAdventureSettings();
|
||||
}
|
||||
|
||||
public void setFlying(boolean flying) {
|
||||
this.flying = flying;
|
||||
|
||||
if (sneaking) {
|
||||
// update bounding box as it is not reduced when flying
|
||||
setSneakingPose(!flying);
|
||||
playerEntity.updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
public void setGameMode(GameMode newGamemode) {
|
||||
boolean currentlySpectator = this.gameMode == GameMode.SPECTATOR;
|
||||
this.gameMode = newGamemode;
|
||||
@@ -2228,7 +2174,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
}
|
||||
|
||||
public float getEyeHeight() {
|
||||
return switch (pose) {
|
||||
return switch (this.pose) {
|
||||
case SNEAKING -> 1.27f;
|
||||
case SWIMMING,
|
||||
FALL_FLYING, // Elytra
|
||||
|
||||
@@ -83,10 +83,10 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
switch (input) {
|
||||
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
|
||||
case PERFORM_ITEM_STACK_REQUEST -> session.getPlayerInventoryHolder().translateRequests(List.of(packet.getItemStackRequest()));
|
||||
case START_SWIMMING -> session.setSwimming(true);
|
||||
case STOP_SWIMMING -> session.setSwimming(false);
|
||||
case START_CRAWLING -> session.setCrawling(true);
|
||||
case STOP_CRAWLING -> session.setCrawling(false);
|
||||
case START_SWIMMING -> entity.setFlag(EntityFlag.SWIMMING, true);
|
||||
case STOP_SWIMMING -> entity.setFlag(EntityFlag.SWIMMING, false);
|
||||
case START_CRAWLING -> entity.setFlag(EntityFlag.CRAWLING, true);
|
||||
case STOP_CRAWLING -> entity.setFlag(EntityFlag.CRAWLING, false);
|
||||
case START_SPRINTING -> {
|
||||
if (!leftOverInputData.contains(PlayerAuthInputData.STOP_SPRINTING)) {
|
||||
if (!session.isSprinting()) {
|
||||
@@ -140,11 +140,11 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
session.setFlying(false);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(false));
|
||||
}
|
||||
session.setGliding(true);
|
||||
entity.setFlag(EntityFlag.GLIDING, true);
|
||||
session.sendDownstreamGamePacket(new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_ELYTRA_FLYING));
|
||||
} else {
|
||||
entity.forceFlagUpdate();
|
||||
session.setGliding(false);
|
||||
entity.setFlag(EntityFlag.GLIDING, false);
|
||||
// return to flying if we can't start gliding
|
||||
if (session.isFlying()) {
|
||||
session.sendAdventureSettings();
|
||||
@@ -152,14 +152,14 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
}
|
||||
}
|
||||
}
|
||||
case START_SPIN_ATTACK -> session.setSpinAttack(true);
|
||||
case STOP_SPIN_ATTACK -> session.setSpinAttack(false);
|
||||
case START_SPIN_ATTACK -> entity.setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, true);
|
||||
case STOP_SPIN_ATTACK -> entity.setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, false);
|
||||
case STOP_GLIDING -> {
|
||||
// Java doesn't allow elytra gliding to stop mid-air.
|
||||
boolean shouldBeGliding = entity.isGliding() && entity.canStartGliding();
|
||||
// Always update; Bedrock can get real weird if the gliding state is mismatching
|
||||
entity.forceFlagUpdate();
|
||||
session.setGliding(shouldBeGliding);
|
||||
entity.setFlag(EntityFlag.GLIDING, shouldBeGliding);
|
||||
}
|
||||
case MISSED_SWING -> {
|
||||
session.setLastAirHitTick(session.getTicks());
|
||||
@@ -183,6 +183,10 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
}
|
||||
}
|
||||
|
||||
// The player will calculate the "desired" pose at the end of every tick, if this pose still invalid then
|
||||
// it will consider the smaller pose, but we don't need to calculate that, we can go off what the client sent us.
|
||||
entity.setPose(entity.getDesiredPose());
|
||||
|
||||
// Vehicle input is send before player movement
|
||||
processVehicleInput(session, packet, wasJumping);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user