Search in sources :

Example 1 with SpongeProxyBlockAccess

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);
        });
    }
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) Entity(org.spongepowered.api.entity.Entity) IBlockState(net.minecraft.block.state.IBlockState) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) ArrayList(java.util.ArrayList) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) World(org.spongepowered.api.world.World) SpongeProxyBlockAccess(org.spongepowered.common.world.SpongeProxyBlockAccess) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockPos(net.minecraft.util.math.BlockPos) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) EntityItem(net.minecraft.entity.item.EntityItem)

Aggregations

ArrayList (java.util.ArrayList)1 IBlockState (net.minecraft.block.state.IBlockState)1 EntityItem (net.minecraft.entity.item.EntityItem)1 BlockPos (net.minecraft.util.math.BlockPos)1 WorldServer (net.minecraft.world.WorldServer)1 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)1 Entity (org.spongepowered.api.entity.Entity)1 World (org.spongepowered.api.world.World)1 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)1 IPhaseState (org.spongepowered.common.event.tracking.IPhaseState)1 ItemDropData (org.spongepowered.common.event.tracking.context.ItemDropData)1 IMixinLocation (org.spongepowered.common.interfaces.world.IMixinLocation)1 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)1 SpongeBlockChangeFlag (org.spongepowered.common.world.SpongeBlockChangeFlag)1 SpongeProxyBlockAccess (org.spongepowered.common.world.SpongeProxyBlockAccess)1