mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-04-10 14:06:06 +02:00
More sanity checks and fallbacks to chunkloaders and better IOException handling
This commit is contained in:
parent
a4c8004834
commit
a33dda0a29
@ -164,11 +164,7 @@ private void renderThread() {
|
||||
try {
|
||||
ticket.render();
|
||||
} catch (IOException e) {
|
||||
if (ticket.getRenderAttempts() <= 1) {
|
||||
createTicket(ticket);
|
||||
} else {
|
||||
Logger.global.logDebug("Failed to render tile " + ticket.getTile() + " of map '" + ticket.getMapType().getId() + "' after " + ticket.getRenderAttempts() + " render-attempts! (" + e.toString() + ")");
|
||||
}
|
||||
Logger.global.logDebug("Failed to render tile " + ticket.getTile() + " of map '" + ticket.getMapType().getId() + "' after " + ticket.getRenderAttempts() + " render-attempts! (" + e.toString() + ")");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
|
@ -141,7 +141,7 @@ public Section(CompoundTag sectionData) {
|
||||
this.skyLight = sectionData.getByteArray("SkyLight");
|
||||
this.data = sectionData.getByteArray("Data");
|
||||
|
||||
if (blocks.length < 4096) blocks = Arrays.copyOf(biomes, 4096);
|
||||
if (blocks.length < 4096) blocks = Arrays.copyOf(blocks, 4096);
|
||||
if (blockLight.length < 2048) blockLight = Arrays.copyOf(blockLight, 2048);
|
||||
if (skyLight.length < 2048) skyLight = Arrays.copyOf(skyLight, 2048);
|
||||
if (data.length < 2048) data = Arrays.copyOf(data, 2048);
|
||||
|
@ -143,14 +143,18 @@ private class Section {
|
||||
private long[] blocks;
|
||||
private BlockState[] palette;
|
||||
|
||||
private int bitsPerBlock;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Section(CompoundTag sectionData) {
|
||||
this.sectionY = sectionData.getByte("Y");
|
||||
this.blockLight = sectionData.getByteArray("BlockLight");
|
||||
if (blockLight.length == 0) blockLight = new byte[2048];
|
||||
this.skyLight = sectionData.getByteArray("SkyLight");
|
||||
if (skyLight.length == 0) skyLight = new byte[2048];
|
||||
this.blocks = sectionData.getLongArray("BlockStates");
|
||||
|
||||
if (blocks.length < 256) blocks = Arrays.copyOf(blocks, 256);
|
||||
if (blockLight.length < 2048) blockLight = Arrays.copyOf(blockLight, 2048);
|
||||
if (skyLight.length < 2048) skyLight = Arrays.copyOf(skyLight, 2048);
|
||||
|
||||
//read block palette
|
||||
ListTag<CompoundTag> paletteTag = (ListTag<CompoundTag>) sectionData.getListTag("Palette");
|
||||
@ -179,6 +183,8 @@ public Section(CompoundTag sectionData) {
|
||||
} else {
|
||||
this.palette = new BlockState[0];
|
||||
}
|
||||
|
||||
this.bitsPerBlock = blocks.length * 64 / 4096; //64 bits per long and 4096 blocks per section
|
||||
}
|
||||
|
||||
public int getSectionY() {
|
||||
@ -192,7 +198,6 @@ public BlockState getBlockState(Vector3i pos) {
|
||||
int y = pos.getY() & 0xF;
|
||||
int z = pos.getZ() & 0xF;
|
||||
int blockIndex = y * 256 + z * 16 + x;
|
||||
int bitsPerBlock = blocks.length * 64 / 4096; //64 bits per long and 4096 blocks per section
|
||||
int index = blockIndex * bitsPerBlock;
|
||||
int firstLong = index >> 6; // index / 64
|
||||
int bitoffset = index & 0x3F; // Math.floorMod(index, 64)
|
||||
|
@ -150,10 +150,12 @@ private class Section {
|
||||
public Section(CompoundTag sectionData) {
|
||||
this.sectionY = sectionData.getByte("Y");
|
||||
this.blockLight = sectionData.getByteArray("BlockLight");
|
||||
if (blockLight.length == 0) blockLight = new byte[2048];
|
||||
this.skyLight = sectionData.getByteArray("SkyLight");
|
||||
if (skyLight.length == 0) skyLight = new byte[2048];
|
||||
this.blocks = sectionData.getLongArray("BlockStates");
|
||||
|
||||
if (blocks.length < 256) blocks = Arrays.copyOf(blocks, 256);
|
||||
if (blockLight.length < 2048) blockLight = Arrays.copyOf(blockLight, 2048);
|
||||
if (skyLight.length < 2048) skyLight = Arrays.copyOf(skyLight, 2048);
|
||||
|
||||
//read block palette
|
||||
ListTag<CompoundTag> paletteTag = (ListTag<CompoundTag>) sectionData.getListTag("Palette");
|
||||
|
@ -151,10 +151,12 @@ private class Section {
|
||||
public Section(CompoundTag sectionData) {
|
||||
this.sectionY = sectionData.getByte("Y");
|
||||
this.blockLight = sectionData.getByteArray("BlockLight");
|
||||
if (blockLight.length == 0) blockLight = new byte[2048];
|
||||
this.skyLight = sectionData.getByteArray("SkyLight");
|
||||
if (skyLight.length == 0) skyLight = new byte[2048];
|
||||
this.blocks = sectionData.getLongArray("BlockStates");
|
||||
|
||||
if (blocks.length < 256) blocks = Arrays.copyOf(blocks, 256);
|
||||
if (blockLight.length < 2048) blockLight = Arrays.copyOf(blockLight, 2048);
|
||||
if (skyLight.length < 2048) skyLight = Arrays.copyOf(skyLight, 2048);
|
||||
|
||||
//read block palette
|
||||
ListTag<CompoundTag> paletteTag = (ListTag<CompoundTag>) sectionData.getListTag("Palette");
|
||||
|
@ -156,40 +156,32 @@ public BlockState getBlockState(Vector3i pos) {
|
||||
|
||||
@Override
|
||||
public Biome getBiome(Vector3i pos) {
|
||||
try {
|
||||
|
||||
Vector2i chunkPos = blockToChunk(pos);
|
||||
Chunk chunk = getChunk(chunkPos);
|
||||
return chunk.getBiome(pos);
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Unexpected IO-Exception trying to read world-data!", ex);
|
||||
if (pos.getY() < getMinY()) {
|
||||
pos = new Vector3i(pos.getX(), getMinY(), pos.getZ());
|
||||
} else if (pos.getY() > getMaxY()) {
|
||||
pos = new Vector3i(pos.getX(), getMaxY(), pos.getZ());
|
||||
}
|
||||
|
||||
Vector2i chunkPos = blockToChunk(pos);
|
||||
Chunk chunk = getChunk(chunkPos);
|
||||
return chunk.getBiome(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlock(Vector3i pos) {
|
||||
if (pos.getY() < getMinY()) {
|
||||
return new Block(this, BlockState.AIR, LightData.ZERO, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
|
||||
}
|
||||
|
||||
if (pos.getY() > getMaxY()) {
|
||||
} else if (pos.getY() > getMaxY()) {
|
||||
return new Block(this, BlockState.AIR, LightData.SKY, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Vector2i chunkPos = blockToChunk(pos);
|
||||
Chunk chunk = getChunk(chunkPos);
|
||||
BlockState blockState = getExtendedBlockState(chunk, pos);
|
||||
LightData lightData = chunk.getLightData(pos);
|
||||
Biome biome = chunk.getBiome(pos);
|
||||
BlockProperties properties = blockPropertiesMapper.get(blockState);
|
||||
return new Block(this, blockState, lightData, biome, properties, pos);
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Unexpected IO-Exception trying to read world-data!", ex);
|
||||
}
|
||||
Vector2i chunkPos = blockToChunk(pos);
|
||||
Chunk chunk = getChunk(chunkPos);
|
||||
BlockState blockState = getExtendedBlockState(chunk, pos);
|
||||
LightData lightData = chunk.getLightData(pos);
|
||||
Biome biome = chunk.getBiome(pos);
|
||||
BlockProperties properties = blockPropertiesMapper.get(blockState);
|
||||
return new Block(this, blockState, lightData, biome, properties, pos);
|
||||
}
|
||||
|
||||
private BlockState getExtendedBlockState(Chunk chunk, Vector3i pos) {
|
||||
@ -204,21 +196,35 @@ private BlockState getExtendedBlockState(Chunk chunk, Vector3i pos) {
|
||||
return blockState;
|
||||
}
|
||||
|
||||
public Chunk getChunk(Vector2i chunkPos) throws IOException {
|
||||
public Chunk getChunk(Vector2i chunkPos) {
|
||||
try {
|
||||
Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunk(chunkPos));
|
||||
Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunkOrEmpty(chunkPos, 2, 1000));
|
||||
return chunk;
|
||||
} catch (UncheckedExecutionException | ExecutionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
|
||||
if (cause instanceof IOException) {
|
||||
throw (IOException) cause;
|
||||
}
|
||||
|
||||
else throw new IOException(cause);
|
||||
throw new RuntimeException(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private Chunk loadChunkOrEmpty(Vector2i chunkPos, int tries, long tryInterval) {
|
||||
Exception loadException = null;
|
||||
for (int i = 0; i < tries; i++) {
|
||||
try {
|
||||
return loadChunk(chunkPos);
|
||||
} catch (Exception e) {
|
||||
loadException = e;
|
||||
|
||||
if (tryInterval > 0 && i+1 < tries) {
|
||||
try {
|
||||
Thread.sleep(tryInterval);
|
||||
} catch (InterruptedException interrupt) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.global.logDebug("Unexpected exception trying to load chunk (" + chunkPos + "):" + loadException);
|
||||
return Chunk.empty(this, chunkPos);
|
||||
}
|
||||
|
||||
private Chunk loadChunk(Vector2i chunkPos) throws IOException {
|
||||
Vector2i regionPos = chunkToRegion(chunkPos);
|
||||
Path regionPath = getMCAFilePath(regionPos);
|
||||
@ -246,7 +252,7 @@ private Chunk loadChunk(Vector2i chunkPos) throws IOException {
|
||||
byte compressionTypeByte = raf.readByte();
|
||||
CompressionType compressionType = CompressionType.getFromID(compressionTypeByte);
|
||||
if (compressionType == null) {
|
||||
throw new IOException("invalid compression type " + compressionTypeByte);
|
||||
throw new IOException("Invalid compression type " + compressionTypeByte);
|
||||
}
|
||||
|
||||
DataInputStream dis = new DataInputStream(new BufferedInputStream(compressionType.decompress(new FileInputStream(raf.getFD()))));
|
||||
@ -254,8 +260,10 @@ private Chunk loadChunk(Vector2i chunkPos) throws IOException {
|
||||
if (tag instanceof CompoundTag) {
|
||||
return Chunk.create(this, (CompoundTag) tag, ignoreMissingLightData);
|
||||
} else {
|
||||
throw new IOException("invalid data tag: " + (tag == null ? "null" : tag.getClass().getName()));
|
||||
throw new IOException("Invalid data tag: " + (tag == null ? "null" : tag.getClass().getName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Exception trying to load chunk (" + chunkPos + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,10 +172,10 @@ private Iterable<Biome> iterateAverageBiomes(Block block){
|
||||
|
||||
final World world = block.getWorld();
|
||||
final int sx = pos.getX() - radius.getX(),
|
||||
sy = pos.getY() - radius.getY(),
|
||||
sy = Math.max(0, pos.getY() - radius.getY()),
|
||||
sz = pos.getZ() - radius.getZ();
|
||||
final int mx = pos.getX() + radius.getX(),
|
||||
my = pos.getY() + radius.getY(),
|
||||
my = Math.min(255, pos.getY() + radius.getY()),
|
||||
mz = pos.getZ() + radius.getZ();
|
||||
|
||||
return () -> new Iterator<Biome>() {
|
||||
|
Loading…
Reference in New Issue
Block a user