Search in sources :

Example 31 with PhaseTracker

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

the class SpongeCommonEventFactory method callNotifyNeighborEvent.

@SuppressWarnings("rawtypes")
public static NotifyNeighborBlockEvent callNotifyNeighborEvent(World world, BlockPos sourcePos, EnumSet notifiedSides) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData peek = phaseTracker.getCurrentPhaseData();
    final PhaseContext<?> context = peek.context;
    // Don't fire notify events during world gen or while restoring
    if (peek.state.isWorldGeneration() || peek.state == State.RESTORING_BLOCKS) {
        return null;
    }
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        final BlockState blockstate = (BlockState) ((net.minecraft.world.World) world).getBlockState(sourcePos);
        final LocatableBlock locatable = LocatableBlock.builder().location(new Location<World>(world, sourcePos.getX(), sourcePos.getY(), sourcePos.getZ())).state(blockstate).build();
        if (context.getNotifier().isPresent()) {
            context.addNotifierAndOwnerToCauseStack();
        } else {
            final IMixinChunk mixinChunk = (IMixinChunk) ((WorldServer) world).getChunkFromBlockCoords(sourcePos);
            mixinChunk.getBlockNotifier(sourcePos).ifPresent(user -> Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, user));
            mixinChunk.getBlockOwner(sourcePos).ifPresent(owner -> Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner));
        }
        Sponge.getCauseStackManager().pushCause(locatable);
        final Map<Direction, BlockState> neighbors = new HashMap<>();
        for (Object obj : notifiedSides) {
            EnumFacing notifiedSide = (EnumFacing) obj;
            BlockPos offset = sourcePos.offset(notifiedSide);
            Direction direction = DirectionFacingProvider.getInstance().getKey(notifiedSide).get();
            Location<World> location = new Location<>(world, VecHelper.toVector3i(offset));
            if (location.getBlockY() >= 0 && location.getBlockY() <= 255) {
                neighbors.put(direction, location.getBlock());
            }
        }
        // ImmutableMap<Direction, BlockState> originalNeighbors =
        // ImmutableMap.copyOf(neighbors);
        NotifyNeighborBlockEvent event = SpongeEventFactory.createNotifyNeighborBlockEvent(Sponge.getCauseStackManager().getCurrentCause(), neighbors, neighbors);
        SpongeImpl.postEvent(event);
        return event;
    }
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) HashMap(java.util.HashMap) EnumFacing(net.minecraft.util.EnumFacing) World(org.spongepowered.api.world.World) Direction(org.spongepowered.api.util.Direction) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) NotifyNeighborBlockEvent(org.spongepowered.api.event.block.NotifyNeighborBlockEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LocatableBlock(org.spongepowered.api.world.LocatableBlock) IInteractionObject(net.minecraft.world.IInteractionObject) BlockPos(net.minecraft.util.math.BlockPos) Location(org.spongepowered.api.world.Location)

Example 32 with PhaseTracker

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

the class SpongeCommonEventFactory method callCollideEntityEvent.

@SuppressWarnings("unchecked")
@Nullable
public static CollideEntityEvent callCollideEntityEvent(net.minecraft.world.World world, @Nullable net.minecraft.entity.Entity sourceEntity, List<net.minecraft.entity.Entity> entities) {
    PhaseTracker phaseTracker = PhaseTracker.getInstance();
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        if (sourceEntity != null) {
            Sponge.getCauseStackManager().pushCause(sourceEntity);
        } else {
            PhaseContext<?> context = phaseTracker.getCurrentContext();
            final Optional<LocatableBlock> currentTickingBlock = context.getSource(LocatableBlock.class);
            if (currentTickingBlock.isPresent()) {
                Sponge.getCauseStackManager().pushCause(currentTickingBlock.get());
            } else {
                final Optional<TileEntity> currentTickingTileEntity = context.getSource(TileEntity.class);
                if (currentTickingTileEntity.isPresent()) {
                    Sponge.getCauseStackManager().pushCause(currentTickingTileEntity.get());
                } else {
                    final Optional<Entity> currentTickingEntity = context.getSource(Entity.class);
                    if (currentTickingEntity.isPresent()) {
                        Sponge.getCauseStackManager().pushCause(currentTickingEntity.get());
                    } else {
                        return null;
                    }
                }
            }
        }
        phaseTracker.getCurrentPhaseData().context.addNotifierAndOwnerToCauseStack();
        List<Entity> spEntities = (List<Entity>) (List<?>) entities;
        CollideEntityEvent event = SpongeEventFactory.createCollideEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), spEntities);
        SpongeImpl.postEvent(event);
        return event;
    }
}
Also used : Entity(org.spongepowered.api.entity.Entity) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) CollideEntityEvent(org.spongepowered.api.event.entity.CollideEntityEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LocatableBlock(org.spongepowered.api.world.LocatableBlock) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Nullable(javax.annotation.Nullable)

Example 33 with PhaseTracker

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

the class SpongeCommonEventFactory method handleCollideImpactEvent.

public static boolean handleCollideImpactEvent(net.minecraft.entity.Entity projectile, @Nullable ProjectileSource projectileSource, RayTraceResult movingObjectPosition) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    RayTraceResult.Type movingObjectType = movingObjectPosition.typeOfHit;
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(projectile);
        Sponge.getCauseStackManager().addContext(EventContextKeys.PROJECTILE_SOURCE, projectileSource == null ? ProjectileSource.UNKNOWN : projectileSource);
        final Optional<User> owner = phaseTracker.getCurrentPhaseData().context.getOwner();
        owner.ifPresent(user -> Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, user));
        Location<World> impactPoint = new Location<>((World) projectile.world, VecHelper.toVector3d(movingObjectPosition.hitVec));
        boolean cancelled = false;
        if (movingObjectType == RayTraceResult.Type.BLOCK) {
            final BlockPos blockPos = movingObjectPosition.getBlockPos();
            if (blockPos.getY() <= 0) {
                return false;
            }
            BlockSnapshot targetBlock = ((World) projectile.world).createSnapshot(VecHelper.toVector3i(movingObjectPosition.getBlockPos()));
            Direction side = Direction.NONE;
            if (movingObjectPosition.sideHit != null) {
                side = DirectionFacingProvider.getInstance().getKey(movingObjectPosition.sideHit).get();
            }
            CollideBlockEvent.Impact event = SpongeEventFactory.createCollideBlockEventImpact(Sponge.getCauseStackManager().getCurrentCause(), impactPoint, targetBlock.getState(), targetBlock.getLocation().get(), side);
            cancelled = SpongeImpl.postEvent(event);
            // Track impact block if event is not cancelled
            if (!cancelled && owner.isPresent()) {
                BlockPos targetPos = VecHelper.toBlockPos(impactPoint.getBlockPosition());
                IMixinChunk spongeChunk = (IMixinChunk) projectile.world.getChunkFromBlockCoords(targetPos);
                spongeChunk.addTrackedBlockPosition((Block) targetBlock.getState().getType(), targetPos, owner.get(), PlayerTracker.Type.NOTIFIER);
            }
        } else if (movingObjectPosition.entityHit != null) {
            // entity
            ArrayList<Entity> entityList = new ArrayList<>();
            entityList.add((Entity) movingObjectPosition.entityHit);
            CollideEntityEvent.Impact event = SpongeEventFactory.createCollideEntityEventImpact(Sponge.getCauseStackManager().getCurrentCause(), entityList, impactPoint);
            cancelled = SpongeImpl.postEvent(event);
        }
        if (cancelled) {
            // Entities such as EnderPearls call setDead during onImpact. However, if the event is cancelled
            // setDead will never be called resulting in a bad state such as falling through world.
            projectile.setDead();
        }
        return cancelled;
    }
}
Also used : Entity(org.spongepowered.api.entity.Entity) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) User(org.spongepowered.api.entity.living.player.User) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) RayTraceResult(net.minecraft.util.math.RayTraceResult) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) ArrayList(java.util.ArrayList) World(org.spongepowered.api.world.World) Direction(org.spongepowered.api.util.Direction) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BlockPos(net.minecraft.util.math.BlockPos) Location(org.spongepowered.api.world.Location)

