From c6208161ab03b66bf709633637f91938df0d8436 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 24 Aug 2021 16:31:01 +0200 Subject: [PATCH] Add ScriptMenu for custom commands Signed-off-by: yoyosource --- .../script/CustomCommandListener.java | 178 ++++++++++++++++-- .../features/script/ScriptCommand.java | 11 +- .../features/script/ScriptExecutor.java | 64 +++++-- .../ScriptMenuBauGuiItem.java} | 6 +- 4 files changed, 217 insertions(+), 42 deletions(-) rename BauSystem_Main/src/de/steamwar/bausystem/features/script/{ScriptBookBauGuiItem.java => items/ScriptMenuBauGuiItem.java} (92%) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java index 3a29c34c..dbddcd35 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java @@ -19,12 +19,17 @@ package de.steamwar.bausystem.features.script; +import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.features.script.variables.Value; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; import de.steamwar.core.VersionedCallable; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.UserConfig; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -34,27 +39,28 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; +import yapion.hierarchy.output.LengthOutput; +import yapion.hierarchy.output.StringOutput; +import yapion.hierarchy.types.YAPIONArray; +import yapion.hierarchy.types.YAPIONMap; +import yapion.hierarchy.types.YAPIONObject; +import yapion.hierarchy.types.YAPIONValue; +import yapion.parser.YAPIONParser; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; @Linked(LinkageType.LISTENER) public class CustomCommandListener implements Listener { - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - private static class CustomCommand { - private final BookMeta bookMeta; - private final String[] args; - - public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { + private interface CustomCommand { + default Map check(String[] args, String[] command) { if (args.length != command.length) { - return false; + return null; } if (!args[0].equals(command[0])) { - return false; + return null; } Map arguments = new HashMap<>(); @@ -64,20 +70,71 @@ public class CustomCommandListener implements Listener { arguments.put(current.substring(1, current.length() - 1), new Value.StringValue(command[i])); } else { if (!current.equals(command[i])) { - return false; + return null; } } } + return arguments; + } + + boolean execute(String[] command, PlayerCommandPreprocessEvent e); + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + private static class InventoryCommand implements CustomCommand { + private final BookMeta bookMeta; + private final String[] args; + + public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { + Map arguments = check(args, command); + if (arguments == null) { + return false; + } + e.setCancelled(true); new ScriptExecutor(bookMeta, e.getPlayer(), arguments); return true; } } + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + private static class MenuCommand implements CustomCommand { + private final List pages; + private final String[] args; + + public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { + Map arguments = check(args, command); + if (arguments == null) { + return false; + } + + e.setCancelled(true); + new ScriptExecutor(pages, e.getPlayer(), arguments); + return true; + } + + public void toYAPION(YAPIONMap yapionMap) { + YAPIONArray yapionArray = new YAPIONArray(); + pages.forEach(yapionArray::add); + yapionMap.put(String.join(" ", args), yapionArray); + } + + public ItemStack toItem() { + SWItem swItem = new SWItem(Material.WRITABLE_BOOK, String.join(" ", args)); + BookMeta bookMeta = (BookMeta) swItem.getItemMeta(); + bookMeta.setPages(pages.toArray(new String[0])); + swItem.setItemMeta(bookMeta); + return swItem.getItemStack(); + } + } + private Map> playerMap = new HashMap<>(); private void updateInventory(Player p) { - playerMap.remove(p); + playerMap.computeIfPresent(p, (player, customCommands) -> { + customCommands.removeIf(InventoryCommand.class::isInstance); + return customCommands; + }); for (ItemStack item : p.getInventory().getContents()) { if (item == null || isNoBook(item) || item.getItemMeta() == null) { continue; @@ -94,20 +151,54 @@ public class CustomCommandListener implements Listener { if (!s.startsWith("#!CMD /")) { continue; } - playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomCommand(bookMeta, s.substring(6).split(" "))); + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new InventoryCommand(bookMeta, s.substring(6).split(" "))); } } @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - updateInventory(event.getPlayer()); + Player p = event.getPlayer(); + updateInventory(p); + + String s = UserConfig.getConfig(p.getUniqueId(), "bausystem-commands"); + YAPIONObject yapionObject; + if (s == null) { + yapionObject = new YAPIONObject(); + } else { + yapionObject = YAPIONParser.parse(s); + } + + yapionObject.getYAPIONMapOrSetDefault("", new YAPIONMap()).forEach((key, value) -> { + String[] command = ((YAPIONValue) key).get().split(" "); + List pages = ((YAPIONArray) value).stream().map(YAPIONValue.class::cast).map(YAPIONValue::get).map(String.class::cast).collect(Collectors.toList()); + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new MenuCommand(pages, command)); + }); } @EventHandler public void onPlayerQuit(PlayerQuitEvent e) { + save(e.getPlayer()); playerMap.remove(e.getPlayer()); } + private boolean save(Player p) { + if (!playerMap.containsKey(p)) { + UserConfig.removePlayerConfig(p.getUniqueId(), "bausystem-commands"); + return true; + } + YAPIONObject yapionObject = new YAPIONObject(); + YAPIONMap yapionMap = new YAPIONMap(); + yapionObject.add("", yapionMap); + playerMap.get(p).stream().filter(MenuCommand.class::isInstance).map(MenuCommand.class::cast).forEach(menuCommand -> { + menuCommand.toYAPION(yapionMap); + }); + if (yapionObject.toYAPION(new LengthOutput()).getLength() > 64 * 1024) { + return false; + } + UserConfig.updatePlayerConfig(p.getUniqueId(), "bausystem-commands", yapionObject.toYAPION(new StringOutput()).getResult()); + return true; + } + @EventHandler public void onInventoryClose(InventoryCloseEvent e) { if (e.getPlayer() instanceof Player) { @@ -122,13 +213,13 @@ public class CustomCommandListener implements Listener { return; } - List customCommands = playerMap.get(e.getPlayer()); - if (customCommands == null) { + List inventoryCommands = playerMap.get(e.getPlayer()); + if (inventoryCommands == null) { return; } String[] command = e.getMessage().split(" "); - for (CustomCommand customCommand : customCommands) { + for (CustomCommand customCommand : inventoryCommands) { if (customCommand.execute(command, e)) { return; } @@ -138,4 +229,53 @@ public class CustomCommandListener implements Listener { private boolean isNoBook(ItemStack item) { return VersionedCallable.call(new VersionedCallable<>(() -> ScriptListener_15.isNoBook(item), 15)); } + + public void openCommandsMenu(Player p) { + List> menuCommands = new ArrayList<>(); + playerMap.getOrDefault(p, new ArrayList<>()).stream().filter(MenuCommand.class::isInstance).map(MenuCommand.class::cast).forEach(menuCommand -> { + String command = "§e" + String.join(" ", menuCommand.args); + + menuCommands.add(new SWListInv.SWListEntry<>(new SWItem(Material.BOOK, command, Arrays.asList("§7Klicke zum rausnehmen"), false, clickType -> { + }), menuCommand)); + }); + SWListInv menuCommandSWListInv = new SWListInv<>(p, "§eScript Commands", false, menuCommands, (clickType, menuCommand) -> { + playerMap.get(p).removeIf(customCommand -> customCommand == menuCommand); + SWUtils.giveItemToPlayer(p, menuCommand.toItem()); + p.closeInventory(); + save(p); + }); + menuCommandSWListInv.setItem(49, new SWItem(Material.HOPPER, "§eHinzufügen", Arrays.asList("§7Klicke mit einem Buch zum hinzufügen"), false, clickType -> { + ItemStack item = p.getItemOnCursor(); + if (item.getType().isAir()) { + return; + } + if (isNoBook(item) || item.getItemMeta() == null) { + return; + } + + BookMeta bookMeta = ((BookMeta) item.getItemMeta()); + if (bookMeta.getPageCount() == 0) { + return; + } + if (bookMeta.getPage(1).isEmpty()) { + return; + } + String s = bookMeta.getPage(1).split("\n")[0]; + if (!s.startsWith("#!CMD /")) { + return; + } + MenuCommand menuCommand = new MenuCommand(bookMeta.getPages(), s.substring(6).split(" ")); + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(menuCommand); + if (!save(p)) { + playerMap.get(p).removeIf(customCommand -> customCommand == menuCommand); + p.closeInventory(); + save(p); + p.sendMessage("§cScript CMD-Buch Limit erreicht"); + return; + } + p.setItemOnCursor(null); + openCommandsMenu(p); + })); + menuCommandSWListInv.open(); + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java index 69d8af0d..a18b2461 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java @@ -2,6 +2,7 @@ package de.steamwar.bausystem.features.script; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.linkage.LinkedInstance; import de.steamwar.command.SWCommand; import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWListInv; @@ -22,15 +23,19 @@ public class ScriptCommand extends SWCommand { super("script"); } + @LinkedInstance + private CustomCommandListener customCommandListener = null; + private static List> swItems = new ArrayList<>(); @Register(help = true) public void genericHelp(Player p, String... args) { p.sendMessage("§8/§escript §8- §7Öffnet die ScriptGUI"); + p.sendMessage("§8/§escript menu §8- §7Öffnet die ScriptMenuGUI für Custom Command b auübergreifend"); } @Register - public void giveCommand(Player p) { + public void menuCommand(Player p) { if (swItems.isEmpty()) { for (int i = 0; i < 3; i++) { swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", new ArrayList<>(), false, clickType -> { @@ -127,4 +132,8 @@ public class ScriptCommand extends SWCommand { swListInv.open(); } + @Register({"menu"}) + public void menuGUICommand(Player p) { + customCommandListener.openCommandsMenu(p); + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java index 01ffc8e6..939fae0f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java @@ -46,30 +46,56 @@ public final class ScriptExecutor { this.player = player; globalVariables = ScriptListener.getGlobalContext(player); - boolean initial = true; - for (String page : bookMeta.getPages()) { - for (String command : page.split("\n")) { - command = command.replaceAll(" +", " "); - if (command.startsWith("#") || command.trim().isEmpty()) { - if (initial && command.startsWith("#!CMD /")) { - specialCommand = command.substring(7).split(" ")[0]; - } - initial = false; - continue; - } - initial = false; - if (command.startsWith(".")) { - jumpPoints.put(command.substring(1), commands.size()); - continue; - } - commands.add(command); - } - } + parseMeta(bookMeta); if (commands.isEmpty()) return; localVariables.forEach(this.localVariables::putValue); resume(); } + public ScriptExecutor(List pages, Player player, Map localVariables) { + this.player = player; + globalVariables = ScriptListener.getGlobalContext(player); + + parseList(pages); + if (commands.isEmpty()) return; + localVariables.forEach(this.localVariables::putValue); + resume(); + } + + private void parseMeta(BookMeta bookMeta) { + boolean initial = true; + for (String page : bookMeta.getPages()) { + initial = parsePage(page, initial); + } + } + + private void parseList(List pages) { + boolean initial = true; + for (String page : pages) { + initial = parsePage(page, initial); + } + } + + private boolean parsePage(String page, boolean initial) { + for (String command : page.split("\n")) { + command = command.replaceAll(" +", " "); + if (command.startsWith("#") || command.trim().isEmpty()) { + if (initial && command.startsWith("#!CMD /")) { + specialCommand = command.substring(7).split(" ")[0]; + } + initial = false; + continue; + } + initial = false; + if (command.startsWith(".")) { + jumpPoints.put(command.substring(1), commands.size()); + continue; + } + commands.add(command); + } + return initial; + } + public void resume() { if (!player.isOnline()) { return; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java similarity index 92% rename from BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java rename to BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java index 35e2b2ad..c7bed6f3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.bausystem.features.script; +package de.steamwar.bausystem.features.script.items; import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.config.ColorConfig; @@ -31,9 +31,9 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; @Linked(LinkageType.BAU_GUI_ITEM) -public class ScriptBookBauGuiItem extends BauGuiItem { +public class ScriptMenuBauGuiItem extends BauGuiItem { - public ScriptBookBauGuiItem() { + public ScriptMenuBauGuiItem() { super(15); }