Search in sources :

Example 61 with PhaseTracker

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

the class BlockWorkerPhaseState method switchIfNecessary.

@Nullable
public PhaseContext<@NonNull ?> switchIfNecessary(final PhaseTracker server) {
    final PhaseTracker instance = PhaseTracker.getInstance();
    if (!server.onSidedThread()) {
        return null;
    }
    final IPhaseState<@NonNull ?> currentState = instance.getCurrentState();
    if (currentState.isApplyingStreams()) {
        return null;
    }
    return this.createPhaseContext(server);
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 62 with PhaseTracker

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

the class SpongeVolumeStream method apply.

@Override
public <W extends MutableVolume> void apply(final VolumeCollector<W, T, ?> collector) {
    final PhaseTracker instance = PhaseTracker.getInstance();
    try (@Nullable final PhaseContext<@NonNull ?> context = instance.getPhaseContext().isApplyingStreams() ? null : PluginPhase.State.VOLUME_STREAM_APPLICATION.createPhaseContext(instance).setVolumeStream(this).spawnType(() -> PhaseTracker.getCauseStackManager().context(EventContextKeys.SPAWN_TYPE).orElse(null))) {
        if (context != null) {
            context.buildAndSwitch();
        }
        this.stream.forEach(element -> {
            final W targetVolume = collector.target().get();
            final VolumeElement<W, T> transformed = collector.positionTransform().apply(VolumeElement.of(collector.target(), element::type, element.position()));
            collector.applicator().apply(targetVolume, transformed);
        });
    }
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 63 with PhaseTracker

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

the class ServerLevelMixin_Tracker method shadow$neighborChanged.

@Override
public void shadow$neighborChanged(final BlockPos pos, final Block blockIn, final BlockPos fromPos) {
    final BlockPos immutableTarget = pos.immutable();
    final BlockPos immutableFrom = fromPos.immutable();
    // Sponge Start - Check asynchronicity,
    // if not on the server thread and we're a server world, we've got problems...
    final PhaseTracker server = PhaseTracker.SERVER;
    if (server.getSidedThread() != Thread.currentThread()) {
        // lol no, report the block change properly
        new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr().addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS).add().add(new Exception("Async Block Notifcation Detected")).log(SpongeCommon.logger(), Level.ERROR);
        // Maybe? I don't think this is wise to try and sync back a notification on the main thread.
        return;
    }
    // world that Sponge isn't directly managing, so we'll just ignore trying to record on those.
    if (this.bridge$isFake()) {
        // If we're fake, well, we could effectively call this without recording on worlds we don't
        // want to care about.
        super.shadow$neighborChanged(immutableTarget, blockIn, immutableFrom);
        return;
    }
    // Otherwise, we continue with recording, maybe.
    final LevelChunk targetChunk = this.shadow$getChunkAt(immutableTarget);
    final BlockState targetBlockState = targetChunk.getBlockState(immutableTarget);
    // Sponge - Shortcircuit if the block has no neighbor logic
    if (!((TrackableBlockBridge) targetBlockState.getBlock()).bridge$overridesNeighborNotificationLogic()) {
        return;
    }
    // Sponge End
    // Sponge start - prepare notification
    final PhaseContext<@NonNull ?> peek = server.getPhaseContext();
    // try { // Vanilla - We need to push the effect transactor so that it always pops
    try {
        final Supplier<ServerLevel> worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier((ServerLevel) (Object) this, "ServerWorld");
        final net.minecraft.world.level.block.entity.@Nullable BlockEntity existingTile = targetChunk.getBlockEntity(immutableTarget, LevelChunk.EntityCreationType.CHECK);
        peek.getTransactor().logNeighborNotification(worldSupplier, immutableFrom, blockIn, immutableTarget, targetBlockState, existingTile);
        peek.associateNeighborStateNotifier(immutableFrom, targetBlockState.getBlock(), immutableTarget, ((ServerLevel) (Object) this), PlayerTracker.Type.NOTIFIER);
        // Sponge End
        targetBlockState.neighborChanged(((ServerLevel) (Object) this), immutableTarget, blockIn, immutableFrom, false);
    } catch (final Throwable throwable) {
        final CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours");
        final CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated");
        crashreportcategory.setDetail("Source block type", () -> {
            try {
                return String.format("ID #%d (%s // %s)", Registry.BLOCK.getId(blockIn), blockIn.getDescriptionId(), blockIn.getClass().getCanonicalName());
            } catch (final Throwable var2) {
                return "ID #" + Registry.BLOCK.getId(blockIn);
            }
        });
        CrashReportCategory.populateBlockDetails(crashreportcategory, immutableTarget, targetBlockState);
        throw new ReportedException(crashreport);
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) CrashReport(net.minecraft.CrashReport) ReportedException(net.minecraft.ReportedException) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState) BlockPos(net.minecraft.core.BlockPos) Nullable(org.checkerframework.checker.nullness.qual.Nullable) CrashReportCategory(net.minecraft.CrashReportCategory) ReportedException(net.minecraft.ReportedException)

Example 64 with PhaseTracker

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

the class ServerLevelMixin_Tracker method tracker$throwPreEventAndRecord.

@Inject(method = "addEntity(Lnet/minecraft/world/entity/Entity;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getX()D"), cancellable = true)
private void tracker$throwPreEventAndRecord(final Entity entityIn, final CallbackInfoReturnable<Boolean> cir) {
    if (this.bridge$isFake()) {
        return;
    }
    final PhaseTracker tracker = PhaseTracker.SERVER;
    if (tracker.getSidedThread() != Thread.currentThread()) {
        // TODO - async entity spawn logging
        return;
    }
    final PhaseContext<@NonNull ?> current = tracker.getPhaseContext();
    if (!current.doesAllowEntitySpawns()) {
        cir.setReturnValue(false);
        return;
    }
    try (final CauseStackManager.StackFrame frame = tracker.pushCauseFrame()) {
        final List<org.spongepowered.api.entity.Entity> entities = new ArrayList<>();
        entities.add((org.spongepowered.api.entity.Entity) entityIn);
        frame.addContext(EventContextKeys.SPAWN_TYPE, current.getSpawnTypeForTransaction(entityIn));
        final SpawnEntityEvent.Pre pre = SpongeEventFactory.createSpawnEntityEventPre(frame.currentCause(), entities);
        Sponge.eventManager().post(pre);
        if (pre.isCancelled() || entities.isEmpty()) {
            cir.setReturnValue(false);
            return;
        }
    }
    if (current.allowsBulkEntityCaptures()) {
        current.getTransactor().logEntitySpawn(current, this, entityIn);
    }
}
Also used : TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) RemoveBlockEntity(org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) Entity(net.minecraft.world.entity.Entity) ArrayList(java.util.ArrayList) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 65 with PhaseTracker

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

the class EntityMixin_Tracker method tracker$ensureDropEffectCompleted.

@Inject(method = "remove()V", at = @At("RETURN"))
private void tracker$ensureDropEffectCompleted(final CallbackInfo ci) {
    final PhaseTracker instance = PhaseTracker.SERVER;
    if (!instance.onSidedThread()) {
        return;
    }
    if (((LevelBridge) this.level).bridge$isFake()) {
        return;
    }
    final PhaseContext<@NonNull ?> context = instance.getPhaseContext();
    if (!context.doesBlockEventTracking()) {
        return;
    }
    if (this.tracker$dropsTransactor != null) {
        this.tracker$dropsTransactor.close();
    }
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) Inject(org.spongepowered.asm.mixin.injection.Inject)

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