minecraft-src/net/minecraft/commands/functions/CommandFunction.java
2025-07-04 01:41:11 +03:00

102 lines
4 KiB
Java

package net.minecraft.commands.functions;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.context.ContextChain;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.List;
import java.util.Optional;
import net.minecraft.commands.Commands;
import net.minecraft.commands.ExecutionCommandSource;
import net.minecraft.commands.FunctionInstantiationException;
import net.minecraft.commands.execution.UnboundEntryAction;
import net.minecraft.commands.execution.tasks.BuildContexts;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
public interface CommandFunction<T> {
ResourceLocation id();
InstantiatedFunction<T> instantiate(@Nullable CompoundTag arguments, CommandDispatcher<T> dispatcher) throws FunctionInstantiationException;
private static boolean shouldConcatenateNextLine(CharSequence line) {
int i = line.length();
return i > 0 && line.charAt(i - 1) == '\\';
}
static <T extends ExecutionCommandSource<T>> CommandFunction<T> fromLines(ResourceLocation id, CommandDispatcher<T> dispatcher, T source, List<String> lines) {
FunctionBuilder<T> functionBuilder = new FunctionBuilder<>();
for (int i = 0; i < lines.size(); i++) {
int j = i + 1;
String string = ((String)lines.get(i)).trim();
String string3;
if (shouldConcatenateNextLine(string)) {
StringBuilder stringBuilder = new StringBuilder(string);
do {
if (++i == lines.size()) {
throw new IllegalArgumentException("Line continuation at end of file");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
String string2 = ((String)lines.get(i)).trim();
stringBuilder.append(string2);
checkCommandLineLength(stringBuilder);
} while (shouldConcatenateNextLine(stringBuilder));
string3 = stringBuilder.toString();
} else {
string3 = string;
}
checkCommandLineLength(string3);
StringReader stringReader = new StringReader(string3);
if (stringReader.canRead() && stringReader.peek() != '#') {
if (stringReader.peek() == '/') {
stringReader.skip();
if (stringReader.peek() == '/') {
throw new IllegalArgumentException("Unknown or invalid command '" + string3 + "' on line " + j + " (if you intended to make a comment, use '#' not '//')");
}
String string2 = stringReader.readUnquotedString();
throw new IllegalArgumentException(
"Unknown or invalid command '" + string3 + "' on line " + j + " (did you mean '" + string2 + "'? Do not use a preceding forwards slash.)"
);
}
if (stringReader.peek() == '$') {
functionBuilder.addMacro(string3.substring(1), j, source);
} else {
try {
functionBuilder.addCommand(parseCommand(dispatcher, source, stringReader));
} catch (CommandSyntaxException var11) {
throw new IllegalArgumentException("Whilst parsing command on line " + j + ": " + var11.getMessage());
}
}
}
}
return functionBuilder.build(id);
}
static void checkCommandLineLength(CharSequence command) {
if (command.length() > 2000000) {
CharSequence charSequence = command.subSequence(0, Math.min(512, 2000000));
throw new IllegalStateException("Command too long: " + command.length() + " characters, contents: " + charSequence + "...");
}
}
static <T extends ExecutionCommandSource<T>> UnboundEntryAction<T> parseCommand(CommandDispatcher<T> dispatcher, T source, StringReader command) throws CommandSyntaxException {
ParseResults<T> parseResults = dispatcher.parse(command, source);
Commands.validateParseResults(parseResults);
Optional<ContextChain<T>> optional = ContextChain.tryFlatten(parseResults.getContext().build(command.getString()));
if (optional.isEmpty()) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseResults.getReader());
} else {
return new BuildContexts.Unbound<>(command.getString(), (ContextChain<T>)optional.get());
}
}
}