DataPackCommand.java

net.minecraft.server.commands.DataPackCommand

信息

  • 全限定名:net.minecraft.server.commands.DataPackCommand
  • 类型:public class
  • 包:net.minecraft.server.commands
  • 源码路径:src/main/java/net/minecraft/server/commands/DataPackCommand.java
  • 起始行号:L47
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L48
    • 说明:

      TODO

  • ERROR_UNKNOWN_PACK

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L49
    • 说明:

      TODO

  • ERROR_PACK_ALREADY_ENABLED

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L52
    • 说明:

      TODO

  • ERROR_PACK_ALREADY_DISABLED

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L55
    • 说明:

      TODO

  • ERROR_CANNOT_DISABLE_FEATURE

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L58
    • 说明:

      TODO

  • ERROR_PACK_FEATURES_NOT_ENABLED

    • 类型: Dynamic2CommandExceptionType
    • 修饰符: private static final
    • 源码定位: L61
    • 说明:

      TODO

  • ERROR_PACK_INVALID_NAME

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L64
    • 说明:

      TODO

  • ERROR_PACK_INVALID_FULL_NAME

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L67
    • 说明:

      TODO

  • ERROR_PACK_ALREADY_EXISTS

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L70
    • 说明:

      TODO

  • ERROR_PACK_METADATA_ENCODE_FAILURE

    • 类型: Dynamic2CommandExceptionType
    • 修饰符: private static final
    • 源码定位: L73
    • 说明:

      TODO

  • ERROR_PACK_IO_FAILURE

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L76
    • 说明:

      TODO

  • SELECTED_PACKS

    • 类型: SuggestionProvider<CommandSourceStack>
    • 修饰符: private static final
    • 源码定位: L79
    • 说明:

      TODO

  • UNSELECTED_PACKS

    • 类型: SuggestionProvider<CommandSourceStack>
    • 修饰符: private static final
    • 源码定位: L82
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.commands.DataPackCommand.Inserter
    • 类型: interface
    • 修饰符: private
    • 源码定位: L308
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) @ L97

  • 方法名:register
  • 源码定位:L97
  • 返回类型:void
  • 修饰符:public static

参数:

  • dispatcher: CommandDispatcher
  • context: CommandBuildContext

说明:

TODO

private static int createPack(CommandSourceStack source, String id, Component description) @ L173

  • 方法名:createPack
  • 源码定位:L173
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • id: String
  • description: Component

说明:

TODO

private static int enablePack(CommandSourceStack source, Pack unopened, DataPackCommand.Inserter inserter) @ L219

  • 方法名:enablePack
  • 源码定位:L219
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • unopened: Pack
  • inserter: DataPackCommand.Inserter

说明:

TODO

private static int disablePack(CommandSourceStack source, Pack unopened) @ L228

  • 方法名:disablePack
  • 源码定位:L228
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack
  • unopened: Pack

说明:

TODO

private static int listPacks(CommandSourceStack source) @ L237

  • 方法名:listPacks
  • 源码定位:L237
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack

说明:

TODO

private static int listAvailablePacks(CommandSourceStack source) @ L241

  • 方法名:listAvailablePacks
  • 源码定位:L241
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack

说明:

TODO

private static int listEnabledPacks(CommandSourceStack source) @ L264

  • 方法名:listEnabledPacks
  • 源码定位:L264
  • 返回类型:int
  • 修饰符:private static

参数:

  • source: CommandSourceStack

说明:

TODO

private static Pack getPack(CommandContext<CommandSourceStack> context, String name, boolean enabling) @ L282

  • 方法名:getPack
  • 源码定位:L282
  • 返回类型:Pack
  • 修饰符:private static

参数:

  • context: CommandContext
  • name: String
  • enabling: boolean

说明:

TODO

代码

