Search in sources :

Example 21 with PhaseTracker

use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method createChangeBlockEventPlace.

public static ChangeBlockEvent.Place createChangeBlockEventPlace(BlockEvent.MultiPlaceEvent forgeEvent) {
    final net.minecraft.world.World world = forgeEvent.getWorld();
    if (world.isRemote) {
        return null;
    }
    ImmutableList.Builder<Transaction<BlockSnapshot>> builder = new ImmutableList.Builder<Transaction<BlockSnapshot>>();
    for (net.minecraftforge.common.util.BlockSnapshot blockSnapshot : forgeEvent.getReplacedBlockSnapshots()) {
        final BlockPos snapshotPos = blockSnapshot.getPos();
        BlockSnapshot originalSnapshot = ((IMixinBlockSnapshot) blockSnapshot).createSpongeBlockSnapshot();
        BlockSnapshot finalSnapshot = ((World) world).createSnapshot(snapshotPos.getX(), snapshotPos.getY(), snapshotPos.getZ());
        builder.add(new Transaction<>(originalSnapshot, finalSnapshot));
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    EntityPlayer player = forgeEvent.getPlayer();
    if (SpongeImplHooks.isFakePlayer(player)) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
    } else if (Sponge.getCauseStackManager().getCurrentCause() == null) {
        Sponge.getCauseStackManager().pushCause(player);
    }
    if (owner != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(owner);
        }
    } else {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(player);
        }
    }
    if (notifier != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
    }
    return SpongeEventFactory.createChangeBlockEventPlace(Sponge.getCauseStackManager().getCurrentCause(), builder.build());
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) ImmutableList(com.google.common.collect.ImmutableList) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Transaction(org.spongepowered.api.data.Transaction) EntityPlayer(net.minecraft.entity.player.EntityPlayer) BlockPos(net.minecraft.util.math.BlockPos) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot)

Example 22 with PhaseTracker

use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.

the class TransactionalCaptureSupplier method generateEventForTransaction.

@SuppressWarnings("unchecked")
private static <E extends Event & Cancellable> void generateEventForTransaction(@NonNull final GameTransaction<E> pointer, @Nullable final GameTransaction<@NonNull ?> parent, final PhaseContext<@NonNull ?> context, final ImmutableList.Builder<EventByTransaction<@NonNull ?>> builder, final ImmutableList<GameTransaction<E>> transactions, final ImmutableMultimap.Builder<TransactionType, ? extends Event> transactionPostEventBuilder) {
    final Optional<BiConsumer<PhaseContext<@NonNull ?>, CauseStackManager.StackFrame>> frameMutator = pointer.getFrameMutator(parent);
    final PhaseTracker instance = PhaseTracker.getInstance();
    try (final CauseStackManager.StackFrame frame = frameMutator.map(mutator -> {
        final CauseStackManager.StackFrame transactionFrame = instance.pushCauseFrame();
        mutator.accept(context, transactionFrame);
        return transactionFrame;
    }).orElseGet(instance::pushCauseFrame)) {
        final Optional<E> generatedEvent = pointer.generateEvent(context, parent, transactions, instance.currentCause());
        generatedEvent.ifPresent(e -> {
            final EventByTransaction<E> element = new EventByTransaction<>(e, transactions, parent, pointer);
            builder.add(element);
            ((ImmutableMultimap.Builder) transactionPostEventBuilder).put(pointer.getTransactionType(), e);
        });
        for (final GameTransaction<E> transaction : transactions) {
            if (transaction.sideEffects == null || transaction.sideEffects.isEmpty()) {
                continue;
            }
            generatedEvent.ifPresent(frame::pushCause);
            for (final ResultingTransactionBySideEffect sideEffect : transaction.sideEffects) {
                if (sideEffect.head == null) {
                    continue;
                }
                builder.addAll(TransactionalCaptureSupplier.batchTransactions(sideEffect.head, pointer, context, transactionPostEventBuilder));
            }
        }
    }
}
Also used : NonNull(org.checkerframework.checker.nullness.qual.NonNull) Iterator(java.util.Iterator) Event(org.spongepowered.api.event.Event) Spliterators(java.util.Spliterators) Sponge(org.spongepowered.api.Sponge) SpongeCommon(org.spongepowered.common.SpongeCommon) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) PrepareBlockDrops(org.spongepowered.common.event.tracking.context.transaction.effect.PrepareBlockDrops) Objects(java.util.Objects) ImmutableList(com.google.common.collect.ImmutableList) Cancellable(org.spongepowered.api.event.Cancellable) ICaptureSupplier(org.spongepowered.common.event.tracking.context.ICaptureSupplier) PhaseContext(org.spongepowered.common.event.tracking.PhaseContext) StringJoiner(java.util.StringJoiner) BiConsumer(java.util.function.BiConsumer) Optional(java.util.Optional) TransactionType(org.spongepowered.common.event.tracking.context.transaction.type.TransactionType) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Collections(java.util.Collections) Spliterator(java.util.Spliterator) Nullable(org.checkerframework.checker.nullness.qual.Nullable) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BiConsumer(java.util.function.BiConsumer)

