mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Fix some regressions in swim handling
This commit is contained in:
parent
b134dd3b1c
commit
68c13c08fa
6 changed files with 47 additions and 18 deletions
|
@ -65,6 +65,8 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
@Getter @Setter
|
||||
public class PlayerEntity extends LivingEntity {
|
||||
public static final float SNEAKING_POSE_HEIGHT = 1.5f;
|
||||
|
||||
private GameProfile profile;
|
||||
private String username;
|
||||
private boolean playerList = true; // Player is in the player list
|
||||
|
@ -381,7 +383,7 @@ public class PlayerEntity extends LivingEntity {
|
|||
protected void setDimensions(Pose pose) {
|
||||
float height;
|
||||
switch (pose) {
|
||||
case SNEAKING -> height = 1.5f;
|
||||
case SNEAKING -> height = SNEAKING_POSE_HEIGHT;
|
||||
case FALL_FLYING, SPIN_ATTACK, SWIMMING -> height = 0.6f;
|
||||
default -> {
|
||||
super.setDimensions(pose);
|
||||
|
|
|
@ -28,21 +28,17 @@ package org.geysermc.geyser.entity.type.player;
|
|||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.AttributeData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.AttributeUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -112,12 +108,7 @@ public class SessionPlayerEntity extends PlayerEntity {
|
|||
@Override
|
||||
public void setFlags(ByteEntityMetadata entityMetadata) {
|
||||
super.setFlags(entityMetadata);
|
||||
// Swimming/crawling is controlled by the Java server
|
||||
boolean swimming = (entityMetadata.getPrimitiveValue() & 0x10) == 0x10;
|
||||
if (swimming) {
|
||||
setPose(Pose.SWIMMING);
|
||||
}
|
||||
session.setSwimmingInWater(swimming && getFlag(EntityFlag.SPRINTING));
|
||||
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
|
||||
refreshSpeed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -362,7 +362,22 @@ public class CollisionManager {
|
|||
* @return true if the block located at the player's floor position plus 1 would intersect with the player,
|
||||
* were they not sneaking
|
||||
*/
|
||||
public boolean isUnderSlab() {
|
||||
public boolean mustPlayerSneakHere() {
|
||||
return checkPose(EntityDefinitions.PLAYER.height());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the block located at the player's floor position plus 1 would intersect with the player,
|
||||
* were they not crawling
|
||||
*/
|
||||
public boolean mustPlayerCrawlHere() {
|
||||
return checkPose(PlayerEntity.SNEAKING_POSE_HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param height check and see if this height is invalid in the current player position
|
||||
*/
|
||||
private boolean checkPose(float height) {
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt();
|
||||
BlockCollision collision = BlockUtils.getCollisionAt(session, position);
|
||||
if (collision != null) {
|
||||
|
@ -370,7 +385,7 @@ public class CollisionManager {
|
|||
// at the current location.
|
||||
double originalY = playerBoundingBox.getMiddleY();
|
||||
double originalHeight = playerBoundingBox.getSizeY();
|
||||
double standingY = originalY - (originalHeight / 2.0) + (EntityDefinitions.PLAYER.height() / 2.0);
|
||||
double standingY = originalY - (originalHeight / 2.0) + (height / 2.0);
|
||||
|
||||
playerBoundingBox.setSizeY(EntityDefinitions.PLAYER.height());
|
||||
playerBoundingBox.setMiddleY(standingY);
|
||||
|
|
|
@ -1069,6 +1069,18 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||
playerEntity.setFlag(EntityFlag.SNEAKING, sneaking);
|
||||
}
|
||||
|
||||
public void setSwimming(boolean swimming) {
|
||||
if (swimming) {
|
||||
this.pose = Pose.SWIMMING;
|
||||
playerEntity.setBoundingBoxHeight(0.6f);
|
||||
} else {
|
||||
this.pose = Pose.STANDING;
|
||||
playerEntity.setBoundingBoxHeight(playerEntity.getDefinition().height());
|
||||
}
|
||||
playerEntity.setFlag(EntityFlag.SWIMMING, swimming);
|
||||
playerEntity.updateBedrockMetadata();
|
||||
}
|
||||
|
||||
public void setFlying(boolean flying) {
|
||||
this.flying = flying;
|
||||
|
||||
|
@ -1087,7 +1099,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||
public AttributeData adjustSpeed() {
|
||||
AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED);
|
||||
if (currentPlayerSpeed != null) {
|
||||
if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.isUnderSlab()) ||
|
||||
if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) ||
|
||||
(!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
|
||||
// Either of those conditions means that Bedrock goes zoom when they shouldn't be
|
||||
AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f);
|
||||
|
|
|
@ -44,6 +44,11 @@ public class BedrockAdventureSettingsTranslator extends PacketTranslator<Adventu
|
|||
// We should always be flying in spectator mode
|
||||
session.sendAdventureSettings();
|
||||
return;
|
||||
} else if (isFlying && session.getPlayerEntity().getFlag(EntityFlag.SWIMMING) && session.getCollisionManager().isPlayerInWater()) {
|
||||
// As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling
|
||||
// If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE
|
||||
session.sendAdventureSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
session.setFlying(isFlying);
|
||||
|
|
|
@ -77,16 +77,20 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
|||
session.sendUpstreamPacket(attributesPacket);
|
||||
break;
|
||||
case START_SWIMMING:
|
||||
if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
|
||||
session.sendDownstreamPacket(startSwimPacket);
|
||||
|
||||
session.setSwimming(true);
|
||||
}
|
||||
break;
|
||||
case STOP_SWIMMING:
|
||||
// Prevent packet spam when Bedrock players are crawling near the edge of a block
|
||||
if (session.isSwimmingInWater()) {
|
||||
if (!session.getCollisionManager().mustPlayerCrawlHere()) {
|
||||
ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
|
||||
session.sendDownstreamPacket(stopSwimPacket);
|
||||
|
||||
session.setSwimming(false);
|
||||
}
|
||||
break;
|
||||
case START_GLIDE:
|
||||
|
@ -135,14 +139,14 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
|||
session.setSneaking(false);
|
||||
break;
|
||||
case START_SPRINT:
|
||||
if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING);
|
||||
session.sendDownstreamPacket(startSprintPacket);
|
||||
session.setSprinting(true);
|
||||
}
|
||||
break;
|
||||
case STOP_SPRINT:
|
||||
if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
|
||||
if (!entity.getFlag(EntityFlag.SWIMMING)) {
|
||||
ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING);
|
||||
session.sendDownstreamPacket(stopSprintPacket);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue