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 393a1f188..4f93b0f53 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 @@ -32,14 +32,17 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import lombok.Setter; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.chunk.GeyserColumn; import org.geysermc.connector.utils.MathUtils; public class ChunkCache { private final boolean cache; - private final Long2ObjectMap chunks; + private final Long2ObjectMap chunks; @Setter private int minY; + @Setter + private int heightY; public ChunkCache(GeyserSession session) { this.cache = !session.getConnector().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing @@ -51,10 +54,12 @@ public class ChunkCache { return; } - chunks.put(MathUtils.chunkPositionToLong(chunk.getX(), chunk.getZ()), chunk); + long chunkPosition = MathUtils.chunkPositionToLong(chunk.getX(), chunk.getZ()); + GeyserColumn geyserColumn = GeyserColumn.from(this, chunk); + chunks.put(chunkPosition, geyserColumn); } - public Column getChunk(int chunkX, int chunkZ) { + public GeyserColumn getChunk(int chunkX, int chunkZ) { long chunkPosition = MathUtils.chunkPositionToLong(chunkX, chunkZ); return chunks.getOrDefault(chunkPosition, null); } @@ -64,7 +69,7 @@ public class ChunkCache { return; } - Column column = this.getChunk(x >> 4, z >> 4); + GeyserColumn column = this.getChunk(x >> 4, z >> 4); if (column == null) { return; } @@ -77,8 +82,10 @@ public class ChunkCache { Chunk chunk = column.getChunks()[(y >> 4) - getChunkMinY()]; if (chunk == null) { if (block != BlockTranslator.JAVA_AIR_ID) { - chunk = new Chunk(); // A previously empty chunk, which is no longer empty as a block has been added to it + chunk = new Chunk(); + // Fixes the chunk assuming that all blocks is the `block` variable we are updating. /shrug + chunk.getPalette().stateToId(BlockTranslator.JAVA_AIR_ID); column.getChunks()[(y >> 4) - getChunkMinY()] = chunk; } else { // Nothing to update @@ -94,7 +101,7 @@ public class ChunkCache { return BlockTranslator.JAVA_AIR_ID; } - Column column = this.getChunk(x >> 4, z >> 4); + GeyserColumn column = this.getChunk(x >> 4, z >> 4); if (column == null) { return BlockTranslator.JAVA_AIR_ID; } @@ -124,4 +131,8 @@ public class ChunkCache { public int getChunkMinY() { return minY >> 4; } + + public int getChunkHeightY() { + return heightY >> 4; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/GeyserColumn.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/GeyserColumn.java new file mode 100644 index 000000000..3da5787a5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/GeyserColumn.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.world.chunk; + +import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; +import com.github.steveice10.mc.protocol.data.game.chunk.Column; +import lombok.Getter; +import org.geysermc.connector.network.session.cache.ChunkCache; + +/** + * Acts as a lightweight version of {@link Column} that doesn't store + * biomes or heightmaps. + */ +public class GeyserColumn { + @Getter + private final Chunk[] chunks; + + private GeyserColumn(Chunk[] chunks) { + this.chunks = chunks; + } + + public static GeyserColumn from(ChunkCache chunkCache, Column column) { + int chunkHeightY = chunkCache.getChunkHeightY(); + Chunk[] chunks; + if (chunkHeightY < column.getChunks().length) { + chunks = new Chunk[chunkHeightY]; + // TODO addresses https://github.com/Steveice10/MCProtocolLib/pull/598#issuecomment-862782392 + System.arraycopy(column.getChunks(), 0, chunks, 0, chunks.length); + } else { + chunks = column.getChunks(); + } + return new GeyserColumn(chunks); + } +} 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 85b7f8600..343f5c53e 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -419,6 +419,7 @@ public class ChunkUtils { } session.getChunkCache().setMinY(minY); + session.getChunkCache().setHeightY(maxY); } @Data