Search in sources :

Example 6 with ProgressReceiver

use of org.pepsoft.util.ProgressReceiver in project WorldPainter by Captain-Chaos.

the class AbstractWorldExporter method secondPass.

protected List<Fixup> secondPass(List<Layer> secondaryPassLayers, Dimension dimension, MinecraftWorld minecraftWorld, Map<Layer, LayerExporter> exporters, Collection<Tile> tiles, Point regionCoords, ProgressReceiver progressReceiver) throws OperationCancelled {
    // Apply other secondary pass layers
    if (logger.isDebugEnabled()) {
        logger.debug("Start of second pass for region {},{}", regionCoords.x, regionCoords.y);
    }
    int layerCount = secondaryPassLayers.size(), counter = 0;
    Rectangle area = new Rectangle((regionCoords.x << 9) - 16, (regionCoords.y << 9) - 16, 544, 544);
    Rectangle exportedArea = new Rectangle((regionCoords.x << 9), (regionCoords.y << 9), 512, 512);
    List<Fixup> fixups = new ArrayList<>();
    // boolean frost = false;
    for (Layer layer : secondaryPassLayers) {
        // if (layer instanceof Frost) {
        // frost = true;
        // continue;
        // }
        @SuppressWarnings("unchecked") SecondPassLayerExporter exporter = (SecondPassLayerExporter) exporters.get(layer);
        if (logger.isDebugEnabled()) {
            logger.debug("Exporting layer {} for region {},{}", layer, regionCoords.x, regionCoords.y);
        }
        if (progressReceiver != null) {
            if (minecraftWorld instanceof InvertedWorld) {
                progressReceiver.setMessage("Exporting layer " + layer + " for ceiling");
            } else {
                progressReceiver.setMessage("Exporting layer " + layer);
            }
        }
        List<Fixup> layerFixups = exporter.render(dimension, area, exportedArea, minecraftWorld);
        if (layerFixups != null) {
            fixups.addAll(layerFixups);
        }
        if (progressReceiver != null) {
            counter++;
            progressReceiver.setProgress((float) counter / layerCount);
        }
    }
    // Garden / seeds first and second pass
    GardenExporter gardenExporter = new GardenExporter();
    Set<Seed> firstPassProcessedSeeds = new HashSet<>();
    Set<Seed> secondPassProcessedSeeds = new HashSet<>();
    tiles.stream().filter(tile -> tile.getLayers().contains(GardenCategory.INSTANCE)).forEach(tile -> {
        gardenExporter.firstPass(dimension, tile, minecraftWorld, firstPassProcessedSeeds);
        gardenExporter.secondPass(dimension, tile, minecraftWorld, secondPassProcessedSeeds);
    });
    // elegant
    if ((dimension.getDim() == 0) && world.isCreateGoodiesChest()) {
        Point goodiesPoint = (Point) world.getSpawnPoint().clone();
        goodiesPoint.translate(3, 3);
        int height = Math.min(dimension.getIntHeightAt(goodiesPoint) + 1, dimension.getMaxHeight() - 1);
        minecraftWorld.setMaterialAt(goodiesPoint.x, goodiesPoint.y, height, Material.CHEST_NORTH);
        Chunk chunk = minecraftWorld.getChunk(goodiesPoint.x >> 4, goodiesPoint.y >> 4);
        if ((chunk != null) && (chunk.getTileEntities() != null)) {
            Chest goodiesChest = createGoodiesChest();
            goodiesChest.setX(goodiesPoint.x);
            goodiesChest.setY(height);
            goodiesChest.setZ(goodiesPoint.y);
            chunk.getTileEntities().add(goodiesChest);
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("End of second pass for region {},{}", regionCoords.x, regionCoords.y);
    }
    return fixups;
}
Also used : java.util(java.util) org.pepsoft.minecraft(org.pepsoft.minecraft) BLOCKS(org.pepsoft.minecraft.Block.BLOCKS) EventVO(org.pepsoft.worldpainter.vo.EventVO) LoggerFactory(org.slf4j.LoggerFactory) ParallelProgressManager(org.pepsoft.util.ParallelProgressManager) PlatformProvider(org.pepsoft.worldpainter.plugins.PlatformProvider) SimpleDateFormat(java.text.SimpleDateFormat) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) CustomLayer(org.pepsoft.worldpainter.layers.CustomLayer) Platform(org.pepsoft.worldpainter.Platform) PlatformManager(org.pepsoft.worldpainter.plugins.PlatformManager) CombinedLayer(org.pepsoft.worldpainter.layers.CombinedLayer) DateFormat(java.text.DateFormat) PrintWriter(java.io.PrintWriter) Constants(org.pepsoft.worldpainter.Constants) Box(org.pepsoft.util.Box) AttributeKeyVO(org.pepsoft.worldpainter.vo.AttributeKeyVO) Logger(org.slf4j.Logger) Seed(org.pepsoft.worldpainter.gardenofeden.Seed) java.util.concurrent(java.util.concurrent) GardenExporter(org.pepsoft.worldpainter.gardenofeden.GardenExporter) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) GardenCategory(org.pepsoft.worldpainter.layers.GardenCategory) File(java.io.File) Layer(org.pepsoft.worldpainter.layers.Layer) Dimension(org.pepsoft.worldpainter.Dimension) java.awt(java.awt) List(java.util.List) Constants(org.pepsoft.minecraft.Constants) ProgressReceiver(org.pepsoft.util.ProgressReceiver) OperationCancelled(org.pepsoft.util.ProgressReceiver.OperationCancelled) Tile(org.pepsoft.worldpainter.Tile) World2(org.pepsoft.worldpainter.World2) NotNull(org.jetbrains.annotations.NotNull) CustomLayer(org.pepsoft.worldpainter.layers.CustomLayer) CombinedLayer(org.pepsoft.worldpainter.layers.CombinedLayer) Layer(org.pepsoft.worldpainter.layers.Layer) Seed(org.pepsoft.worldpainter.gardenofeden.Seed) GardenExporter(org.pepsoft.worldpainter.gardenofeden.GardenExporter)

