forked from GeyserMC/Geyser
Handle player teleports properly (#389)
* Handle player teleports properly Co-authored-by: ForceUpdate1 <mneuhaus44@gmail.com> * impl teleport cache * impl teleport cache * removed debugs * Cleanup Co-authored-by: ForceUpdate1 <mneuhaus44@gmail.com>
This commit is contained in:
parent
82433f8078
commit
bea070395f
8 changed files with 114 additions and 35 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<Packet> 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;
|
||||
}
|
||||
}
|
||||
|
|
47
connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java
vendored
Normal file
47
connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java
vendored
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<MovePlayerPack
|
|||
return;
|
||||
}
|
||||
|
||||
// We need to parse the float as a string since casting a float to a double causes us to
|
||||
// lose precision and thus, causes players to get stuck when walking near walls
|
||||
double javaY = packet.getPosition().getY() - EntityType.PLAYER.getOffset();
|
||||
if (packet.isOnGround()) javaY = Math.ceil(javaY * 2) / 2;
|
||||
|
||||
Vector3f position = Vector3f.from(Double.parseDouble(Float.toString(packet.getPosition().getX())), javaY,
|
||||
Double.parseDouble(Float.toString(packet.getPosition().getZ())));
|
||||
|
||||
if(!session.confirmTeleport(position)){
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) {
|
||||
session.getConnector().getLogger().debug("Recalculating position...");
|
||||
recalculatePosition(session, entity, entity.getPosition());
|
||||
return;
|
||||
}
|
||||
|
||||
double javaY = packet.getPosition().getY() - EntityType.PLAYER.getOffset();
|
||||
if (packet.isOnGround()) javaY = Math.ceil(javaY * 2) / 2;
|
||||
// We need to parse the float as a string since casting a float to a double causes us to
|
||||
// lose precision and thus, causes players to get stuck when walking near walls
|
||||
ClientPlayerPositionRotationPacket playerPositionRotationPacket = new ClientPlayerPositionRotationPacket(
|
||||
packet.isOnGround(), Double.parseDouble(Float.toString(packet.getPosition().getX())), javaY, Double.parseDouble(Float.toString(packet.getPosition().getZ())), packet.getRotation().getY(), packet.getRotation().getX()
|
||||
packet.isOnGround(), position.getX(), position.getY(), position.getZ(), packet.getRotation().getY(), packet.getRotation().getX()
|
||||
);
|
||||
|
||||
// head yaw, pitch, head yaw
|
||||
Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
|
||||
entity.setPosition(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0));
|
||||
entity.setPosition(position);
|
||||
entity.setRotation(rotation);
|
||||
|
||||
/*
|
||||
|
|
|
@ -44,6 +44,6 @@ public class JavaEntityTeleportTranslator extends PacketTranslator<ServerEntityT
|
|||
}
|
||||
if (entity == null) return;
|
||||
|
||||
entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), packet.isOnGround());
|
||||
entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), packet.isOnGround(), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
|
||||
package org.geysermc.connector.network.translators.java.entity.player;
|
||||
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
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.ChunkUtils;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
|
@ -40,13 +33,20 @@ import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
|||
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
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.session.cache.TeleportCache;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.utils.ChunkUtils;
|
||||
|
||||
@Translator(packet = ServerPlayerPositionRotationPacket.class)
|
||||
public class JavaPlayerPositionRotationTranslator extends PacketTranslator<ServerPlayerPositionRotationPacket> {
|
||||
|
||||
@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<Serve
|
|||
}
|
||||
|
||||
session.setSpawned(true);
|
||||
|
||||
if (!packet.getRelative().isEmpty()) {
|
||||
session.setTeleportCache(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getTeleportId()));
|
||||
entity.moveRelative(session, packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ(), packet.getYaw(), packet.getPitch(), true);
|
||||
} else {
|
||||
double xDis = Math.abs(entity.getPosition().getX() - packet.getX());
|
||||
double yDis = entity.getPosition().getY() - packet.getY();
|
||||
double zDis = Math.abs(entity.getPosition().getZ() - packet.getZ());
|
||||
if (xDis > 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ServerSpawnPlayerPacket> {
|
||||
|
||||
@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());
|
||||
|
|
Loading…
Reference in a new issue