From 758700cb2271ed54a3890bcdaac9c3c3db04f7a9 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 27 Feb 2025 20:11:16 +0100 Subject: [PATCH] Fix render distance issues (#5381) * Potentially fix render distance issues * AGGRESSIVE fix render distance issues --------- Co-authored-by: Camotoy <20743703+Camotoy@users.noreply.github.com> --- .../geyser/session/GeyserSession.java | 21 ++++++++++++++++++- .../org/geysermc/geyser/util/ChunkUtils.java | 9 +++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 96f553e2049..f303ae3ce04 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -341,7 +341,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private Vector2i lastChunkPosition = null; - @Setter private int clientRenderDistance = -1; private int serverRenderDistance = -1; @@ -1453,11 +1452,31 @@ public void sendCommand(String command) { sendDownstreamGamePacket(new ServerboundChatCommandSignedPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet())); } + public void setClientRenderDistance(int clientRenderDistance) { + boolean oldSquareToCircle = this.clientRenderDistance < this.serverRenderDistance; + this.clientRenderDistance = clientRenderDistance; + boolean newSquareToCircle = this.clientRenderDistance < this.serverRenderDistance; + + if (this.serverRenderDistance != -1 && oldSquareToCircle != newSquareToCircle) { + recalculateBedrockRenderDistance(); + } + } + public void setServerRenderDistance(int renderDistance) { // Ensure render distance is not above 96 as sending a larger value at any point crashes mobile clients and 96 is the max of any bedrock platform renderDistance = Math.min(renderDistance, 96); this.serverRenderDistance = renderDistance; + recalculateBedrockRenderDistance(); + } + + /** + * Ensures that the ChunkRadiusUpdatedPacket uses the correct render distance for whatever the client distance is set as. + * If the server render distance is larger than the client's, then account for this and add some extra padding. + * We don't want to apply this for every render distance, if at all possible, because + */ + private void recalculateBedrockRenderDistance() { + int renderDistance = ChunkUtils.squareToCircle(this.serverRenderDistance); ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket(); chunkRadiusUpdatedPacket.setRadius(renderDistance); upstream.sendPacket(chunkRadiusUpdatedPacket); diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index 96471a2cec0..cb149426d7d 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -99,13 +99,20 @@ public static void updateChunkPosition(GeyserSession session, Vector3i position) chunkPublisherUpdatePacket.setPosition(position); // Mitigates chunks not loading on 1.17.1 Paper and 1.19.3 Fabric. As of Bedrock 1.19.60. // https://github.com/GeyserMC/Geyser/issues/3490 - chunkPublisherUpdatePacket.setRadius(GenericMath.ceil((session.getServerRenderDistance() + 1) * MathUtils.SQRT_OF_TWO) << 4); + chunkPublisherUpdatePacket.setRadius(squareToCircle(session.getServerRenderDistance()) << 4); session.sendUpstreamPacket(chunkPublisherUpdatePacket); session.setLastChunkPosition(newChunkPos); } } + /** + * Converts a Java render distance number to the equivalent in Bedrock. + */ + public static int squareToCircle(int renderDistance) { + return GenericMath.ceil((renderDistance + 1) * MathUtils.SQRT_OF_TWO); + } + /** * Sends a block update to the Bedrock client. If the platform is not Spigot, this also * adds that block to the cache.