Send position update every 3 seconds if idle (#1421)

* Send position update every 3 seconds if idle

Prevents timeouts in certain instances when AFK.

* Cancel position sending on dimension switching

* Remove debug lines

* Create function to centralize movement translation
This commit is contained in:
Camotoy 2020-11-02 16:04:08 -05:00 committed by GitHub
parent 3e0d898b6a
commit 69d4d9f0d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 11 deletions

View file

@ -221,6 +221,12 @@ public class GeyserSession implements CommandSender {
@Setter @Setter
private ScheduledFuture<?> bucketScheduledFuture; private ScheduledFuture<?> bucketScheduledFuture;
/**
* Sends a movement packet every three seconds if the player hasn't moved. Prevents timeouts when AFK in certain instances.
*/
@Setter
private ScheduledFuture<?> movementSendIfIdle;
private boolean reducedDebugInfo = false; private boolean reducedDebugInfo = false;
@Setter @Setter

View file

@ -25,7 +25,13 @@
package org.geysermc.connector.network.translators.bedrock.entity.player; package org.geysermc.connector.network.translators.bedrock.entity.player;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
import com.nukkitx.math.vector.Vector3d; import com.nukkitx.math.vector.Vector3d;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.entity.PlayerEntity;
@ -34,11 +40,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translator;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; import java.util.concurrent.TimeUnit;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
@Translator(packet = MovePlayerPacket.class) @Translator(packet = MovePlayerPacket.class)
public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPacket> { public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPacket> {
@ -59,13 +61,11 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
return; return;
} }
// We need to parse the float as a string since casting a float to a double causes us to if (session.getMovementSendIfIdle() != null) {
// lose precision and thus, causes players to get stuck when walking near walls session.getMovementSendIfIdle().cancel(true);
double javaY = packet.getPosition().getY() - EntityType.PLAYER.getOffset(); }
if (packet.isOnGround()) javaY = Math.ceil(javaY * 2) / 2;
Vector3d position = Vector3d.from(Double.parseDouble(Float.toString(packet.getPosition().getX())), javaY, Vector3d position = adjustBedrockPosition(packet.getPosition(), packet.isOnGround());
Double.parseDouble(Float.toString(packet.getPosition().getZ())));
if(!session.confirmTeleport(position)){ if(!session.confirmTeleport(position)){
return; return;
@ -106,6 +106,28 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
if (!colliding) if (!colliding)
*/ */
session.sendDownstreamPacket(playerPositionRotationPacket); session.sendDownstreamPacket(playerPositionRotationPacket);
// Schedule a position send loop if the player is idle
session.setMovementSendIfIdle(session.getConnector().getGeneralThreadPool().schedule(() -> sendPositionIfIdle(session),
3, TimeUnit.SECONDS));
}
/**
* Adjust the Bedrock position before sending to the Java server to account for inaccuracies in movement between
* the two versions.
*
* @param position the current Bedrock position of the client
* @param onGround whether the Bedrock player is on the ground
* @return the position to send to the Java server.
*/
private Vector3d adjustBedrockPosition(Vector3f position, boolean onGround) {
// 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 = position.getY() - EntityType.PLAYER.getOffset();
if (onGround) javaY = Math.ceil(javaY * 2) / 2;
return Vector3d.from(Double.parseDouble(Float.toString(position.getX())), javaY,
Double.parseDouble(Float.toString(position.getZ())));
} }
public boolean isValidMove(GeyserSession session, MovePlayerPacket.Mode mode, Vector3f currentPosition, Vector3f newPosition) { public boolean isValidMove(GeyserSession session, MovePlayerPacket.Mode mode, Vector3f currentPosition, Vector3f newPosition) {
@ -147,4 +169,16 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN); movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
session.sendUpstreamPacket(movePlayerPacket); session.sendUpstreamPacket(movePlayerPacket);
} }
private void sendPositionIfIdle(GeyserSession session) {
if (session.isClosed()) return;
PlayerEntity entity = session.getPlayerEntity();
// Recalculate in case something else changed position
Vector3d position = adjustBedrockPosition(entity.getPosition(), entity.isOnGround());
ClientPlayerPositionPacket packet = new ClientPlayerPositionPacket(session.getPlayerEntity().isOnGround(),
position.getX(), position.getY(), position.getZ());
session.sendDownstreamPacket(packet);
session.setMovementSendIfIdle(session.getConnector().getGeneralThreadPool().schedule(() -> sendPositionIfIdle(session),
3, TimeUnit.SECONDS));
}
} }

View file

@ -52,6 +52,10 @@ public class DimensionUtils {
if (javaDimension.equals(player.getDimension())) if (javaDimension.equals(player.getDimension()))
return; return;
if (session.getMovementSendIfIdle() != null) {
session.getMovementSendIfIdle().cancel(true);
}
session.getEntityCache().removeAllEntities(); session.getEntityCache().removeAllEntities();
session.getItemFrameCache().clear(); session.getItemFrameCache().clear();
if (session.getPendingDimSwitches().getAndIncrement() > 0) { if (session.getPendingDimSwitches().getAndIncrement() > 0) {