Archived
0

решение проблемы с непрорисованными чанками

Проблема оказалась вот в чем: если вокруг карты(зоны?) имеются незагруженные чанки ("Waiting for chunk..."),
то клиент начинает дурить и перестает крайние чанки этой карты(зоны?) отрисовывать.

Решение проблемы:всегда отдавать чанк клиенту. Если по какой-то причине Chunk будет null,
то нужно будет отправить Пустой чанк (EmptyChunk), у которого все блоки - это AIR.
This commit is contained in:
2019-01-27 20:51:39 +03:00
parent cebc19fd3f
commit 2ce3871424
2 changed files with 163 additions and 4 deletions

View File

@@ -0,0 +1,153 @@
package mc.world.anvil;
import lombok.Getter;
import lombok.NoArgsConstructor;
import mc.core.world.Biome;
import mc.core.world.block.Block;
import mc.core.world.block.BlockLocation;
import mc.core.world.block.BlockType;
import mc.core.world.chunk.Chunk;
import mc.core.world.chunk.ChunkSection;
import java.util.LinkedList;
import java.util.List;
@Getter
public class EmptyChunk implements Chunk {
private int x;
private int z;
private List<ChunkSection> $sections = new LinkedList<>();
public EmptyChunk(int x, int z) {
this.x = x;
this.z = z;
for (int i = 0; i < 16; i++) {
this.$sections.add(null);
}
}
@Override
public ChunkSection getChunkSection(int height) {
ChunkSection section;
if ((section = $sections.get(height)) == null) {
section = new EmptySection(height);
$sections.set(height, section);
}
return section;
}
@Override
public void setChunkSection(int height, ChunkSection chunkSection) {
}
@Override
public Block getBlock(int x, int y, int z) {
return getChunkSection(y >> 4).getBlock(
x - getX() << 4,
y - (y >> 4) << 4,
z - getZ() << 4
);
}
@Override
public void setBlock(Block block) {
}
@Override
public int getSkyLight(int x, int y, int z) {
return getChunkSection(y >> 4).getSkyLight(x, y, z);
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getAddition(int x, int y, int z) {
return getChunkSection(y >> 4).getAddition(x, y, z);
}
@Override
public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int x, int z) {
return Biome.PLAINS;
}
@Override
public void setBiome(int x, int z, Biome biome) {
}
@NoArgsConstructor
@Getter
public class EmptySection implements ChunkSection {
private int y;
EmptySection(int y) {
this.y = y;
}
@Override
public Chunk getParent() {
return EmptyChunk.this;
}
@Override
public void setParent(Chunk chunk) {
}
@Override
public Block getBlock(int localX, int localY, int localZ) {
return new Block() {
@Override
public int getLight() {
return 15;
}
@Override
public void setLight(int light) {
}
@Override
public BlockType getType() {
return BlockType.AIR;
}
@Override
public BlockLocation getLocation() {
return new BlockLocation(
(getParent().getX() << 4) + localX,
(getY() << 4) + localY,
(getParent().getZ() << 4) + localZ
);
}
};
}
@Override
public void setBlock(Block block) {
}
@Override
public int getSkyLight(int localX, int localY, int localZ) {
return 15;
}
@Override
public void setSkyLight(int localX, int localY, int localZ, int lightLevel) {
}
@Override
public int getAddition(int localX, int localY, int localZ) {
return 0;
}
@Override
public void setAddition(int localX, int localY, int localZ, int value) {
}
}
}

View File

@@ -53,20 +53,26 @@ class Region implements Closeable {
try { try {
offset = getOffset(x, z); offset = getOffset(x, z);
} catch (Exception e) { } catch (Exception e) {
return null; return new EmptyChunk(x, z);
} }
if (offset == 0) return null; if (offset == 0) {
return new EmptyChunk(x, z);
}
int v1 = offset >> 8; int v1 = offset >> 8;
int v2 = offset & 255; int v2 = offset & 255;
if (v1 + v2 > sectorFree.size()) return null; if (v1 + v2 > sectorFree.size()) {
return new EmptyChunk(x, z);
}
try { try {
file.seek((long) (v1 * 4096)); file.seek((long) (v1 * 4096));
int read = file.readInt(); int read = file.readInt();
if (read <= 0 || read > 4096 * v2) return null; if (read <= 0 || read > 4096 * v2) {
return new EmptyChunk(x, z);
}
boolean gzippedData = (file.readByte() == 0x01); boolean gzippedData = (file.readByte() == 0x01);