Search in sources :

Example 41 with Level

use of net.minecraft.world.level.Level in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method copyWorld.

@Override
public CompletableFuture<Boolean> copyWorld(final ResourceKey key, final ResourceKey copyKey) {
    final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
    final net.minecraft.resources.ResourceKey<Level> copyRegistryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(copyKey, "copyKey"));
    if (Level.OVERWORLD.equals(copyRegistryKey)) {
        return CompletableFuture.completedFuture(false);
    }
    if (!this.worldExists(key)) {
        return CompletableFuture.completedFuture(false);
    }
    if (this.worldExists(copyKey)) {
        return CompletableFuture.completedFuture(false);
    }
    final ServerLevel loadedWorld = this.worlds.get(registryKey);
    boolean disableLevelSaving = false;
    if (loadedWorld != null) {
        disableLevelSaving = loadedWorld.noSave;
        loadedWorld.save(null, true, loadedWorld.noSave);
        loadedWorld.noSave = true;
    }
    final boolean isDefaultWorld = this.isDefaultWorld(key);
    final boolean isVanillaWorld = this.isVanillaWorld(key);
    final String directoryName = this.getDirectoryName(key);
    final Path originalDirectory = isDefaultWorld ? this.defaultWorldDirectory : isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
    final boolean isVanillaCopyWorld = this.isVanillaWorld(copyKey);
    final String copyDirectoryName = this.getDirectoryName(copyKey);
    final Path copyDirectory = isVanillaCopyWorld ? this.defaultWorldDirectory.resolve(copyDirectoryName) : this.customWorldsDirectory.resolve(copyKey.namespace()).resolve(copyKey.value());
    try {
        Files.walkFileTree(originalDirectory, new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
                // Silly recursion if the default world is being copied
                if (dir.getFileName().toString().equals(Constants.Sponge.World.DIMENSIONS_DIRECTORY)) {
                    return FileVisitResult.SKIP_SUBTREE;
                }
                // Silly copying of vanilla sub worlds if the default world is being copied
                if (isDefaultWorld && SpongeWorldManager.this.isVanillaSubWorld(dir.getFileName().toString())) {
                    return FileVisitResult.SKIP_SUBTREE;
                }
                final Path relativize = originalDirectory.relativize(dir);
                final Path directory = copyDirectory.resolve(relativize);
                Files.createDirectories(directory);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
                final String fileName = file.getFileName().toString();
                // Do not copy backups (not relevant anymore)
                if (fileName.equals(Constants.Sponge.World.LEVEL_SPONGE_DAT_OLD)) {
                    return FileVisitResult.CONTINUE;
                }
                if (fileName.equals(Constants.World.LEVEL_DAT_OLD)) {
                    return FileVisitResult.CONTINUE;
                }
                Files.copy(file, copyDirectory.resolve(originalDirectory.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
                return FileVisitResult.CONTINUE;
            }
        });
    } catch (final IOException e) {
        // Bail the whole deal if we hit IO problems!
        try {
            Files.deleteIfExists(copyDirectory);
        } catch (final IOException ignore) {
        }
        return FutureUtil.completedWithException(e);
    }
    if (loadedWorld != null) {
        loadedWorld.noSave = disableLevelSaving;
    }
    final Path dimensionTemplate = this.getDataPackFile(key);
    final Path copiedDimensionTemplate = this.getDataPackFile(copyKey);
    try {
        Files.createDirectories(copiedDimensionTemplate.getParent());
        Files.copy(dimensionTemplate, copiedDimensionTemplate);
    } catch (final IOException e) {
        FutureUtil.completedWithException(e);
    }
    final JsonObject fixedObject;
    try (final InputStream stream = Files.newInputStream(copiedDimensionTemplate);
        final InputStreamReader reader = new InputStreamReader(stream)) {
        final JsonParser parser = new JsonParser();
        final JsonElement element = parser.parse(reader);
        final JsonObject root = element.getAsJsonObject();
        final JsonObject spongeData = root.getAsJsonObject("#sponge");
        spongeData.remove("unique_id");
        fixedObject = root;
    } catch (final IOException e) {
        return FutureUtil.completedWithException(e);
    }
    if (fixedObject != null) {
        try (final BufferedWriter writer = Files.newBufferedWriter(copiedDimensionTemplate)) {
            writer.write(fixedObject.toString());
        } catch (final IOException e) {
            FutureUtil.completedWithException(e);
        }
    }
    return CompletableFuture.completedFuture(true);
}
Also used : Path(java.nio.file.Path) ServerLevel(net.minecraft.server.level.ServerLevel) InputStreamReader(java.io.InputStreamReader) InputStream(java.io.InputStream) JsonObject(com.google.gson.JsonObject) FileVisitResult(java.nio.file.FileVisitResult) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter) JsonElement(com.google.gson.JsonElement) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes) JsonParser(com.google.gson.JsonParser)

