Fix update-region expanding with force-updates & chunks with broken tile-entity data can now be loaded

This commit is contained in:
Lukas Rieger (Blue) 2024-06-03 10:17:53 +02:00
parent 7afcbeefd7
commit b5e8bf42ae
No known key found for this signature in database
GPG Key ID: AA33883B1BBA03E6
10 changed files with 112 additions and 8 deletions

View File

@ -44,7 +44,7 @@ public class WebAppImpl implements WebApp {
private final BlueMapService blueMapService;
private final @Nullable Plugin plugin;
private final Timer timer = new Timer();
private final Timer timer = new Timer("BlueMap-WebbAppImpl-Timer", true);
private @Nullable TimerTask scheduledWebAppSettingsUpdate;
public WebAppImpl(BlueMapService blueMapService, @Nullable Plugin plugin) {

View File

@ -28,8 +28,10 @@
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.map.BmMap;
import de.bluecolored.bluemap.core.map.renderstate.MapTileState;
import de.bluecolored.bluemap.core.map.renderstate.TileInfoRegion;
import de.bluecolored.bluemap.core.map.renderstate.TileState;
import de.bluecolored.bluemap.core.storage.GridStorage;
import de.bluecolored.bluemap.core.storage.compression.CompressedInputStream;
import de.bluecolored.bluemap.core.util.Grid;
import de.bluecolored.bluemap.core.world.World;
@ -134,6 +136,21 @@ private static Collection<Vector2i> getRegions(BmMap map, Vector2i center, int r
Grid cellGrid = MapTileState.GRID.multiply(tileGrid);
try (Stream<GridStorage.Cell> stream = map.getStorage().tileState().stream()) {
stream
.filter(c -> { // filter out files that are fully UNKNOWN
try (CompressedInputStream in = c.read()) {
if (in == null) return false;
TileState[] states = TileInfoRegion.loadPalette(in.decompress());
for (TileState state : states) {
if (
state != TileState.UNKNOWN &&
state != TileState.NOT_GENERATED
) return true;
}
return false;
} catch (IOException ignore) {
return true;
}
})
.map(c -> new Vector2i(c.getX(), c.getZ()))
.flatMap(v -> cellGrid.getIntersecting(v, regionGrid).stream())
.filter(regionRadiusFilter)

View File

@ -24,12 +24,18 @@
*/
package de.bluecolored.bluemap.core.map.renderstate;
import com.google.gson.reflect.TypeToken;
import de.bluecolored.bluemap.core.util.Key;
import de.bluecolored.bluemap.core.util.RegistryAdapter;
import de.bluecolored.bluenbt.BlueNBT;
import de.bluecolored.bluenbt.NBTName;
import de.bluecolored.bluenbt.NBTPostDeserialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
@ -122,4 +128,29 @@ public static TileInfoRegion create() {
return region;
}
/**
* Only loads the palette-part from a TileState-file
*/
public static TileState[] loadPalette(InputStream in) throws IOException {
return PaletteOnly.BLUE_NBT.read(in, PaletteOnly.class).tileStates.palette;
}
@Getter
private static class PaletteOnly {
private final static BlueNBT BLUE_NBT = new BlueNBT();
static {
BLUE_NBT.register(TypeToken.get(TileState.class), new RegistryAdapter<>(TileState.REGISTRY, Key.BLUEMAP_NAMESPACE, TileState.UNKNOWN));
}
@NBTName("tile-states")
private TileStates tileStates;
@Getter
private static class TileStates {
private TileState[] palette;
}
}
}

View File

@ -203,7 +203,7 @@ public void accept(int chunkX, int chunkZ, Chunk chunk) {
}
});
} catch (IOException ex) {
Logger.global.logDebug("Unexpected exception trying to load preload region (x:" + x + ", z:" + z + "):" + ex);
Logger.global.logDebug("Unexpected exception trying to load preload region (x:" + x + ", z:" + z + "): " + ex);
}
}
@ -257,7 +257,7 @@ private Chunk loadChunk(int x, int z) {
}
}
Logger.global.logDebug("Unexpected exception trying to load chunk (x:" + x + ", z:" + z + "):" + loadException);
Logger.global.logDebug("Unexpected exception trying to load chunk (x:" + x + ", z:" + z + "): " + loadException);
return Chunk.ERRORED_CHUNK;
}

View File