Example 34 with PhaseTracker

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

the class SpongeCommonEventFactory method callChangeBlockEventPre.

/**
 * Processes pre block event data then fires event.
 *
 * Note: This method does not create a stack frame.
 * Any caller to this method should have a frame created to
 * avoid stack corruption.
 *
 * @param worldIn The world
 * @param locations The locations affected
 * @param source The source of event
 * @return The event
 */
private static ChangeBlockEvent.Pre callChangeBlockEventPre(IMixinWorldServer worldIn, ImmutableList<Location<World>> locations, @Nullable Object source) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    if (source == null) {
        source = data.context.getSource(LocatableBlock.class).orElse(null);
        if (source == null) {
            // safety measure, return a dummy event
            if (DUMMY_BLOCK_PRE_EVENT == null) {
                DUMMY_BLOCK_PRE_EVENT = SpongeEventFactory.createChangeBlockEventPre(Sponge.getCauseStackManager().getCurrentCause(), ImmutableList.of());
            }
            return DUMMY_BLOCK_PRE_EVENT;
        }
    }
    EntityPlayer player = null;
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    Sponge.getCauseStackManager().pushCause(source);
    if (source instanceof Player) {
        player = (EntityPlayer) source;
        if (SpongeImplHooks.isFakePlayer(player)) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
        }
    }
    if (owner != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
    } else if (player != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
    }
    if (notifier != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
    }
    ChangeBlockEvent.Pre event = SpongeEventFactory.createChangeBlockEventPre(Sponge.getCauseStackManager().getCurrentCause(), locations);
    SpongeImpl.postEvent(event);
    return event;
}
Also used : ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) Player(org.spongepowered.api.entity.living.player.Player) EntityPlayer(net.minecraft.entity.player.EntityPlayer) IMixinInventoryPlayer(org.spongepowered.common.interfaces.entity.player.IMixinInventoryPlayer) ContainerPlayer(net.minecraft.inventory.ContainerPlayer) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) EntityPlayer(net.minecraft.entity.player.EntityPlayer)