Example 42 with Level

use of net.minecraft.world.level.Level in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method loadWorld.

@Override
public CompletableFuture<org.spongepowered.api.world.server.ServerWorld> loadWorld(final WorldTemplate template) {
    final ResourceKey key = Objects.requireNonNull(template, "template").key();
    final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(key);
    if (Level.OVERWORLD.equals(registryKey)) {
        FutureUtil.completedWithException(new IllegalArgumentException("The default world cannot be told to load!"));
    }
    final ServerLevel serverWorld = this.worlds.get(registryKey);
    if (serverWorld != null) {
        return CompletableFuture.completedFuture((org.spongepowered.api.world.server.ServerWorld) serverWorld);
    }
    this.saveTemplate(template);
    return this.loadWorld0(registryKey, ((SpongeWorldTemplate) template).asDimension(), ((WorldGenSettings) template.generationConfig()));
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) WorldGenSettings(net.minecraft.world.level.levelgen.WorldGenSettings) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) ResourceKey(org.spongepowered.api.ResourceKey)

Example 43 with Level

use of net.minecraft.world.level.Level in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method loadWorld.

@Override
public CompletableFuture<org.spongepowered.api.world.server.ServerWorld> loadWorld(final ResourceKey key) {
    final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
    if (Level.OVERWORLD.equals(registryKey)) {
        FutureUtil.completedWithException(new IllegalArgumentException("The default world cannot be told to load!"));
    }
    final ServerLevel world = this.worlds.get(registryKey);
    if (world != null) {
        return CompletableFuture.completedFuture((org.spongepowered.api.world.server.ServerWorld) world);
    }
    return this.loadTemplate(key).thenCompose(r -> {
        WorldTemplate loadedTemplate = r.orElse(null);
        if (loadedTemplate == null) {
            final LevelStem scratch = BootstrapProperties.worldGenSettings.dimensions().get(net.minecraft.resources.ResourceKey.create(net.minecraft.core.Registry.LEVEL_STEM_REGISTRY, (ResourceLocation) (Object) key));
            if (scratch != null) {
                ((ResourceKeyBridge) (Object) scratch).bridge$setKey(key);
                loadedTemplate = new SpongeWorldTemplate(scratch);
            }
            if (loadedTemplate == null) {
                return FutureUtil.completedWithException(new IOException(String.format("Failed to load a template for '%s'!", key)));
            }
            this.saveTemplate(loadedTemplate);
        }
        return this.loadWorld0(registryKey, ((SpongeWorldTemplate) loadedTemplate).asDimension(), ((WorldGenSettings) loadedTemplate.generationConfig()));
    });
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) IOException(java.io.IOException) WorldGenSettings(net.minecraft.world.level.levelgen.WorldGenSettings) LevelStem(net.minecraft.world.level.dimension.LevelStem) ResourceLocation(net.minecraft.resources.ResourceLocation) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) WorldTemplate(org.spongepowered.api.world.server.WorldTemplate) ResourceKeyBridge(org.spongepowered.common.bridge.ResourceKeyBridge)

Example 44 with Level

use of net.minecraft.world.level.Level in project SpongeCommon by SpongePowered.

the class VolumeStreamUtils method getBlockEntityStream.

