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