Search in sources :

Example 1 with RegionFile

use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.

the class FindOutliers method main.

public static void main(String[] args) throws IOException {
    File[] worldDirs = new File(args[0]).listFiles();
    for (File worldDir : worldDirs) {
        System.out.println("Scanning " + worldDir);
        File[] regionFiles = new File(worldDir, "region").listFiles();
        if ((regionFiles == null) || (regionFiles.length == 0)) {
            System.out.println("  No regions found");
            continue;
        }
        int regionCount = 0, chunkCount = 0;
        int lowestChunkX = Integer.MAX_VALUE, highestChunkX = Integer.MIN_VALUE, lowestChunkZ = Integer.MAX_VALUE, highestChunkZ = Integer.MIN_VALUE;
        List<Integer> xValues = new ArrayList<>(), zValues = new ArrayList<>();
        List<Point> chunks = new ArrayList<>();
        for (File file : regionFiles) {
            String[] nameFrags = file.getName().split("\\.");
            int regionX = Integer.parseInt(nameFrags[1]);
            int regionZ = Integer.parseInt(nameFrags[2]);
            regionCount++;
            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)) {
                            chunkCount++;
                            int chunkX = regionX * 32 + x, chunkZ = regionZ * 32 + z;
                            if (chunkX < lowestChunkX) {
                                lowestChunkX = chunkX;
                            }
                            if (chunkX > highestChunkX) {
                                highestChunkX = chunkX;
                            }
                            if (chunkZ < lowestChunkZ) {
                                lowestChunkZ = chunkZ;
                            }
                            if (chunkZ > highestChunkZ) {
                                highestChunkZ = chunkZ;
                            }
                            xValues.add(chunkX);
                            zValues.add(chunkZ);
                            chunks.add(new Point(chunkX, chunkZ));
                        }
                    }
                }
            } finally {
                regionFile.close();
            }
        }
        // System.out.println(args[0]);
        // System.out.println("Region count: " + regionCount);
        // System.out.println("Chunk count: " + chunkCount);
        // System.out.println("Size in chunks: " + (highestChunkX - lowestChunkX + 1) + " by " + (highestChunkZ - lowestChunkZ + 1));
        // System.out.println("Lowest chunk x: " + lowestChunkX + ", highest chunk x: " + highestChunkX);
        // System.out.println("Lowest chunk z: " + lowestChunkZ + ", highest chunk z: " + highestChunkZ);
        Collections.sort(xValues);
        int p1 = xValues.size() / 4;
        float q1 = xValues.get(p1) * 0.75f + xValues.get(p1 + 1) * 0.25f;
        int p2 = xValues.size() / 2;
        float q2 = (xValues.get(p2) + xValues.get(p2 + 1)) / 2f;
        int p3 = xValues.size() * 3 / 4;
        float q3 = xValues.get(p3) * 0.25f + xValues.get(p3 + 1) * 0.75f;
        float iqr = q3 - q1;
        int lowerLimit = (int) (q2 - iqr * 1.5f);
        int upperLimit = (int) (q2 + iqr * 1.5f);
        Set<Point> outlyingChunks = new HashSet<>();
        for (Point chunk : chunks) {
            if ((chunk.x < lowerLimit) || (chunk.x > upperLimit)) {
                outlyingChunks.add(chunk);
            }
        }
        Collections.sort(zValues);
        p1 = zValues.size() / 4;
        q1 = zValues.get(p1) * 0.75f + zValues.get(p1 + 1) * 0.25f;
        p2 = zValues.size() / 2;
        q2 = (zValues.get(p2) + zValues.get(p2 + 1)) / 2f;
        p3 = zValues.size() * 3 / 4;
        q3 = zValues.get(p3) * 0.25f + zValues.get(p3 + 1) * 0.75f;
        iqr = q3 - q1;
        lowerLimit = (int) (q2 - iqr * 1.5f);
        upperLimit = (int) (q2 + iqr * 1.5f);
        for (Point chunk : chunks) {
            if ((chunk.y < lowerLimit) || (chunk.y > upperLimit)) {
                outlyingChunks.add(chunk);
            }
        }
        if (!outlyingChunks.isEmpty()) {
            System.out.println("  Outlying chunk count: " + outlyingChunks.size());
        // for (Point outlyingChunk: outlyingChunks) {
        // System.out.println(outlyingChunk);
        // }
        } else {
            System.out.println("  No outlying chunks found: " + outlyingChunks.size());
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Point(java.awt.Point) Point(java.awt.Point) RegionFile(org.pepsoft.minecraft.RegionFile) File(java.io.File) RegionFile(org.pepsoft.minecraft.RegionFile) HashSet(java.util.HashSet)

Example 2 with RegionFile

use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.

the class MapImportDialog method analyseMap.

private void analyseMap() {
    mapStatistics = null;
    resetStats();
    File levelDatFile = new File(fieldFilename.getText());
    final File worldDir = levelDatFile.getParentFile();
    // Check if it's a valid level.dat file before we commit
    int version;
    try {
        Level testLevel = Level.load(levelDatFile);
        version = testLevel.getVersion();
    } catch (IOException e) {
        logger.error("IOException while analysing map " + levelDatFile, e);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
        return;
    } catch (IllegalArgumentException e) {
        logger.error("IllegalArgumentException while analysing map " + levelDatFile, e);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
        return;
    } catch (NullPointerException e) {
        logger.error("NullPointerException while analysing map " + levelDatFile, e);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("selected.file.is.not.a.valid.level.dat.file"), strings.getString("invalid.file"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    // Other sanity checks
    if ((version != SUPPORTED_VERSION_1) && (version != SUPPORTED_VERSION_2)) {
        logger.error("Unsupported Minecraft version while analysing map " + levelDatFile);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("unsupported.minecraft.version"), strings.getString("unsupported.version"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    File regionDir = new File(worldDir, "region");
    if (!regionDir.isDirectory()) {
        logger.error("Region directory missing while analysing map " + levelDatFile);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("the.region.folder.is.missing"), strings.getString("region.folder.missing"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    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)) {
        logger.error("Region files missing while analysing map " + levelDatFile);
        JOptionPane.showMessageDialog(MapImportDialog.this, strings.getString("the.region.folder.contains.no.region.files"), strings.getString("region.files.missing"), JOptionPane.ERROR_MESSAGE);
        return;
    }
    // Check for Nether and End
    boolean netherPresent = false, endPresent = false;
    File netherRegionDir = new File(worldDir, "DIM-1/region");
    if (netherRegionDir.isDirectory()) {
        File[] netherRegionFiles = netherRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
        if ((netherRegionFiles != null) && (netherRegionFiles.length > 0)) {
            netherPresent = true;
        }
    }
    File endRegionDir = new File(worldDir, "DIM1/region");
    if (endRegionDir.isDirectory()) {
        File[] endRegionFiles = endRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
        if ((endRegionFiles != null) && (endRegionFiles.length > 0)) {
            endPresent = true;
        }
    }
    checkBoxImportNether.setEnabled(netherPresent);
    checkBoxImportNether.setSelected(netherPresent);
    checkBoxImportEnd.setEnabled(endPresent);
    checkBoxImportEnd.setSelected(endPresent);
    mapStatistics = ProgressDialog.executeTask(this, new ProgressTask<MapStatistics>() {

        @Override
        public String getName() {
            return "Analyzing map...";
        }

        @Override
        public MapStatistics execute(ProgressReceiver progressReceiver) throws OperationCancelled {
            MapStatistics stats = new MapStatistics();
            int chunkCount = 0;
            List<Integer> xValues = new ArrayList<>(), zValues = new ArrayList<>();
            List<Point> chunks = new ArrayList<>();
            int count = 0;
            for (File file : regionFiles) {
                String[] nameFrags = file.getName().split("\\.");
                int regionX = Integer.parseInt(nameFrags[1]);
                int regionZ = Integer.parseInt(nameFrags[2]);
                try {
                    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)) {
                                    chunkCount++;
                                    int chunkX = regionX * 32 + x, chunkZ = regionZ * 32 + z;
                                    if (chunkX < stats.lowestChunkX) {
                                        stats.lowestChunkX = chunkX;
                                    }
                                    if (chunkX > stats.highestChunkX) {
                                        stats.highestChunkX = chunkX;
                                    }
                                    if (chunkZ < stats.lowestChunkZ) {
                                        stats.lowestChunkZ = chunkZ;
                                    }
                                    if (chunkZ > stats.highestChunkZ) {
                                        stats.highestChunkZ = chunkZ;
                                    }
                                    xValues.add(chunkX);
                                    zValues.add(chunkZ);
                                    chunks.add(new Point(chunkX, chunkZ));
                                }
                            }
                        }
                    } finally {
                        regionFile.close();
                    }
                } catch (IOException e) {
                    throw new RuntimeException("I/O error while analyzing map " + worldDir, e);
                }
                count++;
                progressReceiver.setProgress((float) count / (regionFiles.length + 1));
            }
            stats.chunkCount = chunkCount;
            if (chunkCount == 0) {
                // Completely empty map (wrong region file format)?
                progressReceiver.setProgress(1.0f);
                return stats;
            }
            Collections.sort(xValues);
            int p1 = xValues.size() / 4;
            float q1 = xValues.get(p1) * 0.75f + xValues.get(p1 + 1) * 0.25f;
            int p2 = xValues.size() / 2;
            float q2 = (xValues.get(p2) + xValues.get(p2 + 1)) / 2f;
            int p3 = xValues.size() * 3 / 4;
            float q3 = xValues.get(p3) * 0.25f + xValues.get(p3 + 1) * 0.75f;
            float iqr = q3 - q1;
            int lowerLimit = (int) (q2 - iqr * 1.5f);
            int upperLimit = (int) (q2 + iqr * 1.5f);
            for (Point chunk : chunks) {
                if ((chunk.x < lowerLimit) || (chunk.x > upperLimit)) {
                    stats.outlyingChunks.add(chunk);
                }
            }
            Collections.sort(zValues);
            p1 = zValues.size() / 4;
            q1 = zValues.get(p1) * 0.75f + zValues.get(p1 + 1) * 0.25f;
            p2 = zValues.size() / 2;
            q2 = (zValues.get(p2) + zValues.get(p2 + 1)) / 2f;
            p3 = zValues.size() * 3 / 4;
            q3 = zValues.get(p3) * 0.25f + zValues.get(p3 + 1) * 0.75f;
            iqr = q3 - q1;
            lowerLimit = (int) (q2 - iqr * 1.5f);
            upperLimit = (int) (q2 + iqr * 1.5f);
            for (Point chunk : chunks) {
                if ((chunk.y < lowerLimit) || (chunk.y > upperLimit)) {
                    stats.outlyingChunks.add(chunk);
                }
            }
            if (!stats.outlyingChunks.isEmpty()) {
                chunks.stream().filter(chunk -> !stats.outlyingChunks.contains(chunk)).forEach(chunk -> {
                    if (chunk.x < stats.lowestChunkXNoOutliers) {
                        stats.lowestChunkXNoOutliers = chunk.x;
                    }
                    if (chunk.x > stats.highestChunkXNoOutliers) {
                        stats.highestChunkXNoOutliers = chunk.x;
                    }
                    if (chunk.y < stats.lowestChunkZNoOutliers) {
                        stats.lowestChunkZNoOutliers = chunk.y;
                    }
                    if (chunk.y > stats.highestChunkZNoOutliers) {
                        stats.highestChunkZNoOutliers = chunk.y;
                    }
                });
            } else {
                stats.lowestChunkXNoOutliers = stats.lowestChunkX;
                stats.highestChunkXNoOutliers = stats.highestChunkX;
                stats.lowestChunkZNoOutliers = stats.lowestChunkZ;
                stats.highestChunkZNoOutliers = stats.highestChunkZ;
            }
            progressReceiver.setProgress(1.0f);
            return stats;
        }
    }, true);
    if ((mapStatistics != null) && (mapStatistics.chunkCount > 0)) {
        int width = mapStatistics.highestChunkXNoOutliers - mapStatistics.lowestChunkXNoOutliers + 1;
        int length = mapStatistics.highestChunkZNoOutliers - mapStatistics.lowestChunkZNoOutliers + 1;
        int area = (mapStatistics.chunkCount - mapStatistics.outlyingChunks.size());
        labelWidth.setText(FORMATTER.format(width * 16) + " blocks (from " + FORMATTER.format(mapStatistics.lowestChunkXNoOutliers << 4) + " to " + FORMATTER.format((mapStatistics.highestChunkXNoOutliers << 4) + 15) + "; " + FORMATTER.format(width) + " chunks)");
        labelLength.setText(FORMATTER.format(length * 16) + " blocks (from " + FORMATTER.format(mapStatistics.lowestChunkZNoOutliers << 4) + " to " + FORMATTER.format((mapStatistics.highestChunkZNoOutliers << 4) + 15) + "; " + FORMATTER.format(length) + " chunks)");
        labelArea.setText(FORMATTER.format(area * 256L) + " blocksĀ² (" + FORMATTER.format(area) + " chunks)");
        if (!mapStatistics.outlyingChunks.isEmpty()) {
            // There are outlying chunks
            int widthWithOutliers = mapStatistics.highestChunkX - mapStatistics.lowestChunkX + 1;
            int lengthWithOutliers = mapStatistics.highestChunkZ - mapStatistics.lowestChunkZ + 1;
            int areaOfOutliers = mapStatistics.outlyingChunks.size();
            labelOutliers1.setVisible(true);
            labelOutliers2.setVisible(true);
            labelWidthWithOutliers.setText(FORMATTER.format(widthWithOutliers * 16) + " blocks (" + FORMATTER.format(widthWithOutliers) + " chunks)");
            labelWidthWithOutliers.setVisible(true);
            labelOutliers3.setVisible(true);
            labelLengthWithOutliers.setText(FORMATTER.format(lengthWithOutliers * 16) + " blocks (" + FORMATTER.format(lengthWithOutliers) + " chunks)");
            labelLengthWithOutliers.setVisible(true);
            labelOutliers4.setVisible(true);
            labelAreaOutliers.setText(FORMATTER.format(areaOfOutliers * 256L) + " blocksĀ² (" + FORMATTER.format(areaOfOutliers) + " chunks)");
            labelAreaOutliers.setVisible(true);
            checkBoxImportOutliers.setVisible(true);
            // The dialog may need to become bigger:
            pack();
        }
    }
}
Also used : org.pepsoft.worldpainter(org.pepsoft.worldpainter) java.util(java.util) DocumentListener(javax.swing.event.DocumentListener) ProgressDialog(org.pepsoft.util.swing.ProgressDialog) IOException(java.io.IOException) FileFilter(javax.swing.filechooser.FileFilter) File(java.io.File) NumberFormat(java.text.NumberFormat) InvocationTargetException(java.lang.reflect.InvocationTargetException) java.awt(java.awt) ProgressTask(org.pepsoft.util.swing.ProgressTask) List(java.util.List) ProgressReceiver(org.pepsoft.util.ProgressReceiver) OperationCancelled(org.pepsoft.util.ProgressReceiver.OperationCancelled) FileUtils(org.pepsoft.util.FileUtils) Level(org.pepsoft.minecraft.Level) Pattern(java.util.regex.Pattern) DocumentEvent(javax.swing.event.DocumentEvent) MinecraftUtil(org.pepsoft.worldpainter.util.MinecraftUtil) SUPPORTED_VERSION_2(org.pepsoft.minecraft.Constants.SUPPORTED_VERSION_2) RegionFile(org.pepsoft.minecraft.RegionFile) javax.swing(javax.swing) SUPPORTED_VERSION_1(org.pepsoft.minecraft.Constants.SUPPORTED_VERSION_1) Pattern(java.util.regex.Pattern) ProgressTask(org.pepsoft.util.swing.ProgressTask) IOException(java.io.IOException) RegionFile(org.pepsoft.minecraft.RegionFile) ProgressReceiver(org.pepsoft.util.ProgressReceiver) Level(org.pepsoft.minecraft.Level) File(java.io.File) RegionFile(org.pepsoft.minecraft.RegionFile)

