Search in sources :

Example 46 with Vector3d

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

the class PlayerListMixin method impl$onInitPlayer_getWorld.

@Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;"))
private net.minecraft.server.level.ServerLevel impl$onInitPlayer_getWorld(final MinecraftServer minecraftServer, final ResourceKey<Level> dimension, final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer) {
    @Nullable final net.minecraft.network.chat.Component kickReason = ((ConnectionBridge) networkManager).bridge$getKickReason();
    final Component disconnectMessage;
    if (kickReason != null) {
        disconnectMessage = SpongeAdventure.asAdventure(kickReason);
    } else {
        disconnectMessage = Component.text("You are not allowed to log in to this server.");
    }
    net.minecraft.server.level.ServerLevel mcWorld = minecraftServer.getLevel(dimension);
    if (mcWorld == null) {
        SpongeCommon.logger().warn("The player '{}' was located in a world that isn't loaded or doesn't exist. This is not safe so " + "the player will be moved to the spawn of the default world.", mcPlayer.getGameProfile().getName());
        mcWorld = minecraftServer.overworld();
        final BlockPos spawnPoint = mcWorld.getSharedSpawnPos();
        mcPlayer.setPos(spawnPoint.getX() + 0.5, spawnPoint.getY() + 0.5, spawnPoint.getZ() + 0.5);
    }
    mcPlayer.setLevel(mcWorld);
    final ServerPlayer player = (ServerPlayer) mcPlayer;
    final ServerLocation location = player.serverLocation();
    final Vector3d rotation = player.rotation();
    // player.connection() cannot be used here, because it's still be null at this point
    final ServerSideConnection connection = (ServerSideConnection) networkManager.getPacketListener();
    // The user is not yet in the player list, so we need to make special provision.
    final User user = SpongeUserView.createLoginEventUser(player);
    final Cause cause = Cause.of(EventContext.empty(), connection, user);
    final ServerSideConnectionEvent.Login event = SpongeEventFactory.createServerSideConnectionEventLogin(cause, disconnectMessage, disconnectMessage, location, location, rotation, rotation, connection, user);
    if (kickReason != null) {
        event.setCancelled(true);
    }
    if (SpongeCommon.post(event)) {
        this.impl$disconnectClient(networkManager, event.message(), player.profile());
        return null;
    }
    final ServerLocation toLocation = event.toLocation();
    final Vector3d toRotation = event.toRotation();
    mcPlayer.absMoveTo(toLocation.x(), toLocation.y(), toLocation.z(), (float) toRotation.y(), (float) toRotation.x());
    return (net.minecraft.server.level.ServerLevel) toLocation.world();
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) User(org.spongepowered.api.entity.living.player.User) ServerLocation(org.spongepowered.api.world.server.ServerLocation) ServerSideConnection(org.spongepowered.api.network.ServerSideConnection) ServerSideConnectionEvent(org.spongepowered.api.event.network.ServerSideConnectionEvent) ServerLevel(net.minecraft.server.level.ServerLevel) Vector3d(org.spongepowered.math.vector.Vector3d) ConnectionBridge(org.spongepowered.common.bridge.network.ConnectionBridge) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) Cause(org.spongepowered.api.event.Cause) BlockPos(net.minecraft.core.BlockPos) TranslatableComponent(net.minecraft.network.chat.TranslatableComponent) TextComponent(net.minecraft.network.chat.TextComponent) MutableComponent(net.minecraft.network.chat.MutableComponent) Component(net.kyori.adventure.text.Component) Nullable(javax.annotation.Nullable) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 47 with Vector3d

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

the class EntityMixin method bridge$changeDimension.

/**
 * This is effectively an overwrite of changeDimension: required due to
 * Forge changing the signature.
 *
 * @author dualspiral - 18th December 2020 - 1.16.4
 * @author dualspiral - 8th August 2021 - 1.16.5 (adjusted for SpongeForge)
 *
 * @param originalDestinationWorld The original target world
 * @param originalPortalLogic performs additional teleportation logic, as required.
 * @return The {@link Entity} that is either this one, or replaces this one
 */
