package game.command; import java.util.List; import java.util.Map; import java.util.function.Function; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import game.Server; import game.color.TextColor; import game.command.commands.CommandSpawn; public class ScriptEnvironment { private final Server server; private final Map executables = Maps.newTreeMap(); private final List replacers = Lists.newArrayList(); private ScriptExecutor currentExecutor; private Object previousOutput; public ScriptEnvironment(Server server) { this.server = server; this.registerDefaults(); } public void registerExecutable(Executable executable) { CachedExecutable cached = CachedExecutable.cacheExecutable(executable); this.executables.put(cached.getName(), cached); this.registerReplacer(cached.getName(), new Function() { 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 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() { public String apply(String ign) { return variable.get(); } })); } public Server getServer() { return this.server; } 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); o = cached.getExecutable().exec(this, args); 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()); } finally { this.currentExecutor = null; this.previousOutput = null; } } public List complete(String cmd, ScriptExecutor exec) { List 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; String[] comp; if(argv.length > 1) { CachedExecutable cached = this.executables.get(argv[0]); if(cached == null) return list; comp = ScriptArgs.parseComplete(this, argv, cached); } else { comp = this.executables.keySet().toArray(new String[this.executables.keySet().size()]); } String param = cmd.endsWith(" ") ? "" : argv[argv.length - 1]; for(String cmp : comp) { if(cmp.regionMatches(true, 0, param, 0, param.length())) list.add(cmp); } } catch(Throwable t) { list.clear(); } return list; } 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(); } }); this.registerExecutable(new CommandSpawn()); } }