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
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;
@Setter

View File

@ -25,7 +25,13 @@
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.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.entity.Entity;
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.Translator;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
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 java.util.concurrent.TimeUnit;
@Translator(packet = MovePlayerPacket.class)
public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPacket> {
@ -59,13 +61,11 @@ 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;
if (session.getMovementSendIfIdle() != null) {
session.getMovementSendIfIdle().cancel(true);
}
Vector3d position = Vector3d.from(Double.parseDouble(Float.toString(packet.getPosition().getX())), javaY,
Double.parseDouble(Float.toString(packet.getPosition().getZ())));
Vector3d position = adjustBedrockPosition(packet.getPosition(), packet.isOnGround());
if(!session.confirmTeleport(position)){
return;
@ -106,6 +106,28 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
if (!colliding)
*/
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) {
@ -147,4 +169,16 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
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()))
return;
if (session.getMovementSendIfIdle() != null) {
session.getMovementSendIfIdle().cancel(true);
}
session.getEntityCache().removeAllEntities();
session.getItemFrameCache().clear();
if (session.getPendingDimSwitches().getAndIncrement() > 0) {