Search in sources :

Example 56 with Redirect

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

the class ServerPlayerMixin_Tracker method tracker$throwItemDrop.

/**
 * @author gabizou - June 4th, 2016
 * @author i509VCB - February 17th, 2020 - 1.14.4
 * @author gabizou - December 31st, 2021 - 1.16.5
 * @reason We inject a construct event for the item drop and conveniently
 * can redirect the super call.
 */
@Redirect(method = "drop", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;"))
@Nullable
private ItemEntity tracker$throwItemDrop(final Player thisPlayer, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem) {
    if (droppedItem.isEmpty()) {
        return null;
    }
    if (((PlatformEntityBridge) this).bridge$isFakePlayer()) {
        return super.shadow$drop(droppedItem, dropAround, traceItem);
    }
    if (((LevelBridge) this.level).bridge$isFake()) {
        return super.shadow$drop(droppedItem, dropAround, traceItem);
    }
    final double posX1 = this.shadow$getX();
    final double posY1 = this.shadow$getEyeY() - (double) 0.3F;
    final double posZ1 = this.shadow$getZ();
    // Now the real fun begins.
    final ItemStack item;
    final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(droppedItem);
    final List<ItemStackSnapshot> original = new ArrayList<>();
    original.add(snapshot);
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        item = SpongeCommonEventFactory.throwDropItemAndConstructEvent((ServerPlayer) (Object) this, posX1, posY1, posZ1, snapshot, original, frame);
        if (item == null || item.isEmpty()) {
            return null;
        }
        // Here is where we would potentially perform item pre-merging (merge the item stacks with previously captured item stacks
        // and only if those stacks can be stacked (count increased). Otherwise, we'll just continue to throw the entity item.
        // For now, due to refactoring a majority of all of this code, pre-merging is disabled entirely.
        final ItemEntity itemEntity = new ItemEntity(this.level, posX1, posY1, posZ1, droppedItem);
        itemEntity.setPickUpDelay(40);
        if (traceItem) {
            itemEntity.setThrower(this.shadow$getUUID());
        }
        final Random random = this.shadow$getRandom();
        if (dropAround) {
            final float f = random.nextFloat() * 0.5F;
            final float f1 = random.nextFloat() * ((float) Math.PI * 2F);
            itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
        } else {
            final float f8 = Mth.sin(this.xRot * ((float) Math.PI / 180F));
            final float f2 = Mth.cos(this.xRot * ((float) Math.PI / 180F));
            final float f3 = Mth.sin(this.yRot * ((float) Math.PI / 180F));
            final float f4 = Mth.cos(this.yRot * ((float) Math.PI / 180F));
            final float f5 = this.random.nextFloat() * ((float) Math.PI * 2F);
            final float f6 = 0.02F * this.random.nextFloat();
            itemEntity.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos(f5) * (double) f6, (-f8 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin(f5) * (double) f6);
        }
        return itemEntity;
    }
}
Also used : ItemEntity(net.minecraft.world.entity.item.ItemEntity) ArrayList(java.util.ArrayList) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) Random(java.util.Random) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ServerPlayer(net.minecraft.server.level.ServerPlayer) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.world.item.ItemStack) Redirect(org.spongepowered.asm.mixin.injection.Redirect) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 57 with Redirect

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

the class PlayerListMixin_Tracker method tracker$trackPlayerLogoutThroughPhaseTracker.

