WIP chunk storage rework (use an array instead of a map) hope that this is working

This commit is contained in:
Felix Cravic 2020-04-26 16:08:04 +02:00
parent 18019277e6
commit 005d95e97b
11 changed files with 133 additions and 100 deletions

View File

@ -12,6 +12,7 @@ import java.util.List;
public class AStarPathfinder { public class AStarPathfinder {
// TODO ladder, jump, etc... // TODO ladder, jump, etc...
// TODO include BoundingBox support
private boolean canClimbLadder; private boolean canClimbLadder;
private boolean canSwim; private boolean canSwim;

View File

@ -37,9 +37,9 @@ public class Chunk implements Viewable {
private Biome biome; private Biome biome;
private int chunkX, chunkZ; private int chunkX, chunkZ;
// Int represent the chunk coord of the block // blocks id based on coord
// value is: 2 bytes -> blockId | 2 bytes -> customBlockId (filled with 0 if isn't) private short[][][] blocksId = new short[CHUNK_SIZE_X][CHUNK_SIZE_Y][CHUNK_SIZE_Z];
private Int2IntMap blocks = new Int2IntOpenHashMap(16 * 16 * 16); // Start with the size of a full chunk section private short[][][] customBlocksId = new short[CHUNK_SIZE_X][CHUNK_SIZE_Y][CHUNK_SIZE_Z];
// Used to get all blocks with data (no null) // Used to get all blocks with data (no null)
// Key is still chunk coord // Key is still chunk coord
@ -65,39 +65,41 @@ public class Chunk implements Viewable {
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
} }
public void UNSAFE_setBlock(int index, short blockId, Data data) { public void UNSAFE_setBlock(int x, int y, int z, short blockId, Data data) {
setBlock(index, blockId, (short) 0, data, null); setBlock(x, y, z, blockId, (short) 0, data, null);
} }
public void UNSAFE_setBlock(int index, short blockId) { public void UNSAFE_setBlock(int x, int y, int z, short blockId) {
UNSAFE_setBlock(index, blockId, null); UNSAFE_setBlock(x, y, z, blockId, null);
} }
public void UNSAFE_setCustomBlock(int index, short customBlockId, Data data) { public void UNSAFE_setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
CustomBlock customBlock = BLOCK_MANAGER.getBlock(customBlockId); CustomBlock customBlock = BLOCK_MANAGER.getBlock(customBlockId);
if (customBlock == null) if (customBlock == null)
throw new IllegalArgumentException("The custom block " + customBlockId + " does not exist or isn't registered"); throw new IllegalArgumentException("The custom block " + customBlockId + " does not exist or isn't registered");
setCustomBlock(index, customBlock, data); setCustomBlock(x, y, z, customBlock, data);
} }
public void UNSAFE_setCustomBlock(int index, short customBlockId) { public void UNSAFE_setCustomBlock(int x, int y, int z, short customBlockId) {
UNSAFE_setCustomBlock(index, customBlockId, null); UNSAFE_setCustomBlock(x, y, z, customBlockId, null);
} }
private void setCustomBlock(int index, CustomBlock customBlock, Data data) { private void setCustomBlock(int x, int y, int z, CustomBlock customBlock, Data data) {
UpdateConsumer updateConsumer = customBlock.hasUpdate() ? customBlock::update : null; UpdateConsumer updateConsumer = customBlock.hasUpdate() ? customBlock::update : null;
setBlock(index, customBlock.getBlockId(), customBlock.getId(), data, updateConsumer); setBlock(x, y, z, customBlock.getBlockId(), customBlock.getId(), data, updateConsumer);
} }
private void setBlock(int index, short blockId, short customId, Data data, UpdateConsumer updateConsumer) { private void setBlock(int x, int y, int z, short blockId, short customId, Data data, UpdateConsumer updateConsumer) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (blockId != 0 if (blockId != 0
|| (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found || (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
refreshBlockValue(index, blockId, customId); refreshBlockValue(x, y, z, blockId, customId);
} else { } else {
// Block has been deleted, clear cache and return // Block has been deleted, clear cache and return
this.blocks.remove(index); this.blocksId[x][y][z] = 0; // Set to air
//this.blocks.remove(index);
this.blocksData.remove(index); this.blocksData.remove(index);
@ -135,7 +137,7 @@ public class Chunk implements Viewable {
this.packetUpdated = false; this.packetUpdated = false;
} }
public void setBlockData(byte x, byte y, byte z, Data data) { public void setBlockData(int x, int y, int z, Data data) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z); int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (data != null) { if (data != null) {
this.blocksData.put(index, data); this.blocksData.put(index, data);
@ -144,42 +146,35 @@ public class Chunk implements Viewable {
} }
} }
public short getBlockId(byte x, byte y, byte z) { public short getBlockId(int x, int y, int z) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z); short id = blocksId[x][y][z];
int value = getBlockValue(index); return id;
return (short) (value >>> 16);
} }
public CustomBlock getCustomBlock(byte x, byte y, byte z) { public short getCustomBlockId(int x, int y, int z) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z); short id = customBlocksId[x][y][z];
return getCustomBlock(index); return id;
} }
protected CustomBlock getCustomBlock(int index) { public CustomBlock getCustomBlock(int x, int y, int z) {
int value = getBlockValue(index); short id = customBlocksId[x][y][z];
short id = (short) (value & 0xffff);
return id != 0 ? BLOCK_MANAGER.getBlock(id) : null; return id != 0 ? BLOCK_MANAGER.getBlock(id) : null;
} }
protected void refreshBlockValue(int index, short blockId, short customId) { protected CustomBlock getCustomBlock(int index) {
int value = createBlockValue(blockId, customId); byte[] pos = SerializerUtils.indexToChunkPosition(index);
this.blocks.put(index, value); return getCustomBlock(pos[0], pos[1], pos[2]);
} }
protected void refreshBlockValue(int index, short blockId) { protected void refreshBlockValue(int x, int y, int z, short blockId, short customId) {
CustomBlock customBlock = getCustomBlock(index); this.blocksId[x][y][z] = blockId;
this.customBlocksId[x][y][z] = customId;
}
protected void refreshBlockValue(int x, int y, int z, short blockId) {
CustomBlock customBlock = getCustomBlock(x, y, z);
short customBlockId = customBlock == null ? 0 : customBlock.getId(); short customBlockId = customBlock == null ? 0 : customBlock.getId();
refreshBlockValue(index, blockId, customBlockId); refreshBlockValue(x, y, z, blockId, customBlockId);
}
public int createBlockValue(short blockId, short customId) {
// Merge blockType and customId to one unique Integer (16/16 bits)
int value = (blockId << 16 | customId & 0xFFFF);
return value;
}
private int getBlockValue(int index) {
return blocks.getOrDefault(index, 0);
} }
public Data getData(byte x, byte y, byte z) { public Data getData(byte x, byte y, byte z) {
@ -258,19 +253,27 @@ public class Chunk implements Viewable {
DataOutputStream dos = new DataOutputStream(output); DataOutputStream dos = new DataOutputStream(output);
dos.writeByte(biome.getId()); dos.writeByte(biome.getId());
for (Int2IntMap.Entry entry : blocks.int2IntEntrySet()) { for (byte x = 0; x < CHUNK_SIZE_X; x++) {
int index = entry.getIntKey(); for (short y = 0; y < CHUNK_SIZE_Y; y++) {
int value = entry.getIntValue(); for (byte z = 0; z < CHUNK_SIZE_Z; z++) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
short blockId = (short) (value >>> 16); short blockId = getBlockId(x, y, z);
short customBlockId = (short) (value & 0xffff); short customBlockId = getCustomBlockId(x, y, z);
boolean isCustomBlock = customBlockId != 0; boolean isCustomBlock = customBlockId != 0;
short id = isCustomBlock ? customBlockId : blockId; short id = isCustomBlock ? customBlockId : blockId;
if (id == 0)
continue;
Data data = blocksData.get(index); Data data = blocksData.get(index);
boolean hasData = data != null; boolean hasData = data != null;
dos.writeInt(index); // Chunk coord // Chunk coord
dos.writeInt(x);
dos.writeInt(y);
dos.writeInt(z);
dos.writeBoolean(isCustomBlock); // Determine the type of the ID dos.writeBoolean(isCustomBlock); // Determine the type of the ID
dos.writeShort(id); dos.writeShort(id);
@ -280,7 +283,8 @@ public class Chunk implements Viewable {
dos.writeInt(d.length); dos.writeInt(d.length);
dos.write(d); dos.write(d);
} }
}
}
} }
byte[] result = output.toByteArray(); byte[] result = output.toByteArray();

View File

@ -157,7 +157,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
public short getBlockId(int x, int y, int z) { public short getBlockId(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
return chunk.getBlockId((byte) (x % 16), (byte) y, (byte) (z % 16)); x = x % 16;
z = z % 16;
x = ChunkUtils.refreshChunkXZ(x);
z = ChunkUtils.refreshChunkXZ(z);
return chunk.getBlockId(x, y, z);
} }
public short getBlockId(float x, float y, float z) { public short getBlockId(float x, float y, float z) {
@ -170,7 +175,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
public CustomBlock getCustomBlock(int x, int y, int z) { public CustomBlock getCustomBlock(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
return chunk.getCustomBlock((byte) (x % 16), (byte) y, (byte) (z % 16)); x = x % 16;
z = z % 16;
x = ChunkUtils.refreshChunkXZ(x);
z = ChunkUtils.refreshChunkXZ(z);
return chunk.getCustomBlock(x, y, z);
} }
public CustomBlock getCustomBlock(BlockPosition blockPosition) { public CustomBlock getCustomBlock(BlockPosition blockPosition) {
@ -192,7 +202,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
public Data getBlockData(int x, int y, int z) { public Data getBlockData(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
return chunk.getData((byte) (x % 16), (byte) y, (byte) (z % 16)); x = x % 16;
z = z % 16;
x = ChunkUtils.refreshChunkXZ(x);
z = ChunkUtils.refreshChunkXZ(z);
return chunk.getData((byte) x, (byte) y, (byte) z);
} }
public Data getBlockData(BlockPosition blockPosition) { public Data getBlockData(BlockPosition blockPosition) {

View File

@ -48,9 +48,12 @@ public class InstanceContainer extends Instance {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
synchronized (chunk) { synchronized (chunk) {
byte chunkX = (byte) (x % 16); int chunkX = x % 16;
byte chunkY = (byte) y; int chunkY = y;
byte chunkZ = (byte) (z % 16); int chunkZ = z % 16;
chunkX = ChunkUtils.refreshChunkXZ(chunkX);
chunkZ = ChunkUtils.refreshChunkXZ(chunkZ);
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ); int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
@ -60,7 +63,7 @@ public class InstanceContainer extends Instance {
blockId = executeBlockPlacementRule(blockId, blockPosition); blockId = executeBlockPlacementRule(blockId, blockPosition);
chunk.UNSAFE_setBlock(index, blockId, data); chunk.UNSAFE_setBlock(chunkX, chunkY, chunkZ, blockId, data);
executeNeighboursBlockPlacementRule(blockPosition); executeNeighboursBlockPlacementRule(blockPosition);
@ -72,9 +75,14 @@ public class InstanceContainer extends Instance {
public synchronized void setCustomBlock(int x, int y, int z, short blockId, Data data) { public synchronized void setCustomBlock(int x, int y, int z, short blockId, Data data) {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
synchronized (chunk) { synchronized (chunk) {
byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y; int chunkX = x % 16;
byte chunkZ = (byte) (z % 16); int chunkY = y;
int chunkZ = z % 16;
chunkX = ChunkUtils.refreshChunkXZ(chunkX);
chunkZ = ChunkUtils.refreshChunkXZ(chunkZ);
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ); int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
callBlockDestroy(chunk, index, x, y, z); callBlockDestroy(chunk, index, x, y, z);
@ -83,7 +91,7 @@ public class InstanceContainer extends Instance {
blockId = executeBlockPlacementRule(blockId, blockPosition); blockId = executeBlockPlacementRule(blockId, blockPosition);
chunk.UNSAFE_setCustomBlock(index, blockId, data); chunk.UNSAFE_setCustomBlock(chunkX, chunkY, chunkZ, blockId, data);
executeNeighboursBlockPlacementRule(blockPosition); executeNeighboursBlockPlacementRule(blockPosition);
@ -103,7 +111,7 @@ public class InstanceContainer extends Instance {
byte chunkZ = (byte) (z % 16); byte chunkZ = (byte) (z % 16);
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ); int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
chunk.refreshBlockValue(index, blockId); chunk.refreshBlockValue(chunkX, chunkY, chunkZ, blockId);
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket // TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
sendBlockChange(chunk, x, y, z, blockId); sendBlockChange(chunk, x, y, z, blockId);
@ -159,7 +167,15 @@ public class InstanceContainer extends Instance {
@Override @Override
public void breakBlock(Player player, BlockPosition blockPosition) { public void breakBlock(Player player, BlockPosition blockPosition) {
Chunk chunk = getChunkAt(blockPosition); Chunk chunk = getChunkAt(blockPosition);
short blockId = chunk.getBlockId((byte) (blockPosition.getX() % 16), (byte) blockPosition.getY(), (byte) (blockPosition.getZ() % 16));
int blockX = blockPosition.getX();
int blockY = blockPosition.getY();
int blockZ = blockPosition.getZ();
blockX = ChunkUtils.refreshChunkXZ(blockX);
blockZ = ChunkUtils.refreshChunkXZ(blockZ);
short blockId = chunk.getBlockId((byte) (blockX % 16), blockY, (byte) (blockZ % 16));
if (blockId == 0) { if (blockId == 0) {
sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player); sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);
return; return;

View File

@ -3,7 +3,6 @@ package net.minestom.server.instance.batch;
import net.minestom.server.data.Data; import net.minestom.server.data.Data;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.utils.SerializerUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -89,11 +88,10 @@ public class BlockBatch implements InstanceBatch {
private Data data; private Data data;
public void apply(Chunk chunk) { public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex((byte) x, (byte) y, (byte) z);
if (!isCustomBlock) { if (!isCustomBlock) {
chunk.UNSAFE_setBlock(index, blockId, data); chunk.UNSAFE_setBlock(x, y, z, blockId, data);
} else { } else {
chunk.UNSAFE_setCustomBlock(index, blockId, data); chunk.UNSAFE_setCustomBlock(x, y, z, blockId, data);
} }
} }

View File

@ -4,7 +4,6 @@ import net.minestom.server.data.Data;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.ChunkGenerator; import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.utils.SerializerUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -31,15 +30,15 @@ public class ChunkBatch implements InstanceBatch {
@Override @Override
public void setBlock(int x, int y, int z, short blockId, Data data) { public void setBlock(int x, int y, int z, short blockId, Data data) {
addBlockData((byte) x, (byte) y, (byte) z, false, blockId, data); addBlockData((byte) x, y, (byte) z, false, blockId, data);
} }
@Override @Override
public void setCustomBlock(int x, int y, int z, short blockId, Data data) { public void setCustomBlock(int x, int y, int z, short blockId, Data data) {
addBlockData((byte) x, (byte) y, (byte) z, true, blockId, data); addBlockData((byte) x, y, (byte) z, true, blockId, data);
} }
private void addBlockData(byte x, byte y, byte z, boolean customBlock, short blockId, Data data) { private void addBlockData(byte x, int y, byte z, boolean customBlock, short blockId, Data data) {
BlockData blockData = new BlockData(); BlockData blockData = new BlockData();
blockData.x = x; blockData.x = x;
blockData.y = y; blockData.y = y;
@ -81,17 +80,16 @@ public class ChunkBatch implements InstanceBatch {
private class BlockData { private class BlockData {
private byte x, y, z; private int x, y, z;
private boolean isCustomBlock; private boolean isCustomBlock;
private short blockId; private short blockId;
private Data data; private Data data;
public void apply(Chunk chunk) { public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (!isCustomBlock) { if (!isCustomBlock) {
chunk.UNSAFE_setBlock(index, blockId, data); chunk.UNSAFE_setBlock(x, y, z, blockId, data);
} else { } else {
chunk.UNSAFE_setCustomBlock(index, blockId, data); chunk.UNSAFE_setCustomBlock(x, y, z, blockId, data);
} }
} }

View File

@ -6,7 +6,6 @@ import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
import net.minestom.server.instance.batch.ChunkBatch; import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.utils.CompressionUtils; import net.minestom.server.utils.CompressionUtils;
import net.minestom.server.utils.SerializerUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
@ -29,7 +28,10 @@ public class ChunkReader {
chunkBatch = instance.createChunkBatch(chunk); chunkBatch = instance.createChunkBatch(chunk);
while (true) { while (true) {
int index = stream.readInt(); int x = stream.readInt();
int y = stream.readInt();
int z = stream.readInt();
boolean isCustomBlock = stream.readBoolean(); boolean isCustomBlock = stream.readBoolean();
short blockId = stream.readShort(); short blockId = stream.readShort();
boolean hasData = stream.readBoolean(); boolean hasData = stream.readBoolean();
@ -42,10 +44,6 @@ public class ChunkReader {
data = DataReader.readData(dataArray, false); data = DataReader.readData(dataArray, false);
} }
byte[] chunkPos = SerializerUtils.indexToChunkPosition(index);
byte x = chunkPos[0];
byte y = chunkPos[1];
byte z = chunkPos[2];
if (isCustomBlock) { if (isCustomBlock) {
chunkBatch.setCustomBlock(x, y, z, blockId, data); chunkBatch.setCustomBlock(x, y, z, blockId, data);
} else { } else {

View File

@ -26,8 +26,6 @@ import java.util.Set;
public class BlockPlacementListener { public class BlockPlacementListener {
private Instance instance;
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) { public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
PlayerInventory playerInventory = player.getInventory(); PlayerInventory playerInventory = player.getInventory();
Player.Hand hand = packet.hand; Player.Hand hand = packet.hand;

View File

@ -24,7 +24,7 @@ public class ChunkDataPacket implements ServerPacket {
public Chunk chunk; public Chunk chunk;
public int[] sections; public int[] sections;
private static final int CHUNK_SECTION_COUNT = 16; private static final byte CHUNK_SECTION_COUNT = 16;
private static final int BITS_PER_ENTRY = 14; private static final int BITS_PER_ENTRY = 14;
private static final int MAX_BUFFER_SIZE = (Short.BYTES + Byte.BYTES + 5 * Byte.BYTES + (4096 * BITS_PER_ENTRY / Long.SIZE * Long.BYTES)) * CHUNK_SECTION_COUNT + 256 * Integer.BYTES; private static final int MAX_BUFFER_SIZE = (Short.BYTES + Byte.BYTES + 5 * Byte.BYTES + (4096 * BITS_PER_ENTRY / Long.SIZE * Long.BYTES)) * CHUNK_SECTION_COUNT + 256 * Integer.BYTES;
@ -36,7 +36,7 @@ public class ChunkDataPacket implements ServerPacket {
int mask = 0; int mask = 0;
BufferWrapper blocks = BufferUtils.getBuffer(MAX_BUFFER_SIZE); BufferWrapper blocks = BufferUtils.getBuffer(MAX_BUFFER_SIZE);
for (int i = 0; i < CHUNK_SECTION_COUNT; i++) { for (byte i = 0; i < CHUNK_SECTION_COUNT; i++) {
if (fullChunk || (sections.length == CHUNK_SECTION_COUNT && sections[i] != 0)) { if (fullChunk || (sections.length == CHUNK_SECTION_COUNT && sections[i] != 0)) {
short[] section = getSection(chunk, i); short[] section = getSection(chunk, i);
if (section != null) { // section contains at least one block if (section != null) { // section contains at least one block
@ -109,14 +109,13 @@ public class ChunkDataPacket implements ServerPacket {
} }
} }
private short[] getSection(Chunk chunk, int section) { private short[] getSection(Chunk chunk, byte section) {
short[] blocks = new short[16 * 16 * 16]; short[] blocks = new short[16 * 16 * 16];
boolean empty = true; boolean empty = true;
for (byte y = 0; y < 16; y++) { for (byte y = 0; y < 16; y++) {
for (byte x = 0; x < 16; x++) { for (byte x = 0; x < 16; x++) {
for (byte z = 0; z < 16; z++) { for (byte z = 0; z < 16; z++) {
short blockId = chunk.getBlockId(x, (byte) (y + 16 * section), z); short blockId = chunk.getBlockId(x, (y + 16 * section), z);
if (blockId != 0) if (blockId != 0)
empty = false; empty = false;

View File

@ -1,5 +1,6 @@
package net.minestom.server.utils; package net.minestom.server.utils;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
public class ChunkUtils { public class ChunkUtils {
@ -12,6 +13,11 @@ public class ChunkUtils {
return Math.floorDiv(xz, 16); return Math.floorDiv(xz, 16);
} }
public static int refreshChunkXZ(int xz) {
/// suppose CHUNK_SIZE_X == CHUNK_SIZE_Z
return xz = xz < 0 ? Chunk.CHUNK_SIZE_X + xz : xz;
}
public static long getChunkIndex(int chunkX, int chunkZ) { public static long getChunkIndex(int chunkX, int chunkZ) {
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL); return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
} }

View File

@ -18,7 +18,7 @@ public class SerializerUtils {
((value[3] & 0xFF) << 0); ((value[3] & 0xFF) << 0);
} }
public static int chunkCoordToIndex(byte x, byte y, byte z) { public static int chunkCoordToIndex(int x, int y, int z) {
short index = (short) (x & 0x000F); short index = (short) (x & 0x000F);
index |= (y << 4) & 0x0FF0; index |= (y << 4) & 0x0FF0;
index |= (z << 12) & 0xF000; index |= (z << 12) & 0xF000;