Example 3 with RegionFile

use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.

the class DumpEntities method main.

public static void main(String[] args) throws IOException {
    File worldDir = new File(args[0]);
    File[] regionFiles = new File(worldDir, "region").listFiles();
    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)) {
                        CompoundTag tag;
                        try (NBTInputStream in = new NBTInputStream(regionFile.getChunkDataInputStream(x, z))) {
                            tag = (CompoundTag) in.readTag();
                        }
                        ChunkImpl2 chunk = new ChunkImpl2(tag, 256);
                        /*&& (((Painting) entity).getTileX() == 40) && (((Painting) entity).getTileZ() == 31)*/
                        chunk.getEntities().stream().filter(entity -> (entity instanceof Painting)).forEach(System.out::println);
                    }
                }
            }
        } finally {
            regionFile.close();
        }
    }
}
Also used : NBTInputStream(org.jnbt.NBTInputStream) Painting(org.pepsoft.minecraft.Painting) CompoundTag(org.jnbt.CompoundTag) ChunkImpl2(org.pepsoft.minecraft.ChunkImpl2) IOException(java.io.IOException) File(java.io.File) RegionFile(org.pepsoft.minecraft.RegionFile) RegionFile(org.pepsoft.minecraft.RegionFile) NBTInputStream(org.jnbt.NBTInputStream) File(java.io.File) RegionFile(org.pepsoft.minecraft.RegionFile) CompoundTag(org.jnbt.CompoundTag) ChunkImpl2(org.pepsoft.minecraft.ChunkImpl2) Painting(org.pepsoft.minecraft.Painting)

