уточнение алгоритма сериализации чанков (ChunkDataPacket)
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
Reference in New Issue
Block a user