решение проблемы с непрорисованными чанками
Проблема оказалась вот в чем: если вокруг карты(зоны?) имеются незагруженные чанки ("Waiting for chunk..."),
то клиент начинает дурить и перестает крайние чанки этой карты(зоны?) отрисовывать.
Решение проблемы:всегда отдавать чанк клиенту. Если по какой-то причине Chunk будет null,
то нужно будет отправить Пустой чанк (EmptyChunk), у которого все блоки - это AIR.
This commit is contained in:
153
anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java
Normal file
153
anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java
Normal 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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,20 +53,26 @@ class Region implements Closeable {
|
||||
try {
|
||||
offset = getOffset(x, z);
|
||||
} 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 v2 = offset & 255;
|
||||
|
||||
if (v1 + v2 > sectorFree.size()) return null;
|
||||
if (v1 + v2 > sectorFree.size()) {
|
||||
return new EmptyChunk(x, z);
|
||||
}
|
||||
|
||||
try {
|
||||
file.seek((long) (v1 * 4096));
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user