Example 4 with RegionFile

use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.

the class RegionFileNode method loadChildren.

@Override
protected Node[] loadChildren() {
    try {
        List<Node> chunks = new ArrayList<>();
        RegionFile regionFile = new RegionFile(file);
        for (int chunkX = 0; chunkX < 32; chunkX++) {
            for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                if (regionFile.containsChunk(chunkX, chunkZ)) {
                    chunks.add(new ChunkNode(regionFile, chunkX, chunkZ));
                }
            }
        }
        return chunks.toArray(new Node[chunks.size()]);
    } catch (IOException e) {
        throw new RuntimeException("I/O error while reading region file", e);
    }
}
Also used : RegionFile(org.pepsoft.minecraft.RegionFile) Node(org.pepsoft.worldpainter.mapexplorer.Node) ArrayList(java.util.ArrayList) IOException(java.io.IOException)

Example 5 with RegionFile

use of org.pepsoft.minecraft.RegionFile in project WorldPainter by Captain-Chaos.

the class Mapper method map.

private static void map(final File worldDir, final int dim, final ColourScheme colourScheme, File output) throws IOException, InterruptedException {
    File levelDatFile = new File(worldDir, "level.dat");
    Level level = Level.load(levelDatFile);
    final Platform platform = level.getVersion() == SUPPORTED_VERSION_1 ? DefaultPlugin.JAVA_MCREGION : DefaultPlugin.JAVA_ANVIL;
    maxHeight = level.getMaxHeight();
    File dimensionDir;
    switch(dim) {
        case 0:
            dimensionDir = worldDir;
            break;
        case 1:
            dimensionDir = new File(worldDir, "DIM-1");
            break;
        case 2:
            dimensionDir = new File(worldDir, "DIM1");
            break;
        default:
            throw new IllegalArgumentException(Integer.toString(dim));
    }
    final File regionDir = new File(dimensionDir, "region");
    if (!regionDir.exists()) {
        error("Map does not have dimension " + dim);
    }
    System.out.println("Mapping " + worldDir);
    System.out.println("Name: " + level.getName());
    System.out.println("Seed: " + level.getSeed());
    if (level.getGeneratorName() != null) {
        System.out.println("Generator: " + level.getGeneratorName() + " (version " + level.getGeneratorVersion() + ")");
    }
    System.out.println("Map height: " + maxHeight);
    System.out.println("Storage format: " + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? "McRegion (Minecraft 1.1 or earlier)" : "Anvil (Minecraft 1.2 or later)"));
    // Determine size
    File[] regionFiles = regionDir.listFiles(platform.equals(DefaultPlugin.JAVA_MCREGION) ? (dir, name) -> name.toLowerCase().endsWith(".mcr") : (FilenameFilter) (dir, name) -> name.toLowerCase().endsWith(".mca"));
    int tmpLowestRegionX = Integer.MAX_VALUE, tmpHighestRegionX = Integer.MIN_VALUE;
    int tmpLowestRegionZ = Integer.MAX_VALUE, tmpHighestRegionZ = Integer.MIN_VALUE;
    for (File regionFile : regionFiles) {
        String[] parts = regionFile.getName().split("\\.");
        int regionX = Integer.parseInt(parts[1]);
        int regionZ = Integer.parseInt(parts[2]);
        if (regionX < tmpLowestRegionX) {
            tmpLowestRegionX = regionX;
        }
        if (regionX > tmpHighestRegionX) {
            tmpHighestRegionX = regionX;
        }
        if (regionZ < tmpLowestRegionZ) {
            tmpLowestRegionZ = regionZ;
        }
        if (regionZ > tmpHighestRegionZ) {
            tmpHighestRegionZ = regionZ;
        }
    }
    final int lowestRegionX = tmpLowestRegionX, highestRegionX = tmpHighestRegionX;
    final int lowestRegionZ = tmpLowestRegionZ, highestRegionZ = tmpHighestRegionZ;
    int tmpLowestChunkX = Integer.MAX_VALUE, tmpHighestChunkX = Integer.MIN_VALUE;
    int tmpLowestChunkZ = Integer.MAX_VALUE, tmpHighestChunkZ = Integer.MIN_VALUE;
    for (int regionX = lowestRegionX; regionX <= highestRegionX; regionX++) {
        File file = new File(regionDir, "r." + regionX + "." + lowestRegionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
        if (file.exists()) {
            int regionChunkX = regionX << 5;
            int regionChunkZ = lowestRegionZ << 5;
            RegionFile region = new RegionFile(file);
            try {
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                        if (region.containsChunk(chunkX, chunkZ)) {
                            int x = regionChunkX + chunkX;
                            int z = regionChunkZ + chunkZ;
                            if (x < tmpLowestChunkX) {
                                tmpLowestChunkX = x;
                            }
                            if (x > tmpHighestChunkX) {
                                tmpHighestChunkX = x;
                            }
                            if (z < tmpLowestChunkZ) {
                                tmpLowestChunkZ = z;
                            }
                            if (z > tmpHighestChunkZ) {
                                tmpHighestChunkZ = z;
                            }
                        }
                    }
                }
            } finally {
                region.close();
            }
        }
        file = new File(regionDir, "r." + regionX + "." + highestRegionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
        if (file.exists()) {
            int regionChunkX = regionX << 5;
            int regionChunkZ = highestRegionZ << 5;
            RegionFile region = new RegionFile(file);
            try {
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                        if (region.containsChunk(chunkX, chunkZ)) {
                            int x = regionChunkX + chunkX;
                            int z = regionChunkZ + chunkZ;
                            if (x < tmpLowestChunkX) {
                                tmpLowestChunkX = x;
                            }
                            if (x > tmpHighestChunkX) {
                                tmpHighestChunkX = x;
                            }
                            if (z < tmpLowestChunkZ) {
                                tmpLowestChunkZ = z;
                            }
                            if (z > tmpHighestChunkZ) {
                                tmpHighestChunkZ = z;
                            }
                        }
                    }
                }
            } finally {
                region.close();
            }
        }
    }
    for (int regionZ = lowestRegionZ + 1; regionZ <= highestRegionZ - 1; regionZ++) {
        File file = new File(regionDir, "r." + lowestRegionX + "." + regionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
        if (file.exists()) {
            int regionChunkX = lowestRegionX << 5;
            int regionChunkZ = regionZ << 5;
            RegionFile region = new RegionFile(file);
            try {
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                        if (region.containsChunk(chunkX, chunkZ)) {
                            int x = regionChunkX + chunkX;
                            int z = regionChunkZ + chunkZ;
                            if (x < tmpLowestChunkX) {
                                tmpLowestChunkX = x;
                            }
                            if (x > tmpHighestChunkX) {
                                tmpHighestChunkX = x;
                            }
                            if (z < tmpLowestChunkZ) {
                                tmpLowestChunkZ = z;
                            }
                            if (z > tmpHighestChunkZ) {
                                tmpHighestChunkZ = z;
                            }
                        }
                    }
                }
            } finally {
                region.close();
            }
        }
        file = new File(regionDir, "r." + highestRegionX + "." + regionZ + (platform.equals(DefaultPlugin.JAVA_MCREGION) ? ".mcr" : ".mca"));
        if (file.exists()) {
            int regionChunkX = highestRegionX << 5;
            int regionChunkZ = regionZ << 5;
            RegionFile region = new RegionFile(file);
            try {
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
                        if (region.containsChunk(chunkX, chunkZ)) {
                            int x = regionChunkX + chunkX;
                            int z = regionChunkZ + chunkZ;
                            if (x < tmpLowestChunkX) {
                                tmpLowestChunkX = x;
                            }
                            if (x > tmpHighestChunkX) {
                                tmpHighestChunkX = x;
                            }
                            if (z < tmpLowestChunkZ) {
                                tmpLowestChunkZ = z;
                            }
                            if (z > tmpHighestChunkZ) {
                                tmpHighestChunkZ = z;
                            }
                        }
                    }
                }
            } finally {
                region.close();
            }
        }
    }
    final int lowestChunkX = tmpLowestChunkX;
    final int lowestChunkZ = tmpLowestChunkZ;
    int widthChunks = (tmpHighestChunkX - tmpLowestChunkX + 1);
    int heightChunks = (tmpHighestChunkZ - tmpLowestChunkZ + 1);
    System.out.println("Width: " + (widthChunks << 4));
    System.out.println("Height: " + (heightChunks << 4));
    final BufferedImage image = new BufferedImage(widthChunks << 4, heightChunks << 4, BufferedImage.TYPE_INT_ARGB);
    final int imageOffsetX = lowestChunkX << 4;
    final int imageOffsetY = lowestChunkZ << 4;
    final int waterColour = colourScheme.getColour(Material.WATER);
    final int lavaColour = colourScheme.getColour(Material.LAVA);
    final int snowColour = colourScheme.getColour(Material.SNOW);
    int threads = Runtime.getRuntime().availableProcessors();
    System.out.print("Mapping");
    ExecutorService executorService = Executors.newFixedThreadPool(threads);
    for (File file : regionFiles) {
        final File finalFile = file;
        executorService.submit(() -> {
            try {
                String[] parts = finalFile.getName().split("\\.");
                int regionX = Integer.parseInt(parts[1]);
                int regionY = Integer.parseInt(parts[2]);
                WorldRegion world = new WorldRegion(worldDir, dim, regionX, regionY, maxHeight, platform);
                int[][] heightCache = new int[544][544];
                for (int i = 0; i < 544; i++) {
                    Arrays.fill(heightCache[i], -1);
                }
                for (int chunkX = 0; chunkX < 32; chunkX++) {
                    for (int chunkY = 0; chunkY < 32; chunkY++) {
                        int worldChunkX = (regionX << 5) | chunkX;
                        int worldChunkY = (regionY << 5) | chunkY;
                        if (world.isChunkPresent(worldChunkX, worldChunkY)) {
                            for (int x = 0; x < 16; x++) {
                                for (int y = 0; y < 16; y++) {
                                    int worldX = (worldChunkX << 4) | x;
                                    int worldY = (worldChunkY << 4) | y;
                                    boolean snow = false, water = false, lava = false;
                                    int waterLevel = 0;
                                    for (int height = maxHeight - 1; height >= 0; height--) {
                                        int blockType = world.getBlockTypeAt(worldX, worldY, height);
                                        if (blockType != BLK_AIR) {
                                            if (blockType == BLK_SNOW) {
                                                snow = true;
                                            } else if ((blockType == BLK_STATIONARY_WATER) || (blockType == BLK_WATER) || (blockType == BLK_STATIONARY_LAVA) || (blockType == BLK_LAVA)) {
                                                if ((world.getDataAt(worldX, worldY, height) == 0) && (waterLevel == 0)) {
                                                    waterLevel = height;
                                                    if ((blockType == BLK_LAVA) || (blockType == BLK_STATIONARY_LAVA)) {
                                                        lava = true;
                                                    } else {
                                                        water = true;
                                                    }
                                                }
                                            } else if (TERRAIN_BLOCKS.contains(blockType)) {
                                                // Terrain found
                                                int data = world.getDataAt(worldX, worldY, height);
                                                int depth = waterLevel - height;
                                                int fluidAlpha = 0xff >> Math.min(depth, 3);
                                                int colour = colourScheme.getColour(blockType, data);
                                                if (depth > 0) {
                                                    colour = ColourUtils.multiply(colour, getBrightenAmount(world, heightCache, ((chunkX + 1) << 4) | x, ((chunkY + 1) << 4) | y, regionX, regionY));
                                                }
                                                if (water) {
                                                    colour = ColourUtils.mix(colour, waterColour, fluidAlpha);
                                                } else if (lava) {
                                                    colour = ColourUtils.mix(colour, lavaColour, fluidAlpha);
                                                }
                                                if (snow) {
                                                    colour = ColourUtils.mix(colour, snowColour, 64);
                                                }
                                                if (depth <= 0) {
                                                    colour = ColourUtils.multiply(colour, getBrightenAmount(world, heightCache, ((chunkX + 1) << 4) | x, ((chunkY + 1) << 4) | y, regionX, regionY));
                                                }
                                                image.setRGB(worldX - imageOffsetX, worldY - imageOffsetY, 0xff000000 | colour);
                                                break;
                                            } else {
                                                // Non-terrain block found (not shaded)
                                                int data = world.getDataAt(worldX, worldY, height);
                                                int depth = waterLevel - height;
                                                int fluidAlpha = 0xff >> Math.min(depth, 3);
                                                int colour = colourScheme.getColour(blockType, data);
                                                if (water) {
                                                    colour = ColourUtils.mix(colour, waterColour, fluidAlpha);
                                                } else if (lava) {
                                                    colour = ColourUtils.mix(colour, lavaColour, fluidAlpha);
                                                }
                                                if (snow) {
                                                    colour = ColourUtils.mix(colour, snowColour);
                                                }
                                                image.setRGB(worldX - imageOffsetX, worldY - imageOffsetY, 0xff000000 | colour);
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                System.out.print('.');
                System.out.flush();
            } catch (Throwable t) {
                t.printStackTrace();
                System.exit(1);
            }
        });
    }
    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.DAYS);
    System.out.println();
    // Save image
    System.out.println("Saving image to " + output + "...");
    ImageIO.write(image, "PNG", output);
    System.out.println("Finished");
}
Also used : FilenameFilter(java.io.FilenameFilter) MinecraftWorld(org.pepsoft.worldpainter.exporting.MinecraftWorld) Arrays(java.util.Arrays) BufferedImage(java.awt.image.BufferedImage) WorldRegion(org.pepsoft.worldpainter.exporting.WorldRegion) DynMapColourScheme(org.pepsoft.worldpainter.colourschemes.DynMapColourScheme) Set(java.util.Set) IOException(java.io.IOException) File(java.io.File) Executors(java.util.concurrent.Executors) HashSet(java.util.HashSet) TimeUnit(java.util.concurrent.TimeUnit) Constants(org.pepsoft.minecraft.Constants) Platform(org.pepsoft.worldpainter.Platform) Material(org.pepsoft.minecraft.Material) ColourUtils(org.pepsoft.util.ColourUtils) ImageIO(javax.imageio.ImageIO) Level(org.pepsoft.minecraft.Level) ColourScheme(org.pepsoft.worldpainter.ColourScheme) DefaultPlugin(org.pepsoft.worldpainter.DefaultPlugin) Version(org.pepsoft.worldpainter.Version) ExecutorService(java.util.concurrent.ExecutorService) RegionFile(org.pepsoft.minecraft.RegionFile) WorldRegion(org.pepsoft.worldpainter.exporting.WorldRegion) Platform(org.pepsoft.worldpainter.Platform) BufferedImage(java.awt.image.BufferedImage) FilenameFilter(java.io.FilenameFilter) RegionFile(org.pepsoft.minecraft.RegionFile) ExecutorService(java.util.concurrent.ExecutorService) Level(org.pepsoft.minecraft.Level) File(java.io.File) RegionFile(org.pepsoft.minecraft.RegionFile)

Aggregations

RegionFile (org.pepsoft.minecraft.RegionFile)5 File (java.io.File)4 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Level (org.pepsoft.minecraft.Level)2 java.awt (java.awt)1 Point (java.awt.Point)1 BufferedImage (java.awt.image.BufferedImage)1 FilenameFilter (java.io.FilenameFilter)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 NumberFormat (java.text.NumberFormat)1 java.util (java.util)1 Arrays (java.util.Arrays)1 List (java.util.List)1 Set (java.util.Set)1 ExecutorService (java.util.concurrent.ExecutorService)1 Executors (java.util.concurrent.Executors)1 TimeUnit (java.util.concurrent.TimeUnit)1 Pattern (java.util.regex.Pattern)1