use of org.terasology.engine.world.generation.Region in project Terasology by MovingBlocks.
the class AbstractSpawner method getStartHeight.
/**
* Get the elevation at a single point, to use as the base point for searching.
*/
private int getStartHeight(World world, Vector2i pos) {
BlockRegion spawnArea = new BlockRegion(pos.x(), 0, pos.y());
Region worldRegion = world.getWorldData(spawnArea);
ElevationFacet elevationFacet = worldRegion.getFacet(ElevationFacet.class);
if (elevationFacet != null) {
return (int) elevationFacet.getWorld(pos);
} else {
// We'll have to rely on the SurfaceHeightFacet or SpawnHeightFacet anyway, and those are purely 2D so the height doesn't matter.
return 0;
}
}
use of org.terasology.engine.world.generation.Region in project Terasology by MovingBlocks.
the class AbstractSpawner method findSpawnPosition.
/**
* Tries to find a suitable spawning point based on {@link SurfacesFacet} and {@link ElevationFacet}.
* @param searchRadius the radius within a suitable spawning point will be searched
* @param world the facet-based world
* @param pos the desired 2D position in that world
* @return a 3D position above the surface and sea level or <code>null</code> if none was found
* @throws IllegalStateException if no required facets can be created.
*/
protected Vector3f findSpawnPosition(World world, Vector2i pos, int searchRadius) {
Vector3i ext = new Vector3i(searchRadius, searchRadius, searchRadius);
Vector3i desiredPos = new Vector3i(pos.x(), getStartHeight(world, pos), pos.y());
// try and find somewhere in this region a spot to land
BlockRegion spawnArea = new BlockRegion(desiredPos).expand(ext);
Region worldRegion = world.getWorldData(spawnArea);
Function<Vector2ic, Optional<Float>> getWorld;
// check if generation uses sea level and surface height facets
SurfacesFacet surfacesFacet = worldRegion.getFacet(SurfacesFacet.class);
ElevationFacet elevationFacet = worldRegion.getFacet(ElevationFacet.class);
SpawnHeightFacet spawnHeightFacet = worldRegion.getFacet(SpawnHeightFacet.class);
if (spawnHeightFacet != null) {
getWorld = v -> spawnHeightFacet.getWorld(v.x(), v.y());
} else if (elevationFacet != null) {
if (surfacesFacet != null) {
getWorld = v -> surfacesFacet.getPrimarySurface(elevationFacet, v.x(), v.y());
} else {
getWorld = v -> Optional.of(elevationFacet.getWorld(v.x(), v.y()));
}
} else {
throw new IllegalStateException("No spawn height facet or elevation facet facet found. Can't place spawn point.");
}
Function<Vector2ic, Optional<Integer>> getSeaLevel;
SeaLevelFacet seaLevelFacet = worldRegion.getFacet(SeaLevelFacet.class);
StrictlySparseSeaLevelFacet sparseSeaLevelFacet = worldRegion.getFacet(StrictlySparseSeaLevelFacet.class);
if (sparseSeaLevelFacet != null) {
getSeaLevel = v -> sparseSeaLevelFacet.getSeaLevel(v.x(), v.y());
} else if (seaLevelFacet != null) {
getSeaLevel = v -> Optional.of(seaLevelFacet.getSeaLevel());
} else {
getSeaLevel = v -> Optional.of(0);
}
int spiralRad = searchRadius / 2 - 1;
SpiralIterable spiral = SpiralIterable.clockwise(pos).maxRadius(spiralRad).scale(2).build();
for (Vector2ic test : spiral) {
Optional<Float> val = getWorld.apply(test);
if (!val.isPresent()) {
continue;
}
int height = TeraMath.floorToInt(val.get());
if (!getSeaLevel.apply(test).isPresent() || height >= getSeaLevel.apply(test).get()) {
return new Vector3f(test.x(), height, test.y());
}
}
// nothing above sea level found
for (Vector2ic test : spiral) {
Optional<Float> val = getWorld.apply(test);
if (!val.isPresent()) {
continue;
}
return new Vector3f(test.x(), TeraMath.floorToInt(val.get()), test.y());
}
throw new IllegalStateException("No spawn location found");
}
use of org.terasology.engine.world.generation.Region in project Terasology by MovingBlocks.
the class FacetLayerPreview method render.
@Override
public ByteBuffer render(TextureData texData, int scale, ProgressListener progressListener) throws InterruptedException {
int width = texData.getWidth();
int height = texData.getWidth();
final int offX = -width * scale / 2;
final int offY = -height * scale / 2;
// trigger building the World now
worldGenerator.getWorld();
Rectanglei worldArea = new Rectanglei(offX, offY).setSize(width * scale, height * scale);
Rectanglei tileArea = worldToTileArea(worldArea);
AtomicInteger tilesComplete = new AtomicInteger(0);
int tileCount = tileArea.area();
int[] masks = colorModel.getMasks();
DataBufferInt imageBuffer = new DataBufferInt(width * height);
WritableRaster raster = Raster.createPackedRaster(imageBuffer, width, height, width, masks, null);
BufferedImage view = new BufferedImage(colorModel, raster, false, null);
Graphics2D g = view.createGraphics();
g.scale(1f / scale, 1f / scale);
g.translate(-offX, -offY);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Map<Vector2ic, Future<BufferedImage>> imageFutures = new HashMap<>(tileCount);
for (int z = tileArea.minY(); z < tileArea.maxY(); z++) {
for (int x = tileArea.minX(); x < tileArea.maxX(); x++) {
Vector2i pos = new Vector2i(x, z);
imageFutures.put(pos, threadPool.submit(() -> {
Region createRegion = createRegion(pos);
BufferedImage image = rasterize(createRegion);
if (progressListener != null) {
progressListener.onProgress(tilesComplete.incrementAndGet() / (float) tileCount);
}
return image;
}));
}
}
for (int z = tileArea.minY(); z < tileArea.maxY(); z++) {
for (int x = tileArea.minX(); x < tileArea.maxX(); x++) {
Vector2i pos = new Vector2i(x, z);
try {
BufferedImage tileImage = imageFutures.get(pos).get();
g.drawImage(tileImage, x * TILE_SIZE_X, z * TILE_SIZE_Y, null);
} catch (ExecutionException e) {
logger.warn("Could not rasterize tile {}", pos, e);
}
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
}
// draw coordinate lines through 0 / 0
g.setColor(Color.GRAY);
g.drawLine(worldArea.minX(), 0, worldArea.maxX(), 0);
g.drawLine(0, worldArea.minY(), 0, worldArea.maxY());
g.dispose();
int[] data = imageBuffer.getData();
ByteBuffer byteBuffer = texData.getBuffers()[0];
byteBuffer.asIntBuffer().put(data);
return byteBuffer;
}
Aggregations