diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index 56309f2..2a42867 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -117,6 +117,7 @@ public class BauSystem extends JavaPlugin implements Listener { getCommand("watervision").setExecutor(new CommandGills()); getCommand("detonator").setExecutor(new CommandDetonator()); getCommand("detonator").setTabCompleter(new CommandDetonatorTabCompleter()); + getCommand("script").setExecutor(new CommandScript()); Bukkit.getPluginManager().registerEvents(this, this); Bukkit.getPluginManager().registerEvents(new RegionListener(), this); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java new file mode 100644 index 0000000..b093046 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java @@ -0,0 +1,74 @@ +/* + * + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * / + */ + +package de.steamwar.bausystem.commands; + +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.util.ArrayList; +import java.util.List; + +public class CommandScript implements CommandExecutor { + + public static final ItemStack BOOK = new ItemStack(Material.WRITTEN_BOOK, 1); + + static { + List 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("§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("§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("§6Variablen§8\n\nMit Variablen kann man sich Zahlen speichern. Man definiert diese mit 'var '.\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("§6Abfragen§8\n\nMit Abfragen kann man nur Gleichheit von 2 Werten überprüft werden. Hierfür verwendet man\n'if '.\nNach den zwei Werten kann man ein oder 2 Jump-Points schreiben\n'if [...] (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 ' 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"); + + BookMeta bookMeta = (BookMeta) BOOK.getItemMeta(); + bookMeta.setGeneration(BookMeta.Generation.ORIGINAL); + bookMeta.setAuthor("§eSteam§8war"); + bookMeta.setTitle("§7Script Buch"); + bookMeta.setDisplayName("§7Script Buch"); + bookMeta.setPages(pages); + BOOK.setItemMeta(bookMeta); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + if (!(sender instanceof Player)) { + return false; + } + ((Player) sender).getInventory().setItemInMainHand(BOOK); + return false; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java b/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java index a4dacb6..98c0b7f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java @@ -20,22 +20,27 @@ package de.steamwar.bausystem.world; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.commands.CommandFire; +import de.steamwar.bausystem.commands.CommandFreeze; +import de.steamwar.bausystem.commands.CommandScript; +import de.steamwar.bausystem.commands.CommandTNT; +import de.steamwar.bausystem.tracer.recorder.RecordManager; import de.steamwar.core.Core; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.logging.Level; public class ScriptListener implements Listener { @@ -52,6 +57,10 @@ public class ScriptListener implements Listener { if(item == null || isNoBook(item) || item.getItemMeta() == null) return; + if (item.getItemMeta().getDisplayName().equals(CommandScript.BOOK.getItemMeta().getDisplayName())) { + return; + } + if (event.getAction() != Action.LEFT_CLICK_AIR && event.getAction() != Action.LEFT_CLICK_BLOCK) { if (event.getAction() == Action.RIGHT_CLICK_AIR) { playerSet.add(event.getPlayer()); @@ -80,6 +89,9 @@ public class ScriptListener implements Listener { private final Player player; private final List commands = new ArrayList<>(); + private final Map jumpPoints = new HashMap<>(); + private Map variables = new HashMap<>(); + private int index = 0; public ScriptExecutor(BookMeta bookMeta, Player player) { @@ -88,6 +100,10 @@ public class ScriptListener implements Listener { for(String page : bookMeta.getPages()) { for (String command : page.split("\n")) { if (command.startsWith("#") || command.trim().isEmpty()) continue; + if (command.startsWith(".")) { + jumpPoints.put(command.substring(1), commands.size()); + continue; + } commands.add(command); } } @@ -100,20 +116,59 @@ public class ScriptListener implements Listener { return; } + int executionPoints = 0; + while (index < commands.size()) { String command = commands.get(index++); - - if (command.toLowerCase().startsWith("sleep")) { - ScriptListener.sleepCommand(this, generateArgumentArray("sleep", command)); + if (executionPoints++ > 200) { + player.sendMessage(BauSystem.PREFIX + "§cFüge ein sleep in dein Script ein"); return; } + String firstArg = command; + if (command.contains(" ")) { + firstArg = command.substring(0, command.indexOf(' ')); + } + switch (firstArg.toLowerCase()) { + case "sleep": + ScriptListener.sleepCommand(this, generateArgumentArray("sleep", command)); + return; + case "exit": + return; + case "jump": + int jumpIndex = ScriptListener.jumpCommand(this, generateArgumentArray("jump", command)); + if (jumpIndex != -1) { + index = jumpIndex; + } else { + player.sendMessage(BauSystem.PREFIX + "§cUnbekannter Jump Punkt: " + command); + } + continue; + case "echo": + ScriptListener.echoCommand(this, generateArgumentArray("echo", command)); + continue; + case "var": + ScriptListener.variableCommand(this, generateArgumentArray("var", command)); + continue; + case "if": + int ifJumpIndex = ScriptListener.ifCommand(this, generateArgumentArray("if", command)); + if (ifJumpIndex != -1) { + index = ifJumpIndex; + } + continue; + } + PlayerCommandPreprocessEvent preprocessEvent = new PlayerCommandPreprocessEvent(player, "/" + command); Bukkit.getServer().getPluginManager().callEvent(preprocessEvent); if (preprocessEvent.isCancelled()) { continue; } + // 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); + Bukkit.getLogger().log(Level.INFO, player.getName() + " dispatched command: " + command); Bukkit.getServer().dispatchCommand(player, command); } @@ -141,4 +196,128 @@ public class ScriptListener implements Listener { Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), scriptExecutor::resume, sleepTime); } + private static int jumpCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cEin Jump Punkt muss angegeben sein."); + return -1; + } + return scriptExecutor.jumpPoints.getOrDefault(args[0], -1); + } + + private static void replaceVariables(ScriptExecutor scriptExecutor, String[] args) { + 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)) + ""; + } + } + } + + private static void echoCommand(ScriptExecutor scriptExecutor, String[] args) { + replaceVariables(scriptExecutor, args); + scriptExecutor.player.sendMessage("§eInfo§8» §7" + ChatColor.translateAlternateColorCodes('&', String.join(" ", args))); + } + + private static void variableCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen und Zahlen/Boolsche Wert fehlt."); + return; + } + if (args.length < 2) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cZahlen/Boolsche Wert fehlt."); + return; + } + switch (args[1]) { + case "inc": + case "increment": + case "++": + add(scriptExecutor, args[0], 1); + return; + case "dec": + case "decrement": + case "--": + add(scriptExecutor, args[0], -1); + return; + } + setValue(scriptExecutor, args[0], 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."); + 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]); + } + + if (firstValue == secondValue) { + return jumpTruePoint; + } else { + return jumpFalsePoint; + } + } + + private static void setValue(ScriptExecutor scriptExecutor, String key, String value) { + scriptExecutor.variables.put(key, parseValue(value)); + } + + private static void add(ScriptExecutor scriptExecutor, String key, int value) { + if (!isVariable(scriptExecutor, key)) { + scriptExecutor.variables.put(key, 0); + } + scriptExecutor.variables.put(key, scriptExecutor.variables.get(key) + value); + } + + private static int getValue(ScriptExecutor scriptExecutor, String key) { + switch (key) { + case "trace": + return RecordManager.getStatus().isTracing() ? 1 : 0; + case "tnt": + return CommandTNT.getInstance().isOn() ? 1 : 0; + case "freeze": + return CommandFreeze.getInstance().isOn() ? 1 : 0; + case "fire": + return CommandFire.getInstance().isOn() ? 1 : 0; + } + return scriptExecutor.variables.getOrDefault(key, 0); + } + + private static boolean isVariable(ScriptExecutor scriptExecutor, String key) { + switch (key) { + case "trace": + case "tnt": + case "freeze": + case "fire": + return true; + default: + return scriptExecutor.variables.containsKey(key); + } + } + + private static int parseValue(String value) { + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) { + return 1; + } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) { + return 0; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return 0; + } + } + } diff --git a/BauSystem_Main/src/plugin.yml b/BauSystem_Main/src/plugin.yml index 0c6a0f4..bc85fb9 100644 --- a/BauSystem_Main/src/plugin.yml +++ b/BauSystem_Main/src/plugin.yml @@ -33,3 +33,4 @@ commands: lockschem: detonator: aliases: dt + script: \ No newline at end of file