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;
}
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;
}
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;
}
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;
}
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);
}
}
Aggregations