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] 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 8febf4d21..8cdd6120d 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.erosion.UnixSocketClientListener; 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.text.MinecraftLocale; 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 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { } 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 074ec76f6..d46debb13 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 50589851b..c4592517c 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 record JavaDimension(int minY, int maxY, boolean piglinSafe, boolean ultr 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 ac7be8f2d..29cd0fa39 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.text.MinecraftLocale; 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 class GeyserSession implements GeyserConnection, GeyserCommandSource { * 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 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { 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 a6d6e6c70..cadbf4e22 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.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; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -68,7 +69,7 @@ public class JavaLoginTranslator extends PacketTranslator 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 288b425ba..96471a2ce 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 class ChunkUtils { 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 class ChunkUtils { 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 a48a85a0e..9a520ed44 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 @@ import java.util.Set; 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 class DimensionUtils { // 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 class DimensionUtils { }); } - 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 class DimensionUtils { */ 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 class DimensionUtils { 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 class DimensionUtils { * @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 class DimensionUtils { return currentBedrockDimension == BedrockDimension.OVERWORLD_ID ? BedrockDimension.DEFAULT_NETHER_ID : BedrockDimension.OVERWORLD_ID; } - public static boolean isCustomBedrockNetherId() { - return BEDROCK_NETHER_ID == BedrockDimension.END_ID; - } }