Search in sources :

Example 46 with ServerLevel

use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.

the class WorldPipeline method processEffects.

public boolean processEffects(final PhaseContext<?> context, final BlockState currentState, final BlockState newProposedState, final BlockPos pos, @Nullable final Entity destroyer, final SpongeBlockChangeFlag flag, final int limit) {
    if (this.worldEffects.isEmpty()) {
        return false;
    }
    final ServerLevel serverWorld = Objects.requireNonNull(this.serverWorld).get();
    // Keep track of the existing block entity prior to processing the chunk pipeline
    // and the reasoning is that in several cases where the block entity that is being removed
    // will no longer be available. This could be avoided by having the "previous cursor" returned
    // from ChunkPipeline, but alas.... that's a refactor for another time.
    @Nullable final BlockEntity existing = this.chunkSupplier.get().getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
    // We have to get the "old state" from
    @Nullable final BlockState oldState = this.chunkPipeline.processChange(context, currentState, newProposedState, pos, limit);
    if (oldState == null) {
        return false;
    }
    final int oldOpacity = oldState.getLightBlock(serverWorld, pos);
    PipelineCursor formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, destroyer, limit);
    for (final ResultingTransactionBySideEffect effect : this.worldEffects) {
        try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) {
            final EffectResult result = effect.effect.processSideEffect(this, formerState, newProposedState, flag, limit);
            if (result.hasResult) {
                return result.resultingState != null;
            }
            if (formerState.drops.isEmpty() && !result.drops.isEmpty()) {
                formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, formerState.destroyer, result.drops, limit);
            }
        }
    }
    // if we've gotten here, means something is wrong, we didn't build our effects right.
    return false;
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) BlockState(net.minecraft.world.level.block.state.BlockState) EffectResult(org.spongepowered.common.event.tracking.context.transaction.effect.EffectResult) ResultingTransactionBySideEffect(org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect) EffectTransactor(org.spongepowered.common.event.tracking.context.transaction.EffectTransactor) Nullable(org.checkerframework.checker.nullness.qual.Nullable) BlockEntity(net.minecraft.world.level.block.entity.BlockEntity)

Example 47 with ServerLevel

use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.

the class LevelChunkMixin_Tracker method bridge$createChunkPipeline.

/**
 * Technically a full overwrite for {@link LevelChunk#setBlockState(BlockPos, BlockState, boolean)}
 * and due to Sponge's hijacking of {@link ServerLevel#setBlock(BlockPos, BlockState, int)},
 * it needs to be able to record transactions when necessary. This implementation allows for us to
 * further specify the types of transactions and what proxies are needing to set up where.
 *
 * @param pos The position changing
 * @param newState The new state
 * @param currentState The current state - passed in from either chunk or world
 * @param flag The sponge change flag, converted from an int to a proper struct
 * @return The changed block state if not null
 * @author gabizou - January 13th, 2020 - Minecraft 1.14.3
 */
@Override
@NonNull
public ChunkPipeline bridge$createChunkPipeline(final BlockPos pos, final BlockState newState, final BlockState currentState, final SpongeBlockChangeFlag flag, final int limit) {
    final boolean isFake = ((LevelBridge) this.level).bridge$isFake();
    if (isFake) {
        throw new IllegalStateException("Cannot call ChunkBridge.bridge$buildChunkPipeline in non-Server managed worlds");
    }
    // int i = pos.getX() & 15;
    final int xPos = pos.getX() & 15;
    // int j = pos.getY();
    final int yPos = pos.getY();
    // int k = pos.getZ() & 15;
    final int zPos = pos.getZ() & 15;
    // Sponge - get the moving flag from our flag construct
    LevelChunkSection chunksection = this.sections[yPos >> 4];
    if (chunksection == LevelChunkMixin_Tracker.EMPTY_SECTION) {
        if (newState.isAir()) {
            return ChunkPipeline.nullReturn((LevelChunk) (Object) this, (ServerLevel) this.level);
        }
        chunksection = new LevelChunkSection(yPos >> 4 << 4);
        this.sections[yPos >> 4] = chunksection;
    }
    // Sponge Start - Build out the BlockTransaction
    final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext();
    @Nullable final BlockEntity existing = this.shadow$getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
    // Build a transaction maybe?
    final WeakReference<ServerLevel> ref = new WeakReference<>((ServerLevel) this.level);
    final SpongeBlockSnapshot snapshot = TrackingUtil.createPooledSnapshot(currentState, pos, flag, limit, existing, () -> Objects.requireNonNull(ref.get(), "ServerWorld dereferenced"), Optional::empty, Optional::empty);
    // Pulled up from below
    final ChangeBlock transaction = context.createTransaction(snapshot, newState, flag);
    snapshot.blockChange = context.associateBlockChangeWithSnapshot(newState, currentState);
    if (((BlockStateBridge) snapshot.state()).bridge$hasTileEntity() && (snapshot.blockChange == BlockChange.BREAK || snapshot.blockChange == BlockChange.MODIFY)) {
        transaction.queuedRemoval = existing;
    }
    final ChunkPipeline.Builder builder = ChunkPipeline.builder().kickOff(transaction).chunk((LevelChunk) (Object) this).chunkSection(chunksection).world((ServerLevel) this.level);
    // Populate the effects
    transaction.populateChunkEffects(builder);
    return builder.build();
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) Optional(java.util.Optional) ChangeBlock(org.spongepowered.common.event.tracking.context.transaction.block.ChangeBlock) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) LevelChunkSection(net.minecraft.world.level.chunk.LevelChunkSection) WeakReference(java.lang.ref.WeakReference) Nullable(org.checkerframework.checker.nullness.qual.Nullable) ChunkPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.ChunkPipeline) BlockEntity(net.minecraft.world.level.block.entity.BlockEntity) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) NonNull(org.checkerframework.checker.nullness.qual.NonNull)

