use of org.terasology.engine.world.generation.facets.SurfacesFacet 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");
}
Aggregations