@SuppressWarnings("ConstantConditions")
@org.checkerframework.checker.nullness.qual.Nullable
public Entity bridge$changeDimension(final net.minecraft.server.level.ServerLevel originalDestinationWorld, final PortalLogic originalPortalLogic) {
    // Sponge Start
    if (this.shadow$getCommandSenderWorld().isClientSide || this.removed) {
        return null;
    }
    final boolean isPlayer = ((Object) this) instanceof ServerPlayer;
    final TeleportContext contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(PhaseTracker.getInstance()).worldChange();
    if (isPlayer) {
        contextToSwitchTo.player();
    }
    try (final TeleportContext context = contextToSwitchTo.buildAndSwitch();
        final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(this);
        frame.pushCause(originalPortalLogic.getPortalType());
        frame.addContext(EventContextKeys.MOVEMENT_TYPE, originalPortalLogic.getMovementType());
        this.impl$originalDestinationWorld = new WeakReference<>((ServerWorld) originalDestinationWorld);
        final ChangeEntityWorldEvent.Pre preChangeEvent = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre((Entity) (Object) this, originalDestinationWorld);
        if (preChangeEvent.isCancelled()) {
            this.impl$onPreWorldChangeCanceled();
            return null;
        }
        this.impl$customPortal = preChangeEvent.originalDestinationWorld() != preChangeEvent.destinationWorld();
        final PortalLogic finalPortalLogic;
        if (this.impl$customPortal && originalPortalLogic == originalDestinationWorld.getPortalForcer()) {
            finalPortalLogic = (PortalLogic) ((ServerLevel) preChangeEvent.destinationWorld()).getPortalForcer();
        } else {
            finalPortalLogic = originalPortalLogic;
        }
        final net.minecraft.server.level.ServerLevel targetWorld = (net.minecraft.server.level.ServerLevel) preChangeEvent.destinationWorld();
        final Vector3d currentPosition = VecHelper.toVector3d(this.shadow$position());
        // If a player, set the fact they are changing dimensions
        this.impl$onChangingDimension(targetWorld);
        final net.minecraft.server.level.ServerLevel serverworld = (net.minecraft.server.level.ServerLevel) this.level;
        final ResourceKey<Level> registrykey = serverworld.dimension();
        if (isPlayer && registrykey == Level.END && targetWorld.dimension() == Level.OVERWORLD && finalPortalLogic.isVanilla()) {
            // avoids modded dimensions
            return this.impl$postProcessChangeDimension(this.impl$performGameWinLogic());
        } else {
            // Sponge Start: Redirect the find portal call to the teleporter.
            // If this is vanilla, this will house our Reposition Event and return an appropriate
            // portal info
            final PortalInfo portalinfo = originalPortalLogic.getPortalInfo((Entity) (Object) this, targetWorld, // don't make this a method reference, it'll crash vanilla.
            x -> this.shadow$findDimensionEntryPoint(x));
            // Sponge End
            if (portalinfo != null) {
                if (portalinfo instanceof SpongePortalInfo) {
                    frame.addContext(EventContextKeys.PORTAL, ((SpongePortalInfo) portalinfo).portal());
                }
                // Only start teleporting if we have somewhere to go.
                this.impl$prepareForPortalTeleport(serverworld, targetWorld);
                try {
                    // Sponge Start: wrap the teleportation logic within a function to allow for modification
                    // of the teleporter
                    final Vector3d originalDestination = new Vector3d(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z);
                    // Note that impl$portalRepositioning is the lambda. As this will be different in ServerPlayer,
                    // we transfer it to a method instead so we can override it.
                    final Entity transportedEntity = originalPortalLogic.placeEntity((Entity) (Object) this, serverworld, targetWorld, this.yRot, createEndPlatform -> this.impl$portalRepositioning(createEndPlatform, serverworld, targetWorld, portalinfo));
                    // Make sure the right object was returned
                    this.impl$validateEntityAfterTeleport(transportedEntity, originalPortalLogic);
                    // If we need to reposition: well... reposition.
                    // Downside: portals won't come with us, but with how it's implemented in Forge,
                    // not sure how we'd do this.
                    // 
                    // If this is vanilla, we've already fired and dealt with the event
                    final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
                    if (transportedEntity != null && this.impl$shouldFireRepositionEvent) {
                        final Vector3d destination = VecHelper.toVector3d(this.shadow$position());
                        final ChangeEntityWorldEvent.Reposition reposition = SpongeEventFactory.createChangeEntityWorldEventReposition(cause, (org.spongepowered.api.entity.Entity) transportedEntity, (org.spongepowered.api.world.server.ServerWorld) serverworld, currentPosition, destination, (org.spongepowered.api.world.server.ServerWorld) originalDestinationWorld, originalDestination, (org.spongepowered.api.world.server.ServerWorld) targetWorld);
                        final Vector3d finalPosition;
                        if (reposition.isCancelled()) {
                            // send them back to the original destination
                            finalPosition = originalDestination;
                        } else if (reposition.destinationPosition() != destination) {
                            finalPosition = reposition.destinationPosition();
                        } else {
                            finalPosition = null;
                        }
                        if (finalPosition != null) {
                            // TODO: Rollback captures during phase - anything generated needs to vanish here
                            // Issue chunk ticket of type Portal, even if a portal isn't being created here.
                            final BlockPos ticketPos = VecHelper.toBlockPos(finalPosition);
                            targetWorld.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(ticketPos), 3, ticketPos);
                            this.shadow$absMoveTo(finalPosition.x(), finalPosition.y(), finalPosition.z());
                        }
                    }
                    // Used to perform player specific tasks.
                    this.impl$postPortalForceChangeTasks(transportedEntity, targetWorld, originalPortalLogic.getPortalType() instanceof NetherPortalType);
                    // Call post event
                    Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost(cause, (org.spongepowered.api.entity.Entity) this, (ServerWorld) serverworld, (ServerWorld) originalDestinationWorld, (ServerWorld) targetWorld));
                } catch (final RuntimeException e) {
                    // just in case a mod does something less than clever.
                    if ((Object) this instanceof ServerPlayer) {
                        this.impl$postPortalForceChangeTasks((Entity) (Object) this, (net.minecraft.server.level.ServerLevel) this.level, false);
                    }
                    throw e;
                }
            // Sponge End
            } else {
                // Didn't work out.
                return null;
            }
        }
        return this.impl$postProcessChangeDimension((Entity) (Object) this);
    } finally {
        // Reset for the next attempt.
        this.impl$shouldFireRepositionEvent = true;
        this.impl$originalDestinationWorld = null;
        this.impl$customPortal = false;
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) LivingEntity(net.minecraft.world.entity.LivingEntity) ItemEntity(net.minecraft.world.entity.item.ItemEntity) Entity(net.minecraft.world.entity.Entity) SpongePortalInfo(org.spongepowered.common.world.portal.SpongePortalInfo) PortalInfo(net.minecraft.world.level.portal.PortalInfo) ServerLevel(net.minecraft.server.level.ServerLevel) PortalLogic(org.spongepowered.common.world.portal.PortalLogic) TeleportContext(org.spongepowered.common.event.tracking.phase.entity.TeleportContext) ServerWorld(org.spongepowered.api.world.server.ServerWorld) SpongePortalInfo(org.spongepowered.common.world.portal.SpongePortalInfo) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Cause(org.spongepowered.api.event.Cause) BlockPos(net.minecraft.core.BlockPos) ChunkPos(net.minecraft.world.level.ChunkPos) NetherPortalType(org.spongepowered.common.world.portal.NetherPortalType) ChangeEntityWorldEvent(org.spongepowered.api.event.entity.ChangeEntityWorldEvent) Vector3d(org.spongepowered.math.vector.Vector3d) ServerPlayer(net.minecraft.server.level.ServerPlayer) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel)

