mirror of
https://github.com/Minestom/Minestom.git
synced 2024-09-24 20:42:39 +02:00
Add basic block entity support, simplify code
Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
parent
201b5500b9
commit
972e15a62b
@ -8,14 +8,16 @@ import net.minestom.server.entity.Player;
|
|||||||
import net.minestom.server.entity.pathfinding.PFBlock;
|
import net.minestom.server.entity.pathfinding.PFBlock;
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.instance.block.BlockHandler;
|
import net.minestom.server.instance.block.BlockHandler;
|
||||||
|
import net.minestom.server.instance.palette.Palette;
|
||||||
import net.minestom.server.network.packet.server.CachedPacket;
|
import net.minestom.server.network.packet.server.CachedPacket;
|
||||||
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||||
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
||||||
import net.minestom.server.network.packet.server.play.data.ChunkPacketData;
|
import net.minestom.server.network.packet.server.play.data.ChunkData;
|
||||||
import net.minestom.server.network.packet.server.play.data.LightPacketData;
|
import net.minestom.server.network.packet.server.play.data.LightData;
|
||||||
import net.minestom.server.utils.ArrayUtils;
|
import net.minestom.server.utils.ArrayUtils;
|
||||||
import net.minestom.server.utils.MathUtils;
|
import net.minestom.server.utils.MathUtils;
|
||||||
import net.minestom.server.utils.Utils;
|
import net.minestom.server.utils.Utils;
|
||||||
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.world.biomes.Biome;
|
import net.minestom.server.world.biomes.Biome;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -170,12 +172,20 @@ public class DynamicChunk extends Chunk {
|
|||||||
.setLongArray("MOTION_BLOCKING", Utils.encodeBlocks(motionBlocking, bitsForHeight))
|
.setLongArray("MOTION_BLOCKING", Utils.encodeBlocks(motionBlocking, bitsForHeight))
|
||||||
.setLongArray("WORLD_SURFACE", Utils.encodeBlocks(worldSurface, bitsForHeight));
|
.setLongArray("WORLD_SURFACE", Utils.encodeBlocks(worldSurface, bitsForHeight));
|
||||||
}
|
}
|
||||||
|
// Data
|
||||||
|
final BinaryWriter writer = new BinaryWriter();
|
||||||
|
for (int i = 0; i < 16; i++) { // TODO: variable section count
|
||||||
|
final Section section = Objects.requireNonNullElseGet(sectionMap.get(i), Section::new);
|
||||||
|
final Palette blockPalette = section.getPalette();
|
||||||
|
writer.writeShort(blockPalette.getBlockCount());
|
||||||
|
blockPalette.write(writer); // Blocks
|
||||||
|
new Palette(2, 2).write(writer); // Biomes
|
||||||
|
}
|
||||||
|
|
||||||
ChunkDataPacket packet = new ChunkDataPacket();
|
ChunkDataPacket packet = new ChunkDataPacket();
|
||||||
packet.chunkX = chunkX;
|
packet.chunkX = chunkX;
|
||||||
packet.chunkZ = chunkZ;
|
packet.chunkZ = chunkZ;
|
||||||
// TODO deep clone sections
|
packet.chunkData = new ChunkData(heightmapsNBT, writer.getBuffer().flip(), entries);
|
||||||
packet.chunkData = new ChunkPacketData(heightmapsNBT, sectionMap, entries);
|
|
||||||
packet.lightData = createLightData();
|
packet.lightData = createLightData();
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
@ -188,7 +198,7 @@ public class DynamicChunk extends Chunk {
|
|||||||
return updateLightPacket;
|
return updateLightPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LightPacketData createLightData() {
|
private LightData createLightData() {
|
||||||
BitSet skyMask = new BitSet();
|
BitSet skyMask = new BitSet();
|
||||||
BitSet blockMask = new BitSet();
|
BitSet blockMask = new BitSet();
|
||||||
BitSet emptySkyMask = new BitSet();
|
BitSet emptySkyMask = new BitSet();
|
||||||
@ -213,7 +223,7 @@ public class DynamicChunk extends Chunk {
|
|||||||
blockMask.set(index);
|
blockMask.set(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new LightPacketData(true,
|
return new LightData(true,
|
||||||
skyMask, blockMask,
|
skyMask, blockMask,
|
||||||
emptySkyMask, emptyBlockMask,
|
emptySkyMask, emptyBlockMask,
|
||||||
skyLights, blockLights);
|
skyLights, blockLights);
|
||||||
|
@ -162,6 +162,6 @@ public class ItemMeta implements TagReadable, Writeable {
|
|||||||
w.writeNBT("", nbt);
|
w.writeNBT("", nbt);
|
||||||
this.cachedBuffer = w.getBuffer();
|
this.cachedBuffer = w.getBuffer();
|
||||||
}
|
}
|
||||||
writer.write(cachedBuffer);
|
writer.write(cachedBuffer.flip());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,16 @@ package net.minestom.server.network.packet.server.play;
|
|||||||
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import net.minestom.server.network.packet.server.play.data.ChunkPacketData;
|
import net.minestom.server.network.packet.server.play.data.ChunkData;
|
||||||
import net.minestom.server.network.packet.server.play.data.LightPacketData;
|
import net.minestom.server.network.packet.server.play.data.LightData;
|
||||||
import net.minestom.server.utils.binary.BinaryReader;
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class ChunkDataPacket implements ServerPacket {
|
public class ChunkDataPacket implements ServerPacket {
|
||||||
public int chunkX, chunkZ;
|
public int chunkX, chunkZ;
|
||||||
public ChunkPacketData chunkData;
|
public ChunkData chunkData;
|
||||||
public LightPacketData lightData;
|
public LightData lightData;
|
||||||
|
|
||||||
public ChunkDataPacket() {
|
public ChunkDataPacket() {
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package net.minestom.server.network.packet.server.play;
|
|||||||
|
|
||||||
import net.minestom.server.network.packet.server.ServerPacket;
|
import net.minestom.server.network.packet.server.ServerPacket;
|
||||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||||
import net.minestom.server.network.packet.server.play.data.LightPacketData;
|
import net.minestom.server.network.packet.server.play.data.LightData;
|
||||||
import net.minestom.server.utils.binary.BinaryReader;
|
import net.minestom.server.utils.binary.BinaryReader;
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -11,7 +11,7 @@ public class UpdateLightPacket implements ServerPacket {
|
|||||||
|
|
||||||
public int chunkX;
|
public int chunkX;
|
||||||
public int chunkZ;
|
public int chunkZ;
|
||||||
public LightPacketData lightData;
|
public LightData lightData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor, required for reflection operations.
|
* Default constructor, required for reflection operations.
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package net.minestom.server.network.packet.server.play.data;
|
||||||
|
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
import net.minestom.server.instance.block.BlockHandler;
|
||||||
|
import net.minestom.server.tag.Tag;
|
||||||
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
|
import net.minestom.server.utils.binary.Writeable;
|
||||||
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public final class ChunkData implements Writeable {
|
||||||
|
private final NBTCompound heightmaps;
|
||||||
|
private final ByteBuffer data;
|
||||||
|
private final Map<Integer, Block> blockEntities;
|
||||||
|
|
||||||
|
public ChunkData(NBTCompound heightmaps, ByteBuffer data, Map<Integer, Block> blockEntities) {
|
||||||
|
this.heightmaps = heightmaps.deepClone();
|
||||||
|
this.data = data.asReadOnlyBuffer();
|
||||||
|
this.blockEntities = Map.copyOf(blockEntities);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void write(@NotNull BinaryWriter writer) {
|
||||||
|
// Heightmaps
|
||||||
|
writer.writeNBT("", this.heightmaps);
|
||||||
|
// Data
|
||||||
|
writer.writeVarInt(data.position(0).remaining());
|
||||||
|
writer.write(data);
|
||||||
|
// Block entities
|
||||||
|
writer.writeVarInt(blockEntities.size());
|
||||||
|
for (var entry : blockEntities.entrySet()) {
|
||||||
|
final int index = entry.getKey();
|
||||||
|
final Block block = entry.getValue();
|
||||||
|
final var registry = block.registry();
|
||||||
|
if (!registry.isBlockEntity()) continue;
|
||||||
|
|
||||||
|
final Point point = ChunkUtils.getBlockPosition(index, 0, 0);
|
||||||
|
|
||||||
|
writer.writeByte((byte) ((point.blockX() & 15) << 4 | point.blockZ() & 15)); // xz
|
||||||
|
writer.writeShort((short) point.blockY()); // y
|
||||||
|
|
||||||
|
writer.writeVarInt(0); // TODO block entity id
|
||||||
|
|
||||||
|
|
||||||
|
final NBTCompound resultNbt = new NBTCompound();
|
||||||
|
{
|
||||||
|
// Append handler tags
|
||||||
|
final BlockHandler handler = block.handler();
|
||||||
|
if (handler != null) {
|
||||||
|
final NBTCompound blockNbt = Objects.requireNonNullElseGet(block.nbt(), NBTCompound::new);
|
||||||
|
for (Tag<?> tag : handler.getBlockEntityTags()) {
|
||||||
|
final var value = tag.read(blockNbt);
|
||||||
|
if (value != null) {
|
||||||
|
// Tag is present and valid
|
||||||
|
tag.writeUnsafe(resultNbt, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeNBT("", resultNbt); // block nbt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
package net.minestom.server.network.packet.server.play.data;
|
|
||||||
|
|
||||||
import net.minestom.server.instance.Section;
|
|
||||||
import net.minestom.server.instance.block.Block;
|
|
||||||
import net.minestom.server.instance.palette.Palette;
|
|
||||||
import net.minestom.server.utils.Utils;
|
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
|
||||||
import net.minestom.server.utils.binary.Writeable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public final class ChunkPacketData implements Writeable {
|
|
||||||
private final NBTCompound heightmaps;
|
|
||||||
private final Map<Integer, Section> sections;
|
|
||||||
private final Map<Integer, Block> blockEntities;
|
|
||||||
|
|
||||||
public ChunkPacketData(NBTCompound heightmaps, Map<Integer, Section> sections, Map<Integer, Block> blockEntities) {
|
|
||||||
this.heightmaps = heightmaps.deepClone();
|
|
||||||
this.sections = Map.copyOf(sections);
|
|
||||||
this.blockEntities = Map.copyOf(blockEntities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(@NotNull BinaryWriter writer) {
|
|
||||||
writer.writeNBT("", this.heightmaps);
|
|
||||||
// Data
|
|
||||||
{
|
|
||||||
final ByteBuffer buffer = writer.getBuffer();
|
|
||||||
final int index = Utils.writeEmptyVarIntHeader(buffer);
|
|
||||||
for (int i = 0; i < 16; i++) { // TODO: variable section count
|
|
||||||
final Section section = Objects.requireNonNullElseGet(sections.get(i), Section::new);
|
|
||||||
final Palette blockPalette = section.getPalette();
|
|
||||||
writer.writeShort(blockPalette.getBlockCount());
|
|
||||||
blockPalette.write(writer); // Blocks
|
|
||||||
new Palette(2, 2).write(writer); // Biomes
|
|
||||||
}
|
|
||||||
final int dataLength = buffer.position() - index - 3;
|
|
||||||
Utils.writeVarIntHeader(buffer, index, dataLength);
|
|
||||||
}
|
|
||||||
// Block entities
|
|
||||||
writer.writeVarInt(0);
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class LightPacketData implements Writeable {
|
public final class LightData implements Writeable {
|
||||||
private final boolean trustEdges;
|
private final boolean trustEdges;
|
||||||
private final BitSet skyMask;
|
private final BitSet skyMask;
|
||||||
private final BitSet blockMask;
|
private final BitSet blockMask;
|
||||||
@ -16,10 +16,10 @@ public final class LightPacketData implements Writeable {
|
|||||||
private final List<byte[]> skyLight;
|
private final List<byte[]> skyLight;
|
||||||
private final List<byte[]> blockLight;
|
private final List<byte[]> blockLight;
|
||||||
|
|
||||||
public LightPacketData(boolean trustEdges,
|
public LightData(boolean trustEdges,
|
||||||
BitSet skyMask, BitSet blockMask,
|
BitSet skyMask, BitSet blockMask,
|
||||||
BitSet emptySkyMask, BitSet emptyBlockMask,
|
BitSet emptySkyMask, BitSet emptyBlockMask,
|
||||||
List<byte[]> skyLight, List<byte[]> blockLight) {
|
List<byte[]> skyLight, List<byte[]> blockLight) {
|
||||||
this.trustEdges = trustEdges;
|
this.trustEdges = trustEdges;
|
||||||
this.skyMask = skyMask;
|
this.skyMask = skyMask;
|
||||||
this.blockMask = blockMask;
|
this.blockMask = blockMask;
|
@ -312,8 +312,8 @@ public class BinaryWriter extends OutputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void write(@NotNull ByteBuffer buffer) {
|
public void write(@NotNull ByteBuffer buffer) {
|
||||||
ensureSize(buffer.position());
|
ensureSize(buffer.remaining());
|
||||||
this.buffer.put(buffer.flip());
|
this.buffer.put(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(@NotNull BinaryWriter writer) {
|
public void write(@NotNull BinaryWriter writer) {
|
||||||
|
Loading…
Reference in New Issue
Block a user