@Redirect(method = "remove", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;removePlayerImmediately(Lnet/minecraft/server/level/ServerPlayer;)V"))
private void tracker$trackPlayerLogoutThroughPhaseTracker(final ServerLevel world, final ServerPlayer player) {
    try (final GeneralizedContext context = PlayerPhase.State.PLAYER_LOGOUT.createPhaseContext(PhaseTracker.SERVER).source(player)) {
        context.buildAndSwitch();
        world.removePlayerImmediately(player);
    }
}
Also used : GeneralizedContext(org.spongepowered.common.event.tracking.context.GeneralizedContext) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 58 with Redirect

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

the class LivingEntityMixin_Tracker method tracker$enterDeathPhase.

/**
 * @author i509VCB
 * @author gabizou
 *
 * @reason We can enter in to the entity drops transaction here which will
 * successfully batch the side effects (this is effectively a singular side
 * effect/transaction instead of a pipeline) to perform some things around
 * the entity's death. This successfully records the transactions associated
 * with this entity entering into the death state.
 */
@Redirect(method = "baseTick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;tickDeath()V"))
private void tracker$enterDeathPhase(final LivingEntity livingEntity) {
    final PhaseTracker instance = PhaseTracker.SERVER;
    if (!instance.onSidedThread()) {
        this.shadow$tickDeath();
        return;
    }
    if (((LevelBridge) this.level).bridge$isFake()) {
        this.shadow$tickDeath();
        return;
    }
    final PhaseContext<@NonNull ?> context = instance.getPhaseContext();
    if (!context.doesBlockEventTracking()) {
        this.shadow$tickDeath();
        return;
    }
    try (final EffectTransactor ignored = context.getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) {
        this.shadow$tickDeath();
    }
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) EffectTransactor(org.spongepowered.common.event.tracking.context.transaction.EffectTransactor) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 59 with Redirect

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

the class CampfireBlockMixin method impl$spongeRedirectForFireDamage.

@Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private boolean impl$spongeRedirectForFireDamage(final Entity self, final DamageSource source, final float damage, final BlockState blockState, final Level world, final BlockPos blockPos, final Entity entity) {
    if (self.level.isClientSide) {
        // Short Circuit
        return self.hurt(source, damage);
    }
    try {
        final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ());
        final DamageSource fire = MinecraftBlockDamageSource.ofFire("inFire", location, true);
        ((DamageSourceBridge) fire).bridge$setFireSource();
        return self.hurt(DamageSource.IN_FIRE, damage);
    } finally {
        // Since "source" is already the DamageSource.IN_FIRE object, we can re-use it to re-assign.
        ((DamageSourceBridge) source).bridge$setFireSource();
    }
}
Also used : DamageSource(net.minecraft.world.damagesource.DamageSource) MinecraftBlockDamageSource(org.spongepowered.common.util.MinecraftBlockDamageSource) DamageSourceBridge(org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 60 with Redirect

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

the class FallingBlockMixin method impl$checkFallable.

@Redirect(method = "tick(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Ljava/util/Random;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;getY()I"))
public int impl$checkFallable(final BlockPos pos, final BlockState state, final ServerLevel world, final BlockPos samePos, final Random random, final CallbackInfo ci) {
    if (pos.getY() < 0) {
        return pos.getY();
    }
    if (!ShouldFire.CONSTRUCT_ENTITY_EVENT_PRE) {
        return pos.getY();
    }
    final EntityType<org.spongepowered.api.entity.FallingBlock> fallingBlock = EntityTypes.FALLING_BLOCK.get();
    final org.spongepowered.api.world.server.ServerWorld spongeWorld = (org.spongepowered.api.world.server.ServerWorld) world;
    final BlockSnapshot snapshot = spongeWorld.createSnapshot(pos.getX(), pos.getY(), pos.getZ());
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(snapshot);
        frame.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.FALLING_BLOCK);
        final ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(frame.currentCause(), ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) world, pos.getX() + 0.5D, pos.getY(), pos.getZ() + 0.5D), new Vector3d(0, 0, 0), fallingBlock);
        if (SpongeCommon.post(event)) {
            return -1;
        }
        return pos.getY();
    }
}
Also used : BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) FallingBlock(net.minecraft.world.level.block.FallingBlock) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) Vector3d(org.spongepowered.math.vector.Vector3d) CauseStackManager(org.spongepowered.api.event.CauseStackManager) 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