Example 48 with Vector3d

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

the class EntityMixin method impl$fireRepositionEventWhenFindingAPortal.

@Inject(method = "getExitPortal", cancellable = true, at = @At("RETURN"))
private void impl$fireRepositionEventWhenFindingAPortal(final net.minecraft.server.level.ServerLevel targetWorld, final BlockPos targetPosition, final boolean targetIsNether, final CallbackInfoReturnable<Optional<BlockUtil.FoundRectangle>> cir) {
    if (this.impl$shouldFireRepositionEvent) {
        // This exists as we're injecting at return
        final Optional<BlockUtil.FoundRectangle> result = cir.getReturnValue();
        final Vector3d destinationPosition = result.map(this::impl$getEntityPositionInPotentialExitPortal).orElseGet(() -> VecHelper.toVector3d(targetPosition));
        final ServerWorld originalDestinationWorld;
        if (this.impl$originalDestinationWorld != null && this.impl$originalDestinationWorld.get() != null) {
            originalDestinationWorld = this.impl$originalDestinationWorld.get();
        } else {
            originalDestinationWorld = (ServerWorld) targetWorld;
        }
        final ChangeEntityWorldEvent.Reposition reposition = this.bridge$fireRepositionEvent(originalDestinationWorld, (ServerWorld) targetWorld, destinationPosition);
        if (!reposition.isCancelled() && reposition.destinationPosition() != destinationPosition) {
            // Something changed so we want to re-rerun this loop.
            // TODO: There is an open question here about whether we want to force the creation of a portal in this
            // scenario, or whether we're happy if the repositioning will put someone in a nearby portal.
            cir.setReturnValue(this.shadow$getExitPortal(targetWorld, VecHelper.toBlockPos(reposition.destinationPosition()), targetIsNether));
            this.impl$dontCreateExitPortal = true;
        }
    }
}
Also used : ServerWorld(org.spongepowered.api.world.server.ServerWorld) ChangeEntityWorldEvent(org.spongepowered.api.event.entity.ChangeEntityWorldEvent) Vector3d(org.spongepowered.math.vector.Vector3d) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 49 with Vector3d

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

