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 {
|
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;
|
||||||
|
@ -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,29 +253,38 @@ 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;
|
||||||
|
|
||||||
Data data = blocksData.get(index);
|
if (id == 0)
|
||||||
boolean hasData = data != null;
|
continue;
|
||||||
|
|
||||||
dos.writeInt(index); // Chunk coord
|
Data data = blocksData.get(index);
|
||||||
dos.writeBoolean(isCustomBlock); // Determine the type of the ID
|
boolean hasData = data != null;
|
||||||
dos.writeShort(id);
|
|
||||||
|
|
||||||
dos.writeBoolean(hasData);
|
// Chunk coord
|
||||||
if (hasData) {
|
dos.writeInt(x);
|
||||||
byte[] d = data.getSerializedData();
|
dos.writeInt(y);
|
||||||
dos.writeInt(d.length);
|
dos.writeInt(z);
|
||||||
dos.write(d);
|
|
||||||
|
dos.writeBoolean(isCustomBlock); // Determine the type of the ID
|
||||||
|
dos.writeShort(id);
|
||||||
|
|
||||||
|
dos.writeBoolean(hasData);
|
||||||
|
if (hasData) {
|
||||||
|
byte[] d = data.getSerializedData();
|
||||||
|
dos.writeInt(d.length);
|
||||||
|
dos.write(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] result = output.toByteArray();
|
byte[] result = output.toByteArray();
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user