Search in sources :

Example 36 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class TrackingUtil method trackBlockChange.

@SuppressWarnings("rawtypes")
static boolean trackBlockChange(PhaseTracker phaseTracker, IMixinWorldServer mixinWorld, Chunk chunk, IBlockState currentState, IBlockState newState, BlockPos pos, BlockChangeFlag flags, PhaseContext<?> phaseContext, IPhaseState<?> phaseState) {
    final SpongeBlockSnapshot originalBlockSnapshot;
    final WorldServer minecraftWorld = mixinWorld.asMinecraftWorld();
    if (((IPhaseState) phaseState).shouldCaptureBlockChangeOrSkip(phaseContext, pos)) {
        // final IBlockState actualState = currentState.getActualState(minecraftWorld, pos);
        originalBlockSnapshot = mixinWorld.createSpongeBlockSnapshot(currentState, currentState, pos, flags);
        final List<BlockSnapshot> capturedSnapshots = phaseContext.getCapturedBlocks();
        final Block newBlock = newState.getBlock();
        associateBlockChangeWithSnapshot(phaseState, newBlock, currentState, originalBlockSnapshot, capturedSnapshots);
        final IMixinChunk mixinChunk = (IMixinChunk) chunk;
        final IBlockState originalBlockState = mixinChunk.setBlockState(pos, newState, currentState, originalBlockSnapshot);
        if (originalBlockState == null) {
            capturedSnapshots.remove(originalBlockSnapshot);
            return false;
        }
        ((IPhaseState) phaseState).postTrackBlock(originalBlockSnapshot, phaseTracker, phaseContext);
    } else {
        originalBlockSnapshot = (SpongeBlockSnapshot) BlockSnapshot.NONE;
        final IMixinChunk mixinChunk = (IMixinChunk) chunk;
        final IBlockState originalBlockState = mixinChunk.setBlockState(pos, newState, currentState, originalBlockSnapshot);
        if (originalBlockState == null) {
            return false;
        }
    }
    if (newState.getLightOpacity() != currentState.getLightOpacity() || newState.getLightValue() != currentState.getLightValue()) {
        minecraftWorld.profiler.startSection("checkLight");
        minecraftWorld.checkLight(pos);
        minecraftWorld.profiler.endSection();
    }
    return true;
}
Also used : SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) IBlockState(net.minecraft.block.state.IBlockState) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) EntityFallingBlock(net.minecraft.entity.item.EntityFallingBlock) Block(net.minecraft.block.Block) LocatableBlock(org.spongepowered.api.world.LocatableBlock) IMixinBlock(org.spongepowered.common.interfaces.block.IMixinBlock) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer)

Example 37 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class RestoringBlockPhaseState method spawnEntityOrCapture.

@Override
public boolean spawnEntityOrCapture(GeneralizedContext context, Entity entity, int chunkX, int chunkZ) {
    final User user = context.getNotifier().orElseGet(() -> context.getOwner().orElse(null));
    if (user != null) {
        entity.setCreator(user.getUniqueId());
    }
    final ArrayList<Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
    SpongeImpl.postEvent(event);
    if (!event.isCancelled() && event.getEntities().size() > 0) {
        for (org.spongepowered.api.entity.Entity item : event.getEntities()) {
            ((IMixinWorldServer) item.getWorld()).forceSpawnEntity(item);
        }
        return true;
    }
    return false;
}
Also used : Entity(org.spongepowered.api.entity.Entity) User(org.spongepowered.api.entity.living.player.User) ArrayList(java.util.ArrayList) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) Entity(org.spongepowered.api.entity.Entity)

Example 38 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer 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)

Example 39 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class GeneralState method spawnEntityOrCapture.

