SteamWar/BauSystem
Archiviert
13
0

Merge pull request 'Add variable reference support to internal commands' (#207) from ScriptSystemImprovements into master

Reviewed-on: #207
Reviewed-by: Chaoscaot <chaoscaot444@gmail.com>
Dieser Commit ist enthalten in:
YoyoNow 2021-03-24 17:29:58 +01:00
Commit ab81466a33
3 geänderte Dateien mit 171 neuen und 41 gelöschten Zeilen

Datei anzeigen

@ -39,20 +39,31 @@ public class CommandScript implements CommandExecutor {
static {
List<String> pages = new ArrayList<>();
pages.add("§6Script System§8\n\n- Commands\n- Kommentare\n- Scriptausführung\n- Sleep\n- Variablen\n- Konstanten\n- Abfragen\n- Schleifen\n- \"echo\"");
pages.add("§6Script System§8\n\n- Commands\n- Kommentare\n- Scriptausführung\n- Sleep\n- Variablen\n- Konstanten\n- Abfragen\n- Schleifen\n- \"echo\"\n- \"input\"\n- Arithmetik\n- Logik");
pages.add("§6Commands§8\n\nEin minecraft Befehl wird im Scriptbuch so hingeschrieben. Dabei kann man ein '/' weglassen. Um Befehle zu trennen kommen diese in neue Zeilen.\n\nStatt\n/tnt -> tnt\n//pos1 -> /pos1");
pages.add("§6Kommentare§8\n\nFür ein Kommentar fängt die Zeile mit einem '#' an. Diese Zeilen werden bei dem Ausführen dann ignoriert.\n\nBeispiel:\n§9# TNT an/aus\ntnt§8");
pages.add("§6Kommentare§8\n\nFür ein Kommentar fängt die Zeile mit einem '#' an. Diese Zeilen werden bei dem Ausführen dann ignoriert.\n\nBeispiel:\n§9# TNT an/aus\ntnt");
pages.add("§6Scriptausführung§8\n\nWenn du mit dem Buch in der Hand links klickst wird dieses ausgeführt.");
pages.add("§6Sleep§8\n\nUm Sachen langsamer zu machen kann man ein 'sleep' in sein Script schreiben. Danach kommt eine Zahl mit der Anzahl der GameTicks die zu schlafen sind.\n\nBeispiel:\n§9# 1 Sekunde schlafen\nsleep 20§8");
pages.add("§6Sleep§8\n\nUm Sachen langsamer zu machen kann man ein 'sleep' in sein Script schreiben. Danach kommt eine Zahl mit der Anzahl der GameTicks die zu schlafen sind.\n\nBeispiel:\n§9# 1 Sekunde schlafen\nsleep 20");
pages.add("§6Variablen§8\n\nMit Variablen kann man sich Zahlen speichern. Man definiert diese mit 'var <NAME> <VALUE>'.\n\nBeispiel:\n§9# Setze i zu 0\nvar i 0§8\n\nEs gibt einige spezial values. Dazu zählen");
pages.add("§8'true', 'yes', 'false' und 'no', welche für 1, 1, 0 und 0 stehen.\n\nMan kann eine Variable auch um einen erhöhen oder verkleinern. Hierfür schreibt man statt einer Zahl '++', 'inc' oder '--', 'dec'.\n\nBeispiel:\n§9var i ++§8");
pages.add("§8Variablen kann man referenzieren\ndurch '$' vor dem Variablennamen. Diese kann man in jedem Befehl verwenden.\n\nBeispiel:\n§9# Stacked um 10\nvar stacks 10\n/stack $stacks§8");
pages.add("§6Konstanten§8\n\nNeben den variablen gibt es noch 4 Konstante Werte, welche nicht mit dem 'var' Befehl verändert werden können.\n\nDiese sind:\n- trace\n- tnt\n- freeze\n- fire");
pages.add("§8'true', 'yes', 'false' und 'no', welche für 1, 1, 0 und 0 stehen.\n\nMan kann eine Variable auch um einen erhöhen oder verkleinern. Hierfür schreibt man statt einer Zahl '++', 'inc' oder '--', 'dec'.\n\nBeispiel:\n§9var i ++");
pages.add("§8Variablen kann man referenzieren\ndurch '<' vor dem Variablennamen und '>' nach diesem. Diese kann man in jedem Befehl verwenden.\n\nBeispiel:\n§9# Stacked um 10\nvar stacks 10\n/stack <stacks>");
pages.add("§6Konstanten§8\n\nNeben den variablen gibt es noch 5 Konstante Werte, welche nicht mit dem 'var' Befehl verändert werden können.\n\nDiese sind:\n- trace/autotrace\n- tnt\n- freeze\n- fire");
pages.add("§6Abfragen§8\n\nMit Abfragen kann man nur Gleichheit von 2 Werten überprüft werden. Hierfür verwendet man\n'if <VAL> <VAL>'.\nNach den zwei Werten kann man ein oder 2 Jump-Points schreiben\n'if [...] <JP> (JP)'.");
pages.add("§8Ein Jump-Point ist eine Zeile Script, wohin man springen kann. Dieser wird mit einem '.' am Anfang der Zeile beschrieben und direkt danach der Jump-Point Namen ohne Leerzeichen.\n\nBeispiel:\n§9# Jump-Point X\n.X§8");
pages.add("§8Um zu einem Jump-Point ohne Abfrage zu springen kann man den\n'jump <JP>' Befehl verwenden.");
pages.add("§6Schleifen§8\n\nSchleifen werden mit Jump-Points, if Abfragen und Jumps gebaut.\n\nBeispiel:\n§9var i 0\n.JUMP\nvar i ++\nif i 10 END JUMP\n.END§8");
pages.add("§6\"echo\"§8\n\nDer echo Befehl ist gut um Ausgaben zu tätigen. Hier drin kann man sowohl Variablen ausgeben, als auch Farbcodes verwenden. Es wird alles nach dem Befehl ausgegeben.\n\nBeispiel:\n§9echo &eSteam&8war &7war hier!§8");
pages.add("§6\"echo\"§8\n\nDer echo Befehl ist da um Ausgaben zu tätigen. Hier drin kann man sowohl Variablen ausgeben, als auch Farbcodes verwenden. Es wird alles nach dem Befehl ausgegeben.\n\nBeispiel:\n§9echo &eSteam&8war &7war hier!");
pages.add("§6\"input\"§8\n\nDer input Befehl ist eine Aufforderung einer Eingabe des Users. Die Argumente sind eine Variable und ein Text als Nachricht.\n\nBeispiel:\n§9input age &eDein Alter?");
pages.add("§6Arithmetik§8\n\nEs gibt 4 Arithmetische Befehle:\n- add\n- sub\n- mul\n- div\n\nDer erste Parameter ist die Variable welche den ausgerechneten Wert halten soll. Hiernach muss ein");
pages.add("§8Wert oder Variable kommen welcher verrechnet wird. Hierbei wird das erste Argument als ersten Operand genommen.\n\nBeispiel:\n§9var i 2\nvar j 3\nadd i j\necho $i");
pages.add("§8Man kann auch 3 Argumente angeben. Dann wird die arithmetische Operation zwischen den letzten beiden Argumenten berechnet und als Variable des ersten Arguments abgespeichert. \n\nBeispiel auf der nächsten Seite -->");
pages.add("§8Beispiel:\n§9var i 2\nvar j 2\nadd k i j\necho $k");
pages.add("§6Logik§8\n\nEs gibt 3 Vergleichs Befehle:\n- equal\n- less\n- greater\n\nUnd 3 Logik Befehle:\n- and\n- or\n- not");
pages.add("§8Der erste Parameter ist die Variable welche den ausgerechneten Wert halten soll. Hiernach muss ein Wert oder Variable kommen welcher verrechnet wird. Hierbei wird das erste Argument als ersten Operand genommen. Dies gilt nicht für den 'not' Befehl, welcher");
pages.add("§8nur 2 Parameter nimmt. Der erste die Variable und der zweite eine optionale Variable oder ein Wert. Equal vergleicht 2 Werte, less gibt zurück ob der erste kleiner als der zweite Wert ist, greater gibt zurück ob der erste größer als der zweite Wert ist.");
pages.add("§8And vergleicht ob 2 Werte true (1) sind. Or vergleicht ob 1 Wert oder 2 Werte true (1) ist/sind. Not invertiert den Wert von true (1) auf false und anders rum.");
pages.add("§8Beispiel:\n§9var i 1\nvar j 1\n#Ist i und j gleich\nequal k i j\nvar j 0\n#Ist i kleiner j\nless k i j\n#Ist i größer j\ngreater k i j\n#Ist i und j true\nand k i j\n#Beispiel weiter auf nächster Seite");
pages.add("§9#Ist i oder j true\nor k i j\n#Invertiere i\nnot k i");
BookMeta bookMeta = (BookMeta) BOOK.getItemMeta();
bookMeta.setGeneration(BookMeta.Generation.ORIGINAL);

Datei anzeigen

@ -44,6 +44,10 @@ public enum RecordStatus {
return tracing;
}
public boolean isAutoTrace() {
return this == RECORD_AUTO || this == IDLE_AUTO;
}
public String getAutoMessage() {
return autoMessage;
}

Datei anzeigen

@ -24,6 +24,7 @@ import de.steamwar.bausystem.commands.CommandScript;
import de.steamwar.bausystem.commands.CommandTNT;
import de.steamwar.bausystem.tracer.record.RecordStateMachine;
import de.steamwar.core.VersionedCallable;
import de.steamwar.inventory.SWAnvilInv;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
@ -37,6 +38,8 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import java.util.*;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import java.util.logging.Level;
public class ScriptListener implements Listener {
@ -122,12 +125,12 @@ public class ScriptListener implements Listener {
}
switch (firstArg.toLowerCase()) {
case "sleep":
ScriptListener.sleepCommand(this, generateArgumentArray("sleep", command));
ScriptListener.sleepCommand(this, generateArgumentArray("sleep", this, command));
return;
case "exit":
return;
case "jump":
int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", command));
int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", this, command));
if (jumpIndex != -1) {
index = jumpIndex;
} else {
@ -135,13 +138,46 @@ public class ScriptListener implements Listener {
}
continue;
case "echo":
ScriptListener.echoCommand(this, generateArgumentArray("echo", command));
ScriptListener.echoCommand(this, generateArgumentArray("echo", this, command));
continue;
case "input":
ScriptListener.inputCommand(this, generateArgumentArray("input", this, command));
return;
case "var":
ScriptListener.variableCommand(this, generateArgumentArray("var", command));
ScriptListener.variableCommand(this, generateArgumentArray("var", this, command));
continue;
case "add":
ScriptListener.arithmeticCommand(this, generateArgumentArray("add", this, command), (left, right) -> left + right);
continue;
case "sub":
ScriptListener.arithmeticCommand(this, generateArgumentArray("sub", this, command), (left, right) -> left - right);
continue;
case "mul":
ScriptListener.arithmeticCommand(this, generateArgumentArray("mul", this, command), (left, right) -> left * right);
continue;
case "div":
ScriptListener.arithmeticCommand(this, generateArgumentArray("div", this, command), (left, right) -> left / right);
continue;
case "equal":
ScriptListener.arithmeticCommand(this, generateArgumentArray("equal", this, command), (left, right) -> left == right ? 1 : 0);
continue;
case "less":
ScriptListener.arithmeticCommand(this, generateArgumentArray("less", this, command), (left, right) -> left < right ? 1 : 0);
continue;
case "greater":
ScriptListener.arithmeticCommand(this, generateArgumentArray("greater", this, command), (left, right) -> left > right ? 1 : 0);
continue;
case "not":
ScriptListener.arithmeticInfixCommand(this, generateArgumentArray("not", this, command), (left) -> left == 1 ? 0 : 1);
continue;
case "and":
ScriptListener.arithmeticCommand(this, generateArgumentArray("and", this, command), (left, right) -> left == 1 && right == 1 ? 1 : 0);
continue;
case "or":
ScriptListener.arithmeticCommand(this, generateArgumentArray("or", this, command), (left, right) -> left == 1 || right == 1 ? 1 : 0);
continue;
case "if":
int ifJumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", command));
int ifJumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", this, command));
if (ifJumpIndex != -1) {
index = ifJumpIndex;
}
@ -157,10 +193,7 @@ public class ScriptListener implements Listener {
}
// Variable Replaces in commands.
String[] commandArgs = command.split(" ");
String[] args = Arrays.copyOfRange(commandArgs, 1, commandArgs.length);
replaceVariables(this, args);
command = commandArgs[0] + " " + String.join(" ", args);
command = String.join(" ", generateArgumentArray("", this, command));
Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command);
Bukkit.getServer().dispatchCommand(player, command);
@ -169,8 +202,14 @@ public class ScriptListener implements Listener {
}
private static String[] generateArgumentArray(String command, String fullCommand) {
return fullCommand.substring(command.length()).trim().split(" ");
private static String[] generateArgumentArray(String command, ScriptExecutor scriptExecutor, String fullCommand) {
String[] strings;
if (command.isEmpty()) {
strings = fullCommand.split(" ");
} else {
strings = fullCommand.substring(command.length()).trim().split(" ");
}
return replaceVariables(scriptExecutor, strings);
}
private static void sleepCommand(ScriptExecutor scriptExecutor, String[] args) {
@ -197,17 +236,25 @@ public class ScriptListener implements Listener {
return scriptExecutor.jumpPoints.getOrDefault(args[0], -1);
}
private static void replaceVariables(ScriptExecutor scriptExecutor, String[] args) {
private static String[] replaceVariables(ScriptExecutor scriptExecutor, String[] args) {
// Legacy '$' notation for variable reference, could be removed later on.
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("$") && isVariable(scriptExecutor, args[i].substring(1))) {
args[i] = getValue(scriptExecutor, args[i].substring(1)) + "";
}
}
String s = String.join(" ", args);
Set<String> variables = new HashSet<>(scriptExecutor.variables.keySet());
variables.addAll(Arrays.asList("trace", "autotrace", "tnt", "freeze", "fire"));
for (String variable : variables) {
s = s.replace("<" + variable + ">", getValue(scriptExecutor, variable) + "");
}
return s.split(" ");
}
private static void echoCommand(ScriptExecutor scriptExecutor, String[] args) {
replaceVariables(scriptExecutor, args);
scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", args)));
scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", replaceVariables(scriptExecutor, args))));
}
private static void variableCommand(ScriptExecutor scriptExecutor, String[] args) {
@ -233,31 +280,20 @@ public class ScriptListener implements Listener {
default:
break;
}
setValue(scriptExecutor, args[0], args[1]);
setValue(scriptExecutor, args[0], parseValue(args[1]));
}
private static int ifCommand(ScriptExecutor scriptExecutor, String[] args) {
if (args.length < 2) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie ersten beiden Argumente sind Zahlen/Boolsche Wertde oder Variablen.");
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDie ersten beiden Argumente sind Zahlen/Boolsche Werte oder Variablen.");
return -1;
}
int jumpTruePoint = scriptExecutor.jumpPoints.getOrDefault(args[2], -1);
int jumpFalsePoint = args.length > 3 ? scriptExecutor.jumpPoints.getOrDefault(args[3], -1) : -1;
int firstValue;
int secondValue;
if (isVariable(scriptExecutor, args[0])) {
firstValue = getValue(scriptExecutor, args[0]);
} else {
firstValue = parseValue(args[0]);
}
if (isVariable(scriptExecutor, args[1])) {
secondValue = getValue(scriptExecutor, args[1]);
} else {
secondValue = parseValue(args[1]);
}
int firstValue = getValueOrParse(scriptExecutor, args[0]);
int secondValue = getValueOrParse(scriptExecutor, args[1]);
if (firstValue == secondValue) {
return jumpTruePoint;
} else {
@ -265,8 +301,76 @@ public class ScriptListener implements Listener {
}
}
private static void setValue(ScriptExecutor scriptExecutor, String key, String value) {
scriptExecutor.variables.put(key, parseValue(value));
private static void arithmeticCommand(ScriptExecutor scriptExecutor, String[] args, IntBinaryOperator operation) {
if (args.length < 1) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable");
return;
}
if (args.length < 2) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls zweites Argument fehlt eine Zahl oder Variable");
return;
}
int firstValue;
int secondValue;
if (args.length < 3) {
if (!isVariable(scriptExecutor, args[0])) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDas erste Argument muss eine Variable sein");
return;
}
firstValue = getValue(scriptExecutor, args[0]);
secondValue = getValueOrParse(scriptExecutor, args[1]);
} else {
firstValue = getValue(scriptExecutor, args[1]);
secondValue = getValueOrParse(scriptExecutor, args[2]);
}
setValue(scriptExecutor, args[0], operation.applyAsInt(firstValue, secondValue));
}
private static void arithmeticInfixCommand(ScriptExecutor scriptExecutor, String[] args, IntUnaryOperator operation) {
if (args.length < 1) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable");
return;
}
int firstValue;
if (args.length < 2) {
if (!isVariable(scriptExecutor, args[0])) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cDas erste Argument muss eine Variable sein");
return;
}
firstValue = getValue(scriptExecutor, args[0]);
} else {
firstValue = getValue(scriptExecutor, args[1]);
}
setValue(scriptExecutor, args[0], operation.applyAsInt(firstValue));
}
private static void inputCommand(ScriptExecutor scriptExecutor, String[] args) {
if (args.length < 1) {
scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cAls erstes Argument fehlt eine Variable");
return;
}
String varName = args[0];
StringBuilder st = new StringBuilder();
for (int i = 1; i < args.length; i++) {
if (i != 1) {
st.append(" ");
}
st.append(args[i]);
}
SWAnvilInv swAnvilInv = new SWAnvilInv(scriptExecutor.player, ChatColor.translateAlternateColorCodes('&', st.toString()));
swAnvilInv.setCallback(s -> {
int value = parseValue(s);
setValue(scriptExecutor, varName, value);
scriptExecutor.resume();
});
swAnvilInv.open();
}
private static void setValue(ScriptExecutor scriptExecutor, String key, int value) {
scriptExecutor.variables.put(key, value);
}
private static void add(ScriptExecutor scriptExecutor, String key, int value) {
@ -276,17 +380,27 @@ public class ScriptListener implements Listener {
scriptExecutor.variables.put(key, scriptExecutor.variables.get(key) + value);
}
private static int getValueOrParse(ScriptExecutor scriptExecutor, String key) {
if (isVariable(scriptExecutor, key)) {
return getValue(scriptExecutor, key);
} else {
return parseValue(key);
}
}
private static int getValue(ScriptExecutor scriptExecutor, String key) {
Region region = Region.getRegion(scriptExecutor.player.getLocation());
switch (key) {
case "trace":
return RecordStateMachine.getRecordStatus().isTracing() ? 1 : 0;
case "autotrace":
return RecordStateMachine.getRecordStatus().isAutoTrace() ? 1 : 0;
case "tnt":
return region == null || region.getTntMode() == CommandTNT.TNTMode.OFF ? 0 : 1;
return region.getTntMode() == CommandTNT.TNTMode.OFF ? 0 : 1;
case "freeze":
return region == null || !region.isFreeze() ? 0 : 1;
return !region.isFreeze() ? 0 : 1;
case "fire":
return region == null || !region.isFire() ? 0 : 1;
return !region.isFire() ? 0 : 1;
default:
return scriptExecutor.variables.getOrDefault(key, 0);
}
@ -295,6 +409,7 @@ public class ScriptListener implements Listener {
private static boolean isVariable(ScriptExecutor scriptExecutor, String key) {
switch (key) {
case "trace":
case "autotrace":
case "tnt":
case "freeze":
case "fire":