Search in sources :

Example 16 with Tile

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

the class PlantLayerExporter method render.

@Override
public List<Fixup> render(Dimension dimension, Rectangle area, Rectangle exportedArea, MinecraftWorld minecraftWorld) {
    final long seed = dimension.getSeed();
    final int tileX1 = exportedArea.x >> TILE_SIZE_BITS, tileX2 = (exportedArea.x + exportedArea.width - 1) >> TILE_SIZE_BITS;
    final int tileY1 = exportedArea.y >> TILE_SIZE_BITS, tileY2 = (exportedArea.y + exportedArea.height - 1) >> TILE_SIZE_BITS;
    final int maxY = minecraftWorld.getMaxHeight() - 1;
    final boolean generateTilledDirt = layer.isGenerateTilledDirt();
    final boolean blockRulesEnforced = !"false".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.enforceBlockRules"));
    final Bo2ObjectProvider objectProvider = layer.getObjectProvider();
    for (int tileX = tileX1; tileX <= tileX2; tileX++) {
        for (int tileY = tileY1; tileY <= tileY2; tileY++) {
            final Tile tile = dimension.getTile(tileX, tileY);
            if ((tile == null) || (!tile.hasLayer(layer))) {
                // Tile doesn't exist, or it doesn't have the layer
                continue;
            }
            final long tileSeed = (long) tileX << 32 ^ tileY ^ seed;
            objectProvider.setSeed(tileSeed);
            for (int x = 0; x < TILE_SIZE; x++) {
                for (int y = 0; y < TILE_SIZE; y++) {
                    if (tile.getBitLayerValue(layer, x, y)) {
                        // Possibly place a plant
                        final int height = tile.getIntHeight(x, y);
                        if (height < maxY) {
                            final int worldX = (tileX << TILE_SIZE_BITS) | x, worldY = (tileY << TILE_SIZE_BITS) | y;
                            final Plant plant = (Plant) objectProvider.getObject();
                            if (plant.getCategory() == Plant.Category.WATER_PLANTS) {
                                if ((!blockRulesEnforced) || plant.isValidFoundation(minecraftWorld, worldX, worldY, height)) {
                                    possiblyRenderWaterPlant(minecraftWorld, dimension, plant, worldX, worldY, height + 1);
                                }
                            } else {
                                if (tile.getIntHeight(x, y) >= tile.getWaterLevel(x, y)) {
                                    if (!blockRulesEnforced) {
                                        renderObject(minecraftWorld, dimension, plant, worldX, worldY, height + 1, false);
                                        if (generateTilledDirt && (plant.getCategory() == Plant.Category.CROPS) && ((minecraftWorld.getBlockTypeAt(worldX, worldY, height) == Constants.BLK_GRASS) || (minecraftWorld.getBlockTypeAt(worldX, worldY, height) == Constants.BLK_DIRT))) {
                                            minecraftWorld.setMaterialAt(worldX, worldY, height, TILLED_DIRT);
                                        }
                                    } else {
                                        if (plant.isValidFoundation(minecraftWorld, worldX, worldY, height)) {
                                            renderObject(minecraftWorld, dimension, plant, worldX, worldY, height + 1, false);
                                        } else if (generateTilledDirt && (plant.getCategory() == Plant.Category.CROPS) && ((minecraftWorld.getBlockTypeAt(worldX, worldY, height) == Constants.BLK_GRASS) || (minecraftWorld.getBlockTypeAt(worldX, worldY, height) == Constants.BLK_DIRT))) {
                                            minecraftWorld.setMaterialAt(worldX, worldY, height, TILLED_DIRT);
                                            renderObject(minecraftWorld, dimension, plant, worldX, worldY, height + 1, false);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return null;
}
Also used : Tile(org.pepsoft.worldpainter.Tile) Bo2ObjectProvider(org.pepsoft.worldpainter.layers.bo2.Bo2ObjectProvider)

Example 17 with Tile

use of org.pepsoft.worldpainter.Tile 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 18 with Tile

use of org.pepsoft.worldpainter.Tile 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 19 with Tile

use of org.pepsoft.worldpainter.Tile 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 20 with Tile

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

the class PruneTiles method main.

public static void main(String[] args) throws IOException, ClassNotFoundException {
    File worldFile = new File(args[0]);
    int maxTileDistance = Integer.parseInt(args[1]);
    World2 world;
    try (ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new FileInputStream(worldFile)))) {
        world = (World2) in.readObject();
    }
    for (Dimension dimension : world.getDimensions()) {
        for (Tile tile : dimension.getTiles()) {
            int dx = Math.abs(tile.getX()), dy = Math.abs(tile.getY());
            if ((dx > maxTileDistance) || (dy > maxTileDistance)) {
                // It's an outlier. Remove it
                System.out.println("Removing tile at " + tile.getX() + ", " + tile.getY());
                dimension.removeTile(tile);
            }
        }
    }
    try (ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(worldFile)))) {
        out.writeObject(world);
    }
}
Also used : GZIPInputStream(java.util.zip.GZIPInputStream) GZIPOutputStream(java.util.zip.GZIPOutputStream) World2(org.pepsoft.worldpainter.World2) FileOutputStream(java.io.FileOutputStream) Tile(org.pepsoft.worldpainter.Tile) Dimension(org.pepsoft.worldpainter.Dimension) ObjectOutputStream(java.io.ObjectOutputStream) File(java.io.File) FileInputStream(java.io.FileInputStream) ObjectInputStream(java.io.ObjectInputStream)

Aggregations

Tile (org.pepsoft.worldpainter.Tile)31 Dimension (org.pepsoft.worldpainter.Dimension)6 CombinedLayer (org.pepsoft.worldpainter.layers.CombinedLayer)5 Point (java.awt.Point)4 FileOutputStream (java.io.FileOutputStream)4 Terrain (org.pepsoft.worldpainter.Terrain)4 World2 (org.pepsoft.worldpainter.World2)4 Rectangle (java.awt.Rectangle)3 BufferedImage (java.awt.image.BufferedImage)3 File (java.io.File)3 FileInputStream (java.io.FileInputStream)3 ObjectInputStream (java.io.ObjectInputStream)3 GZIPInputStream (java.util.zip.GZIPInputStream)3 SubProgressReceiver (org.pepsoft.util.SubProgressReceiver)3 Layer (org.pepsoft.worldpainter.layers.Layer)3 Graphics2D (java.awt.Graphics2D)2 ObjectOutputStream (java.io.ObjectOutputStream)2 PrintWriter (java.io.PrintWriter)2 java.util (java.util)2 List (java.util.List)2