FunctionCommand.java

net.minecraft.server.commands.FunctionCommand

信息

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

    TODO

字段/常量

  • ERROR_ARGUMENT_NOT_COMPOUND

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

      TODO

  • ERROR_NO_FUNCTIONS

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

      TODO

  • ERROR_FUNCTION_INSTANTATION_FAILURE

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

      TODO

  • SUGGEST_FUNCTION

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

      TODO

  • FULL_CONTEXT_CALLBACKS

    • 类型: FunctionCommand.Callbacks<CommandSourceStack>
    • 修饰符: private static final public
    • 源码定位: L57
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.server.commands.FunctionCommand.Accumulator

    • 类型: class
    • 修饰符: package-private
    • 源码定位: L202
    • 说明:

      TODO

  • net.minecraft.server.commands.FunctionCommand.Callbacks

    • 类型: interface
    • 修饰符: public
    • 源码定位: L230
    • 说明:

      TODO

  • net.minecraft.server.commands.FunctionCommand.FunctionCustomExecutor

    • 类型: class
    • 修饰符: private abstract static
    • 源码定位: L234
    • 说明:

      TODO

构造器

方法

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

public static void register(CommandDispatcher<CommandSourceStack> dispatcher) @ L63

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

参数:

  • dispatcher: CommandDispatcher

说明:

TODO

private static CompoundTag getArgumentTag(NbtPathArgument.NbtPath path, DataAccessor accessor) @ L99

  • 方法名:getArgumentTag
  • 源码定位:L99
  • 返回类型:CompoundTag
  • 修饰符:private static

参数:

  • path: NbtPathArgument.NbtPath
  • accessor: DataAccessor

说明:

TODO

public static CommandSourceStack modifySenderForExecution(CommandSourceStack sender) @ L108

  • 方法名:modifySenderForExecution
  • 源码定位:L108
  • 返回类型:CommandSourceStack
  • 修饰符:public static

参数:

  • sender: CommandSourceStack

说明:

TODO

public static <T extends ExecutionCommandSource<T>> void queueFunctions(Collection<CommandFunction<T>> functions, CompoundTag arguments, T originalSource, T functionSource, ExecutionControl<T> output, FunctionCommand.Callbacks<T> callbacks, ChainModifiers modifiers) @ L112

  • 方法名:queueFunctions
  • 源码定位:L112
  • 返回类型:<T extends ExecutionCommandSource> void
  • 修饰符:public static

参数:

  • functions: Collection<CommandFunction>
  • arguments: CompoundTag
  • originalSource: T
  • functionSource: T
  • output: ExecutionControl
  • callbacks: FunctionCommand.Callbacks
  • modifiers: ChainModifiers

说明:

TODO

private static <T extends ExecutionCommandSource<T>> void instantiateAndQueueFunctions(CompoundTag arguments, ExecutionControl<T> output, CommandDispatcher<T> dispatcher, T noCallbackSource, CommandFunction<T> function, Identifier id, CommandResultCallback functionResultCollector, boolean returnParentFrame) @ L128

  • 方法名:instantiateAndQueueFunctions
  • 源码定位:L128
  • 返回类型:<T extends ExecutionCommandSource> void
  • 修饰符:private static

参数:

  • arguments: CompoundTag
  • output: ExecutionControl
  • dispatcher: CommandDispatcher
  • noCallbackSource: T
  • function: CommandFunction
  • id: Identifier
  • functionResultCollector: CommandResultCallback
  • returnParentFrame: boolean

说明:

TODO

private static <T extends ExecutionCommandSource<T>> CommandResultCallback decorateOutputIfNeeded(T originalSource, FunctionCommand.Callbacks<T> callbacks, Identifier id, CommandResultCallback callback) @ L146

  • 方法名:decorateOutputIfNeeded
  • 源码定位:L146
  • 返回类型:<T extends ExecutionCommandSource> CommandResultCallback
  • 修饰符:private static

参数:

  • originalSource: T
  • callbacks: FunctionCommand.Callbacks
  • id: Identifier
  • callback: CommandResultCallback

说明:

TODO

