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..8c01b10a495 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, Math.abs(maxY) + Math.abs(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; } }