Example 23 with PhaseTracker

use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.

the class ServerLevelMixin_Tracker method bridge$startBlockChange.

@Override
public Optional<WorldPipeline.Builder> bridge$startBlockChange(final BlockPos pos, final BlockState newState, final int flags) {
    if (net.minecraft.world.level.Level.isOutsideBuildHeight(pos)) {
        return Optional.empty();
    } else if (this.shadow$isDebug()) {
        // isClientSide is always false since this is WorldServer
        return Optional.empty();
    }
    // Sponge Start - Sanity check against the PhaseTracker for instances
    if (this.bridge$isFake()) {
        return Optional.empty();
    }
    final PhaseTracker instance = PhaseTracker.getInstance();
    if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
        throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
    }
    final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags);
    final LevelChunk chunk = this.shadow$getChunkAt(pos);
    if (chunk.isEmpty()) {
        return Optional.empty();
    }
    final net.minecraft.world.level.block.state.BlockState currentState = chunk.getBlockState(pos);
    return Optional.of(this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState)

Example 24 with PhaseTracker

use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.

the class ServerLevelMixin_Tracker method destroyBlock.

@Override
public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final Entity p_241212_3_, final int limit) {
    final BlockState currentState = this.shadow$getBlockState(pos);
    if (currentState.isAir()) {
        return false;
    } else {
        // Sponge Start - Sanity check against the PhaseTracker for instances
        if (this.bridge$isFake()) {
            return super.destroyBlock(pos, doDrops, p_241212_3_, limit);
        }
        final PhaseTracker instance = PhaseTracker.getInstance();
        if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
            throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
        }
        final FluidState fluidstate = this.shadow$getFluidState(pos);
        final BlockState emptyBlock = fluidstate.createLegacyBlock();
        final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(3);
        final LevelChunk chunk = this.shadow$getChunkAt(pos);
        if (chunk.isEmpty()) {
            return false;
        }
        final WorldPipeline.Builder pipelineBuilder = this.bridge$makePipeline(pos, currentState, emptyBlock, chunk, spongeFlag, limit).addEffect(WorldDestroyBlockLevelEffect.getInstance());
        if (doDrops) {
            pipelineBuilder.addEffect(PerformBlockDropsFromDestruction.getInstance());
        }
        final WorldPipeline pipeline = pipelineBuilder.addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
        return pipeline.processEffects(instance.getPhaseContext(), currentState, emptyBlock, pos, p_241212_3_, spongeFlag, limit);
    }
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) BlockState(net.minecraft.world.level.block.state.BlockState) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) WorldPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline) FluidState(net.minecraft.world.level.material.FluidState)

Example 25 with PhaseTracker

use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.

the class ServerLevelMixin_Tracker method setBlock.

/**
 * @author gabizou, March 12th, 2016
 * <p>
 * Move this into WorldServer as we should not be modifying the client world.
 * <p>
 * Purpose: Rewritten to support capturing blocks
 */
@Override
public boolean setBlock(final BlockPos pos, final net.minecraft.world.level.block.state.BlockState newState, final int flags, final int limit) {
    if (net.minecraft.world.level.Level.isOutsideBuildHeight(pos)) {
        return false;
    } else if (this.shadow$isDebug()) {
        // isClientSide is always false since this is WorldServer
        return false;
    }
    // Sponge Start - Sanity check against the PhaseTracker for instances
    if (this.bridge$isFake()) {
        return super.setBlock(pos, newState, flags, limit);
    }
    final PhaseTracker instance = PhaseTracker.getInstance();
    if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
        throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
    }
    final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags);
    final LevelChunk chunk = this.shadow$getChunkAt(pos);
    if (chunk.isEmpty()) {
        return false;
    }
    final net.minecraft.world.level.block.state.BlockState currentState = chunk.getBlockState(pos);
    // change of "don't do anything if the block is the same".
    if (currentState == newState) {
        return false;
    }
    final WorldPipeline pipeline = this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, limit).addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
    return pipeline.processEffects(instance.getPhaseContext(), currentState, newState, pos, null, spongeFlag, limit);
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState) WorldPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline)

Aggregations

PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)67 PhaseData (org.spongepowered.common.event.tracking.PhaseData)22 IPhaseState (org.spongepowered.common.event.tracking.IPhaseState)20 BlockPos (net.minecraft.util.math.BlockPos)15 CauseStackManager (org.spongepowered.api.event.CauseStackManager)15 World (org.spongepowered.api.world.World)12 Redirect (org.spongepowered.asm.mixin.injection.Redirect)12 IBlockState (net.minecraft.block.state.IBlockState)11 EntityPlayer (net.minecraft.entity.player.EntityPlayer)11 User (org.spongepowered.api.entity.living.player.User)11 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)10 Inject (org.spongepowered.asm.mixin.injection.Inject)10 ArrayList (java.util.ArrayList)8 Overwrite (org.spongepowered.asm.mixin.Overwrite)8 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)8 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)7 BlockState (org.spongepowered.api.block.BlockState)6 LocatableBlock (org.spongepowered.api.world.LocatableBlock)6 Location (org.spongepowered.api.world.Location)6 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)6