private static <T extends ExecutionCommandSource<T>> void queueFunctionsAsReturn(Collection<CommandFunction<T>> functions, CompoundTag arguments, T originalSource, T functionSource, ExecutionControl<T> output, FunctionCommand.Callbacks<T> callbacks) @ L155

  • 方法名:queueFunctionsAsReturn
  • 源码定位:L155
  • 返回类型:<T extends ExecutionCommandSource> void
  • 修饰符:private static

参数:

  • functions: Collection<CommandFunction>
  • arguments: CompoundTag
  • originalSource: T
  • functionSource: T
  • output: ExecutionControl
  • callbacks: FunctionCommand.Callbacks

说明:

TODO

private static <T extends ExecutionCommandSource<T>> void queueFunctionsNoReturn(Collection<CommandFunction<T>> functions, CompoundTag arguments, T originalSource, T functionSource, ExecutionControl<T> output, FunctionCommand.Callbacks<T> callbacks) @ L178

  • 方法名:queueFunctionsNoReturn
  • 源码定位:L178
  • 返回类型:<T extends ExecutionCommandSource> void
  • 修饰符:private static

参数:

  • functions: Collection<CommandFunction>
  • arguments: CompoundTag
  • originalSource: T
  • functionSource: T
  • output: ExecutionControl
  • callbacks: FunctionCommand.Callbacks

说明:

TODO

代码

public class FunctionCommand {
    private static final DynamicCommandExceptionType ERROR_ARGUMENT_NOT_COMPOUND = new DynamicCommandExceptionType(
        type -> Component.translatableEscape("commands.function.error.argument_not_compound", type)
    );
    private static final DynamicCommandExceptionType ERROR_NO_FUNCTIONS = new DynamicCommandExceptionType(
        name -> Component.translatableEscape("commands.function.scheduled.no_functions", name)
    );
    @VisibleForTesting
    public static final Dynamic2CommandExceptionType ERROR_FUNCTION_INSTANTATION_FAILURE = new Dynamic2CommandExceptionType(
        (id, reason) -> Component.translatableEscape("commands.function.instantiationFailure", id, reason)
    );
    public static final SuggestionProvider<CommandSourceStack> SUGGEST_FUNCTION = (c, p) -> {
        ServerFunctionManager manager = c.getSource().getServer().getFunctions();
        SharedSuggestionProvider.suggestResource(manager.getTagNames(), p, "#");
        return SharedSuggestionProvider.suggestResource(manager.getFunctionNames(), p);
    };
    private static final FunctionCommand.Callbacks<CommandSourceStack> FULL_CONTEXT_CALLBACKS = new FunctionCommand.Callbacks<CommandSourceStack>() {
        public void signalResult(CommandSourceStack originalSource, Identifier id, int newValue) {
            originalSource.sendSuccess(() -> Component.translatable("commands.function.result", Component.translationArg(id), newValue), true);
        }
    };
 
    public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        LiteralArgumentBuilder<CommandSourceStack> sources = Commands.literal("with");
 
        for (DataCommands.DataProvider provider : DataCommands.SOURCE_PROVIDERS) {
            provider.wrap(sources, p -> p.executes(new FunctionCommand.FunctionCustomExecutor() {
                @Override
                protected CompoundTag arguments(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
                    return provider.access(context).getData();
                }
            }).then(Commands.argument("path", NbtPathArgument.nbtPath()).executes(new FunctionCommand.FunctionCustomExecutor() {
                @Override
                protected CompoundTag arguments(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
                    return FunctionCommand.getArgumentTag(NbtPathArgument.getPath(context, "path"), provider.access(context));
                }
            })));
        }
 