Example 48 with ServerLevel

use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.

the class EndDragonFightMixin_Tracker method tracker$switchToFeatureState.

// @formatter:on
@Redirect(method = "spawnNewGateway(Lnet/minecraft/core/BlockPos;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/feature/ConfiguredFeature;place(Lnet/minecraft/world/level/WorldGenLevel;Lnet/minecraft/world/level/chunk/ChunkGenerator;Ljava/util/Random;Lnet/minecraft/core/BlockPos;)Z"))
private boolean tracker$switchToFeatureState(final ConfiguredFeature configuredFeature, final WorldGenLevel worldIn, final ChunkGenerator generator, final Random rand, final BlockPos pos) {
    try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.SERVER)) {
        context.world((ServerLevel) worldIn).generator(generator).feature(configuredFeature.feature).origin(pos);
        context.buildAndSwitch();
        return configuredFeature.place(worldIn, generator, rand, pos);
    }
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) FeaturePhaseContext(org.spongepowered.common.event.tracking.phase.generation.FeaturePhaseContext) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 49 with ServerLevel

use of net.minecraft.server.level.ServerLevel 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)

Example 50 with ServerLevel

use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.

the class SpongeUserData method create.

public static SpongeUserData create(final GameProfile profile) throws IOException {
    final ServerLevel world = SpongeCommon.server().overworld();
    if (world == null) {
        SpongeCommon.logger().warn("Overworld not initialized, cannot create users!");
        throw new IllegalStateException("Overworld not initialized, cannot create users!");
    }
    final LevelStorageSource.LevelStorageAccess storageSource = ((MinecraftServerAccessor) Sponge.server()).accessor$storageSource();
    final File file = storageSource.getLevelPath(LevelResource.PLAYER_DATA_DIR).resolve(profile.getId().toString() + ".dat").toFile();
    if (!file.exists()) {
        return new SpongeUserData(profile, new CompoundTag());
    }
    try {
        final CompoundTag compound;
        try (final FileInputStream in = new FileInputStream(file)) {
            compound = NbtIo.readCompressed(in);
        }
        // See PlayerDataAccess - keep this line up to date.
        final int version = compound.contains("DataVersion", 3) ? compound.getInt("DataVersion") : -1;
        NbtUtils.update(DataFixers.getDataFixer(), DataFixTypes.PLAYER, compound, version);
        return new SpongeUserData(profile, compound);
    } catch (final IOException e) {
        SpongeCommon.logger().warn("Unable to load corrupt user file '{}'!", file.toPath().relativize(Paths.get("")).toString(), e);
        FileUtil.copyCorruptedFile(file);
        throw e;
    }
}
Also used : MinecraftServerAccessor(org.spongepowered.common.accessor.server.MinecraftServerAccessor) ServerLevel(net.minecraft.server.level.ServerLevel) LevelStorageSource(net.minecraft.world.level.storage.LevelStorageSource) IOException(java.io.IOException) File(java.io.File) CompoundTag(net.minecraft.nbt.CompoundTag) FileInputStream(java.io.FileInputStream)

Aggregations

ServerLevel (net.minecraft.server.level.ServerLevel)115 BlockPos (net.minecraft.core.BlockPos)30 Nullable (org.checkerframework.checker.nullness.qual.Nullable)21 Level (net.minecraft.world.level.Level)20 BlockEntity (net.minecraft.world.level.block.entity.BlockEntity)16 Entity (net.minecraft.world.entity.Entity)14 ServerPlayer (net.minecraft.server.level.ServerPlayer)11 ItemStack (net.minecraft.world.item.ItemStack)10 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)10 IOException (java.io.IOException)9 LevelChunk (net.minecraft.world.level.chunk.LevelChunk)9 CraftWorld (org.bukkit.craftbukkit.v1_18_R1.CraftWorld)9 ArrayList (java.util.ArrayList)8 BlockState (net.minecraft.world.level.block.state.BlockState)8 List (java.util.List)7 Optional (java.util.Optional)7 UUID (java.util.UUID)7 Vec3 (net.minecraft.world.phys.Vec3)7 CraftWorld (org.bukkit.craftbukkit.v1_17_R1.CraftWorld)7 Cause (org.spongepowered.api.event.Cause)7