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 3dd763546..519eef3b5 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -392,7 +392,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
* Whether to work around 1.13's different behavior in villager trading menus.
*/
@Setter
- private boolean emulatePost1_14Logic = true;
+ private boolean emulatePost1_13Logic = true;
/**
* Starting in 1.17, Java servers expect the carriedItem
parameter of the serverbound click container
* packet to be the current contents of the mouse after the transaction has been done. 1.16 expects the clicked slot
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
index 7db01e655..ac0c93204 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
@@ -101,10 +101,10 @@ public class TagCache {
this.smallFlowers = IntList.of(itemTags.get("minecraft:small_flowers"));
// Hack btw
- boolean emulatePost1_14Logic = itemTags.get("minecraft:signs").length > 1;
- session.setEmulatePost1_14Logic(emulatePost1_14Logic);
+ boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1;
+ session.setEmulatePost1_13Logic(emulatePost1_13Logic);
if (logger.isDebug()) {
- logger.debug("Emulating post 1.14 villager logic for " + session.name() + "? " + emulatePost1_14Logic);
+ logger.debug("Emulating post 1.13 villager logic for " + session.name() + "? " + emulatePost1_13Logic);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
index 061f6c5ea..031fb606e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/MerchantInventoryTranslator.java
@@ -159,7 +159,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
ServerboundSelectTradePacket packet = new ServerboundSelectTradePacket(tradeChoice);
session.sendDownstreamPacket(packet);
- if (session.isEmulatePost1_14Logic()) {
+ if (session.isEmulatePost1_13Logic()) {
// 1.18 Java cooperates nicer than older versions
if (inventory instanceof MerchantContainer merchantInventory) {
merchantInventory.onTradeSelected(session, tradeChoice);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
index f5d21ecc9..2d2d7279f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java
@@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.Serverb
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
+import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
@@ -84,6 +85,15 @@ public class JavaPlayerPositionTranslator extends PacketTranslator 47 && !session.isEmulatePost1_13Logic()) {
+ // See DimensionUtils for an explanation
+ ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
+ chunkRadiusUpdatedPacket.setRadius(session.getServerRenderDistance());
+ session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
+
+ session.setLastChunkPosition(null);
+ }
+
ChunkUtils.updateChunkPosition(session, pos.toInt());
if (session.getGeyser().getConfig().isDebugMode()) {
diff --git a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
index fbc891131..7e5d65a97 100644
--- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.util;
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.ChangeDimensionPacket;
+import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
import com.nukkitx.protocol.bedrock.packet.MobEffectPacket;
import com.nukkitx.protocol.bedrock.packet.StopSoundPacket;
import org.geysermc.geyser.entity.type.Entity;
@@ -69,6 +70,22 @@ public class DimensionUtils {
session.getPistonCache().clear();
session.getSkullCache().clear();
+ if (session.getServerRenderDistance() > 47 && !session.isEmulatePost1_13Logic()) {
+ // The server-sided view distance wasn't a thing until Minecraft Java 1.14
+ // So ViaVersion compensates by sending a "view distance" of 64
+ // That's fine, except when the actual view distance sent from the server is five chunks
+ // The client locks up when switching dimensions, expecting more chunks than it's getting
+ // To solve this, we cap at 32 unless we know that the render distance actually exceeds 32
+ // 47 is the Bedrock equivalent of 32
+ // Also, as of 1.19: PS4 crashes with a ChunkRadiusUpdatedPacket too large
+ session.getGeyser().getLogger().debug("Applying dimension switching workaround for Bedrock render distance of "
+ + session.getServerRenderDistance());
+ ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
+ chunkRadiusUpdatedPacket.setRadius(47);
+ session.sendUpstreamPacket(chunkRadiusUpdatedPacket);
+ // Will be re-adjusted on spawn
+ }
+
Vector3f pos = Vector3f.from(0, Short.MAX_VALUE, 0);
ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket();