Search in sources :

Example 41 with Vector3d

use of org.spongepowered.math.vector.Vector3d in project SpongeCommon by SpongePowered.

the class SpongeEntityArchetype method getRotation.

private Vector3d getRotation() {
    final ListTag tag = this.compound.getList("Rotation", 5);
    final float rotationYaw = tag.getFloat(0);
    final float rotationPitch = tag.getFloat(1);
    return new Vector3d(rotationPitch, rotationYaw, 0);
}
Also used : Vector3d(org.spongepowered.math.vector.Vector3d) ListTag(net.minecraft.nbt.ListTag)

Example 42 with Vector3d

use of org.spongepowered.math.vector.Vector3d in project SpongeCommon by SpongePowered.

the class DataUtil method getLocation.

public static ServerLocation getLocation(final DataView view, final boolean castToInt) {
    final ResourceKey world = view.getResourceKey(Queries.WORLD_KEY).orElseThrow(DataUtil.dataNotFound());
    final Vector3d pos = DataUtil.getPosition3d(view, null);
    if (castToInt) {
        return ServerLocation.of(SpongeCommon.game().server().worldManager().world(world).orElseThrow(DataUtil.dataNotFound()), pos.toInt());
    }
    return ServerLocation.of(SpongeCommon.game().server().worldManager().world(world).orElseThrow(DataUtil.dataNotFound()), pos);
}
Also used : Vector3d(org.spongepowered.math.vector.Vector3d) ResourceKey(org.spongepowered.api.ResourceKey)

Example 43 with Vector3d

use of org.spongepowered.math.vector.Vector3d in project SpongeCommon by SpongePowered.

the class SpongeAABB method intersects.

@Override
public Optional<Tuple<Vector3d, Vector3d>> intersects(final Vector3d start, final Vector3d direction) {
    Objects.requireNonNull(start, "start");
    Objects.requireNonNull(direction, "direction");
    // Adapted from: https://github.com/flow/react/blob/develop/src/main/java/com/flowpowered/react/collision/RayCaster.java#L156
    // The box is interpreted as 6 infinite perpendicular places, one for each face (being expanded infinitely)
    // "t" variables are multipliers: start + direction * t gives the intersection point
    // Find the intersections on the -x and +x planes, oriented by direction
    final double txMin;
    final double txMax;
    final Vector3d xNormal;
    if (Math.copySign(1, direction.x()) > 0) {
        txMin = (this.min.x() - start.x()) / direction.x();
        txMax = (this.max.x() - start.x()) / direction.x();
        xNormal = Vector3d.UNIT_X;
    } else {
        txMin = (this.max.x() - start.x()) / direction.x();
        txMax = (this.min.x() - start.x()) / direction.x();
        xNormal = Vector3d.UNIT_X.negate();
    }
    // Find the intersections on the -y and +y planes, oriented by direction
    final double tyMin;
    final double tyMax;
    final Vector3d yNormal;
    if (Math.copySign(1, direction.y()) > 0) {
        tyMin = (this.min.y() - start.y()) / direction.y();
        tyMax = (this.max.y() - start.y()) / direction.y();
        yNormal = Vector3d.UNIT_Y;
    } else {
        tyMin = (this.max.y() - start.y()) / direction.y();
        tyMax = (this.min.y() - start.y()) / direction.y();
        yNormal = Vector3d.UNIT_Y.negate();
    }
    // the -y plane before the +x plane, else it is outside the box
    if (txMin > tyMax || txMax < tyMin) {
        return Optional.empty();
    }
    // Keep track of the intersection normal which also helps with floating point errors
    Vector3d normalMax;
    Vector3d normalMin;
    // The ray intersects only the furthest min plane on the box and only the closest
    // max plane on the box
    double tMin;
    if (tyMin == txMin) {
        tMin = tyMin;
        normalMin = xNormal.negate().sub(yNormal);
    } else if (tyMin > txMin) {
        tMin = tyMin;
        normalMin = yNormal.negate();
    } else {
        tMin = txMin;
        normalMin = xNormal.negate();
    }
    double tMax;
    if (tyMax == txMax) {
        tMax = tyMax;
        normalMax = xNormal.add(yNormal);
    } else if (tyMax < txMax) {
        tMax = tyMax;
        normalMax = yNormal;
    } else {
        tMax = txMax;
        normalMax = xNormal;
    }
    // Find the intersections on the -z and +z planes, oriented by direction
    final double tzMin;
    final double tzMax;
    final Vector3d zNormal;
    if (Math.copySign(1, direction.z()) > 0) {
        tzMin = (this.min.z() - start.z()) / direction.z();
        tzMax = (this.max.z() - start.z()) / direction.z();
        zNormal = Vector3d.UNIT_Z;
    } else {
        tzMin = (this.max.z() - start.z()) / direction.z();
        tzMax = (this.min.z() - start.z()) / direction.z();
        zNormal = Vector3d.UNIT_Z.negate();
    }
    // max plane on the box
    if (tMin > tzMax || tMax < tzMin) {
        return Optional.empty();
    }
    // plane outside last
    if (tzMin == tMin) {
        normalMin = normalMin.sub(zNormal);
    } else if (tzMin > tMin) {
        tMin = tzMin;
        normalMin = zNormal.negate();
    }
    if (tzMax == tMax) {
        normalMax = normalMax.add(zNormal);
    } else if (tzMax < tMax) {
        tMax = tzMax;
        normalMax = zNormal;
    }
    // Both intersection points are behind the start, there are no intersections
    if (tMax < 0) {
        return Optional.empty();
    }
    // Find the final intersection multiplier and normal
    final double t;
    Vector3d normal;
    if (tMin < 0) {
        // Only the furthest intersection is after the start, so use it
        t = tMax;
        normal = normalMax;
    } else {
        // Both are after the start, use the closest one
        t = tMin;
        normal = normalMin;
    }
    normal = normal.normalize();
    // To avoid rounding point errors leaving the intersection point just off the plane
    // we check the normal to use the actual plane value from the box coordinates
    final double x;
    final double y;
    final double z;
    if (normal.x() > 0) {
        x = this.max.x();
    } else if (normal.x() < 0) {
        x = this.min.x();
    } else {
        x = direction.x() * t + start.x();
    }
    if (normal.y() > 0) {
        y = this.max.y();
    } else if (normal.y() < 0) {
        y = this.min.y();
    } else {
        y = direction.y() * t + start.y();
    }
    if (normal.z() > 0) {
        z = this.max.z();
    } else if (normal.z() < 0) {
        z = this.min.z();
    } else {
        z = direction.z() * t + start.z();
    }
    return Optional.of(new Tuple<>(new Vector3d(x, y, z), normal));
}
Also used : Vector3d(org.spongepowered.math.vector.Vector3d)

Example 44 with Vector3d

use of org.spongepowered.math.vector.Vector3d in project SpongeCommon by SpongePowered.

the class SpongeAABB method intersects.

@Override
public boolean intersects(final AABB other) {
    Objects.requireNonNull(other, "other");
    final Vector3d mins = this.min;
    final Vector3d maxs = this.max;
    final Vector3d mino = other.min();
    final Vector3d maxo = other.max();
    return maxs.x() >= mino.x() && maxo.x() >= mins.x() && maxs.y() >= mino.y() && maxo.y() >= mins.y() && maxs.z() >= mino.z() && maxo.z() >= mins.z();
}
Also used : Vector3d(org.spongepowered.math.vector.Vector3d)

Example 45 with Vector3d

use of org.spongepowered.math.vector.Vector3d in project SpongeCommon by SpongePowered.

the class ServerGamePacketListenerImplMixin method impl$callMoveEntityEvent.

/**
 * Effectively, hooking into the following code block:
 * <pre>
 *       if (isMovePlayerPacketInvalid(packetIn)) {
 *          this.disconnect(new TranslationTextComponent("multiplayer.disconnect.invalid_player_movement"));
 *       } else {
 *          ServerWorld serverworld = this.server.world(this.player.dimension);
 *          if (!this.player.queuedEndExit) { // <---- Here is where we're injecting
 *             if (this.networkTickCount == 0) {
 *                this.captureCurrentPosition();
 *             }
 * </pre>
 * we can effectively short circuit the method to handle movement code where
 * returning {@code true} will escape the packet being processed further entirely and
 * {@code false} will allow the remaining processing of the method run.
 *
 * @param packetIn The movement packet
 */
@Inject(method = "handleMovePlayer", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;awaitingPositionFromClient:Lnet/minecraft/world/phys/Vec3;"), slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerPlayer;wonGame:Z"), to = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;tickCount:I", ordinal = 1)), cancellable = true)
private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) {
    // If the movement is modified we pretend that the player has queuedEndExit = true
    // so that vanilla wont process that packet further
    final ServerboundMovePlayerPacketAccessor packetInAccessor = (ServerboundMovePlayerPacketAccessor) packetIn;
    // We don't fire an event to avoid confusing plugins.
    if (!packetInAccessor.accessor$hasPos() && !packetInAccessor.accessor$hasRot()) {
        return;
    }
    final boolean goodMovementPacket = this.receivedMovePacketCount - this.knownMovePacketCount <= 5;
    final boolean fireMoveEvent = goodMovementPacket && packetInAccessor.accessor$hasPos() && ShouldFire.MOVE_ENTITY_EVENT;
    final boolean fireRotationEvent = goodMovementPacket && packetInAccessor.accessor$hasRot() && ShouldFire.ROTATE_ENTITY_EVENT;
    final ServerPlayer player = (ServerPlayer) this.player;
    final Vector3d fromRotation = new Vector3d(this.player.yRot, this.player.xRot, 0);
    // Use the position of the last movement with an event or the current player position if never called
    // We need this because we ignore very small position changes as to not spam as many move events.
    final Vector3d fromPosition = player.position();
    Vector3d toPosition = new Vector3d(packetIn.getX(this.player.getX()), packetIn.getY(this.player.getY()), packetIn.getZ(this.player.getZ()));
    Vector3d toRotation = new Vector3d(packetIn.getYRot(this.player.yRot), packetIn.getXRot(this.player.xRot), 0);
    final boolean significantRotation = fromRotation.distanceSquared(toRotation) > (.15f * .15f);
    final Vector3d originalToPosition = toPosition;
    boolean cancelMovement = false;
    boolean cancelRotation = false;
    // Call move & rotate event as needed...
    if (fireMoveEvent) {
        final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromPosition, toPosition, toPosition);
        if (SpongeCommon.post(event)) {
            cancelMovement = true;
        } else {
            toPosition = event.destinationPosition();
        }
    }
    if (significantRotation && fireRotationEvent) {
        final RotateEntityEvent event = SpongeEventFactory.createRotateEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromRotation, toRotation);
        if (SpongeCommon.post(event)) {
            cancelRotation = true;
            toRotation = fromRotation;
        } else {
            toRotation = event.toRotation();
        }
    }
    // player position and update the player's relation in the chunk manager.
    if (cancelMovement) {
        if (fromPosition.distanceSquared(toPosition) > 0) {
            // Set the location, as if the player was teleporting
            this.awaitingTeleportTime = this.tickCount;
            this.shadow$teleport(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
        } else {
            // If this is only rotation do not teleport back
            this.player.absMoveTo(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
        }
        ci.cancel();
        return;
    }
    // Handle event results
    if (!toPosition.equals(originalToPosition)) {
        // Check if we have to say it's a "teleport" vs a standard move
        final double d4 = packetIn.getX(this.player.getX());
        final double d5 = packetIn.getY(this.player.getY());
        final double d6 = packetIn.getZ(this.player.getZ());
        final double d7 = d4 - this.firstGoodX;
        final double d8 = d5 - this.firstGoodY;
        final double d9 = d6 - this.firstGoodZ;
        final double d10 = this.player.getDeltaMovement().lengthSqr();
        final double d11 = d7 * d7 + d8 * d8 + d9 * d9;
        final float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;
        final int i = this.receivedMovePacketCount - this.knownMovePacketCount;
        if (d11 - d10 > (double) (f2 * (float) i) && !this.shadow$isSingleplayerOwner()) {
            // At this point, we need to set the target position so the teleport code forces it
            this.awaitingPositionFromClient = VecHelper.toVanillaVector3d(toPosition);
            ((EntityAccessor) this.player).invoker$setRot((float) toRotation.x(), (float) toRotation.y());
            // And reset the position update so the force set is done.
            this.awaitingTeleportTime = this.tickCount - Constants.Networking.MAGIC_TRIGGER_TELEPORT_CONFIRM_DIFF;
        } else {
            // otherwise, set the data back onto the packet
            packetInAccessor.accessor$hasPos(true);
            packetInAccessor.accessor$x(toPosition.x());
            packetInAccessor.accessor$y(toPosition.y());
            packetInAccessor.accessor$z(toPosition.z());
        }
    }
}
Also used : EntityAccessor(org.spongepowered.common.accessor.world.entity.EntityAccessor) ServerboundMovePlayerPacketAccessor(org.spongepowered.common.accessor.network.protocol.game.ServerboundMovePlayerPacketAccessor) MoveEntityEvent(org.spongepowered.api.event.entity.MoveEntityEvent) Vector3d(org.spongepowered.math.vector.Vector3d) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) RotateEntityEvent(org.spongepowered.api.event.entity.RotateEntityEvent) Inject(org.spongepowered.asm.mixin.injection.Inject)

Aggregations

Vector3d (org.spongepowered.math.vector.Vector3d)71 Vector3i (org.spongepowered.math.vector.Vector3i)16 CauseStackManager (org.spongepowered.api.event.CauseStackManager)14 AABB (org.spongepowered.api.util.AABB)14 Test (org.junit.jupiter.api.Test)13 ServerWorld (org.spongepowered.api.world.server.ServerWorld)13 BlockPos (net.minecraft.core.BlockPos)8 ServerLevel (net.minecraft.server.level.ServerLevel)7 BlockState (org.spongepowered.api.block.BlockState)7 Transformation (org.spongepowered.api.util.transformation.Transformation)7 Function (java.util.function.Function)6 IntStream (java.util.stream.IntStream)6 Stream (java.util.stream.Stream)6 Entity (org.spongepowered.api.entity.Entity)6 MoveEntityEvent (org.spongepowered.api.event.entity.MoveEntityEvent)6 ServerLocation (org.spongepowered.api.world.server.ServerLocation)6 Nullable (org.checkerframework.checker.nullness.qual.Nullable)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 MethodSource (org.junit.jupiter.params.provider.MethodSource)5 BlockType (org.spongepowered.api.block.BlockType)5