Search in sources :

Example 61 with Redirect

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

the class EnderMan_EndermanLeaveBlockGoalMixin method impl$onPlaceBlockCancel.

/**
 * @reason Makes Endermen check for block changes before they can place their blocks.
 * This allows plugins to cancel the event regardless without issue.
 */
@Redirect(method = "canPlaceBlock(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;isCollisionShapeFullBlock(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z"))
private boolean impl$onPlaceBlockCancel(BlockState blockState, BlockGetter blockReaderIn, BlockPos blockPosIn) {
    if (blockState.isCollisionShapeFullBlock(blockReaderIn, blockPosIn)) {
        // Sponge start
        if (ShouldFire.CHANGE_BLOCK_EVENT_PRE) {
            final ServerLocation location = ServerLocation.of((ServerWorld) blockReaderIn, blockPosIn.getX(), blockPosIn.getY(), blockPosIn.getZ());
            final List<ServerLocation> list = new ArrayList<>(1);
            list.add(location);
            final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
            final ChangeBlockEvent.Pre event = SpongeEventFactory.createChangeBlockEventPre(cause, list, ((ServerWorld) this.enderman.level));
            return !SpongeCommon.post(event);
        }
        // Sponge end
        return true;
    }
    return false;
}
Also used : ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) ServerWorld(org.spongepowered.api.world.server.ServerWorld) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Cause(org.spongepowered.api.event.Cause) ArrayList(java.util.ArrayList) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 62 with Redirect

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

the class AbstractFurnaceBlockEntityMixin method impl$throwFuelEventIfOrShrink.

// @Formatter:on
// Shrink Fuel
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V"))
private void impl$throwFuelEventIfOrShrink(final ItemStack itemStack, final int quantity) {
    final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
    final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(itemStack);
    final ItemStackSnapshot shrinkedFuel = ItemStackUtil.snapshotOf(ItemStackUtil.cloneDefensive(itemStack, itemStack.getCount() - 1));
    final Transaction<ItemStackSnapshot> transaction = new Transaction<>(fuel, shrinkedFuel);
    final AbstractCookingRecipe recipe = this.impl$getCurrentRecipe();
    final CookingEvent.ConsumeFuel event = SpongeEventFactory.createCookingEventConsumeFuel(cause, (FurnaceBlockEntity) this, Optional.of(fuel), Optional.of((CookingRecipe) recipe), Collections.singletonList(transaction));
    SpongeCommon.post(event);
    if (event.isCancelled()) {
        this.cookingTotalTime = 0;
        return;
    }
    if (!transaction.isValid()) {
        return;
    }
    if (transaction.custom().isPresent()) {
        this.items.set(1, ItemStackUtil.fromSnapshotToNative(transaction.finalReplacement()));
    } else {
        // vanilla
        itemStack.shrink(quantity);
    }
}
Also used : Transaction(org.spongepowered.api.data.Transaction) CookingRecipe(org.spongepowered.api.item.recipe.cooking.CookingRecipe) AbstractCookingRecipe(net.minecraft.world.item.crafting.AbstractCookingRecipe) Cause(org.spongepowered.api.event.Cause) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) AbstractCookingRecipe(net.minecraft.world.item.crafting.AbstractCookingRecipe) CookingEvent(org.spongepowered.api.event.block.entity.CookingEvent) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 63 with Redirect

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

the class CactusBlockMixin method impl$reAssignForBlockDamageSource.

@Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private boolean impl$reAssignForBlockDamageSource(final Entity self, final DamageSource source, float damage, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.level.Level world, final BlockPos pos, final Entity entity) {
    if (world.isClientSide()) {
        return entity.hurt(source, damage);
    }
    try {
        final ServerLocation location = ServerLocation.of((ServerWorld) world, pos.getX(), pos.getY(), pos.getZ());
        final MinecraftBlockDamageSource cactus = new MinecraftBlockDamageSource("cactus", location);
        ((DamageSourceBridge) (Object) cactus).bridge$setCactusSource();
        return entity.hurt(DamageSource.CACTUS, damage);
    } finally {
        ((DamageSourceBridge) source).bridge$setCactusSource();
    }
}
Also used : DamageSourceBridge(org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge) ServerLocation(org.spongepowered.api.world.server.ServerLocation) MinecraftBlockDamageSource(org.spongepowered.common.util.MinecraftBlockDamageSource) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 64 with Redirect

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

the class FishingRodItemMixin method onNewEntityFishHook.

@Redirect(method = "use", at = @At(value = "NEW", target = "net/minecraft/world/entity/projectile/FishingHook"))
private FishingHook onNewEntityFishHook(Player p_i50220_1_, Level p_i50220_2_, int p_i50220_3_, int p_i50220_4_) {
    // Use the fish hook we created for the event
    FishingHook fishHook = this.impl$fishHook;
    this.impl$fishHook = null;
    return fishHook;
}
Also used : FishingHook(net.minecraft.world.entity.projectile.FishingHook) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 65 with Redirect

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

the class BoneMealItemMixin_Tracker method tracker$wrapGrowWithPhaseEntry.

/**
 * @author gabizou - March 20th, 2019 - 1.12.2
 * @reason To allow growing to be captured via bonemeal without
 * explicitly attempting to capture the growth, we can enter an
 * alternate phase blockState that will specifically track the block
 * changes as growth, and therefor will be able to throw
 * {@link ChangeBlockEvent.Grow} without specifying the cases
 * where the phase blockState needs to throw the event during another
 * phases's capturing.
 */
@SuppressWarnings({ "Duplicates" })
// @Group(name = "org.spongepowered.tracker:bonemeal", min = 1, max = 1)
@Redirect(method = "growCrop", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BonemealableBlock;performBonemeal(Lnet/minecraft/server/level/ServerLevel;Ljava/util/Random;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V"), // Will be removed once the above github issue is resolved with a proper solution
require = 0, // Even though we're in a group, expecting this to succeed in forge environments will not work since there is a different mixin
expect = 0)
private static void tracker$wrapGrowWithPhaseEntry(final BonemealableBlock iGrowable, final ServerLevel worldIn, final Random rand, final BlockPos pos, final BlockState state, final ItemStack stack) {
    if (((LevelBridge) worldIn).bridge$isFake() || !ShouldFire.CHANGE_BLOCK_EVENT_ALL) {
        iGrowable.performBonemeal(worldIn, rand, pos, state);
        return;
    }
    final PhaseContext<@NonNull ?> current = PhaseTracker.getInstance().getPhaseContext();
    final boolean doesEvent = current.doesBlockEventTracking();
    if (doesEvent) {
        // We can enter the new phase state.
        try (final GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(PhaseTracker.SERVER).provideItem(stack).world(worldIn).block(state).pos(pos)) {
            context.buildAndSwitch();
            iGrowable.performBonemeal(worldIn, rand, pos, state);
        }
    }
}
Also used : GrowablePhaseContext(org.spongepowered.common.event.tracking.phase.block.GrowablePhaseContext) 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