/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.annotations.VisibleForTesting * com.mojang.brigadier.Command * com.mojang.brigadier.CommandDispatcher * com.mojang.brigadier.builder.ArgumentBuilder * com.mojang.brigadier.builder.LiteralArgumentBuilder * com.mojang.brigadier.builder.RequiredArgumentBuilder * com.mojang.brigadier.context.CommandContext * com.mojang.brigadier.context.ContextChain * com.mojang.brigadier.exceptions.CommandSyntaxException * com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType * com.mojang.brigadier.exceptions.DynamicCommandExceptionType * com.mojang.brigadier.suggestion.SuggestionProvider * com.mojang.datafixers.util.Pair * org.jspecify.annotations.Nullable */ package net.minecraft.server.commands; import com.google.common.annotations.VisibleForTesting; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.ContextChain; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.datafixers.util.Pair; import java.util.Collection; import net.minecraft.commands.CommandResultCallback; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.ExecutionCommandSource; import net.minecraft.commands.FunctionInstantiationException; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.arguments.CompoundTagArgument; import net.minecraft.commands.arguments.NbtPathArgument; import net.minecraft.commands.arguments.item.FunctionArgument; import net.minecraft.commands.execution.ChainModifiers; import net.minecraft.commands.execution.CustomCommandExecutor; import net.minecraft.commands.execution.ExecutionControl; import net.minecraft.commands.execution.tasks.CallFunction; import net.minecraft.commands.execution.tasks.FallthroughTask; import net.minecraft.commands.functions.CommandFunction; import net.minecraft.commands.functions.InstantiatedFunction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.resources.Identifier; import net.minecraft.server.ServerFunctionManager; import net.minecraft.server.commands.data.DataAccessor; import net.minecraft.server.commands.data.DataCommands; import net.minecraft.server.permissions.LevelBasedPermissionSet; import org.jspecify.annotations.Nullable; 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 SUGGEST_FUNCTION = (c, p) -> { ServerFunctionManager manager = ((CommandSourceStack)c.getSource()).getServer().getFunctions(); SharedSuggestionProvider.suggestResource(manager.getTagNames(), p, "#"); return SharedSuggestionProvider.suggestResource(manager.getFunctionNames(), p); }; private static final Callbacks FULL_CONTEXT_CALLBACKS = new Callbacks(){ @Override 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 dispatcher) { LiteralArgumentBuilder sources = Commands.literal("with"); for (final DataCommands.DataProvider provider : DataCommands.SOURCE_PROVIDERS) { provider.wrap((ArgumentBuilder)sources, p -> p.executes((Command)new FunctionCustomExecutor(){ @Override protected CompoundTag arguments(CommandContext context) throws CommandSyntaxException { return provider.access(context).getData(); } }).then(Commands.argument("path", NbtPathArgument.nbtPath()).executes((Command)new FunctionCustomExecutor(){ @Override protected CompoundTag arguments(CommandContext context) throws CommandSyntaxException { return FunctionCommand.getArgumentTag(NbtPathArgument.getPath(context, "path"), provider.access(context)); } }))); } dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("function").requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("name", FunctionArgument.functions()).suggests(SUGGEST_FUNCTION).executes((Command)new FunctionCustomExecutor(){ @Override protected @Nullable CompoundTag arguments(CommandContext context) { return null; } })).then(Commands.argument("arguments", CompoundTagArgument.compoundTag()).executes((Command)new FunctionCustomExecutor(){ @Override protected CompoundTag arguments(CommandContext 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 compoundTag = (CompoundTag)tag; return compoundTag; } throw ERROR_ARGUMENT_NOT_COMPOUND.create((Object)tag.getType().getName()); } public static CommandSourceStack modifySenderForExecution(CommandSourceStack sender) { return sender.withSuppressedOutput().withMaximumPermission(LevelBasedPermissionSet.GAMEMASTER); } public static > void queueFunctions(Collection> functions, @Nullable CompoundTag arguments, T originalSource, T functionSource, ExecutionControl output, Callbacks callbacks, ChainModifiers modifiers) throws CommandSyntaxException { if (modifiers.isReturn()) { FunctionCommand.queueFunctionsAsReturn(functions, arguments, originalSource, functionSource, output, callbacks); } else { FunctionCommand.queueFunctionsNoReturn(functions, arguments, originalSource, functionSource, output, callbacks); } } private static > void instantiateAndQueueFunctions(@Nullable CompoundTag arguments, ExecutionControl output, CommandDispatcher dispatcher, T noCallbackSource, CommandFunction function, Identifier id, CommandResultCallback functionResultCollector, boolean returnParentFrame) throws CommandSyntaxException { try { InstantiatedFunction instantiatedFunction = function.instantiate(arguments, dispatcher); output.queueNext(new CallFunction(instantiatedFunction, functionResultCollector, returnParentFrame).bind(noCallbackSource)); } catch (FunctionInstantiationException exception) { throw ERROR_FUNCTION_INSTANTATION_FAILURE.create((Object)id, (Object)exception.messageComponent()); } } private static > CommandResultCallback decorateOutputIfNeeded(T originalSource, Callbacks callbacks, Identifier id, CommandResultCallback callback) { if (originalSource.isSilent()) { return callback; } return (success, result) -> { callbacks.signalResult(originalSource, id, result); callback.onResult(success, result); }; } private static > void queueFunctionsAsReturn(Collection> functions, @Nullable CompoundTag arguments, T originalSource, T functionSource, ExecutionControl output, Callbacks callbacks) throws CommandSyntaxException { CommandDispatcher dispatcher = originalSource.dispatcher(); T noCallbackSource = functionSource.clearCallbacks(); CommandResultCallback functionCommandOutputCallback = CommandResultCallback.chain(originalSource.callback(), output.currentFrame().returnValueConsumer()); for (CommandFunction function : functions) { Identifier id = function.id(); CommandResultCallback functionResultCollector = FunctionCommand.decorateOutputIfNeeded(originalSource, callbacks, id, functionCommandOutputCallback); FunctionCommand.instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, true); } output.queueNext(FallthroughTask.instance()); } private static > void queueFunctionsNoReturn(Collection> functions, @Nullable CompoundTag arguments, T originalSource, T functionSource, ExecutionControl output, Callbacks callbacks) throws CommandSyntaxException { CommandDispatcher dispatcher = originalSource.dispatcher(); T noCallbackSource = functionSource.clearCallbacks(); CommandResultCallback originalCallback = originalSource.callback(); if (functions.isEmpty()) { return; } if (functions.size() == 1) { CommandFunction function = functions.iterator().next(); Identifier id = function.id(); CommandResultCallback functionResultCollector = FunctionCommand.decorateOutputIfNeeded(originalSource, callbacks, id, originalCallback); FunctionCommand.instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false); } else if (originalCallback == CommandResultCallback.EMPTY) { for (CommandFunction function : functions) { Identifier id = function.id(); CommandResultCallback functionResultCollector = FunctionCommand.decorateOutputIfNeeded(originalSource, callbacks, id, originalCallback); FunctionCommand.instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false); } } else { class Accumulator { private boolean anyResult; private int sum; Accumulator() { } public void add(int result) { this.anyResult = true; this.sum += result; } } Accumulator accumulator = new Accumulator(); CommandResultCallback partialResultCallback = (success, result) -> accumulator.add(result); for (CommandFunction function : functions) { Identifier id = function.id(); CommandResultCallback functionResultCollector = FunctionCommand.decorateOutputIfNeeded(originalSource, callbacks, id, partialResultCallback); FunctionCommand.instantiateAndQueueFunctions(arguments, output, dispatcher, noCallbackSource, function, id, functionResultCollector, false); } output.queueNext((context, frame) -> { if (accumulator.anyResult) { originalCallback.onSuccess(accumulator.sum); } }); } } public static interface Callbacks { public void signalResult(T var1, Identifier var2, int var3); } private static abstract class FunctionCustomExecutor extends CustomCommandExecutor.WithErrorHandling implements CustomCommandExecutor.CommandAdapter { private FunctionCustomExecutor() { } protected abstract @Nullable CompoundTag arguments(CommandContext var1) throws CommandSyntaxException; @Override public void runGuarded(CommandSourceStack sender, ContextChain currentStep, ChainModifiers modifiers, ExecutionControl output) throws CommandSyntaxException { CommandContext currentContext = currentStep.getTopContext().copyFor((Object)sender); Pair>> nameAndFunctions = FunctionArgument.getFunctionCollection((CommandContext)currentContext, "name"); Collection functions = (Collection)nameAndFunctions.getSecond(); if (functions.isEmpty()) { throw ERROR_NO_FUNCTIONS.create((Object)Component.translationArg((Identifier)nameAndFunctions.getFirst())); } CompoundTag arguments = this.arguments((CommandContext)currentContext); CommandSourceStack commonFunctionContext = FunctionCommand.modifySenderForExecution(sender); if (functions.size() == 1) { sender.sendSuccess(() -> Component.translatable("commands.function.scheduled.single", Component.translationArg(((CommandFunction)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, FULL_CONTEXT_CALLBACKS, modifiers); } } }