From bb20afb1232fa1b15c09eab88272269ead71d36f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 7 Jun 2021 23:09:42 -0400 Subject: [PATCH] Warn if server is using high/low dimension heights and remove translations on some strings --- .../network/session/cache/ChunkCache.java | 8 +++- .../network/translators/BiomeTranslator.java | 3 +- .../translators/EntityIdentifierRegistry.java | 3 +- .../translators/item/ItemRegistry.java | 6 +-- .../translators/item/RecipeRegistry.java | 3 +- .../java/JavaJoinGameTranslator.java | 4 ++ .../java/JavaRespawnTranslator.java | 3 ++ .../geysermc/connector/utils/ChunkUtils.java | 46 +++++++++++++++++-- .../geysermc/connector/utils/FileUtils.java | 2 +- connector/src/main/resources/languages | 2 +- 10 files changed, 63 insertions(+), 17 deletions(-) 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 a925b43b9..e9d97d66d 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 @@ -89,7 +89,7 @@ public class ChunkCache { return; } - Chunk chunk = column.getChunks()[y >> 4]; + Chunk chunk = column.getChunks()[(y >> 4) - getChunkMinY()]; if (chunk != null) { chunk.set(x & 0xF, y & 0xF, z & 0xF, block); } @@ -110,7 +110,7 @@ public class ChunkCache { return BlockTranslator.JAVA_AIR_ID; } - Chunk chunk = column.getChunks()[y >> 4]; + Chunk chunk = column.getChunks()[(y >> 4) - getChunkMinY()]; if (chunk != null) { return chunk.get(x & 0xF, y & 0xF, z & 0xF); } @@ -126,4 +126,8 @@ public class ChunkCache { long chunkPosition = MathUtils.chunkPositionToLong(chunkX, chunkZ); chunks.remove(chunkPosition); } + + public int getChunkMinY() { + return minY >> 4; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java index eed901cdf..d797381ce 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java @@ -30,7 +30,6 @@ import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; -import org.geysermc.connector.utils.LanguageUtils; import java.io.InputStream; import java.util.Arrays; @@ -59,7 +58,7 @@ public class BiomeTranslator { biomesTag = (NbtMap) biomenbtInputStream.readTag(); BIOMES = biomesTag; } catch (Exception ex) { - GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.biome_read")); + GeyserConnector.getInstance().getLogger().warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); throw new AssertionError(ex); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java index fb6d5b93d..5bb029882 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java @@ -29,7 +29,6 @@ import com.nukkitx.nbt.NBTInputStream; import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; import org.geysermc.connector.utils.FileUtils; -import org.geysermc.connector.utils.LanguageUtils; import java.io.InputStream; @@ -54,7 +53,7 @@ public class EntityIdentifierRegistry { try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { ENTITY_IDENTIFIERS = (NbtMap) nbtInputStream.readTag(); } catch (Exception e) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.entity"), e); + throw new AssertionError("Unable to get entities from entity identifiers", e); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java index 5bbf379f3..f428d37e9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java @@ -148,7 +148,7 @@ public class ItemRegistry { try { itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType); } catch (Exception e) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_bedrock"), e); + throw new AssertionError("Unable to load Bedrock runtime item IDs", e); } int lodestoneCompassId = 0; @@ -172,7 +172,7 @@ public class ItemRegistry { try { creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items"); } catch (Exception e) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e); + throw new AssertionError("Unable to load creative items", e); } int netId = 1; @@ -247,7 +247,7 @@ public class ItemRegistry { try { items = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (Exception e) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e); + throw new AssertionError("Unable to load Java runtime item IDs", e); } BlockTranslator blockTranslator = BlockTranslator1_17_0.INSTANCE; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java index 8f7a4a8a2..506317ab9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/RecipeRegistry.java @@ -41,7 +41,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; -import org.geysermc.connector.utils.LanguageUtils; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -144,7 +143,7 @@ public class RecipeRegistry { try { items = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (Exception e) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e); + throw new AssertionError("Unable to load Java runtime item IDs", e); } for (JsonNode entry : items.get("leather_armor")) { 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 dceb13789..53ebd92ff 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 @@ -39,6 +39,7 @@ import org.geysermc.connector.entity.player.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.PluginMessageUtils; @@ -53,6 +54,9 @@ 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())) { if (!packet.getWorldName().equals(session.getWorldName()) && session.getDimension().equals(newDimension)) { 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 3fd38d508..9723cd53c 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -32,6 +32,7 @@ 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.nukkitx.math.vector.Vector2i; @@ -67,6 +68,14 @@ import static org.geysermc.connector.network.translators.world.block.BlockTransl @UtilityClass public class ChunkUtils { + /** + * The minimum height Bedrock Edition will accept. + */ + private static final int MINIMUM_ACCEPTED_HEIGHT = 0; + /** + * The maximum height Bedrock Edition will accept. + */ + private static final int MAXIMUM_ACCEPTED_HEIGHT = 256; private static int indexYZXtoXZY(int yzx) { return (yzx >> 8) | (yzx & 0x0F0) | ((yzx & 0x00F) << 8); @@ -74,7 +83,9 @@ public class ChunkUtils { public static ChunkData translateToBedrock(GeyserSession session, Column column) { Chunk[] javaSections = column.getChunks(); - ChunkSection[] sections = new ChunkSection[javaSections.length]; + // Ensure that, if the player is using lower world heights, the position is not offset + int yOffset = session.getChunkCache().getChunkMinY(); + ChunkSection[] sections = new ChunkSection[javaSections.length - yOffset]; // Temporarily stores compound tags of Bedrock-only block entities List bedrockOnlyBlockEntities = new ArrayList<>(); @@ -83,6 +94,11 @@ public class ChunkUtils { BitSet pistonOrFlowerPaletteIds = new BitSet(); for (int sectionY = 0; sectionY < javaSections.length; sectionY++) { + if (yOffset < 0 && sectionY < -yOffset) { + // Ignore this chunk since it goes below the accepted height limit + continue; + } + Chunk javaSection = javaSections[sectionY]; // No need to encode an empty section... @@ -114,7 +130,7 @@ public class ChunkUtils { )); } } - sections[sectionY] = section; + sections[sectionY + yOffset] = section; continue; } @@ -187,7 +203,7 @@ public class ChunkUtils { layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) }; } - sections[sectionY] = new ChunkSection(layers); + sections[sectionY + yOffset] = new ChunkSection(layers); } CompoundTag[] blockEntities = column.getTileEntities(); @@ -220,7 +236,7 @@ public class ChunkUtils { // Get Java blockstate ID from block entity position int blockState = 0; - Chunk section = column.getChunks()[pos.getY() >> 4]; + Chunk section = column.getChunks()[(pos.getY() >> 4) - yOffset]; if (section != null) { blockState = section.get(pos.getX() & 0xF, pos.getY() & 0xF, pos.getZ() & 0xF); } @@ -385,6 +401,28 @@ public class ChunkUtils { } } + /** + * Process the minimum and maximum heights for this dimension + */ + public static void applyDimensionHeight(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. + + 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!"); + } + + if (minY < MINIMUM_ACCEPTED_HEIGHT || maxY > MAXIMUM_ACCEPTED_HEIGHT) { + session.getConnector().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.translator.chunk.out_of_bounds")); + } + + session.getChunkCache().setMinY(minY); + } + @Data public static final class ChunkData { private final ChunkSection[] sections; diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java index a96d29da2..eecae8e4f 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java @@ -152,7 +152,7 @@ public class FileUtils { public static InputStream getResource(String resource) { InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource); if (stream == null) { - throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.resource", resource)); + throw new AssertionError("Unable to find resource: " + resource); } return stream; } diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages index b66aef5db..fcc8f01e2 160000 --- a/connector/src/main/resources/languages +++ b/connector/src/main/resources/languages @@ -1 +1 @@ -Subproject commit b66aef5db3633468f1e6ece408ecd7a3d4a4faeb +Subproject commit fcc8f01e25e481c9c82f2ee9bff23111ec781dd7