diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java index f5bc250c8..4fa746444 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import lombok.Getter; import lombok.Setter; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockStateValues; @@ -44,6 +45,13 @@ public class ChunkCache { @Setter private int heightY; + /** + * Whether the Bedrock client believes they are in a world with a minimum of -64 and maximum of 320 + */ + @Getter + @Setter + private boolean isExtendedHeight = false; + public ChunkCache(GeyserSession session) { this.cache = !session.getConnector().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing chunks = cache ? new Long2ObjectOpenHashMap<>() : null; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java index 904a6cc62..8d3ca2f23 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java @@ -44,12 +44,12 @@ import org.geysermc.connector.network.translators.Translator; @Translator(packet = MovePlayerPacket.class) public class BedrockMovePlayerTranslator extends PacketTranslator { /* The upper and lower bounds to check for the void floor that only exists in Bedrock */ - private static final int BEDROCK_VOID_FLOOR_UPPER_Y; - private static final int BEDROCK_VOID_FLOOR_LOWER_Y; + private static final int BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y; + private static final int BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y; static { - BEDROCK_VOID_FLOOR_LOWER_Y = GeyserConnector.getInstance().getConfig().isExtendedWorldHeight() ? -104 : -40; - BEDROCK_VOID_FLOOR_UPPER_Y = BEDROCK_VOID_FLOOR_LOWER_Y + 2; + BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y = GeyserConnector.getInstance().getConfig().isExtendedWorldHeight() ? -104 : -40; + BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y = BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y + 2; } @Override @@ -117,10 +117,11 @@ public class BedrockMovePlayerTranslator extends PacketTranslator= BEDROCK_VOID_FLOOR_UPPER_Y) { - // Work around there being a floor at Y -40 and teleport the player below it + boolean overworld = session.getChunkCache().isExtendedHeight(); + if (floorY <= (overworld ? BEDROCK_OVERWORLD_VOID_FLOOR_LOWER_Y : -38) + && floorY >= (overworld ? BEDROCK_OVERWORLD_VOID_FLOOR_UPPER_Y : -40)) { + // Work around there being a floor at Y -40 (Y - and teleport the player below it // Moving from below Y -40 to above the void floor works fine - //TODO: This will need to be changed for 1.17 entity.setPosition(entity.getPosition().sub(0, 4f, 0)); MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index 53ebd92ff..6b5f63438 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -55,8 +55,6 @@ public class JavaJoinGameTranslator extends PacketTranslator session.setThunder(false); } - ChunkUtils.applyDimensionHeight(session, packet.getDimension()); - String newDimension = DimensionUtils.getNewDimension(packet.getDimension()); if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) { // Switching to a new world (based off the world name change); send a fake dimension change @@ -93,5 +91,7 @@ public class JavaRespawnTranslator extends PacketTranslator session.setWorldName(packet.getWorldName()); DimensionUtils.switchDimension(session, newDimension); } + + ChunkUtils.applyDimensionHeight(session, packet.getDimension()); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 912d0e8ee..1ca18c4ac 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -123,7 +123,7 @@ public class ChunkUtils { BitSet waterloggedPaletteIds = new BitSet(); BitSet pistonOrFlowerPaletteIds = new BitSet(); - boolean overworld = session.getDimension().equals(DimensionUtils.OVERWORLD); + boolean overworld = session.getChunkCache().isExtendedHeight(); for (int sectionY = 0; sectionY < javaSections.length; sectionY++) { if (yOffset < ((overworld ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) >> 4) && sectionY < -yOffset) { @@ -434,7 +434,8 @@ public class ChunkUtils { } /** - * Process the minimum and maximum heights for this dimension + * Process the minimum and maximum heights for this dimension. + * This must be done after the player has switched dimensions so we know what their dimension is */ public static void applyDimensionHeight(GeyserSession session, CompoundTag dimensionTag) { int minY = ((IntTag) dimensionTag.get("min_y")).getValue(); @@ -448,7 +449,10 @@ public class ChunkUtils { throw new RuntimeException("Maximum Y must be a multiple of 16!"); } - if (minY < MINIMUM_ACCEPTED_HEIGHT || maxY > MAXIMUM_ACCEPTED_HEIGHT) { + session.getChunkCache().setExtendedHeight(DimensionUtils.javaToBedrock(session.getDimension()) == 0 && session.getConnector().getConfig().isExtendedWorldHeight()); + + if (minY < (session.getChunkCache().isExtendedHeight() ? MINIMUM_ACCEPTED_HEIGHT_OVERWORLD : MINIMUM_ACCEPTED_HEIGHT) + || maxY > (session.getChunkCache().isExtendedHeight() ? MAXIMUM_ACCEPTED_HEIGHT_OVERWORLD : MAXIMUM_ACCEPTED_HEIGHT)) { session.getConnector().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds")); }