Search in sources :

Example 1 with RayTraceResult

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!"));
}
Also used : NonNull(org.checkerframework.checker.nullness.qual.NonNull) ArgumentReader(org.spongepowered.api.command.parameter.ArgumentReader) Entity(org.spongepowered.api.entity.Entity) CommandCause(org.spongepowered.api.command.CommandCause) Component(net.kyori.adventure.text.Component) ArgumentParseException(org.spongepowered.api.command.exception.ArgumentParseException) ResourceKey(org.spongepowered.api.ResourceKey) CommandContext(org.spongepowered.api.command.parameter.CommandContext) ResourceKeyedZeroAdvanceValueParameter(org.spongepowered.common.command.brigadier.argument.ResourceKeyedZeroAdvanceValueParameter) Optional(java.util.Optional) Player(org.spongepowered.api.entity.living.player.Player) RayTrace(org.spongepowered.api.util.blockray.RayTrace) Living(org.spongepowered.api.entity.living.Living) RayTraceResult(org.spongepowered.api.util.blockray.RayTraceResult) Player(org.spongepowered.api.entity.living.player.Player) Living(org.spongepowered.api.entity.living.Living) NonNull(org.checkerframework.checker.nullness.qual.NonNull) RayTraceResult(org.spongepowered.api.util.blockray.RayTraceResult) NonNull(org.checkerframework.checker.nullness.qual.NonNull)

Example 2 with RayTraceResult

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();
}
Also used : RayTraceResult(org.spongepowered.api.util.blockray.RayTraceResult) ServerWorld(org.spongepowered.api.world.server.ServerWorld) Vector3d(org.spongepowered.math.vector.Vector3d) NonNull(org.checkerframework.checker.nullness.qual.NonNull) Vector3i(org.spongepowered.math.vector.Vector3i) AABB(net.minecraft.world.phys.AABB) NonNull(org.checkerframework.checker.nullness.qual.NonNull)

Example 3 with RayTraceResult

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!"));
}
Also used : NonNull(org.checkerframework.checker.nullness.qual.NonNull) LocatableBlock(org.spongepowered.api.world.LocatableBlock) ArgumentReader(org.spongepowered.api.command.parameter.ArgumentReader) CommandCause(org.spongepowered.api.command.CommandCause) Component(net.kyori.adventure.text.Component) ArgumentParseException(org.spongepowered.api.command.exception.ArgumentParseException) ResourceKey(org.spongepowered.api.ResourceKey) CommandContext(org.spongepowered.api.command.parameter.CommandContext) ResourceKeyedZeroAdvanceValueParameter(org.spongepowered.common.command.brigadier.argument.ResourceKeyedZeroAdvanceValueParameter) Optional(java.util.Optional) RayTrace(org.spongepowered.api.util.blockray.RayTrace) Living(org.spongepowered.api.entity.living.Living) RayTraceResult(org.spongepowered.api.util.blockray.RayTraceResult) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Living(org.spongepowered.api.entity.living.Living) NonNull(org.checkerframework.checker.nullness.qual.NonNull) RayTraceResult(org.spongepowered.api.util.blockray.RayTraceResult) NonNull(org.checkerframework.checker.nullness.qual.NonNull)

Aggregations

NonNull (org.checkerframework.checker.nullness.qual.NonNull)3 RayTraceResult (org.spongepowered.api.util.blockray.RayTraceResult)3 Optional (java.util.Optional)2 Component (net.kyori.adventure.text.Component)2 ResourceKey (org.spongepowered.api.ResourceKey)2 CommandCause (org.spongepowered.api.command.CommandCause)2 ArgumentParseException (org.spongepowered.api.command.exception.ArgumentParseException)2 ArgumentReader (org.spongepowered.api.command.parameter.ArgumentReader)2 CommandContext (org.spongepowered.api.command.parameter.CommandContext)2 Living (org.spongepowered.api.entity.living.Living)2 RayTrace (org.spongepowered.api.util.blockray.RayTrace)2 ResourceKeyedZeroAdvanceValueParameter (org.spongepowered.common.command.brigadier.argument.ResourceKeyedZeroAdvanceValueParameter)2 AABB (net.minecraft.world.phys.AABB)1 Entity (org.spongepowered.api.entity.Entity)1 Player (org.spongepowered.api.entity.living.player.Player)1 LocatableBlock (org.spongepowered.api.world.LocatableBlock)1 ServerLocation (org.spongepowered.api.world.server.ServerLocation)1 ServerWorld (org.spongepowered.api.world.server.ServerWorld)1 Vector3d (org.spongepowered.math.vector.Vector3d)1 Vector3i (org.spongepowered.math.vector.Vector3i)1