2025-03-11 00:23:54 +01:00
|
|
|
package game.command;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
2025-03-18 01:29:36 +01:00
|
|
|
import java.util.Set;
|
2025-03-11 00:23:54 +01:00
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
import com.google.common.collect.Lists;
|
2025-03-16 17:40:47 +01:00
|
|
|
import com.google.common.collect.Maps;
|
2025-03-18 01:29:36 +01:00
|
|
|
import com.google.common.collect.Sets;
|
2025-03-16 17:40:47 +01:00
|
|
|
|
2025-03-11 00:23:54 +01:00
|
|
|
import game.block.Block;
|
|
|
|
import game.entity.Entity;
|
|
|
|
import game.entity.npc.EntityNPC;
|
|
|
|
import game.entity.types.EntityLiving;
|
|
|
|
import game.item.Item;
|
|
|
|
import game.item.ItemStack;
|
2025-03-19 02:08:41 +01:00
|
|
|
import game.nbt.NBTTagCompound;
|
2025-03-11 00:23:54 +01:00
|
|
|
import game.world.BlockPos;
|
|
|
|
import game.world.State;
|
|
|
|
import game.world.Vec3;
|
|
|
|
import game.world.WorldPos;
|
2025-03-18 01:29:36 +01:00
|
|
|
import game.world.WorldServer;
|
2025-03-11 00:23:54 +01:00
|
|
|
|
|
|
|
public class ScriptArgs {
|
|
|
|
private final String command;
|
|
|
|
private final Map<String, ScriptArg> arguments;
|
2025-03-18 01:29:36 +01:00
|
|
|
private final ScriptEnvironment env;
|
2025-03-11 00:23:54 +01:00
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
protected ScriptArgs(Map<String, ScriptArg> arguments, String command, ScriptEnvironment env) {
|
2025-03-11 00:23:54 +01:00
|
|
|
this.arguments = arguments;
|
|
|
|
this.command = command;
|
2025-03-18 01:29:36 +01:00
|
|
|
this.env = env;
|
2025-03-11 00:23:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private static <T> String joinArgs(Iterable<T> iter) {
|
|
|
|
StringBuilder sb = new StringBuilder("'");
|
|
|
|
for(T obj : iter) {
|
|
|
|
if(sb.length() > 1)
|
|
|
|
sb.append("', '");
|
|
|
|
sb.append(String.valueOf(obj));
|
|
|
|
}
|
|
|
|
return sb.append("'").toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static ScriptArgs parseArgs(ScriptEnvironment env, String str, String[] argv, CachedExecutable cached) {
|
|
|
|
Map<String, Parameter> parameters = cached.getParameters();
|
2025-03-18 01:29:36 +01:00
|
|
|
List<Parameter> positionals = Lists.newArrayList(cached.getPositionals());
|
2025-03-11 00:23:54 +01:00
|
|
|
// String[] argv = ArgumentParser.splitString(str);
|
|
|
|
Map<String, ScriptArg> args = Maps.newHashMap();
|
|
|
|
int ppos = 0;
|
|
|
|
boolean parse = true;
|
|
|
|
for(int z = 1; z < argv.length; z++) {
|
|
|
|
String arg = argv[z];
|
|
|
|
Parameter param = null;
|
|
|
|
boolean pos = false;
|
|
|
|
if(parse && arg.equals("--")) {
|
|
|
|
parse = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if(parse && (arg.startsWith("--") || (arg.startsWith("-") && arg.length() == 2))) {
|
|
|
|
param = parameters.get(arg.substring(arg.startsWith("--") ? 2 : 1));
|
|
|
|
if(param != null && param.isPositional() && !args.containsKey(param.getName())) {
|
|
|
|
for(int n = 0; n < positionals.size(); n++) {
|
|
|
|
if(param == positionals.get(n)) {
|
|
|
|
positionals.remove(n);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ppos < positionals.size()) {
|
|
|
|
param = positionals.get(ppos++);
|
|
|
|
pos = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw new ScriptException("Position %d: Parameter '%s' ist überflüssig", z, arg);
|
|
|
|
}
|
|
|
|
if(param == null)
|
|
|
|
throw new ScriptException("Position %d: Argument '%s' ist unbekannt", z, arg);
|
|
|
|
if(args.containsKey(param.getName()))
|
|
|
|
throw new ScriptException("Position %d: Parameter '%s' mehrfach angegeben", z, param.getName());
|
|
|
|
int nargs = param.getParsers().size();
|
|
|
|
// if(!pos)
|
|
|
|
// z += 1;
|
2025-03-18 01:29:36 +01:00
|
|
|
if(z + (pos ? 0 : 1) + nargs > argv.length)
|
2025-03-11 00:23:54 +01:00
|
|
|
if(nargs == 1 && param.getName().equals(param.getParsers().get(0).getName()))
|
|
|
|
throw new ScriptException("Position %d: Argument '%s' benötigt einen Parameter", z, param.getName());
|
|
|
|
else
|
|
|
|
throw new ScriptException("Position %d: Argument '%s' benötigt %d Parameter (%s)", z, param.getName(), nargs,
|
|
|
|
joinArgs(param.getParsers()));
|
|
|
|
Map<String, Object> params = Maps.newHashMapWithExpectedSize(nargs);
|
|
|
|
String[] inputs = new String[nargs + (pos ? 0 : 1)];
|
|
|
|
int apos = 0;
|
|
|
|
for(int n = pos ? 0 : 1; n < nargs + (pos ? 0 : 1); n++) {
|
|
|
|
String par = inputs[n] = argv[z + n];
|
|
|
|
ArgumentParser parser = param.getParsers().get(apos);
|
|
|
|
if(parse && (par.startsWith("--") || (par.startsWith("-") && par.length() == 2)))
|
|
|
|
if(nargs == 1 && param.getName().equals(parser.getName()))
|
|
|
|
throw new ScriptException("Position %d: Argument '%s': '%s' als Parameter verwendet", z + n, param.getName(), par);
|
|
|
|
else
|
|
|
|
throw new ScriptException("Position %d: Argument '%s': '%s' als Parameter '%s' (#%d) verwendet", z + n,
|
|
|
|
param.getName(), par, parser.getName(), apos + 1);
|
|
|
|
try {
|
|
|
|
params.put(parser.getName(), parser.parse(env, par));
|
|
|
|
}
|
|
|
|
catch(Throwable e) {
|
|
|
|
if(nargs == 1 && param.getName().equals(parser.getName()))
|
|
|
|
throw new ScriptException(e, "Position %d: Argument '%s': Parameter konnte nicht interpretiert werden", z + n,
|
|
|
|
param.getName());
|
|
|
|
else
|
|
|
|
throw new ScriptException(e, "Position %d: Argument '%s': Parameter '%s' (#%d) konnte nicht interpretiert werden", z + n,
|
|
|
|
param.getName(), parser.getName(), apos + 1);
|
|
|
|
}
|
|
|
|
apos += 1;
|
|
|
|
}
|
|
|
|
if(!pos)
|
|
|
|
inputs[0] = arg;
|
|
|
|
args.put(param.getName(), new ScriptArg(param, z, inputs, params));
|
2025-03-18 01:29:36 +01:00
|
|
|
z += nargs - (pos ? 1 : 0);
|
2025-03-11 00:23:54 +01:00
|
|
|
}
|
|
|
|
for(Parameter param : parameters.values()) {
|
|
|
|
if(!args.containsKey(param.getName())) {
|
|
|
|
if(param.isRequired()) {
|
|
|
|
for(ArgumentParser parser : param.getParsers()) {
|
|
|
|
if(parser.getDefault(env) == null)
|
|
|
|
throw new ScriptException("Argument '%s' muss angegeben werden", param.getName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Map<String, Object> params = Maps.newHashMapWithExpectedSize(param.getParsers().size());
|
|
|
|
for(ArgumentParser parser : param.getParsers()) {
|
|
|
|
params.put(parser.getName(), parser.getDefault(env));
|
|
|
|
}
|
|
|
|
args.put(param.getName(), new ScriptArg(param, -1, null, params));
|
|
|
|
}
|
|
|
|
}
|
2025-03-18 01:29:36 +01:00
|
|
|
return new ScriptArgs(args, str, env);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String[] getParam(ScriptEnvironment env, String[] argv, CachedExecutable cached) {
|
|
|
|
Map<String, Parameter> parameters = cached.getParameters();
|
|
|
|
List<Parameter> positionals = Lists.newArrayList(cached.getPositionals());
|
|
|
|
Set<String> args = Sets.newHashSet();
|
|
|
|
int ppos = 0;
|
|
|
|
boolean parse = true;
|
|
|
|
for(int z = 1; z < argv.length; z++) {
|
|
|
|
String arg = argv[z];
|
|
|
|
Parameter param = null;
|
|
|
|
boolean pos = false;
|
|
|
|
if(z == argv.length - 1) {
|
|
|
|
if(ppos < positionals.size()) {
|
|
|
|
param = positionals.get(ppos);
|
|
|
|
if(param.getParsers().isEmpty()) // np
|
|
|
|
return null;
|
|
|
|
return param.getParsers().get(0).getCompletions(env);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(parse && arg.equals("--")) {
|
|
|
|
parse = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if(parse && (arg.startsWith("--") || (arg.startsWith("-") && arg.length() == 2))) {
|
|
|
|
param = parameters.get(arg.substring(arg.startsWith("--") ? 2 : 1));
|
|
|
|
if(param != null && param.isPositional() && !args.contains(param.getName())) {
|
|
|
|
for(int n = 0; n < positionals.size(); n++) {
|
|
|
|
if(param == positionals.get(n)) {
|
|
|
|
positionals.remove(n);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ppos < positionals.size()) {
|
|
|
|
param = positionals.get(ppos++);
|
|
|
|
pos = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if(param == null || args.contains(param.getName()))
|
|
|
|
return null;
|
|
|
|
int nargs = param.getParsers().size();
|
|
|
|
// if(z + (pos ? 0 : 1) + nargs > argv.length - 1) {
|
|
|
|
// return param.getParsers().get(argv.length - z).getCompletions(env);
|
|
|
|
// }
|
|
|
|
int apos = 0;
|
|
|
|
for(int n = pos ? 0 : 1; n < nargs + (pos ? 0 : 1); n++) {
|
|
|
|
if(z + n == argv.length - 1)
|
|
|
|
return param.getParsers().get(apos).getCompletions(env);
|
|
|
|
String par = argv[z + n];
|
|
|
|
if(parse && (par.startsWith("--") || (par.startsWith("-") && par.length() == 2)))
|
|
|
|
return null;
|
|
|
|
apos += 1;
|
|
|
|
}
|
|
|
|
args.add(param.getName());
|
|
|
|
z += nargs - (pos ? 1 : 0);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String[] parseComplete(ScriptEnvironment env, String[] argv, CachedExecutable cached) {
|
|
|
|
String[] comp = getParam(env, argv, cached);
|
|
|
|
if(comp == null || comp.length == 0) {
|
|
|
|
Set<String> params = Sets.newTreeSet();
|
|
|
|
for(String param : cached.getParameters().keySet()) {
|
|
|
|
params.add(param.length() == 1 ? "-" + param : ("--" + param));
|
|
|
|
}
|
|
|
|
comp = params.toArray(new String[params.size()]);
|
|
|
|
}
|
|
|
|
return comp;
|
2025-03-11 00:23:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public ScriptArg getArg(String name) {
|
|
|
|
return this.arguments.get(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasArg(String name) {
|
|
|
|
return this.arguments.containsKey(name);
|
|
|
|
}
|
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
public boolean has(String name, String par) {
|
|
|
|
return this.arguments.containsKey(name) && this.arguments.get(name).getValues().containsKey(par);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean has(String name) {
|
|
|
|
return this.has(name, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public <T> T getDefault(String name, String par, T def) {
|
2025-03-11 00:23:54 +01:00
|
|
|
ScriptArg arg = this.arguments.get(name);
|
|
|
|
if(arg == null)
|
|
|
|
return def;
|
|
|
|
Object value = arg.getValues().get(par);
|
|
|
|
return value == null ? def : (T)value;
|
|
|
|
}
|
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
public <T> T getDefault(String name, T def) {
|
2025-03-11 00:23:54 +01:00
|
|
|
return this.getDefault(name, name, def);
|
|
|
|
}
|
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
public <T> T getUnchecked(String name, String par) {
|
2025-03-11 00:23:54 +01:00
|
|
|
return this.getDefault(name, par, null);
|
|
|
|
}
|
|
|
|
|
2025-03-18 01:29:36 +01:00
|
|
|
public <T> T getUnchecked(String name) {
|
2025-03-11 00:23:54 +01:00
|
|
|
return this.getDefault(name, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean getBool(String name, boolean def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean getBool(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public <T extends Enum<?>> T getEnum(String name, T def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public <T extends Enum<?>> T getEnum(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInt(String name, int def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInt(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getLong(String name, long def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getLong(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getDouble(String name, double def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getDouble(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getString(String name, String def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getString(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String[] getStrings(String name, String[] def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String[] getStrings(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Entity getEntity(String name, Entity def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Entity getEntity(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EntityLiving getLiving(String name, EntityLiving def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EntityLiving getLiving(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EntityNPC getNpc(String name, EntityNPC def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EntityNPC getNpc(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Block getBlock(String name, Block def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Block getBlock(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public State getState(String name, State def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public State getState(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getItem(String name, Item def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getItem(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ItemStack getStack(String name, ItemStack def) {
|
|
|
|
return this.getDefault(name, def);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ItemStack getStack(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
public BlockPos getColumnPos(String name, BlockPos def) {
|
|
|
|
return this.hasArg(name) ? this.getColumnPos(name) : def;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BlockPos getColumnPos(String name) {
|
|
|
|
return new BlockPos(this.getUnchecked(name, "x"), 0, this.getUnchecked(name, "z"));
|
|
|
|
}
|
|
|
|
|
|
|
|
public BlockPos getBlockPos(String name, BlockPos def) {
|
|
|
|
return this.hasArg(name) ? this.getBlockPos(name) : def;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BlockPos getBlockPos(String name) {
|
|
|
|
return new BlockPos(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z"));
|
|
|
|
}
|
|
|
|
|
|
|
|
public WorldPos getWorldPos(String name, WorldPos def) {
|
|
|
|
return this.hasArg(name) ? this.getWorldPos(name) : def;
|
|
|
|
}
|
|
|
|
|
|
|
|
public WorldPos getWorldPos(String name) {
|
|
|
|
return new WorldPos(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z"),
|
|
|
|
this.getUnchecked(name, "dim"));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vec3 getVector2D(String name, Vec3 def) {
|
|
|
|
return this.hasArg(name) ? this.getVector2D(name) : def;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vec3 getVector2D(String name) {
|
|
|
|
return new Vec3(this.getUnchecked(name, "x"), 0.0, this.getUnchecked(name, "z"));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vec3 getVector(String name, Vec3 def) {
|
|
|
|
return this.hasArg(name) ? this.getVector(name) : def;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vec3 getVector(String name) {
|
|
|
|
return new Vec3(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z"));
|
|
|
|
}
|
2025-03-18 01:29:36 +01:00
|
|
|
|
|
|
|
public WorldServer getWorld(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
2025-03-19 02:08:41 +01:00
|
|
|
|
|
|
|
public NBTTagCompound getTag(String name) {
|
|
|
|
return this.getUnchecked(name);
|
|
|
|
}
|
2025-03-11 00:23:54 +01:00
|
|
|
}
|