Skip to content

Commit a58fa79

Browse files
authored
Fix: Player pose switching behaviour (#5987)
* More accurate pose switching behaviour. * Revert some change.
1 parent 659369a commit a58fa79

File tree

5 files changed

+44
-79
lines changed

5 files changed

+44
-79
lines changed

core/src/main/java/org/geysermc/geyser/entity/type/player/AvatarEntity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,19 @@ public void setPose(Pose pose) {
322322
setFlag(EntityFlag.SWIMMING, true);
323323
} else {
324324
setFlag(EntityFlag.CRAWLING, true);
325+
325326
// Look at https://github.com/GeyserMC/Geyser/issues/5316, we're fixing this by spoofing player pitch to 0.
326-
updateRotation(this.yaw, 0, this.onGround);
327+
// Don't do this for session player however, as that teleport them back and messed up their rotation.
328+
if (!(this instanceof SessionPlayerEntity)) {
329+
updateRotation(this.yaw, 0, this.onGround);
330+
}
327331
}
328332
}
329333
}
330334

331335
@Override
332336
public void setPitch(float pitch) {
333-
super.setPitch(getFlag(EntityFlag.CRAWLING) ? 0 : pitch);
337+
super.setPitch(getFlag(EntityFlag.CRAWLING) && !(this instanceof SessionPlayerEntity) ? 0 : pitch);
334338
}
335339

336340
@Override

core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.checkerframework.checker.nullness.qual.Nullable;
3131
import org.cloudburstmc.math.vector.Vector3f;
3232
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
33+
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
3334
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
3435
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
3536
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
@@ -40,6 +41,7 @@
4041
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
4142
import org.geysermc.geyser.session.GeyserSession;
4243
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
44+
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
4345
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
4446

4547
import java.util.Collections;
@@ -224,4 +226,19 @@ public UUID getTabListUuid() {
224226
public Vector3f position() {
225227
return this.position.down(definition.offset());
226228
}
229+
230+
// From 1.21.8 code, should be correct since some pose should be prioritized.
231+
public Pose getDesiredPose() {
232+
if (this.getBedPosition() != null) {
233+
return Pose.SLEEPING;
234+
} else if (this.getFlag(EntityFlag.SWIMMING) || this.getFlag(EntityFlag.CRAWLING)) {
235+
return Pose.SWIMMING;
236+
} else if (this.getFlag(EntityFlag.GLIDING)) {
237+
return Pose.FALL_FLYING;
238+
} else if (this.getFlag(EntityFlag.DAMAGE_NEARBY_MOBS)) {
239+
return Pose.SPIN_ATTACK;
240+
} else {
241+
return this.getFlag(EntityFlag.SNEAKING) && !session.isFlying() ? Pose.SNEAKING : Pose.STANDING;
242+
}
243+
}
227244
}

core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,6 @@ public void setFlags(ByteEntityMetadata entityMetadata) {
235235
}
236236
}
237237

