use of org.spongepowered.api.util.blockray.RayTraceResult in project SpongeCommon by SpongePowered.
the class SpongeTargetEntityValueParameter method parseValue.
@Override
@NonNull
public Optional<? extends Entity> parseValue(@NonNull final CommandCause cause, final ArgumentReader.@NonNull Mutable reader) throws ArgumentParseException {
final Object root = cause.cause().root();
if (root instanceof Living) {
final Living living = (Living) root;
final Optional<RayTraceResult<@NonNull Entity>> rayTraceResult = RayTrace.entity().sourceEyePosition(living).direction(living.headDirection()).limit(30).continueWhileBlock(RayTrace.onlyAir()).select(this.isPlayerOnly ? entity -> entity instanceof Player : entity -> true).continueWhileEntity(// if we hit an entity first, it obscures a player.
r -> false).execute();
if (rayTraceResult.isPresent()) {
return rayTraceResult.map(RayTraceResult::selectedObject);
}
throw reader.createException(Component.text("The cause root is not looking at a entity!"));
}
throw reader.createException(Component.text("The cause root must be a Living!"));
}
use of org.spongepowered.api.util.blockray.RayTraceResult in project SpongeCommon by SpongePowered.
the class AbstractSpongeRayTrace method execute.
@Override
@NonNull
public Optional<RayTraceResult<@NonNull T>> execute() {
this.setupEnd();
// get the direction
final Vector3d directionWithLength = this.end.sub(this.start);
final double length = directionWithLength.length();
final Vector3d direction = directionWithLength.normalize();
if (direction.lengthSquared() == 0) {
throw new IllegalStateException("The start and end must be two different vectors");
}
final ServerWorld serverWorld = Sponge.server().worldManager().world(this.world).orElseThrow(() -> new IllegalStateException("World with key " + this.world.formatted() + " is not loaded!"));
Vector3i currentBlock = this.initialBlock(direction);
final Vector3i steps = this.createSteps(direction);
// The ray equation is, vec(u) + t vec(d). From a point (x, y), there is a t
// that we need to traverse to get to a boundary. We work that out now...
TData tData = this.createInitialTData(direction);
Vector3d currentLocation = new Vector3d(this.start.x(), this.start.y(), this.start.z());
final boolean requiresEntityTracking = this.requiresEntityTracking();
boolean requireAdvancement = true;
while (requireAdvancement) {
final net.minecraft.world.phys.Vec3 vec3dstart = VecHelper.toVanillaVector3d(currentLocation);
// As this iteration is for the CURRENT block location, we need to check where we are with the filter.
if (this.continueWhileLocation != null && !this.continueWhileLocation.test(ServerLocation.of(serverWorld, currentBlock))) {
return Optional.empty();
}
final Vector3d nextLocation;
final net.minecraft.world.phys.Vec3 vec3dend;
if (tData.getTotalTWithNextStep() > length) {
// This is the last step, we break out of the loop after this set of checks.
requireAdvancement = false;
nextLocation = this.end;
vec3dend = VecHelper.toVanillaVector3d(this.end);
} else {
nextLocation = currentLocation.add(direction.x() * tData.getNextStep(), direction.y() * tData.getNextStep(), direction.z() * tData.getNextStep());
vec3dend = VecHelper.toVanillaVector3d(nextLocation);
}
// Get the selection result.
final Optional<RayTraceResult<@NonNull T>> result = this.testSelectLocation(serverWorld, vec3dstart, vec3dend);
if (result.isPresent() && !this.shouldCheckFailures()) {
// that's blocking the view.
return result;
}
// Ensure that the block can be travelled through.
if (!this.shouldAdvanceThroughBlock(serverWorld, vec3dstart, vec3dend)) {
return Optional.empty();
}
// Ensure that the entities in the block can be travelled through.
if (requiresEntityTracking && this.continueWhileEntity != null) {
final double resultDistance;
if (result.isPresent()) {
resultDistance = result.get().hitPosition().distanceSquared(currentLocation);
} else {
resultDistance = Double.MAX_VALUE;
}
final AABB targetAABB = this.getBlockAABB(currentBlock);
for (final net.minecraft.world.entity.Entity entity : this.getFailingEntities(serverWorld, targetAABB)) {
final Optional<net.minecraft.world.phys.Vec3> vec3d = entity.getBoundingBox().clip(vec3dstart, vec3dend);
if (vec3d.isPresent()) {
final net.minecraft.world.phys.Vec3 hitPosition = vec3d.get();
final double sqdist = hitPosition.distanceToSqr(vec3dstart);
if (sqdist < resultDistance) {
// We have a failure, so at this point we just bail out and end the trace.
return Optional.empty();
}
}
}
}
// If we still have a result at this point, return it.
if (result.isPresent()) {
return result;
}
if (requireAdvancement) {
currentLocation = nextLocation;
currentBlock = this.getNextBlock(currentBlock, tData, steps);
tData = this.advance(tData, steps, direction);
}
}
return Optional.empty();
}
use of org.spongepowered.api.util.blockray.RayTraceResult in project SpongeCommon by SpongePowered.
the class SpongeTargetBlockValueParameter method parseValue.
@Override
@NonNull
public Optional<? extends ServerLocation> parseValue(@NonNull final CommandCause cause, final ArgumentReader.@NonNull Mutable reader) throws ArgumentParseException {
final Object root = cause.cause().root();
if (root instanceof Living) {
final Living living = (Living) root;
final Optional<RayTraceResult<@NonNull LocatableBlock>> rayTraceResult = RayTrace.block().sourceEyePosition(living).direction(living.headDirection()).limit(30).continueWhileBlock(RayTrace.onlyAir()).select(RayTrace.nonAir()).continueWhileEntity(r -> false).execute();
if (rayTraceResult.isPresent()) {
return rayTraceResult.map(x -> x.selectedObject().serverLocation());
}
throw reader.createException(Component.text("The cause root is not looking at a block!"));
}
throw reader.createException(Component.text("The cause root must be a Living!"));
}
Aggregations