mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-26 02:57:37 +01:00
WIP chunk storage rework (use an array instead of a map) hope that this is working
This commit is contained in:
parent
18019277e6
commit
005d95e97b
@ -12,6 +12,7 @@ import java.util.List;
|
||||
public class AStarPathfinder {
|
||||
|
||||
// TODO ladder, jump, etc...
|
||||
// TODO include BoundingBox support
|
||||
|
||||
private boolean canClimbLadder;
|
||||
private boolean canSwim;
|
||||
|
@ -37,9 +37,9 @@ public class Chunk implements Viewable {
|
||||
private Biome biome;
|
||||
private int chunkX, chunkZ;
|
||||
|
||||
// Int represent the chunk coord of the block
|
||||
// value is: 2 bytes -> blockId | 2 bytes -> customBlockId (filled with 0 if isn't)
|
||||
private Int2IntMap blocks = new Int2IntOpenHashMap(16 * 16 * 16); // Start with the size of a full chunk section
|
||||
// blocks id based on coord
|
||||
private short[][][] blocksId = new short[CHUNK_SIZE_X][CHUNK_SIZE_Y][CHUNK_SIZE_Z];
|
||||
private short[][][] customBlocksId = new short[CHUNK_SIZE_X][CHUNK_SIZE_Y][CHUNK_SIZE_Z];
|
||||
|
||||
// Used to get all blocks with data (no null)
|
||||
// Key is still chunk coord
|
||||
@ -65,39 +65,41 @@ public class Chunk implements Viewable {
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public void UNSAFE_setBlock(int index, short blockId, Data data) {
|
||||
setBlock(index, blockId, (short) 0, data, null);
|
||||
public void UNSAFE_setBlock(int x, int y, int z, short blockId, Data data) {
|
||||
setBlock(x, y, z, blockId, (short) 0, data, null);
|
||||
}
|
||||
|
||||
public void UNSAFE_setBlock(int index, short blockId) {
|
||||
UNSAFE_setBlock(index, blockId, null);
|
||||
public void UNSAFE_setBlock(int x, int y, int z, short blockId) {
|
||||
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);
|
||||
if (customBlock == null)
|
||||
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) {
|
||||
UNSAFE_setCustomBlock(index, customBlockId, null);
|
||||
public void UNSAFE_setCustomBlock(int x, int y, int z, short customBlockId) {
|
||||
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;
|
||||
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
|
||||
|| (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 {
|
||||
// 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);
|
||||
|
||||
@ -135,7 +137,7 @@ public class Chunk implements Viewable {
|
||||
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);
|
||||
if (data != null) {
|
||||
this.blocksData.put(index, data);
|
||||
@ -144,42 +146,35 @@ public class Chunk implements Viewable {
|
||||
}
|
||||
}
|
||||
|
||||
public short getBlockId(byte x, byte y, byte z) {
|
||||
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
|
||||
int value = getBlockValue(index);
|
||||
return (short) (value >>> 16);
|
||||
public short getBlockId(int x, int y, int z) {
|
||||
short id = blocksId[x][y][z];
|
||||
return id;
|
||||
}
|
||||
|
||||
public CustomBlock getCustomBlock(byte x, byte y, byte z) {
|
||||
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
|
||||
return getCustomBlock(index);
|
||||
public short getCustomBlockId(int x, int y, int z) {
|
||||
short id = customBlocksId[x][y][z];
|
||||
return id;
|
||||
}
|
||||
|
||||
protected CustomBlock getCustomBlock(int index) {
|
||||
int value = getBlockValue(index);
|
||||
short id = (short) (value & 0xffff);
|
||||
public CustomBlock getCustomBlock(int x, int y, int z) {
|
||||
short id = customBlocksId[x][y][z];
|
||||
return id != 0 ? BLOCK_MANAGER.getBlock(id) : null;
|
||||
}
|
||||
|
||||
protected void refreshBlockValue(int index, short blockId, short customId) {
|
||||
int value = createBlockValue(blockId, customId);
|
||||
this.blocks.put(index, value);
|
||||
protected CustomBlock getCustomBlock(int index) {
|
||||
byte[] pos = SerializerUtils.indexToChunkPosition(index);
|
||||
return getCustomBlock(pos[0], pos[1], pos[2]);
|
||||
}
|
||||
|
||||
protected void refreshBlockValue(int index, short blockId) {
|
||||
CustomBlock customBlock = getCustomBlock(index);
|
||||
protected void refreshBlockValue(int x, int y, int z, short blockId, short customId) {
|
||||
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();
|
||||
refreshBlockValue(index, 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);
|
||||
refreshBlockValue(x, y, z, blockId, customBlockId);
|
||||
}
|
||||
|
||||
public Data getData(byte x, byte y, byte z) {
|
||||
@ -258,19 +253,27 @@ public class Chunk implements Viewable {
|
||||
DataOutputStream dos = new DataOutputStream(output);
|
||||
dos.writeByte(biome.getId());
|
||||
|
||||
for (Int2IntMap.Entry entry : blocks.int2IntEntrySet()) {
|
||||
int index = entry.getIntKey();
|
||||
int value = entry.getIntValue();
|
||||
for (byte x = 0; x < CHUNK_SIZE_X; x++) {
|
||||
for (short y = 0; y < CHUNK_SIZE_Y; y++) {
|
||||
for (byte z = 0; z < CHUNK_SIZE_Z; z++) {
|
||||
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
|
||||
|
||||
short blockId = (short) (value >>> 16);
|
||||
short customBlockId = (short) (value & 0xffff);
|
||||
short blockId = getBlockId(x, y, z);
|
||||
short customBlockId = getCustomBlockId(x, y, z);
|
||||
boolean isCustomBlock = customBlockId != 0;
|
||||
short id = isCustomBlock ? customBlockId : blockId;
|
||||
|
||||
if (id == 0)
|
||||
continue;
|
||||
|
||||
Data data = blocksData.get(index);
|
||||
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.writeShort(id);
|
||||
|
||||
@ -280,7 +283,8 @@ public class Chunk implements Viewable {
|
||||
dos.writeInt(d.length);
|
||||
dos.write(d);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] result = output.toByteArray();
|
||||
|
@ -157,7 +157,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
|
||||
|
||||
public short getBlockId(int x, int y, int 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) {
|
||||
@ -170,7 +175,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
|
||||
|
||||
public CustomBlock getCustomBlock(int x, int y, int 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) {
|
||||
@ -192,7 +202,12 @@ public abstract class Instance implements BlockModifier, DataContainer {
|
||||
|
||||
public Data getBlockData(int x, int y, int 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) {
|
||||
|
@ -48,9 +48,12 @@ public class InstanceContainer extends Instance {
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
synchronized (chunk) {
|
||||
|
||||
byte chunkX = (byte) (x % 16);
|
||||
byte chunkY = (byte) y;
|
||||
byte chunkZ = (byte) (z % 16);
|
||||
int chunkX = x % 16;
|
||||
int chunkY = y;
|
||||
int chunkZ = z % 16;
|
||||
|
||||
chunkX = ChunkUtils.refreshChunkXZ(chunkX);
|
||||
chunkZ = ChunkUtils.refreshChunkXZ(chunkZ);
|
||||
|
||||
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
|
||||
|
||||
@ -60,7 +63,7 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
blockId = executeBlockPlacementRule(blockId, blockPosition);
|
||||
|
||||
chunk.UNSAFE_setBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setBlock(chunkX, chunkY, chunkZ, blockId, data);
|
||||
|
||||
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) {
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
synchronized (chunk) {
|
||||
byte chunkX = (byte) (x % 16);
|
||||
byte chunkY = (byte) y;
|
||||
byte chunkZ = (byte) (z % 16);
|
||||
|
||||
int chunkX = x % 16;
|
||||
int chunkY = y;
|
||||
int chunkZ = z % 16;
|
||||
|
||||
chunkX = ChunkUtils.refreshChunkXZ(chunkX);
|
||||
chunkZ = ChunkUtils.refreshChunkXZ(chunkZ);
|
||||
|
||||
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
|
||||
|
||||
callBlockDestroy(chunk, index, x, y, z);
|
||||
@ -83,7 +91,7 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
blockId = executeBlockPlacementRule(blockId, blockPosition);
|
||||
|
||||
chunk.UNSAFE_setCustomBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setCustomBlock(chunkX, chunkY, chunkZ, blockId, data);
|
||||
|
||||
executeNeighboursBlockPlacementRule(blockPosition);
|
||||
|
||||
@ -103,7 +111,7 @@ public class InstanceContainer extends Instance {
|
||||
byte chunkZ = (byte) (z % 16);
|
||||
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
|
||||
sendBlockChange(chunk, x, y, z, blockId);
|
||||
@ -159,7 +167,15 @@ public class InstanceContainer extends Instance {
|
||||
@Override
|
||||
public void breakBlock(Player player, BlockPosition 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) {
|
||||
sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);
|
||||
return;
|
||||
|
@ -3,7 +3,6 @@ package net.minestom.server.instance.batch;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
import net.minestom.server.utils.SerializerUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -89,11 +88,10 @@ public class BlockBatch implements InstanceBatch {
|
||||
private Data data;
|
||||
|
||||
public void apply(Chunk chunk) {
|
||||
int index = SerializerUtils.chunkCoordToIndex((byte) x, (byte) y, (byte) z);
|
||||
if (!isCustomBlock) {
|
||||
chunk.UNSAFE_setBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setBlock(x, y, z, blockId, data);
|
||||
} else {
|
||||
chunk.UNSAFE_setCustomBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setCustomBlock(x, y, z, blockId, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.ChunkGenerator;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
import net.minestom.server.utils.SerializerUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -31,15 +30,15 @@ public class ChunkBatch implements InstanceBatch {
|
||||
|
||||
@Override
|
||||
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
|
||||
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.x = x;
|
||||
blockData.y = y;
|
||||
@ -81,17 +80,16 @@ public class ChunkBatch implements InstanceBatch {
|
||||
|
||||
private class BlockData {
|
||||
|
||||
private byte x, y, z;
|
||||
private int x, y, z;
|
||||
private boolean isCustomBlock;
|
||||
private short blockId;
|
||||
private Data data;
|
||||
|
||||
public void apply(Chunk chunk) {
|
||||
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
|
||||
if (!isCustomBlock) {
|
||||
chunk.UNSAFE_setBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setBlock(x, y, z, blockId, data);
|
||||
} else {
|
||||
chunk.UNSAFE_setCustomBlock(index, blockId, data);
|
||||
chunk.UNSAFE_setCustomBlock(x, y, z, blockId, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.batch.ChunkBatch;
|
||||
import net.minestom.server.utils.CompressionUtils;
|
||||
import net.minestom.server.utils.SerializerUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
@ -29,7 +28,10 @@ public class ChunkReader {
|
||||
chunkBatch = instance.createChunkBatch(chunk);
|
||||
|
||||
while (true) {
|
||||
int index = stream.readInt();
|
||||
int x = stream.readInt();
|
||||
int y = stream.readInt();
|
||||
int z = stream.readInt();
|
||||
|
||||
boolean isCustomBlock = stream.readBoolean();
|
||||
short blockId = stream.readShort();
|
||||
boolean hasData = stream.readBoolean();
|
||||
@ -42,10 +44,6 @@ public class ChunkReader {
|
||||
data = DataReader.readData(dataArray, false);
|
||||
}
|
||||
|
||||
byte[] chunkPos = SerializerUtils.indexToChunkPosition(index);
|
||||
byte x = chunkPos[0];
|
||||
byte y = chunkPos[1];
|
||||
byte z = chunkPos[2];
|
||||
if (isCustomBlock) {
|
||||
chunkBatch.setCustomBlock(x, y, z, blockId, data);
|
||||
} else {
|
||||
|
@ -26,8 +26,6 @@ import java.util.Set;
|
||||
|
||||
public class BlockPlacementListener {
|
||||
|
||||
private Instance instance;
|
||||
|
||||
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
Player.Hand hand = packet.hand;
|
||||
|
@ -24,7 +24,7 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
public Chunk chunk;
|
||||
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 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;
|
||||
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)) {
|
||||
short[] section = getSection(chunk, i);
|
||||
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];
|
||||
boolean empty = true;
|
||||
|
||||
for (byte y = 0; y < 16; y++) {
|
||||
for (byte x = 0; x < 16; x++) {
|
||||
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)
|
||||
empty = false;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.minestom.server.utils;
|
||||
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
public class ChunkUtils {
|
||||
@ -12,6 +13,11 @@ public class ChunkUtils {
|
||||
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) {
|
||||
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class SerializerUtils {
|
||||
((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);
|
||||
index |= (y << 4) & 0x0FF0;
|
||||
index |= (z << 12) & 0xF000;
|
||||
|
Loading…
Reference in New Issue
Block a user