238-
@Override
239-
protected void setGliding(boolean value) {
240-
session.setGliding(value);
241-
}
242-
243238
@Override
244239
protected void setSneaking(boolean value) {
245240
if (value) {
@@ -250,11 +245,6 @@ protected void setSneaking(boolean value) {
250245
}
251246
}
252247

253-
@Override
254-
protected void setSpinAttack(boolean value) {
255-
session.setSpinAttack(value);
256-
}
257-
258248
/**
259249
* Since 1.19.40, the client must be re-informed of its bounding box on respawn
260250
* See <a href="https://github.com/GeyserMC/Geyser/issues/3370">issue 3370</a>
@@ -279,7 +269,11 @@ public boolean setBoundingBoxHeight(float height) {
279269
@Override
280270
public void setPose(Pose pose) {
281271
super.setPose(pose);
282-
session.setPose(pose);
272+
273+
if (pose != session.getPose()) {
274+
session.setPose(pose);
275+
updateBedrockMetadata();
276+
}
283277
}
284278

285279
public float getMaxHealth() {

core/src/main/java/org/geysermc/geyser/session/GeyserSession.java

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
635635
/**
636636
* If the current player is flying
637637
*/
638+
@Setter
638639
private boolean flying = false;
639640

640641
/**
@@ -1320,26 +1321,13 @@ public void startSneaking(boolean updateMetaData) {
13201321

13211322
public void stopSneaking(boolean updateMetaData) {
13221323
disableBlocking();
1323-
13241324
setSneaking(false, updateMetaData);
13251325
}
13261326

1327-
public void setSpinAttack(boolean spinAttack) {
1328-
switchPose(spinAttack, EntityFlag.DAMAGE_NEARBY_MOBS, Pose.SPIN_ATTACK);
1329-
}
1330-
1331-
public void setGliding(boolean gliding) {
1332-
switchPose(gliding, EntityFlag.GLIDING, Pose.FALL_FLYING);
1333-
}
1334-
13351327
private void setSneaking(boolean sneaking, boolean update) {
13361328
this.sneaking = sneaking;
13371329

1338-
// Update pose and bounding box on our end
1339-
if (!flying) {
1340-
// The pose and bounding box should not be updated if the player is flying
1341-
setSneakingPose(sneaking);
1342-
}
1330+
playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
13431331
collisionManager.updateScaffoldingFlags(false);
13441332

13451333
if (update) {
@@ -1352,38 +1340,6 @@ private void setSneaking(boolean sneaking, boolean update) {
13521340
}
13531341
}
13541342

1355-
private void setSneakingPose(boolean sneaking) {
1356-
if (this.pose == Pose.SNEAKING && !sneaking) {
1357-
this.pose = Pose.STANDING;
1358-
playerEntity.setBoundingBoxHeight(playerEntity.getDefinition().height());
1359-
} else if (sneaking) {
1360-
this.pose = Pose.SNEAKING;
1361-
playerEntity.setBoundingBoxHeight(1.5f);
1362-
}
1363-
playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
1364-
}
1365-
1366-
public void setSwimming(boolean swimming) {
1367-
if (!swimming && playerEntity.getFlag(EntityFlag.CRAWLING)) {
1368-
// Do not update bounding box.
1369-
playerEntity.setFlag(EntityFlag.SWIMMING, false);
1370-
playerEntity.updateBedrockMetadata();
1371-
return;
1372-
}
1373-
switchPose(swimming, EntityFlag.SWIMMING, Pose.SWIMMING);
1374-
}
1375-
1376-
public void setCrawling(boolean crawling) {
1377-
switchPose(crawling, EntityFlag.CRAWLING, Pose.SWIMMING);
1378-
}
1379-
1380-
private void switchPose(boolean value, EntityFlag flag, Pose pose) {
1381-
this.pose = value ? pose : this.pose == pose ? Pose.STANDING : this.pose;
1382-
playerEntity.setDimensionsFromPose(this.pose);
1383-
playerEntity.setFlag(flag, value);
1384-
playerEntity.updateBedrockMetadata();
1385-
}
1386-
13871343
public void setNoClip(boolean noClip) {
13881344
if (this.noClip == noClip) {
13891345
return;
@@ -1393,16 +1349,6 @@ public void setNoClip(boolean noClip) {
13931349
this.sendAdventureSettings();
13941350
}
13951351

1396-
public void setFlying(boolean flying) {
1397-
this.flying = flying;
1398-
1399-
if (sneaking) {
1400-
// update bounding box as it is not reduced when flying
1401-
setSneakingPose(!flying);
1402-
playerEntity.updateBedrockMetadata();
1403-
}
1404-
}
1405-
14061352
public void setGameMode(GameMode newGamemode) {
14071353
boolean currentlySpectator = this.gameMode == GameMode.SPECTATOR;
14081354
this.gameMode = newGamemode;
@@ -2228,7 +2174,7 @@ public void playSoundEvent(SoundEvent sound, Vector3f position) {
22282174
}
22292175

22302176
public float getEyeHeight() {
2231-
return switch (pose) {
2177+
return switch (this.pose) {
22322178
case SNEAKING -> 1.27f;
22332179
case SWIMMING,
22342180
FALL_FLYING, // Elytra

core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ public void translate(GeyserSession session, PlayerAuthInputPacket packet) {
8383
switch (input) {
8484
case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction());
8585
case PERFORM_ITEM_STACK_REQUEST -> session.getPlayerInventoryHolder().translateRequests(List.of(packet.getItemStackRequest()));
86-
case START_SWIMMING -> session.setSwimming(true);
87-
case STOP_SWIMMING -> session.setSwimming(false);
88-
case START_CRAWLING -> session.setCrawling(true);
89-
case STOP_CRAWLING -> session.setCrawling(false);
86+
case START_SWIMMING -> entity.setFlag(EntityFlag.SWIMMING, true);
87+
case STOP_SWIMMING -> entity.setFlag(EntityFlag.SWIMMING, false);
88+
case START_CRAWLING -> entity.setFlag(EntityFlag.CRAWLING, true);
89+
case STOP_CRAWLING -> entity.setFlag(EntityFlag.CRAWLING, false);
9090
case START_SPRINTING -> {
9191
if (!leftOverInputData.contains(PlayerAuthInputData.STOP_SPRINTING)) {
9292
if (!session.isSprinting()) {
@@ -140,26 +140,26 @@ public void translate(GeyserSession session, PlayerAuthInputPacket packet) {
140140
session.setFlying(false);
141141
session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(false));
142142
}
143-
session.setGliding(true);
143+
entity.setFlag(EntityFlag.GLIDING, true);
144144
session.sendDownstreamGamePacket(new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_ELYTRA_FLYING));
145145
} else {
146146
entity.forceFlagUpdate();
147-
session.setGliding(false);
147+
entity.setFlag(EntityFlag.GLIDING, false);
148148
// return to flying if we can't start gliding
149149
if (session.isFlying()) {
150150
session.sendAdventureSettings();
151151
}
152152
}
153153
}
154154
}
155-
case START_SPIN_ATTACK -> session.setSpinAttack(true);
156-
case STOP_SPIN_ATTACK -> session.setSpinAttack(false);
155+
case START_SPIN_ATTACK -> entity.setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, true);
156+
case STOP_SPIN_ATTACK -> entity.setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, false);
157157
case STOP_GLIDING -> {
158158
// Java doesn't allow elytra gliding to stop mid-air.
159159
boolean shouldBeGliding = entity.isGliding() && entity.canStartGliding();
160160
// Always update; Bedrock can get real weird if the gliding state is mismatching
161161
entity.forceFlagUpdate();
162-
session.setGliding(shouldBeGliding);
162+
entity.setFlag(EntityFlag.GLIDING, shouldBeGliding);
163163
}
164164
case MISSED_SWING -> {
165165
session.setLastAirHitTick(session.getTicks());
@@ -183,6 +183,10 @@ public void translate(GeyserSession session, PlayerAuthInputPacket packet) {
183183
}
184184
}
185185

186+
// The player will calculate the "desired" pose at the end of every tick, if this pose still invalid then
187+
// it will consider the smaller pose, but we don't need to calculate that, we can go off what the client sent us.
188+
entity.setPose(entity.getDesiredPose());
189+
186190
// Vehicle input is send before player movement
187191
processVehicleInput(session, packet, wasJumping);
188192

0 commit comments

Comments
 (0)