Use custom class for caching chunk data

Right now, our chunk cache stores the heightmap and biome data that the server sends, which we never use. This commit saves that data in a custom GeyserColumn class that only stores chunk data. In the future, it may also store NBT data.
This commit is contained in:
Camotoy 2021-06-29 10:09:47 -04:00
parent 62174c0e3b
commit afc1f48d5e
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
3 changed files with 75 additions and 6 deletions

View File

@ -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<Column> chunks;
private final Long2ObjectMap<GeyserColumn> 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;
}
}

View File

@ -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);
}
}

View File

@ -419,6 +419,7 @@ public class ChunkUtils {
}
session.getChunkCache().setMinY(minY);
session.getChunkCache().setHeightY(maxY);
}
@Data