Archived
0

уточнение алгоритма сериализации чанков (ChunkDataPacket)

This commit is contained in:
2018-08-16 11:40:04 +03:00
parent 54992d8b59
commit e17acb812b
7 changed files with 95 additions and 26 deletions

View File

@@ -13,7 +13,8 @@ import mc.core.events.SC_ChunkLoadEvent;
import mc.core.player.PlayerManager; import mc.core.player.PlayerManager;
import mc.core.time.TimeProcessor; import mc.core.time.TimeProcessor;
import mc.core.utils.CompactedCoords; import mc.core.utils.CompactedCoords;
import mc.core.world.chunk.ChunkSection; import mc.core.world.World;
import mc.core.world.chunk.Chunk;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@Slf4j @Slf4j
@@ -49,30 +50,31 @@ public class GameLoop extends Thread {
log.trace("(GameLoop) playerMoveEventHandler()"); log.trace("(GameLoop) playerMoveEventHandler()");
event.getPlayer().getLocation().setXYZ(event.getNewLocation()); event.getPlayer().getLocation().setXYZ(event.getNewLocation());
ChunkSection chunkSection = event.getNewLocation().getChunkSection(); Chunk chunk = event.getNewLocation().getChunk(); // Next chunk
int ncX = chunkSection.getX(); int ncX = chunk.getX();
int ncZ = chunkSection.getZ(); int ncZ = chunk.getZ();
chunkSection = event.getPlayer().getLocation().getChunkSection(); chunk = event.getPlayer().getLocation().getChunk(); // Current chunk
int ccX = chunkSection.getX(); int ccX = chunk.getX();
int ccZ = chunkSection.getZ(); int ccZ = chunk.getZ();
if (event.isRecalcChunk() || (ncX != ccX && ncZ != ccZ)) { if (event.isRecalcChunk() || (ncX != ccX && ncZ != ccZ)) {
/* FIXME заменить "8" на актуальный view distance */ final int viewDistance = event.getPlayer().getSettings().getViewDistance();
final int viewDistance = 8; int cMinX = chunk.getX() - viewDistance;
int cMinX = chunkSection.getX() - viewDistance; int cMaxX = chunk.getX() + viewDistance;
int cMaxX = chunkSection.getX() + viewDistance; int cMinZ = chunk.getZ() - viewDistance;
int cMinZ = chunkSection.getZ() - viewDistance; int cMaxZ = chunk.getZ() + viewDistance;
int cMaxZ = chunkSection.getZ() + viewDistance;
SC_ChunkLoadEvent eventChunkLoad = new SC_ChunkLoadEvent(event.getPlayer()); SC_ChunkLoadEvent eventChunkLoad = new SC_ChunkLoadEvent(event.getPlayer());
for (int cZ = cMinZ; cZ <= cMaxZ; cZ++) { for (int cZ = cMinZ; cZ <= cMaxZ; cZ++) {
for (int cX = cMinX; cX <= cMaxX; cX++) { for (int cX = cMinX; cX <= cMaxX; cX++) {
int compressXZ = CompactedCoords.compressXZ(cX, cZ); int compressXZ = CompactedCoords.compressXZ(cX, cZ);
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) { if (!event.getPlayer().getLoadedChunks().contains(compressXZ)) {
eventChunkLoad.getNeedLoadChunks().add(compressXZ); eventChunkLoad.getNeedLoadChunks().add(compressXZ);
} }
} }
} }
}
if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) { if (!eventChunkLoad.getNeedLoadChunks().isEmpty()) {
EventBusGetter.INSTANCE.post(eventChunkLoad); EventBusGetter.INSTANCE.post(eventChunkLoad);

View File

@@ -12,6 +12,8 @@ import mc.core.player.Player;
import mc.core.player.PlayerManager; import mc.core.player.PlayerManager;
import mc.core.text.Text; import mc.core.text.Text;
import mc.core.text.Title; import mc.core.text.Title;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;

View File

@@ -4,6 +4,7 @@
*/ */
package mc.core.world.chunk; package mc.core.world.chunk;
import mc.core.world.Biome;
import mc.core.world.World; import mc.core.world.World;
import mc.core.world.block.Block; import mc.core.world.block.Block;
@@ -22,5 +23,7 @@ public interface ChunkSection {
int getAddition(int x, int y, int z); int getAddition(int x, int y, int z);
void setAddition(int x, int y, int z, int value); void setAddition(int x, int y, int z, int value);
Biome getBiome(int localX, int localZ);
World getWorld(); World getWorld();
} }

View File

@@ -4,12 +4,17 @@
*/ */
package mc.world.flat; package mc.world.flat;
import mc.core.world.Biome;
import mc.core.world.World; import mc.core.world.World;
import mc.core.world.block.Block; import mc.core.world.block.Block;
import mc.core.world.block.BlockFactory; import mc.core.world.block.BlockFactory;
import mc.core.world.block.BlockType; import mc.core.world.block.BlockType;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection; import mc.core.world.chunk.ChunkSection;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
public class SimpleChunkSection implements ChunkSection { public class SimpleChunkSection implements ChunkSection {
@Override @Override
public int getSkyLight(int x, int y, int z) { public int getSkyLight(int x, int y, int z) {
@@ -19,7 +24,6 @@ public class SimpleChunkSection implements ChunkSection {
@Override @Override
public void setSkyLight(int x, int y, int z, int lightLevel) { public void setSkyLight(int x, int y, int z, int lightLevel) {
} }
@Override @Override
@@ -29,7 +33,11 @@ public class SimpleChunkSection implements ChunkSection {
@Override @Override
public void setAddition(int x, int y, int z, int value) { public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int localX, int localZ) {
return Biome.PLAINS;
} }
@Override @Override
@@ -49,7 +57,6 @@ public class SimpleChunkSection implements ChunkSection {
@Override @Override
public void setBlock(Block block) { public void setBlock(Block block) {
} }
@Override @Override

View File

@@ -17,6 +17,8 @@ import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection; import mc.core.world.chunk.ChunkSection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
/* /*
@@ -77,26 +79,74 @@ public class ChunkDataPacket implements SCPacket {
private int z; private int z;
@Setter @Setter
private boolean initChunk = true; // "Ground-Up Continuous" private boolean initChunk = true; // "Ground-Up Continuous"
@Setter
private Chunk chunk; private Chunk chunk;
private List<ChunkSection> sectionList;
private int serializeBlockState(BlockType blockType) { private int serializeBlockState(BlockType blockType) {
return (blockType.getId() << 4) | blockType.getMeta(); return (blockType.getId() << 4) | blockType.getMeta();
} }
public void setChunk(Chunk chunk) {
this.sectionList = null;
this.chunk = chunk;
}
public void setChunkSectionList(List<ChunkSection> sectionList) {
this.chunk = null;
this.sectionList = sectionList;
}
@Override @Override
public void writeSelf(NetOutputStream netStream) { public void writeSelf(NetOutputStream netStream) {
netStream.writeInt(x); // Chunk X netStream.writeInt(x); // Chunk X
netStream.writeInt(z); // Chunk Y netStream.writeInt(z); // Chunk Y
netStream.writeBoolean(initChunk); // Init Chunk netStream.writeBoolean(initChunk); // Init Chunk
netStream.writeVarInt(0b00000001); // Primary Bit Mask
if (sectionList == null && chunk != null) {
int bitMask = 0;
for (int h = 15; h >= 0; h--) {
bitMask = bitMask << 1;
ChunkSection chunkSection = chunk.getChunkSection(h);
if (chunkSection != null && chunkSection.getY() == h) {
bitMask |= 0x01;
} else {
bitMask |= 0x00;
}
}
netStream.writeVarInt(bitMask); // Primary Bit Mask
} else if (sectionList != null && chunk == null) {
sectionList.sort(Comparator.comparingInt(ChunkSection::getY));
int bitMask = 0;
for (int h = 15, i = 0; h >= 0; h--) {
bitMask = bitMask << 1;
ChunkSection chunkSection = sectionList.get(i);
if (chunkSection != null && chunkSection.getY() == h) {
bitMask |= 0x01;
} else {
bitMask |= 0x00;
}
}
netStream.writeVarInt(bitMask); // Primary Bit Mask
} else {
log.warn("Empty chunk data");
return;
}
final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream(); final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream();
int dataItems = 0; int dataItems = 0;
final int airBlockPalette = serializeBlockState(BlockType.AIR); final int airBlockPalette = serializeBlockState(BlockType.AIR);
for (int h = 0; h < 1/*потому что у нас пока только единичная сейция*/; h++) { for (int h = 0; h < 16; h++) {
ChunkSection chunkSection = chunk.getChunkSection(h); ChunkSection chunkSection = null;
if (chunk != null) {
chunkSection = chunk.getChunkSection(h);
} else if (sectionList != null) {
chunkSection = sectionList.remove(0);
}
if (chunkSection == null) { if (chunkSection == null) {
continue; continue;
} }
@@ -156,7 +206,7 @@ public class ChunkDataPacket implements SCPacket {
} }
if (!biomeFinally) { if (!biomeFinally) {
biomes.writeByte(chunk.getBiome(x, z).getId()); biomes.writeByte(chunkSection.getBiome(x, z).getId());
if (x == 15 && z == 15) { if (x == 15 && z == 15) {
biomeFinally = true; biomeFinally = true;
} }

View File

@@ -31,6 +31,11 @@ public class DummyWorld implements World {
public void setAddition(int x, int y, int z, int value) { public void setAddition(int x, int y, int z, int value) {
} }
@Override
public Biome getBiome(int localX, int localZ) {
return Biome.PLAINS;
}
@Override @Override
public int getX() { public int getX() {
return 0; return 0;

View File

@@ -64,7 +64,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
pkt1.setMode(PlayerMode.CREATIVE); pkt1.setMode(PlayerMode.CREATIVE);
pkt1.setDimension(0/*Overworld*/); pkt1.setDimension(0/*Overworld*/);
pkt1.setDifficulty(0/*Peaceful*/); pkt1.setDifficulty(0/*Peaceful*/);
pkt1.setLevelType("flat"); //FIXME pkt1.setLevelType(world.getWorldType().getName());
channel.write(pkt1); channel.write(pkt1);
// Spawn Position // Spawn Position
@@ -81,11 +81,11 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
channel.write(pkt3); channel.write(pkt3);
channel.flush(); channel.flush();
// One Chunk // First Chunk
ChunkDataPacket pkt8 = new ChunkDataPacket(); ChunkDataPacket pkt8 = new ChunkDataPacket();
pkt8.setX(0); pkt8.setX(player.getLocation().getChunk().getX());
pkt8.setZ(0); pkt8.setZ(player.getLocation().getChunk().getZ());
pkt8.setChunk(world.getChunk(0, 0)); pkt8.setChunk(player.getLocation().getChunk());
pkt8.setInitChunk(true); pkt8.setInitChunk(true);
channel.writeAndFlush(pkt8); channel.writeAndFlush(pkt8);
player.getLoadedChunks().add(CompactedCoords.compressXZ(0, 0)); player.getLoadedChunks().add(CompactedCoords.compressXZ(0, 0));