        dispatcher.register(
            Commands.literal("function")
                .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
                .then(
                    Commands.argument("name", FunctionArgument.functions()).suggests(SUGGEST_FUNCTION).executes(new FunctionCommand.FunctionCustomExecutor() {
                        @Override
                        protected @Nullable CompoundTag arguments(CommandContext<CommandSourceStack> context) {
                            return null;
                        }
                    }).then(Commands.argument("arguments", CompoundTagArgument.compoundTag()).executes(new FunctionCommand.FunctionCustomExecutor() {
                        @Override
                        protected CompoundTag arguments(CommandContext<CommandSourceStack> context) {
                            return CompoundTagArgument.getCompoundTag(context, "arguments");
                        }
                    })).then(sources)
                )
        );
    }
 
    private static CompoundTag getArgumentTag(NbtPathArgument.NbtPath path, DataAccessor accessor) throws CommandSyntaxException {
        Tag tag = DataCommands.getSingleTag(path, accessor);
        if (tag instanceof CompoundTag compoundTag) {
            return compoundTag;
        } else {
            throw ERROR_ARGUMENT_NOT_COMPOUND.create(tag.getType().getName());
        }
    }
 
    public static CommandSourceStack modifySenderForExecution(CommandSourceStack sender) {
        return sender.withSuppressedOutput().withMaximumPermission(LevelBasedPermissionSet.GAMEMASTER);
    }
 
    public static <T extends ExecutionCommandSource<T>> void queueFunctions(
        Collection<CommandFunction<T>> functions,
        @Nullable CompoundTag arguments,
        T originalSource,
        T functionSource,
        ExecutionControl<T> output,
        FunctionCommand.Callbacks<T> callbacks,
        ChainModifiers modifiers
    ) throws CommandSyntaxException {
        if (modifiers.isReturn()) {
            queueFunctionsAsReturn(functions, arguments, originalSource, functionSource, output, callbacks);
        } else {
            queueFunctionsNoReturn(functions, arguments, originalSource, functionSource, output, callbacks);
        }
    }
 
    private static <T extends ExecutionCommandSource<T>> void instantiateAndQueueFunctions(
        @Nullable CompoundTag arguments,
        ExecutionControl<T> output,
        CommandDispatcher<T> dispatcher,
        T noCallbackSource,
        CommandFunction<T> function,
        Identifier id,
        CommandResultCallback functionResultCollector,
        boolean returnParentFrame
    ) throws CommandSyntaxException {
        try {
            InstantiatedFunction<T> instantiatedFunction = function.instantiate(arguments, dispatcher);
            output.queueNext(new CallFunction<>(instantiatedFunction, functionResultCollector, returnParentFrame).bind(noCallbackSource));
        } catch (FunctionInstantiationException var9) {
            throw ERROR_FUNCTION_INSTANTATION_FAILURE.create(id, var9.messageComponent());
        }
    }
 
    private static <T extends ExecutionCommandSource<T>> CommandResultCallback decorateOutputIfNeeded(
        T originalSource, FunctionCommand.Callbacks<T> callbacks, Identifier id, CommandResultCallback callback
    ) {
        return originalSource.isSilent() ? callback : (success, result) -> {
            callbacks.signalResult(originalSource, id, result);
            callback.onResult(success, result);
        };
    }
 
    private static <T extends ExecutionCommandSource<T>> void queueFunctionsAsReturn(
        Collection<CommandFunction<T>> functions,
        @Nullable CompoundTag arguments,
        T originalSource,
        T functionSource,
        ExecutionControl<T> output,
        FunctionCommand.Callbacks<T> callbacks
    ) throws CommandSyntaxException {
        CommandDispatcher<T> dispatcher = originalSource.dispatcher();
        T noCallbackSource = functionSource.clearCallbacks();
        CommandResultCallback functionCommandOutputCallback = CommandResultCallback.chain(
            originalSource.callback(), output.currentFrame().returnValueConsumer()
        );
 
        for (CommandFunction<T> function : functions) {
            Identifier id = function.id();
            CommandResultCallback functionResultCollector = decorateOutputIfNeeded(originalSource, callbacks, id, functionCommandOutputCallback);
            instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, true);
        }
 
        output.queueNext(FallthroughTask.instance());
    }
 
    private static <T extends ExecutionCommandSource<T>> void queueFunctionsNoReturn(
        Collection<CommandFunction<T>> functions,
        @Nullable CompoundTag arguments,
        T originalSource,
        T functionSource,
        ExecutionControl<T> output,
        FunctionCommand.Callbacks<T> callbacks
    ) throws CommandSyntaxException {
        CommandDispatcher<T> dispatcher = originalSource.dispatcher();
        T noCallbackSource = functionSource.clearCallbacks();
        CommandResultCallback originalCallback = originalSource.callback();
        if (!functions.isEmpty()) {
            if (functions.size() == 1) {
                CommandFunction<T> function = functions.iterator().next();
                Identifier id = function.id();
                CommandResultCallback functionResultCollector = decorateOutputIfNeeded(originalSource, callbacks, id, originalCallback);
                instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false);
            } else if (originalCallback == CommandResultCallback.EMPTY) {
                for (CommandFunction<T> function : functions) {
                    Identifier id = function.id();
                    CommandResultCallback functionResultCollector = decorateOutputIfNeeded(originalSource, callbacks, id, originalCallback);
                    instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false);
                }
            } else {
                class Accumulator {
                    private boolean anyResult;
                    private int sum;
 
                    public void add(int result) {
                        this.anyResult = true;
                        this.sum += result;
                    }
                }
 
                Accumulator accumulator = new Accumulator();
                CommandResultCallback partialResultCallback = (success, result) -> accumulator.add(result);
 
                for (CommandFunction<T> function : functions) {
                    Identifier id = function.id();
                    CommandResultCallback functionResultCollector = decorateOutputIfNeeded(originalSource, callbacks, id, partialResultCallback);
                    instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false);
                }
 
                output.queueNext((context, frame) -> {
                    if (accumulator.anyResult) {
                        originalCallback.onSuccess(accumulator.sum);
                    }
                });
            }
        }
    }
 
    public interface Callbacks<T> {
        void signalResult(T originalSource, Identifier functionId, int newValue);
    }
 
    private abstract static class FunctionCustomExecutor
        extends CustomCommandExecutor.WithErrorHandling<CommandSourceStack>
        implements CustomCommandExecutor.CommandAdapter<CommandSourceStack> {
        protected abstract @Nullable CompoundTag arguments(final CommandContext<CommandSourceStack> context) throws CommandSyntaxException;
 
        public void runGuarded(
            CommandSourceStack sender, ContextChain<CommandSourceStack> currentStep, ChainModifiers modifiers, ExecutionControl<CommandSourceStack> output
        ) throws CommandSyntaxException {
            CommandContext<CommandSourceStack> currentContext = currentStep.getTopContext().copyFor(sender);
            Pair<Identifier, Collection<CommandFunction<CommandSourceStack>>> nameAndFunctions = FunctionArgument.getFunctionCollection(currentContext, "name");
            Collection<CommandFunction<CommandSourceStack>> functions = nameAndFunctions.getSecond();
            if (functions.isEmpty()) {
                throw FunctionCommand.ERROR_NO_FUNCTIONS.create(Component.translationArg(nameAndFunctions.getFirst()));
            } else {
                CompoundTag arguments = this.arguments(currentContext);
                CommandSourceStack commonFunctionContext = FunctionCommand.modifySenderForExecution(sender);
                if (functions.size() == 1) {
                    sender.sendSuccess(
                        () -> Component.translatable("commands.function.scheduled.single", Component.translationArg(functions.iterator().next().id())), true
                    );
                } else {
                    sender.sendSuccess(
                        () -> Component.translatable(
                            "commands.function.scheduled.multiple",
                            ComponentUtils.formatList(functions.stream().map(CommandFunction::id).toList(), Component::translationArg)
                        ),
                        true
                    );
                }
 
                FunctionCommand.queueFunctions(functions, arguments, sender, commonFunctionContext, output, FunctionCommand.FULL_CONTEXT_CALLBACKS, modifiers);
            }
        }
    }
}

引用的其他类

  • CommandResultCallback

    • 引用位置: 参数/方法调用/返回值
    • 关联成员: CommandResultCallback.chain()
  • CommandSourceStack

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

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

    • 引用位置: 返回值
  • SharedSuggestionProvider

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

    • 引用位置: 方法调用
    • 关联成员: CompoundTagArgument.compoundTag(), CompoundTagArgument.getCompoundTag()
  • NbtPathArgument

    • 引用位置: 参数/方法调用
    • 关联成员: NbtPathArgument.getPath(), NbtPathArgument.nbtPath()
  • FunctionArgument

    • 引用位置: 方法调用
    • 关联成员: FunctionArgument.functions(), FunctionArgument.getFunctionCollection()
  • ChainModifiers

    • 引用位置: 参数
  • ExecutionControl

    • 引用位置: 参数
  • FallthroughTask

    • 引用位置: 方法调用
    • 关联成员: FallthroughTask.instance()
  • CommandFunction

    • 引用位置: 参数
  • CompoundTag

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

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

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

    • 引用位置: 参数
  • DataAccessor

    • 引用位置: 参数
  • DataCommands

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