Search in sources :

Example 36 with ServerLevel

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

the class SpongeWorldManager method unloadWorld0.

private void unloadWorld0(final ServerLevel world) throws IOException {
    final net.minecraft.resources.ResourceKey<Level> registryKey = world.dimension();
    if (world.getPlayers(p -> true).size() != 0) {
        throw new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()));
    }
    SpongeCommon.logger().info("Unloading world '{}' ({})", registryKey.location(), RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) world.dimensionType()));
    SpongeCommon.post(SpongeEventFactory.createUnloadWorldEvent(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.world.server.ServerWorld) world));
    final BlockPos spawnPoint = world.getSharedSpawnPos();
    world.getChunkSource().removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, new ChunkPos(spawnPoint), 11, registryKey.location());
    ((PrimaryLevelDataBridge) world.getLevelData()).bridge$configAdapter().save();
    ((ServerLevelBridge) world).bridge$setManualSave(true);
    try {
        world.save(null, true, world.noSave);
        world.close();
        ((ServerLevelBridge) world).bridge$getLevelSave().close();
    } catch (final Exception ex) {
        throw new IOException(ex);
    }
    this.worlds.remove(registryKey);
}
Also used : IOException(java.io.IOException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ReportedException(net.minecraft.ReportedException) WorldType(org.spongepowered.api.world.WorldType) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) BlockPos(net.minecraft.core.BlockPos) ChunkPos(net.minecraft.world.level.ChunkPos) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge)

Example 37 with ServerLevel

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

the class SpongeWorldManager method deleteWorld.

@Override
public CompletableFuture<Boolean> deleteWorld(final ResourceKey key) {
    final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
    if (Level.OVERWORLD.equals(registryKey)) {
        return CompletableFuture.completedFuture(false);
    }
    if (!this.worldExists(key)) {
        return CompletableFuture.completedFuture(false);
    }
    final ServerLevel loadedWorld = this.worlds.get(registryKey);
    if (loadedWorld != null) {
        final boolean disableLevelSaving = loadedWorld.noSave;
        loadedWorld.noSave = true;
        try {
            this.unloadWorld0(loadedWorld);
        } catch (final IOException e) {
            loadedWorld.noSave = disableLevelSaving;
            return FutureUtil.completedWithException(e);
        }
    }
    final boolean isVanillaWorld = this.isVanillaWorld(key);
    final String directoryName = this.getDirectoryName(key);
    final Path directory = isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
    if (Files.exists(directory)) {
        try {
            for (final Path path : Files.walk(directory).sorted(Comparator.reverseOrder()).collect(Collectors.toList())) {
                Files.deleteIfExists(path);
            }
        } catch (final IOException e) {
            return FutureUtil.completedWithException(e);
        }
    }
    final Path configFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(key.namespace()).resolve(key.value() + ".conf");
    try {
        Files.deleteIfExists(configFile);
    } catch (final IOException e) {
        return FutureUtil.completedWithException(e);
    }
    final Path dimensionTemplate = this.getDataPackFile(key);
    try {
        Files.deleteIfExists(dimensionTemplate);
    } catch (final IOException e) {
        FutureUtil.completedWithException(e);
    }
    return CompletableFuture.completedFuture(true);
}
Also used : Path(java.nio.file.Path) ServerLevel(net.minecraft.server.level.ServerLevel) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) IOException(java.io.IOException)

Example 38 with ServerLevel

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

the class SpongeWorldManager method moveWorld.

@Override
public CompletableFuture<Boolean> moveWorld(final ResourceKey key, final ResourceKey movedKey) {
    final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
    if (Level.OVERWORLD.equals(registryKey)) {
        return CompletableFuture.completedFuture(false);
    }
    if (!this.worldExists(key)) {
        return CompletableFuture.completedFuture(false);
    }
    if (this.worldExists(movedKey)) {
        return CompletableFuture.completedFuture(false);
    }
    final ServerLevel loadedWorld = this.worlds.get(registryKey);
    if (loadedWorld != null) {
        try {
            this.unloadWorld0(loadedWorld);
        } catch (final IOException e) {
            return FutureUtil.completedWithException(e);
        }
    }
    final boolean isVanillaWorld = this.isVanillaWorld(key);
    final String directoryName = this.getDirectoryName(key);
    final Path originalDirectory = isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
    final boolean isVanillaMoveWorld = this.isVanillaWorld(movedKey);
    final String moveDirectoryName = this.getDirectoryName(movedKey);
    final Path moveDirectory = isVanillaMoveWorld ? this.defaultWorldDirectory.resolve(moveDirectoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
    try {
        Files.createDirectories(moveDirectory);
        Files.move(originalDirectory, moveDirectory, StandardCopyOption.REPLACE_EXISTING);
    } catch (final IOException e) {
        return FutureUtil.completedWithException(e);
    }
    final Path configFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(key.namespace()).resolve(key.value() + ".conf");
    final Path copiedConfigFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(movedKey.namespace()).resolve(movedKey.value() + ".conf");
    try {
        Files.createDirectories(copiedConfigFile.getParent());
        Files.move(configFile, copiedConfigFile, StandardCopyOption.REPLACE_EXISTING);
    } catch (final IOException e) {
        return FutureUtil.completedWithException(e);
    }
    final Path dimensionTemplate = this.getDataPackFile(key);
    final Path copiedDimensionTemplate = this.getDataPackFile(movedKey);
    try {
        Files.createDirectories(copiedDimensionTemplate.getParent());
        Files.move(dimensionTemplate, copiedDimensionTemplate, StandardCopyOption.REPLACE_EXISTING);
    } catch (final IOException e) {
        FutureUtil.completedWithException(e);
    }
    return CompletableFuture.completedFuture(true);
}
Also used : Path(java.nio.file.Path) ServerLevel(net.minecraft.server.level.ServerLevel) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) IOException(java.io.IOException)

