Search in sources :

Example 1 with WorldRegion

use of org.pepsoft.worldpainter.exporting.WorldRegion 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

BufferedImage (java.awt.image.BufferedImage)1 File (java.io.File)1 FilenameFilter (java.io.FilenameFilter)1 IOException (java.io.IOException)1 Arrays (java.util.Arrays)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 ExecutorService (java.util.concurrent.ExecutorService)1 Executors (java.util.concurrent.Executors)1 TimeUnit (java.util.concurrent.TimeUnit)1 ImageIO (javax.imageio.ImageIO)1 Constants (org.pepsoft.minecraft.Constants)1 Level (org.pepsoft.minecraft.Level)1 Material (org.pepsoft.minecraft.Material)1 RegionFile (org.pepsoft.minecraft.RegionFile)1 ColourUtils (org.pepsoft.util.ColourUtils)1 ColourScheme (org.pepsoft.worldpainter.ColourScheme)1 DefaultPlugin (org.pepsoft.worldpainter.DefaultPlugin)1 Platform (org.pepsoft.worldpainter.Platform)1 Version (org.pepsoft.worldpainter.Version)1