166 lines
6.1 KiB
Java
166 lines
6.1 KiB
Java
package net.minecraft.commands.functions;
|
|
|
|
import com.mojang.brigadier.CommandDispatcher;
|
|
import com.mojang.brigadier.StringReader;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import it.unimi.dsi.fastutil.ints.IntList;
|
|
import it.unimi.dsi.fastutil.ints.IntLists;
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
|
import java.text.DecimalFormat;
|
|
import java.text.DecimalFormatSymbols;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.function.UnaryOperator;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.commands.ExecutionCommandSource;
|
|
import net.minecraft.commands.FunctionInstantiationException;
|
|
import net.minecraft.commands.execution.UnboundEntryAction;
|
|
import net.minecraft.nbt.ByteTag;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.DoubleTag;
|
|
import net.minecraft.nbt.FloatTag;
|
|
import net.minecraft.nbt.LongTag;
|
|
import net.minecraft.nbt.ShortTag;
|
|
import net.minecraft.nbt.StringTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class MacroFunction<T extends ExecutionCommandSource<T>> implements CommandFunction<T> {
|
|
private static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("#"), decimalFormat -> {
|
|
decimalFormat.setMaximumFractionDigits(15);
|
|
decimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.US));
|
|
});
|
|
private static final int MAX_CACHE_ENTRIES = 8;
|
|
private final List<String> parameters;
|
|
private final Object2ObjectLinkedOpenHashMap<List<String>, InstantiatedFunction<T>> cache = new Object2ObjectLinkedOpenHashMap<>(8, 0.25F);
|
|
private final ResourceLocation id;
|
|
private final List<MacroFunction.Entry<T>> entries;
|
|
|
|
public MacroFunction(ResourceLocation id, List<MacroFunction.Entry<T>> entries, List<String> parameters) {
|
|
this.id = id;
|
|
this.entries = entries;
|
|
this.parameters = parameters;
|
|
}
|
|
|
|
@Override
|
|
public ResourceLocation id() {
|
|
return this.id;
|
|
}
|
|
|
|
@Override
|
|
public InstantiatedFunction<T> instantiate(@Nullable CompoundTag arguments, CommandDispatcher<T> dispatcher) throws FunctionInstantiationException {
|
|
if (arguments == null) {
|
|
throw new FunctionInstantiationException(Component.translatable("commands.function.error.missing_arguments", Component.translationArg(this.id())));
|
|
} else {
|
|
List<String> list = new ArrayList(this.parameters.size());
|
|
|
|
for (String string : this.parameters) {
|
|
Tag tag = arguments.get(string);
|
|
if (tag == null) {
|
|
throw new FunctionInstantiationException(Component.translatable("commands.function.error.missing_argument", Component.translationArg(this.id()), string));
|
|
}
|
|
|
|
list.add(stringify(tag));
|
|
}
|
|
|
|
InstantiatedFunction<T> instantiatedFunction = this.cache.getAndMoveToLast(list);
|
|
if (instantiatedFunction != null) {
|
|
return instantiatedFunction;
|
|
} else {
|
|
if (this.cache.size() >= 8) {
|
|
this.cache.removeFirst();
|
|
}
|
|
|
|
InstantiatedFunction<T> instantiatedFunction2 = this.substituteAndParse(this.parameters, list, dispatcher);
|
|
this.cache.put(list, instantiatedFunction2);
|
|
return instantiatedFunction2;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static String stringify(Tag tag) {
|
|
return switch (tag) {
|
|
case FloatTag(float var24) -> DECIMAL_FORMAT.format(var24);
|
|
case DoubleTag(double var25) -> DECIMAL_FORMAT.format(var25);
|
|
case ByteTag(byte var26) -> String.valueOf(var26);
|
|
case ShortTag(short var27) -> String.valueOf(var27);
|
|
case LongTag(long var28) -> String.valueOf(var28);
|
|
case StringTag(String var17) -> var17;
|
|
default -> tag.toString();
|
|
};
|
|
}
|
|
|
|
private static void lookupValues(List<String> arguments, IntList parameters, List<String> output) {
|
|
output.clear();
|
|
parameters.forEach(i -> output.add((String)arguments.get(i)));
|
|
}
|
|
|
|
private InstantiatedFunction<T> substituteAndParse(List<String> argumentNames, List<String> argumentValues, CommandDispatcher<T> dispatcher) throws FunctionInstantiationException {
|
|
List<UnboundEntryAction<T>> list = new ArrayList(this.entries.size());
|
|
List<String> list2 = new ArrayList(argumentValues.size());
|
|
|
|
for (MacroFunction.Entry<T> entry : this.entries) {
|
|
lookupValues(argumentValues, entry.parameters(), list2);
|
|
list.add(entry.instantiate(list2, dispatcher, this.id));
|
|
}
|
|
|
|
return new PlainTextFunction<>(this.id().withPath((UnaryOperator<String>)(string -> string + "/" + argumentNames.hashCode())), list);
|
|
}
|
|
|
|
interface Entry<T> {
|
|
IntList parameters();
|
|
|
|
UnboundEntryAction<T> instantiate(List<String> arguments, CommandDispatcher<T> dispatcher, ResourceLocation function) throws FunctionInstantiationException;
|
|
}
|
|
|
|
static class MacroEntry<T extends ExecutionCommandSource<T>> implements MacroFunction.Entry<T> {
|
|
private final StringTemplate template;
|
|
private final IntList parameters;
|
|
private final T compilationContext;
|
|
|
|
public MacroEntry(StringTemplate template, IntList parameters, T compilationContext) {
|
|
this.template = template;
|
|
this.parameters = parameters;
|
|
this.compilationContext = compilationContext;
|
|
}
|
|
|
|
@Override
|
|
public IntList parameters() {
|
|
return this.parameters;
|
|
}
|
|
|
|
@Override
|
|
public UnboundEntryAction<T> instantiate(List<String> arguments, CommandDispatcher<T> dispatcher, ResourceLocation function) throws FunctionInstantiationException {
|
|
String string = this.template.substitute(arguments);
|
|
|
|
try {
|
|
return CommandFunction.parseCommand(dispatcher, this.compilationContext, new StringReader(string));
|
|
} catch (CommandSyntaxException var6) {
|
|
throw new FunctionInstantiationException(
|
|
Component.translatable("commands.function.error.parse", Component.translationArg(function), string, var6.getMessage())
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
static class PlainTextEntry<T> implements MacroFunction.Entry<T> {
|
|
private final UnboundEntryAction<T> compiledAction;
|
|
|
|
public PlainTextEntry(UnboundEntryAction<T> compiledAction) {
|
|
this.compiledAction = compiledAction;
|
|
}
|
|
|
|
@Override
|
|
public IntList parameters() {
|
|
return IntLists.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public UnboundEntryAction<T> instantiate(List<String> arguments, CommandDispatcher<T> dispatcher, ResourceLocation function) {
|
|
return this.compiledAction;
|
|
}
|
|
}
|
|
}
|