public class DataPackCommand {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final DynamicCommandExceptionType ERROR_UNKNOWN_PACK = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.unknown", id)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_ALREADY_ENABLED = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.enable.failed", id)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_ALREADY_DISABLED = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.disable.failed", id)
    );
    private static final DynamicCommandExceptionType ERROR_CANNOT_DISABLE_FEATURE = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.disable.failed.feature", id)
    );
    private static final Dynamic2CommandExceptionType ERROR_PACK_FEATURES_NOT_ENABLED = new Dynamic2CommandExceptionType(
        (id, flags) -> Component.translatableEscape("commands.datapack.enable.failed.no_flags", id, flags)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_INVALID_NAME = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.create.invalid_name", id)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_INVALID_FULL_NAME = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.create.invalid_full_name", id)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_ALREADY_EXISTS = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.create.already_exists", id)
    );
    private static final Dynamic2CommandExceptionType ERROR_PACK_METADATA_ENCODE_FAILURE = new Dynamic2CommandExceptionType(
        (id, error) -> Component.translatableEscape("commands.datapack.create.metadata_encode_failure", id, error)
    );
    private static final DynamicCommandExceptionType ERROR_PACK_IO_FAILURE = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("commands.datapack.create.io_failure", id)
    );
    private static final SuggestionProvider<CommandSourceStack> SELECTED_PACKS = (c, p) -> SharedSuggestionProvider.suggest(
        c.getSource().getServer().getPackRepository().getSelectedIds().stream().map(StringArgumentType::escapeIfRequired), p
    );
    private static final SuggestionProvider<CommandSourceStack> UNSELECTED_PACKS = (c, p) -> {
        PackRepository packRepository = c.getSource().getServer().getPackRepository();
        Collection<String> selectedIds = packRepository.getSelectedIds();
        FeatureFlagSet enabledFeatures = c.getSource().enabledFeatures();
        return SharedSuggestionProvider.suggest(
            packRepository.getAvailablePacks()
                .stream()
                .filter(pack -> pack.getRequestedFeatures().isSubsetOf(enabledFeatures))
                .map(Pack::getId)
                .filter(id -> !selectedIds.contains(id))
                .map(StringArgumentType::escapeIfRequired),
            p
        );
    };
 
    public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
        dispatcher.register(
            Commands.literal("datapack")
                .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
                .then(
                    Commands.literal("enable")
                        .then(
                            Commands.argument("name", StringArgumentType.string())
                                .suggests(UNSELECTED_PACKS)
                                .executes(
                                    c -> enablePack(
                                        c.getSource(), getPack(c, "name", true), (l, p) -> p.getDefaultPosition().insert(l, p, Pack::selectionConfig, false)
                                    )
                                )
                                .then(
                                    Commands.literal("after")
                                        .then(
                                            Commands.argument("existing", StringArgumentType.string())
                                                .suggests(SELECTED_PACKS)
                                                .executes(
                                                    c -> enablePack(
                                                        c.getSource(),
                                                        getPack(c, "name", true),
                                                        (l, p) -> l.add(l.indexOf(getPack(c, "existing", false)) + 1, p)
                                                    )
                                                )
                                        )
                                )
                                .then(
                                    Commands.literal("before")
                                        .then(
                                            Commands.argument("existing", StringArgumentType.string())
                                                .suggests(SELECTED_PACKS)
                                                .executes(
                                                    c -> enablePack(
                                                        c.getSource(), getPack(c, "name", true), (l, p) -> l.add(l.indexOf(getPack(c, "existing", false)), p)
                                                    )
                                                )
                                        )
                                )
                                .then(Commands.literal("last").executes(c -> enablePack(c.getSource(), getPack(c, "name", true), List::add)))
                                .then(Commands.literal("first").executes(c -> enablePack(c.getSource(), getPack(c, "name", true), (l, p) -> l.add(0, p))))
                        )
                )
                .then(
                    Commands.literal("disable")
                        .then(
                            Commands.argument("name", StringArgumentType.string())
                                .suggests(SELECTED_PACKS)
                                .executes(c -> disablePack(c.getSource(), getPack(c, "name", false)))
                        )
                )
                .then(
                    Commands.literal("list")
                        .executes(c -> listPacks(c.getSource()))
                        .then(Commands.literal("available").executes(c -> listAvailablePacks(c.getSource())))
                        .then(Commands.literal("enabled").executes(c -> listEnabledPacks(c.getSource())))
                )
                .then(
                    Commands.literal("create")
                        .requires(Commands.hasPermission(Commands.LEVEL_OWNERS))
                        .then(
                            Commands.argument("id", StringArgumentType.string())
                                .then(
                                    Commands.argument("description", ComponentArgument.textComponent(context))
                                        .executes(
                                            c -> createPack(
                                                c.getSource(), StringArgumentType.getString(c, "id"), ComponentArgument.getResolvedComponent(c, "description")
                                            )
                                        )
                                )
                        )
                )
        );
    }
 
    private static int createPack(CommandSourceStack source, String id, Component description) throws CommandSyntaxException {
        Path datapackDir = source.getServer().getWorldPath(LevelResource.DATAPACK_DIR);
        if (!FileUtil.isValidPathSegment(id)) {
            throw ERROR_PACK_INVALID_NAME.create(id);
        } else if (!FileUtil.isPathPartPortable(id)) {
            throw ERROR_PACK_INVALID_FULL_NAME.create(id);
        } else {
            Path packDir = datapackDir.resolve(id);
            if (Files.exists(packDir)) {
                throw ERROR_PACK_ALREADY_EXISTS.create(id);
            } else {
                PackMetadataSection packMetadataSection = new PackMetadataSection(
                    description, SharedConstants.getCurrentVersion().packVersion(PackType.SERVER_DATA).minorRange()
                );
                DataResult<JsonElement> encodedMeta = PackMetadataSection.SERVER_TYPE.codec().encodeStart(JsonOps.INSTANCE, packMetadataSection);
                Optional<Error<JsonElement>> error = encodedMeta.error();
                if (error.isPresent()) {
                    throw ERROR_PACK_METADATA_ENCODE_FAILURE.create(id, error.get().message());
                } else {
                    JsonObject topMcmeta = new JsonObject();
                    topMcmeta.add(PackMetadataSection.SERVER_TYPE.name(), encodedMeta.getOrThrow());
 
                    try {
                        Files.createDirectory(packDir);
                        Files.createDirectory(packDir.resolve(PackType.SERVER_DATA.getDirectory()));
 
                        try (
                            BufferedWriter mcmetaFile = Files.newBufferedWriter(packDir.resolve("pack.mcmeta"), StandardCharsets.UTF_8);
                            JsonWriter jsonWriter = new JsonWriter(mcmetaFile);
                        ) {
                            jsonWriter.setSerializeNulls(false);
                            jsonWriter.setIndent("  ");
                            GsonHelper.writeValue(jsonWriter, topMcmeta, null);
                        }
                    } catch (IOException var17) {
                        LOGGER.warn("Failed to create pack at {}", datapackDir.toAbsolutePath(), var17);
                        throw ERROR_PACK_IO_FAILURE.create(id);
                    }
 
                    source.sendSuccess(() -> Component.translatable("commands.datapack.create.success", id), true);
                    return 1;
                }
            }
        }
    }
 
    private static int enablePack(CommandSourceStack source, Pack unopened, DataPackCommand.Inserter inserter) throws CommandSyntaxException {
        PackRepository packRepository = source.getServer().getPackRepository();
        List<Pack> selected = Lists.newArrayList(packRepository.getSelectedPacks());
        inserter.apply(selected, unopened);
        source.sendSuccess(() -> Component.translatable("commands.datapack.modify.enable", unopened.getChatLink(true)), true);
        ReloadCommand.reloadPacks(selected.stream().map(Pack::getId).collect(Collectors.toList()), source);
        return selected.size();
    }
 
    private static int disablePack(CommandSourceStack source, Pack unopened) {
        PackRepository packRepository = source.getServer().getPackRepository();
        List<Pack> selected = Lists.newArrayList(packRepository.getSelectedPacks());
        selected.remove(unopened);
        source.sendSuccess(() -> Component.translatable("commands.datapack.modify.disable", unopened.getChatLink(true)), true);
        ReloadCommand.reloadPacks(selected.stream().map(Pack::getId).collect(Collectors.toList()), source);
        return selected.size();
    }
 
    private static int listPacks(CommandSourceStack source) {
        return listEnabledPacks(source) + listAvailablePacks(source);
    }
 
    private static int listAvailablePacks(CommandSourceStack source) {
        PackRepository repository = source.getServer().getPackRepository();
        repository.reload();
        Collection<Pack> selectedPacks = repository.getSelectedPacks();
        Collection<Pack> availablePacks = repository.getAvailablePacks();
        FeatureFlagSet enabledFeatures = source.enabledFeatures();
        List<Pack> unselectedPacks = availablePacks.stream()
            .filter(p -> !selectedPacks.contains(p) && p.getRequestedFeatures().isSubsetOf(enabledFeatures))
            .toList();
        if (unselectedPacks.isEmpty()) {
            source.sendSuccess(() -> Component.translatable("commands.datapack.list.available.none"), false);
        } else {
            source.sendSuccess(
                () -> Component.translatable(
                    "commands.datapack.list.available.success", unselectedPacks.size(), ComponentUtils.formatList(unselectedPacks, p -> p.getChatLink(false))
                ),
                false
            );
        }
 
        return unselectedPacks.size();
    }
 
    private static int listEnabledPacks(CommandSourceStack source) {
        PackRepository repository = source.getServer().getPackRepository();
        repository.reload();
        Collection<? extends Pack> selectedPacks = repository.getSelectedPacks();
        if (selectedPacks.isEmpty()) {
            source.sendSuccess(() -> Component.translatable("commands.datapack.list.enabled.none"), false);
        } else {
            source.sendSuccess(
                () -> Component.translatable(
                    "commands.datapack.list.enabled.success", selectedPacks.size(), ComponentUtils.formatList(selectedPacks, p -> p.getChatLink(true))
                ),
                false
            );
        }
 
        return selectedPacks.size();
    }
 
    private static Pack getPack(CommandContext<CommandSourceStack> context, String name, boolean enabling) throws CommandSyntaxException {
        String id = StringArgumentType.getString(context, name);
        PackRepository repository = context.getSource().getServer().getPackRepository();
        Pack pack = repository.getPack(id);
        if (pack == null) {
            throw ERROR_UNKNOWN_PACK.create(id);
        } else {
            boolean enabled = repository.getSelectedPacks().contains(pack);
            if (enabling && enabled) {
                throw ERROR_PACK_ALREADY_ENABLED.create(id);
            } else if (!enabling && !enabled) {
                throw ERROR_PACK_ALREADY_DISABLED.create(id);
            } else {
                FeatureFlagSet availableFeatures = context.getSource().enabledFeatures();
                FeatureFlagSet requestedFeatures = pack.getRequestedFeatures();
                if (!enabling && !requestedFeatures.isEmpty() && pack.getPackSource() == PackSource.FEATURE) {
                    throw ERROR_CANNOT_DISABLE_FEATURE.create(id);
                } else if (!requestedFeatures.isSubsetOf(availableFeatures)) {
                    throw ERROR_PACK_FEATURES_NOT_ENABLED.create(id, FeatureFlags.printMissingFlags(availableFeatures, requestedFeatures));
                } else {
                    return pack;
                }
            }
        }
    }
 
    private interface Inserter {
        void apply(final List<Pack> selected, final Pack pack) throws CommandSyntaxException;
    }
}