@ -95,8 +95,12 @@ private static class ChunkVersionLoader<D extends MCAChunk.Data> {
private final int dataVersion;
public MCAChunk load(MCAWorld world, InputStream in) throws IOException {
D data = MCAUtil.BLUENBT.read(in, dataType);
return mightSupport(data.getDataVersion()) ? constructor.apply(world, data) : new MCAChunk(world, data) {};
try {
D data = MCAUtil.BLUENBT.read(in, dataType);
return mightSupport(data.getDataVersion()) ? constructor.apply(world, data) : new MCAChunk(world, data) {};
} catch (Exception e) {
throw new IOException("Failed to parse chunk-data: " + e, e);
}
}
public boolean mightSupport(int dataVersion) {

View File

@ -33,6 +33,8 @@
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.mca.data.LenientBlockEntityArrayDeserializer;
import de.bluecolored.bluenbt.NBTDeserializer;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
@ -295,7 +297,10 @@ public static class Level {
private HeightmapsData heightmaps = new HeightmapsData();
private SectionData @Nullable [] sections = null;
private int[] biomes = EMPTY_INT_ARRAY;
@NBTName("TileEntities") private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
@NBTName("TileEntities")
@NBTDeserializer(LenientBlockEntityArrayDeserializer.class)
private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
}
@Getter

View File

@ -34,6 +34,8 @@
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
import de.bluecolored.bluemap.core.world.mca.data.LenientBlockEntityArrayDeserializer;
import de.bluecolored.bluenbt.NBTDeserializer;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
@ -282,7 +284,10 @@ public static class Level {
private HeightmapsData heightmaps = new HeightmapsData();
private SectionData @Nullable [] sections = null;
private int[] biomes = EMPTY_INT_ARRAY;
@NBTName("TileEntities") private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
@NBTName("TileEntities")
@NBTDeserializer(LenientBlockEntityArrayDeserializer.class)
private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
}
@Getter

View File

@ -34,6 +34,8 @@
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
import de.bluecolored.bluemap.core.world.mca.data.LenientBlockEntityArrayDeserializer;
import de.bluecolored.bluenbt.NBTDeserializer;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
@ -290,7 +292,10 @@ public static class Data extends MCAChunk.Data {
private long inhabitedTime = 0;
private HeightmapsData heightmaps = new HeightmapsData();
private SectionData @Nullable [] sections = null;
@NBTName("block_entities") private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
@NBTName("block_entities")
@NBTDeserializer(LenientBlockEntityArrayDeserializer.class)
private @Nullable BlockEntity [] blockEntities = EMPTY_BLOCK_ENTITIES_ARRAY;
}
@Getter

View File

@ -0,0 +1,34 @@
package de.bluecolored.bluemap.core.world.mca.data;
import com.google.gson.reflect.TypeToken;
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
import de.bluecolored.bluenbt.BlueNBT;
import de.bluecolored.bluenbt.NBTReader;
import de.bluecolored.bluenbt.TagType;
import de.bluecolored.bluenbt.TypeDeserializer;
import java.io.IOException;
/**
* TypeSerializer that returns a default value instead of failing when the serialized field is of the wrong type
*/
public class LenientBlockEntityArrayDeserializer implements TypeDeserializer<BlockEntity[]> {
private static final BlockEntity[] EMPTY_BLOCK_ENTITIES_ARRAY = new BlockEntity[0];
private final TypeDeserializer<BlockEntity[]> delegate;
public LenientBlockEntityArrayDeserializer(BlueNBT blueNBT) {
delegate = blueNBT.getTypeDeserializer(new TypeToken<>(){});
}
@Override
public BlockEntity[] read(NBTReader reader) throws IOException {
if (reader.peek() != TagType.LIST) {
reader.skip();
return EMPTY_BLOCK_ENTITIES_ARRAY;
}
return delegate.read(reader);
}
}

View File

@ -33,6 +33,7 @@
import de.bluecolored.bluemap.common.config.ConfigurationException;
import de.bluecolored.bluemap.common.config.CoreConfig;
import de.bluecolored.bluemap.common.config.WebserverConfig;
import de.bluecolored.bluemap.common.debug.StateDumper;
import de.bluecolored.bluemap.common.plugin.MapUpdateService;
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
import de.bluecolored.bluemap.common.rendermanager.RenderManager;
@ -209,6 +210,8 @@ public void run() {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
shutdown.run();
}
StateDumper.global().dump(Path.of("teststate.json"));
}
public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOException, ConfigurationException, InterruptedException {