Search in sources :

Example 1 with LocatableBlock

use of org.spongepowered.api.world.LocatableBlock in project SpongeCommon by SpongePowered.

the class TrackingUtil method randomTickBlock.

public static void randomTickBlock(PhaseTracker phaseTracker, IMixinWorldServer mixinWorld, Block block, BlockPos pos, IBlockState state, Random random) {
    final WorldServer minecraftWorld = mixinWorld.asMinecraftWorld();
    try (@SuppressWarnings("unused") StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(minecraftWorld);
        if (ShouldFire.TICK_BLOCK_EVENT) {
            final BlockSnapshot currentTickBlock = mixinWorld.createSpongeBlockSnapshot(state, state, pos, BlockChangeFlags.NONE);
            final TickBlockEvent event = SpongeEventFactory.createTickBlockEventRandom(Sponge.getCauseStackManager().getCurrentCause(), currentTickBlock);
            SpongeImpl.postEvent(event);
            if (event.isCancelled()) {
                return;
            }
        }
        final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(mixinWorld.asSpongeWorld(), pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build();
        Sponge.getCauseStackManager().pushCause(locatable);
        IPhaseState<BlockTickContext> phase = ((IMixinBlock) block).requiresBlockCapture() ? TickPhase.Tick.RANDOM_BLOCK : TickPhase.Tick.NO_CAPTURE_BLOCK;
        final BlockTickContext phaseContext = phase.createPhaseContext().source(locatable);
        checkAndAssignBlockTickConfig(block, minecraftWorld, phaseContext);
        // We have to associate any notifiers in case of scheduled block updates from other sources
        final PhaseData current = phaseTracker.getCurrentPhaseData();
        final IPhaseState<?> currentState = current.state;
        ((IPhaseState) currentState).appendNotifierPreBlockTick(mixinWorld, pos, current.context, phaseContext);
        // Now actually switch to the new phase
        try (PhaseContext<?> context = phaseContext.buildAndSwitch()) {
            block.randomTick(minecraftWorld, pos, state, random);
        } catch (Exception | NoClassDefFoundError e) {
            phaseTracker.printExceptionFromPhase(e, phaseContext);
        }
    }
}
Also used : SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) TickBlockEvent(org.spongepowered.api.event.block.TickBlockEvent) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) BlockTickContext(org.spongepowered.common.event.tracking.phase.tick.BlockTickContext) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) LocatableBlock(org.spongepowered.api.world.LocatableBlock)

Example 2 with LocatableBlock

use of org.spongepowered.api.world.LocatableBlock in project SpongeCommon by SpongePowered.

the class BlockDecayPhaseState method unwind.