Example 35 with PhaseTracker

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

the class SpongeCommonEventFactory method callChangeBlockEventModifyLiquidBreak.

public static ChangeBlockEvent.Break callChangeBlockEventModifyLiquidBreak(net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, int flags) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    BlockState fromState = BlockUtil.fromNative(worldIn.getBlockState(pos));
    BlockState toState = BlockUtil.fromNative(state);
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    Object source = data.context.getSource(LocatableBlock.class).orElse(null);
    if (source == null) {
        // Fallback
        source = worldIn;
    }
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(source);
        Sponge.getCauseStackManager().addContext(EventContextKeys.LIQUID_BREAK, (World) worldIn);
        if (owner != null) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
        }
        if (notifier != null) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
        }
        WorldProperties world = ((World) worldIn).getProperties();
        Vector3i position = new Vector3i(pos.getX(), pos.getY(), pos.getZ());
        Transaction<BlockSnapshot> transaction = new Transaction<>(BlockSnapshot.builder().blockState(fromState).world(world).position(position).build(), BlockSnapshot.builder().blockState(toState).world(world).position(position).build());
        ChangeBlockEvent.Break event = SpongeEventFactory.createChangeBlockEventBreak(Sponge.getCauseStackManager().getCurrentCause(), Collections.singletonList(transaction));
        SpongeImpl.postEvent(event);
        return event;
    }
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Vector3i(com.flowpowered.math.vector.Vector3i) IInteractionObject(net.minecraft.world.IInteractionObject) LocatableBlock(org.spongepowered.api.world.LocatableBlock) WorldProperties(org.spongepowered.api.world.storage.WorldProperties)

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