use of org.spongepowered.common.event.tracking.phase.general.UnwindingPhaseContext in project SpongeForge by SpongePowered.
the class SpongeForgeEventFactory method callBlockPlaceEvent.
public static ChangeBlockEvent.Place callBlockPlaceEvent(Event event) {
ChangeBlockEvent.Place spongeEvent = (ChangeBlockEvent.Place) event;
if (spongeEvent.getCause().root() instanceof Player) {
EntityPlayer player = (EntityPlayer) spongeEvent.getCause().first(Player.class).get();
net.minecraft.world.World world = player.world;
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseContext<?> currentContext = phaseTracker.getCurrentContext();
PhaseContext<?> target = currentContext;
if (currentContext instanceof UnwindingPhaseContext) {
target = ((UnwindingPhaseContext) currentContext).getUnwindingContext();
}
PacketContext<?> context = target instanceof PacketContext<?> ? (PacketContext<?>) target : null;
Packet<?> contextPacket = context != null ? context.getPacket() : null;
if (contextPacket == null) {
return spongeEvent;
}
if (spongeEvent.getTransactions().size() == 1) {
BlockPos pos = VecHelper.toBlockPos(spongeEvent.getTransactions().get(0).getOriginal().getPosition());
IBlockState state = (IBlockState) spongeEvent.getTransactions().get(0).getOriginal().getState();
net.minecraftforge.common.util.BlockSnapshot blockSnapshot = new net.minecraftforge.common.util.BlockSnapshot(world, pos, state);
IBlockState placedAgainst = Blocks.AIR.getDefaultState();
EnumHand hand = EnumHand.MAIN_HAND;
if (contextPacket instanceof CPacketPlayerTryUseItemOnBlock) {
CPacketPlayerTryUseItemOnBlock packet = (CPacketPlayerTryUseItemOnBlock) contextPacket;
EnumFacing facing = packet.getDirection();
placedAgainst = blockSnapshot.getWorld().getBlockState(blockSnapshot.getPos().offset(facing.getOpposite()));
hand = packet.getHand();
}
BlockEvent.PlaceEvent forgeEvent = new BlockEvent.PlaceEvent(blockSnapshot, placedAgainst, player, hand);
((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
if (forgeEvent.isCanceled()) {
spongeEvent.setCancelled(true);
}
} else {
// multi
Iterator<Transaction<BlockSnapshot>> iterator = spongeEvent.getTransactions().iterator();
List<net.minecraftforge.common.util.BlockSnapshot> blockSnapshots = new ArrayList<>();
while (iterator.hasNext()) {
Transaction<BlockSnapshot> transaction = iterator.next();
Location<World> location = transaction.getOriginal().getLocation().get();
IBlockState state = (IBlockState) transaction.getOriginal().getState();
BlockPos pos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
net.minecraftforge.common.util.BlockSnapshot blockSnapshot = new net.minecraftforge.common.util.BlockSnapshot(world, pos, state);
blockSnapshots.add(blockSnapshot);
}
IBlockState placedAgainst = Blocks.AIR.getDefaultState();
EnumHand hand = EnumHand.MAIN_HAND;
if (contextPacket instanceof CPacketPlayerTryUseItemOnBlock) {
CPacketPlayerTryUseItemOnBlock packet = (CPacketPlayerTryUseItemOnBlock) contextPacket;
EnumFacing facing = packet.getDirection();
placedAgainst = blockSnapshots.get(0).getWorld().getBlockState(blockSnapshots.get(0).getPos().offset(facing.getOpposite()));
hand = packet.getHand();
}
BlockEvent.MultiPlaceEvent forgeEvent = new BlockEvent.MultiPlaceEvent(blockSnapshots, placedAgainst, player, hand);
((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
if (forgeEvent.isCanceled()) {
spongeEvent.setCancelled(true);
}
}
}
return spongeEvent;
}
use of org.spongepowered.common.event.tracking.phase.general.UnwindingPhaseContext in project SpongeCommon by SpongePowered.
the class PhaseTracker method completePhase.
@SuppressWarnings({ "rawtypes", "unused", "try" })
public void completePhase(IPhaseState<?> prevState) {
final PhaseData currentPhaseData = this.stack.peek();
final IPhaseState<?> state = currentPhaseData.state;
final boolean isEmpty = this.stack.isEmpty();
if (isEmpty) {
// The random occurrence that we're told to complete a phase
// while a world is being changed unknowingly.
this.printEmptyStackOnCompletion();
return;
}
if (prevState != state) {
this.printIncorrectPhaseCompletion(prevState, state);
// The phase on the top of the stack was most likely never completed.
// Since we don't know when and where completePhase was intended to be called for it,
// we simply pop it to allow processing to continue (somewhat) as normal
this.stack.pop();
}
if (SpongeImpl.getGlobalConfig().getConfig().getPhaseTracker().isVerbose() && this.stack.size() > 6 && state != GeneralPhase.Post.UNWINDING && !state.isExpectedForReEntrance()) {
// This printing is to detect possibilities of a phase not being cleared properly
// and resulting in a "runaway" phase state accumulation.
this.printRunnawayPhaseCompletion(state);
}
this.stack.pop();
// If pop is called, the Deque will already throw an exception if there is no element
// so it's an error properly handled.
final TrackingPhase phase = state.getPhase();
final PhaseContext<?> context = currentPhaseData.context;
try (final UnwindingPhaseContext unwinding = UnwindingPhaseContext.unwind(state, context)) {
// a new list of capture lists
try {
// Yes this is a nested try, but in the event the current phase cannot be unwound, at least unwind UNWINDING
((IPhaseState) state).unwind(context);
} catch (Exception e) {
this.printMessageWithCaughtException("Exception Exiting Phase", "Something happened when trying to unwind", state, context, e);
}
} catch (Exception e) {
this.printMessageWithCaughtException("Exception Post Dispatching Phase", "Something happened when trying to post dispatch state", state, context, e);
}
}
Aggregations