Search in sources :

Example 16 with ProgressReceiver

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

the class NewWorldDialog method getSelectedDimension.

public Dimension getSelectedDimension(final ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled {
    long minecraftSeed;
    try {
        minecraftSeed = Long.parseLong(fieldSeed.getText());
    } catch (NumberFormatException e) {
        minecraftSeed = fieldSeed.getText().hashCode();
    }
    if (radioButtonCustomSeed.isSelected()) {
        worldpainterSeed = minecraftSeed;
    }
    int waterHeight = (Integer) spinnerWaterLevel.getValue();
    final TileFactory tileFactory = createTileFactory(worldpainterSeed);
    int maxHeight = (Integer) comboBoxMaxHeight.getSelectedItem();
    final Dimension dimension = new Dimension(minecraftSeed, tileFactory, dim, maxHeight);
    dimension.setEventsInhibited(true);
    try {
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        final AtomicBoolean cancelled = new AtomicBoolean();
        if (tiles != null) {
            logger.info("Creating new dimension with " + tiles.size() + " preselected tiles");
            final int[] tileCount = new int[1];
            final int totalTiles = tiles.size();
            for (final Point tileCoords : tiles) {
                executorService.execute(() -> {
                    if (cancelled.get()) {
                        // Operation cancelled by user
                        return;
                    }
                    Tile tile = tileFactory.createTile(tileCoords.x, tileCoords.y);
                    dimension.addTile(tile);
                    if (progressReceiver != null) {
                        synchronized (tileCount) {
                            tileCount[0]++;
                            try {
                                progressReceiver.setProgress((float) tileCount[0] / totalTiles);
                            } catch (ProgressReceiver.OperationCancelled e) {
                                cancelled.set(true);
                            }
                        }
                    }
                });
            }
        } else if (checkBoxCircular.isSelected()) {
            final int radius = (Integer) spinnerWidth.getValue() / 2;
            int diameter = radius * 2;
            logger.info("Creating new circular dimension with diameter " + diameter + " blocks");
            int tileRadius = (radius + 127) / 128;
            final int[] tileCount = new int[1];
            final int approximateTotalTiles = (int) Math.ceil(Math.PI * tileRadius * tileRadius);
            for (int x = -tileRadius; x < tileRadius; x++) {
                for (int y = -tileRadius; y < tileRadius; y++) {
                    if (org.pepsoft.worldpainter.util.MathUtils.getSmallestDistanceFromOrigin(x, y) < radius) {
                        // At least one corner is inside the circle; include
                        // the tile. Note that this is always correct in
                        // this case only because the centre of the circle
                        // is always at a tile intersection so the circle
                        // can never "bulge" into a tile without any of the
                        // the tile's corners being inside the circle
                        final int tileX = x, tileY = y;
                        executorService.execute(() -> {
                            if (cancelled.get()) {
                                // Operation cancelled by user
                                return;
                            }
                            Tile tile = tileFactory.createTile(tileX, tileY);
                            dimension.addTile(tile);
                            if (org.pepsoft.worldpainter.util.MathUtils.getLargestDistanceFromOrigin(tileX, tileY) >= radius) {
                                // the edge
                                for (int xx = 0; xx < TILE_SIZE; xx++) {
                                    for (int yy = 0; yy < TILE_SIZE; yy++) {
                                        float distance = MathUtils.getDistance(tileX * TILE_SIZE + xx + 0.5f, tileY * TILE_SIZE + yy + 0.5f);
                                        if (distance > radius) {
                                            tile.setBitLayerValue(org.pepsoft.worldpainter.layers.Void.INSTANCE, xx, yy, true);
                                        }
                                    }
                                }
                            }
                            if (progressReceiver != null) {
                                synchronized (tileCount) {
                                    tileCount[0]++;
                                    try {
                                        // System.out.println("Progress: " + tileCount[0] + " of " + approximateTotalTiles + " (" + ((float) tileCount[0] / approximateTotalTiles) + ")");
                                        progressReceiver.setProgress(Math.min((float) tileCount[0] / approximateTotalTiles, 1.0f));
                                    } catch (ProgressReceiver.OperationCancelled e) {
                                        cancelled.set(true);
                                    }
                                }
                            }
                        });
                    }
                }
            }
            // Assume the user will want an endless void border by default;
            // override the preferences
            dimension.setBorder(Border.ENDLESS_VOID);
        } else {
            int width = ((Integer) spinnerWidth.getValue()) / 128;
            int height = ((Integer) spinnerLength.getValue()) / 128;
            logger.info("Creating new dimension of size " + width + "x" + height + " for a total of " + width * height + " tiles");
            final int[] tileCount = new int[1];
            final int totalTiles = width * height;
            int startX = -width / 2;
            int startY = -height / 2;
            for (int x = startX; x < startX + width; x++) {
                for (int y = startY; y < startY + height; y++) {
                    final int tileX = x, tileY = y;
                    executorService.execute(() -> {
                        if (cancelled.get()) {
                            // Operation cancelled by user
                            return;
                        }
                        Tile tile = tileFactory.createTile(tileX, tileY);
                        dimension.addTile(tile);
                        if (progressReceiver != null) {
                            synchronized (tileCount) {
                                tileCount[0]++;
                                try {
                                    progressReceiver.setProgress((float) tileCount[0] / totalTiles);
                                } catch (ProgressReceiver.OperationCancelled e) {
                                    cancelled.set(true);
                                }
                            }
                        }
                    });
                }
            }
        }
        // Wait for all tiles to be created
        executorService.shutdown();
        try {
            executorService.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            throw new RuntimeException("Thread interrupted", e);
        }
        if (cancelled.get()) {
            // The operation was cancelled by the user
            return null;
        }
        if (dim == DIM_NORMAL_CEILING) {
            ResourcesExporter.ResourcesExporterSettings resourcesSettings = new ResourcesExporter.ResourcesExporterSettings(maxHeight);
            // Invert min and max levels:
            int maxZ = maxHeight - 1;
            for (int blockType : resourcesSettings.getBlockTypes()) {
                int low = resourcesSettings.getMinLevel(blockType);
                int high = resourcesSettings.getMaxLevel(blockType);
                resourcesSettings.setMinLevel(blockType, maxZ - high);
                resourcesSettings.setMaxLevel(blockType, maxZ - low);
            }
            // Remove lava and water:
            resourcesSettings.setChance(BLK_WATER, 0);
            resourcesSettings.setChance(BLK_LAVA, 0);
            dimension.setLayerSettings(Resources.INSTANCE, resourcesSettings);
        } else if (dim == DIM_NETHER) {
            dimension.setSubsurfaceMaterial(NETHERLIKE);
            CavernsSettings cavernsSettings = new CavernsSettings();
            cavernsSettings.setCavernsEverywhereLevel(16);
            cavernsSettings.setSurfaceBreaking(true);
            cavernsSettings.setFloodWithLava(true);
            cavernsSettings.setWaterLevel(16);
            dimension.setLayerSettings(Caverns.INSTANCE, cavernsSettings);
        } else if (dim == DIM_NETHER_CEILING) {
            dimension.setSubsurfaceMaterial(NETHERLIKE);
        } else if ((dim == DIM_END) || (dim == DIM_END_CEILING)) {
            dimension.setSubsurfaceMaterial(END_STONE);
        }
        Configuration config = Configuration.getInstance();
        Dimension defaults = config.getDefaultTerrainAndLayerSettings();
        if (dim == DIM_NORMAL) {
            if (!checkBoxCircular.isSelected()) {
                dimension.setBorder(defaults.getBorder());
                dimension.setBorderSize(defaults.getBorderSize());
            }
            dimension.setBedrockWall(defaults.isBedrockWall());
            dimension.setSubsurfaceMaterial(defaults.getSubsurfaceMaterial());
            dimension.setPopulate(defaults.isPopulate());
            dimension.setTopLayerMinDepth(defaults.getTopLayerMinDepth());
            dimension.setTopLayerVariation(defaults.getTopLayerVariation());
            dimension.setBottomless(defaults.isBottomless());
            for (Map.Entry<Layer, ExporterSettings> entry : defaults.getAllLayerSettings().entrySet()) {
                dimension.setLayerSettings(entry.getKey(), entry.getValue().clone());
            }
        }
        dimension.setBorderLevel(waterHeight);
        dimension.setCoverSteepTerrain(defaults.isCoverSteepTerrain());
        dimension.setGridEnabled(config.isDefaultGridEnabled());
        dimension.setGridSize(config.getDefaultGridSize());
        dimension.setContoursEnabled(config.isDefaultContoursEnabled());
        dimension.setContourSeparation(config.getDefaultContourSeparation());
    } finally {
        dimension.setEventsInhibited(false);
    }
    dimension.setDirty(false);
    return dimension;
}
Also used : ExporterSettings(org.pepsoft.worldpainter.layers.exporters.ExporterSettings) CavernsSettings(org.pepsoft.worldpainter.layers.exporters.CavernsExporter.CavernsSettings) ResourcesExporter(org.pepsoft.worldpainter.layers.exporters.ResourcesExporter) Layer(org.pepsoft.worldpainter.layers.Layer) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ExecutorService(java.util.concurrent.ExecutorService) 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