From f6f8886f2300f3d01e836e17150196e33bbcebcf Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 13 Jul 2022 21:31:10 -0400 Subject: [PATCH] Fix PS4 players crashing on certain dimension switches --- .../geysermc/geyser/session/GeyserSession.java | 2 +- .../geysermc/geyser/session/cache/TagCache.java | 6 +++--- .../inventory/MerchantInventoryTranslator.java | 2 +- .../player/JavaPlayerPositionTranslator.java | 10 ++++++++++ .../geysermc/geyser/util/DimensionUtils.java | 17 +++++++++++++++++ 5 files changed, 32 insertions(+), 5 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 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();