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 4c2d8c36f..6154ff65f 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 @@ -67,7 +67,10 @@ public class ChunkCache { chunks.put(chunkPosition, geyserColumn); } - public GeyserColumn getChunk(int chunkX, int chunkZ) { + /** + * Doesn't check for cache enabled, so don't use this without checking that first! + */ + private GeyserColumn getChunk(int chunkX, int chunkZ) { long chunkPosition = MathUtils.chunkPositionToLong(chunkX, chunkZ); return chunks.getOrDefault(chunkPosition, null); } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldBorder.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldBorder.java index 202be421c..f312bb8b4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldBorder.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldBorder.java @@ -26,7 +26,7 @@ package org.geysermc.connector.network.session.cache; import com.nukkitx.math.GenericMath; -import com.nukkitx.math.vector.Vector2f; +import com.nukkitx.math.vector.Vector2d; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; @@ -43,35 +43,45 @@ import java.util.Collections; public class WorldBorder { private static final double DEFAULT_WORLD_BORDER_SIZE = 5.9999968E7D; - @Getter @Setter - private @Nonnull Vector2f center = Vector2f.ZERO; + @Setter + private @Nonnull Vector2d center = Vector2d.ZERO; /** * The diameter in blocks of the world border before it got changed or similar to newDiameter if not changed. */ - @Getter @Setter + @Setter private double oldDiameter = DEFAULT_WORLD_BORDER_SIZE; /** * The diameter in blocks of the new world border. */ - @Getter @Setter + @Setter private double newDiameter = DEFAULT_WORLD_BORDER_SIZE; /** * The speed to apply an expansion/shrinking of the world border. * When a client joins they get the actual border oldDiameter and the time left to reach the newDiameter. */ - @Getter @Setter + @Setter private long speed = 0; /** * The time in seconds before a shrinking world border would hit a not moving player. * Creates the same visual warning effect as warningBlocks. */ - @Getter @Setter + @Setter private int warningDelay = 15; /** * Block length before you reach the border to show warning particles. */ - @Getter @Setter + @Setter private int warningBlocks = 5; + /** + * The world border cannot go beyond this number, positive or negative, in world coordinates + */ + @Setter + private int absoluteMaxSize = 29999984; + + /** + * The world coordinate scale as sent in the dimension registry. Used to scale the center X and Z. + */ + private double worldCoordinateScale = 1.0D; @Getter private boolean resizing; @@ -112,6 +122,14 @@ public class WorldBorder { update(); } + public void setWorldCoordinateScale(double worldCoordinateScale) { + boolean needsUpdate = worldCoordinateScale != this.worldCoordinateScale; + this.worldCoordinateScale = worldCoordinateScale; + if (needsUpdate) { + this.update(); + } + } + /** * @return true as long the entity is within the world limits. */ @@ -173,10 +191,16 @@ public class WorldBorder { } else { radius = this.newDiameter / 2.0D; } - this.minX = center.getX() - radius; - this.minZ = center.getY() - radius; // Mapping 2D vector to 3D coordinates >> Y becomes Z - this.maxX = center.getX() + radius; - this.maxZ = center.getY() + radius; // Mapping 2D vector to 3D coordinates >> Y becomes Z + + double absoluteMinSize = -this.absoluteMaxSize; + // Used in the Nether by default + double centerX = this.center.getX() / this.worldCoordinateScale; + double centerZ = this.center.getY() / this.worldCoordinateScale; // Mapping 2D vector to 3D coordinates >> Y becomes Z + + this.minX = GenericMath.clamp(centerX - radius, absoluteMinSize, this.absoluteMaxSize); + this.minZ = GenericMath.clamp(centerZ - radius, absoluteMinSize, this.absoluteMaxSize); + this.maxX = GenericMath.clamp(centerX + radius, absoluteMinSize, this.absoluteMaxSize); + this.maxZ = GenericMath.clamp(centerZ + radius, absoluteMinSize, this.absoluteMaxSize); /* * Caching the warning boundaries. 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 da21b7c22..b0332e23e 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 @@ -114,6 +114,6 @@ public class JavaJoinGameTranslator extends PacketTranslator DimensionUtils.switchDimension(session, newDimension); } - ChunkUtils.applyDimensionHeight(session, packet.getDimension()); + ChunkUtils.loadDimensionTag(session, packet.getDimension()); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaInitializeBorderTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaInitializeBorderTranslator.java index 45c33fcf8..05632cefa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaInitializeBorderTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaInitializeBorderTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.connector.network.translators.java.world.border; import com.github.steveice10.mc.protocol.packet.ingame.server.world.border.ServerInitializeBorderPacket; -import com.nukkitx.math.vector.Vector2f; +import com.nukkitx.math.vector.Vector2d; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.cache.WorldBorder; import org.geysermc.connector.network.translators.PacketTranslator; @@ -38,13 +38,14 @@ public class JavaInitializeBorderTranslator extends PacketTranslator 0); + worldBorder.setAbsoluteMaxSize(packet.getNewAbsoluteMaxSize()); worldBorder.update(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterTranslator.java similarity index 90% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterPacket.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterTranslator.java index 034c7cf6d..3d755fce1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterPacket.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/border/JavaSetBorderCenterTranslator.java @@ -26,19 +26,19 @@ package org.geysermc.connector.network.translators.java.world.border; import com.github.steveice10.mc.protocol.packet.ingame.server.world.border.ServerSetBorderCenterPacket; -import com.nukkitx.math.vector.Vector2f; +import com.nukkitx.math.vector.Vector2d; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.cache.WorldBorder; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @Translator(packet = ServerSetBorderCenterPacket.class) -public class JavaSetBorderCenterPacket extends PacketTranslator { +public class JavaSetBorderCenterTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ServerSetBorderCenterPacket packet) { WorldBorder worldBorder = session.getWorldBorder(); - worldBorder.setCenter(Vector2f.from(packet.getNewCenterX(), packet.getNewCenterZ())); + worldBorder.setCenter(Vector2d.from(packet.getNewCenterX(), packet.getNewCenterZ())); worldBorder.update(); } 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 3b2614d77..fbe30f6e5 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -31,10 +31,7 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.github.steveice10.opennbt.tag.builtin.*; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.NbtMap; @@ -429,10 +426,10 @@ public class ChunkUtils { } /** - * Process the minimum and maximum heights for this dimension. + * Process the minimum and maximum heights for this dimension, and processes the world coordinate scale. * 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) { + public static void loadDimensionTag(GeyserSession session, CompoundTag dimensionTag) { int minY = ((IntTag) dimensionTag.get("min_y")).getValue(); int maxY = ((IntTag) dimensionTag.get("height")).getValue(); // Logical height can be ignored probably - seems to be for artificial limits like the Nether. @@ -467,6 +464,10 @@ public class ChunkUtils { session.getChunkCache().setMinY(minY); session.getChunkCache().setHeightY(maxY); + + // Load world coordinate scale for the world border + double coordinateScale = ((DoubleTag) dimensionTag.get("coordinate_scale")).getValue(); + session.getWorldBorder().setWorldCoordinateScale(coordinateScale); } @Data