Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-03 14:50:19 +01:00
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
Dieser Commit ist enthalten in:
Ursprung
3e0d898b6a
Commit
69d4d9f0d6
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren