tcr/java/src/game/command/ScriptEnvironment.java

203 lines
5.9 KiB
Java
Raw Normal View History

2025-03-11 00:23:54 +01:00
package game.command;
2025-03-19 21:54:09 +01:00
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
2025-03-11 00:23:54 +01:00
import java.util.List;
import java.util.Map;
import java.util.function.Function;
2025-03-16 17:40:47 +01:00
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
2025-03-11 00:23:54 +01:00
import game.Server;
import game.color.TextColor;
2025-03-25 10:13:15 +01:00
import game.command.commands.CommandHelp;
2025-03-18 01:29:36 +01:00
import game.command.commands.CommandSpawn;
2025-03-19 21:54:09 +01:00
import game.log.Log;
2025-03-11 00:23:54 +01:00
public class ScriptEnvironment {
private final Server server;
private final Map<String, CachedExecutable> executables = Maps.newTreeMap();
private final List<PatternReplacer> replacers = Lists.newArrayList();
private ScriptExecutor currentExecutor;
private Object previousOutput;
public ScriptEnvironment(Server server) {
this.server = server;
2025-03-18 01:29:36 +01:00
this.registerDefaults();
2025-03-11 00:23:54 +01:00
}
public void registerExecutable(Executable executable) {
CachedExecutable cached = CachedExecutable.cacheExecutable(executable);
this.executables.put(cached.getName(), cached);
this.registerReplacer(cached.getName(), new Function<String, String>() {
public String apply(String str) {
Object o;
try {
o = ScriptEnvironment.this.execute(str, false);
}
catch(Throwable e) {
throw new ScriptException(e, "Variable konnte nicht ersetzt werden: '%s' konnte nicht ausgeführt werden", str);
}
if(o == null)
throw new ScriptException("Variable konnte nicht ersetzt werden: null von '%s' zurückgegeben", str);
return o.toString();
}
});
}
public void registerReplacer(String var, Function<String, String> function) {
this.replacers.add(new PatternReplacer(var, true, function));
}
public void registerVariable(String var, Variable variable) {
this.replacers.add(new PatternReplacer(var, false, new Function<String, String>() {
public String apply(String ign) {
return variable.get();
}
}));
}
public Server getServer() {
return this.server;
}
2025-03-25 10:13:15 +01:00
public Map<String, CachedExecutable> getExecutables() {
return this.executables;
}
2025-03-11 00:23:54 +01:00
public ScriptExecutor getExecutor() {
return this.currentExecutor;
}
private String substitute(String str) {
StringBuffer sb = new StringBuffer(str);
for(PatternReplacer replacer : this.replacers) {
replacer.replaceVar(sb);
}
return sb.toString();
}
private Object execute(String cmd, boolean setPrev) {
String line = this.substitute(cmd);
String[][] cmds = ArgumentParser.splitString(line);
Object o = null;
for(String[] argv : cmds) {
CachedExecutable cached = this.executables.get(argv[0]);
if(cached == null)
throw new ScriptException("Skript '%s' existiert nicht", argv[0]);
ScriptArgs args = ScriptArgs.parseArgs(this, cmd, argv, cached);
2025-03-19 21:54:09 +01:00
List<Object> params = Lists.newArrayList(this, this.currentExecutor);
for(Parameter param : cached.getExecutable().getParamList()) {
ArgCombiner combiner = param.getCombiner();
if(combiner != null) {
Object[] data = (Object[])Array.newInstance(combiner.getInputClass(), param.getParsers().size());
for(int z = 0; z < data.length; z++) {
data[z] = args.getUnchecked(param.getName(), param.getParsers().get(z).getName());
if(data[z] == null) {
data = null;
break;
}
}
params.add(data == null ? null : combiner.combine(data));
continue;
}
if(param.getParsers().isEmpty()) {
params.add(args.hasArg(param.getName()));
continue;
}
for(ArgumentParser parser : param.getParsers()) {
params.add(args.getUnchecked(param.getName(), parser.getName()));
}
}
try {
o = cached.getMethod().invoke(cached.getExecutable(), params.toArray(new Object[params.size()]));
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
// o = cached.getExecutable().exec(this, args);
2025-03-11 00:23:54 +01:00
if(setPrev)
this.previousOutput = o;
}
return o;
}
public void execute(String cmd, ScriptExecutor exec) {
this.currentExecutor = exec;
try {
this.execute(cmd, true);
}
catch(ScriptException e) {
Throwable cause = e;
do {
exec.logConsole(TextColor.RED + cause.getMessage());
cause = cause.getCause();
}
while(cause != null);
}
catch(Throwable t) {
exec.logConsole(TextColor.RED + "Fehler: %s", t.getMessage());
2025-03-19 21:54:09 +01:00
Log.CONSOLE.error(t, "Fehler beim Ausführen von Befehl '%s'", cmd);
2025-03-11 00:23:54 +01:00
}
finally {
this.currentExecutor = null;
this.previousOutput = null;
}
}
2025-03-18 01:29:36 +01:00
public List<String> complete(String cmd, ScriptExecutor exec) {
List<String> list = Lists.newArrayList();
try {
String[][] cmds = ArgumentParser.splitString(cmd.endsWith(" ") ? cmd + "END" : cmd);
if(cmds.length == 0)
return list;
String[] argv = cmds[cmds.length - 1];
if(argv.length == 0)
return list;
2025-03-19 21:54:09 +01:00
String param = cmd.endsWith(" ") ? "" : argv[argv.length - 1];
2025-03-18 01:29:36 +01:00
String[] comp;
if(argv.length > 1) {
CachedExecutable cached = this.executables.get(argv[0]);
if(cached == null)
return list;
2025-03-19 21:54:09 +01:00
comp = ScriptArgs.parseComplete(this, argv, cached, param);
2025-03-18 01:29:36 +01:00
}
else {
comp = this.executables.keySet().toArray(new String[this.executables.keySet().size()]);
}
for(String cmp : comp) {
if(cmp.regionMatches(true, 0, param, 0, param.length()))
list.add(cmp);
}
}
catch(Throwable t) {
list.clear();
}
return list;
2025-03-11 00:23:54 +01:00
}
public void registerDefaults() {
this.registerVariable("id", new Variable() {
public String get() {
return ScriptEnvironment.this.currentExecutor.getExecId();
}
});
this.registerVariable("name", new Variable() {
public String get() {
return ScriptEnvironment.this.currentExecutor.getExecName();
}
});
this.registerVariable("chain", new Variable() {
public String get() {
return ScriptEnvironment.this.previousOutput == null ? null : ScriptEnvironment.this.previousOutput.toString();
}
});
2025-03-18 01:29:36 +01:00
this.registerExecutable(new CommandSpawn());
2025-03-25 10:13:15 +01:00
this.registerExecutable(new CommandHelp(this));
2025-03-11 00:23:54 +01:00
}
}