use of org.spongepowered.common.world.SpongeProxyBlockAccess in project SpongeCommon by SpongePowered.
the class GeneralPhase method performPostBlockAdditions.
@SuppressWarnings("unchecked")
private static void performPostBlockAdditions(PhaseContext<?> postContext, List<Transaction<BlockSnapshot>> transactions, IPhaseState<?> unwindingState, PhaseContext<?> unwindingPhaseContext) {
// We have to use a proxy so that our pending changes are notified such that any accessors from block
// classes do not fail on getting the incorrect block state from the IBlockAccess
final SpongeProxyBlockAccess proxyBlockAccess = new SpongeProxyBlockAccess(transactions);
final CapturedMultiMapSupplier<BlockPos, ItemDropData> capturedBlockDrops = postContext.getBlockDropSupplier();
final CapturedMultiMapSupplier<BlockPos, EntityItem> capturedBlockItemEntityDrops = postContext.getBlockItemDropSupplier();
for (Transaction<BlockSnapshot> transaction : transactions) {
if (!transaction.isValid()) {
// Don't use invalidated block transactions during notifications, these only need to be restored
continue;
}
// Handle custom replacements
if (transaction.getCustom().isPresent()) {
transaction.getFinal().restore(true, BlockChangeFlags.ALL);
}
final SpongeBlockSnapshot oldBlockSnapshot = (SpongeBlockSnapshot) transaction.getOriginal();
final SpongeBlockSnapshot newBlockSnapshot = (SpongeBlockSnapshot) transaction.getFinal();
// Handle item drops captured
final Location<World> worldLocation = oldBlockSnapshot.getLocation().get();
final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldLocation.getExtent();
final BlockPos pos = ((IMixinLocation) (Object) worldLocation).getBlockPos();
capturedBlockDrops.acceptAndRemoveIfPresent(pos, items -> TrackingUtil.spawnItemDataForBlockDrops(items, oldBlockSnapshot, unwindingPhaseContext, unwindingState));
capturedBlockItemEntityDrops.acceptAndRemoveIfPresent(pos, items -> TrackingUtil.spawnItemEntitiesForBlockDrops(items, oldBlockSnapshot, unwindingPhaseContext, unwindingState));
final WorldServer worldServer = mixinWorldServer.asMinecraftWorld();
SpongeHooks.logBlockAction(worldServer, oldBlockSnapshot.blockChange, transaction);
final SpongeBlockChangeFlag spongeFlag = oldBlockSnapshot.getChangeFlag();
final int updateFlag = spongeFlag.getRawFlag();
final IBlockState originalState = (IBlockState) oldBlockSnapshot.getState();
final IBlockState newState = (IBlockState) newBlockSnapshot.getState();
// Containers get placed automatically
final CapturedSupplier<BlockSnapshot> capturedBlockSupplier = postContext.getCapturedBlockSupplier();
if (spongeFlag.performBlockPhysics() && originalState.getBlock() != newState.getBlock() && !SpongeImplHooks.hasBlockTileEntity(newState.getBlock(), newState)) {
newState.getBlock().onBlockAdded(worldServer, pos, newState);
postContext.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
final ArrayList<Entity> capturedEntities = new ArrayList<>(entities);
((IPhaseState) unwindingState).postProcessSpawns(unwindingPhaseContext, capturedEntities);
});
capturedBlockSupplier.acceptAndClearIfNotEmpty(blocks -> {
final List<BlockSnapshot> blockSnapshots = new ArrayList<>(blocks);
processBlockTransactionListsPost(postContext, blockSnapshots, unwindingState, unwindingPhaseContext);
});
}
proxyBlockAccess.proceed();
((IPhaseState) unwindingState).handleBlockChangeWithUser(oldBlockSnapshot.blockChange, transaction, unwindingPhaseContext);
if (spongeFlag.isNotifyClients()) {
// Since notifyBlockUpdate is basically to tell clients that the block position has changed,
// we need to respect that flag
worldServer.notifyBlockUpdate(pos, originalState, newState, updateFlag);
}
if (spongeFlag.updateNeighbors()) {
// Notify neighbors only if the change flag allowed it.
mixinWorldServer.spongeNotifyNeighborsPostBlockChange(pos, originalState, newState, spongeFlag);
} else if (spongeFlag.notifyObservers()) {
worldServer.updateObservingBlocksAt(pos, newState.getBlock());
}
capturedBlockSupplier.acceptAndClearIfNotEmpty(blocks -> {
final List<BlockSnapshot> blockSnapshots = new ArrayList<>(blocks);
blocks.clear();
processBlockTransactionListsPost(postContext, blockSnapshots, unwindingState, unwindingPhaseContext);
});
}
}
Aggregations