Search in sources :

Example 36 with Redirect

use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.

the class EntityMixin method impl$onMoveCollide.

@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;collide(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;"))
private Vec3 impl$onMoveCollide(final Entity entity, final Vec3 originalMove) {
    final Vec3 afterCollide = this.shadow$collide(originalMove);
    if (ShouldFire.COLLIDE_BLOCK_EVENT_MOVE && !originalMove.equals(afterCollide)) {
        // We had a collision! Try to find the colliding block
        // TODO this is not 100% accurate as the collision happens with the bb potentially colliding with multiple blocks
        // TODO maybe actually check for blocks in bb?
        BlockPos pos = new BlockPos(this.position.add(originalMove));
        if (this.blockPosition.equals(pos)) {
            // retry with bigger move for entities with big bounding box - e.g. minecart
            pos = new BlockPos(this.position.add(originalMove.normalize()));
        }
        final BlockState state = this.level.getBlockState(pos);
        final org.spongepowered.api.util.Direction dir = org.spongepowered.api.util.Direction.closest(new Vector3d(originalMove.x, originalMove.y, originalMove.z));
        if (SpongeCommonEventFactory.handleCollideBlockEvent(state.getBlock(), this.level, pos, state, (Entity) (Object) this, dir, SpongeCommonEventFactory.CollisionType.MOVE)) {
            return originalMove;
        }
    }
    return afterCollide;
}
Also used : BlockState(net.minecraft.world.level.block.state.BlockState) Vector3d(org.spongepowered.math.vector.Vector3d) Vec3(net.minecraft.world.phys.Vec3) BlockPos(net.minecraft.core.BlockPos) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 37 with Redirect

use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.

the class LivingEntityMixin method impl$onSetHeldItem.

@Redirect(method = "completeUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setItemInHand(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/ItemStack;)V"))
private void impl$onSetHeldItem(final LivingEntity self, final InteractionHand hand, final ItemStack stack) {
    if (this.level.isClientSide) {
        self.setItemInHand(hand, stack);
        return;
    }
    // Unforunately, ItemFood calls ItemStack#shrink in Item#onItemUseFinish.
    // To ensure that we provide the original ItemStack in the event,
    // we make a copy of in our onUpdateItemUse redirect
    // If the event or transaction is cancelled, we make sure to explicitly
    // set the copy back in the player's hand, since it may have been already
    // modified if an ItemFood is being used.
    final ItemStackSnapshot activeItemStackSnapshot = ItemStackUtil.snapshotOf(this.impl$activeItemStackCopy == null ? ItemStack.EMPTY : this.impl$activeItemStackCopy);
    final UseItemStackEvent.Replace event;
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack == null ? ItemStack.EMPTY : stack);
        final HandType handType = (HandType) (Object) hand;
        this.impl$addSelfToFrame(frame, activeItemStackSnapshot, handType);
        final Ticks useItemRemainingTicks = Ticks.of(this.useItemRemaining);
        event = SpongeEventFactory.createUseItemStackEventReplace(PhaseTracker.getCauseStackManager().currentCause(), useItemRemainingTicks, useItemRemainingTicks, activeItemStackSnapshot, new Transaction<>(ItemStackUtil.snapshotOf(this.impl$activeItemStackCopy), snapshot));
    }
    if (SpongeCommon.post(event)) {
        this.shadow$setItemInHand(hand, this.impl$activeItemStackCopy.copy());
        return;
    }
    if (!event.itemStackResult().isValid()) {
        this.shadow$setItemInHand(hand, this.impl$activeItemStackCopy.copy());
        return;
    }
    this.shadow$setItemInHand(hand, ItemStackUtil.fromSnapshotToNative(event.itemStackResult().finalReplacement()));
}
Also used : PlayerInventoryTransaction(org.spongepowered.common.event.tracking.context.transaction.inventory.PlayerInventoryTransaction) Transaction(org.spongepowered.api.data.Transaction) UseItemStackEvent(org.spongepowered.api.event.item.inventory.UseItemStackEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager) HandType(org.spongepowered.api.data.type.HandType) Ticks(org.spongepowered.api.util.Ticks) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 38 with Redirect

use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.

the class MobMixin method impl$getClosestPlayerForSpawning.

@Nullable
@Redirect(method = "checkDespawn()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getNearestPlayer(Lnet/minecraft/world/entity/Entity;D)Lnet/minecraft/world/entity/player/Player;"))
private Player impl$getClosestPlayerForSpawning(final Level world, final net.minecraft.world.entity.Entity entityIn, final double distance) {
    double bestDistance = -1.0D;
    Player result = null;
    for (final Player player : world.players()) {
        if (player == null || player.removed || !((PlayerBridge) player).bridge$affectsSpawning()) {
            continue;
        }
        final double playerDistance = player.distanceToSqr(entityIn);
        if ((distance < 0.0D || playerDistance < distance * distance) && (bestDistance == -1.0D || playerDistance < bestDistance)) {
            bestDistance = playerDistance;
            result = player;
        }
    }
    return result;
}
Also used : Player(net.minecraft.world.entity.player.Player) PlayerBridge(org.spongepowered.common.bridge.world.entity.player.PlayerBridge) Redirect(org.spongepowered.asm.mixin.injection.Redirect) Nullable(javax.annotation.Nullable)

