From 2ce3871424f1c449c5176743dddd7aa289de2af0 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 27 Jan 2019 20:51:39 +0300 Subject: [PATCH] =?UTF-8?q?=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D1=8B=20=D1=81=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=BF=D1=80=D0=BE=D1=80=D0=B8=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D0=BC=D0=B8=20=D1=87=D0=B0=D0=BD=D0=BA?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проблема оказалась вот в чем: если вокруг карты(зоны?) имеются незагруженные чанки ("Waiting for chunk..."), то клиент начинает дурить и перестает крайние чанки этой карты(зоны?) отрисовывать. Решение проблемы:всегда отдавать чанк клиенту. Если по какой-то причине Chunk будет null, то нужно будет отправить Пустой чанк (EmptyChunk), у которого все блоки - это AIR. --- .../main/java/mc/world/anvil/EmptyChunk.java | 153 ++++++++++++++++++ .../src/main/java/mc/world/anvil/Region.java | 14 +- 2 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java diff --git a/anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java b/anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java new file mode 100644 index 0000000..0ff6a8f --- /dev/null +++ b/anvil-loader/src/main/java/mc/world/anvil/EmptyChunk.java @@ -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 $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) { + } + } +} diff --git a/anvil-loader/src/main/java/mc/world/anvil/Region.java b/anvil-loader/src/main/java/mc/world/anvil/Region.java index d8bbf33..794d27f 100644 --- a/anvil-loader/src/main/java/mc/world/anvil/Region.java +++ b/anvil-loader/src/main/java/mc/world/anvil/Region.java @@ -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);