Search in sources :

Example 1 with StrictlySparseSeaLevelFacet

use of org.terasology.engine.world.generation.facets.StrictlySparseSeaLevelFacet 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");
}
Also used : SpawnHeightFacet(org.terasology.engine.world.generation.facets.SpawnHeightFacet) BlockRegion(org.terasology.engine.world.block.BlockRegion) Region(org.terasology.engine.world.generation.Region) StrictlySparseSeaLevelFacet(org.terasology.engine.world.generation.facets.StrictlySparseSeaLevelFacet) ElevationFacet(org.terasology.engine.world.generation.facets.ElevationFacet) World(org.terasology.engine.world.generation.World) Function(java.util.function.Function) SurfacesFacet(org.terasology.engine.world.generation.facets.SurfacesFacet) Vector2ic(org.joml.Vector2ic) Vector2i(org.joml.Vector2i) Vector3i(org.joml.Vector3i) SpiralIterable(org.terasology.engine.math.SpiralIterable) SeaLevelFacet(org.terasology.engine.world.generation.facets.SeaLevelFacet) Vector3f(org.joml.Vector3f) Optional(java.util.Optional) TeraMath(org.terasology.math.TeraMath) Optional(java.util.Optional) ElevationFacet(org.terasology.engine.world.generation.facets.ElevationFacet) StrictlySparseSeaLevelFacet(org.terasology.engine.world.generation.facets.StrictlySparseSeaLevelFacet) SurfacesFacet(org.terasology.engine.world.generation.facets.SurfacesFacet) Vector2ic(org.joml.Vector2ic) Vector3f(org.joml.Vector3f) Vector3i(org.joml.Vector3i) BlockRegion(org.terasology.engine.world.block.BlockRegion) Region(org.terasology.engine.world.generation.Region) BlockRegion(org.terasology.engine.world.block.BlockRegion) StrictlySparseSeaLevelFacet(org.terasology.engine.world.generation.facets.StrictlySparseSeaLevelFacet) SeaLevelFacet(org.terasology.engine.world.generation.facets.SeaLevelFacet) SpiralIterable(org.terasology.engine.math.SpiralIterable) SpawnHeightFacet(org.terasology.engine.world.generation.facets.SpawnHeightFacet)

Aggregations

Optional (java.util.Optional)1 Function (java.util.function.Function)1 Vector2i (org.joml.Vector2i)1 Vector2ic (org.joml.Vector2ic)1 Vector3f (org.joml.Vector3f)1 Vector3i (org.joml.Vector3i)1 SpiralIterable (org.terasology.engine.math.SpiralIterable)1 BlockRegion (org.terasology.engine.world.block.BlockRegion)1 Region (org.terasology.engine.world.generation.Region)1 World (org.terasology.engine.world.generation.World)1 ElevationFacet (org.terasology.engine.world.generation.facets.ElevationFacet)1 SeaLevelFacet (org.terasology.engine.world.generation.facets.SeaLevelFacet)1 SpawnHeightFacet (org.terasology.engine.world.generation.facets.SpawnHeightFacet)1 StrictlySparseSeaLevelFacet (org.terasology.engine.world.generation.facets.StrictlySparseSeaLevelFacet)1 SurfacesFacet (org.terasology.engine.world.generation.facets.SurfacesFacet)1 TeraMath (org.terasology.math.TeraMath)1