Example 39 with ServerLevel

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

the class ServerLevelMixin_Tracker method shadow$addBlockEntity.

@SuppressWarnings({ "ConstantConditions", "RedundantCast" })
@Override
public boolean shadow$addBlockEntity(final net.minecraft.world.level.block.entity.BlockEntity tileEntity) {
    if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
        // out whoever is trying to remove tile entities asynchronously....
        return super.shadow$addBlockEntity(tileEntity);
    }
    // Otherwise, let's go on and check if we're recording transactions,
    // and if so, log the tile entity removal (may associate with an existing transaction,
    // or create a new transaction.
    final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext();
    if (current.doesBlockEventTracking()) {
        final BlockPos immutable = tileEntity.getBlockPos().immutable();
        if (tileEntity.getLevel() != (ServerLevel) (Object) this) {
            tileEntity.setLevelAndPosition((ServerLevel) (Object) this, immutable);
        }
        final ChunkAccess iChunk = this.shadow$getChunk(immutable.getX() >> 4, immutable.getZ() >> 4, ChunkStatus.FULL, false);
        if (!(iChunk instanceof LevelChunk)) {
            return super.shadow$addBlockEntity(tileEntity);
        }
        final LevelChunk chunk = this.shadow$getChunkAt(immutable);
        if (current.getTransactor().logTileAddition(tileEntity, () -> (ServerLevel) (Object) this, chunk)) {
            final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(AddTileEntityToWorldWhileProcessingEffect.getInstance()).addEffect(AddTileEntityToLoadedListInWorldEffect.getInstance()).addEffect(AddTileEntityToTickableListEffect.getInstance()).addEffect(TileOnLoadDuringAddToWorldEffect.getInstance()).build();
            return pipeline.processEffects(current, new PipelineCursor(tileEntity.getBlockState(), 0, immutable, tileEntity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
        }
    }
    return super.shadow$addBlockEntity(tileEntity);
}
Also used : ChunkAccess(net.minecraft.world.level.chunk.ChunkAccess) ServerLevel(net.minecraft.server.level.ServerLevel) TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) RemoveBlockEntity(org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) Entity(net.minecraft.world.entity.Entity) TileEntityPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) PipelineCursor(org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor) BlockPos(net.minecraft.core.BlockPos)

Example 40 with ServerLevel

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

the class ServerLevelMixin_Tracker method shadow$setBlockEntity.

@SuppressWarnings({ "RedundantCast", "ConstantConditions" })
@Override
public void shadow$setBlockEntity(final BlockPos pos, final net.minecraft.world.level.block.entity.@Nullable BlockEntity proposed) {
    final BlockPos immutable = pos.immutable();
    if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
        // If we're fake or not on the server thread, well, we could effectively call
        // out whoever is trying to remove tile entities asynchronously....
        super.shadow$setBlockEntity(pos, proposed);
        return;
    }
    if (proposed != null) {
        if (proposed.getLevel() != (ServerLevel) (Object) this) {
            proposed.setLevelAndPosition((ServerLevel) (Object) this, immutable);
        } else {
            proposed.setPosition(pos);
        }
    }
    // Otherwise, let's go on and check if we're recording transactions,
    // and if so, log the tile entity removal (may associate with an existing transaction,
    // or create a new transaction.
    final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext();
    if (current.doesBlockEventTracking()) {
        final net.minecraft.world.level.block.entity.@Nullable BlockEntity existing = this.shadow$getChunkAt(immutable).getBlockEntity(immutable);
        if (current.getTransactor().logTileReplacement(immutable, existing, proposed, () -> (ServerLevel) (Object) this)) {
            final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(RemoveProposedTileEntitiesDuringSetIfWorldProcessingEffect.getInstance()).addEffect(ReplaceTileEntityInWorldEffect.getInstance()).build();
            pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), 0, immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
            return;
        }
    }
    super.shadow$setBlockEntity(immutable, proposed);
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) RemoveBlockEntity(org.spongepowered.common.event.tracking.context.transaction.block.RemoveBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity) Entity(net.minecraft.world.entity.Entity) TileEntityPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.TileEntityPipeline) PipelineCursor(org.spongepowered.common.event.tracking.context.transaction.pipeline.PipelineCursor) BlockPos(net.minecraft.core.BlockPos) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

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