diff --git a/BauSystem_12/src/de/steamwar/bausystem/commands/TPSLimit_12.java b/BauSystem_12/src/de/steamwar/bausystem/commands/TPSLimit_12.java index b7e5272..cfe3928 100644 --- a/BauSystem_12/src/de/steamwar/bausystem/commands/TPSLimit_12.java +++ b/BauSystem_12/src/de/steamwar/bausystem/commands/TPSLimit_12.java @@ -24,7 +24,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; import java.util.ArrayList; @@ -36,7 +36,7 @@ class TPSLimit_12 { static void createTickCache(World world) { packets.clear(); - world.getEntitiesByClasses(TNTPrimed.class, FallingBlock.class).forEach(entity -> { + world.getEntities().stream().filter(entity -> !(entity instanceof Player)).forEach(entity -> { packets.add(new PacketPlayOutEntityVelocity(entity.getEntityId(), 0, 0, 0)); packets.add(new PacketPlayOutEntityTeleport(((CraftEntity) entity).getHandle())); diff --git a/BauSystem_12/src/de/steamwar/bausystem/tracer/TraceEntity_12.java b/BauSystem_12/src/de/steamwar/bausystem/tracer/TraceEntity_12.java index c42cf23..d39c62f 100644 --- a/BauSystem_12/src/de/steamwar/bausystem/tracer/TraceEntity_12.java +++ b/BauSystem_12/src/de/steamwar/bausystem/tracer/TraceEntity_12.java @@ -49,7 +49,7 @@ class TraceEntity_12 extends EntityFallingBlock implements AbstractTraceEntity { } else if (references++ > 0) return; - PacketPlayOutSpawnEntity packetPlayOutSpawnEntity = new PacketPlayOutSpawnEntity(this, 0, 0); + PacketPlayOutSpawnEntity packetPlayOutSpawnEntity = new PacketPlayOutSpawnEntity(this, 70, Block.getCombinedId(getBlock())); PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutSpawnEntity); diff --git a/BauSystem_15/src/de/steamwar/bausystem/commands/TPSLimit_15.java b/BauSystem_15/src/de/steamwar/bausystem/commands/TPSLimit_15.java index 04cd25c..344bcf9 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/commands/TPSLimit_15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/commands/TPSLimit_15.java @@ -24,7 +24,7 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; import java.util.ArrayList; @@ -37,7 +37,7 @@ class TPSLimit_15 { static void createTickCache(World world) { packets.clear(); - world.getEntitiesByClasses(TNTPrimed.class, FallingBlock.class).forEach(entity -> { + world.getEntities().stream().filter(entity -> !(entity instanceof Player)).forEach(entity -> { packets.add(new PacketPlayOutEntityVelocity(entity.getEntityId(), noMotion)); packets.add(new PacketPlayOutEntityTeleport(((CraftEntity) entity).getHandle())); diff --git a/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java b/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java index e5b2468..693cd1f 100644 --- a/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java +++ b/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java @@ -29,6 +29,14 @@ import java.util.List; public class SWUtils { public static void giveItemToPlayer(Player player, ItemStack itemStack) { + for (int i = 0; i < player.getInventory().getSize(); i++) { + ItemStack current = player.getInventory().getItem(i); + if (current != null && current.isSimilar(itemStack)) { + player.getInventory().setItem(i, null); + itemStack = current; + break; + } + } ItemStack current = player.getInventory().getItemInMainHand(); player.getInventory().setItemInMainHand(itemStack); if (current.getType() != Material.AIR) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index dd1817f..78869bc 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -23,6 +23,7 @@ import de.steamwar.bausystem.commands.*; import de.steamwar.bausystem.world.*; import de.steamwar.core.CommandRemover; import de.steamwar.core.Core; +import de.steamwar.core.VersionedRunnable; import de.steamwar.scoreboard.SWScoreboard; import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; @@ -97,8 +98,11 @@ public class BauSystem extends JavaPlugin implements Listener { getCommand("detonator").setExecutor(new CommandDetonator()); getCommand("detonator").setTabCompleter(new CommandDetonatorTabCompleter()); getCommand("script").setExecutor(new CommandScript()); + getCommand("scriptvars").setExecutor(new CommandScriptVars()); + getCommand("scriptvars").setTabCompleter(new CommandScriptVarsTabCompleter()); getCommand("simulator").setExecutor(new CommandSimulator()); getCommand("simulator").setTabCompleter(new CommandSimulatorTabCompleter()); + getCommand("redstonetester").setExecutor(new CommandRedstoneTester()); getCommand("gui").setExecutor(new CommandGUI()); Bukkit.getPluginManager().registerEvents(this, this); @@ -109,6 +113,7 @@ public class BauSystem extends JavaPlugin implements Listener { Bukkit.getPluginManager().registerEvents(new TNTSimulatorListener(), this); Bukkit.getPluginManager().registerEvents(new CommandGUI(), this); Bukkit.getPluginManager().registerEvents(new DetonatorListener(), this); + VersionedRunnable.call(new VersionedRunnable(() -> Bukkit.getPluginManager().registerEvents(new RedstoneListener(), this), 15)); new AFKStopper(); autoShutdown = Bukkit.getScheduler().runTaskLater(this, Bukkit::shutdown, 1200); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandDetonator.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandDetonator.java index 0785385..1528920 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandDetonator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandDetonator.java @@ -33,7 +33,7 @@ public class CommandDetonator implements CommandExecutor { private void help(Player player) { player.sendMessage("§8/§edetonator wand §8- §7Legt den Fernzünder ins Inventar"); - player.sendMessage("§8/§edetonator detonate §8- §7Benutzt den Fernzünder"); + player.sendMessage("§8/§edetonator detonate §8- §7Benutzt den nächst besten Fernzünder"); player.sendMessage("§8/§edetonator reset §8- §7Löscht alle markierten Positionen"); player.sendMessage("§8/§edetonator remove §8- §7Entfernt den Fernzünder"); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandGUI.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandGUI.java index 48abaca..5038659 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandGUI.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandGUI.java @@ -53,8 +53,6 @@ public class CommandGUI implements CommandExecutor, Listener { OPEN_INVS.remove(player); }); - inv.setItem(37, getMaterial("GLASS_PANE", "THIN_GLASS"), "§7Platzhalter", clickType -> { - }); inv.setItem(43, getMaterial("GLASS_PANE", "THIN_GLASS"), "§7Platzhalter", clickType -> { }); inv.setItem(42, Material.NETHER_STAR, "§7Bau GUI Item", Arrays.asList("§7Du kannst dieses Item zum Öffnen der BauGUI nutzen", "§7oder Doppel F (Swap hands) drücken."), false, clickType -> { @@ -78,6 +76,14 @@ public class CommandGUI implements CommandExecutor, Listener { player.performCommand("sim wand"); }); + ItemStack redstoneWand = wand(player, RedstoneListener.WAND, "§8/§7redstonetester", Permission.build, "Du hast keine Buildrechte"); + inv.setItem(37, redstoneWand, clickType -> { + if (Welt.noPermission(player, Permission.build)) + return; + player.closeInventory(); + player.performCommand("redstonetester"); + }); + inv.setItem(40, getMaterial("WOODEN_AXE", "WOOD_AXE"), "§eWorldedit Axt", getNoPermsLore(Arrays.asList("§8//§7wand"), player, "§cDu hast keine Worldeditrechte", Permission.worldedit), false, clickType -> { if (Welt.noPermission(player, Permission.world)) return; @@ -571,7 +577,7 @@ public class CommandGUI implements CommandExecutor, Listener { ItemMeta meta = base.getItemMeta(); List lore = meta.getLore(); lore.add(command); - if (Welt.noPermission(player, permission)) + if (permission != null && Welt.noPermission(player, permission)) lore.add(noPermissionMessage); meta.setLore(lore); base.setItemMeta(meta); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java new file mode 100644 index 0000000..08c794a --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandRedstoneTester.java @@ -0,0 +1,60 @@ +/* + * 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 de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.world.RedstoneListener; +import de.steamwar.bausystem.world.Welt; +import de.steamwar.core.VersionedRunnable; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class CommandRedstoneTester implements CommandExecutor { + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.build)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Redstonetester nutzen"); + return false; + } + return true; + } + + @Override + public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) { + if (!(commandSender instanceof Player)) + return false; + Player player = (Player) commandSender; + VersionedRunnable.call(new VersionedRunnable(() -> { + player.sendMessage(BauSystem.PREFIX + "Der RedstoneTester ist nicht in der 1.12 verfügbar"); + }, 8), new VersionedRunnable(() -> { + if (!permissionCheck(player)) { + return; + } + player.sendMessage(BauSystem.PREFIX + "Messe die Zeit zwischen der Aktivierung zweier Redstone Komponenten"); + SWUtils.giveItemToPlayer(player, RedstoneListener.WAND); + }, 15)); + return false; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java index e8d0811..1af6767 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScript.java @@ -39,20 +39,36 @@ public class CommandScript implements CommandExecutor { 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("§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 '.\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 "); + pages.add("§8Man kann auch explizit eine globale, locale, oder konstante variable referenzieren, indem 'global.', 'local.' oder 'const.' vor den Namen in die Klammern zu schreiben."); + pages.add("§8Um Variablen über das Script ausführen zu speichern gibt es 'global' und 'unglobal' als Befehle. Der erste speichert eine locale Variable global und das zweite löscht eine globale wieder."); + pages.add("§8Des weiteren kann man Lokale Variablen mit 'unvar' löschen. Nach dem verlassen einer Welt werden alle Globalen Variablen gelöscht. Globale Variablen kann man mit '/scriptvars' einsehen."); + 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("§8Des weiteren gibt es 3 weitere Variablen, welche explizit Spieler gebunden sind\n\nDiese sind:\n- x\n- y\n- z"); 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("§8Des weiteren kann man überprüfen, ob eine Variable existiert mit 'if exists' wonach dann wieder 1 oder 2 Jump-Points sein müssen."); 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"); + 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); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVars.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVars.java new file mode 100644 index 0000000..946e07b --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVars.java @@ -0,0 +1,68 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.world.ScriptListener; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public class CommandScriptVars implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + if (!(sender instanceof Player)) { + return false; + } + Player player = (Player) sender; + if (args.length == 0) { + Map globalVariables = ScriptListener.GLOBAL_VARIABLES.get(player); + if (globalVariables == null) { + player.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + return false; + } + int i = 0; + player.sendMessage(BauSystem.PREFIX + globalVariables.size() + " Variable(n)"); + for (Map.Entry var : globalVariables.entrySet()) { + if (i++ >= 40) break; + player.sendMessage("- " + var.getKey() + "=" + var.getValue()); + } + return false; + } + String varName = args[0]; + if (args.length == 1) { + Map globalVariables = ScriptListener.GLOBAL_VARIABLES.get(player); + if (globalVariables == null) { + player.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + return false; + } + if (!globalVariables.containsKey(varName)) { + player.sendMessage(BauSystem.PREFIX + "§cUnbekannte Variable"); + return false; + } + player.sendMessage(BauSystem.PREFIX + varName + "=" + globalVariables.get(varName)); + return false; + } + switch (args[1].toLowerCase()) { + case "delete": + case "clear": + case "remove": + if (!ScriptListener.GLOBAL_VARIABLES.containsKey(player)) { + player.sendMessage(BauSystem.PREFIX + "§cKeine globalen Variablen definiert"); + break; + } + ScriptListener.GLOBAL_VARIABLES.get(player).remove(varName); + player.sendMessage(BauSystem.PREFIX + "Variable " + varName + " gelöscht"); + break; + default: + int value = ScriptListener.parseValue(args[1]); + ScriptListener.GLOBAL_VARIABLES.computeIfAbsent(player, p -> new HashMap<>()).put(varName, value); + player.sendMessage(BauSystem.PREFIX + varName + " auf " + value + " gesetzt"); + } + return false; + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVarsTabCompleter.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVarsTabCompleter.java new file mode 100644 index 0000000..f9fa6ef --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandScriptVarsTabCompleter.java @@ -0,0 +1,34 @@ +package de.steamwar.bausystem.commands; + +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.world.ScriptListener; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +public class CommandScriptVarsTabCompleter implements TabCompleter { + + @Override + public List onTabComplete(CommandSender sender, Command command, String s, String[] args) { + if (!(sender instanceof Player)) { + return new ArrayList<>(); + } + Player player = (Player) sender; + if (args.length == 1) { + List variables = new ArrayList<>(ScriptListener.GLOBAL_VARIABLES.getOrDefault(player, new HashMap<>()).keySet()); + return SWUtils.manageList(variables, args); + } + if (args.length != 2) { + return new ArrayList<>(); + } + int value = ScriptListener.GLOBAL_VARIABLES.getOrDefault(player, new HashMap<>()).getOrDefault(args[0], 0); + return SWUtils.manageList(Arrays.asList(value + "", "true", "false", "yes", "no", "delete", "clear", "remove"), args); + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/tracer/record/RecordStatus.java b/BauSystem_Main/src/de/steamwar/bausystem/tracer/record/RecordStatus.java index a70e53b..b87e740 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/tracer/record/RecordStatus.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/tracer/record/RecordStatus.java @@ -44,6 +44,10 @@ public enum RecordStatus { return tracing; } + public boolean isAutoTrace() { + return this == RECORD_AUTO || this == IDLE_AUTO; + } + public String getAutoMessage() { return autoMessage; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/Detonator.java b/BauSystem_Main/src/de/steamwar/bausystem/world/Detonator.java index b3918e8..81d7295 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/Detonator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/Detonator.java @@ -50,7 +50,11 @@ public class Detonator implements Listener { im.setDisplayName("§eFernzünder"); - VersionedRunnable.call(new VersionedRunnable(() -> im.getPersistentDataContainer().set(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE, (byte) 1), 15)); + VersionedRunnable.call( + new VersionedRunnable(() -> { + im.getPersistentDataContainer().set(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE, (byte) 1); + im.getPersistentDataContainer().set(new NamespacedKey(BauSystem.getPlugin(), "deto-locs"), PersistentDataType.INTEGER, 0); + }, 15)); List lorelist = Arrays.asList("§eLinks Klick §8- §7Setzte einen Punkt zum Aktivieren", "§eLinks Klick + Shift §8- §7Füge einen Punkt hinzu", "§eRechts Klick §8- §7Löse alle Punkte aus"); @@ -66,7 +70,7 @@ public class Detonator implements Listener { ItemMeta meta = item.getItemMeta(); PersistentDataContainer container = meta.getPersistentDataContainer(); List locs = new ArrayList<>(); - for (int i = 0; i < 128; i++) { + for (int i = 0; i < getDetoLocs(container); i++) { NamespacedKey key = new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + i); if (container.has(key, PersistentDataType.INTEGER_ARRAY)) locs.add(container.get(key, PersistentDataType.INTEGER_ARRAY)); @@ -80,7 +84,14 @@ public class Detonator implements Listener { PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).clear(); PLAYER_LOCS.get(player).add(detoloader); return item; - }, 12), new VersionedCallable<>(() -> pushLocToDetonator(clearDetonator(item), detoloader), 15)); + }, 12), new VersionedCallable<>(() -> { + try { + return pushLocToDetonator(clearDetonator(item), detoloader); + }catch (SecurityException e){ + player.sendMessage(BauSystem.PREFIX + "§c" + e.getMessage()); + return item; + } + }, 15)); } public static ItemStack toggleLocation(ItemStack item, Player player, Detoloader detoloader, Location location) { @@ -94,27 +105,70 @@ public class Detonator implements Listener { }, 12), new VersionedCallable<>(() -> removeLocation(item, location), 15)); } else { DetonatorListener.print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " hinzugefügt" : - detoloader.getBlock(), Math.min(Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() + 1, 128)); + detoloader.getBlock(), Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() + 1); if (detoloader.getActivation() == 0) return VersionedCallable.call(new VersionedCallable<>(() -> { PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).add(new Detoloader.DetonatorActivation(location)); return item; - }, 12), new VersionedCallable<>(() -> pushLocToDetonator(item, new Detoloader.DetonatorActivation(location)), 15)); + }, 12), new VersionedCallable<>(() -> { + try { + return pushLocToDetonator(item, new Detoloader.DetonatorActivation(location)); + }catch (SecurityException e){ + player.sendMessage(BauSystem.PREFIX + "§c" + e.getMessage()); + return item; + } + }, 15)); else return VersionedCallable.call(new VersionedCallable<>(() -> { PLAYER_LOCS.computeIfAbsent(player, player1 -> new HashSet<>()).add(new Detoloader.DetonatorActivation(detoloader.getActivation(), location)); return item; - }, 12), new VersionedCallable<>(() -> pushLocToDetonator(item, new Detoloader.DetonatorActivation(detoloader.getActivation(), location)), 15)); + }, 12), new VersionedCallable<>(() -> { + try { + return pushLocToDetonator(item, new Detoloader.DetonatorActivation(detoloader.getActivation(), location)); + }catch (SecurityException e){ + player.sendMessage(BauSystem.PREFIX + "§c" + e.getMessage()); + return item; + } + }, 15)); } } public static void execute(Player player) { VersionedRunnable.call(new VersionedRunnable(() -> execute(player, PLAYER_LOCS.get(player)), 12), new VersionedRunnable(() -> { - Detonator detonator = getDetonator(player, player.getInventory().getItemInMainHand()); - execute(player, detonator.getLocs()); + try { + ItemStack item = getNextBestDetonator(player); + if (item == null) + return; + Detonator detonator = getDetonator(player, item); + execute(player, detonator.getLocs()); + } catch (SecurityException e) { + player.sendMessage(BauSystem.PREFIX + "§c" + e.getMessage()); + } }, 15)); } + private static ItemStack getNextBestDetonator(Player player) { + if (player.getInventory().getItemInMainHand().getItemMeta() != null && player.getInventory().getItemInMainHand().getItemMeta().getPersistentDataContainer().has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + return player.getInventory().getItemInMainHand(); + } + + if(player.getInventory().getItemInOffHand().getItemMeta() != null && player.getInventory().getItemInOffHand().getItemMeta().getPersistentDataContainer().has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + return player.getInventory().getItemInOffHand(); + } + + for (ItemStack item : player.getInventory().getContents()) { + if (item == null) + continue; + + if (item.getItemMeta() != null && + item.getItemMeta().getPersistentDataContainer().has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + return item; + } + } + player.sendMessage(BauSystem.PREFIX + "§cDu hast keinen Detonator im Inventar"); + return null; + } + private static void execute(Player player, Set locs) { for (Detoloader.DetonatorActivation activation : locs) { @@ -141,22 +195,46 @@ public class Detonator implements Listener { private static int getFreeSlot(ItemStack item) { ItemMeta meta = item.getItemMeta(); + if (meta == null) { + throw new SecurityException("Das Item ist kein Detonator"); + } PersistentDataContainer container = meta.getPersistentDataContainer(); - for (int i = 0; i < 128; i++) { - if (!container.has(new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + i), PersistentDataType.INTEGER_ARRAY)) + if (!container.has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + throw new SecurityException("Das Item ist kein Detonator"); + } + for (int i = 0; i < getDetoLocs(container) + 1; i++) { + if (!container.has(new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + i), PersistentDataType.INTEGER_ARRAY)) { return i; + } } return -1; } + private static int getDetoLocs(PersistentDataContainer container) { + if (!container.has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + throw new SecurityException("Das Item ist kein Detonator"); + } + return container.get(new NamespacedKey(BauSystem.getPlugin(), "deto-locs"), PersistentDataType.INTEGER); + } + + private static void increaseLocsSize(PersistentDataContainer container, int to) { + if (!container.has(new NamespacedKey(BauSystem.getPlugin(), "deto"), PersistentDataType.BYTE)) { + throw new SecurityException("Das Item ist kein Detonator"); + } + if (container.get(new NamespacedKey(BauSystem.getPlugin(), "deto-locs"), PersistentDataType.INTEGER) < to) { + container.set(new NamespacedKey(BauSystem.getPlugin(), "deto-locs"), PersistentDataType.INTEGER, to); + } + } + public static ItemStack pushLocToDetonator(ItemStack item, Detoloader.DetonatorActivation detoloader) { int slot = getFreeSlot(item); if (slot == -1) - throw new SecurityException("Der Detonator ist auf 128 Positionen Limitiert"); + throw new SecurityException("Mit dem Detonator stimmt etwas nicht. Nimm dir einen neuen mit /dt wand. Wenn es dann immer nicht nicht tut, wende dich an einen Developer"); ItemMeta meta = item.getItemMeta(); Location block = detoloader.location; meta.getPersistentDataContainer().set(new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + slot), PersistentDataType.INTEGER_ARRAY, new int[] {block.getBlockX(), block.getBlockY(), block.getBlockZ(), detoloader.activation}); + increaseLocsSize(meta.getPersistentDataContainer(), slot + 1); item.setItemMeta(meta); return item; } @@ -164,7 +242,8 @@ public class Detonator implements Listener { public static ItemStack clearDetonator(ItemStack item) { ItemMeta meta = item.getItemMeta(); PersistentDataContainer container = meta.getPersistentDataContainer(); - for (int i = 0; i < 128; i++) { + container.set(new NamespacedKey(BauSystem.getPlugin(), "deto-locs"), PersistentDataType.INTEGER, 0); + for (int i = 0; i < getDetoLocs(container); i++) { NamespacedKey key = new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + i); container.remove(key); } @@ -179,7 +258,7 @@ public class Detonator implements Listener { private static int getSlotOfLocation(ItemStack item, Location location) { ItemMeta meta = item.getItemMeta(); PersistentDataContainer container = meta.getPersistentDataContainer(); - for (int i = 0; i < 128; i++) { + for (int i = 0; i < getDetoLocs(container); i++) { NamespacedKey key = new NamespacedKey(BauSystem.getPlugin(), DETO_PREFIX + i); if (container.has(key, PersistentDataType.INTEGER_ARRAY)) { int[] locs = container.get(key, PersistentDataType.INTEGER_ARRAY); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/DetonatorListener.java b/BauSystem_Main/src/de/steamwar/bausystem/world/DetonatorListener.java index fb0b1c6..dced125 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/DetonatorListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/DetonatorListener.java @@ -27,40 +27,35 @@ public class DetonatorListener implements Listener { } ItemStack item = event.getItem(); event.setCancelled(true); - try { - switch (event.getAction()) { - case LEFT_CLICK_BLOCK: - Detoloader detoloader = VersionedCallable.call( - new VersionedCallable<>(() -> AutoLoader_12.onPlayerInteractLoader(event), 12), - new VersionedCallable<>(() -> AutoLoader_15.onPlayerInteractLoader(event), 15)); + switch (event.getAction()) { + case LEFT_CLICK_BLOCK: + Detoloader detoloader = VersionedCallable.call( + new VersionedCallable<>(() -> AutoLoader_12.onPlayerInteractLoader(event), 12), + new VersionedCallable<>(() -> AutoLoader_15.onPlayerInteractLoader(event), 15)); - if (detoloader == null) { - return; - } else if (detoloader.activation == -1) { - print(player, detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); - return; - } + if (detoloader == null) { + return; + } else if (detoloader.activation == -1) { + print(player, detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); + return; + } - if (event.getPlayer().isSneaking()) { - player.getInventory().setItemInMainHand(Detonator.toggleLocation(item, player, detoloader, event.getClickedBlock().getLocation())); + if (event.getPlayer().isSneaking()) { + player.getInventory().setItemInMainHand(Detonator.toggleLocation(item, player, detoloader, event.getClickedBlock().getLocation())); + } else { + if (detoloader.getActivation() == 0) { + player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(event.getClickedBlock().getLocation()))); } else { - if (detoloader.getActivation() == 0) { - player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(event.getClickedBlock().getLocation()))); - } else { - player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(detoloader.activation, event.getClickedBlock().getLocation()))); - } - print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " gesetzt" : - detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); + player.getInventory().setItemInMainHand(Detonator.setLocation(player, item, new Detoloader.DetonatorActivation(detoloader.activation, event.getClickedBlock().getLocation()))); } - break; - case RIGHT_CLICK_AIR: - case RIGHT_CLICK_BLOCK: - Detonator.execute(player); - break; - } - } catch (RuntimeException e) { - player.sendMessage(BauSystem.PREFIX + "§c" + e.getMessage()); - player.getInventory().setItemInMainHand(item); + print(player, detoloader.addBack ? "§e" + detoloader.getBlock() + " gesetzt" : + detoloader.getBlock(), detoloader.addBack ? Detonator.getDetonator(player, player.getInventory().getItemInMainHand()).getLocs().size() : 0); + } + break; + case RIGHT_CLICK_AIR: + case RIGHT_CLICK_BLOCK: + Detonator.execute(player); + break; } } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/RedstoneListener.java b/BauSystem_Main/src/de/steamwar/bausystem/world/RedstoneListener.java new file mode 100644 index 0000000..1fd82b3 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/RedstoneListener.java @@ -0,0 +1,175 @@ +/* + * 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.world; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.inventory.SWItem; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Powerable; +import org.bukkit.block.data.type.Piston; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class RedstoneListener implements Listener { + + public static final ItemStack WAND = new SWItem(Material.BLAZE_ROD, "§eRedstonetester", Arrays.asList("§eLinksklick Block §8- §7Setzt die 1. Position", "§eRechtsklick Block §8- §7Setzt die 2. Position", "§eShift-Rechtsklick Luft §8- §7Zurücksetzten"), false, null).getItemStack(); + private static Map playerMap = new HashMap<>(); + + private boolean permissionCheck(Player player) { + if (Welt.noPermission(player, Permission.build)) { + player.sendMessage(BauSystem.PREFIX + "§cDu darfst hier nicht den Redstonetester nutzen"); + return false; + } + return true; + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (!WAND.isSimilar(event.getItem())) return; + Player player = event.getPlayer(); + Block block = event.getClickedBlock(); + event.setCancelled(true); + + if (!permissionCheck(event.getPlayer())) { + return; + } + + switch (event.getAction()) { + case RIGHT_CLICK_AIR: + if (player.isSneaking()) { + playerMap.remove(event.getPlayer()); + player.sendMessage(BauSystem.PREFIX + "Positionen gelöscht§8."); + } + break; + case LEFT_CLICK_BLOCK: + if (!validBlock(event.getPlayer(), block.getBlockData())) return; + playerMap.computeIfAbsent(event.getPlayer(), RedstoneTester::new).loc1 = block.getLocation(); + sendLocation(event.getPlayer(), "POS1", block.getLocation()); + break; + case RIGHT_CLICK_BLOCK: + if (!validBlock(event.getPlayer(), block.getBlockData())) return; + playerMap.computeIfAbsent(event.getPlayer(), RedstoneTester::new).loc2 = block.getLocation(); + sendLocation(event.getPlayer(), "POS2", block.getLocation()); + break; + default: + break; + } + } + + private void sendLocation(Player player, String prefix, Location location) { + player.sendMessage(BauSystem.PREFIX + prefix + "§8: §e" + locationToString(location)); + } + + private static String locationToString(Location location) { + return location.getBlockX() + " " + location.getBlockY() + " " + location.getBlockZ(); + } + + private boolean validBlock(Player player, BlockData block) { + if (block instanceof Powerable) return true; + if (block instanceof Piston) return true; + player.sendMessage(BauSystem.PREFIX + "§cUnbekannte Position"); + return false; + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + playerMap.remove(event.getPlayer()); + } + + @EventHandler + public void onPistonExtend(BlockPistonExtendEvent e) { + playerMap.forEach((player, redstoneTester) -> { + redstoneTester.activate(e.getBlock().getLocation()); + }); + } + + @EventHandler + public void onPistonRetract(BlockPistonRetractEvent e) { + playerMap.forEach((player, redstoneTester) -> { + redstoneTester.activate(e.getBlock().getLocation()); + }); + } + + @EventHandler + public void onRedstoneEvent(BlockRedstoneEvent e) { + playerMap.forEach((player, redstoneTester) -> { + redstoneTester.activate(e.getBlock().getLocation()); + }); + } + + @EventHandler + public void onBlockDispense(BlockDispenseEvent e) { + playerMap.forEach((player, redstoneTester) -> { + redstoneTester.activate(e.getBlock().getLocation()); + }); + } + + private static class RedstoneTester { + + private final Player player; + private Location loc1 = null; + private Location loc2 = null; + + private long lastTick = 0; + private Long tick = null; + + public RedstoneTester(Player player) { + this.player = player; + } + + private void activate(Location location) { + if (loc1 == null || loc2 == null) { + tick = null; + return; + } + if (loc1.equals(location)) { + if (TPSUtils.currentTick.get() - lastTick > 100) { + tick = null; + } + lastTick = TPSUtils.currentTick.get(); + if (tick == null) { + tick = TPSUtils.currentTick.get(); + } + return; + } + if (tick != null && loc2.equals(location)) { + player.sendMessage(BauSystem.PREFIX + "Differenz§8: §e" + (TPSUtils.currentTick.get() - tick) + "§8 - §7in Ticks §8(§7Ticks/2 -> Redstoneticks§8)"); + } + } + + } + +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java b/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java index 179ca07..cf084e2 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/ScriptListener.java @@ -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; @@ -33,14 +34,32 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import java.util.*; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntUnaryOperator; import java.util.logging.Level; public class ScriptListener implements Listener { + public static final Map> GLOBAL_VARIABLES = new HashMap<>(); + private static final Map> CONSTANTS = new HashMap<>(); + + static { + CONSTANTS.put("trace", player -> RecordStateMachine.getRecordStatus().isTracing() ? 1 : 0); + CONSTANTS.put("autotrace", player -> RecordStateMachine.getRecordStatus().isAutoTrace() ? 1 : 0); + CONSTANTS.put("tnt", player -> Region.getRegion(player.getLocation()).getTntMode() == CommandTNT.TNTMode.OFF ? 0 : 1); + CONSTANTS.put("freeze", player -> Region.getRegion(player.getLocation()).isFreeze() ? 1 : 0); + CONSTANTS.put("fire", player -> Region.getRegion(player.getLocation()).isFire() ? 1 : 0); + CONSTANTS.put("x", player -> player.getLocation().getBlockX()); + CONSTANTS.put("y", player -> player.getLocation().getBlockY()); + CONSTANTS.put("z", player -> player.getLocation().getBlockZ()); + } + private Set playerSet = new HashSet<>(); public ScriptListener() { @@ -71,6 +90,11 @@ public class ScriptListener implements Listener { new ScriptExecutor((BookMeta) item.getItemMeta(), event.getPlayer()); } + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + GLOBAL_VARIABLES.remove(event.getPlayer()); + } + private boolean isNoBook(ItemStack item) { return VersionedCallable.call(new VersionedCallable<>(() -> ScriptListener_12.isNoBook(item), 8), new VersionedCallable<>(() -> ScriptListener_15.isNoBook(item), 15)); @@ -90,6 +114,7 @@ public class ScriptListener implements Listener { for (String page : bookMeta.getPages()) { for (String command : page.split("\n")) { + command = command.replaceAll(" +", " "); if (command.startsWith("#") || command.trim().isEmpty()) continue; if (command.startsWith(".")) { jumpPoints.put(command.substring(1), commands.size()); @@ -122,12 +147,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 +160,55 @@ 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 "unvar": + ScriptListener.unvariableCommand(this, generateArgumentArray("unvar", this, command)); + continue; + case "global": + ScriptListener.globalCommand(this, generateArgumentArray("global", this, command)); + continue; + case "unglobal": + ScriptListener.unglobalCommand(this, generateArgumentArray("unglobal", 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 +224,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 +233,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 +267,37 @@ 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 variables = new HashSet<>(scriptExecutor.variables.keySet()); + variables.addAll(CONSTANTS.keySet()); + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + variables.addAll(GLOBAL_VARIABLES.get(scriptExecutor.player).keySet()); + } + for (String variable : variables) { + s = s.replace("<" + variable + ">", getValue(scriptExecutor, variable) + ""); + } + for (String constVariable : CONSTANTS.keySet()) { + s = s.replace("", getConstantValue(scriptExecutor, constVariable) + ""); + } + for (String localVariable : scriptExecutor.variables.keySet()) { + s = s.replace("", getLocalValue(scriptExecutor, localVariable) + ""); + } + for (String globalVariable : GLOBAL_VARIABLES.getOrDefault(scriptExecutor.player, new HashMap<>()).keySet()) { + s = s.replace("", getGlobalValue(scriptExecutor, globalVariable) + ""); + } + 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 +323,65 @@ public class ScriptListener implements Listener { default: break; } - setValue(scriptExecutor, args[0], args[1]); + setValue(scriptExecutor, args[0], parseValue(args[1])); + } + + private static void unvariableCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isLocalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + scriptExecutor.variables.remove(args[0]); + } + + private static void globalCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isLocalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + GLOBAL_VARIABLES.computeIfAbsent(scriptExecutor.player, player -> new HashMap<>()).put(args[0], scriptExecutor.variables.getOrDefault(args[0], 0)); + } + + private static void unglobalCommand(ScriptExecutor scriptExecutor, String[] args) { + if (args.length < 1) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariablen Namen fehlt."); + return; + } + if (!isGlobalVariable(scriptExecutor, args[0])) { + scriptExecutor.player.sendMessage(BauSystem.PREFIX + "§cVariable is nicht definiert"); + return; + } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + GLOBAL_VARIABLES.get(scriptExecutor.player).remove(args[0]); + } } 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 (args[1].equals("exists")) { + if (isVariable(scriptExecutor, args[0])) { + return jumpTruePoint; + } else { + return jumpFalsePoint; + } } - 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 +389,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,35 +468,61 @@ public class ScriptListener implements Listener { scriptExecutor.variables.put(key, scriptExecutor.variables.get(key) + value); } - 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 "tnt": - return region == null || region.getTntMode() == CommandTNT.TNTMode.OFF ? 0 : 1; - case "freeze": - return region == null || !region.isFreeze() ? 0 : 1; - case "fire": - return region == null || !region.isFire() ? 0 : 1; - default: - return scriptExecutor.variables.getOrDefault(key, 0); + 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) { + if (CONSTANTS.containsKey(key)) { + return CONSTANTS.get(key).apply(scriptExecutor.player); + } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player) && GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key)) { + return GLOBAL_VARIABLES.get(scriptExecutor.player).get(key); + } + return scriptExecutor.variables.getOrDefault(key, 0); + } + + private static int getConstantValue(ScriptExecutor scriptExecutor, String key) { + return CONSTANTS.getOrDefault(key, player -> 0).apply(scriptExecutor.player); + } + + private static int getGlobalValue(ScriptExecutor scriptExecutor, String key) { + if (!GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + return 0; + } + return GLOBAL_VARIABLES.get(scriptExecutor.player).getOrDefault(key, 0); + } + + private static int getLocalValue(ScriptExecutor scriptExecutor, String key) { + 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); + if (CONSTANTS.containsKey(key)) { + return true; } + if (GLOBAL_VARIABLES.containsKey(scriptExecutor.player) && GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key)) { + return true; + } + return scriptExecutor.variables.containsKey(key); } - private static int parseValue(String value) { + private static boolean isLocalVariable(ScriptExecutor scriptExecutor, String key) { + return isVariable(scriptExecutor, key) && !isGlobalVariable(scriptExecutor, key); + } + + private static boolean isGlobalVariable(ScriptExecutor scriptExecutor, String key) { + if (!GLOBAL_VARIABLES.containsKey(scriptExecutor.player)) { + return false; + } + return GLOBAL_VARIABLES.get(scriptExecutor.player).containsKey(key); + } + + public static int parseValue(String value) { if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) { return 1; } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/world/TPSUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/world/TPSUtils.java index 53777f2..6ec2518 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/world/TPSUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/world/TPSUtils.java @@ -26,6 +26,8 @@ import de.steamwar.core.TPSWatcher; import de.steamwar.core.VersionedRunnable; import org.bukkit.Bukkit; +import java.util.function.Supplier; + public class TPSUtils { private TPSUtils() { @@ -36,12 +38,19 @@ public class TPSUtils { private static long nanoOffset = 0; private static long nanoDOffset = 0; + private static long ticksSinceServerStart = 0; + public static final Supplier currentTick = () -> ticksSinceServerStart; + public static void init() { VersionedRunnable.call(new VersionedRunnable(() -> warp = false, 8), new VersionedRunnable(() -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> nanoOffset += nanoDOffset, 1, 1); TPSUtils_15.init(() -> nanoOffset); }, 15)); + + Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), () -> { + ticksSinceServerStart++; + }, 1, 1); } public static void setTPS(double tps) { diff --git a/BauSystem_Main/src/plugin.yml b/BauSystem_Main/src/plugin.yml index 113cb9a..dd285ac 100644 --- a/BauSystem_Main/src/plugin.yml +++ b/BauSystem_Main/src/plugin.yml @@ -36,6 +36,9 @@ commands: detonator: aliases: dt script: + scriptvars: simulator: aliases: sim - gui: \ No newline at end of file + gui: + redstonetester: + aliases: rt \ No newline at end of file