Script Turing Completeness #152
@ -83,11 +83,9 @@ public class ScriptListener implements Listener {
|
|||||||
private final Player player;
|
private final Player player;
|
||||||
private final List<String> commands = new ArrayList<>();
|
private final List<String> commands = new ArrayList<>();
|
||||||
private final Map<String, Integer> jumpPoints = new HashMap<>();
|
private final Map<String, Integer> jumpPoints = new HashMap<>();
|
||||||
private final VariableHolder variableHolder = new VariableHolder();
|
private Map<String, Integer> variables = new HashMap<>();
|
||||||
|
|
||||||
private boolean lastCommandWasSleep = false;
|
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|||||||
private int executionPoints = 0;
|
|
||||||
|
|
||||||
public ScriptExecutor(BookMeta bookMeta, Player player) {
|
public ScriptExecutor(BookMeta bookMeta, Player player) {
|
||||||
Lixfel
hat
Wenn jemand mehr als 200 Befehle in ein Skriptbuch packt, dann werden eben mehr als 200 Befehle ausgeführt. Du kannst damit nicht Serverabstürze verhindern. Wenn jemand mehr als 200 Befehle in ein Skriptbuch packt, dann werden eben mehr als 200 Befehle ausgeführt. Du kannst damit nicht Serverabstürze verhindern.
YoyoNow
hat
Ich will damit auch verhindern, dass du unendlich schleifen machst. Aber ich habe es nun rausgenommen. Ich will damit auch verhindern, dass du unendlich schleifen machst. Aber ich habe es nun rausgenommen.
|
|||||||
this.player = player;
|
this.player = player;
|
||||||
@ -114,51 +112,36 @@ public class ScriptListener implements Listener {
|
|||||||
while (index < commands.size()) {
|
while (index < commands.size()) {
|
||||||
String command = commands.get(index++);
|
String command = commands.get(index++);
|
||||||
|
|
||||||
executionPoints++;
|
String firstArg = command;
|
||||||
if (executionPoints > 200) {
|
if (command.contains(" ")) {
|
||||||
player.sendMessage(BauSystem.PREFIX + "§cBitte füge ein sleep in dein Script ein.");
|
firstArg = command.substring(0, command.indexOf(' '));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (executionPoints < 0) {
|
switch (firstArg.toLowerCase()) {
|
||||||
executionPoints = 0;
|
case "sleep":
|
||||||
}
|
ScriptListener.sleepCommand(this, generateArgumentArray("sleep", command));
|
||||||
|
return;
|
||||||
if (command.toLowerCase().startsWith("sleep")) {
|
case "exit":
|
||||||
ScriptListener.sleepCommand(this, generateArgumentArray("sleep", command));
|
return;
|
||||||
lastCommandWasSleep = true;
|
case "jump":
|
||||||
return;
|
int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", command));
|
||||||
}
|
if (jumpIndex != -1) {
|
||||||
lastCommandWasSleep = false;
|
index = jumpIndex;
|
||||||
if (command.toLowerCase().startsWith("exit")) {
|
} else {
|
||||||
return;
|
player.sendMessage(BauSystem.PREFIX + "§cUnbekannter Jump Punkt: " + command);
|
||||||
}
|
}
|
||||||
if (command.toLowerCase().startsWith("jump")) {
|
continue;
|
||||||
int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", command));
|
case "info":
|
||||||
if (jumpIndex != -1) {
|
ScriptListener.infoCommand(this, generateArgumentArray("info", command));
|
||||||
executionPoints += 2;
|
continue;
|
||||||
Lixfel
hat
Wenn du hier mit so vielen Extracommands anfängst: Mach ein switch case draus. Wenn du hier mit so vielen Extracommands anfängst: Mach ein switch case draus.
|
|||||||
index = jumpIndex;
|
case "var":
|
||||||
} else {
|
ScriptListener.variableCommand(this, generateArgumentArray("var", command));
|
||||||
player.sendMessage(BauSystem.PREFIX + "§cUnbekannter Jump Punkt: " + command);
|
continue;
|
||||||
}
|
case "if":
|
||||||
continue;
|
int ifJumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", command));
|
||||||
}
|
if (ifJumpIndex != -1) {
|
||||||
if (command.toLowerCase().startsWith("info")) {
|
index = ifJumpIndex;
|
||||||
executionPoints -= 1;
|
}
|
||||||
ScriptListener.infoCommand(this, generateArgumentArray("info", command));
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (command.toLowerCase().startsWith("var")) {
|
|
||||||
executionPoints -= 1;
|
|
||||||
ScriptListener.variableCommand(this, generateArgumentArray("var", command));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (command.toLowerCase().startsWith("if")) {
|
|
||||||
int jumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", command));
|
|
||||||
if (jumpIndex != -1) {
|
|
||||||
executionPoints += 2;
|
|
||||||
index = jumpIndex;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommandPreprocessEvent preprocessEvent = new PlayerCommandPreprocessEvent(player, "/" + command);
|
PlayerCommandPreprocessEvent preprocessEvent = new PlayerCommandPreprocessEvent(player, "/" + command);
|
||||||
@ -191,9 +174,6 @@ public class ScriptListener implements Listener {
|
|||||||
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie Zeit darf nur aus Zahlen bestehen.");
|
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie Zeit darf nur aus Zahlen bestehen.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!scriptExecutor.lastCommandWasSleep) {
|
|
||||||
scriptExecutor.executionPoints -= sleepTime - 1;
|
|
||||||
}
|
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), scriptExecutor::resume, sleepTime);
|
Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), scriptExecutor::resume, sleepTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +187,8 @@ public class ScriptListener implements Listener {
|
|||||||
|
|
||||||
private static void infoCommand(ScriptExecutor scriptExecutor, String[] args) {
|
private static void infoCommand(ScriptExecutor scriptExecutor, String[] args) {
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
if (args[i].startsWith("$") && scriptExecutor.variableHolder.isVariable(args[i].substring(1))) {
|
if (args[i].startsWith("$") && isVariable(scriptExecutor, args[i].substring(1))) {
|
||||||
args[i] = scriptExecutor.variableHolder.getValue(args[i].substring(1)) + "";
|
args[i] = getValue(scriptExecutor, args[i].substring(1)) + "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", args)));
|
scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", args)));
|
||||||
@ -227,15 +207,15 @@ public class ScriptListener implements Listener {
|
|||||||
case "inc":
|
case "inc":
|
||||||
case "increment":
|
case "increment":
|
||||||
Lixfel
hat
Den Info-Befehl finde ich etwas unnötig, sicherlich wird er interessant zum Debuggen sein, aber wir wollen die Leute nicht dazu ermuntern, horrend aufwändige Skripte zu schreiben, und wenn, dann soll es eine Herausforderung sein. Der Info-Command bläst das System nur ohne nennenswerten Mehrwert auf. Den Info-Befehl finde ich etwas unnötig, sicherlich wird er interessant zum Debuggen sein, aber wir wollen die Leute nicht dazu ermuntern, horrend aufwändige Skripte zu schreiben, und wenn, dann soll es eine Herausforderung sein. Der Info-Command bläst das System nur ohne nennenswerten Mehrwert auf.
YoyoNow
hat
Mit diesem Command soll man, besonders, wenn man einem anderen sein eigenes Skript gibt, So dass er weiß wie man diesen verwendet? Bzw auch um user Rückgaben zu machen. Mit diesem Command soll man, besonders, wenn man einem anderen sein eigenes Skript gibt, So dass er weiß wie man diesen verwendet? Bzw auch um user Rückgaben zu machen.
|
|||||||
case "++":
|
case "++":
|
||||||
scriptExecutor.variableHolder.add(args[0], 1);
|
add(scriptExecutor, args[0], 1);
|
||||||
return;
|
return;
|
||||||
case "dec":
|
case "dec":
|
||||||
case "decrement":
|
case "decrement":
|
||||||
case "--":
|
case "--":
|
||||||
scriptExecutor.variableHolder.add(args[0], -1);
|
add(scriptExecutor, args[0], -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Lixfel
hat
Bislang sind keine freien Variablen außer den 4 Konstanten fire, tnt, trace & freeze nötig. Das Programm hat so wenige Input- und Outputmöglichkeiten (Man kann Variablen schließlich nur in ifs verwenden), dass man es daher immer auf die Konstanten zurückgreifen kann und einfach keine freien Variablen benötigt. Entweder das System wird mächtiger, oder Variablen sind sinnlos. Bislang sind keine freien Variablen außer den 4 Konstanten fire, tnt, trace & freeze nötig. Das Programm hat so wenige Input- und Outputmöglichkeiten (Man kann Variablen schließlich nur in ifs verwenden), dass man es daher immer auf die Konstanten zurückgreifen kann und einfach keine freien Variablen benötigt. Entweder das System wird mächtiger, oder Variablen sind sinnlos.
YoyoNow
hat
Du kannst mit variablen schleifenabbrüche und sonstige Sachen machen. Ich glaube das das doch sinnvoll wäre. Du kannst mit variablen schleifenabbrüche und sonstige Sachen machen. Ich glaube das das doch sinnvoll wäre.
Lixfel
hat
Du hast aber nix, wofür Schleifen sinnvoll wären. Variablen kannst du letztendlich nur für ifs verwenden. Und eine "Schleife" kannst du ohne variablen Input auch einfach entrollen, da die Länge schon während des Schreibens des Skriptes bekannt ist, d.h besteht dafür keine Notwendigkeit. Du hast aber nix, wofür Schleifen sinnvoll wären. Variablen kannst du letztendlich nur für ifs verwenden. Und eine "Schleife" kannst du ohne variablen Input auch einfach entrollen, da die Länge schon während des Schreibens des Skriptes bekannt ist, d.h besteht dafür keine Notwendigkeit.
YoyoNow
hat
Jedoch ist es einfacher, wenn man diese als Schleife darstellen kann. Außerdem welche Output/Input Systeme kann man noch einbauen? Jedoch ist es einfacher, wenn man diese als Schleife darstellen kann. Außerdem welche Output/Input Systeme kann man noch einbauen?
Lixfel
hat
Nein, das ist nicht mal einfacher. Die Variablen fügen dem Skriptsystem derzeit nix hinzu. Anders würde es aussehen, wenn man die Befehle auch für andere Befehle als für info verwenden könnte...., dann würde ich allerdings info umbenennen in echo und in einen normalen Befehl umwandeln. Nein, das ist nicht mal einfacher. Die Variablen fügen dem Skriptsystem derzeit nix hinzu.
Anders würde es aussehen, wenn man die Befehle auch für andere Befehle als für info verwenden könnte...., dann würde ich allerdings info umbenennen in echo und in einen normalen Befehl umwandeln.
YoyoNow
hat
Welche Befehle soll man für andere Befehle verwenden? Meinst du variablen soll man für andere Befehle verwenden können sollen. Und das umwandeln könnte ich. Ich weiß halt nicht wie man das mit den Variablen dann sinnvoll machen sollte. Weil es dann ja scheinbar globale und nicht globale variablen geben sollte? Welche Befehle soll man für andere Befehle verwenden? Meinst du variablen soll man für andere Befehle verwenden können sollen. Und das umwandeln könnte ich. Ich weiß halt nicht wie man das mit den Variablen dann sinnvoll machen sollte. Weil es dann ja scheinbar globale und nicht globale variablen geben sollte?
Lixfel
hat
Nein, ich habe nix von globalen und nicht globalen Variablen geschrieben. Ich habe etwas von der Einsetzbarkeit von Variablen geschrieben. Ich möchte die Variablen innerhalb eines Skripts für nahezu jeden Befehl verwenden können, z.B. für ein //pos1 X,Y,Z Nein, ich habe nix von globalen und nicht globalen Variablen geschrieben. Ich habe etwas von der Einsetzbarkeit von Variablen geschrieben. Ich möchte die Variablen innerhalb eines Skripts für nahezu jeden Befehl verwenden können, z.B. für ein //pos1 X,Y,Z
YoyoNow
hat
Achso. Ich glaube das lässt sich einrichten. Achso. Ich glaube das lässt sich einrichten.
|
|||||||
scriptExecutor.variableHolder.setValue(args[0], args[1]);
|
setValue(scriptExecutor, args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ifCommand(ScriptExecutor scriptExecutor, String[] args) {
|
private static int ifCommand(ScriptExecutor scriptExecutor, String[] args) {
|
||||||
@ -249,15 +229,15 @@ public class ScriptListener implements Listener {
|
|||||||
|
|
||||||
int firstValue;
|
int firstValue;
|
||||||
int secondValue;
|
int secondValue;
|
||||||
if (scriptExecutor.variableHolder.isVariable(args[0])) {
|
if (isVariable(scriptExecutor, args[0])) {
|
||||||
firstValue = scriptExecutor.variableHolder.getValue(args[0]);
|
firstValue = getValue(scriptExecutor, args[0]);
|
||||||
} else {
|
} else {
|
||||||
firstValue = scriptExecutor.variableHolder.parseValue(args[0]);
|
firstValue = parseValue(args[0]);
|
||||||
}
|
}
|
||||||
if (scriptExecutor.variableHolder.isVariable(args[1])) {
|
if (isVariable(scriptExecutor, args[1])) {
|
||||||
secondValue = scriptExecutor.variableHolder.getValue(args[1]);
|
secondValue = getValue(scriptExecutor, args[1]);
|
||||||
} else {
|
} else {
|
||||||
secondValue = scriptExecutor.variableHolder.parseValue(args[1]);
|
secondValue = parseValue(args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstValue == secondValue) {
|
if (firstValue == secondValue) {
|
||||||
@ -267,60 +247,54 @@ public class ScriptListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class VariableHolder {
|
private static void setValue(ScriptExecutor scriptExecutor, String key, String value) {
|
||||||
|
scriptExecutor.variables.put(key, parseValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Integer> variables = new HashMap<>();
|
private static void add(ScriptExecutor scriptExecutor, String key, int value) {
|
||||||
|
if (!isVariable(scriptExecutor, key)) {
|
||||||
public void setValue(String key, String value) {
|
scriptExecutor.variables.put(key, 0);
|
||||||
variables.put(key, parseValue(value));
|
|
||||||
}
|
}
|
||||||
|
scriptExecutor.variables.put(key, scriptExecutor.variables.get(key) + value);
|
||||||
|
}
|
||||||
|
|
||||||
public void add(String key, int value) {
|
private static int getValue(ScriptExecutor scriptExecutor, String key) {
|
||||||
if (!isVariable(key)) {
|
switch (key) {
|
||||||
variables.put(key, 0);
|
case "trace":
|
||||||
}
|
return RecordManager.getStatus().isTracing() ? 1 : 0;
|
||||||
variables.put(key, variables.get(key) + value);
|
case "tnt":
|
||||||
|
return CommandTNT.getInstance().isOn() ? 1 : 0;
|
||||||
|
case "freeze":
|
||||||
|
return CommandFreeze.getInstance().isOn() ? 1 : 0;
|
||||||
|
case "fire":
|
||||||
|
return CommandFire.getInstance().isOn() ? 1 : 0;
|
||||||
Lixfel
hat
Das System ist viel zu aufwändig für das wenige, dass es kann. Einfach eine Map<String, Integer> statt einem "VariableHolder". Es gibt nur Integer, keine Boolean. Alles außer 0 wird true bewertet. Die Konstanten "trace", "tnt", "freeze" und "fire" kannst du als solche extra behandeln wie hier in getValue(). Das System ist viel zu aufwändig für das wenige, dass es kann. Einfach eine Map<String, Integer> statt einem "VariableHolder". Es gibt nur Integer, keine Boolean. Alles außer 0 wird true bewertet. Die Konstanten "trace", "tnt", "freeze" und "fire" kannst du als solche extra behandeln wie hier in getValue().
|
|||||||
}
|
}
|
||||||
|
return scriptExecutor.variables.getOrDefault(key, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public int getValue(String key) {
|
private static boolean isVariable(ScriptExecutor scriptExecutor, String key) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "trace":
|
case "trace":
|
||||||
return RecordManager.getStatus().isTracing() ? 1 : 0;
|
case "tnt":
|
||||||
case "tnt":
|
case "freeze":
|
||||||
return CommandTNT.getInstance().isOn() ? 1 : 0;
|
case "fire":
|
||||||
case "freeze":
|
return true;
|
||||||
return CommandFreeze.getInstance().isOn() ? 1 : 0;
|
default:
|
||||||
case "fire":
|
return scriptExecutor.variables.containsKey(key);
|
||||||
return CommandFire.getInstance().isOn() ? 1 : 0;
|
|
||||||
}
|
|
||||||
return variables.getOrDefault(key, 0);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isVariable(String key) {
|
private static int parseValue(String value) {
|
||||||
switch (key) {
|
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) {
|
||||||
case "trace":
|
return 1;
|
||||||
case "tnt":
|
} else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) {
|
||||||
case "freeze":
|
return 0;
|
||||||
case "fire":
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return variables.containsKey(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
public int parseValue(String value) {
|
return Integer.parseInt(value);
|
||||||
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) {
|
} catch (NumberFormatException e) {
|
||||||
return 1;
|
return 0;
|
||||||
} else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(value);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Mach das System nicht komplexer als nötig.