Trazado de Rayos (Ray Tracing)
Advertencia
These docs were written for SpongeAPI 7 and are likely out of date. If you feel like you can help update them, please submit a PR!
Genéricamente, el trazado de rayos es un método para determinar el camino de una partícula a través de un sistema de coordenadas. En SpongeAPI, esto se implementa con la clase :javadoc: BlockRay para descubrir bloques en la ruta de una línea arbitraria en el espacio. Un caso de uso común podría ser encontrar el bloque que está mirando a :javadoc: Player.
Puede especificar el origen del rayo utilizando el método BlockRay # from
, pasando ya sea a :javadoc: Location, una :javadoc:`Extensión` y Vector3d
, o una :javadoc:`Entidad`. El método devolverá a BlockRay.BlockRayBuilder.
Truco
Si especifica que el origen del rayo es una Entidad
, la dirección predeterminada será la dirección a la que apunta Entidad
.
To specify the end point, you can use the BlockRay.BlockRayBuilder#to(Vector3d) method, which will set both the direction and ending location. Alternatively, you can specify a direction using BlockRay.BlockRayBuilder#direction(Vector3d) and also a distance limit using BlockRay.BlockRayBuilder#distanceLimit(double).
Nota
The default distance limit is 1000 blocks as a safeguard to prevent infinite iteration. To disable the distance
limit, use a negative value with BlockRayBuilder#distanceLimit(double)
.
Filtración
Filters determine what blocks are accepted by the BlockRay
. To add a filter, use the BlockRayBuilder#stopFilter
or BlockRayBuilder#skipFilter
method, passing in one or many Predicate<BlockRayHit<E>>
s (where E
extends
Extent
). The BlockRayBuilder#stopFilter
continues the ray cast when it hits a block that passes the given
filter and the BlockRayBuilder#skipFilter
skips all blocks that pass the filter. These filters can be chained
together to create a complex BlockRay
. For convenience, BlockRay
contains the following methods for common
filter use cases:
allFilter
: devuelve un filtro que acepta todos los bloques
onlyAirFilter
: devuelve un filtro que acepta solo aire
blockTypeFilter(BlockType)
: devuelve un filtro que acepta solo lo especificado :javadoc: BlockType
continueAfterFilter(Predicate<BlockRayHit<E >>, int)
: devuelve un filtro que continúa más allá del filtro dado por el número especificado de bloques.
Por supuesto, también puede escribir su propio filtro Predicate<BlockRayHit<E>>
.
Finalmente, use BlockRay.BlockRayBuilder#build() para terminar de construir el BlockRay
. Un ejemplo de uso de BlockRayBuilder
para obtener el primer bloque no aéreo que se ve en Player
se proporciona a continuación.
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.util.blockray.BlockRay;
import org.spongepowered.api.world.World;
Player player;
BlockRay<World> blockRay = BlockRay.from(player)
.skipFilter(BlockRay.onlyAirFilter()).stopFilter(BlockRay.onlyAirFilter()).build();
We can rewrite the above to use BlockRay#skipFilter(Predicate<BlockRayHit>)
in addition to
BlockRay#stopFilter(Predicate<BlockRayHit>)
. This will skip all air blocks and stop at the first non-air block it
hits.
BlockRay<World> blockRay = BlockRay.from(player)
.skipFilter(BlockRay.onlyAirFilter()).stopFilter(BlockRay.allFilter()).build();
Usando BlockRay
Como BlockRay
implementa Iterator
, puedes usar métodos como hasNext
y next
(pero no remove
) para iterar a través de BlockRayHits generados por el BlockRay
. Además, puede usar el método BlockRay#reset() para restablecer el iterador a la ubicación de inicio. En lugar de iterar a través del BlockRayHit
s, también puede usar el método BlockRay#end() para rastrear el bloque de rayos hasta el final de su ruta para obtener el último bloque aceptado por el filtro (o ninguno si se alcanzó el límite de bloque).
Usando BlockRayHit
BlockRayHit
contiene información sobre cada bloque intersectado por el rayo. Contiene la ubicación del bloque, la dirección del rayo, las coordenadas de la intersección del rayo y el bloque, y otros datos similares. El siguiente código usa BlockRay
del ejemplo anterior para imprimir la ubicación del primer bloque no aéreo delante del jugador.
import org.spongepowered.api.util.blockray.BlockRayHit;
import java.util.Optional;
BlockRay<World> blockRay = ...;
Optional<BlockRayHit<World>> hitOpt = blockRay.end();
if (hitOpt.isPresent()) {
BlockRayHit<World> hit = hitOpt.get();
System.out.println("Found " + hit.getLocation().getBlockType() + " block at "
+ hit.getLocation() + " with intersection at " + hit.getPosition());
}