Search in sources :

Example 6 with Tag

use of org.jnbt.Tag in project WorldPainter by Captain-Chaos.

the class Bo3Object method loadTileEntity.

private static TileEntity loadTileEntity(File bo3File, String nbtFileName) throws IOException {
    File nbtFile = new File(bo3File.getParentFile(), nbtFileName);
    try (NBTInputStream in = new NBTInputStream(new GZIPInputStream(new FileInputStream(nbtFile)))) {
        CompoundTag tag = (CompoundTag) in.readTag();
        Map<String, Tag> map = tag.getValue();
        if ((map.size() == 1) && (map.values().iterator().next() instanceof CompoundTag)) {
            // contains the data
            return TileEntity.fromNBT((CompoundTag) tag.getValue().values().iterator().next());
        } else {
            return TileEntity.fromNBT(tag);
        }
    }
}
Also used : GZIPInputStream(java.util.zip.GZIPInputStream) NBTInputStream(org.jnbt.NBTInputStream) CompoundTag(org.jnbt.CompoundTag) Tag(org.jnbt.Tag) CompoundTag(org.jnbt.CompoundTag)

Example 7 with Tag

use of org.jnbt.Tag in project WorldPainter by Captain-Chaos.

the class JavaWorldMerger method thirdPass.

private String thirdPass(MinecraftWorld minecraftWorld, File oldRegionDir, Dimension dimension, Point regionCoords, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
    if (progressReceiver != null) {
        progressReceiver.setMessage("Merging existing blocks with new");
    }
    int lowestChunkX = (regionCoords.x << 5) - 1;
    int highestChunkX = (regionCoords.x << 5) + 32;
    int lowestChunkY = (regionCoords.y << 5) - 1;
    int highestChunkY = (regionCoords.y << 5) + 32;
    Platform platform = dimension.getWorld().getPlatform();
    int maxHeight = dimension.getMaxHeight();
    Map<Point, RegionFile> regionFiles = new HashMap<>();
    Set<Point> damagedRegions = new HashSet<>();
    StringBuilder reportBuilder = new StringBuilder();
    try {
        int chunkNo = 0;
        for (int chunkX = lowestChunkX; chunkX <= highestChunkX; chunkX++) {
            for (int chunkY = lowestChunkY; chunkY <= highestChunkY; chunkY++) {
                chunkNo++;
                if (progressReceiver != null) {
                    progressReceiver.setProgress((float) chunkNo / 1156);
                }
                Chunk newChunk;
                if (dimension.getTile(chunkX >> 3, chunkY >> 3) == null) {
                    // The tile for this chunk does not exist in the new
                    // world, so the chunk from the existing world should
                    // be copied
                    newChunk = null;
                } else {
                    newChunk = minecraftWorld.getChunk(chunkX, chunkY);
                }
                if (replaceChunks && (newChunk != null)) {
                    // as is
                    continue;
                }
                int regionX = chunkX >> 5;
                int regionY = chunkY >> 5;
                Point coords = new Point(regionX, regionY);
                if (damagedRegions.contains(coords)) {
                    // reported and logged earlier
                    continue;
                }
                RegionFile regionFile = regionFiles.get(coords);
                if (regionFile == null) {
                    File file = new File(oldRegionDir, "r." + regionX + "." + regionY + (platform.equals(DefaultPlugin.JAVA_ANVIL) ? ".mca" : ".mcr"));
                    try {
                        regionFile = new RegionFile(file);
                        regionFiles.put(coords, regionFile);
                    } catch (IOException e) {
                        reportBuilder.append("I/O error while opening region file " + file + " (message: \"" + e.getMessage() + "\"); skipping region" + EOL);
                        logger.error("I/O error while opening region file " + file + "; skipping region", e);
                        damagedRegions.add(coords);
                        continue;
                    }
                }
                int chunkXInRegion = chunkX & 0x1f;
                int chunkYInRegion = chunkY & 0x1f;
                if (regionFile.containsChunk(chunkXInRegion, chunkYInRegion)) {
                    Tag tag;
                    try {
                        DataInputStream chunkData = regionFile.getChunkDataInputStream(chunkXInRegion, chunkYInRegion);
                        if (chunkData == null) {
                            // This should never happen, since we checked with
                            // isChunkPresent(), but in practice it does. Perhaps
                            // corrupted data?
                            reportBuilder.append("Missing chunk data in existing map for chunk " + chunkXInRegion + ", " + chunkYInRegion + " in " + regionFile + "; skipping chunk" + EOL);
                            logger.warn("Missing chunk data in existing map for chunk " + chunkXInRegion + ", " + chunkYInRegion + " in " + regionFile + "; skipping chunk");
                            continue;
                        }
                        try (NBTInputStream in = new NBTInputStream(chunkData)) {
                            tag = in.readTag();
                        }
                    } catch (IOException e) {
                        reportBuilder.append("I/O error while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                        logger.error("I/O error while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + "; skipping chunk", e);
                        continue;
                    } catch (IllegalArgumentException e) {
                        reportBuilder.append("Illegal argument exception while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                        logger.error("Illegal argument exception while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + "; skipping chunk", e);
                        continue;
                    }
                    Chunk existingChunk = platform.equals(DefaultPlugin.JAVA_ANVIL) ? new ChunkImpl2((CompoundTag) tag, maxHeight) : new ChunkImpl((CompoundTag) tag, maxHeight);
                    if (newChunk != null) {
                        // Chunk exists in existing and new world; merge it
                        // Do any necessary processing of the existing chunk
                        // (clearing trees, etc.) No need to check for
                        // read-only; if the chunk was read-only it
                        // wouldn't exist in the new map and we wouldn't
                        // be here
                        processExistingChunk(existingChunk);
                        try {
                            newChunk = mergeChunk(existingChunk, newChunk, dimension);
                            minecraftWorld.addChunk(newChunk);
                        } catch (NullPointerException e) {
                            reportBuilder.append("Null pointer exception while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + "; skipping chunk" + EOL);
                            logger.error("Null pointer exception while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + "; skipping chunk", e);
                            continue;
                        } catch (ArrayIndexOutOfBoundsException e) {
                            reportBuilder.append("Array index out of bounds while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                            logger.error("Array index out of bounds while reading chunk in existing map " + chunkXInRegion + ", " + chunkYInRegion + " from file " + regionFile + "; skipping chunk", e);
                            continue;
                        }
                    } else {
                        // Chunk exists in existing world, but not in new
                        // one, copy old to new
                        minecraftWorld.addChunk(existingChunk);
                    }
                }
            }
        }
    } finally {
        for (RegionFile regionFile : regionFiles.values()) {
            regionFile.close();
        }
    }
    if (progressReceiver != null) {
        progressReceiver.setProgress(1.0f);
    }
    return reportBuilder.length() != 0 ? reportBuilder.toString() : null;
}
Also used : NBTInputStream(org.jnbt.NBTInputStream) CompoundTag(org.jnbt.CompoundTag) Tag(org.jnbt.Tag) CompoundTag(org.jnbt.CompoundTag)

Example 8 with Tag

use of org.jnbt.Tag in project WorldPainter by Captain-Chaos.

the class JavaMapImporter method importDimension.

private String importDimension(File regionDir, Dimension dimension, int version, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
    if (progressReceiver != null) {
        progressReceiver.setMessage(dimension.getName() + " dimension");
    }
    final int maxHeight = dimension.getMaxHeight();
    final int maxY = maxHeight - 1;
    final Pattern regionFilePattern = (version == SUPPORTED_VERSION_1) ? Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mcr") : Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca");
    final File[] regionFiles = regionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
    if ((regionFiles == null) || (regionFiles.length == 0)) {
        throw new RuntimeException("The " + dimension.getName() + " dimension of this map has no region files!");
    }
    final Set<Point> newChunks = new HashSet<>();
    // final SortedSet<Material> manMadeBlockTypes = new TreeSet<Material>();
    final boolean importBiomes = (version == SUPPORTED_VERSION_2) && (dimension.getDim() == DIM_NORMAL);
    final int total = regionFiles.length * 1024;
    int count = 0;
    final StringBuilder reportBuilder = new StringBuilder();
    for (File file : regionFiles) {
        try {
            RegionFile regionFile = new RegionFile(file);
            try {
                for (int x = 0; x < 32; x++) {
                    for (int z = 0; z < 32; z++) {
                        if (progressReceiver != null) {
                            progressReceiver.setProgress((float) count / total);
                            count++;
                        }
                        final Point chunkCoords = new Point((regionFile.getX() << 5) | x, (regionFile.getZ() << 5) | z);
                        if ((chunksToSkip != null) && chunksToSkip.contains(chunkCoords)) {
                            continue;
                        }
                        if (regionFile.containsChunk(x, z)) {
                            final Tag tag;
                            try {
                                final InputStream chunkData = regionFile.getChunkDataInputStream(x, z);
                                if (chunkData == null) {
                                    // This should never happen, since we checked
                                    // with isChunkPresent(), but in practice it
                                    // does. Perhaps corrupted data?
                                    reportBuilder.append("Missing chunk data for chunk " + x + ", " + z + " in " + file + "; skipping chunk" + EOL);
                                    logger.warn("Missing chunk data for chunk " + x + ", " + z + " in " + file + "; skipping chunk");
                                    continue;
                                }
                                try (NBTInputStream in = new NBTInputStream(chunkData)) {
                                    tag = in.readTag();
                                }
                            } catch (IOException e) {
                                reportBuilder.append("I/O error while reading chunk " + x + ", " + z + " from file " + file + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                                logger.error("I/O error while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk", e);
                                continue;
                            } catch (IllegalArgumentException e) {
                                reportBuilder.append("Illegal argument exception while reading chunk " + x + ", " + z + " from file " + file + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                                logger.error("Illegal argument exception while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk", e);
                                continue;
                            } catch (NegativeArraySizeException e) {
                                reportBuilder.append("Negative array size exception while reading chunk " + x + ", " + z + " from file " + file + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                                logger.error("Negative array size exception while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk", e);
                                continue;
                            }
                            final Chunk chunk = (version == SUPPORTED_VERSION_1) ? new ChunkImpl((CompoundTag) tag, maxHeight) : new ChunkImpl2((CompoundTag) tag, maxHeight);
                            final Point tileCoords = new Point(chunk.getxPos() >> 3, chunk.getzPos() >> 3);
                            Tile tile = dimension.getTile(tileCoords);
                            if (tile == null) {
                                tile = dimension.getTileFactory().createTile(tileCoords.x, tileCoords.y);
                                for (int xx = 0; xx < 8; xx++) {
                                    for (int yy = 0; yy < 8; yy++) {
                                        newChunks.add(new Point((tileCoords.x << TILE_SIZE_BITS) | (xx << 4), (tileCoords.y << TILE_SIZE_BITS) | (yy << 4)));
                                    }
                                }
                                dimension.addTile(tile);
                            }
                            newChunks.remove(new Point(chunk.getxPos() << 4, chunk.getzPos() << 4));
                            boolean manMadeStructuresBelowGround = false;
                            boolean manMadeStructuresAboveGround = false;
                            try {
                                for (int xx = 0; xx < 16; xx++) {
                                    for (int zz = 0; zz < 16; zz++) {
                                        float height = -1.0f;
                                        int waterLevel = 0;
                                        boolean floodWithLava = false, frost = false;
                                        Terrain terrain = Terrain.BEDROCK;
                                        for (int y = maxY; y >= 0; y--) {
                                            int blockType = chunk.getBlockType(xx, y, zz);
                                            int data = chunk.getDataValue(xx, y, zz);
                                            if (!NATURAL_BLOCKS.get(blockType)) {
                                                if (height == -1.0f) {
                                                    manMadeStructuresAboveGround = true;
                                                } else {
                                                    manMadeStructuresBelowGround = true;
                                                }
                                            // manMadeBlockTypes.add(Material.get(blockType, data));
                                            }
                                            if ((blockType == BLK_SNOW) || (blockType == BLK_ICE)) {
                                                frost = true;
                                            }
                                            if (((blockType == BLK_ICE) || (blockType == BLK_FROSTED_ICE) || (((blockType == BLK_STATIONARY_WATER) || (blockType == BLK_WATER) || (blockType == BLK_STATIONARY_LAVA) || (blockType == BLK_LAVA)) && (data == 0))) && (waterLevel == 0)) {
                                                waterLevel = y;
                                                if ((blockType == BLK_LAVA) || (blockType == BLK_STATIONARY_LAVA)) {
                                                    floodWithLava = true;
                                                }
                                            } else if (height == -1.0f) {
                                                final Material material = Material.get(blockType, data);
                                                if (SPECIAL_TERRAIN_MAPPING.containsKey(material)) {
                                                    // Special terrain found
                                                    // Value that falls in the middle of the lowest one eigthth which will still round to the same integer value and will receive a one layer thick smooth snow block (principle of least surprise)
                                                    height = y - 0.4375f;
                                                    terrain = SPECIAL_TERRAIN_MAPPING.get(material);
                                                } else if (TERRAIN_MAPPING.containsKey(blockType)) {
                                                    // Terrain found
                                                    // Value that falls in the middle of the lowest one eigthth which will still round to the same integer value and will receive a one layer thick smooth snow block (principle of least surprise)
                                                    height = y - 0.4375f;
                                                    terrain = TERRAIN_MAPPING.get(blockType);
                                                }
                                            }
                                        }
                                        // Use smooth snow, if present, to better approximate world height, so smooth snow will survive merge
                                        final int intHeight = (int) (height + 0.5f);
                                        if ((height != -1.0f) && (intHeight < maxY) && (chunk.getBlockType(xx, intHeight + 1, zz) == BLK_SNOW)) {
                                            int data = chunk.getDataValue(xx, intHeight + 1, zz);
                                            height += data * 0.125;
                                        }
                                        if ((waterLevel == 0) && (height >= 61.5f)) {
                                            waterLevel = 62;
                                        }
                                        final int blockX = (chunk.getxPos() << 4) | xx;
                                        final int blockY = (chunk.getzPos() << 4) | zz;
                                        final Point coords = new Point(blockX, blockY);
                                        dimension.setTerrainAt(coords, terrain);
                                        dimension.setHeightAt(coords, Math.max(height, 0.0f));
                                        dimension.setWaterLevelAt(blockX, blockY, waterLevel);
                                        if (frost) {
                                            dimension.setBitLayerValueAt(Frost.INSTANCE, blockX, blockY, true);
                                        }
                                        if (floodWithLava) {
                                            dimension.setBitLayerValueAt(FloodWithLava.INSTANCE, blockX, blockY, true);
                                        }
                                        if (height == -1.0f) {
                                            dimension.setBitLayerValueAt(org.pepsoft.worldpainter.layers.Void.INSTANCE, blockX, blockY, true);
                                        }
                                        if (importBiomes && chunk.isBiomesAvailable()) {
                                            final int biome = chunk.getBiome(xx, zz);
                                            // adjust the biome when the user makes changes
                                            if ((biome != 255) && (biome != dimension.getAutoBiome(blockX, blockY))) {
                                                dimension.setLayerValueAt(Biome.INSTANCE, blockX, blockY, biome);
                                            }
                                        }
                                    }
                                }
                            } catch (NullPointerException e) {
                                reportBuilder.append("Null pointer exception while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk" + EOL);
                                logger.error("Null pointer exception while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk", e);
                                continue;
                            } catch (ArrayIndexOutOfBoundsException e) {
                                reportBuilder.append("Array index out of bounds while reading chunk " + x + ", " + z + " from file " + file + " (message: \"" + e.getMessage() + "\"); skipping chunk" + EOL);
                                logger.error("Array index out of bounds while reading chunk " + x + ", " + z + " from file " + file + "; skipping chunk", e);
                                continue;
                            }
                            if (((readOnlyOption == ReadOnlyOption.MAN_MADE) && (manMadeStructuresBelowGround || manMadeStructuresAboveGround)) || ((readOnlyOption == ReadOnlyOption.MAN_MADE_ABOVE_GROUND) && manMadeStructuresAboveGround) || (readOnlyOption == ReadOnlyOption.ALL)) {
                                dimension.setBitLayerValueAt(ReadOnly.INSTANCE, chunk.getxPos() << 4, chunk.getzPos() << 4, true);
                            }
                        }
                    }
                }
            } finally {
                regionFile.close();
            }
        } catch (IOException e) {
            reportBuilder.append("I/O error while opening region file " + file + " (message: \"" + e.getMessage() + "\"); skipping region" + EOL);
            logger.error("I/O error while opening region file " + file + "; skipping region", e);
        }
    }
    // Process chunks that were only added to fill out a tile
    for (Point newChunkCoords : newChunks) {
        dimension.setBitLayerValueAt(NotPresent.INSTANCE, newChunkCoords.x, newChunkCoords.y, true);
        if (populateNewChunks) {
            dimension.setBitLayerValueAt(Populate.INSTANCE, newChunkCoords.x, newChunkCoords.y, true);
        }
    }
    if (progressReceiver != null) {
        progressReceiver.setProgress(1.0f);
    }
    return reportBuilder.length() != 0 ? reportBuilder.toString() : null;
}
Also used : CompoundTag(org.jnbt.CompoundTag) Pattern(java.util.regex.Pattern) NBTInputStream(org.jnbt.NBTInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) NBTInputStream(org.jnbt.NBTInputStream) CompoundTag(org.jnbt.CompoundTag) Tag(org.jnbt.Tag) File(java.io.File)

Example 9 with Tag

use of org.jnbt.Tag in project WorldPainter by Captain-Chaos.

the class Statistics method main.

public static void main(String[] args) throws IOException {
    File levelDatFile = new File(args[0]);
    Level level = Level.load(levelDatFile);
    if ((level.getVersion() != SUPPORTED_VERSION_1) && (level.getVersion() != SUPPORTED_VERSION_2)) {
        throw new UnsupportedOperationException("Level format version " + level.getVersion() + " not supported");
    }
    int maxHeight = level.getMaxHeight();
    int maxY = maxHeight - 1;
    File worldDir = levelDatFile.getParentFile();
    File regionDir = new File(worldDir, "region");
    int version = level.getVersion();
    final Pattern regionFilePattern = (version == SUPPORTED_VERSION_1) ? Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mcr") : Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca");
    File[] regionFiles = regionDir.listFiles((dir, name) -> {
        return regionFilePattern.matcher(name).matches();
    });
    int[][] blockTypeCounts = new int[maxHeight >> 4][4096];
    int[][] blockTypeTotals = new int[maxHeight >> 4][4096];
    // int totalBlockCount = 0, totalBlocksPerLevel = 0;
    System.out.println("Scanning " + worldDir);
    System.out.print('|');
    for (int i = 0; i < regionFiles.length - 2; i++) {
        System.out.print('-');
    }
    System.out.println('|');
    for (File file : regionFiles) {
        RegionFile regionFile = new RegionFile(file);
        try {
            for (int x = 0; x < 32; x++) {
                for (int z = 0; z < 32; z++) {
                    if (regionFile.containsChunk(x, z)) {
                        // totalBlocksPerLevel += 256;
                        // System.out.println("Chunk " + x + ", " + z);
                        // System.out.print('.');
                        Tag tag;
                        try (NBTInputStream in = new NBTInputStream(regionFile.getChunkDataInputStream(x, z))) {
                            tag = in.readTag();
                        }
                        Chunk chunk = (version == SUPPORTED_VERSION_1) ? new ChunkImpl((CompoundTag) tag, maxHeight) : new ChunkImpl2((CompoundTag) tag, maxHeight);
                        for (int xx = 0; xx < 16; xx++) {
                            for (int zz = 0; zz < 16; zz++) {
                                for (int y = maxY; y >= 0; y--) {
                                    int blockType = chunk.getBlockType(xx, y, zz);
                                    int dataValue = chunk.getDataValue(xx, y, zz);
                                    blockTypeCounts[y >> 4][(blockType << 4) | dataValue]++;
                                    blockTypeTotals[y >> 4][(blockType << 4) | dataValue]++;
                                // totalBlockCount++;
                                }
                            }
                        }
                    }
                }
            }
        // System.out.println();
        } finally {
            regionFile.close();
        }
        System.out.print('#');
    }
    System.out.println();
    System.out.println("\tGranite\tDiorite\tAndesite");
    for (int y = 0; y < maxHeight >> 4; y++) {
        int stoneLikeTotal = blockTypeTotals[y][Material.STONE.index] + blockTypeTotals[y][Material.GRANITE.index] + blockTypeTotals[y][Material.DIORITE.index] + blockTypeTotals[y][Material.ANDESITE.index];
        // System.out.println("Total stonelike blocks: " + stoneLikeTotal);
        System.out.print(y + "\t");
        System.out.printf("%6.2f‰\t", ((float) blockTypeTotals[y][Material.GRANITE.index] / stoneLikeTotal * 1000));
        System.out.printf("%6.2f‰\t", ((float) blockTypeTotals[y][Material.DIORITE.index] / stoneLikeTotal * 1000));
        System.out.printf("%6.2f‰%n", ((float) blockTypeTotals[y][Material.ANDESITE.index] / stoneLikeTotal * 1000));
    }
}
Also used : Pattern(java.util.regex.Pattern) NBTInputStream(org.jnbt.NBTInputStream) CompoundTag(org.jnbt.CompoundTag) Tag(org.jnbt.Tag) File(java.io.File) CompoundTag(org.jnbt.CompoundTag)

Example 10 with Tag

use of org.jnbt.Tag in project WorldPainter by Captain-Chaos.

the class RegressionIT method verifyJavaDimension.

protected void verifyJavaDimension(File worldDir, Dimension dimension, int... expectedBlocks) throws IOException {
    World2 world = dimension.getWorld();
    logger.info("Verifying dimension {} of map {}", dimension.getName(), world.getName());
    boolean checkBounds;
    Rectangle expectedBounds = null;
    if (!dimension.containsOneOf(NotPresent.INSTANCE)) {
        checkBounds = true;
        int lowestTileX, highestTileX, lowestTileY, highestTileY;
        if (dimension.getWorld().getTilesToExport() != null) {
            lowestTileX = Integer.MAX_VALUE;
            highestTileX = Integer.MIN_VALUE;
            lowestTileY = Integer.MAX_VALUE;
            highestTileY = Integer.MIN_VALUE;
            for (Point tile : dimension.getWorld().getTilesToExport()) {
                if (tile.x < lowestTileX) {
                    lowestTileX = tile.x;
                }
                if (tile.x > highestTileX) {
                    highestTileX = tile.x;
                }
                if (tile.y < lowestTileY) {
                    lowestTileY = tile.y;
                }
                if (tile.y > highestTileY) {
                    highestTileY = tile.y;
                }
            }
        } else {
            lowestTileX = dimension.getLowestX();
            highestTileX = dimension.getHighestX();
            lowestTileY = dimension.getLowestY();
            highestTileY = dimension.getHighestY();
        }
        int expectedLowestChunkX = lowestTileX << 3;
        int expectedHighestChunkX = ((highestTileX + 1) << 3) - 1;
        int expectedLowestChunkZ = lowestTileY << 3;
        int expectedHighestChunkZ = ((highestTileY + 1) << 3) - 1;
        expectedBounds = new Rectangle(expectedLowestChunkX, expectedLowestChunkZ, expectedHighestChunkX - expectedLowestChunkX + 1, expectedHighestChunkZ - expectedLowestChunkZ + 1);
    } else {
        checkBounds = false;
        logger.warn("Skipping bounds check for dimension which contains the NotReady layer");
    }
    File regionDir;
    switch(dimension.getDim()) {
        case DIM_NORMAL:
            regionDir = new File(worldDir, "region");
            break;
        case DIM_NETHER:
            regionDir = new File(worldDir, "DIM-1/region");
            break;
        case DIM_END:
            regionDir = new File(worldDir, "DIM1/region");
            break;
        default:
            throw new IllegalArgumentException();
    }
    Platform platform = world.getPlatform();
    int maxHeight = dimension.getMaxHeight();
    Pattern regionFilePattern = platform.equals(DefaultPlugin.JAVA_MCREGION) ? Pattern.compile("r\\.(-?\\d+)\\.(-?\\d+)\\.mcr") : Pattern.compile("r\\.(-?\\d+)\\.(-?\\d+)\\.mca");
    int lowestChunkX = Integer.MAX_VALUE, highestChunkX = Integer.MIN_VALUE;
    int lowestChunkZ = Integer.MAX_VALUE, highestChunkZ = Integer.MIN_VALUE;
    BitSet blockTypes = new BitSet(256);
    for (File file : regionDir.listFiles()) {
        Matcher matcher = regionFilePattern.matcher(file.getName());
        if (matcher.matches()) {
            int regionX = Integer.parseInt(matcher.group(1));
            int regionZ = Integer.parseInt(matcher.group(2));
            try (RegionFile regionFile = new RegionFile(file, true)) {
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                        if (regionFile.containsChunk(chunkX, chunkZ)) {
                            int absChunkX = (regionX << 5) + chunkX;
                            int absChunkZ = (regionZ << 5) + chunkZ;
                            if (absChunkX < lowestChunkX) {
                                lowestChunkX = absChunkX;
                            }
                            if (absChunkX > highestChunkX) {
                                highestChunkX = absChunkX;
                            }
                            if (absChunkZ < lowestChunkZ) {
                                lowestChunkZ = absChunkZ;
                            }
                            if (absChunkZ > highestChunkZ) {
                                highestChunkZ = absChunkZ;
                            }
                            Chunk chunk;
                            try (NBTInputStream in = new NBTInputStream(regionFile.getChunkDataInputStream(chunkX, chunkZ))) {
                                Tag tag = in.readTag();
                                chunk = platform.equals(DefaultPlugin.JAVA_MCREGION) ? new ChunkImpl((CompoundTag) tag, maxHeight, true) : new ChunkImpl2((CompoundTag) tag, maxHeight, true);
                            }
                            // all block types present
                            for (int x = 0; x < 16; x++) {
                                for (int y = 0; y < maxHeight; y++) {
                                    for (int z = 0; z < 16; z++) {
                                        blockTypes.set(chunk.getBlockType(x, y, z));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if (checkBounds) {
        assertEquals(expectedBounds, new Rectangle(lowestChunkX, lowestChunkZ, highestChunkX - lowestChunkX + 1, highestChunkZ - lowestChunkZ + 1));
    }
    // types and layers used
    for (int expectedBlock : expectedBlocks) {
        assertTrue("expected block type " + Block.BLOCKS[expectedBlock].name + " missing", blockTypes.get(expectedBlock));
    }
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) BitSet(java.util.BitSet) NBTInputStream(org.jnbt.NBTInputStream) CompoundTag(org.jnbt.CompoundTag) Tag(org.jnbt.Tag) File(java.io.File)

Aggregations

Tag (org.jnbt.Tag)10 CompoundTag (org.jnbt.CompoundTag)9 NBTInputStream (org.jnbt.NBTInputStream)8 File (java.io.File)3 ArrayList (java.util.ArrayList)3 Pattern (java.util.regex.Pattern)3 GZIPInputStream (java.util.zip.GZIPInputStream)3 DoubleTag (org.jnbt.DoubleTag)3 IntTag (org.jnbt.IntTag)3 ListTag (org.jnbt.ListTag)3 ShortTag (org.jnbt.ShortTag)3 ByteArrayTag (org.jnbt.ByteArrayTag)2 ByteTag (org.jnbt.ByteTag)2 FloatTag (org.jnbt.FloatTag)2 IntArrayTag (org.jnbt.IntArrayTag)2 LongTag (org.jnbt.LongTag)2 StringTag (org.jnbt.StringTag)2 FileInputStream (java.io.FileInputStream)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1