Example 39 with Redirect

use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.

the class PlayerListMixin method impl$callRespawnPlayerRecreateEvent.

@Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V", ordinal = 1))
private void impl$callRespawnPlayerRecreateEvent(final ServerGamePacketListenerImpl serverPlayNetHandler, final Packet<?> packetIn, final net.minecraft.server.level.ServerPlayer originalPlayer, final boolean keepAllPlayerData) {
    final net.minecraft.server.level.ServerPlayer recreatedPlayer = serverPlayNetHandler.player;
    final Vector3d originalPosition = VecHelper.toVector3d(originalPlayer.position());
    final Vector3d destinationPosition = VecHelper.toVector3d(recreatedPlayer.position());
    final org.spongepowered.api.world.server.ServerWorld originalWorld = (org.spongepowered.api.world.server.ServerWorld) originalPlayer.level;
    final org.spongepowered.api.world.server.ServerWorld originalDestinationWorld = (org.spongepowered.api.world.server.ServerWorld) this.server.getLevel(this.impl$originalDestination == null ? Level.OVERWORLD : this.impl$originalDestination);
    final org.spongepowered.api.world.server.ServerWorld destinationWorld = (org.spongepowered.api.world.server.ServerWorld) this.server.getLevel(this.impl$newDestination == null ? Level.OVERWORLD : this.impl$newDestination);
    final RespawnPlayerEvent.Recreate event = SpongeEventFactory.createRespawnPlayerEventRecreate(PhaseTracker.getCauseStackManager().currentCause(), destinationPosition, originalWorld, originalPosition, destinationWorld, originalDestinationWorld, destinationPosition, (ServerPlayer) originalPlayer, (ServerPlayer) recreatedPlayer, this.impl$isGameMechanicRespawn, !keepAllPlayerData);
    SpongeCommon.post(event);
    recreatedPlayer.setPos(event.destinationPosition().x(), event.destinationPosition().y(), event.destinationPosition().z());
    this.impl$isGameMechanicRespawn = false;
    this.impl$originalDestination = null;
    this.impl$newDestination = null;
    final ServerLevel targetWorld = (ServerLevel) event.destinationWorld();
    ((ServerPlayerBridge) recreatedPlayer).bridge$sendChangeDimension(targetWorld.dimensionType(), ((ClientboundRespawnPacketAccessor) packetIn).accessor$dimension(), ((ClientboundRespawnPacketAccessor) packetIn).accessor$seed(), recreatedPlayer.gameMode.getGameModeForPlayer(), recreatedPlayer.gameMode.getPreviousGameModeForPlayer(), targetWorld.isDebug(), targetWorld.isFlat(), keepAllPlayerData);
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) RespawnPlayerEvent(org.spongepowered.api.event.entity.living.player.RespawnPlayerEvent) ServerPlayerBridge(org.spongepowered.common.bridge.server.level.ServerPlayerBridge) Vector3d(org.spongepowered.math.vector.Vector3d) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 40 with Redirect

use of org.spongepowered.asm.mixin.injection.Redirect in project SpongeCommon by SpongePowered.

the class ServerChunkCacheMixin method impl$useSerializationBehaviorWhenSaving.

// @formatter:on
@Redirect(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;saveAllChunks(Z)V"))
private void impl$useSerializationBehaviorWhenSaving(final ChunkMap chunkManager, final boolean flush) {
    final ServerLevel world = this.level;
    final SerializationBehavior serializationBehavior = ((ServerWorldProperties) world.getLevelData()).serializationBehavior();
    if (serializationBehavior == SerializationBehavior.AUTOMATIC || serializationBehavior == SerializationBehavior.MANUAL) {
        ((ChunkMapAccessor) chunkManager).invoker$saveAllChunks(flush);
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) ServerWorldProperties(org.spongepowered.api.world.server.storage.ServerWorldProperties) ChunkMapAccessor(org.spongepowered.common.accessor.server.level.ChunkMapAccessor) SerializationBehavior(org.spongepowered.api.world.SerializationBehavior) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Aggregations

Redirect (org.spongepowered.asm.mixin.injection.Redirect)165 CauseStackManager (org.spongepowered.api.event.CauseStackManager)25 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)15 ItemStack (net.minecraft.item.ItemStack)13 EffectTransactor (org.spongepowered.common.event.tracking.context.transaction.EffectTransactor)13 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)12 TransactionalCaptureSupplier (org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier)11 ArrayList (java.util.ArrayList)9 ItemStack (net.minecraft.world.item.ItemStack)9 Nullable (javax.annotation.Nullable)8 Vector3d (com.flowpowered.math.vector.Vector3d)7 World (net.minecraft.world.World)7 ServerLocation (org.spongepowered.api.world.server.ServerLocation)7 DamageSourceBridge (org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge)7 IPhaseState (org.spongepowered.common.event.tracking.IPhaseState)7 IBlockState (net.minecraft.block.state.IBlockState)6 Entity (net.minecraft.entity.Entity)6 EntityPlayer (net.minecraft.entity.player.EntityPlayer)6 ServerLevel (net.minecraft.server.level.ServerLevel)6 EntityItem (net.minecraft.entity.item.EntityItem)5