Search in sources :

Example 1 with IPhaseState

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

the class PlayerPhase method unwind.

@SuppressWarnings("unchecked")
public void unwind(IPhaseState<?> state, PhaseContext<?> phaseContext) {
    // Since currently all we have is PLAYER_LOGOUT, don't care about
    // states.
    final Player player = phaseContext.getSource(Player.class).orElseThrow(TrackingUtil.throwWithContext("Expected to be processing a player leaving, but we're not!", phaseContext));
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(player);
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DISPENSE);
        phaseContext.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(items -> {
            final ArrayList<Entity> entities = new ArrayList<>();
            for (EntityItem item : items) {
                entities.add(EntityUtil.fromNative(item));
            }
            final DropItemEvent.Dispense dispense = SpongeEventFactory.createDropItemEventDispense(Sponge.getCauseStackManager().getCurrentCause(), entities);
            SpongeImpl.postEvent(dispense);
            if (!dispense.isCancelled()) {
                for (Entity entity : dispense.getEntities()) {
                    EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
                }
            }
        });
        Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM);
        phaseContext.getCapturedItemStackSupplier().acceptAndClearIfNotEmpty(items -> {
            final List<EntityItem> drops = items.stream().map(drop -> drop.create(EntityUtil.getMinecraftWorld(player))).collect(Collectors.toList());
            final List<Entity> entities = (List<Entity>) (List<?>) drops;
            if (!entities.isEmpty()) {
                DropItemEvent.Custom event = SpongeEventFactory.createDropItemEventCustom(Sponge.getCauseStackManager().getCurrentCause(), entities);
                SpongeImpl.postEvent(event);
                if (!event.isCancelled()) {
                    for (Entity droppedItem : event.getEntities()) {
                        EntityUtil.getMixinWorld(droppedItem).forceSpawnEntity(droppedItem);
                    }
                }
            }
        });
        phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> TrackingUtil.processBlockCaptures(blocks, state, phaseContext));
    }
}
Also used : EntityItem(net.minecraft.entity.item.EntityItem) SpongeImpl(org.spongepowered.common.SpongeImpl) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) Sponge(org.spongepowered.api.Sponge) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Entity(org.spongepowered.api.entity.Entity) Collectors(java.util.stream.Collectors) EntityUtil(org.spongepowered.common.entity.EntityUtil) ArrayList(java.util.ArrayList) SpawnTypes(org.spongepowered.api.event.cause.entity.spawn.SpawnTypes) List(java.util.List) TrackingUtil(org.spongepowered.common.event.tracking.TrackingUtil) GeneralizedContext(org.spongepowered.common.event.tracking.context.GeneralizedContext) PhaseContext(org.spongepowered.common.event.tracking.PhaseContext) Player(org.spongepowered.api.entity.living.player.Player) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Entity(org.spongepowered.api.entity.Entity) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Player(org.spongepowered.api.entity.living.player.Player) ArrayList(java.util.ArrayList) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ArrayList(java.util.ArrayList) List(java.util.List) EntityItem(net.minecraft.entity.item.EntityItem)

Example 2 with IPhaseState

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

the class MixinWorldServer method onUpdateTick.

// This ticks pending updates to blocks, Requires mixin for NextTickListEntry so we use the correct tracking
@SuppressWarnings("unchecked")
@Redirect(method = "tickUpdates", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;updateTick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;Ljava/util/Random;)V"))
private void onUpdateTick(Block block, net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, Random rand) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData phaseData = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = phaseData.state;
    if (phaseState.alreadyCapturingBlockTicks(phaseData.context) || phaseState.ignoresBlockUpdateTick(phaseData)) {
        block.updateTick(worldIn, pos, state, rand);
        return;
    }
    IMixinBlock spongeBlock = (IMixinBlock) block;
    spongeBlock.getTimingsHandler().startTiming();
    TrackingUtil.updateTickBlock(this, block, pos, state, rand);
    spongeBlock.getTimingsHandler().stopTiming();
}
Also used : IMixinBlock(org.spongepowered.common.interfaces.block.IMixinBlock) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 3 with IPhaseState

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

the class MixinWorldServer method onCreateScheduledBlockUpdate.

/*@Redirect(method = "updateBlockTick",
            at = @At(value = "INVOKE", target = "Lnet/minecraft/world/NextTickListEntry;setPriority(I)V"))
    private void onUpdateScheduledBlock(NextTickListEntry sbu, int priority) {
        this.onCreateScheduledBlockUpdate(sbu, priority);
    }*/
