Search in sources :

Example 21 with Layer

use of org.pepsoft.worldpainter.layers.Layer in project WorldPainter by Captain-Chaos.

the class TunnelLayerExporter method render.

@Override
public List<Fixup> render(Dimension dimension, Rectangle area, Rectangle exportedArea, MinecraftWorld world) {
    final TunnelLayer.Mode floorMode = layer.getFloorMode(), roofMode = layer.getRoofMode();
    final int floorWallDepth = layer.getFloorWallDepth(), roofWallDepth = layer.getRoofWallDepth(), floorLevel = layer.getFloorLevel(), roofLevel = layer.getRoofLevel(), maxWallDepth = Math.max(floorWallDepth, roofWallDepth) + 1, floorMin = layer.getFloorMin(), floorMax = layer.getFloorMax(), roofMin = layer.getRoofMin(), roofMax = layer.getRoofMax(), floodLevel = layer.getFloodLevel();
    final int minZ = dimension.isBottomless() ? 0 : 1, maxZ = dimension.getMaxHeight() - 1;
    final boolean removeWater = layer.isRemoveWater(), floodWithLava = layer.isFloodWithLava();
    final MixedMaterial floorMaterial = layer.getFloorMaterial(), wallMaterial = layer.getWallMaterial(), roofMaterial = layer.getRoofMaterial();
    if (floorNoise != null) {
        floorNoise.setSeed(dimension.getSeed());
    }
    if (roofNoise != null) {
        roofNoise.setSeed(dimension.getSeed());
    }
    if ((floorMaterial == null) && (wallMaterial == null) && (roofMaterial == null)) {
        // One pass: just remove blocks
        for (int x = area.x; x < area.x + area.width; x++) {
            for (int y = area.y; y < area.y + area.height; y++) {
                if (dimension.getBitLayerValueAt(layer, x, y)) {
                    final int terrainHeight = dimension.getIntHeightAt(x, y);
                    int actualFloorLevel = calculateLevel(floorMode, floorLevel, terrainHeight, floorMin, floorMax, minZ, maxZ, (floorNoise != null) ? ((int) floorNoise.getHeight(x, y) - floorNoiseOffset) : 0);
                    int actualRoofLevel = calculateLevel(roofMode, roofLevel, terrainHeight, roofMin, roofMax, minZ, maxZ, (roofNoise != null) ? ((int) roofNoise.getHeight(x, y) - roofNoiseOffset) : 0);
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final float distanceToWall = dimension.getDistanceToEdge(layer, x, y, maxWallDepth) - 1;
                    final int floorLedgeHeight = calculateLedgeHeight(floorWallDepth, distanceToWall);
                    final int roofLedgeHeight = calculateLedgeHeight(roofWallDepth, distanceToWall);
                    actualFloorLevel += floorLedgeHeight;
                    actualRoofLevel -= roofLedgeHeight;
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final int waterLevel = dimension.getWaterLevelAt(x, y);
                    for (int z = Math.min(removeWater ? Math.max(terrainHeight, waterLevel) : terrainHeight, actualRoofLevel); z > actualFloorLevel; z--) {
                        if (removeWater || (z <= terrainHeight) || (z > waterLevel)) {
                            if (z <= floodLevel) {
                                world.setMaterialAt(x, y, z, floodWithLava ? Material.LAVA : Material.WATER);
                            } else {
                                world.setMaterialAt(x, y, z, Material.AIR);
                            }
                        }
                    }
                    if (actualFloorLevel == 0) {
                        // probably what the user wants
                        if ((floodLevel > 0) && (0 <= floodLevel)) {
                            world.setMaterialAt(x, y, 0, floodWithLava ? Material.STATIONARY_LAVA : Material.STATIONARY_WATER);
                        } else {
                            world.setMaterialAt(x, y, 0, Material.AIR);
                        }
                    }
                }
            }
        }
    } else {
        // excavate the interior
        for (int x = area.x; x < area.x + area.width; x++) {
            for (int y = area.y; y < area.y + area.height; y++) {
                if (dimension.getBitLayerValueAt(layer, x, y)) {
                    int terrainHeight = dimension.getIntHeightAt(x, y);
                    int actualFloorLevel = calculateLevel(floorMode, floorLevel, terrainHeight, floorMin, floorMax, minZ, maxZ, (floorNoise != null) ? ((int) floorNoise.getHeight(x, y) - floorNoiseOffset) : 0);
                    int actualRoofLevel = calculateLevel(roofMode, roofLevel, terrainHeight, roofMin, roofMax, minZ, maxZ, (roofNoise != null) ? ((int) roofNoise.getHeight(x, y) - roofNoiseOffset) : 0);
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final float distanceToWall = dimension.getDistanceToEdge(layer, x, y, maxWallDepth) - 1;
                    final int floorLedgeHeight = calculateLedgeHeight(floorWallDepth, distanceToWall);
                    final int roofLedgeHeight = calculateLedgeHeight(roofWallDepth, distanceToWall);
                    actualFloorLevel += floorLedgeHeight;
                    actualRoofLevel -= roofLedgeHeight;
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    int waterLevel = dimension.getWaterLevelAt(x, y);
                    boolean flooded = waterLevel > terrainHeight;
                    final int startZ = Math.min(removeWater ? Math.max(terrainHeight, waterLevel) : terrainHeight, actualRoofLevel);
                    for (int z = startZ; z > actualFloorLevel; z--) {
                        if ((floorLedgeHeight == 0) && (floorMaterial != null)) {
                            setIfSolid(world, x, y, z - 1, minZ, maxZ, floorMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                        if (wallMaterial != null) {
                            if (floorLedgeHeight > 0) {
                                setIfSolid(world, x, y, z - 1, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                            }
                            if (roofLedgeHeight > 0) {
                                setIfSolid(world, x, y, z + 1, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                            }
                        }
                        if ((roofLedgeHeight == 0) && (roofMaterial != null)) {
                            setIfSolid(world, x, y, z + 1, minZ, maxZ, roofMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                    }
                    if (wallMaterial != null) {
                        terrainHeight = dimension.getIntHeightAt(x - 1, y);
                        waterLevel = dimension.getWaterLevelAt(x - 1, y);
                        flooded = waterLevel > terrainHeight;
                        for (int z = startZ; z > actualFloorLevel; z--) {
                            setIfSolid(world, x - 1, y, z, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                        terrainHeight = dimension.getIntHeightAt(x, y - 1);
                        waterLevel = dimension.getWaterLevelAt(x, y - 1);
                        flooded = waterLevel > terrainHeight;
                        for (int z = startZ; z > actualFloorLevel; z--) {
                            setIfSolid(world, x, y - 1, z, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                        terrainHeight = dimension.getIntHeightAt(x + 1, y);
                        waterLevel = dimension.getWaterLevelAt(x + 1, y);
                        flooded = waterLevel > terrainHeight;
                        for (int z = startZ; z > actualFloorLevel; z--) {
                            setIfSolid(world, x + 1, y, z, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                        terrainHeight = dimension.getIntHeightAt(x, y + 1);
                        waterLevel = dimension.getWaterLevelAt(x, y + 1);
                        flooded = waterLevel > terrainHeight;
                        for (int z = startZ; z > actualFloorLevel; z--) {
                            setIfSolid(world, x, y + 1, z, minZ, maxZ, wallMaterial, flooded, terrainHeight, waterLevel, removeWater);
                        }
                    }
                }
            }
        }
        // Second pass: excavate interior
        for (int x = area.x; x < area.x + area.width; x++) {
            for (int y = area.y; y < area.y + area.height; y++) {
                if (dimension.getBitLayerValueAt(layer, x, y)) {
                    final int terrainHeight = dimension.getIntHeightAt(x, y);
                    int actualFloorLevel = calculateLevel(floorMode, floorLevel, terrainHeight, floorMin, floorMax, minZ, maxZ, (floorNoise != null) ? ((int) floorNoise.getHeight(x, y) - floorNoiseOffset) : 0);
                    int actualRoofLevel = calculateLevel(roofMode, roofLevel, terrainHeight, roofMin, roofMax, minZ, maxZ, (roofNoise != null) ? ((int) roofNoise.getHeight(x, y) - roofNoiseOffset) : 0);
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final float distanceToWall = dimension.getDistanceToEdge(layer, x, y, maxWallDepth) - 1;
                    final int floorLedgeHeight = calculateLedgeHeight(floorWallDepth, distanceToWall);
                    final int roofLedgeHeight = calculateLedgeHeight(roofWallDepth, distanceToWall);
                    actualFloorLevel += floorLedgeHeight;
                    actualRoofLevel -= roofLedgeHeight;
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final int waterLevel = dimension.getWaterLevelAt(x, y);
                    for (int z = actualRoofLevel; z > actualFloorLevel; z--) {
                        if (removeWater || (z <= terrainHeight) || (z > waterLevel)) {
                            if (z <= floodLevel) {
                                world.setMaterialAt(x, y, z, floodWithLava ? Material.LAVA : Material.WATER);
                            } else {
                                world.setMaterialAt(x, y, z, Material.AIR);
                            }
                        }
                    }
                    if (actualFloorLevel == 0) {
                        // probably what the user wants
                        if ((floodLevel > 0) && (0 <= floodLevel)) {
                            world.setMaterialAt(x, y, 0, floodWithLava ? Material.LAVA : Material.WATER);
                        } else {
                            world.setMaterialAt(x, y, 0, Material.AIR);
                        }
                    }
                }
            }
        }
    }
    // Second/third pass: render floor layers
    List<Fixup> fixups = new ArrayList<>();
    final Map<Layer, TunnelLayer.LayerSettings> floorLayers = layer.getFloorLayers();
    if ((floorLayers != null) && (!floorLayers.isEmpty())) {
        final IncidentalLayerExporter[] floorExporters = new IncidentalLayerExporter[floorLayers.size()];
        final TunnelLayer.LayerSettings[] floorLayerSettings = new TunnelLayer.LayerSettings[floorLayers.size()];
        final NoiseHeightMap[] floorLayerNoise = new NoiseHeightMap[floorLayers.size()];
        int index = 0;
        for (Layer floorLayer : floorLayers.keySet()) {
            floorExporters[index] = (IncidentalLayerExporter) floorLayer.getExporter();
            TunnelLayer.LayerSettings layerSettings = floorLayers.get(floorLayer);
            floorLayerSettings[index] = layerSettings;
            if (layerSettings.getVariation() != null) {
                floorLayerNoise[index] = new NoiseHeightMap(layerSettings.getVariation(), index);
                floorLayerNoise[index].setSeed(dimension.getSeed());
            }
            index++;
        }
        final TunnelFloorDimension floorDimension = new TunnelFloorDimension(dimension, layer);
        for (int x = area.x; x < area.x + area.width; x++) {
            for (int y = area.y; y < area.y + area.height; y++) {
                if (dimension.getBitLayerValueAt(layer, x, y)) {
                    final int terrainHeight = dimension.getIntHeightAt(x, y);
                    int actualFloorLevel = calculateLevel(floorMode, floorLevel, terrainHeight, floorMin, floorMax, minZ, maxZ, (floorNoise != null) ? ((int) floorNoise.getHeight(x, y) - floorNoiseOffset) : 0);
                    int actualRoofLevel = calculateLevel(roofMode, roofLevel, terrainHeight, roofMin, roofMax, minZ, maxZ, (roofNoise != null) ? ((int) roofNoise.getHeight(x, y) - roofNoiseOffset) : 0);
                    if (actualRoofLevel <= actualFloorLevel) {
                        continue;
                    }
                    final float distanceToWall = dimension.getDistanceToEdge(layer, x, y, maxWallDepth) - 1;
                    final int floorLedgeHeight = calculateLedgeHeight(floorWallDepth, distanceToWall);
                    final int roofLedgeHeight = calculateLedgeHeight(roofWallDepth, distanceToWall);
                    actualFloorLevel += floorLedgeHeight;
                    actualRoofLevel -= roofLedgeHeight;
                    if ((actualRoofLevel <= actualFloorLevel) || (actualFloorLevel == 0)) {
                        continue;
                    }
                    final int z = actualFloorLevel + 1;
                    final Point3i location = new Point3i(x, y, z);
                    for (int i = 0; i < floorExporters.length; i++) {
                        if ((z >= floorLayerSettings[i].getMinLevel()) && (z <= floorLayerSettings[i].getMaxLevel())) {
                            final int intensity = floorLayerNoise[i] != null ? MathUtils.clamp(0, (int) (floorLayerSettings[i].getIntensity() + floorLayerNoise[i].getValue(x, y, z) + 0.5f), 100) : floorLayerSettings[i].getIntensity();
                            if (intensity > 0) {
                                Fixup fixup = floorExporters[i].apply(floorDimension, location, intensity, exportedArea, world);
                                if (fixup != null) {
                                    fixups.add(fixup);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return fixups.isEmpty() ? null : fixups;
}
Also used : ArrayList(java.util.ArrayList) Layer(org.pepsoft.worldpainter.layers.Layer) Point3i(javax.vecmath.Point3i) NoiseHeightMap(org.pepsoft.worldpainter.heightMaps.NoiseHeightMap) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial)

Example 22 with Layer

use of org.pepsoft.worldpainter.layers.Layer in project WorldPainter by Captain-Chaos.

the class AbstractWorldExporter method parallelExportRegions.

protected final ChunkFactory.Stats parallelExportRegions(Dimension dimension, Platform platform, File worldDir, ProgressReceiver progressReceiver) throws OperationCancelled {
    if (progressReceiver != null) {
        progressReceiver.setMessage("Exporting " + dimension.getName() + " dimension");
    }
    long start = System.currentTimeMillis();
    final Dimension ceiling;
    switch(dimension.getDim()) {
        case DIM_NORMAL:
            ceiling = dimension.getWorld().getDimension(DIM_NORMAL_CEILING);
            break;
        case DIM_NETHER:
            ceiling = dimension.getWorld().getDimension(DIM_NETHER_CEILING);
            break;
        case DIM_END:
            ceiling = dimension.getWorld().getDimension(DIM_END_CEILING);
            break;
        default:
            throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported");
    }
    final ChunkFactory.Stats collectedStats = new ChunkFactory.Stats();
    boolean wasDirty = dimension.isDirty(), ceilingWasDirty = (ceiling != null) && ceiling.isDirty();
    dimension.rememberChanges();
    if (ceiling != null) {
        ceiling.rememberChanges();
    }
    try {
        final Map<Layer, LayerExporter> exporters = setupDimensionForExport(dimension);
        final Map<Layer, LayerExporter> ceilingExporters = (ceiling != null) ? setupDimensionForExport(ceiling) : null;
        // Determine regions to export
        int lowestRegionX = Integer.MAX_VALUE, highestRegionX = Integer.MIN_VALUE, lowestRegionZ = Integer.MAX_VALUE, highestRegionZ = Integer.MIN_VALUE;
        final Set<Point> regions = new HashSet<>(), exportedRegions = new HashSet<>();
        final boolean tileSelection = selectedTiles != null;
        if (tileSelection) {
            // Sanity check
            assert selectedDimensions.size() == 1;
            assert selectedDimensions.contains(dimension.getDim());
            for (Point tile : selectedTiles) {
                int regionX = tile.x >> 2;
                int regionZ = tile.y >> 2;
                regions.add(new Point(regionX, regionZ));
                if (regionX < lowestRegionX) {
                    lowestRegionX = regionX;
                }
                if (regionX > highestRegionX) {
                    highestRegionX = regionX;
                }
                if (regionZ < lowestRegionZ) {
                    lowestRegionZ = regionZ;
                }
                if (regionZ > highestRegionZ) {
                    highestRegionZ = regionZ;
                }
            }
        } else {
            for (Tile tile : dimension.getTiles()) {
                // Also add regions for any bedrock wall and/or border
                // tiles, if present
                int r = (((dimension.getBorder() != null) && (!dimension.getBorder().isEndless())) ? dimension.getBorderSize() : 0) + (((dimension.getBorder() == null) || (!dimension.getBorder().isEndless())) && dimension.isBedrockWall() ? 1 : 0);
                for (int dx = -r; dx <= r; dx++) {
                    for (int dy = -r; dy <= r; dy++) {
                        int regionX = (tile.getX() + dx) >> 2;
                        int regionZ = (tile.getY() + dy) >> 2;
                        regions.add(new Point(regionX, regionZ));
                        if (regionX < lowestRegionX) {
                            lowestRegionX = regionX;
                        }
                        if (regionX > highestRegionX) {
                            highestRegionX = regionX;
                        }
                        if (regionZ < lowestRegionZ) {
                            lowestRegionZ = regionZ;
                        }
                        if (regionZ > highestRegionZ) {
                            highestRegionZ = regionZ;
                        }
                    }
                }
            }
            if (ceiling != null) {
                for (Tile tile : ceiling.getTiles()) {
                    int regionX = tile.getX() >> 2;
                    int regionZ = tile.getY() >> 2;
                    regions.add(new Point(regionX, regionZ));
                    if (regionX < lowestRegionX) {
                        lowestRegionX = regionX;
                    }
                    if (regionX > highestRegionX) {
                        highestRegionX = regionX;
                    }
                    if (regionZ < lowestRegionZ) {
                        lowestRegionZ = regionZ;
                    }
                    if (regionZ > highestRegionZ) {
                        highestRegionZ = regionZ;
                    }
                }
            }
        }
        // Sort the regions to export the first two rows together, and then
        // row by row, to get the optimum tempo of performing fixups
        java.util.List<Point> sortedRegions = new ArrayList<>(regions.size());
        if (lowestRegionZ == highestRegionZ) {
            // No point in sorting it
            sortedRegions.addAll(regions);
        } else {
            for (int x = lowestRegionX; x <= highestRegionX; x++) {
                for (int z = lowestRegionZ; z <= (lowestRegionZ + 1); z++) {
                    Point regionCoords = new Point(x, z);
                    if (regions.contains(regionCoords)) {
                        sortedRegions.add(regionCoords);
                    }
                }
            }
            for (int z = lowestRegionZ + 2; z <= highestRegionZ; z++) {
                for (int x = lowestRegionX; x <= highestRegionX; x++) {
                    Point regionCoords = new Point(x, z);
                    if (regions.contains(regionCoords)) {
                        sortedRegions.add(regionCoords);
                    }
                }
            }
        }
        final WorldPainterChunkFactory chunkFactory = new WorldPainterChunkFactory(dimension, exporters, platform, world.getMaxHeight());
        final WorldPainterChunkFactory ceilingChunkFactory = (ceiling != null) ? new WorldPainterChunkFactory(ceiling, ceilingExporters, platform, world.getMaxHeight()) : null;
        Runtime runtime = Runtime.getRuntime();
        runtime.gc();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long memoryInUse = totalMemory - freeMemory;
        long maxMemory = runtime.maxMemory();
        long maxMemoryAvailable = maxMemory - memoryInUse;
        int maxThreadsByMem = (int) (maxMemoryAvailable / 250000000L);
        int threads;
        if (System.getProperty("org.pepsoft.worldpainter.threads") != null) {
            threads = Math.max(Math.min(Integer.parseInt(System.getProperty("org.pepsoft.worldpainter.threads")), sortedRegions.size()), 1);
        } else {
            threads = Math.max(Math.min(Math.min(maxThreadsByMem, runtime.availableProcessors()), sortedRegions.size()), 1);
        }
        logger.info("Using " + threads + " thread(s) for export (cores: " + runtime.availableProcessors() + ", available memory: " + (maxMemoryAvailable / 1048576L) + " MB)");
        final Map<Point, List<Fixup>> fixups = new HashMap<>();
        ExecutorService executor = Executors.newFixedThreadPool(threads, new ThreadFactory() {

            @Override
            public synchronized Thread newThread(Runnable r) {
                Thread thread = new Thread(threadGroup, r, "Exporter-" + nextID++);
                thread.setPriority(Thread.MIN_PRIORITY);
                return thread;
            }

            private final ThreadGroup threadGroup = new ThreadGroup("Exporters");

            private int nextID = 1;
        });
        final ParallelProgressManager parallelProgressManager = (progressReceiver != null) ? new ParallelProgressManager(progressReceiver, regions.size()) : null;
        try {
            // Export each individual region
            for (Point region : sortedRegions) {
                final Point regionCoords = region;
                executor.execute(() -> {
                    ProgressReceiver progressReceiver1 = (parallelProgressManager != null) ? parallelProgressManager.createProgressReceiver() : null;
                    if (progressReceiver1 != null) {
                        try {
                            progressReceiver1.checkForCancellation();
                        } catch (OperationCancelled e) {
                            return;
                        }
                    }
                    try {
                        WorldRegion worldRegion = new WorldRegion(regionCoords.x, regionCoords.y, dimension.getMaxHeight(), platform);
                        ExportResults exportResults = null;
                        try {
                            exportResults = exportRegion(worldRegion, dimension, ceiling, platform, regionCoords, tileSelection, exporters, ceilingExporters, chunkFactory, ceilingChunkFactory, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.0f, 0.9f) : null);
                            if (logger.isDebugEnabled()) {
                                logger.debug("Generated region " + regionCoords.x + "," + regionCoords.y);
                            }
                            if (exportResults.chunksGenerated) {
                                synchronized (collectedStats) {
                                    collectedStats.landArea += exportResults.stats.landArea;
                                    collectedStats.surfaceArea += exportResults.stats.surfaceArea;
                                    collectedStats.waterArea += exportResults.stats.waterArea;
                                }
                            }
                        } finally {
                            if ((exportResults != null) && exportResults.chunksGenerated) {
                                long saveStart = System.currentTimeMillis();
                                worldRegion.save(worldDir, dimension.getDim());
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Saving region took {} ms", System.currentTimeMillis() - saveStart);
                                }
                            }
                        }
                        synchronized (fixups) {
                            if ((exportResults.fixups != null) && (!exportResults.fixups.isEmpty())) {
                                fixups.put(new Point(regionCoords.x, regionCoords.y), exportResults.fixups);
                            }
                            exportedRegions.add(regionCoords);
                        }
                        // thread is not already doing it
                        if (performingFixups.tryAcquire()) {
                            try {
                                Map<Point, List<Fixup>> myFixups = new HashMap<>();
                                synchronized (fixups) {
                                    for (Iterator<Map.Entry<Point, List<Fixup>>> i = fixups.entrySet().iterator(); i.hasNext(); ) {
                                        Map.Entry<Point, List<Fixup>> entry = i.next();
                                        Point fixupRegionCoords = entry.getKey();
                                        if (isReadyForFixups(regions, exportedRegions, fixupRegionCoords)) {
                                            myFixups.put(fixupRegionCoords, entry.getValue());
                                            i.remove();
                                        }
                                    }
                                }
                                if (!myFixups.isEmpty()) {
                                    performFixups(worldDir, dimension, platform, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.9f, 0.1f) : null, myFixups);
                                }
                            } finally {
                                performingFixups.release();
                            }
                        }
                    } catch (Throwable t) {
                        if (progressReceiver1 != null) {
                            progressReceiver1.exceptionThrown(t);
                        } else {
                            logger.error("Exception while exporting region", t);
                        }
                    }
                });
            }
        } finally {
            executor.shutdown();
            try {
                executor.awaitTermination(366, TimeUnit.DAYS);
            } catch (InterruptedException e) {
                throw new RuntimeException("Thread interrupted while waiting for all tasks to finish", e);
            }
        }
        // performing fixups and thread B added new ones and then quit
        synchronized (fixups) {
            if (!fixups.isEmpty()) {
                if (progressReceiver != null) {
                    progressReceiver.setMessage("Doing remaining fixups for " + dimension.getName());
                    progressReceiver.reset();
                }
                performFixups(worldDir, dimension, platform, progressReceiver, fixups);
            }
        }
        // Calculate total size of dimension
        collectedStats.time = System.currentTimeMillis() - start;
        if (progressReceiver != null) {
            progressReceiver.setProgress(1.0f);
        }
    } finally {
        // Undo any changes we made (such as applying any combined layers)
        if (dimension.undoChanges()) {
            // TODO: some kind of cleverer undo mechanism (undo history
            // cloning?) so we don't mess up the user's redo history
            dimension.clearRedo();
            dimension.armSavePoint();
        }
        // If the dimension wasn't dirty make sure it still isn't
        dimension.setDirty(wasDirty);
        if (ceiling != null) {
            // Undo any changes we made (such as applying any combined layers)
            if (ceiling.undoChanges()) {
                // TODO: some kind of cleverer undo mechanism (undo history
                // cloning?) so we don't mess up the user's redo history
                ceiling.clearRedo();
                ceiling.armSavePoint();
            }
            // If the dimension wasn't dirty make sure it still isn't
            ceiling.setDirty(ceilingWasDirty);
        }
    }
    return collectedStats;
}
Also used : List(java.util.List) OperationCancelled(org.pepsoft.util.ProgressReceiver.OperationCancelled) Tile(org.pepsoft.worldpainter.Tile) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) Dimension(org.pepsoft.worldpainter.Dimension) CustomLayer(org.pepsoft.worldpainter.layers.CustomLayer) CombinedLayer(org.pepsoft.worldpainter.layers.CombinedLayer) Layer(org.pepsoft.worldpainter.layers.Layer) java.util(java.util) ParallelProgressManager(org.pepsoft.util.ParallelProgressManager) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) ProgressReceiver(org.pepsoft.util.ProgressReceiver)

Example 23 with Layer

use of org.pepsoft.worldpainter.layers.Layer in project WorldPainter by Captain-Chaos.

the class AbstractWorldExporter method exportRegion.

protected final ExportResults exportRegion(MinecraftWorld minecraftWorld, Dimension dimension, Dimension ceiling, Platform platform, Point regionCoords, boolean tileSelection, Map<Layer, LayerExporter> exporters, Map<Layer, LayerExporter> ceilingExporters, ChunkFactory chunkFactory, ChunkFactory ceilingChunkFactory, ProgressReceiver progressReceiver) throws OperationCancelled, IOException {
    if (progressReceiver != null) {
        progressReceiver.setMessage("Exporting region " + regionCoords.x + "," + regionCoords.y + " of " + dimension.getName());
    }
    int lowestTileX = (regionCoords.x << 2) - 1;
    int highestTileX = lowestTileX + 5;
    int lowestTileY = (regionCoords.y << 2) - 1;
    int highestTileY = lowestTileY + 5;
    Map<Point, Tile> tiles = new HashMap<>(), ceilingTiles = new HashMap<>();
    for (int tileX = lowestTileX; tileX <= highestTileX; tileX++) {
        for (int tileY = lowestTileY; tileY <= highestTileY; tileY++) {
            Point tileCoords = new Point(tileX, tileY);
            Tile tile = dimension.getTile(tileCoords);
            if ((tile != null) && ((!tileSelection) || dimension.getWorld().getTilesToExport().contains(tileCoords))) {
                tiles.put(tileCoords, tile);
            }
            if (ceiling != null) {
                tile = ceiling.getTile(tileCoords);
                if ((tile != null) && ((!tileSelection) || dimension.getWorld().getTilesToExport().contains(tileCoords))) {
                    ceilingTiles.put(tileCoords, tile);
                }
            }
        }
    }
    Set<Layer> allLayers = new HashSet<>(), allCeilingLayers = new HashSet<>();
    for (Tile tile : tiles.values()) {
        allLayers.addAll(tile.getLayers());
    }
    // Add layers that have been configured to be applied everywhere
    Set<Layer> minimumLayers = dimension.getMinimumLayers(), ceilingMinimumLayers = (ceiling != null) ? ceiling.getMinimumLayers() : null;
    allLayers.addAll(minimumLayers);
    // Remove layers which have been excluded for export
    allLayers.removeIf(layer -> (layer instanceof CustomLayer) && (!((CustomLayer) layer).isExport()));
    List<Layer> secondaryPassLayers = new ArrayList<>(), ceilingSecondaryPassLayers = new ArrayList<>();
    for (Layer layer : allLayers) {
        LayerExporter exporter = layer.getExporter();
        if (exporter instanceof SecondPassLayerExporter) {
            secondaryPassLayers.add(layer);
        }
    }
    Collections.sort(secondaryPassLayers);
    // Set up export of ceiling
    if (ceiling != null) {
        for (Tile tile : ceilingTiles.values()) {
            allCeilingLayers.addAll(tile.getLayers());
        }
        allCeilingLayers.addAll(ceilingMinimumLayers);
        // Remove layers which have been excluded for export
        allCeilingLayers.removeIf(layer -> (layer instanceof CustomLayer) && (!((CustomLayer) layer).isExport()));
        for (Layer layer : allCeilingLayers) {
            LayerExporter exporter = layer.getExporter();
            if (exporter instanceof SecondPassLayerExporter) {
                ceilingSecondaryPassLayers.add(layer);
            }
        }
        Collections.sort(ceilingSecondaryPassLayers);
    }
    long t1 = System.currentTimeMillis();
    // First pass. Create terrain and apply layers which don't need access
    // to neighbouring chunks
    ExportResults exportResults = firstPass(minecraftWorld, dimension, regionCoords, tiles, tileSelection, exporters, chunkFactory, false, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.0f, ((ceiling != null) ? 0.225f : 0.45f)) : null);
    ExportResults ceilingExportResults = null;
    if (ceiling != null) {
        // First pass for the ceiling. Create terrain and apply layers which
        // don't need access to neighbouring chunks
        ceilingExportResults = firstPass(minecraftWorld, ceiling, regionCoords, ceilingTiles, tileSelection, ceilingExporters, ceilingChunkFactory, true, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.225f, 0.225f) : null);
    }
    if (exportResults.chunksGenerated || ((ceiling != null) && ceilingExportResults.chunksGenerated)) {
        // Second pass. Apply layers which need information from or apply
        // changes to neighbouring chunks
        long t2 = System.currentTimeMillis();
        List<Fixup> myFixups = secondPass(secondaryPassLayers, dimension, minecraftWorld, exporters, tiles.values(), regionCoords, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.45f, (ceiling != null) ? 0.05f : 0.1f) : null);
        if ((myFixups != null) && (!myFixups.isEmpty())) {
            exportResults.fixups = myFixups;
        }
        if (ceiling != null) {
            // Second pass for ceiling. Apply layers which need information
            // from or apply changes to neighbouring chunks. Fixups are not
            // supported for the ceiling for now. TODO: implement
            secondPass(ceilingSecondaryPassLayers, ceiling, new InvertedWorld(minecraftWorld, ceiling.getMaxHeight() - ceiling.getCeilingHeight()), ceilingExporters, ceilingTiles.values(), regionCoords, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.4f, 0.05f) : null);
        }
        // Post processing. Fix covered grass blocks, things like that
        long t3 = System.currentTimeMillis();
        PlatformManager.getInstance().getPostProcessor(platform).postProcess(minecraftWorld, new Rectangle(regionCoords.x << 9, regionCoords.y << 9, 512, 512), (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.55f, 0.1f) : null);
        // Third pass. Calculate lighting
        long t4 = System.currentTimeMillis();
        lightingPass(minecraftWorld, regionCoords, (progressReceiver != null) ? new SubProgressReceiver(progressReceiver, 0.65f, 0.35f) : null);
        long t5 = System.currentTimeMillis();
        if ("true".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.devMode"))) {
            String timingMessage = (t2 - t1) + ", " + (t3 - t2) + ", " + (t4 - t3) + ", " + (t5 - t4) + ", " + (t5 - t1);
            // System.out.println("Export timing: " + timingMessage);
            synchronized (TIMING_FILE_LOCK) {
                try (PrintWriter out = new PrintWriter(new FileOutputStream("exporttimings.csv", true))) {
                    out.println(timingMessage);
                }
            }
        }
    }
    return exportResults;
}
Also used : CustomLayer(org.pepsoft.worldpainter.layers.CustomLayer) Tile(org.pepsoft.worldpainter.Tile) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) CustomLayer(org.pepsoft.worldpainter.layers.CustomLayer) CombinedLayer(org.pepsoft.worldpainter.layers.CombinedLayer) Layer(org.pepsoft.worldpainter.layers.Layer) FileOutputStream(java.io.FileOutputStream) PrintWriter(java.io.PrintWriter)

Example 24 with Layer

use of org.pepsoft.worldpainter.layers.Layer in project WorldPainter by Captain-Chaos.

the class BorderChunkFactory method create.

public static ChunkFactory.ChunkCreationResult create(int chunkX, int chunkZ, Dimension dimension, Map<Layer, LayerExporter> exporters) {
    final int maxHeight = dimension.getMaxHeight();
    final Platform platform = dimension.getWorld().getPlatform();
    final Border border = dimension.getBorder();
    final int borderLevel = dimension.getBorderLevel();
    final boolean dark = dimension.isDarkLevel();
    final boolean bottomless = dimension.isBottomless();
    final Terrain subsurfaceMaterial = dimension.getSubsurfaceMaterial();
    final PerlinNoise noiseGenerator;
    if (noiseGenerators.get() == null) {
        noiseGenerator = new PerlinNoise(0);
        noiseGenerators.set(noiseGenerator);
    } else {
        noiseGenerator = noiseGenerators.get();
    }
    final long seed = dimension.getSeed();
    if (noiseGenerator.getSeed() != seed) {
        noiseGenerator.setSeed(seed);
    }
    final int floor = Math.max(borderLevel - 20, 0);
    final int variation = Math.min(15, (borderLevel - floor) / 2);
    final ChunkFactory.ChunkCreationResult result = new ChunkFactory.ChunkCreationResult();
    result.chunk = PlatformManager.getInstance().createChunk(platform, chunkX, chunkZ, maxHeight);
    final int maxY = maxHeight - 1;
    if (platform.capabilities.contains(BIOMES)) {
        switch(border) {
            case VOID:
            case LAVA:
                for (int x = 0; x < 16; x++) {
                    for (int z = 0; z < 16; z++) {
                        result.chunk.setBiome(x, z, BIOME_PLAINS);
                    }
                }
                break;
            case WATER:
                for (int x = 0; x < 16; x++) {
                    for (int z = 0; z < 16; z++) {
                        result.chunk.setBiome(x, z, BIOME_OCEAN);
                    }
                }
                break;
            default:
                throw new InternalError();
        }
    }
    for (int x = 0; x < 16; x++) {
        for (int z = 0; z < 16; z++) {
            if (border != Border.VOID) {
                final int worldX = (chunkX << 4) | x, worldZ = (chunkZ << 4) | z;
                final int floorLevel = (int) (floor + (noiseGenerator.getPerlinNoise(worldX / MEDIUM_BLOBS, worldZ / MEDIUM_BLOBS) + 0.5f) * variation + 0.5f);
                final int surfaceLayerLevel = floorLevel - dimension.getTopLayerDepth(worldX, worldZ, floorLevel);
                for (int y = 0; y <= maxY; y++) {
                    if ((y == 0) && (!bottomless)) {
                        result.chunk.setBlockType(x, y, z, BLK_BEDROCK);
                    } else if (y <= surfaceLayerLevel) {
                        result.chunk.setMaterial(x, y, z, subsurfaceMaterial.getMaterial(seed, worldX, worldZ, y, floorLevel));
                    } else if (y <= floorLevel) {
                        result.chunk.setMaterial(x, y, z, BEACHES.getMaterial(seed, worldX, worldZ, y, floorLevel));
                    } else if (y <= borderLevel) {
                        switch(border) {
                            case WATER:
                                result.chunk.setBlockType(x, y, z, BLK_STATIONARY_WATER);
                                break;
                            case LAVA:
                                result.chunk.setBlockType(x, y, z, BLK_STATIONARY_LAVA);
                                break;
                            default:
                        }
                    }
                }
            }
            if (dark) {
                result.chunk.setBlockType(x, maxY, z, BLK_BEDROCK);
                result.chunk.setHeight(x, z, maxY);
            } else if (border == Border.VOID) {
                result.chunk.setHeight(x, z, 0);
            } else {
                result.chunk.setHeight(x, z, (borderLevel < maxY) ? (borderLevel + 1) : maxY);
            }
        }
    }
    if (border != Border.VOID) {
        // Apply layers set to be applied everywhere, if any
        final Set<Layer> minimumLayers = dimension.getMinimumLayers();
        if (!minimumLayers.isEmpty()) {
            Tile virtualTile = new Tile(chunkX >> 3, chunkZ >> 3, dimension.getMaxHeight()) {

                @Override
                public synchronized float getHeight(int x, int y) {
                    return floor + (noiseGenerator.getPerlinNoise(((getX() << TILE_SIZE_BITS) | x) / MEDIUM_BLOBS, ((getY() << TILE_SIZE_BITS) | y) / MEDIUM_BLOBS) + 0.5f) * variation;
                }

                @Override
                public synchronized int getWaterLevel(int x, int y) {
                    return borderLevel;
                }

                private static final long serialVersionUID = 1L;
            };
            for (Layer layer : minimumLayers) {
                LayerExporter layerExporter = exporters.get(layer);
                if (layerExporter instanceof FirstPassLayerExporter) {
                    ((FirstPassLayerExporter) layerExporter).render(dimension, virtualTile, result.chunk);
                }
            }
        }
    }
    result.chunk.setTerrainPopulated(true);
    result.stats.surfaceArea = 256;
    if ((border == Border.WATER) || (border == Border.LAVA)) {
        result.stats.waterArea = 256;
    }
    return result;
}
Also used : Platform(org.pepsoft.worldpainter.Platform) Tile(org.pepsoft.worldpainter.Tile) PerlinNoise(org.pepsoft.util.PerlinNoise) Layer(org.pepsoft.worldpainter.layers.Layer) Terrain(org.pepsoft.worldpainter.Terrain) Border(org.pepsoft.worldpainter.Dimension.Border) ChunkFactory(org.pepsoft.minecraft.ChunkFactory)

Example 25 with Layer

use of org.pepsoft.worldpainter.layers.Layer in project WorldPainter by Captain-Chaos.

the class RecoverWorld method main.

public static void main(String[] args) throws IOException, ClassNotFoundException {
    int defaultMaxHeight = Integer.parseInt(args[1]);
    // Load or initialise configuration
    Configuration config;
    try {
        // This will migrate the configuration directory if necessary
        config = Configuration.load();
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
    if (config == null) {
        if (!logger.isDebugEnabled()) {
            // If debug logging is on, the Configuration constructor will
            // already log this
            logger.info("Creating new configuration");
        }
        config = new Configuration();
    }
    Configuration.setInstance(config);
    logger.info("Installation ID: " + config.getUuid());
    // Load and install trusted WorldPainter root certificate
    X509Certificate trustedCert = null;
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        trustedCert = (X509Certificate) certificateFactory.generateCertificate(RecoverWorld.class.getResourceAsStream("/wproot.pem"));
    } catch (CertificateException e) {
        logger.error("Certificate exception while loading trusted root certificate", e);
    }
    // Load the plugins
    if (trustedCert != null) {
        PluginManager.loadPlugins(new File(Configuration.getConfigDir(), "plugins"), trustedCert.getPublicKey());
    } else {
        logger.error("Trusted root certificate not available; not loading plugins");
    }
    WPPluginManager.initialise(config.getUuid());
    // Read as much data as possible. Use a trick via InstanceKeeper to get
    // hold of the objects as they are created during deserialisation, even
    // if the readObject() method throws an exception and never returns an
    // instance
    final List<World2> worlds = new ArrayList<>();
    final Map<Dimension, List<Tile>> tiles = new HashMap<>();
    @SuppressWarnings("unchecked") final List<Tile>[] tileListHolder = new List[1];
    InstanceKeeper.setInstantiationListener(World2.class, worlds::add);
    InstanceKeeper.setInstantiationListener(Dimension.class, dimension -> {
        List<Tile> tileList = new ArrayList<>();
        tiles.put(dimension, tileList);
        tileListHolder[0] = tileList;
    });
    InstanceKeeper.setInstantiationListener(Tile.class, tile -> tileListHolder[0].add(tile));
    File file = new File(args[0]);
    try {
        try (WPCustomObjectInputStream wrappedIn = new WPCustomObjectInputStream(new GZIPInputStream(new FileInputStream(file)), PluginManager.getPluginClassLoader(), AbstractObject.class)) {
            Map<String, Object> metadata = null;
            World2 world;
            Object object = wrappedIn.readObject();
            if (object instanceof Map) {
                metadata = (Map<String, Object>) object;
                object = wrappedIn.readObject();
            }
            if (object instanceof World2) {
                world = (World2) object;
                if (metadata != null) {
                    world.setMetadata(metadata);
                }
            } else if (object instanceof World) {
                throw new RuntimeException("Old worlds (pre-0.2) not supported");
            } else {
                throw new RuntimeException("Object of unexpected type " + object.getClass() + " encountered");
            }
        }
    } catch (IOException e) {
        System.err.println("Warning: I/O error while reading world; world most likely corrupted! (Type: " + e.getClass().getSimpleName() + ", message: " + e.getMessage() + ")");
    } catch (ClassNotFoundException e) {
        System.err.println("Warning: class not found while reading world; world most likely corrupted! (Type: " + e.getClass().getSimpleName() + ", message: " + e.getMessage() + ")");
    }
    // Reconstitute as much of the data as possible
    System.out.println(worlds.size() + " worlds read");
    System.out.println(tiles.size() + " dimensions read");
    World2 newWorld = null;
    for (Map.Entry<Dimension, List<Tile>> entry : tiles.entrySet()) {
        Dimension dimension = entry.getKey();
        List<Tile> tileList = entry.getValue();
        System.out.println(tileList.size() + " tiles read for dimension " + dimension.getName());
        int maxHeight;
        if (dimension.getMaxHeight() != 0) {
            maxHeight = dimension.getMaxHeight();
        } else {
            maxHeight = defaultMaxHeight;
        }
        if (newWorld == null) {
            if (worlds.size() > 0) {
                World2 world = worlds.get(0);
                if (world.getPlatform() != null) {
                    newWorld = new World2(world.getPlatform(), maxHeight);
                } else if (maxHeight == DEFAULT_MAX_HEIGHT_2) {
                    newWorld = new World2(JAVA_ANVIL, maxHeight);
                } else {
                    newWorld = new World2(JAVA_MCREGION, maxHeight);
                }
                if (world.getName() != null) {
                    newWorld.setName(worlds.get(0).getName() + " (recovered)");
                }
                newWorld.setCreateGoodiesChest(world.isCreateGoodiesChest());
                try {
                    for (int i = 0; i < Terrain.CUSTOM_TERRAIN_COUNT; i++) {
                        newWorld.setMixedMaterial(i, world.getMixedMaterial(i));
                    }
                } catch (NullPointerException e) {
                    System.err.println("Custom material settings lost");
                }
                newWorld.setGameType(world.getGameType());
                if (world.getGenerator() != null) {
                    newWorld.setGenerator(world.getGenerator());
                } else {
                    System.err.println("Landscape generator setting lost");
                }
                newWorld.setImportedFrom(world.getImportedFrom());
                newWorld.setMapFeatures(world.isMapFeatures());
                if (world.getSpawnPoint() != null) {
                    newWorld.setSpawnPoint(world.getSpawnPoint());
                } else {
                    System.err.println("Spawn point setting lost; resetting to 0,0");
                }
                if (world.getUpIs() != null) {
                    newWorld.setUpIs(world.getUpIs());
                } else {
                    System.err.println("North direction setting lost; resetting to north is up");
                }
            } else {
                System.err.println("No world recovered; all world settings lost");
                if (maxHeight == DEFAULT_MAX_HEIGHT_2) {
                    newWorld = new World2(JAVA_ANVIL, maxHeight);
                } else {
                    newWorld = new World2(JAVA_MCREGION, maxHeight);
                }
            }
            newWorld.addHistoryEntry(HistoryEntry.WORLD_RECOVERED);
            if (newWorld.getName() == null) {
                String worldName = file.getName();
                if (worldName.toLowerCase().endsWith(".world")) {
                    worldName = worldName.substring(0, worldName.length() - 6);
                }
                newWorld.setName(worldName + " (recovered)");
            }
        }
        TileFactory tileFactory = dimension.getTileFactory();
        if (tileFactory == null) {
            System.err.println("Dimension " + dimension.getName() + " tile factory lost; creating default tile factory");
            tileFactory = TileFactoryFactory.createNoiseTileFactory(dimension.getSeed(), Terrain.GRASS, maxHeight, 58, 62, false, true, 20, 1.0);
        }
        Dimension newDimension = new Dimension(dimension.getMinecraftSeed(), tileFactory, dimension.getDim(), maxHeight);
        try {
            for (Map.Entry<Layer, ExporterSettings> settingsEntry : dimension.getAllLayerSettings().entrySet()) {
                if (settingsEntry.getValue() != null) {
                    newDimension.setLayerSettings(settingsEntry.getKey(), settingsEntry.getValue());
                } else {
                    System.err.println("Layer settings for layer " + settingsEntry.getKey().getName() + " lost for dimension " + dimension.getName());
                }
            }
        } catch (NullPointerException e) {
            System.err.println("Layer settings lost for dimension " + dimension.getName());
        }
        newDimension.setBedrockWall(dimension.isBedrockWall());
        if ((dimension.getBorderLevel() > 0) && (dimension.getBorderSize() > 0)) {
            newDimension.setBorder(dimension.getBorder());
            newDimension.setBorderLevel(dimension.getBorderLevel());
            newDimension.setBorderSize(dimension.getBorderSize());
        } else {
            System.err.println("Border settings lost for dimension " + dimension.getName());
        }
        if (dimension.getContourSeparation() > 0) {
            newDimension.setContoursEnabled(dimension.isContoursEnabled());
            newDimension.setContourSeparation(dimension.getContourSeparation());
        } else {
            System.err.println("Contour settings lost for dimension " + dimension.getName());
        }
        newDimension.setDarkLevel(dimension.isDarkLevel());
        if (dimension.getGridSize() > 0) {
            newDimension.setGridEnabled(dimension.isGridEnabled());
            newDimension.setGridSize(dimension.getGridSize());
        } else {
            System.err.println("Grid settings lost for dimension " + dimension.getName());
        }
        newDimension.setMinecraftSeed(dimension.getMinecraftSeed());
        newDimension.setOverlay(dimension.getOverlay());
        newDimension.setOverlayEnabled(dimension.isOverlayEnabled());
        newDimension.setOverlayOffsetX(dimension.getOverlayOffsetX());
        newDimension.setOverlayOffsetY(dimension.getOverlayOffsetY());
        newDimension.setOverlayScale(dimension.getOverlayScale());
        newDimension.setOverlayTransparency(dimension.getOverlayTransparency());
        newDimension.setPopulate(dimension.isPopulate());
        if (dimension.getSubsurfaceMaterial() != null) {
            newDimension.setSubsurfaceMaterial(dimension.getSubsurfaceMaterial());
        } else {
            System.err.println("Sub surface material lost for dimension " + dimension.getName() + "; resetting to STONE_MIX");
            newDimension.setSubsurfaceMaterial(Terrain.STONE_MIX);
        }
        newWorld.addDimension(newDimension);
        for (Tile tile : tileList) {
            tile.repair(maxHeight, System.err);
            newDimension.addTile(tile);
        }
    }
    // Write to a new file
    String filename = file.getName();
    if (filename.toLowerCase().endsWith(".world")) {
        filename = filename.substring(0, filename.length() - 6);
    }
    filename = filename + ".recovered.world";
    WorldIO worldIO = new WorldIO(newWorld);
    File outFile = new File(file.getParentFile(), filename);
    try (OutputStream out = new FileOutputStream(outFile)) {
        worldIO.save(out);
    }
    System.out.println("Recovered world written to " + outFile);
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) CertificateException(java.security.cert.CertificateException) ExporterSettings(org.pepsoft.worldpainter.layers.exporters.ExporterSettings) CertificateFactory(java.security.cert.CertificateFactory) GZIPInputStream(java.util.zip.GZIPInputStream) ArrayList(java.util.ArrayList) List(java.util.List) WPCustomObjectInputStream(org.pepsoft.util.WPCustomObjectInputStream) Layer(org.pepsoft.worldpainter.layers.Layer) X509Certificate(java.security.cert.X509Certificate) AbstractObject(org.pepsoft.worldpainter.objects.AbstractObject) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

Layer (org.pepsoft.worldpainter.layers.Layer)34 CustomLayer (org.pepsoft.worldpainter.layers.CustomLayer)9 Map (java.util.Map)8 ProgressReceiver (org.pepsoft.util.ProgressReceiver)7 HashMap (java.util.HashMap)6 OperationCancelled (org.pepsoft.util.ProgressReceiver.OperationCancelled)5 ExporterSettings (org.pepsoft.worldpainter.layers.exporters.ExporterSettings)5 Point (java.awt.Point)4 ArrayList (java.util.ArrayList)4 List (java.util.List)4 SubProgressReceiver (org.pepsoft.util.SubProgressReceiver)4 TILE_SIZE (org.pepsoft.worldpainter.Constants.TILE_SIZE)4 Biome (org.pepsoft.worldpainter.layers.Biome)4 Bo2Layer (org.pepsoft.worldpainter.layers.Bo2Layer)4 CombinedLayer (org.pepsoft.worldpainter.layers.CombinedLayer)4 GroundCoverLayer (org.pepsoft.worldpainter.layers.groundcover.GroundCoverLayer)4 PlantLayer (org.pepsoft.worldpainter.layers.plants.PlantLayer)4 File (java.io.File)3 Arrays (java.util.Arrays)3 BitSet (java.util.BitSet)3