Search in sources :

Example 1 with WorldPipeline

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);
    }
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) BlockState(net.minecraft.world.level.block.state.BlockState) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) WorldPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline) FluidState(net.minecraft.world.level.material.FluidState)

Example 2 with WorldPipeline

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);
}
Also used : SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState) WorldPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline)

Example 3 with WorldPipeline

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));
            }
        }
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) BlockState(net.minecraft.world.level.block.state.BlockState) BlockPos(net.minecraft.core.BlockPos) WorldPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Aggregations

BlockState (net.minecraft.world.level.block.state.BlockState)3 WorldPipeline (org.spongepowered.common.event.tracking.context.transaction.pipeline.WorldPipeline)3 LevelChunk (net.minecraft.world.level.chunk.LevelChunk)2 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)2 SpongeBlockChangeFlag (org.spongepowered.common.world.SpongeBlockChangeFlag)2 BlockPos (net.minecraft.core.BlockPos)1 ServerLevel (net.minecraft.server.level.ServerLevel)1 FluidState (net.minecraft.world.level.material.FluidState)1 Overwrite (org.spongepowered.asm.mixin.Overwrite)1