use of org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method destroyBlock.
@Override
public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable final Entity p_241212_3_, final int limit) {
final BlockState currentState = this.shadow$getBlockState(pos);
if (currentState.isAir()) {
return false;
} else {
// Sponge Start - Sanity check against the PhaseTracker for instances
if (this.bridge$isFake()) {
return super.destroyBlock(pos, doDrops, p_241212_3_, limit);
}
final PhaseTracker instance = PhaseTracker.getInstance();
if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
}
final FluidState fluidstate = this.shadow$getFluidState(pos);
final BlockState emptyBlock = fluidstate.createLegacyBlock();
final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(3);
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk.isEmpty()) {
return false;
}
final WorldPipeline.Builder pipelineBuilder = this.bridge$makePipeline(pos, currentState, emptyBlock, chunk, spongeFlag, limit).addEffect(WorldDestroyBlockLevelEffect.getInstance());
if (doDrops) {
pipelineBuilder.addEffect(PerformBlockDropsFromDestruction.getInstance());
}
final WorldPipeline pipeline = pipelineBuilder.addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
return pipeline.processEffects(instance.getPhaseContext(), currentState, emptyBlock, pos, p_241212_3_, spongeFlag, limit);
}
}
use of org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method setBlock.
/**
* @author gabizou, March 12th, 2016
* <p>
* Move this into WorldServer as we should not be modifying the client world.
* <p>
* Purpose: Rewritten to support capturing blocks
*/
@Override
public boolean setBlock(final BlockPos pos, final net.minecraft.world.level.block.state.BlockState newState, final int flags, final int limit) {
if (net.minecraft.world.level.Level.isOutsideBuildHeight(pos)) {
return false;
} else if (this.shadow$isDebug()) {
// isClientSide is always false since this is WorldServer
return false;
}
// Sponge Start - Sanity check against the PhaseTracker for instances
if (this.bridge$isFake()) {
return super.setBlock(pos, newState, flags, limit);
}
final PhaseTracker instance = PhaseTracker.getInstance();
if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) {
throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!");
}
final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags);
final LevelChunk chunk = this.shadow$getChunkAt(pos);
if (chunk.isEmpty()) {
return false;
}
final net.minecraft.world.level.block.state.BlockState currentState = chunk.getBlockState(pos);
// change of "don't do anything if the block is the same".
if (currentState == newState) {
return false;
}
final WorldPipeline pipeline = this.bridge$makePipeline(pos, currentState, newState, chunk, spongeFlag, limit).addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
return pipeline.processEffects(instance.getPhaseContext(), currentState, newState, pos, null, spongeFlag, limit);
}
use of org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline in project SpongeCommon by SpongePowered.
the class ExplosionMixin_Tracker method finalizeExplosion.
/**
* @author gabziou
* @author zidane
* @reason Run explosion logic through tracking
*/
@Overwrite
public void finalizeExplosion(final boolean spawnParticles) {
// Sponge Start - In Sponge, we no longer call doExplosionB client-side (kills client perf)
if (this.level.isClientSide) {
return;
}
// Sponge End
// Sponge Start - Send the sound packet down. We must do this as we do not call doExplosionB client-side
this.level.playSound(null, this.x, this.y, this.z, SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 4.0F, (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F);
// Sponge End
final boolean flag = this.blockInteraction != net.minecraft.world.level.Explosion.BlockInteraction.NONE;
if (spawnParticles) {
if (!(this.radius < 2.0F) && (flag || ((ExplosionBridge) this).bridge$getShouldDamageBlocks())) {
// hundreds of explosions at once
if (this.level instanceof ServerLevel) {
((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D);
} else {
this.level.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
// Sponge End
} else {
// hundreds of explosions at once
if (this.level instanceof ServerLevel) {
((ServerLevel) this.level).sendParticles(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D);
} else {
this.level.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
// Sponge End
}
}
if (flag) {
// Sponge Start - Forward changes through a WorldPipeline to associate side effects
// Vanilla - uses a list of itemstacks to do a bunch of pre-merging
// ObjectArrayList<Pair<ItemStack, BlockPos>> objectarraylist = new ObjectArrayList<>();
Collections.shuffle(this.toBlow, this.level.random);
for (final BlockPos blockpos : this.toBlow) {
final BlockState blockstate = this.level.getBlockState(blockpos);
// Block block = blockstate.getBlock(); // Sponge - we don't use this
if (!blockstate.isAir()) {
final BlockPos blockpos1 = blockpos.immutable();
this.level.getProfiler().push("explosion_blocks");
// Sponge - All of this is forwarded to the effects
// if (block.canDropFromExplosion(this) && this.level instanceof ServerLevel) {
// BlockEntity var6 = block.isEntityBlock() ? this.level.getBlockEntity(blockpos) : null;
// LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerLevel)this.level)).withRandom(this.level.rand).withParameter(
// LootParameters.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, var6).withNullableParameter(LootParameters.THIS_ENTITY, this.source);
// if (this.blockInteraction == Explosion.BlockInteraction.DESTROY) {
// lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, this.radius);
// }
// var3.getDrops(var7).forEach((param2) -> addBlockDrops(var1, param2, var5));
// }
// this.level.setBlock(blockpos, Blocks.AIR.defaultState(), 3);
// block.onExplosionDestroy(this.world, blockpos, this);
final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext();
((TrackedWorldBridge) this.level).bridge$startBlockChange(blockpos1, Blocks.AIR.defaultBlockState(), 3).ifPresent(builder -> {
final WorldPipeline build = builder.addEffect(AddBlockLootDropsEffect.getInstance()).addEffect(ExplodeBlockEffect.getInstance()).addEffect(SpawnDestructBlocksEffect.getInstance()).addEffect(WorldBlockChangeCompleteEffect.getInstance()).build();
build.processEffects(context, blockstate, Blocks.AIR.defaultBlockState(), blockpos1, null, BlockChangeFlagManager.fromNativeInt(3), Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT);
});
// Sponge End
this.level.getProfiler().pop();
}
}
// Sponge Start - This is built into the SpawnDestructBlocksEffect
// for(Pair<ItemStack, BlockPos> var8 : objectarraylist) {
// Block.popResource(this.level, var8.getSecond(), var8.getFirst());
// }
// Sponge End
}
if (this.fire) {
for (final BlockPos blockpos2 : this.toBlow) {
if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockpos2).isAir() && this.level.getBlockState(blockpos2.below()).isSolidRender(this.level, blockpos2.below())) {
this.level.setBlockAndUpdate(blockpos2, BaseFireBlock.getState(this.level, blockpos2));
}
}
}
}
Aggregations