More sanity checks and fallbacks to chunkloaders and better IOException handling

This commit is contained in:
Blue (Lukas Rieger) 2020-07-29 20:00:58 +02:00
parent a4c8004834
commit a33dda0a29
7 changed files with 63 additions and 50 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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)

View File

@ -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");

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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>() {