From 22df0035c47ac5306310dd22f1fac3072035e82a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 21 Nov 2021 10:55:08 +0100 Subject: [PATCH] Add SchematicSelector Signed-off-by: Chaoscaot --- .../de/steamwar/util/SchematicSelector.java | 438 ++++++++++++++++++ .../util/SchematicSelectorInjectable.java | 39 ++ .../SchematicSelectorInjectableAdapter.java | 47 ++ .../src/de/steamwar/util/UtilGui.java | 53 +++ 4 files changed, 577 insertions(+) create mode 100644 SpigotCore_Main/src/de/steamwar/util/SchematicSelector.java create mode 100644 SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectable.java create mode 100644 SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectableAdapter.java create mode 100644 SpigotCore_Main/src/de/steamwar/util/UtilGui.java diff --git a/SpigotCore_Main/src/de/steamwar/util/SchematicSelector.java b/SpigotCore_Main/src/de/steamwar/util/SchematicSelector.java new file mode 100644 index 0000000..5cd4ef7 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/util/SchematicSelector.java @@ -0,0 +1,438 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.util; + +import com.google.common.collect.Lists; +import de.steamwar.inventory.*; +import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SchematicType; +import de.steamwar.sql.SteamwarUser; +import lombok.*; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public class SchematicSelector { + + @Getter + private final Player player; + @Getter + private final SteamwarUser user; + @Getter + private final Consumer callback; + @Getter + private final SelectorTarget target; + @Getter + private final SelectorFilter filter = new SelectorFilter(); + private SchematicSelectorInjectable injectable; + private boolean useHooks; + @Setter + @Getter + private PublicMode publicMode = PublicMode.ALL; + @Setter + @Getter + private String title = "{0} auswahl: {1}"; + @Setter + @Getter + private boolean singleDirOpen; + + public SchematicSelector(Player player, SelectorTarget target, Consumer callback) { + this.player = player; + this.user = SteamwarUser.get(player.getUniqueId()); + this.target = target; + this.callback = callback; + this.singleDirOpen = !target.target.isDirs(); + } + + public SchematicSelector(Player player, SelectorTarget target, SchematicSelectorInjectable injectable, Consumer callback) { + this(player, target, callback); + this.useHooks = true; + this.injectable = injectable; + } + + public void open() { + if(useHooks) { + injectable.onSelectorCreate(this); + } + openList(null, publicMode == PublicMode.PUBLIC_ONLY); + } + + private void openList(SchematicNode parent, boolean publics) { + List nodes = new ArrayList<>(); + + if(filter.isFilter()) { + nodes.addAll(SchematicNode.getAllSchematicsAccessibleByUser(publics?0:user.getId())); + nodes.removeIf(node -> { + if(useHooks) { + injectable.onNodeFilter(this, node); + } + return !filter.matches(node); + }); + if(target.target == SelectorTarget.Target.DIRECTORY) { + nodes.removeIf(node -> !node.isDir()); + } + if(target.target == SelectorTarget.Target.SCHEMATIC_TYPE) { + nodes.removeIf(node -> node.isDir() || !node.getType().equals(target.type.toDB())); + } + } else { + switch (target.target) { + case DIRECTORY: + if(parent == null) { + nodes.addAll(SchematicNode.getSchematicsAccessibleByUser(publics?0:user.getId(), null)); + nodes.removeIf(node -> !node.isDir()); + } else { + nodes.addAll(SchematicNode.getSchematicDirectoryInNode(parent.getId())); + } + break; + case SCHEMATIC_TYPE: + nodes.addAll(SchematicNode.getAccessibleSchematicsOfTypeInParent(publics?0:user.getId(), target.type.toDB(), parent==null?0:parent.getId())); + if(target.rank >= 0) { + nodes.removeIf(node -> node.getRank() > target.rank); + } + break; + default: + nodes.addAll(SchematicNode.getSchematicsAccessibleByUser(publics?0:user.getId(), parent == null?0:parent.getId())); + } + + if(singleDirOpen && nodes.size() == 1 && nodes.get(0).isDir()) { + openList(nodes.get(0), publics); + return; + } + } + + List> list = new ArrayList<>(); + + if(parent != null) { + list.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, "§eZurück", clickType -> {}), null)); + } + + for (SchematicNode node : nodes) { + if(node.getName().equals("//copy")) continue; + Material m; + if (node.getItem().isEmpty()) + m = node.isDir()?SWItem.getMaterial("CHEST"):SWItem.getMaterial("CAULDRON_ITEM"); + else + m = SWItem.getMaterial(node.getItem()); + + String name = "§" + (filter.getName().isEmpty()?"e":"7") + node.getName(); + + if(!filter.getName().isEmpty()) { + name = name.replace(filter.getName(), "§e" + filter.getName() + "§7"); + } + + SWItem item = new SWItem(m, name, Collections.singletonList(node.isDir() ? "§9Ordner" : "§7" + node.getSchemtype().name()), !node.isDir() && !node.getSchemtype().writeable(), click -> { + }); + if(!node.isDir()) { + if(node.getRank() > 0) + item.setLore(Lists.newArrayList("§7" + node.getSchemtype().name(), "§8Rang " + node.getRank())); + } + list.add(new SWListInv.SWListEntry<>(item, node)); + } + + SWListInv inv = new SWListInv<>(player, MessageFormat.format(title, target.target.getName(), filter.getName().isEmpty()?(parent == null?"/":parent.generateBreadcrumbs(user)):filter.getName()), false, list, (clickType, node) -> { + if(node == null) { + openList(getParent(parent), publics); + return; + } + if(node.isDir()) { + if(filter.isFilter() && target.target.isDirs()) { + player.closeInventory(); + callback.accept(node); + return; + } + filter.reset(); + openList(node, publics); + return; + } + player.closeInventory(); + callback.accept(node); + }); + if(publicMode == PublicMode.ALL) { + if(publics) { + inv.setItem(48, Material.BUCKET, "§7Eigene Schematics", clickType -> openList(null, false)); + } else { + inv.setItem(48, Material.GLASS, "§7Public Schematics", clickType -> openList(null, true)); + } + } + if(target.target.isDirs()) { + inv.setItem(49, SWItem.getDye(10), "§7Ordner auswählen", clickType -> { + player.closeInventory(); + callback.accept(parent); + }); + } + if(!publics) { + inv.setItem(50, Material.CHEST, "§7Neuer Ordner", clickType -> createFolderIn(parent)); + } + inv.setItem(51, Material.NAME_TAG, "§7Filter", clickType -> openFilter(publics)); + + if(useHooks) { + injectable.onListRender(this, inv, parent); + } + inv.open(); + } + + private void createFolderIn(SchematicNode parent) { + SWAnvilInv inv = new SWAnvilInv(player, "Ordner Erstellen"); + inv.setItem(Material.CHEST); + inv.setCallback(s -> { + if(useHooks) { + if(injectable.onFolderCreate(this, s)) { + SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId()); + openList(parent, false); + } + } else { + SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId()); + openList(parent, false); + } + }); + inv.open(); + } + + private void openFilter(boolean publics) { + SWInventory inv = new SWInventory(player, 9, "Filter"); + InvCallback nameCallback = clickType -> { + if(clickType.isRightClick()) { + filter.setName(""); + openFilter(publics); + } else { + SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Name eingeben"); + swAnvilInv.setItem(Material.NAME_TAG); + swAnvilInv.setCallback(s -> { + filter.setName(s); + openFilter(publics); + }); + swAnvilInv.open(); + } + }; + if(filter.getName().isEmpty()) { + inv.setItem(0, Material.NAME_TAG, "§7Nach namen suchen...", nameCallback); + } else { + inv.setItem(0, Material.NAME_TAG, "§7Nach namen suchen...", Collections.singletonList("§7Suchwort: §e" + filter.getName()), true, nameCallback); + } + + InvCallback ownerCallback = clickType -> { + if(clickType.isRightClick()) { + filter.setOwner(null); + openFilter(publics); + } else { + SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Besitzer eingeben"); + swAnvilInv.setItem(Material.PLAYER_HEAD); + swAnvilInv.setCallback(s -> { + filter.setOwner(SteamwarUser.get(s).getId()); + openFilter(publics); + }); + swAnvilInv.open(); + } + }; + if(filter.getOwner() == null) { + inv.setItem(1, Material.PLAYER_HEAD, "§7Nach Besitzer suchen...", ownerCallback); + } else { + SteamwarUser user = SteamwarUser.get(filter.getOwner()); + SWItem item = SWItem.getPlayerSkull(user.getUserName()); + item.setName("§7Nach Besitzer suchen..."); + item.setEnchanted(true); + item.setLore(Collections.singletonList("§7Besitzer: §e" + user.getUserName())); + item.setCallback(ownerCallback); + inv.setItem(1, item); + } + + if(target.target != SelectorTarget.Target.SCHEMATIC_TYPE) { + InvCallback schemTypeCallback = clickType -> { + if(clickType.isRightClick()) { + filter.setType(null); + openFilter(publics); + } else { + List> types = new ArrayList<>(); + SchematicType.values().forEach(schematicType -> { + types.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial("STONE_BUTTON"), "§e" + schematicType.name(), Collections.emptyList(), schematicType.fightType(), n -> {}), schematicType)); + }); + SWListInv listInv = new SWListInv<>(player, "Typ wählen...", types, (clickType1, schematicType) -> { + filter.setType(schematicType); + openFilter(publics); + }); + listInv.open(); + } + }; + + if(filter.getType() == null) { + inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), "§7Nach Typ Filtern...", schemTypeCallback); + } else { + inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), "§7Nach Typ Filtern...", Collections.singletonList("§7Typ: §e" + filter.getType().name()), true, schemTypeCallback); + } + } + + InvCallback materialCallback = clickType -> { + if(clickType.isRightClick()) { + filter.setItem(null); + openFilter(publics); + } else { + UtilGui.openMaterialSelector(player, material -> { + filter.setItem(material); + openFilter(publics); + }); + } + }; + + final int iSlot = target.target== SelectorTarget.Target.SCHEMATIC_TYPE?2:3; + + if(filter.getItem() == null) { + inv.setItem(iSlot, Material.STONE, "§7Nach Item Filtern...", materialCallback); + } else { + inv.setItem(iSlot, filter.getItem(), "§7Nach Item Filtern...", Collections.singletonList("§7Item: §e" + filter.getItem().name()), true, materialCallback); + } + + inv.setItem(7, SWItem.getDye(1), "§eAbbrechen", clickType -> { + filter.reset(); + openList(null, publics); + }); + inv.setItem(8, SWItem.getDye(10), "§eSuchen...", clickType -> { + filter.setFilter(true); + if(useHooks) { + injectable.onFilterApply(this); + } + openList(null, publics); + }); + + if(useHooks) { + injectable.onFilterRender(this, inv); + } + + inv.open(); + } + + private static SchematicNode getParent(SchematicNode node) { + if(node.getParent() == null) { + return null; + } + return node.getParentNode(); + } + + public static SelectorTarget selectSchematic() { + return new SelectorTarget(SelectorTarget.Target.SCHEMATIC, null, -1); + } + + public static SelectorTarget selectDirectory() { + return new SelectorTarget(SelectorTarget.Target.DIRECTORY, null, -1); + } + + public static SelectorTarget selectSchematicNode() { + return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_NODE, null, -1); + } + + public static SelectorTarget selectSchematicType(SchematicType type) { + return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_TYPE, type, -1); + } + + public static SelectorTarget selectSchematicTypeWithRank(SchematicType type, int rank) { + return new SelectorTarget(SelectorTarget.Target.SCHEMATIC_TYPE, type, rank); + } + + private static class SelectorTarget { + + private final Target target; + private final SchematicType type; + private final int rank; + + private SelectorTarget(Target target, SchematicType type, int rank) { + this.target = target; + this.type = type; + this.rank = rank; + } + + @AllArgsConstructor + private enum Target { + SCHEMATIC("Schematic", false), + DIRECTORY("Ordner", true), + SCHEMATIC_NODE("Schematic/Ordner", true), + SCHEMATIC_TYPE("Schematic", false); + + @Getter + private String name; + @Getter + private boolean dirs; + } + } + + @NoArgsConstructor + @Getter + @Setter + public static class SelectorFilter { + + private boolean filter; + + private String name = ""; + private Integer owner = null; + private SchematicType type = null; + private Material item = null; + + public void reset() { + name = ""; + owner = null; + type = null; + item = null; + filter = false; + } + + public boolean matches(SchematicNode node) { + boolean matches = true; + if(!name.isEmpty()) { + if(!node.getName().contains(name)) { + matches = false; + } + } + + if(owner != null) { + if(node.getOwner() != owner) { + matches = false; + } + } + + if(type != null) { + if(node.isDir() || !node.getType().equals(type.toDB())) { + matches = false; + } + } + + if(item != null) { + String i; + if(node.getItem().isEmpty()) { + i = node.isDir()?"CHEST":"CAULDRON"; + } else { + i = node.getItem(); + } + if(!item.name().equals(i)) { + matches = false; + } + } + return matches; + } + } + + public enum PublicMode { + ALL, + PRIVATE_ONLY, + PUBLIC_ONLY + } +} diff --git a/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectable.java b/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectable.java new file mode 100644 index 0000000..35629d0 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectable.java @@ -0,0 +1,39 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.util; + +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.SchematicNode; + +public interface SchematicSelectorInjectable { + + void onSelectorCreate(SchematicSelector selector); + + void onListRender(SchematicSelector selector, SWListInv inv, SchematicNode parent); + + void onFilterRender(SchematicSelector selector, SWInventory inventory); + + void onFilterApply(SchematicSelector selector); + + boolean onFolderCreate(SchematicSelector selector, String name); + + void onNodeFilter(SchematicSelector selector, SchematicNode node); +} diff --git a/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectableAdapter.java b/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectableAdapter.java new file mode 100644 index 0000000..883ac84 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/util/SchematicSelectorInjectableAdapter.java @@ -0,0 +1,47 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.util; + +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.SchematicNode; +import org.bukkit.entity.Player; + +public abstract class SchematicSelectorInjectableAdapter implements SchematicSelectorInjectable { + @Override + public void onSelectorCreate(SchematicSelector selector) {} + + @Override + public void onListRender(SchematicSelector selector, SWListInv inv, SchematicNode parent) {} + + @Override + public void onFilterRender(SchematicSelector selector, SWInventory inventory) {} + + @Override + public void onFilterApply(SchematicSelector selector) {} + + @Override + public boolean onFolderCreate(SchematicSelector selector, String name) { + return true; + } + + @Override + public void onNodeFilter(SchematicSelector selector, SchematicNode node) {} +} diff --git a/SpigotCore_Main/src/de/steamwar/util/UtilGui.java b/SpigotCore_Main/src/de/steamwar/util/UtilGui.java new file mode 100644 index 0000000..cfb9012 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/util/UtilGui.java @@ -0,0 +1,53 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.util; + +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import lombok.experimental.UtilityClass; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +@UtilityClass +public class UtilGui { + + public static void openMaterialSelector(Player player, Consumer callback) { + openMaterialSelector(player, "Material auswählen", callback); + } + + public static void openMaterialSelector(Player player, String title, Consumer callback) { + List> materials = new LinkedList<>(); + for(Material material : Material.values()){ + if(material.name().startsWith(Material.LEGACY_PREFIX)) + continue; + SWItem item = new SWItem(material, "§7" + material.name()); + if(item.getItemMeta() != null && material.isItem()) { + materials.add(new SWListInv.SWListEntry<>(item, material)); + } + } + + SWListInv swListInv = new SWListInv<>(player, title, materials, (clickType3, material) -> callback.accept(material)); + swListInv.open(); + } +}