public static <R extends Region<R>> VolumeStream<R, BlockEntity> getBlockEntityStream(final LevelReader reader, final Vector3i min, final Vector3i max, final StreamOptions options) {
    VolumeStreamUtils.validateStreamArgs(Objects.requireNonNull(min, "min"), Objects.requireNonNull(max, "max"), Objects.requireNonNull(options, "options"));
    final boolean shouldCarbonCopy = options.carbonCopy();
    final Vector3i size = max.sub(min).add(1, 1, 1);
    @MonotonicNonNull final ObjectArrayMutableBlockEntityBuffer backingVolume;
    if (shouldCarbonCopy) {
        backingVolume = new ObjectArrayMutableBlockEntityBuffer(min, size);
    } else {
        backingVolume = null;
    }
    return VolumeStreamUtils.<R, BlockEntity, net.minecraft.world.level.block.entity.BlockEntity, ChunkAccess, BlockPos>generateStream(min, max, options, // Ref
    (R) reader, // IdentityFunction
    VolumeStreamUtils.getBlockEntityOrCloneToBackingVolume(shouldCarbonCopy, backingVolume, reader instanceof Level ? (Level) reader : null), // ChunkAccessor
    VolumeStreamUtils.getChunkAccessorByStatus(reader, options.loadingStyle().generateArea()), // TileEntity by block pos
    (key, tileEntity) -> key, // TileEntity Accessor
    (chunk) -> chunk instanceof LevelChunk ? ((LevelChunk) chunk).getBlockEntities().entrySet().stream().filter(entry -> VecHelper.inBounds(entry.getKey(), min, max)) : Stream.empty(), // Filtered Position TileEntity Accessor
    (blockPos, world) -> {
        final net.minecraft.world.level.block.entity.@Nullable BlockEntity tileEntity = shouldCarbonCopy ? backingVolume.getTileEntity(blockPos) : ((LevelReader) world).getBlockEntity(blockPos);
        return new Tuple<>(blockPos, tileEntity);
    });
}
Also used : ChunkAccess(net.minecraft.world.level.chunk.ChunkAccess) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) Vector3i(org.spongepowered.math.vector.Vector3i) BlockPos(net.minecraft.core.BlockPos) Level(net.minecraft.world.level.Level) ObjectArrayMutableBlockEntityBuffer(org.spongepowered.common.world.volume.buffer.blockentity.ObjectArrayMutableBlockEntityBuffer) Nullable(org.checkerframework.checker.nullness.qual.Nullable) Tuple(net.minecraft.util.Tuple) BlockEntity(org.spongepowered.api.block.entity.BlockEntity)

Example 45 with Level

use of net.minecraft.world.level.Level in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method loadLevel.