@SuppressWarnings("unchecked")
@Override
public void unwind(GeneralizedContext context) {
    final LocatableBlock locatable = context.getSource(LocatableBlock.class).orElseThrow(TrackingUtil.throwWithContext("Expected to be ticking over at a location!", context));
    final Location<World> worldLocation = locatable.getLocation();
    final IMixinWorldServer mixinWorld = ((IMixinWorldServer) worldLocation.getExtent());
    try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(locatable);
        context.addNotifierAndOwnerToCauseStack();
        context.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> TrackingUtil.processBlockCaptures(blocks, this, context));
        frame.addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.BLOCK_SPAWNING);
        context.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(items -> {
            final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(frame.getCurrentCause(), items);
            SpongeImpl.postEvent(event);
            if (!event.isCancelled()) {
                for (Entity entity : event.getEntities()) {
                    EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
                }
            }
        });
        context.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
            final SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(frame.getCurrentCause(), entities);
            SpongeImpl.postEvent(event);
            if (!event.isCancelled()) {
                for (Entity entity : event.getEntities()) {
                    EntityUtil.getMixinWorld(entity).forceSpawnEntity(entity);
                }
            }
        });
        context.getCapturedItemStackSupplier().acceptAndClearIfNotEmpty(drops -> {
            final List<EntityItem> items = drops.stream().map(drop -> drop.create(mixinWorld.asMinecraftWorld())).collect(Collectors.toList());
            final List<Entity> entities = (List<Entity>) (List<?>) items;
            if (!entities.isEmpty()) {
                DropItemEvent.Custom event = SpongeEventFactory.createDropItemEventCustom(frame.getCurrentCause(), entities);
                SpongeImpl.postEvent(event);
                if (!event.isCancelled()) {
                    for (Entity droppedItem : event.getEntities()) {
                        mixinWorld.forceSpawnEntity(droppedItem);
                    }
                }
            }
        });
    }
}
Also used : EntityItem(net.minecraft.entity.item.EntityItem) SpongeImpl(org.spongepowered.common.SpongeImpl) Location(org.spongepowered.api.world.Location) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) EventContextKeys(org.spongepowered.api.event.cause.EventContextKeys) LocatableBlock(org.spongepowered.api.world.LocatableBlock) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) Sponge(org.spongepowered.api.Sponge) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) Entity(org.spongepowered.api.entity.Entity) Collectors(java.util.stream.Collectors) EntityUtil(org.spongepowered.common.entity.EntityUtil) SpawnTypes(org.spongepowered.api.event.cause.entity.spawn.SpawnTypes) List(java.util.List) TrackingUtil(org.spongepowered.common.event.tracking.TrackingUtil) GeneralizedContext(org.spongepowered.common.event.tracking.context.GeneralizedContext) World(org.spongepowered.api.world.World) Entity(org.spongepowered.api.entity.Entity) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) World(org.spongepowered.api.world.World) SpawnEntityEvent(org.spongepowered.api.event.entity.SpawnEntityEvent) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) LocatableBlock(org.spongepowered.api.world.LocatableBlock) List(java.util.List) EntityItem(net.minecraft.entity.item.EntityItem)

Example 3 with LocatableBlock

use of org.spongepowered.api.world.LocatableBlock in project SpongeCommon by SpongePowered.

the class MixinWorldServer method onAddBlockEvent.

@Redirect(method = "addBlockEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/WorldServer$ServerBlockEventList;add(Ljava/lang/Object;)Z", remap = false))
private boolean onAddBlockEvent(WorldServer.ServerBlockEventList list, Object obj, BlockPos pos, Block blockIn, int eventId, int eventParam) {
    final BlockEventData blockEventData = (BlockEventData) obj;
    IMixinBlockEventData blockEvent = (IMixinBlockEventData) blockEventData;
    // This is very common with pistons as they add block events while blocks are being notified.
    if (blockIn instanceof BlockPistonBase) {
        // We only fire pre events for pistons
        if (SpongeCommonEventFactory.handlePistonEvent(this, list, obj, pos, blockIn, eventId, eventParam)) {
            return false;
        }
        blockEvent.setCaptureBlocks(false);
    // TODO BLOCK_EVENT flag
    } else if (SpongeCommonEventFactory.callChangeBlockEventPre(this, pos).isCancelled()) {
        return false;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData currentPhase = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = currentPhase.state;
    if (phaseState.ignoresBlockEvent()) {
        return list.add((BlockEventData) obj);
    }
    final PhaseContext<?> context = currentPhase.context;
    final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(this, pos.getX(), pos.getY(), pos.getZ())).state(this.getBlock(pos.getX(), pos.getY(), pos.getZ())).build();
    blockEvent.setTickBlock(locatable);
    phaseState.addNotifierToBlockEvent(context, this, pos, blockEvent);
    return list.add((BlockEventData) obj);
}
Also used : IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) BlockPistonBase(net.minecraft.block.BlockPistonBase) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) LocatableBlock(org.spongepowered.api.world.LocatableBlock) IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) BlockEventData(net.minecraft.block.BlockEventData) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 4 with LocatableBlock

use of org.spongepowered.api.world.LocatableBlock in project SpongeCommon by SpongePowered.

the class MixinBlockDynamicLiquid method beforeSetBlockState.