/**
 * A duplicate of {@link IPhaseState#spawnEntityOrCapture(PhaseContext, Entity, int, int)}
 * such that the general states will not know what to do for entity spawns. Eventually, this is going to be centralized
 * so that it's not always delegated between the phases and phase states.
 *
 * Basically, for this method, this is included only for the {@link GeneralPhase.State#COMPLETE}, all other
 * will capture or spawn appropriately. In the case of explosions for example, the entities must be mapped
 * according to the blocks broken so that the blocks themselves can be cancelled and the entities spawned
 * are dropped from the game entirely before throwing additional events.
 *
 * @param context
 * @param entity
 * @param chunkX
 * @param chunkZ
 * @return
 */
@Override
public boolean spawnEntityOrCapture(G context, Entity entity, int chunkX, int chunkZ) {
    final User user = context.getNotifier().orElseGet(() -> context.getOwner().orElse(null));
    if (user != null) {
        entity.setCreator(user.getUniqueId());
    }
    final ArrayList<Entity> entities = new ArrayList<>(1);
    entities.add(entity);
    final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), entities);
    SpongeImpl.postEvent(event);
    if (!event.isCancelled() && event.getEntities().size() > 0) {
        for (Entity item : event.getEntities()) {
            ((IMixinWorldServer) item.getWorld()).forceSpawnEntity(item);
        }
        return true;
    }
    return false;
}
Also used : Entity(org.spongepowered.api.entity.Entity) User(org.spongepowered.api.entity.living.player.User) ArrayList(java.util.ArrayList) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent)

Example 40 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class MixinDedicatedServer method isBlockProtected.

/**
 * @author zml - March 9th, 2016
 * @author blood - July 7th, 2016 - Add cause tracker handling for throwing pre change block checks
 * @author gabizou - July 7th, 2016 - Update for 1.10's cause tracking changes
 *
 * @reason Change spawn protection to take advantage of Sponge permissions. Rather than affecting only the default world like vanilla, this
 * will apply to any world. Additionally, fire a spawn protection event
 */
@Overwrite
@Override
public boolean isBlockProtected(net.minecraft.world.World worldIn, BlockPos pos, EntityPlayer playerIn) {
    // Mods such as ComputerCraft and Thaumcraft check this method before attempting to set a blockstate.
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData peek = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = peek.state;
    if (phaseState == null || !phaseState.isInteraction()) {
        // TODO BLOCK_PROTECTED flag
        if (SpongeCommonEventFactory.callChangeBlockEventPre((IMixinWorldServer) worldIn, pos, playerIn).isCancelled()) {
            return true;
        }
    }
    BlockPos spawnPoint = worldIn.getSpawnPoint();
    int protectionRadius = getSpawnProtectionSize();
    return protectionRadius > 0 && Math.max(Math.abs(pos.getX() - spawnPoint.getX()), Math.abs(pos.getZ() - spawnPoint.getZ())) <= protectionRadius && !((Player) playerIn).hasPermission("minecraft.spawn-protection.override");
}
Also used : EntityPlayer(net.minecraft.entity.player.EntityPlayer) Player(org.spongepowered.api.entity.living.player.Player) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) BlockPos(net.minecraft.util.math.BlockPos) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Aggregations

IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)61 WorldServer (net.minecraft.world.WorldServer)25 BlockPos (net.minecraft.util.math.BlockPos)19 ArrayList (java.util.ArrayList)17 Entity (org.spongepowered.api.entity.Entity)15 World (org.spongepowered.api.world.World)15 IBlockState (net.minecraft.block.state.IBlockState)13 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)13 CauseStackManager (org.spongepowered.api.event.CauseStackManager)11 Overwrite (org.spongepowered.asm.mixin.Overwrite)11 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)9 IMixinEntity (org.spongepowered.common.interfaces.entity.IMixinEntity)9 EntityItem (net.minecraft.entity.item.EntityItem)8 User (org.spongepowered.api.entity.living.player.User)8 LocatableBlock (org.spongepowered.api.world.LocatableBlock)8 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)7 Entity (net.minecraft.entity.Entity)6 EntityPlayer (net.minecraft.entity.player.EntityPlayer)6 Chunk (net.minecraft.world.chunk.Chunk)6 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)6