From bea070395f8624daea332f9651a18b3c80eaf0b0 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 29 Apr 2020 17:06:25 +0100 Subject: [PATCH] Handle player teleports properly (#389) * Handle player teleports properly Co-authored-by: ForceUpdate1 * impl teleport cache * impl teleport cache * removed debugs * Cleanup Co-authored-by: ForceUpdate1 --- .../org/geysermc/connector/entity/Entity.java | 8 ++-- .../connector/entity/PlayerEntity.java | 10 ++-- .../network/session/GeyserSession.java | 26 ++++++++-- .../network/session/cache/TeleportCache.java | 47 +++++++++++++++++++ .../bedrock/BedrockMovePlayerTranslator.java | 21 ++++++--- .../entity/JavaEntityTeleportTranslator.java | 2 +- .../JavaPlayerPositionRotationTranslator.java | 27 ++++++----- .../spawn/JavaSpawnPlayerTranslator.java | 8 ++-- 8 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 5596ca7a..54355d99 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -158,11 +158,11 @@ public class Entity { session.getUpstream().sendPacket(moveEntityPacket); } - public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) { - moveAbsolute(session, position, Vector3f.from(yaw, pitch, yaw), isOnGround); + public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) { + moveAbsolute(session, position, Vector3f.from(yaw, pitch, yaw), isOnGround, teleported); } - public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround) { + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { setPosition(position); setRotation(rotation); @@ -171,7 +171,7 @@ public class Entity { moveEntityPacket.setPosition(position); moveEntityPacket.setRotation(getBedrockRotation()); moveEntityPacket.setOnGround(isOnGround); - moveEntityPacket.setTeleported(false); + moveEntityPacket.setTeleported(teleported); session.getUpstream().sendPacket(moveEntityPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 1766ae5b..d4732168 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -83,7 +83,7 @@ public class PlayerEntity extends LivingEntity { addPlayerPacket.setUsername(username); addPlayerPacket.setRuntimeEntityId(geyserId); addPlayerPacket.setUniqueEntityId(geyserId); - addPlayerPacket.setPosition(position); + addPlayerPacket.setPosition(position.clone().sub(0, EntityType.PLAYER.getOffset(), 0)); addPlayerPacket.setRotation(getBedrockRotation()); addPlayerPacket.setMotion(motion); addPlayerPacket.setHand(hand); @@ -130,7 +130,7 @@ public class PlayerEntity extends LivingEntity { } @Override - public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround) { + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { setPosition(position); setRotation(rotation); @@ -139,7 +139,11 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setPosition(this.position); movePlayerPacket.setRotation(getBedrockRotation()); movePlayerPacket.setOnGround(isOnGround); - movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); + movePlayerPacket.setMode(teleported ? MovePlayerPacket.Mode.TELEPORT : MovePlayerPacket.Mode.NORMAL); + + if (teleported) { + movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.UNKNOWN); + } session.getUpstream().sendPacket(movePlayerPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 95c8c030..186576e1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -30,8 +30,9 @@ import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsExcepti import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; +import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; @@ -83,8 +84,10 @@ public class GeyserSession implements CommandSender { private final UpstreamSession upstream; private RemoteServer remoteServer; private Client downstream; - @Setter private AuthData authData; - @Setter private BedrockClientData clientData; + @Setter + private AuthData authData; + @Setter + private BedrockClientData clientData; private PlayerEntity playerEntity; private PlayerInventory inventory; @@ -94,6 +97,8 @@ public class GeyserSession implements CommandSender { private InventoryCache inventoryCache; private ScoreboardCache scoreboardCache; private WindowCache windowCache; + @Setter + private TeleportCache teleportCache; private DataCache javaPacketCache; @@ -439,4 +444,19 @@ public class GeyserSession implements CommandSender { // startGamePacket.setMovementServerAuthoritative(true); upstream.sendPacket(startGamePacket); } + + public boolean confirmTeleport(Vector3f position) { + if (teleportCache != null) { + if (!teleportCache.canConfirm(position)) { + GeyserConnector.getInstance().getLogger().debug("Unconfirmed Teleport " + teleportCache.getTeleportConfirmId() + + " Ignore movement " + position + " expected " + teleportCache); + return false; + } + int teleportId = teleportCache.getTeleportConfirmId(); + teleportCache = null; + ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(teleportId); + getDownstream().getSession().send(teleportConfirmPacket); + } + return true; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java new file mode 100644 index 00000000..55b7e6fa --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.session.cache; + +import com.nukkitx.math.vector.Vector3f; +import lombok.AllArgsConstructor; +import lombok.Data; + +@AllArgsConstructor +@Data +public class TeleportCache { + + private static final double ERROR = 0.2; + private static final double ERROR_Y = 0.5; + + private double x, y, z; + private int teleportConfirmId; + + public boolean canConfirm(Vector3f position) { + return (Math.abs(this.x - position.getX()) < ERROR && + Math.abs(this.y - position.getY()) < ERROR_Y && + Math.abs(this.z - position.getZ()) < ERROR); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java index 0ae3d88a..be158746 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java @@ -34,7 +34,6 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; -import com.nukkitx.math.GenericMath; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; @@ -59,23 +58,31 @@ public class BedrockMovePlayerTranslator extends PacketTranslator { @Override public void translate(ServerPlayerPositionRotationPacket packet, GeyserSession session) { - Entity entity = session.getPlayerEntity(); + PlayerEntity entity = session.getPlayerEntity(); if (entity == null) return; @@ -94,18 +94,21 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator 1.5 || (yDis < 1.45 || yDis > (session.isJumping() ? 4.3 : (session.isSprinting() ? 2.5 : 1.9))) || zDis > 1.5) { - entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), true); + session.setTeleportCache(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getTeleportId())); + entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), true, true); + } else { + ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(packet.getTeleportId()); + session.getDownstream().getSession().send(teleportConfirmPacket); } } - - ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(packet.getTeleportId()); - session.getDownstream().getSession().send(teleportConfirmPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java index 331eb094..e01b95e9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java @@ -25,23 +25,21 @@ package org.geysermc.connector.network.translators.java.entity.spawn; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; +import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.PlayerEntity; -import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.SkinUtils; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; -import com.nukkitx.math.vector.Vector3f; - @Translator(packet = ServerSpawnPlayerPacket.class) public class JavaSpawnPlayerTranslator extends PacketTranslator { @Override public void translate(ServerSpawnPlayerPacket packet, GeyserSession session) { - Vector3f position = Vector3f.from(packet.getX(), packet.getY() - EntityType.PLAYER.getOffset(), packet.getZ()); + Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getYaw()); PlayerEntity entity = session.getEntityCache().getPlayerEntity(packet.getUuid());