From fc34aa464a1e9f50434497599b8d7dfd64ec5fc6 Mon Sep 17 00:00:00 2001 From: oryxel Date: Fri, 11 Jul 2025 06:34:33 +0700 Subject: [PATCH] Entity flag fixes for shulkers, player entity crawling, out-of-block pushing (#5670) * Some fixes related to flags. * Fixed comments. * Cleanup some if statements. --- .../type/living/monster/ShulkerEntity.java | 6 +++++ .../entity/type/player/PlayerEntity.java | 24 +++++++++++++++++++ .../type/player/SessionPlayerEntity.java | 8 +++++++ 3 files changed, 38 insertions(+) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java index aecb4a915..d8266f29d 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java @@ -52,6 +52,12 @@ public class ShulkerEntity extends GolemEntity { // As of 1.19.4, it seems Java no longer sends the shulker color if it's the default color on initial spawn // We still need the special case for 16 color in setShulkerColor though as it will send it for an entity metadata update dirtyMetadata.put(EntityDataTypes.VARIANT, 16); + + setFlag(EntityFlag.COLLIDABLE, true); + + // This is vanilla behaviour yes (BDS does this), without this as of 1.21.93 entity became fully invisible. + // Doing this allow the invisible parity support inside GeyserOptionalPack to works again. + setFlag(EntityFlag.RENDER_WHEN_INVISIBLE, true); } public void setAttachedFace(EntityMetadata entityMetadata) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 742f550d0..7dbbf0b52 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -51,6 +51,7 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; @@ -422,6 +423,29 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { dirtyMetadata.put(EntityDataTypes.SCORE, show ? cachedScore : ""); } + @Override + public void setPose(Pose pose) { + super.setPose(pose); + setFlag(EntityFlag.SWIMMING, false); + setFlag(EntityFlag.CRAWLING, false); + + if (pose == Pose.SWIMMING) { + // This is just for, so we know if player is swimming or crawling. + if (session.getGeyser().getWorldManager().blockAt(session, this.position().toInt()).is(Blocks.WATER)) { + 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. + updateRotation(this.yaw, 0, this.onGround); + } + } + } + + @Override + public void setPitch(float pitch) { + super.setPitch(getFlag(EntityFlag.CRAWLING) ? 0 : pitch); + } + @Override public void setDimensionsFromPose(Pose pose) { float height; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 1fd4f5cf5..dcd3a1485 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -124,6 +124,14 @@ public class SessionPlayerEntity extends PlayerEntity { valid = true; } + @Override + protected void initializeMetadata() { + super.initializeMetadata(); + + // This allows player to be slowly push towards the closet space when stuck inside block instead of instantly moved out. + setFlag(EntityFlag.PUSH_TOWARDS_CLOSEST_SPACE, true); + } + @Override protected void setClientSideSilent() { // Do nothing, since we want the session player to hear their own footstep sounds for example.