// Capture Lava falling on Water forming Stone
@Inject(method = "updateTick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z"))
private void beforeSetBlockState(net.minecraft.world.World worldIn, BlockPos sourcePos, IBlockState state, Random rand, CallbackInfo ci) {
    Location<org.spongepowered.api.world.World> loc = new Location<>(((org.spongepowered.api.world.World) worldIn), sourcePos.getX(), sourcePos.getY(), sourcePos.getZ());
    LocatableBlock source = LocatableBlock.builder().location(loc).build();
    IBlockState newState = Blocks.STONE.getDefaultState();
    ChangeBlockEvent.Modify event = SpongeCommonEventFactory.callChangeBlockEventModifyLiquidMix(worldIn, sourcePos, newState, source);
    Transaction<BlockSnapshot> transaction = event.getTransactions().get(0);
    if (event.isCancelled() || !transaction.isValid()) {
        ci.cancel();
        return;
    }
    if (!worldIn.setBlockState(sourcePos.down(), BlockUtil.toNative(transaction.getFinal().getState()))) {
        ci.cancel();
    }
}
Also used : ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) IBlockState(net.minecraft.block.state.IBlockState) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) LocatableBlock(org.spongepowered.api.world.LocatableBlock) Location(org.spongepowered.api.world.Location) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 5 with LocatableBlock

use of org.spongepowered.api.world.LocatableBlock in project SpongeCommon by SpongePowered.

the class MixinChunk_Collisions method allowEntityCollision.

private <T extends Entity> boolean allowEntityCollision(List<T> listToFill) {
    if (this.world instanceof IMixinWorldServer) {
        IMixinWorldServer spongeWorld = (IMixinWorldServer) this.world;
        if (spongeWorld.isProcessingExplosion()) {
            // allow explosions
            return true;
        }
        final PhaseContext<?> phaseContext = PhaseTracker.getInstance().getCurrentContext();
        LocatableBlock locatable = phaseContext.getSource(LocatableBlock.class).orElse(null);
        if (locatable != null) {
            BlockType blockType = locatable.getLocation().getBlockType();
            IModData_Collisions spongeBlock = (IModData_Collisions) blockType;
            if (spongeBlock.requiresCollisionsCacheRefresh()) {
                spongeBlock.initializeCollisionState(this.world);
                spongeBlock.requiresCollisionsCacheRefresh(false);
            }
            return !((spongeBlock.getMaxCollisions() >= 0) && (listToFill.size() >= spongeBlock.getMaxCollisions()));
        }
        IModData_Collisions spongeEntity = phaseContext.getSource(IModData_Collisions.class).orElse(null);
        if (spongeEntity != null) {
            if (spongeEntity.requiresCollisionsCacheRefresh()) {
                spongeEntity.initializeCollisionState(this.world);
                spongeEntity.requiresCollisionsCacheRefresh(false);
            }
            return !((spongeEntity.getMaxCollisions() >= 0) && (listToFill.size() >= spongeEntity.getMaxCollisions()));
        }
        return true;
    }
    return true;
}
Also used : IModData_Collisions(org.spongepowered.common.mixin.plugin.entitycollisions.interfaces.IModData_Collisions) BlockType(org.spongepowered.api.block.BlockType) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) LocatableBlock(org.spongepowered.api.world.LocatableBlock)

Aggregations

LocatableBlock (org.spongepowered.api.world.LocatableBlock)34 BlockState (org.spongepowered.api.block.BlockState)13 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)9 IBlockState (net.minecraft.block.state.IBlockState)8 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)8 World (org.spongepowered.api.world.World)8 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)8 Entity (org.spongepowered.api.entity.Entity)7 CauseStackManager (org.spongepowered.api.event.CauseStackManager)7 IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)7 SpongeLocatableBlockBuilder (org.spongepowered.common.world.server.SpongeLocatableBlockBuilder)7 ArrayList (java.util.ArrayList)6 ServerLevel (net.minecraft.server.level.ServerLevel)6 TickBlockEvent (org.spongepowered.api.event.block.TickBlockEvent)6 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)6 List (java.util.List)5 Optional (java.util.Optional)4 Collectors (java.util.stream.Collectors)4 Sponge (org.spongepowered.api.Sponge)4 Player (org.spongepowered.api.entity.living.player.Player)4