Minestom / Hephaistos

NBT & Anvil save format library
MIT License
60 stars 11 forks source link

Chunk file at [0, 23] is missing level data in minecraft logs when loading a modifed world #28

Closed 3l0w closed 2 years ago

3l0w commented 2 years ago

Minecraft version: 1.15.2 Java version : openjdk 17.0.3 2022-04-19 Hephaistos version: 2.4.8

I try to use the lib to fix a map that i receive, but the map contains tile entities with the name "Banner" but minecraft only accept tile entity id in lowercase.

Non [a-z0-9/._-] character in path of location: minecraft:Banner

So i made a script with java to fix the map but each time i open it with my game, minecraft find that the data is missing.

Chunk file at [24, 23] is missing level data, skipping

Here is the full code i use:

Path path = Path.of("map"); //Old map that need to be fixed
Path newPath = Path.of("newMap"); //Fixed map
Path regionPath = path.resolve("region");
Path newRegionPath = newPath.resolve("region");

Map<Pair<Integer, Integer>, RegionFile> regions = new HashMap<>();
Map<Pair<Integer, Integer>, RegionFile> newRegions = new HashMap<>();

for (int x = -4; x <= 3; x++) {
    for (int z = -4; z <= 3; z++) {
        var filename = RegionFile.Companion.createFileName(x, z);
        var path1 = regionPath.resolve(filename);
        var path2 = newRegionPath.resolve(filename);
        var tuple = new Pair<>(x, z);
        regions.put(tuple, new RegionFile(new RandomAccessFile(path1.toFile(), "r"), x, z));
        newRegions.put(tuple, new RegionFile(new RandomAccessFile(path2.toFile(), "rw"), x, z));
    }
}

ExecutorService executorService = Executors.newFixedThreadPool(6, runnable -> new Thread(runnable, "ScrapperThread"));

System.out.println("Regions loaded");

List<Future<?>> futures = new ArrayList<>();

regions.forEach((t, regionFile) -> {
    var regionX = regionFile.getRegionX();
    var regionZ = regionFile.getRegionZ();
    var newRegionFile = newRegions.get(t);

    futures.add(executorService.submit(() -> {
        try {
            for (int i = 0; i < 32; i++) {
                for (int z = 0; z < 32; z++) {
                    final var chunkX = regionX * 32 + i;
                    final var chunkZ = regionZ * 32 + z;
                    ChunkColumn chunkColumn = regionFile.getChunk(chunkX, chunkZ);
                    if (chunkColumn != null) {
                        List<NBTCompound> tilesEntities = chunkColumn.getTileEntities().asListView().stream().map(te -> {
                            var entityId = te.getString("id");
                            if (entityId == null) return te;
                            MutableNBTCompound mutable = te.toMutableCompound();
                            if (entityId.equals("Banner"))
                                mutable.setString("id", "banner");
                            return mutable.toCompound();
                        }).toList();
                        chunkColumn.setTileEntities(NBT.List(NBTType.TAG_Compound, tilesEntities));
                        newRegionFile.writeColumn(chunkColumn);
                        regionFile.forget(chunkColumn);
                    }
                }
            }
            regionFile.close();
            System.out.println("Region " + regionX + " " + regionZ + " finished");
        } catch (Exception e) {
            System.out.println("Exception as occurred: " + regionX + " " + regionZ);
            e.printStackTrace();
        }
    }));
});
for (Future<?> future : futures) {
    future.get();
}
System.out.println("Task finished");
3l0w commented 2 years ago

After some investigation i have noticed that the method ChunkColumn#writeColumn has a version argument. So i set it to SupportedVersion.MC_1_15 and i got a new error in game:

[23:02:28] [Server thread/ERROR]: Couldn't load chunk [13, 15]
java.lang.ArrayIndexOutOfBoundsException: Index 1024 out of bounds for length 1024
    at bzz.<init>(SourceFile:74) ~[minecraft-1.15.2-client.jar:?]
    at cax.a(SourceFile:73) ~[minecraft-1.15.2-client.jar:?]
    at wp.j(SourceFile:516) ~[minecraft-1.15.2-client.jar:?]
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) [?:?]
    at ais.c(SourceFile:144) [minecraft-1.15.2-client.jar:?]
    at xb$a.c(SourceFile:551) [minecraft-1.15.2-client.jar:?]
    at ais.w(SourceFile:118) [minecraft-1.15.2-client.jar:?]
    at xb$a.w(SourceFile:560) [minecraft-1.15.2-client.jar:?]
    at xb.d(SourceFile:278) [minecraft-1.15.2-client.jar:?]
    at net.minecraft.server.MinecraftServer.ba(SourceFile:731) [minecraft-1.15.2-client.jar:?]
    at net.minecraft.server.MinecraftServer.w(SourceFile:719) [minecraft-1.15.2-client.jar:?]
    at ais.c(SourceFile:127) [minecraft-1.15.2-client.jar:?]
    at net.minecraft.server.MinecraftServer.v(SourceFile:704) [minecraft-1.15.2-client.jar:?]
    at net.minecraft.server.MinecraftServer.a(SourceFile:491) [minecraft-1.15.2-client.jar:?]
    at edm.a(SourceFile:90) [minecraft-1.15.2-client.jar:?]
    at edm.d(SourceFile:106) [minecraft-1.15.2-client.jar:?]
    at net.minecraft.server.MinecraftServer.run(SourceFile:628) [minecraft-1.15.2-client.jar:?]

But Hephaistos has no problem to import