mirror of
https://github.com/GeyserMC/Geyser.git
synced 2026-01-06 15:41:50 +00:00
Send TickEndPacket alongside the auth input packet, store correct Java yaw (#5716)
* Moved ServerboundClientTickEndPacket to PlayerAuthInput translator. * Fixed sprinting packet sending. * Make yaw rotation match JE behaviour. * Use the fixed yaw in ServerboundUseItemPacket. * Fixed swinging order for attacking. * Update some comments. Co-authored-by: chris <github@onechris.mozmail.com> * Requested changes. * Update core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockMovePlayer.java Co-authored-by: chris <github@onechris.mozmail.com> * Update core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java Co-authored-by: chris <github@onechris.mozmail.com> * Update core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java Co-authored-by: chris <github@onechris.mozmail.com> --------- Co-authored-by: chris <github@onechris.mozmail.com>
This commit is contained in:
@@ -117,6 +117,9 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
@Getter @Setter
|
||||
private Vector2f bedrockInteractRotation = Vector2f.ZERO;
|
||||
|
||||
@Getter @Setter
|
||||
private float javaYaw;
|
||||
|
||||
public SessionPlayerEntity(GeyserSession session) {
|
||||
super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null);
|
||||
|
||||
@@ -141,6 +144,12 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
// Already logged in
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYaw(float yaw) {
|
||||
super.setYaw(yaw);
|
||||
this.javaYaw = yaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
@@ -216,12 +225,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setSprinting(boolean value) {
|
||||
super.setSprinting(value);
|
||||
session.setSprinting(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setGliding(boolean value) {
|
||||
session.setGliding(value);
|
||||
|
||||
@@ -443,6 +443,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
@Setter
|
||||
private Pose pose = Pose.STANDING;
|
||||
|
||||
/**
|
||||
* This is used to keep track of player sprinting and should only change by START_SPRINT and STOP_SPRINT sent by the player, not from flag update.
|
||||
*/
|
||||
@Setter
|
||||
private boolean sprinting;
|
||||
|
||||
@@ -1296,12 +1299,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
this.bundleCache.tick();
|
||||
this.dialogManager.tick();
|
||||
this.waypointCache.tick();
|
||||
|
||||
if (spawned && protocol.getOutboundState() == ProtocolState.GAME) {
|
||||
// Could move this to the PlayerAuthInput translator, in the event the player lags
|
||||
// but this will work once we implement matching Java custom tick cycles
|
||||
sendDownstreamGamePacket(ServerboundClientTickEndPacket.INSTANCE);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
@@ -1431,7 +1428,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
return;
|
||||
}
|
||||
|
||||
float yaw = playerEntity.getYaw(), pitch = playerEntity.getPitch();
|
||||
float yaw = playerEntity.getJavaYaw(), pitch = playerEntity.getPitch();
|
||||
if (useTouchRotation) { // Only use touch rotation when we actually needed to, resolve https://github.com/GeyserMC/Geyser/issues/5704
|
||||
yaw = playerEntity.getBedrockInteractRotation().getY();
|
||||
pitch = playerEntity.getBedrockInteractRotation().getX();
|
||||
|
||||
@@ -58,7 +58,7 @@ public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
||||
// Other times, there is a 1-tick-delay, which would result in the swing packet sent here. The BedrockAuthInputTranslator's
|
||||
// MISSED_SWING case also accounts for that by checking if a swing was sent a tick ago here.
|
||||
|
||||
// Also, delay the swing so entity damage can be processed first
|
||||
// We also send this right after entity attack to ensure packet order.
|
||||
session.scheduleInEventLoop(() -> {
|
||||
if (session.getArmAnimationTicks() != 0 && (session.getTicks() - session.getLastAirHitTick() > 2)) {
|
||||
// So, generally, a Java player can only do one *thing* at a time.
|
||||
|
||||
@@ -478,6 +478,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
InteractAction.ATTACK, session.isSneaking());
|
||||
session.sendDownstreamGamePacket(attackPacket);
|
||||
|
||||
// Even though it is true that we already send this in BedrockAnimateTranslator, the behaviour is a bit inconsistent and
|
||||
// beside we want to ensure that this should be sent right away after we send interact packet or else the order will
|
||||
// be weird eg: interact - some packet - swing, which is not vanilla behaviour and might flag some anticheats.
|
||||
session.sendDownstreamGamePacket(new ServerboundSwingPacket(Hand.MAIN_HAND));
|
||||
|
||||
// Since 1.19.10, LevelSoundEventPackets are no longer sent by the client when attacking entities
|
||||
CooldownUtils.sendCooldown(session);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.level.physics.CollisionResult;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
|
||||
@@ -82,11 +83,16 @@ final class BedrockMovePlayer {
|
||||
float pitch = packet.getRotation().getX();
|
||||
float headYaw = packet.getRotation().getY();
|
||||
|
||||
// Even though on Java Edition the yaw rotation should never get wrapped and can get larger than 180, on Bedrock Edition
|
||||
// the client always seems to wrap and limit it to -180 and 180, which is not vanilla behaviour, and doesn't cause problems
|
||||
// on the surface - however, some anticheat checks for this, so we account for it
|
||||
float javaYaw = entity.getJavaYaw() + MathUtils.wrapDegrees(yaw - entity.getJavaYaw());
|
||||
|
||||
boolean hasVehicle = entity.getVehicle() != null;
|
||||
|
||||
// shouldSendPositionReminder also increments a tick counter, so make sure it's always called unless the player is on a vehicle.
|
||||
boolean positionChangedAndShouldUpdate = !hasVehicle && (session.getInputCache().shouldSendPositionReminder() || actualPositionChanged);
|
||||
boolean rotationChanged = hasVehicle || (entity.getYaw() != yaw || entity.getPitch() != pitch || entity.getHeadYaw() != headYaw);
|
||||
boolean rotationChanged = hasVehicle || (entity.getJavaYaw() != javaYaw || entity.getPitch() != pitch);
|
||||
|
||||
// Simulate jumping since it happened this tick, not from the last tick end.
|
||||
if (entity.isOnGround() && packet.getInputData().contains(PlayerAuthInputData.START_JUMPING)) {
|
||||
@@ -154,9 +160,10 @@ final class BedrockMovePlayer {
|
||||
// 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
|
||||
if (!positionChangedAndShouldUpdate && rotationChanged) {
|
||||
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(isOnGround, horizontalCollision, yaw, pitch);
|
||||
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(isOnGround, horizontalCollision, javaYaw, pitch);
|
||||
|
||||
entity.setYaw(yaw);
|
||||
entity.setJavaYaw(javaYaw);
|
||||
entity.setPitch(pitch);
|
||||
entity.setHeadYaw(headYaw);
|
||||
|
||||
@@ -181,9 +188,10 @@ final class BedrockMovePlayer {
|
||||
isOnGround,
|
||||
horizontalCollision,
|
||||
position.getX(), position.getY(), position.getZ(),
|
||||
yaw, pitch
|
||||
javaYaw, pitch
|
||||
);
|
||||
entity.setYaw(yaw);
|
||||
entity.setJavaYaw(javaYaw);
|
||||
entity.setPitch(pitch);
|
||||
entity.setHeadYaw(headYaw);
|
||||
} else {
|
||||
|
||||
@@ -52,12 +52,14 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.translator.protocol.bedrock.BedrockInventoryTransactionTranslator;
|
||||
import org.geysermc.geyser.util.CooldownUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientTickEndPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
|
||||
@@ -106,8 +108,10 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
attributesPacket.getAttributes().addAll(entity.getAttributes().values());
|
||||
session.sendUpstreamPacket(attributesPacket);
|
||||
} else {
|
||||
sprintPacket = new ServerboundPlayerCommandPacket(entity.javaId(), PlayerState.START_SPRINTING);
|
||||
session.setSprinting(true);
|
||||
if (!session.isSprinting()) {
|
||||
sprintPacket = new ServerboundPlayerCommandPacket(entity.javaId(), PlayerState.START_SPRINTING);
|
||||
session.setSprinting(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,6 +213,11 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
|
||||
|
||||
BedrockMovePlayer.translate(session, packet);
|
||||
|
||||
// This is the best way send this since most modern anticheat will expect this to be in sync with the player movement packet.
|
||||
if (session.isSpawned()) {
|
||||
session.sendDownstreamGamePacket(ServerboundClientTickEndPacket.INSTANCE);
|
||||
}
|
||||
|
||||
// Only set steering values when the vehicle is a boat and when the client is actually in it
|
||||
if (entity.getVehicle() instanceof BoatEntity && inputData.contains(PlayerAuthInputData.IN_CLIENT_PREDICTED_IN_VEHICLE)) {
|
||||
boolean up = inputData.contains(PlayerAuthInputData.UP);
|
||||
|
||||
Reference in New Issue
Block a user