сериализация полного чанка
This commit is contained in:
@@ -2,17 +2,12 @@ package mc.protocol.packets.play.server;
|
|||||||
|
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import mc.protocol.buffer.NetByteBuf;
|
import mc.protocol.buffer.NetByteBuf;
|
||||||
import mc.protocol.packets.ServerSidePacket;
|
import mc.protocol.packets.ServerSidePacket;
|
||||||
import mc.protocol.pool.ProtocolObjectPool;
|
import mc.protocol.pool.ProtocolObjectPool;
|
||||||
import mc.protocol.world.Block;
|
import mc.protocol.utils.ChunkSerializeUtil;
|
||||||
import mc.protocol.world.Chunk;
|
import mc.protocol.world.Chunk;
|
||||||
import mc.protocol.world.ChunkSection;
|
import mc.protocol.world.ChunkSection;
|
||||||
import mc.utils.array.BitArray;
|
|
||||||
import mc.utils.array.BitByteArray;
|
|
||||||
import mc.utils.array.BitLongArray;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Данные чанка.
|
* Данные чанка.
|
||||||
@@ -79,9 +74,7 @@ import mc.utils.array.BitLongArray;
|
|||||||
@Data
|
@Data
|
||||||
public class ChunkDataPacket implements ServerSidePacket {
|
public class ChunkDataPacket implements ServerSidePacket {
|
||||||
|
|
||||||
private static final int BITS_PER_BLOCK = 13;
|
|
||||||
private static final int FULL_BIT_MASK = 0b11111111_11111111;
|
private static final int FULL_BIT_MASK = 0b11111111_11111111;
|
||||||
private static final int _16_16_16 = 16 * 16 * 16;
|
|
||||||
|
|
||||||
private Chunk chunk;
|
private Chunk chunk;
|
||||||
|
|
||||||
@@ -90,12 +83,10 @@ public class ChunkDataPacket implements ServerSidePacket {
|
|||||||
netByteBuf.writeInt(chunk.getX()); // Chunk X
|
netByteBuf.writeInt(chunk.getX()); // Chunk X
|
||||||
netByteBuf.writeInt(chunk.getZ()); // Chunk Z
|
netByteBuf.writeInt(chunk.getZ()); // Chunk Z
|
||||||
|
|
||||||
AvailableSections availableSections = createAvailableSections();
|
netByteBuf.writeBoolean(true); // Is Full chunk
|
||||||
boolean fullChunk = availableSections.getBitMask() == FULL_BIT_MASK;
|
netByteBuf.writeVarInt(FULL_BIT_MASK); // Available Sections
|
||||||
netByteBuf.writeBoolean(fullChunk); // Is Full chunk
|
|
||||||
netByteBuf.writeVarInt(availableSections.getBitMask()); // Available Sections
|
|
||||||
|
|
||||||
NetByteBuf data = createDataStructure(availableSections.getMaxHeight(), fullChunk);
|
NetByteBuf data = createDataStructure();
|
||||||
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
|
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
|
||||||
netByteBuf.writeBytes(data); // Data
|
netByteBuf.writeBytes(data); // Data
|
||||||
|
|
||||||
@@ -105,108 +96,26 @@ public class ChunkDataPacket implements ServerSidePacket {
|
|||||||
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
|
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AvailableSections createAvailableSections() {
|
private NetByteBuf createDataStructure() {
|
||||||
int bitMask = 0;
|
|
||||||
int maxH = 0;
|
|
||||||
for (int h = 15; h >= 0; h--) {
|
|
||||||
bitMask = bitMask << 1;
|
|
||||||
ChunkSection chunkSection = chunk.getSection(h);
|
|
||||||
if (chunkSection != null && chunkSection.getY() == h) {
|
|
||||||
bitMask |= 0x01;
|
|
||||||
maxH++;
|
|
||||||
} else {
|
|
||||||
bitMask |= 0x00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AvailableSections(bitMask, maxH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private NetByteBuf createDataStructure(int maxHeight, boolean fillBiomes) {
|
|
||||||
NetByteBuf dataStructure = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
|
NetByteBuf dataStructure = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
|
||||||
NetByteBuf biomes = fillBiomes ? ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer()) : null;
|
|
||||||
|
|
||||||
for (int h = 0; h < maxHeight; h++) {
|
for (int h = 0; h < 16; h++) {
|
||||||
ChunkSection section = chunk.getSection(h);
|
ChunkSection section = chunk.getSection(h);
|
||||||
if (section == null) {
|
NetByteBuf data = ChunkSerializeUtil.serializeSection(section);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetByteBuf data = createData(section, biomes);
|
|
||||||
dataStructure.writeBytes(data); // Data
|
dataStructure.writeBytes(data); // Data
|
||||||
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
|
ProtocolObjectPool.getNetByteBufPool().returnObject(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fillBiomes) {
|
// <Biomes>
|
||||||
dataStructure.writeBytes(biomes); // Biomes
|
for (int z = 0; z < 16; z++) {
|
||||||
ProtocolObjectPool.getNetByteBufPool().returnObject(biomes);
|
for (int x = 0; x < 16; x++) {
|
||||||
|
dataStructure.writeByte(chunk.getBiome(
|
||||||
|
(chunk.getX() << 4) + x,
|
||||||
|
(chunk.getZ() << 4) + z));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// </Biomes>
|
||||||
|
|
||||||
return dataStructure;
|
return dataStructure;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetByteBuf createData(ChunkSection section, NetByteBuf biomes) {
|
|
||||||
NetByteBuf data = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
|
|
||||||
|
|
||||||
BitArray blockLight = new BitByteArray(4, 2048 * 2);
|
|
||||||
BitArray skyLight = new BitByteArray(4, 2048 * 2);
|
|
||||||
|
|
||||||
// <Bits Per Block>
|
|
||||||
data.writeUnsignedByte(BITS_PER_BLOCK);
|
|
||||||
// </Bits Per Block>
|
|
||||||
|
|
||||||
// <Palette>
|
|
||||||
data.writeVarInt(0); // Direct mode
|
|
||||||
// </Palette>
|
|
||||||
|
|
||||||
// <Data Array Length>
|
|
||||||
data.writeVarInt(_16_16_16);
|
|
||||||
// </Data Array Length>
|
|
||||||
|
|
||||||
// <Data Array>
|
|
||||||
BitArray dataArray = new BitLongArray(BITS_PER_BLOCK, _16_16_16);
|
|
||||||
boolean writeBiomes = biomes != null;
|
|
||||||
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
Block block = section.getBlock(x, y, z);
|
|
||||||
int blockState = (block.getId() << 4) | block.getMeta();
|
|
||||||
dataArray.put(blockState);
|
|
||||||
|
|
||||||
blockLight.put(block.getLight());
|
|
||||||
skyLight.put(section.getSkyLight(x, y, z));
|
|
||||||
|
|
||||||
if (writeBiomes) {
|
|
||||||
biomes.writeByte(chunk.getBiome(
|
|
||||||
(chunk.getX() << 4) + x,
|
|
||||||
(chunk.getZ() << 4) + z));
|
|
||||||
|
|
||||||
if (x == 15 && z == 15) {
|
|
||||||
writeBiomes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.writeBytes(dataArray.byteBuffer());
|
|
||||||
// </Data Array>
|
|
||||||
|
|
||||||
// <Block Light>
|
|
||||||
data.writeBytes(blockLight.byteBuffer());
|
|
||||||
// </Block Light>
|
|
||||||
|
|
||||||
// <Sky Light>
|
|
||||||
data.writeBytes(skyLight.byteBuffer());
|
|
||||||
// </Sky Light>
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
private static class AvailableSections {
|
|
||||||
private final int bitMask;
|
|
||||||
private final int maxHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package mc.protocol.utils;
|
||||||
|
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import mc.protocol.buffer.NetByteBuf;
|
||||||
|
import mc.protocol.pool.ProtocolObjectPool;
|
||||||
|
import mc.protocol.world.Block;
|
||||||
|
import mc.protocol.world.ChunkSection;
|
||||||
|
import mc.utils.array.BitArray;
|
||||||
|
import mc.utils.array.BitByteArray;
|
||||||
|
import mc.utils.array.BitLongArray;
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public final class ChunkSerializeUtil {
|
||||||
|
|
||||||
|
private static final int BITS_PER_BLOCK = 13;
|
||||||
|
private static final int ALL_BLOCKS = 16 * 16 * 16;
|
||||||
|
|
||||||
|
public static NetByteBuf serializeSection(ChunkSection section) {
|
||||||
|
BitArray blockArray = new BitLongArray(BITS_PER_BLOCK, ALL_BLOCKS);
|
||||||
|
BitArray blockLight = new BitByteArray(4, ALL_BLOCKS);
|
||||||
|
BitArray skyLight = new BitByteArray(4, ALL_BLOCKS);
|
||||||
|
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
Block block = section.getBlock(x, y, z);
|
||||||
|
int blockState = (block.getId() << 4) | block.getMeta();
|
||||||
|
|
||||||
|
blockArray.put(blockState);
|
||||||
|
blockLight.put(block.getLight());
|
||||||
|
skyLight.put(section.getSkyLight(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetByteBuf result = ProtocolObjectPool.getNetByteBufPool().borrowObject().setByteBuf(Unpooled.buffer());
|
||||||
|
result.writeUnsignedByte(BITS_PER_BLOCK); // Bits Per Block
|
||||||
|
result.writeVarInt(0); // Palette, Direct mode
|
||||||
|
result.writeVarInt(blockArray.size()); // Data Array Length
|
||||||
|
result.writeBytes(blockArray.byteBuffer()); // Data Array
|
||||||
|
result.writeBytes(blockLight.byteBuffer()); // Block Light
|
||||||
|
result.writeBytes(skyLight.byteBuffer()); // Sky Light
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,7 +67,7 @@ public class Main {
|
|||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
ServerComponent serverComponent = DaggerServerComponent.builder()
|
ServerComponent serverComponent = DaggerServerComponent.builder()
|
||||||
.processorModule(new ScenarioModule(configComponent.getConfig()))
|
.scenarioModule(new ScenarioModule(configComponent.getConfig()))
|
||||||
.build();
|
.build();
|
||||||
serverComponent.getPacketScenarios().forEach(scenario -> scenario.setup(serverComponent.getProtocolHandlersBus()));
|
serverComponent.getPacketScenarios().forEach(scenario -> scenario.setup(serverComponent.getProtocolHandlersBus()));
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mc.server.di;
|
|||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import mc.protocol.world.World;
|
import mc.protocol.world.World;
|
||||||
import mc.server.world.VoidWorld;
|
import mc.server.world.SomeWorld;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
@@ -13,6 +13,6 @@ public class WorldModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
World provideWorld() {
|
World provideWorld() {
|
||||||
return new VoidWorld();
|
return new SomeWorld();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class ScenarioLogin implements PacketScenario {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void login(ChannelHandlerContext ctx, LoginStartPacket packet) {
|
private void login(ChannelHandlerContext ctx, LoginStartPacket packet) {
|
||||||
Player player = playerManager.create(ctx, packet.getName(), GameMode.SURVIVAL, world.getSpawn());
|
Player player = playerManager.create(ctx, packet.getName(), GameMode.CREATIVE, world.getSpawn());
|
||||||
ctx.channel().attr(ServetAttributes.PLAYER).set(player);
|
ctx.channel().attr(ServetAttributes.PLAYER).set(player);
|
||||||
|
|
||||||
sendLoginSuccess(player);
|
sendLoginSuccess(player);
|
||||||
@@ -85,7 +85,7 @@ public class ScenarioLogin implements PacketScenario {
|
|||||||
var playerAbilitiesPacket = new PlayerAbilitiesPacket();
|
var playerAbilitiesPacket = new PlayerAbilitiesPacket();
|
||||||
playerAbilitiesPacket.setCatFly(true);
|
playerAbilitiesPacket.setCatFly(true);
|
||||||
playerAbilitiesPacket.setFlying(true);
|
playerAbilitiesPacket.setFlying(true);
|
||||||
playerAbilitiesPacket.setCreativeMode(false);
|
playerAbilitiesPacket.setCreativeMode(true);
|
||||||
playerAbilitiesPacket.setInvulnerable(true);
|
playerAbilitiesPacket.setInvulnerable(true);
|
||||||
playerAbilitiesPacket.setFieldOfView(0.0f);
|
playerAbilitiesPacket.setFieldOfView(0.0f);
|
||||||
playerAbilitiesPacket.setFlyingSpeed(0.05f);
|
playerAbilitiesPacket.setFlyingSpeed(0.05f);
|
||||||
@@ -96,7 +96,8 @@ public class ScenarioLogin implements PacketScenario {
|
|||||||
@SuppressWarnings("java:S2589")
|
@SuppressWarnings("java:S2589")
|
||||||
private void sendWorldData(Player player) {
|
private void sendWorldData(Player player) {
|
||||||
Location chunkLocation = LocationUtils.toChunkXZ(player.getLocation());
|
Location chunkLocation = LocationUtils.toChunkXZ(player.getLocation());
|
||||||
Chunk chunk = world.getChunk((int) chunkLocation.getX(), (int) chunkLocation.getZ());
|
// Chunk chunk = world.getChunk((int) chunkLocation.getX(), (int) chunkLocation.getZ());
|
||||||
|
Chunk chunk = world.getChunk(-50, -16);
|
||||||
|
|
||||||
var chunkDataPacket = new ChunkDataPacket();
|
var chunkDataPacket = new ChunkDataPacket();
|
||||||
chunkDataPacket.setChunk(chunk);
|
chunkDataPacket.setChunk(chunk);
|
||||||
@@ -112,12 +113,15 @@ public class ScenarioLogin implements PacketScenario {
|
|||||||
for (int x = minX; x <= maxX; x++) {
|
for (int x = minX; x <= maxX; x++) {
|
||||||
if ((z == minZ || z == maxZ) || (x == minX || x == maxX)) {
|
if ((z == minZ || z == maxZ) || (x == minX || x == maxX)) {
|
||||||
chunkDataPacket = new ChunkDataPacket();
|
chunkDataPacket = new ChunkDataPacket();
|
||||||
chunkDataPacket.setChunk(world.getChunk(x, z));
|
chunk = world.getChunk(x, z);
|
||||||
|
if (chunk != null) {
|
||||||
|
chunkDataPacket.setChunk(chunk);
|
||||||
player.getCtx().write(chunkDataPacket);
|
player.getCtx().write(chunkDataPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
player.getCtx().flush();
|
player.getCtx().flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
package mc.server.world;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.world.Block;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AirBlock implements Block {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final Location location;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMeta() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLight() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLight(int value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
server/src/main/java/mc/server/world/SomeBlock.java
Normal file
14
server/src/main/java/mc/server/world/SomeBlock.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package mc.server.world;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import mc.protocol.model.Location;
|
||||||
|
import mc.protocol.world.Block;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SomeBlock implements Block {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private int meta;
|
||||||
|
private int light;
|
||||||
|
private Location location;
|
||||||
|
}
|
||||||
@@ -8,19 +8,19 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class VoidChunk implements Chunk {
|
public class SomeChunk implements Chunk {
|
||||||
|
|
||||||
private final int x;
|
private final int x;
|
||||||
private final int z;
|
private final int z;
|
||||||
private final Map<Integer, VoidChunkSection> sections = new HashMap<>();
|
private final Map<Integer, ChunkSection> sections = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChunkSection getSection(int height) {
|
public ChunkSection getSection(int height) {
|
||||||
return sections.computeIfAbsent(height, VoidChunkSection::new);
|
return sections.computeIfAbsent(height, SomeChunkSection::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getBiome(int x, int z) {
|
public byte getBiome(int x, int z) {
|
||||||
return 127; // 127 | 7F | minecraft:void | The Void
|
return 0; //ocean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
56
server/src/main/java/mc/server/world/SomeChunkSection.java
Normal file
56
server/src/main/java/mc/server/world/SomeChunkSection.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package mc.server.world;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import mc.protocol.model.Location;
|
||||||
|
import mc.protocol.world.Block;
|
||||||
|
import mc.protocol.world.ChunkSection;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class SomeChunkSection implements ChunkSection {
|
||||||
|
|
||||||
|
private final int y;
|
||||||
|
private final Map<Location, Block> blocks = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getBlock(int x, int y, int z) {
|
||||||
|
if (this.y == 15) {
|
||||||
|
if (y == 0) {
|
||||||
|
return blocks.computeIfAbsent(new Location().set(x, y, z), location -> {
|
||||||
|
SomeBlock block = new SomeBlock();
|
||||||
|
block.setLocation(location);
|
||||||
|
block.setId(3);
|
||||||
|
return block;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return blocks.computeIfAbsent(new Location().set(x, y, z), location -> {
|
||||||
|
SomeBlock block = new SomeBlock();
|
||||||
|
block.setLocation(location);
|
||||||
|
block.setId(0);
|
||||||
|
return block;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return blocks.computeIfAbsent(new Location().set(x, y, z), location -> {
|
||||||
|
SomeBlock block = new SomeBlock();
|
||||||
|
block.setLocation(location);
|
||||||
|
block.setId(1);
|
||||||
|
return block;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSkyLight(int x, int y, int z) {
|
||||||
|
if (this.y == 15 && y != 0) {
|
||||||
|
return 15;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,14 +3,14 @@ package mc.server.world;
|
|||||||
import mc.protocol.model.Location;
|
import mc.protocol.model.Location;
|
||||||
import mc.protocol.pool.ProtocolObjectPool;
|
import mc.protocol.pool.ProtocolObjectPool;
|
||||||
import mc.protocol.utils.LevelType;
|
import mc.protocol.utils.LevelType;
|
||||||
import mc.protocol.utils.Table;
|
|
||||||
import mc.protocol.world.Chunk;
|
import mc.protocol.world.Chunk;
|
||||||
import mc.protocol.world.World;
|
import mc.protocol.world.World;
|
||||||
|
import mc.utils.Table;
|
||||||
|
|
||||||
public class VoidWorld implements World {
|
public class SomeWorld implements World {
|
||||||
|
|
||||||
private static final Location spawn = ProtocolObjectPool.getLocationPool().borrowObject().set(7d, 130d, 7d);
|
private static final Location spawn = ProtocolObjectPool.getLocationPool().borrowObject().set(-790d, 256d, -263d + 16d);
|
||||||
private final Table<Integer, Integer, VoidChunk> chunkTable = new Table<>();
|
private final Table<Integer, Integer, Chunk> chunkTable = new Table<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LevelType getLevelType() {
|
public LevelType getLevelType() {
|
||||||
@@ -19,14 +19,18 @@ public class VoidWorld implements World {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Location getSpawn() {
|
public Location getSpawn() {
|
||||||
return VoidWorld.spawn;
|
return SomeWorld.spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunk(int x, int z) {
|
public Chunk getChunk(int x, int z) {
|
||||||
VoidChunk chunk = chunkTable.getColumnAndRow(x, z);
|
if (x != -50 && z != -16) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk chunk = chunkTable.getColumnAndRow(x, z);
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
chunk = new VoidChunk(x, z);
|
chunk = new SomeChunk(x, z);
|
||||||
chunkTable.put(x, z, chunk);
|
chunkTable.put(x, z, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package mc.server.world;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import mc.protocol.model.Location;
|
|
||||||
import mc.protocol.world.Block;
|
|
||||||
import mc.protocol.world.ChunkSection;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
public class VoidChunkSection implements ChunkSection {
|
|
||||||
|
|
||||||
private final int y;
|
|
||||||
private final Map<Location, AirBlock> blocks = new HashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block getBlock(int x, int y, int z) {
|
|
||||||
return blocks.computeIfAbsent(new Location().set(x, y, z), AirBlock::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSkyLight(int x, int y, int z) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -23,5 +23,5 @@ icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
world {
|
world {
|
||||||
view-distance: 1
|
view-distance: 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,16 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
<!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>out.log</file>
|
||||||
|
<encoder>
|
||||||
|
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%35.35logger{34}] -- %msg%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>-->
|
||||||
|
|
||||||
<root level="info">
|
<root level="info">
|
||||||
<appender-ref ref="CONSOLE"/>
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<!--<appender-ref ref="FILE"/>-->
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<logger name="LAUNCHER" level="debug" additivity="false">
|
<logger name="LAUNCHER" level="debug" additivity="false">
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ public interface BitArray {
|
|||||||
int get(int index);
|
int get(int index);
|
||||||
|
|
||||||
ByteBuffer byteBuffer();
|
ByteBuffer byteBuffer();
|
||||||
|
int size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package mc.utils.array;
|
|||||||
|
|
||||||
public class BitByteArray extends AbstractBitBufferArray {
|
public class BitByteArray extends AbstractBitBufferArray {
|
||||||
|
|
||||||
|
private int countElements;
|
||||||
|
|
||||||
public BitByteArray(int bitPerEntity, int arraySize, boolean direct) {
|
public BitByteArray(int bitPerEntity, int arraySize, boolean direct) {
|
||||||
super(bitPerEntity, arraySize, direct);
|
super(bitPerEntity, arraySize, direct);
|
||||||
}
|
}
|
||||||
@@ -55,8 +57,16 @@ public class BitByteArray extends AbstractBitBufferArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return countElements;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateCapacity() {
|
protected int calculateCapacity() {
|
||||||
return (arraySize * bitPerEntity / Byte.SIZE + 1) * Byte.BYTES;
|
int bits = arraySize * bitPerEntity;
|
||||||
|
int var1 = bits % Byte.SIZE;
|
||||||
|
this.countElements = bits / Byte.SIZE + (var1 > 0 ? 1 : 0);
|
||||||
|
return countElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.nio.LongBuffer;
|
|||||||
public class BitLongArray extends AbstractBitBufferArray {
|
public class BitLongArray extends AbstractBitBufferArray {
|
||||||
|
|
||||||
private final LongBuffer longBuffer;
|
private final LongBuffer longBuffer;
|
||||||
|
private int countElements;
|
||||||
|
|
||||||
public BitLongArray(int bitPerEntity, int arraySize, boolean direct) {
|
public BitLongArray(int bitPerEntity, int arraySize, boolean direct) {
|
||||||
super(bitPerEntity, arraySize, direct);
|
super(bitPerEntity, arraySize, direct);
|
||||||
@@ -60,8 +61,17 @@ public class BitLongArray extends AbstractBitBufferArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return countElements;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateCapacity() {
|
protected int calculateCapacity() {
|
||||||
return (arraySize * bitPerEntity / Long.SIZE + 1) * Long.BYTES;
|
int bits = arraySize * bitPerEntity;
|
||||||
|
int var1 = bits % Long.SIZE;
|
||||||
|
int var2 = (bits + (var1 > 0 ? Long.SIZE - var1 : 0));
|
||||||
|
this.countElements = var2 / Long.SIZE;
|
||||||
|
return var2 / Byte.SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,21 @@ class BitByteArrayTest {
|
|||||||
assertEquals(1, byteBuffer.limit());
|
assertEquals(1, byteBuffer.limit());
|
||||||
assertEquals(0, byteBuffer.position());
|
assertEquals(0, byteBuffer.position());
|
||||||
assertEquals(1, byteBuffer.array().length);
|
assertEquals(1, byteBuffer.array().length);
|
||||||
|
assertEquals(1, bitArray.size());
|
||||||
|
|
||||||
bitArray = new BitByteArray(4, 2);
|
bitArray = new BitByteArray(4, 2);
|
||||||
byteBuffer = bitArray.byteBuffer();
|
byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
|
assertEquals(1, byteBuffer.capacity());
|
||||||
|
assertEquals(1, byteBuffer.limit());
|
||||||
|
assertEquals(1, bitArray.size());
|
||||||
|
|
||||||
|
bitArray = new BitByteArray(4, 3);
|
||||||
|
byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
assertEquals(2, byteBuffer.capacity());
|
assertEquals(2, byteBuffer.capacity());
|
||||||
assertEquals(2, byteBuffer.limit());
|
assertEquals(2, byteBuffer.limit());
|
||||||
|
assertEquals(2, bitArray.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ class BitLongArrayTest {
|
|||||||
assertEquals(8, byteBuffer.limit());
|
assertEquals(8, byteBuffer.limit());
|
||||||
assertEquals(0, byteBuffer.position());
|
assertEquals(0, byteBuffer.position());
|
||||||
assertEquals(8, byteBuffer.array().length);
|
assertEquals(8, byteBuffer.array().length);
|
||||||
|
assertEquals(1, bitArray.size());
|
||||||
|
|
||||||
bitArray = new BitLongArray(13, 5);
|
bitArray = new BitLongArray(13, 5);
|
||||||
byteBuffer = bitArray.byteBuffer();
|
byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
assertEquals(16, byteBuffer.capacity());
|
assertEquals(16, byteBuffer.capacity());
|
||||||
assertEquals(16, byteBuffer.limit());
|
assertEquals(16, byteBuffer.limit());
|
||||||
|
assertEquals(2, bitArray.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user