Example 7 with ProgressReceiver

use of org.pepsoft.util.ProgressReceiver in project WorldPainter by Captain-Chaos.

the class MultiProgressComponent method subProgressStarted.

@Override
public synchronized void subProgressStarted(SubProgressReceiver subProgressReceiver) throws OperationCancelled {
    checkForCancellation();
    doOnEventThread(() -> {
        synchronized (MultiProgressComponent.this) {
            ProgressViewer progressViewer = new ProgressViewer(subProgressReceiver);
            JPanel progressPanel = null;
            ProgressReceiver parent = subProgressReceiver.getParent();
            if (parent == null) {
                // No parent; insert at start
                scrollablePanel1.add(progressViewer, 0);
                progressPanel = progressViewer;
            } else {
                boolean parentFound = false;
                do {
                    for (int i = 0; i < scrollablePanel1.getComponentCount(); i++) {
                        Component component = scrollablePanel1.getComponent(i);
                        ProgressViewer parentViewer;
                        try {
                            parentViewer = (ProgressViewer) ((component instanceof ProgressViewer) ? component : ((JPanel) component).getComponent(1));
                        } catch (ArrayIndexOutOfBoundsException e) {
                            System.out.println("Component " + i + " is a " + component.getClass());
                            throw e;
                        }
                        if (parentViewer.getSubProgressReceiver() == parent) {
                            // Progress viewer for parent found; insert below
                            Integer parentIndentation = (Integer) parentViewer.getClientProperty(CLIENT_PROPERTY_INDENTATION);
                            int indentation = (parentIndentation != null) ? parentIndentation + 1 : 1;
                            progressPanel = new JPanel();
                            progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.LINE_AXIS));
                            progressPanel.add(Box.createHorizontalStrut(indentation * INDENTATION_SIZE));
                            progressPanel.add(progressViewer);
                            scrollablePanel1.add(progressPanel, i + 1);
                            parentFound = true;
                            break;
                        }
                    }
                    if (parent instanceof SubProgressReceiver) {
                        parent = ((SubProgressReceiver) parent).getParent();
                    } else {
                        parent = null;
                    }
                } while ((!parentFound) && (parent != null));
                if (!parentFound) {
                    // Progress viewer not found for any ancestor; append to end
                    scrollablePanel1.add(progressViewer);
                    progressPanel = progressViewer;
                }
            }
            subProgressReceiver.addListener(new ProgressReceiver() {

                @Override
                public void setProgress(float progress) throws OperationCancelled {
                    if (progress >= 1.0f) {
                        doOnEventThread(() -> removeViewerHierarchy(subProgressReceiver));
                    }
                }

                @Override
                public void exceptionThrown(Throwable exception) {
                    doOnEventThread(() -> removeViewerHierarchy(subProgressReceiver));
                }

                @Override
                public void done() {
                    doOnEventThread(() -> removeViewerHierarchy(subProgressReceiver));
                }

                /**
                 * Remove a particular viewer, and any children which may
                 * still exist (this happens in the wild; not entirely clear
                 * why; may be because they never started any progress;
                 * perhaps some kind of race condition).
                 */
                private void removeViewerHierarchy(SubProgressReceiver subProgressReceiver) {
                    // Remove any children
                    for (Component component : scrollablePanel1.getComponents()) {
                        ProgressViewer viewer = (ProgressViewer) ((component instanceof ProgressViewer) ? component : ((JPanel) component).getComponent(1));
                        if (viewer.getSubProgressReceiver().getParent() == subProgressReceiver) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Progress receiver still has child; removing child. Stack trace is of child creation", viewer.getSubProgressReceiver().getCreationTrace());
                            }
                            removeViewerHierarchy(viewer.getSubProgressReceiver());
                        }
                    }
                    // itself
                    for (Component component : scrollablePanel1.getComponents()) {
                        ProgressViewer viewer = (ProgressViewer) ((component instanceof ProgressViewer) ? component : ((JPanel) component).getComponent(1));
                        if (viewer.getSubProgressReceiver() == subProgressReceiver) {
                            scrollablePanel1.remove(component);
                            break;
                        }
                    }
                }

                @Override
                public void setMessage(String message) throws OperationCancelled {
                }

                @Override
                public void checkForCancellation() throws OperationCancelled {
                }

                @Override
                public void reset() throws OperationCancelled {
                }

                @Override
                public void subProgressStarted(SubProgressReceiver subProgressReceiver) throws OperationCancelled {
                }
            });
        }
        jScrollPane1.validate();
    });
}
Also used : SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) ProgressReceiver(org.pepsoft.util.ProgressReceiver)

