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);
}
}
}
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);
}
}
}
});
}
}
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);
}
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();
}
}
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;
}
Aggregations