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());
}
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));
}
}
}
}
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));
}
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);
}
}
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);
}
Aggregations