Example 8 with ProgressReceiver

use of org.pepsoft.util.ProgressReceiver in project WorldPainter by Captain-Chaos.

the class JavaWorldMerger method mergeDimension.

private void mergeDimension(final File worldDir, File backupWorldDir, final Dimension dimension, final Platform platform, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled, IOException {
    if (progressReceiver != null) {
        progressReceiver.setMessage("merging " + dimension.getName() + " dimension");
    }
    final File dimensionDir, backupDimensionDir;
    switch(dimension.getDim()) {
        case org.pepsoft.worldpainter.Constants.DIM_NORMAL:
            dimensionDir = worldDir;
            backupDimensionDir = backupWorldDir;
            break;
        case org.pepsoft.worldpainter.Constants.DIM_NETHER:
            dimensionDir = new File(worldDir, "DIM-1");
            backupDimensionDir = new File(backupWorldDir, "DIM-1");
            break;
        case org.pepsoft.worldpainter.Constants.DIM_END:
            dimensionDir = new File(worldDir, "DIM1");
            backupDimensionDir = new File(backupWorldDir, "DIM1");
            break;
        default:
            throw new IllegalArgumentException("Dimension " + dimension.getDim() + " not supported");
    }
    File regionDir = new File(dimensionDir, "region");
    if (!regionDir.exists()) {
        regionDir.mkdirs();
    }
    dimension.rememberChanges();
    try {
        // Gather all layers used on the map
        final Map<Layer, LayerExporter> exporters = new HashMap<>();
        Set<Layer> allLayers = dimension.getAllLayers(false);
        allLayers.addAll(dimension.getMinimumLayers());
        // If there are combined layers, apply them and gather any newly
        // added layers, recursively
        boolean done;
        do {
            done = true;
            for (Layer layer : new HashSet<>(allLayers)) {
                if (layer instanceof CombinedLayer) {
                    // Apply the combined layer
                    Set<Layer> addedLayers = ((CombinedLayer) layer).apply(dimension);
                    // Remove the combined layer from the list
                    allLayers.remove(layer);
                    // Add any layers it might have added
                    allLayers.addAll(addedLayers);
                    // Signal that we have to go around at least once more,
                    // in case any of the newly added layers are themselves
                    // combined layers
                    done = false;
                }
            }
        } while (!done);
        // Load all layer settings into the exporters
        for (Layer layer : allLayers) {
            @SuppressWarnings("unchecked") LayerExporter exporter = layer.getExporter();
            if (exporter != null) {
                exporter.setSettings(dimension.getLayerSettings(layer));
                exporters.put(layer, exporter);
            }
        }
        // Sort tiles into regions
        int lowestRegionX = Integer.MAX_VALUE, highestRegionX = Integer.MIN_VALUE, lowestRegionZ = Integer.MAX_VALUE, highestRegionZ = Integer.MIN_VALUE;
        Map<Point, Map<Point, Tile>> tilesByRegion = new HashMap<>();
        final boolean tileSelection = selectedTiles != null;
        if (tileSelection) {
            // Sanity check
            assert selectedDimensions.size() == 1;
            assert selectedDimensions.contains(dimension.getDim());
            for (Point tileCoords : selectedTiles) {
                Tile tile = dimension.getTile(tileCoords);
                boolean nonReadOnlyChunksFound = false;
                outerLoop: for (int chunkX = 0; chunkX < TILE_SIZE; chunkX += 16) {
                    for (int chunkY = 0; chunkY < TILE_SIZE; chunkY += 16) {
                        if (!tile.getBitLayerValue(ReadOnly.INSTANCE, chunkX, chunkY)) {
                            nonReadOnlyChunksFound = true;
                            break outerLoop;
                        }
                    }
                }
                if (!nonReadOnlyChunksFound) {
                    // be merged
                    continue;
                }
                int regionX = tileCoords.x >> 2;
                int regionZ = tileCoords.y >> 2;
                Point regionCoords = new Point(regionX, regionZ);
                Map<Point, Tile> tilesForRegion = tilesByRegion.computeIfAbsent(regionCoords, k -> new HashMap<>());
                tilesForRegion.put(tileCoords, tile);
                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()) {
                boolean nonReadOnlyChunksFound = false;
                outerLoop: for (int chunkX = 0; chunkX < TILE_SIZE; chunkX += 16) {
                    for (int chunkY = 0; chunkY < TILE_SIZE; chunkY += 16) {
                        if (!tile.getBitLayerValue(ReadOnly.INSTANCE, chunkX, chunkY)) {
                            nonReadOnlyChunksFound = true;
                            break outerLoop;
                        }
                    }
                }
                if (!nonReadOnlyChunksFound) {
                    // be merged
                    continue;
                }
                int regionX = tile.getX() >> 2;
                int regionZ = tile.getY() >> 2;
                Point regionCoords = new Point(regionX, regionZ);
                Map<Point, Tile> tilesForRegion = tilesByRegion.computeIfAbsent(regionCoords, k -> new HashMap<>());
                tilesForRegion.put(new Point(tile.getX(), tile.getY()), tile);
                if (regionX < lowestRegionX) {
                    lowestRegionX = regionX;
                }
                if (regionX > highestRegionX) {
                    highestRegionX = regionX;
                }
                if (regionZ < lowestRegionZ) {
                    lowestRegionZ = regionZ;
                }
                if (regionZ > highestRegionZ) {
                    highestRegionZ = regionZ;
                }
            }
        }
        // Read the region coordinates of the existing map
        final File backupRegionDir = new File(backupDimensionDir, "region");
        final Pattern regionFilePattern = platform.equals(DefaultPlugin.JAVA_ANVIL) ? Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mca") : Pattern.compile("r\\.-?\\d+\\.-?\\d+\\.mcr");
        File[] existingRegionFiles = backupRegionDir.listFiles((dir, name) -> regionFilePattern.matcher(name).matches());
        Map<Point, File> existingRegions = new HashMap<>();
        for (File file : existingRegionFiles) {
            String[] parts = file.getName().split("\\.");
            int regionX = Integer.parseInt(parts[1]);
            int regionZ = Integer.parseInt(parts[2]);
            existingRegions.put(new Point(regionX, regionZ), file);
            if (regionX < lowestRegionX) {
                lowestRegionX = regionX;
            }
            if (regionX > highestRegionX) {
                highestRegionX = regionX;
            }
            if (regionZ < lowestRegionZ) {
                lowestRegionZ = regionZ;
            }
            if (regionZ > highestRegionZ) {
                highestRegionZ = regionZ;
            }
        }
        final Set<Point> allRegionCoords = new HashSet<>();
        allRegionCoords.addAll(tilesByRegion.keySet());
        allRegionCoords.addAll(existingRegions.keySet());
        // Sort the regions to export the first two rows together, and then
        // row by row, to get the optimum tempo of performing fixups
        List<Point> sortedRegions = new ArrayList<>(allRegionCoords.size());
        if (lowestRegionZ == highestRegionZ) {
            // No point in sorting it
            sortedRegions.addAll(allRegionCoords);
        } else {
            for (int x = lowestRegionX; x <= highestRegionX; x++) {
                for (int z = lowestRegionZ; z <= (lowestRegionZ + 1); z++) {
                    Point regionCoords = new Point(x, z);
                    if (allRegionCoords.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 (allRegionCoords.contains(regionCoords)) {
                        sortedRegions.add(regionCoords);
                    }
                }
            }
        }
        // Merge each individual region
        final WorldPainterChunkFactory chunkFactory = new WorldPainterChunkFactory(dimension, exporters, world.getPlatform(), world.getMaxHeight());
        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")), tilesByRegion.size()), 1);
        } else {
            threads = Math.max(Math.min(Math.min(maxThreadsByMem, runtime.availableProcessors()), allRegionCoords.size()), 1);
        }
        logger.info("Using " + threads + " thread(s) for merge (cores: " + runtime.availableProcessors() + ", available memory: " + (maxMemoryAvailable / 1048576L) + " MB)");
        final Map<Point, List<Fixup>> fixups = new HashMap<>();
        final Set<Point> exportedRegions = new HashSet<>();
        ExecutorService executor = Executors.newFixedThreadPool(threads, new ThreadFactory() {

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

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

            private int nextID = 1;
        });
        final ParallelProgressManager parallelProgressManager = (progressReceiver != null) ? new ParallelProgressManager(progressReceiver, allRegionCoords.size()) : null;
        try {
            // Merge each individual region
            for (final Point regionCoords : sortedRegions) {
                if (existingRegions.containsKey(regionCoords)) {
                    if (tilesByRegion.containsKey(regionCoords)) {
                        // Region exists in new and existing maps; merge it
                        final Map<Point, Tile> tiles = tilesByRegion.get(regionCoords);
                        executor.execute(() -> {
                            ProgressReceiver progressReceiver1 = (parallelProgressManager != null) ? parallelProgressManager.createProgressReceiver() : null;
                            if (progressReceiver1 != null) {
                                try {
                                    progressReceiver1.checkForCancellation();
                                } catch (ProgressReceiver.OperationCancelled e) {
                                    return;
                                }
                            }
                            try {
                                List<Fixup> regionFixups = new ArrayList<>();
                                WorldRegion minecraftWorld = new WorldRegion(regionCoords.x, regionCoords.y, dimension.getMaxHeight(), platform);
                                try {
                                    String regionWarnings = mergeRegion(minecraftWorld, backupRegionDir, dimension, platform, regionCoords, tiles, tileSelection, exporters, chunkFactory, regionFixups, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.0f, 0.9f) : null);
                                    if (regionWarnings != null) {
                                        if (warnings == null) {
                                            warnings = regionWarnings;
                                        } else {
                                            warnings = warnings + regionWarnings;
                                        }
                                    }
                                    if (logger.isDebugEnabled()) {
                                        logger.debug("Merged region " + regionCoords.x + "," + regionCoords.y);
                                    }
                                } finally {
                                    minecraftWorld.save(worldDir, dimension.getDim());
                                }
                                synchronized (fixups) {
                                    if (!regionFixups.isEmpty()) {
                                        fixups.put(new Point(regionCoords.x, regionCoords.y), regionFixups);
                                    }
                                    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(allRegionCoords, 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);
                                }
                            }
                        });
                    } else {
                        // Region only exists in existing world. Copy it to the new
                        // world
                        ProgressReceiver subProgressReceiver = (parallelProgressManager != null) ? parallelProgressManager.createProgressReceiver() : null;
                        if (subProgressReceiver != null) {
                            subProgressReceiver.setMessage("Copying region " + regionCoords.x + "," + regionCoords.y + " unchanged");
                        }
                        FileUtils.copyFileToDir(existingRegions.get(regionCoords), regionDir, subProgressReceiver);
                        synchronized (fixups) {
                            exportedRegions.add(regionCoords);
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("Copied region " + regionCoords.x + "," + regionCoords.y);
                        }
                    }
                } else {
                    // Region only exists in new world. Create it as new
                    executor.execute(() -> {
                        ProgressReceiver progressReceiver1 = (parallelProgressManager != null) ? parallelProgressManager.createProgressReceiver() : null;
                        if (progressReceiver1 != null) {
                            try {
                                progressReceiver1.checkForCancellation();
                            } catch (ProgressReceiver.OperationCancelled e) {
                                return;
                            }
                        }
                        try {
                            WorldRegion minecraftWorld = new WorldRegion(regionCoords.x, regionCoords.y, dimension.getMaxHeight(), platform);
                            ExportResults exportResults = null;
                            try {
                                exportResults = exportRegion(minecraftWorld, dimension, null, platform, regionCoords, tileSelection, exporters, null, chunkFactory, null, (progressReceiver1 != null) ? new SubProgressReceiver(progressReceiver1, 0.9f, 0.1f) : null);
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Generated region " + regionCoords.x + "," + regionCoords.y);
                                }
                            } finally {
                                if ((exportResults != null) && exportResults.chunksGenerated) {
                                    minecraftWorld.save(worldDir, dimension.getDim());
                                }
                            }
                            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(allRegionCoords, 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(1000, 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 != null) ? new SubProgressReceiver(progressReceiver, 0.9f, 0.1f) : null, fixups);
            }
        }
        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();
        }
    }
}
Also used : ThreadFactory(java.util.concurrent.ThreadFactory) List(java.util.List) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) ProgressReceiver(org.pepsoft.util.ProgressReceiver) HistoryEntry(org.pepsoft.worldpainter.history.HistoryEntry) Pattern(java.util.regex.Pattern) ParallelProgressManager(org.pepsoft.util.ParallelProgressManager) ExecutorService(java.util.concurrent.ExecutorService)

Example 9 with ProgressReceiver

use of org.pepsoft.util.ProgressReceiver in project WorldPainter by Captain-Chaos.

the class JavaWorldMerger method merge.

public void merge(File backupDir, ProgressReceiver progressReceiver) throws IOException, ProgressReceiver.OperationCancelled {
    logger.info("Merging world " + world.getName() + " with map at " + levelDatFile.getParentFile());
    // Read existing level.dat file and perform sanity checks
    Level level = performSanityChecks(false);
    // Record start of export
    long start = System.currentTimeMillis();
    // Backup existing level
    File worldDir = levelDatFile.getParentFile();
    if (!worldDir.renameTo(backupDir)) {
        throw new FileInUseException("Could not move " + worldDir + " to " + backupDir);
    }
    if (!worldDir.mkdirs()) {
        throw new IOException("Could not create " + worldDir);
    }
    // Set the world to the same Minecraft version as the existing map, in
    // case it has changed. This affects the type of chunks created in the
    // first pass
    int version = level.getVersion();
    Platform platform = (version == SUPPORTED_VERSION_1) ? DefaultPlugin.JAVA_MCREGION : DefaultPlugin.JAVA_ANVIL;
    world.setPlatform(platform);
    // Modify it if necessary and write it to the the new level
    if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) {
        Dimension surfaceDimension = world.getDimension(DIM_NORMAL);
        level.setSeed(surfaceDimension.getMinecraftSeed());
        Point spawnPoint = world.getSpawnPoint();
        level.setSpawnX(spawnPoint.x);
        level.setSpawnY(Math.max(surfaceDimension.getIntHeightAt(spawnPoint), surfaceDimension.getWaterLevelAt(spawnPoint)));
        level.setSpawnZ(spawnPoint.y);
    }
    // Save the level.dat file. This will also create a session.lock file, hopefully kicking out any Minecraft
    // instances which may have the map open:
    level.save(worldDir);
    // Copy everything that we are not going to generate
    File[] files = backupDir.listFiles();
    // noinspection ConstantConditions // Cannot happen because we previously loaded level.dat from it
    for (File file : files) {
        if ((!file.getName().equalsIgnoreCase("level.dat")) && (!file.getName().equalsIgnoreCase("level.dat_old")) && (!file.getName().equalsIgnoreCase("session.lock")) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_NORMAL))) || (!file.getName().equalsIgnoreCase("region"))) && (!file.getName().equalsIgnoreCase("maxheight.txt")) && (!file.getName().equalsIgnoreCase("Height.txt")) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_NETHER))) || (!file.getName().equalsIgnoreCase("DIM-1"))) && (((selectedDimensions != null) && (!selectedDimensions.contains(DIM_END))) || (!file.getName().equalsIgnoreCase("DIM1")))) {
            if (file.isFile()) {
                FileUtils.copyFileToDir(file, worldDir);
            } else if (file.isDirectory()) {
                FileUtils.copyDir(file, new File(worldDir, file.getName()));
            } else {
                logger.warn("Not copying " + file + "; not a regular file or directory");
            }
        }
    }
    if ((selectedDimensions == null) ? (world.getDimension(DIM_NORMAL) != null) : selectedDimensions.contains(DIM_NORMAL)) {
        mergeDimension(worldDir, backupDir, world.getDimension(DIM_NORMAL), platform, progressReceiver);
    }
    if ((selectedDimensions == null) ? (world.getDimension(DIM_NETHER) != null) : selectedDimensions.contains(DIM_NETHER)) {
        mergeDimension(worldDir, backupDir, world.getDimension(DIM_NETHER), platform, progressReceiver);
    }
    if ((selectedDimensions == null) ? (world.getDimension(DIM_END) != null) : selectedDimensions.contains(DIM_END)) {
        mergeDimension(worldDir, backupDir, world.getDimension(DIM_END), platform, progressReceiver);
    }
    // Update the session.lock file, hopefully kicking out any Minecraft instances which may have tried to open the
    // map in the mean time:
    File sessionLockFile = new File(worldDir, "session.lock");
    try (DataOutputStream sessionOut = new DataOutputStream(new FileOutputStream(sessionLockFile))) {
        sessionOut.writeLong(System.currentTimeMillis());
    }
    // Record the merge in the world history
    if (selectedDimensions == null) {
        world.addHistoryEntry(HistoryEntry.WORLD_MERGED_FULL, level.getName(), worldDir);
    } else {
        String dimNames = selectedDimensions.stream().map(dim -> {
            switch(dim) {
                case DIM_NORMAL:
                    return "Surface";
                case DIM_NETHER:
                    return "Nether";
                case DIM_END:
                    return "End";
                default:
                    return Integer.toString(dim);
            }
        }).collect(Collectors.joining(", "));
        world.addHistoryEntry(HistoryEntry.WORLD_MERGED_PARTIAL, level.getName(), worldDir, dimNames);
    }
    if (!levelDatFile.equals(world.getMergedWith())) {
        world.setMergedWith(levelDatFile);
    }
    // Log an event
    Configuration config = Configuration.getInstance();
    if (config != null) {
        EventVO event = new EventVO(EVENT_KEY_ACTION_MERGE_WORLD).duration(System.currentTimeMillis() - start);
        event.setAttribute(EventVO.ATTRIBUTE_TIMESTAMP, new Date(start));
        event.setAttribute(ATTRIBUTE_KEY_MAX_HEIGHT, world.getMaxHeight());
        event.setAttribute(ATTRIBUTE_KEY_PLATFORM, world.getPlatform().displayName);
        event.setAttribute(ATTRIBUTE_KEY_MAP_FEATURES, world.isMapFeatures());
        event.setAttribute(ATTRIBUTE_KEY_GAME_TYPE_NAME, world.getGameType().name());
        event.setAttribute(ATTRIBUTE_KEY_ALLOW_CHEATS, world.isAllowCheats());
        event.setAttribute(ATTRIBUTE_KEY_GENERATOR, world.getGenerator().name());
        if (world.getPlatform().equals(DefaultPlugin.JAVA_ANVIL) && (world.getGenerator() == Generator.FLAT)) {
            event.setAttribute(ATTRIBUTE_KEY_GENERATOR_OPTIONS, world.getGeneratorOptions());
        }
        if ((selectedDimensions == null) || selectedDimensions.contains(DIM_NORMAL)) {
            Dimension surfaceDimension = world.getDimension(0);
            event.setAttribute(ATTRIBUTE_KEY_TILES, surfaceDimension.getTiles().size());
            logLayers(surfaceDimension, event, "");
        }
        if (world.getImportedFrom() == null) {
            event.setAttribute(ATTRIBUTE_KEY_IMPORTED_WORLD, false);
        }
        config.logEvent(event);
    }
}
Also used : FileInUseException(org.pepsoft.worldpainter.util.FileInUseException) java.util(java.util) org.pepsoft.minecraft(org.pepsoft.minecraft) BLOCKS(org.pepsoft.minecraft.Block.BLOCKS) EventVO(org.pepsoft.worldpainter.vo.EventVO) ParallelProgressManager(org.pepsoft.util.ParallelProgressManager) org.pepsoft.worldpainter.layers(org.pepsoft.worldpainter.layers) NBTOutputStream(org.jnbt.NBTOutputStream) SubProgressReceiver(org.pepsoft.util.SubProgressReceiver) PlatformManager(org.pepsoft.worldpainter.plugins.PlatformManager) org.pepsoft.worldpainter.exporting(org.pepsoft.worldpainter.exporting) ThreadFactory(java.util.concurrent.ThreadFactory) ExecutorService(java.util.concurrent.ExecutorService) org.pepsoft.worldpainter(org.pepsoft.worldpainter) Constants(org.pepsoft.worldpainter.Constants) HistoryEntry(org.pepsoft.worldpainter.history.HistoryEntry) FileInUseException(org.pepsoft.worldpainter.util.FileInUseException) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) NBTInputStream(org.jnbt.NBTInputStream) Dimension(org.pepsoft.worldpainter.Dimension) java.awt(java.awt) TimeUnit(java.util.concurrent.TimeUnit) CompoundTag(org.jnbt.CompoundTag) List(java.util.List) java.io(java.io) Constants(org.pepsoft.minecraft.Constants) ProgressReceiver(org.pepsoft.util.ProgressReceiver) Tag(org.jnbt.Tag) FileUtils(org.pepsoft.util.FileUtils) Pattern(java.util.regex.Pattern) Dimension(org.pepsoft.worldpainter.Dimension) EventVO(org.pepsoft.worldpainter.vo.EventVO)

Example 10 with ProgressReceiver

use of org.pepsoft.util.ProgressReceiver 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)

Aggregations

ProgressReceiver (org.pepsoft.util.ProgressReceiver)16 OperationCancelled (org.pepsoft.util.ProgressReceiver.OperationCancelled)9 SubProgressReceiver (org.pepsoft.util.SubProgressReceiver)6 ProgressTask (org.pepsoft.util.swing.ProgressTask)6 Layer (org.pepsoft.worldpainter.layers.Layer)6 File (java.io.File)5 List (java.util.List)5 IOException (java.io.IOException)4 java.util (java.util)4 javax.swing (javax.swing)4 ProgressDialog (org.pepsoft.util.swing.ProgressDialog)4 java.awt (java.awt)3 Arrays (java.util.Arrays)3 Collection (java.util.Collection)3 Set (java.util.Set)3 ExecutorService (java.util.concurrent.ExecutorService)3 Pattern (java.util.regex.Pattern)3 ParallelProgressManager (org.pepsoft.util.ParallelProgressManager)3 Dimension (org.pepsoft.worldpainter.Dimension)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2