public void loadLevel() {
    final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData();
    final WorldGenSettings defaultGenerationSettings = defaultLevelData.worldGenSettings();
    final LevelSettings defaultLevelSettings = ((PrimaryLevelDataAccessor) defaultLevelData).accessor$settings();
    final MappedRegistry<LevelStem> templates = defaultGenerationSettings.dimensions();
    final boolean multiworldEnabled = this.server.isSingleplayer() || this.server.isNetherEnabled();
    if (!multiworldEnabled) {
        SpongeCommon.logger().warn("The option 'allow-nether' has been set to 'false' in the server.properties. " + "Multi-World support has been disabled and no worlds besides the default world will be loaded.");
    }
    for (final RegistryEntry<LevelStem> entry : ((Registry<LevelStem>) (Object) templates).streamEntries().collect(Collectors.toList())) {
        final ResourceKey worldKey = entry.key();
        final LevelStem template = entry.value();
        final LevelStemBridge templateBridge = (LevelStemBridge) (Object) template;
        ((ResourceKeyBridge) templateBridge).bridge$setKey(worldKey);
        final boolean isDefaultWorld = this.isDefaultWorld(worldKey);
        if (!isDefaultWorld && !multiworldEnabled) {
            continue;
        }
        final WorldType worldType = (WorldType) template.type();
        final ResourceKey worldTypeKey = RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) template.type());
        MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}' ({})", worldKey, worldTypeKey);
        if (!isDefaultWorld && !templateBridge.bridge$loadOnStartup()) {
            SpongeCommon.logger().warn("World '{}' has been disabled from loading at startup. Skipping...", worldKey);
            continue;
        }
        final String directoryName = this.getDirectoryName(worldKey);
        final boolean isVanillaSubLevel = this.isVanillaSubWorld(directoryName);
        final LevelStorageSource.LevelStorageAccess storageSource;
        if (isDefaultWorld) {
            storageSource = ((MinecraftServerAccessor) this.server).accessor$storageSource();
        } else {
            try {
                if (isVanillaSubLevel) {
                    storageSource = LevelStorageSource.createDefault(this.defaultWorldDirectory).createAccess(directoryName);
                } else {
                    storageSource = LevelStorageSource.createDefault(this.customWorldsDirectory).createAccess(worldKey.namespace() + File.separator + worldKey.value());
                }
            } catch (final IOException e) {
                throw new RuntimeException(String.format("Failed to create level data for world '%s'!", worldKey), e);
            }
        }
        PrimaryLevelData levelData;
        final boolean isDebugGeneration;
        if (isDefaultWorld) {
            levelData = defaultLevelData;
            isDebugGeneration = defaultGenerationSettings.isDebug();
        } else {
            levelData = (PrimaryLevelData) storageSource.getDataTag((DynamicOps<Tag>) BootstrapProperties.worldSettingsAdapter, defaultLevelSettings.getDataPackConfig());
            if (levelData == null) {
                final LevelSettings levelSettings;
                final WorldGenSettings generationSettings;
                if (this.server.isDemo()) {
                    levelSettings = MinecraftServer.DEMO_SETTINGS;
                    generationSettings = WorldGenSettings.demoSettings(BootstrapProperties.registries);
                } else {
                    levelSettings = new LevelSettings(directoryName, (GameType) (Object) BootstrapProperties.gameMode.get(Sponge.game()), templateBridge.bridge$hardcore().orElse(BootstrapProperties.hardcore), (Difficulty) (Object) BootstrapProperties.difficulty.get(Sponge.game()), templateBridge.bridge$commands().orElse(BootstrapProperties.commands), new GameRules(), defaultLevelData.getDataPackConfig());
                    generationSettings = ((WorldGenSettingsBridge) defaultLevelData.worldGenSettings()).bridge$copy();
                }
                isDebugGeneration = generationSettings.isDebug();
                ((DimensionGeneratorSettingsAccessor) generationSettings).accessor$dimensions(new MappedRegistry<>(net.minecraft.core.Registry.LEVEL_STEM_REGISTRY, Lifecycle.stable()));
                levelData = new PrimaryLevelData(levelSettings, generationSettings, Lifecycle.stable());
            } else {
                isDebugGeneration = levelData.worldGenSettings().isDebug();
            }
        }
        ((PrimaryLevelDataBridge) levelData).bridge$populateFromDimension(template);
        final InheritableConfigHandle<WorldConfig> configAdapter = SpongeGameConfigs.createWorld(worldTypeKey, worldKey);
        ((PrimaryLevelDataBridge) levelData).bridge$configAdapter(configAdapter);
        levelData.setModdedInfo(this.server.getServerModName(), this.server.getModdedStatus().isPresent());
        final long seed = BiomeManager.obfuscateSeed(levelData.worldGenSettings().seed());
        final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(worldKey);
        final ChunkProgressListener chunkStatusListener = ((MinecraftServerAccessor) this.server).accessor$progressListenerFactory().create(11);
        final List<CustomSpawner> spawners;
        if (isDefaultWorld) {
            spawners = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(levelData));
        } else {
            spawners = ImmutableList.of();
        }
        final ServerLevel world = new ServerLevel(this.server, ((MinecraftServerAccessor) this.server).accessor$executor(), storageSource, levelData, registryKey, (DimensionType) worldType, chunkStatusListener, template.generator(), isDebugGeneration, seed, spawners, true);
        // Ensure that the world border is registered.
        world.getWorldBorder().applySettings(levelData.getWorldBorder());
        this.worlds.put(registryKey, world);
        this.prepareWorld(world, isDebugGeneration);
    }
    ((MinecraftServerAccessor) this.server).invoker$forceDifficulty();
    for (final Map.Entry<net.minecraft.resources.ResourceKey<Level>, ServerLevel> entry : this.worlds.entrySet()) {
        try {
            this.postWorldLoad(entry.getValue(), true).get();
        } catch (final InterruptedException | ExecutionException e) {
            throw new IllegalStateException(e);
        }
    }
    ((SpongeUserManager) Sponge.server().userManager()).init();
    ((SpongeServer) SpongeCommon.server()).getPlayerDataManager().load();
}
Also used : DimensionGeneratorSettingsAccessor(org.spongepowered.common.accessor.world.gen.DimensionGeneratorSettingsAccessor) MinecraftServerAccessor(org.spongepowered.common.accessor.server.MinecraftServerAccessor) Difficulty(net.minecraft.world.Difficulty) GameType(net.minecraft.world.level.GameType) PrimaryLevelData(net.minecraft.world.level.storage.PrimaryLevelData) WorldGenSettings(net.minecraft.world.level.levelgen.WorldGenSettings) WanderingTraderSpawner(net.minecraft.world.entity.npc.WanderingTraderSpawner) WorldType(org.spongepowered.api.world.WorldType) VillageSiege(net.minecraft.world.entity.ai.village.VillageSiege) LevelStorageSource(net.minecraft.world.level.storage.LevelStorageSource) PrimaryLevelDataBridge(org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge) ResourceKey(org.spongepowered.api.ResourceKey) JsonObject(com.google.gson.JsonObject) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) LevelSettings(net.minecraft.world.level.LevelSettings) Map(java.util.Map) ServerLevel(net.minecraft.server.level.ServerLevel) ChunkProgressListener(net.minecraft.server.level.progress.ChunkProgressListener) WorldConfig(org.spongepowered.common.config.inheritable.WorldConfig) PatrolSpawner(net.minecraft.world.level.levelgen.PatrolSpawner) CustomSpawner(net.minecraft.world.level.CustomSpawner) CatSpawner(net.minecraft.world.entity.npc.CatSpawner) LevelStemBridge(org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge) ExecutionException(java.util.concurrent.ExecutionException) SpongeUserManager(org.spongepowered.common.user.SpongeUserManager) ResourceKeyBridge(org.spongepowered.common.bridge.ResourceKeyBridge) GameRules(net.minecraft.world.level.GameRules) IOException(java.io.IOException) LevelStem(net.minecraft.world.level.dimension.LevelStem) Tag(net.minecraft.nbt.Tag) PrimaryLevelDataAccessor(org.spongepowered.common.accessor.world.level.storage.PrimaryLevelDataAccessor) PhantomSpawner(net.minecraft.world.level.levelgen.PhantomSpawner)

Aggregations

Level (net.minecraft.world.level.Level)53 BlockPos (net.minecraft.core.BlockPos)26 ServerLevel (net.minecraft.server.level.ServerLevel)19 ItemStack (net.minecraft.world.item.ItemStack)14 BlockState (net.minecraft.world.level.block.state.BlockState)13 IOException (java.io.IOException)10 Direction (net.minecraft.core.Direction)8 ChunkPos (net.minecraft.world.level.ChunkPos)6 Path (java.nio.file.Path)5 ExecutionException (java.util.concurrent.ExecutionException)5 Nullable (javax.annotation.Nullable)5 Entity (net.minecraft.world.entity.Entity)5 Player (net.minecraft.world.entity.player.Player)5 BlockEntity (net.minecraft.world.level.block.entity.BlockEntity)5 LevelStem (net.minecraft.world.level.dimension.LevelStem)5 SubscribeEvent (net.minecraftforge.eventbus.api.SubscribeEvent)5 Map (java.util.Map)4 Set (java.util.Set)4 CompoundTag (net.minecraft.nbt.CompoundTag)4 ResourceLocation (net.minecraft.resources.ResourceLocation)4