the class EntityMixin method bridge$setLocation.

@Override
public boolean bridge$setLocation(final ServerLocation location) {
    if (this.removed || ((LevelBridge) location.world()).bridge$isFake()) {
        return false;
    }
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN);
        final net.minecraft.server.level.ServerLevel originalWorld = (ServerLevel) this.shadow$getCommandSenderWorld();
        final net.minecraft.server.level.ServerLevel originalDestinationWorld = (net.minecraft.server.level.ServerLevel) location.world();
        final net.minecraft.server.level.ServerLevel destinationWorld;
        @org.checkerframework.checker.nullness.qual.Nullable final Vector3d destinationPosition;
        final boolean isChangeOfWorld = this.shadow$getCommandSenderWorld() != originalDestinationWorld;
        if (isChangeOfWorld) {
            final ChangeEntityWorldEvent.Pre event = PlatformHooks.INSTANCE.getEventHooks().callChangeEntityWorldEventPre((Entity) (Object) this, originalDestinationWorld);
            if (event.isCancelled() || ((LevelBridge) event.destinationWorld()).bridge$isFake()) {
                return false;
            }
            destinationWorld = (ServerLevel) event.destinationWorld();
            final ChangeEntityWorldEvent.Reposition repositionEvent = this.bridge$fireRepositionEvent(event.originalDestinationWorld(), event.destinationWorld(), location.position());
            if (repositionEvent.isCancelled()) {
                return false;
            }
            destinationPosition = repositionEvent.destinationPosition();
        } else {
            destinationWorld = (ServerLevel) this.level;
            destinationPosition = this.impl$fireMoveEvent(PhaseTracker.SERVER, location.position());
            if (destinationPosition == null) {
                return false;
            }
        }
        final boolean completed = this.impl$setLocation(isChangeOfWorld, originalDestinationWorld, destinationWorld, destinationPosition);
        if (isChangeOfWorld) {
            Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.entity.Entity) this, (ServerWorld) originalWorld, (ServerWorld) originalDestinationWorld, (ServerWorld) destinationWorld));
        }
        return completed;
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) LivingEntity(net.minecraft.world.entity.LivingEntity) ItemEntity(net.minecraft.world.entity.item.ItemEntity) Entity(net.minecraft.world.entity.Entity) ChangeEntityWorldEvent(org.spongepowered.api.event.entity.ChangeEntityWorldEvent) ServerLevel(net.minecraft.server.level.ServerLevel) ServerWorld(org.spongepowered.api.world.server.ServerWorld) Vector3d(org.spongepowered.math.vector.Vector3d) CauseStackManager(org.spongepowered.api.event.CauseStackManager)

Example 50 with Vector3d

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

the class LivingEntityMixin method impl$callFinishSleepingEvent.

// End implementation of UseItemStackEvent
@Inject(method = "stopSleeping", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;clearSleepingPos()V"))
private void impl$callFinishSleepingEvent(final CallbackInfo ci) {
    if (this.level.isClientSide) {
        return;
    }
    final Optional<BlockPos> sleepingPos = this.shadow$getSleepingPos();
    if (!sleepingPos.isPresent()) {
        return;
    }
    final BlockSnapshot snapshot = ((ServerWorld) this.level).createSnapshot(sleepingPos.get().getX(), sleepingPos.get().getY(), sleepingPos.get().getZ());
    final Cause currentCause = Sponge.server().causeStackManager().currentCause();
    final ServerLocation loc = ServerLocation.of((ServerWorld) this.level, VecHelper.toVector3d(this.shadow$position()));
    final Vector3d rot = ((Living) this).rotation();
    final SleepingEvent.Finish event = SpongeEventFactory.createSleepingEventFinish(currentCause, loc, loc, rot, rot, snapshot, (Living) this);
    Sponge.eventManager().post(event);
    this.shadow$clearSleepingPos();
    if (event.toLocation().world() != this.level) {
        throw new UnsupportedOperationException("World change is not supported here.");
    }
    this.shadow$setPos(event.toLocation().x(), event.toLocation().y(), event.toLocation().z());
    ((Living) this).setRotation(event.toRotation());
}
Also used : ServerWorld(org.spongepowered.api.world.server.ServerWorld) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Vector3d(org.spongepowered.math.vector.Vector3d) Living(org.spongepowered.api.entity.living.Living) Cause(org.spongepowered.api.event.Cause) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) BlockPos(net.minecraft.core.BlockPos) SleepingEvent(org.spongepowered.api.event.action.SleepingEvent) 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