引用的其他类

  • SharedConstants

    • 引用位置: 方法调用
    • 关联成员: SharedConstants.getCurrentVersion()
  • CommandBuildContext

    • 引用位置: 参数
  • CommandSourceStack

    • 引用位置: 参数/字段
  • Commands

    • 引用位置: 方法调用
    • 关联成员: Commands.argument(), Commands.hasPermission(), Commands.literal()
  • SharedSuggestionProvider

    • 引用位置: 方法调用
    • 关联成员: SharedSuggestionProvider.suggest()
  • ComponentArgument

    • 引用位置: 方法调用
    • 关联成员: ComponentArgument.getResolvedComponent(), ComponentArgument.textComponent()
  • Component

    • 引用位置: 参数/方法调用
    • 关联成员: Component.translatable(), Component.translatableEscape()
  • ComponentUtils

    • 引用位置: 方法调用
    • 关联成员: ComponentUtils.formatList()
  • ReloadCommand

    • 引用位置: 方法调用
    • 关联成员: ReloadCommand.reloadPacks()
  • PackMetadataSection

    • 引用位置: 构造调用
    • 关联成员: PackMetadataSection()
  • Pack

    • 引用位置: 参数/返回值
  • FileUtil

    • 引用位置: 方法调用
    • 关联成员: FileUtil.isPathPartPortable(), FileUtil.isValidPathSegment()
  • GsonHelper

    • 引用位置: 方法调用
    • 关联成员: GsonHelper.writeValue()
  • FeatureFlags

    • 引用位置: 方法调用
    • 关联成员: FeatureFlags.printMissingFlags()