From c5a34f83a8b9bab1cadf21b38537a3985a92681d Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:33:19 +0200 Subject: [PATCH 1/7] Add support for extended world height --- .../geyser/level/BedrockDimension.java | 18 ++++++++--- .../geyser/session/GeyserSession.java | 20 +++++++++++- .../geysermc/geyser/util/DimensionUtils.java | 32 ++++++++----------- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java index 250c0f7a451..074ec76f6f1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java @@ -34,8 +34,18 @@ * @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest. * @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's. */ -public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn) { - public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true); - public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false); - public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true); +public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn, int bedrockId) { + + public static final int OVERWORLD_ID = 0; + public static final int DEFAULT_NETHER_ID = 1; + public static final int END_ID = 2; + + public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true, OVERWORLD_ID); + public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false, DEFAULT_NETHER_ID); + public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true, END_ID); + + public int maxY() { + return minY + height; + } + } 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 607a58e0b88..691875db864 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -72,6 +72,7 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType; +import org.cloudburstmc.protocol.bedrock.data.definitions.DimensionDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.AvailableEntityIdentifiersPacket; @@ -82,6 +83,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ClientboundCloseFormPacket; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket; +import org.cloudburstmc.protocol.bedrock.packet.DimensionDataPacket; import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket; import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket; @@ -383,6 +385,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private boolean sprinting; + /** + * The overworld dimension which Bedrock Edition uses. + */ + @Getter + private BedrockDimension bedrockOverworldDimension = BedrockDimension.OVERWORLD; /** * The dimension of the player. * As all entities are in the same world, this can be safely applied to all other entities. @@ -396,7 +403,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * right before the StartGamePacket is sent. */ @Setter - private BedrockDimension bedrockDimension = BedrockDimension.OVERWORLD; + private BedrockDimension bedrockDimension = this.bedrockOverworldDimension; @Setter private int breakingBlock; @@ -706,6 +713,17 @@ public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSessio * Send all necessary packets to load Bedrock into the server */ public void connect() { + if (this.dimensionType.minY() < BedrockDimension.OVERWORLD.minY() || this.dimensionType.maxY() > BedrockDimension.OVERWORLD.maxY()) { + final int minY = Math.max(this.dimensionType.minY(), -512); + final int maxY = Math.min(this.dimensionType.maxY(), 512); + this.bedrockOverworldDimension = new BedrockDimension(minY, maxY - minY, true, BedrockDimension.OVERWORLD_ID); + this.bedrockDimension = this.bedrockOverworldDimension; + + final DimensionDataPacket dimensionDataPacket = new DimensionDataPacket(); + dimensionDataPacket.getDefinitions().add(new DimensionDefinition("minecraft:overworld", maxY, minY, 5)); + upstream.sendPacket(dimensionDataPacket); + } + startGame(); sentSpawnPacket = true; syncEntityProperties(); 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 f043631b67d..a48a85a0e12 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -53,10 +53,6 @@ public class DimensionUtils { public static final String NETHER_IDENTIFIER = "minecraft:the_nether"; - private static final int BEDROCK_OVERWORLD_ID = 0; - private static final int BEDROCK_DEFAULT_NETHER_ID = 1; - private static final int BEDROCK_END_ID = 2; - public static void switchDimension(GeyserSession session, JavaDimension javaDimension) { switchDimension(session, javaDimension, javaDimension.bedrockId()); } @@ -180,19 +176,17 @@ private static void finalizeDimensionSwitch(GeyserSession session, Entity player public static void setBedrockDimension(GeyserSession session, int bedrockDimension) { session.setBedrockDimension(switch (bedrockDimension) { - case BEDROCK_END_ID -> BedrockDimension.THE_END; - case BEDROCK_DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled. - default -> BedrockDimension.OVERWORLD; + case BedrockDimension.END_ID -> BedrockDimension.THE_END; + case BedrockDimension.DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled. + default -> session.getBedrockOverworldDimension(); }); } public static int javaToBedrock(BedrockDimension dimension) { - if (dimension == BedrockDimension.THE_NETHER) { + if (dimension.bedrockId() == BedrockDimension.DEFAULT_NETHER_ID) { return BEDROCK_NETHER_ID; - } else if (dimension == BedrockDimension.THE_END) { - return BEDROCK_END_ID; - } else { - return BEDROCK_OVERWORLD_ID; + } else { + return dimension.bedrockId(); } } @@ -205,8 +199,8 @@ public static int javaToBedrock(BedrockDimension dimension) { public static int javaToBedrock(String javaDimension) { return switch (javaDimension) { case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID; - case "minecraft:the_end" -> 2; - default -> 0; + case "minecraft:the_end" -> BedrockDimension.END_ID; + default -> BedrockDimension.OVERWORLD_ID; }; } @@ -216,7 +210,7 @@ public static int javaToBedrock(String javaDimension) { public static int javaToBedrock(GeyserSession session) { JavaDimension dimension = session.getDimensionType(); if (dimension == null) { - return BEDROCK_OVERWORLD_ID; + return BedrockDimension.OVERWORLD_ID; } return dimension.bedrockId(); } @@ -229,7 +223,7 @@ public static int javaToBedrock(GeyserSession session) { */ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { // Change dimension ID to the End to allow for building above Bedrock - BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BEDROCK_END_ID : BEDROCK_DEFAULT_NETHER_ID; + BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BedrockDimension.END_ID : BedrockDimension.DEFAULT_NETHER_ID; } /** @@ -243,14 +237,14 @@ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { public static int getTemporaryDimension(int currentBedrockDimension, int newBedrockDimension) { if (isCustomBedrockNetherId()) { // Prevents rare instances of Bedrock locking up - return newBedrockDimension == BEDROCK_END_ID ? BEDROCK_OVERWORLD_ID : BEDROCK_END_ID; + return newBedrockDimension == BedrockDimension.END_ID ? BedrockDimension.OVERWORLD_ID : BedrockDimension.END_ID; } // Check current Bedrock dimension and not just the Java dimension. // Fixes rare instances like https://github.com/GeyserMC/Geyser/issues/3161 - return currentBedrockDimension == BEDROCK_OVERWORLD_ID ? BEDROCK_DEFAULT_NETHER_ID : BEDROCK_OVERWORLD_ID; + return currentBedrockDimension == BedrockDimension.OVERWORLD_ID ? BedrockDimension.DEFAULT_NETHER_ID : BedrockDimension.OVERWORLD_ID; } public static boolean isCustomBedrockNetherId() { - return BEDROCK_NETHER_ID == BEDROCK_END_ID; + return BEDROCK_NETHER_ID == BedrockDimension.END_ID; } } From 98df97e86333816ef1ac12ffea80c4fd33b65395 Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Wed, 28 Aug 2024 00:36:58 +0200 Subject: [PATCH 2/7] Log if world height is extended --- .../src/main/java/org/geysermc/geyser/session/GeyserSession.java | 1 + 1 file changed, 1 insertion(+) 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 691875db864..ac7be8f2d3a 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -718,6 +718,7 @@ public void connect() { final int maxY = Math.min(this.dimensionType.maxY(), 512); this.bedrockOverworldDimension = new BedrockDimension(minY, maxY - minY, true, BedrockDimension.OVERWORLD_ID); this.bedrockDimension = this.bedrockOverworldDimension; + geyser.getLogger().debug("Extending overworld dimension to " + minY + " - " + maxY); final DimensionDataPacket dimensionDataPacket = new DimensionDataPacket(); dimensionDataPacket.getDefinitions().add(new DimensionDefinition("minecraft:overworld", maxY, minY, 5)); From 6b2f315230d34050d3a54a1f3d59fc37fef43815 Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Wed, 28 Aug 2024 23:12:03 +0200 Subject: [PATCH 3/7] Improve code --- .../java/org/geysermc/geyser/GeyserImpl.java | 4 +- .../geyser/level/BedrockDimension.java | 71 +++++++++++++++++-- .../geysermc/geyser/level/JavaDimension.java | 11 ++- .../geyser/session/GeyserSession.java | 13 ++-- .../protocol/java/JavaLoginTranslator.java | 7 +- .../JavaLevelChunkWithLightTranslator.java | 10 ++- .../org/geysermc/geyser/util/ChunkUtils.java | 9 +-- .../geysermc/geyser/util/DimensionUtils.java | 33 +-------- 8 files changed, 97 insertions(+), 61 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 8febf4d2179..8cdd6120dee 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -76,6 +76,7 @@ import org.geysermc.geyser.event.GeyserEventBus; import org.geysermc.geyser.extension.GeyserExtensionManager; import org.geysermc.geyser.impl.MinecraftVersionImpl; +import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.GeyserServer; @@ -95,7 +96,6 @@ import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.CooldownUtils; -import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.Metrics; import org.geysermc.geyser.util.MinecraftAuthLogger; import org.geysermc.geyser.util.NewsHandler; @@ -421,7 +421,7 @@ private void startInstance() { } CooldownUtils.setDefaultShowCooldown(config.getShowCooldown()); - DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether + BedrockDimension.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads"); if (bedrockThreadCount == null) { diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java index 074ec76f6f1..d46debb13ae 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java @@ -25,27 +25,86 @@ package org.geysermc.geyser.level; +import lombok.EqualsAndHashCode; +import lombok.ToString; + /** * A data structure to represent what Bedrock believes are the height requirements for a specific dimension. * As of 1.18.30, biome count is representative of the height of the world, and out-of-bounds chunks can crash * the client. - * - * @param minY The minimum height Bedrock Edition will accept. - * @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest. - * @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's. */ -public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn, int bedrockId) { +@ToString +@EqualsAndHashCode +public class BedrockDimension { public static final int OVERWORLD_ID = 0; public static final int DEFAULT_NETHER_ID = 1; public static final int END_ID = 2; + // Changes if the above-bedrock Nether building workaround is applied + public static int BEDROCK_NETHER_ID = DEFAULT_NETHER_ID; + public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true, OVERWORLD_ID); - public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false, DEFAULT_NETHER_ID); + public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false, -1) { + @Override + public int bedrockId() { + return BEDROCK_NETHER_ID; + } + }; public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true, END_ID); + public static final String NETHER_IDENTIFIER = "minecraft:the_nether"; + + private final int minY; + private final int height; + private final boolean doUpperHeightWarn; + private final int bedrockId; + + /** + * @param minY The minimum height Bedrock Edition will accept. + * @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest. + * @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's. + * @param bedrockId the Bedrock dimension ID of this dimension. + */ + public BedrockDimension(int minY, int height, boolean doUpperHeightWarn, int bedrockId) { + this.minY = minY; + this.height = height; + this.doUpperHeightWarn = doUpperHeightWarn; + this.bedrockId = bedrockId; + } + + /** + * The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension. + * This workaround sets the Nether as the End dimension to ignore this limit. + * + * @param isAboveNetherBedrockBuilding true if we should apply The End workaround + */ + public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { + // Change dimension ID to the End to allow for building above Bedrock + BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? END_ID : DEFAULT_NETHER_ID; + } + + public static boolean isCustomBedrockNetherId() { + return BEDROCK_NETHER_ID == END_ID; + } public int maxY() { return minY + height; } + public int minY() { + return minY; + } + + public int height() { + return height; + } + + public boolean doUpperHeightWarn() { + return doUpperHeightWarn; + } + + public int bedrockId() { + return bedrockId; + } + } diff --git a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java index 50589851bd8..c4592517cdc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -63,12 +63,19 @@ public static JavaDimension read(RegistryEntryContext entry) { if ("minecraft".equals(id.namespace())) { String identifier = id.asString(); bedrockId = DimensionUtils.javaToBedrock(identifier); - isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(identifier); + isNetherLike = BedrockDimension.NETHER_IDENTIFIER.equals(identifier); } else { // Effects should give is a clue on how this (custom) dimension is supposed to look like String effects = dimension.getString("effects"); bedrockId = DimensionUtils.javaToBedrock(effects); - isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(effects); + isNetherLike = BedrockDimension.NETHER_IDENTIFIER.equals(effects); + } + + if (minY % 16 != 0) { + throw new RuntimeException("Minimum Y must be a multiple of 16!"); + } + if (maxY % 16 != 0) { + throw new RuntimeException("Maximum Y must be a multiple of 16!"); } return new JavaDimension(minY, maxY, piglinSafe, ultrawarm, coordinateScale, bedrockId, isNetherLike); 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 ac7be8f2d3a..29cd0fa397c 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -173,7 +173,6 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.ChunkUtils; -import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.LoginEncryptionUtils; import org.geysermc.geyser.util.MinecraftAuthLogger; @@ -713,15 +712,15 @@ public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSessio * Send all necessary packets to load Bedrock into the server */ public void connect() { - if (this.dimensionType.minY() < BedrockDimension.OVERWORLD.minY() || this.dimensionType.maxY() > BedrockDimension.OVERWORLD.maxY()) { - final int minY = Math.max(this.dimensionType.minY(), -512); - final int maxY = Math.min(this.dimensionType.maxY(), 512); + if (this.dimensionType.bedrockId() == BedrockDimension.OVERWORLD_ID && this.dimensionType.minY() < BedrockDimension.OVERWORLD.minY() || this.dimensionType.maxY() > BedrockDimension.OVERWORLD.maxY()) { + int minY = Math.max(this.dimensionType.minY(), -512); + int maxY = Math.min(this.dimensionType.maxY(), 512); this.bedrockOverworldDimension = new BedrockDimension(minY, maxY - minY, true, BedrockDimension.OVERWORLD_ID); this.bedrockDimension = this.bedrockOverworldDimension; geyser.getLogger().debug("Extending overworld dimension to " + minY + " - " + maxY); - final DimensionDataPacket dimensionDataPacket = new DimensionDataPacket(); - dimensionDataPacket.getDefinitions().add(new DimensionDefinition("minecraft:overworld", maxY, minY, 5)); + DimensionDataPacket dimensionDataPacket = new DimensionDataPacket(); + dimensionDataPacket.getDefinitions().add(new DimensionDefinition("minecraft:overworld", maxY, minY, 5 /* Void */)); upstream.sendPacket(dimensionDataPacket); } @@ -1597,7 +1596,7 @@ private void startGame() { startGamePacket.setRotation(Vector2f.from(1, 1)); startGamePacket.setSeed(-1L); - startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(bedrockDimension)); + startGamePacket.setDimensionId(bedrockDimension.bedrockId()); startGamePacket.setGeneratorId(1); startGamePacket.setLevelGameType(GameType.SURVIVAL); startGamePacket.setDifficulty(1); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index a6d6e6c7041..cadbf4e22e8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; +import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -68,7 +69,7 @@ public void translate(GeyserSession session, ClientboundLoginPacket packet) { // If the player is already initialized and a join game packet is sent, they // are swapping servers if (session.isSpawned()) { - int fakeDim = DimensionUtils.getTemporaryDimension(DimensionUtils.javaToBedrock(session.getBedrockDimension()), newDimension.bedrockId()); + int fakeDim = DimensionUtils.getTemporaryDimension(session.getBedrockDimension().bedrockId(), newDimension.bedrockId()); if (fakeDim != newDimension.bedrockId()) { // The player's current dimension and new dimension are the same // We want a dimension switch to clear old chunks out, so switch to a dimension that isn't the one we're currently in. @@ -127,9 +128,9 @@ public void translate(GeyserSession session, ClientboundLoginPacket packet) { } session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(register, Constants.PLUGIN_MESSAGE.getBytes(StandardCharsets.UTF_8))); - if (DimensionUtils.javaToBedrock(session.getBedrockDimension()) != newDimension.bedrockId()) { + if (session.getBedrockDimension().bedrockId() != newDimension.bedrockId()) { DimensionUtils.switchDimension(session, newDimension); - } else if (DimensionUtils.isCustomBedrockNetherId() && newDimension.isNetherLike()) { + } else if (BedrockDimension.isCustomBedrockNetherId() && newDimension.isNetherLike()) { // If the player is spawning into the "fake" nether, send them some fog session.camera().sendFog(DimensionUtils.BEDROCK_FOG_HELL); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java index 0e5d197858d..af3c8595e21 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -29,7 +29,12 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntImmutableList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntLists; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NBTOutputStream; @@ -56,7 +61,6 @@ import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.ChunkUtils; -import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.mcprotocollib.protocol.data.game.chunk.BitStorage; import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection; import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; @@ -509,7 +513,7 @@ public void translate(GeyserSession session, ClientboundLevelChunkWithLightPacke levelChunkPacket.setChunkX(packet.getX()); levelChunkPacket.setChunkZ(packet.getZ()); levelChunkPacket.setData(Unpooled.wrappedBuffer(payload)); - levelChunkPacket.setDimension(DimensionUtils.javaToBedrock(session.getBedrockDimension())); + levelChunkPacket.setDimension(session.getBedrockDimension().bedrockId()); session.sendUpstreamPacket(levelChunkPacket); for (Map.Entry entry : session.getItemFrameCache().entrySet()) { 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 288b425baa7..96471a2cec0 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -167,7 +167,7 @@ public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, byteBuf.readBytes(payload); LevelChunkPacket data = new LevelChunkPacket(); - data.setDimension(DimensionUtils.javaToBedrock(session.getBedrockDimension())); + data.setDimension(session.getBedrockDimension().bedrockId()); data.setChunkX(chunkX); data.setChunkZ(chunkZ); data.setSubChunksLength(0); @@ -207,13 +207,6 @@ public static void loadDimension(GeyserSession session) { int minY = dimension.minY(); int maxY = dimension.maxY(); - if (minY % 16 != 0) { - throw new RuntimeException("Minimum Y must be a multiple of 16!"); - } - if (maxY % 16 != 0) { - throw new RuntimeException("Maximum Y must be a multiple of 16!"); - } - BedrockDimension bedrockDimension = session.getBedrockDimension(); // Yell in the console if the world height is too height in the current scenario // The constraints change depending on if the player is in the overworld or not, and if experimental height is enabled 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 a48a85a0e12..9a520ed4466 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -46,13 +46,8 @@ public class DimensionUtils { - // Changes if the above-bedrock Nether building workaround is applied - private static int BEDROCK_NETHER_ID = 1; - public static final String BEDROCK_FOG_HELL = "minecraft:fog_hell"; - public static final String NETHER_IDENTIFIER = "minecraft:the_nether"; - public static void switchDimension(GeyserSession session, JavaDimension javaDimension) { switchDimension(session, javaDimension, javaDimension.bedrockId()); } @@ -103,7 +98,7 @@ public static void switchDimension(GeyserSession session, JavaDimension javaDime // If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension, // we check if the player is entering the nether and apply the nether fog to fake the fact that the client // thinks they are in the end dimension. - if (isCustomBedrockNetherId()) { + if (BedrockDimension.isCustomBedrockNetherId()) { if (javaDimension.isNetherLike()) { session.camera().sendFog(BEDROCK_FOG_HELL); } else if (previousDimension != null && previousDimension.isNetherLike()) { @@ -182,14 +177,6 @@ public static void setBedrockDimension(GeyserSession session, int bedrockDimensi }); } - public static int javaToBedrock(BedrockDimension dimension) { - if (dimension.bedrockId() == BedrockDimension.DEFAULT_NETHER_ID) { - return BEDROCK_NETHER_ID; - } else { - return dimension.bedrockId(); - } - } - /** * Map the Java edition dimension IDs to Bedrock edition * @@ -198,7 +185,7 @@ public static int javaToBedrock(BedrockDimension dimension) { */ public static int javaToBedrock(String javaDimension) { return switch (javaDimension) { - case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID; + case BedrockDimension.NETHER_IDENTIFIER -> BedrockDimension.BEDROCK_NETHER_ID; case "minecraft:the_end" -> BedrockDimension.END_ID; default -> BedrockDimension.OVERWORLD_ID; }; @@ -215,17 +202,6 @@ public static int javaToBedrock(GeyserSession session) { return dimension.bedrockId(); } - /** - * The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension. - * This workaround sets the Nether as the End dimension to ignore this limit. - * - * @param isAboveNetherBedrockBuilding true if we should apply The End workaround - */ - public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { - // Change dimension ID to the End to allow for building above Bedrock - BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BedrockDimension.END_ID : BedrockDimension.DEFAULT_NETHER_ID; - } - /** * Gets the fake, temporary dimension we send clients to so we aren't switching to the same dimension without an additional * dimension switch. @@ -235,7 +211,7 @@ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { * @return the Bedrock fake dimension to transfer to */ public static int getTemporaryDimension(int currentBedrockDimension, int newBedrockDimension) { - if (isCustomBedrockNetherId()) { + if (BedrockDimension.isCustomBedrockNetherId()) { // Prevents rare instances of Bedrock locking up return newBedrockDimension == BedrockDimension.END_ID ? BedrockDimension.OVERWORLD_ID : BedrockDimension.END_ID; } @@ -244,7 +220,4 @@ public static int getTemporaryDimension(int currentBedrockDimension, int newBedr return currentBedrockDimension == BedrockDimension.OVERWORLD_ID ? BedrockDimension.DEFAULT_NETHER_ID : BedrockDimension.OVERWORLD_ID; } - public static boolean isCustomBedrockNetherId() { - return BEDROCK_NETHER_ID == BedrockDimension.END_ID; - } } From 870e7cb78f5acfdb62756942e94059b213b0ee9b Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Wed, 25 Sep 2024 22:33:55 +0200 Subject: [PATCH 4/7] Code cleanup --- .../main/java/org/geysermc/geyser/level/BedrockDimension.java | 2 -- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 1 - 2 files changed, 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java index d46debb13ae..d62a17232f8 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockDimension.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.level; -import lombok.EqualsAndHashCode; import lombok.ToString; /** @@ -34,7 +33,6 @@ * the client. */ @ToString -@EqualsAndHashCode public class BedrockDimension { public static final int OVERWORLD_ID = 0; 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 9d3d986c71c..6db89f115c4 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,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { /** * The overworld dimension which Bedrock Edition uses. */ - @Getter private BedrockDimension bedrockOverworldDimension = BedrockDimension.OVERWORLD; /** * The dimension of the player. From e9b313bf40b7e2760782758fd08f1bd4469d1f22 Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Sat, 28 Sep 2024 22:37:05 +0200 Subject: [PATCH 5/7] Removed import --- .../geyser/translator/protocol/java/JavaLoginTranslator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index a110648a83e..fb9159c4772 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -33,7 +33,6 @@ import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; -import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.session.GeyserSession; From 29efe0f9fe1d1d0a6af57c28f92f7f0350dc8f8b Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Sun, 29 Sep 2024 20:54:07 +0200 Subject: [PATCH 6/7] Get the highest dimension out of all possible dimensions --- .../geyser/session/GeyserSession.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 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 6db89f115c4..262137f49d7 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -716,11 +716,23 @@ public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSessio * Send all necessary packets to load Bedrock into the server */ public void connect() { - if (this.dimensionType.bedrockId() == BedrockDimension.OVERWORLD_ID && this.dimensionType.minY() < BedrockDimension.OVERWORLD.minY() || this.dimensionType.maxY() > BedrockDimension.OVERWORLD.maxY()) { - int minY = Math.max(this.dimensionType.minY(), -512); - int maxY = Math.min(this.dimensionType.maxY(), 512); + int minY = this.dimensionType.minY(); + int maxY = this.dimensionType.maxY(); + for (JavaDimension javaDimension : this.getRegistryCache().dimensions().values()) { + if (javaDimension.bedrockId() == BedrockDimension.OVERWORLD_ID) { + minY = Math.min(minY, this.dimensionType.minY()); + maxY = Math.max(maxY, this.dimensionType.maxY()); + } + } + minY = Math.max(minY, -512); + maxY = Math.min(maxY, 512); + + if (minY < BedrockDimension.OVERWORLD.minY() || maxY > BedrockDimension.OVERWORLD.maxY()) { + final boolean isInOverworld = this.bedrockDimension == this.bedrockOverworldDimension; this.bedrockOverworldDimension = new BedrockDimension(minY, maxY - minY, true, BedrockDimension.OVERWORLD_ID); - this.bedrockDimension = this.bedrockOverworldDimension; + if (isInOverworld) { + this.bedrockDimension = this.bedrockOverworldDimension; + } geyser.getLogger().debug("Extending overworld dimension to " + minY + " - " + maxY); DimensionDataPacket dimensionDataPacket = new DimensionDataPacket(); From 13a5c0d4b648e05452acbd839282554f290084ef Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Mon, 30 Sep 2024 19:39:54 +0200 Subject: [PATCH 7/7] Fixed copy and paste error --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 4 ++-- 1 file changed, 2 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 262137f49d7..bfdf84bcab1 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -720,8 +720,8 @@ public void connect() { int maxY = this.dimensionType.maxY(); for (JavaDimension javaDimension : this.getRegistryCache().dimensions().values()) { if (javaDimension.bedrockId() == BedrockDimension.OVERWORLD_ID) { - minY = Math.min(minY, this.dimensionType.minY()); - maxY = Math.max(maxY, this.dimensionType.maxY()); + minY = Math.min(minY, javaDimension.minY()); + maxY = Math.max(maxY, javaDimension.maxY()); } } minY = Math.max(minY, -512);