Add basic block entity support, simplify code

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-10-21 10:36:14 +02:00
parent 201b5500b9
commit 972e15a62b
8 changed files with 100 additions and 67 deletions

View File

@ -8,14 +8,16 @@ import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFBlock;
import net.minestom.server.instance.block.Block;
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.play.ChunkDataPacket;
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.LightPacketData;
import net.minestom.server.network.packet.server.play.data.ChunkData;
import net.minestom.server.network.packet.server.play.data.LightData;
import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Utils;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
@ -170,12 +172,20 @@ public class DynamicChunk extends Chunk {
.setLongArray("MOTION_BLOCKING", Utils.encodeBlocks(motionBlocking, 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();
packet.chunkX = chunkX;
packet.chunkZ = chunkZ;
// TODO deep clone sections
packet.chunkData = new ChunkPacketData(heightmapsNBT, sectionMap, entries);
packet.chunkData = new ChunkData(heightmapsNBT, writer.getBuffer().flip(), entries);
packet.lightData = createLightData();
return packet;
}
@ -188,7 +198,7 @@ public class DynamicChunk extends Chunk {
return updateLightPacket;
}
private LightPacketData createLightData() {
private LightData createLightData() {
BitSet skyMask = new BitSet();
BitSet blockMask = new BitSet();
BitSet emptySkyMask = new BitSet();
@ -213,7 +223,7 @@ public class DynamicChunk extends Chunk {
blockMask.set(index);
}
}
return new LightPacketData(true,
return new LightData(true,
skyMask, blockMask,
emptySkyMask, emptyBlockMask,
skyLights, blockLights);

View File

@ -162,6 +162,6 @@ public class ItemMeta implements TagReadable, Writeable {
w.writeNBT("", nbt);
this.cachedBuffer = w.getBuffer();
}
writer.write(cachedBuffer);
writer.write(cachedBuffer.flip());
}
}

View File

@ -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.ServerPacketIdentifier;
import net.minestom.server.network.packet.server.play.data.ChunkPacketData;
import net.minestom.server.network.packet.server.play.data.LightPacketData;
import net.minestom.server.network.packet.server.play.data.ChunkData;
import net.minestom.server.network.packet.server.play.data.LightData;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ChunkDataPacket implements ServerPacket {
public int chunkX, chunkZ;
public ChunkPacketData chunkData;
public LightPacketData lightData;
public ChunkData chunkData;
public LightData lightData;
public ChunkDataPacket() {
}

View File

@ -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.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.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -11,7 +11,7 @@ public class UpdateLightPacket implements ServerPacket {
public int chunkX;
public int chunkZ;
public LightPacketData lightData;
public LightData lightData;
/**
* Default constructor, required for reflection operations.

View File

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

View File

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

View File

@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.BitSet;
import java.util.List;
public final class LightPacketData implements Writeable {
public final class LightData implements Writeable {
private final boolean trustEdges;
private final BitSet skyMask;
private final BitSet blockMask;
@ -16,10 +16,10 @@ public final class LightPacketData implements Writeable {
private final List<byte[]> skyLight;
private final List<byte[]> blockLight;
public LightPacketData(boolean trustEdges,
BitSet skyMask, BitSet blockMask,
BitSet emptySkyMask, BitSet emptyBlockMask,
List<byte[]> skyLight, List<byte[]> blockLight) {
public LightData(boolean trustEdges,
BitSet skyMask, BitSet blockMask,
BitSet emptySkyMask, BitSet emptyBlockMask,
List<byte[]> skyLight, List<byte[]> blockLight) {
this.trustEdges = trustEdges;
this.skyMask = skyMask;
this.blockMask = blockMask;

View File

@ -312,8 +312,8 @@ public class BinaryWriter extends OutputStream {
}
public void write(@NotNull ByteBuffer buffer) {
ensureSize(buffer.position());
this.buffer.put(buffer.flip());
ensureSize(buffer.remaining());
this.buffer.put(buffer);
}
public void write(@NotNull BinaryWriter writer) {