@// really scheduleUpdate
Redirect(// really scheduleUpdate
method = "updateBlockTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/NextTickListEntry;setPriority(I)V"))
private void onCreateScheduledBlockUpdate(NextTickListEntry sbu, int priority) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final IPhaseState phaseState = phaseTracker.getCurrentState();
    if (phaseState.ignoresScheduledUpdates()) {
        this.tmpScheduledObj = sbu;
        return;
    }
    sbu.setPriority(priority);
    ((IMixinNextTickListEntry) sbu).setWorld((WorldServer) (Object) this);
    this.tmpScheduledObj = sbu;
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) IMixinNextTickListEntry(org.spongepowered.common.interfaces.IMixinNextTickListEntry) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 4 with IPhaseState

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

the class MixinWorldServer method onAddBlockEvent.

@Redirect(method = "addBlockEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/WorldServer$ServerBlockEventList;add(Ljava/lang/Object;)Z", remap = false))
private boolean onAddBlockEvent(WorldServer.ServerBlockEventList list, Object obj, BlockPos pos, Block blockIn, int eventId, int eventParam) {
    final BlockEventData blockEventData = (BlockEventData) obj;
    IMixinBlockEventData blockEvent = (IMixinBlockEventData) blockEventData;
    // This is very common with pistons as they add block events while blocks are being notified.
    if (blockIn instanceof BlockPistonBase) {
        // We only fire pre events for pistons
        if (SpongeCommonEventFactory.handlePistonEvent(this, list, obj, pos, blockIn, eventId, eventParam)) {
            return false;
        }
        blockEvent.setCaptureBlocks(false);
    // TODO BLOCK_EVENT flag
    } else if (SpongeCommonEventFactory.callChangeBlockEventPre(this, pos).isCancelled()) {
        return false;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData currentPhase = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = currentPhase.state;
    if (phaseState.ignoresBlockEvent()) {
        return list.add((BlockEventData) obj);
    }
    final PhaseContext<?> context = currentPhase.context;
    final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(this, pos.getX(), pos.getY(), pos.getZ())).state(this.getBlock(pos.getX(), pos.getY(), pos.getZ())).build();
    blockEvent.setTickBlock(locatable);
    phaseState.addNotifierToBlockEvent(context, this, pos, blockEvent);
    return list.add((BlockEventData) obj);
}
Also used : IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) BlockPistonBase(net.minecraft.block.BlockPistonBase) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) LocatableBlock(org.spongepowered.api.world.LocatableBlock) IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) BlockEventData(net.minecraft.block.BlockEventData) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 5 with IPhaseState

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

the class MixinChunkProviderServer method canDenyChunkRequest.

private boolean canDenyChunkRequest() {
    if (!SpongeImpl.getServer().isCallingFromMinecraftThread()) {
        return true;
    }
    if (this.forceChunkRequests) {
        return false;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final IPhaseState currentState = phaseTracker.getCurrentState();
    // States that cannot deny chunks
    if (currentState == TickPhase.Tick.PLAYER || currentState == TickPhase.Tick.DIMENSION || currentState == EntityPhase.State.CHANGING_DIMENSION || currentState == EntityPhase.State.LEAVING_DIMENSION) {
        return false;
    }
    // States that can deny chunks
    if (currentState == GenerationPhase.State.WORLD_SPAWNER_SPAWNING || currentState == PluginPhase.Listener.PRE_SERVER_TICK_LISTENER || currentState == PluginPhase.Listener.POST_SERVER_TICK_LISTENER) {
        return true;
    }
    // Phases that can deny chunks
    if (currentState.getPhase() == TrackingPhases.BLOCK || currentState.getPhase() == TrackingPhases.ENTITY || currentState.getPhase() == TrackingPhases.TICK) {
        return true;
    }
    return false;
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState)

Aggregations

IPhaseState (org.spongepowered.common.event.tracking.IPhaseState)26 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)20 PhaseData (org.spongepowered.common.event.tracking.PhaseData)10 Redirect (org.spongepowered.asm.mixin.injection.Redirect)7 IBlockState (net.minecraft.block.state.IBlockState)5 Overwrite (org.spongepowered.asm.mixin.Overwrite)5 BlockPos (net.minecraft.util.math.BlockPos)4 LocatableBlock (org.spongepowered.api.world.LocatableBlock)4 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)4 EntityItem (net.minecraft.entity.item.EntityItem)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 World (org.spongepowered.api.world.World)3 ArrayList (java.util.ArrayList)2 EntityLivingBase (net.minecraft.entity.EntityLivingBase)2 EntityPlayer (net.minecraft.entity.player.EntityPlayer)2 Chunk (net.minecraft.world.chunk.Chunk)2 BlockState (org.spongepowered.api.block.BlockState)2 Entity (org.spongepowered.api.entity.Entity)2 Player (org.spongepowered.api.entity.living.player.Player)2 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)2