mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-01-09 17:57:39 +01:00
Fix update-region expanding with force-updates & chunks with broken tile-entity data can now be loaded
This commit is contained in:
parent
7afcbeefd7
commit
b5e8bf42ae
@ -44,7 +44,7 @@ public class WebAppImpl implements WebApp {
|
|||||||
private final BlueMapService blueMapService;
|
private final BlueMapService blueMapService;
|
||||||
private final @Nullable Plugin plugin;
|
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;
|
private @Nullable TimerTask scheduledWebAppSettingsUpdate;
|
||||||
|
|
||||||
public WebAppImpl(BlueMapService blueMapService, @Nullable Plugin plugin) {
|
public WebAppImpl(BlueMapService blueMapService, @Nullable Plugin plugin) {
|
||||||
|
@ -28,8 +28,10 @@
|
|||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.map.BmMap;
|
import de.bluecolored.bluemap.core.map.BmMap;
|
||||||
import de.bluecolored.bluemap.core.map.renderstate.MapTileState;
|
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.map.renderstate.TileState;
|
||||||
import de.bluecolored.bluemap.core.storage.GridStorage;
|
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.util.Grid;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
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);
|
Grid cellGrid = MapTileState.GRID.multiply(tileGrid);
|
||||||
try (Stream<GridStorage.Cell> stream = map.getStorage().tileState().stream()) {
|
try (Stream<GridStorage.Cell> stream = map.getStorage().tileState().stream()) {
|
||||||
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()))
|
.map(c -> new Vector2i(c.getX(), c.getZ()))
|
||||||
.flatMap(v -> cellGrid.getIntersecting(v, regionGrid).stream())
|
.flatMap(v -> cellGrid.getIntersecting(v, regionGrid).stream())
|
||||||
.filter(regionRadiusFilter)
|
.filter(regionRadiusFilter)
|
||||||
|
@ -24,12 +24,18 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.map.renderstate;
|
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.NBTName;
|
||||||
import de.bluecolored.bluenbt.NBTPostDeserialize;
|
import de.bluecolored.bluenbt.NBTPostDeserialize;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -122,4 +128,29 @@ public static TileInfoRegion create() {
|
|||||||
return region;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ public void accept(int chunkX, int chunkZ, Chunk chunk) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException ex) {
|
} 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;
|
return Chunk.ERRORED_CHUNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,8 +95,12 @@ private static class ChunkVersionLoader<D extends MCAChunk.Data> {
|
|||||||
private final int dataVersion;
|
private final int dataVersion;
|
||||||
|
|
||||||
public MCAChunk load(MCAWorld world, InputStream in) throws IOException {
|
public MCAChunk load(MCAWorld world, InputStream in) throws IOException {
|
||||||
D data = MCAUtil.BLUENBT.read(in, dataType);
|
try {
|
||||||
return mightSupport(data.getDataVersion()) ? constructor.apply(world, data) : new MCAChunk(world, data) {};
|
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) {
|
public boolean mightSupport(int dataVersion) {
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
import de.bluecolored.bluemap.core.world.block.entity.BlockEntity;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
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 de.bluecolored.bluenbt.NBTName;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -295,7 +297,10 @@ public static class Level {
|
|||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
private SectionData @Nullable [] sections = null;
|
||||||
private int[] biomes = EMPTY_INT_ARRAY;
|
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
|
@Getter
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
||||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
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 de.bluecolored.bluenbt.NBTName;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -282,7 +284,10 @@ public static class Level {
|
|||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
private SectionData @Nullable [] sections = null;
|
||||||
private int[] biomes = EMPTY_INT_ARRAY;
|
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
|
@Getter
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
|
||||||
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
|
||||||
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
|
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 de.bluecolored.bluenbt.NBTName;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -290,7 +292,10 @@ public static class Data extends MCAChunk.Data {
|
|||||||
private long inhabitedTime = 0;
|
private long inhabitedTime = 0;
|
||||||
private HeightmapsData heightmaps = new HeightmapsData();
|
private HeightmapsData heightmaps = new HeightmapsData();
|
||||||
private SectionData @Nullable [] sections = null;
|
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
|
@Getter
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -33,6 +33,7 @@
|
|||||||
import de.bluecolored.bluemap.common.config.ConfigurationException;
|
import de.bluecolored.bluemap.common.config.ConfigurationException;
|
||||||
import de.bluecolored.bluemap.common.config.CoreConfig;
|
import de.bluecolored.bluemap.common.config.CoreConfig;
|
||||||
import de.bluecolored.bluemap.common.config.WebserverConfig;
|
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.plugin.MapUpdateService;
|
||||||
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
|
import de.bluecolored.bluemap.common.rendermanager.MapUpdateTask;
|
||||||
import de.bluecolored.bluemap.common.rendermanager.RenderManager;
|
import de.bluecolored.bluemap.common.rendermanager.RenderManager;
|
||||||
@ -209,6 +210,8 @@ public void run() {
|
|||||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||||
shutdown.run();
|
shutdown.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateDumper.global().dump(Path.of("teststate.json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOException, ConfigurationException, InterruptedException {
|
public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOException, ConfigurationException, InterruptedException {
|
||||||
|
Loading…
Reference in New Issue
Block a user