diff --git a/SpigotCore_Main/src/SpigotCore.properties b/SpigotCore_Main/src/SpigotCore.properties
new file mode 100644
index 0000000..e36969f
--- /dev/null
+++ b/SpigotCore_Main/src/SpigotCore.properties
@@ -0,0 +1,55 @@
+#
+# 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 .
+#
+
+SCHEM_SELECTOR_TITLE={0} auswählen: {1}
+SCHEM_SELECTOR_BACK=§eZurück
+SCHEM_SELECTOR_DIR=§9Ordner
+SCHEM_SELECTOR_RANK=§8Rang {0}
+SCHEM_SELECTOR_OWN=§7Eigene Schematics
+SCHEM_SELECTOR_PUB=§7Public Schematics
+SCHEM_SELECTOR_SEL_DIR=§7Ordner auswählen
+SCHEM_SELECTOR_NEW_DIR=§7Neuer Ordner
+SCHEM_SELECTOR_FILTER=§7Filter
+
+SCHEM_SELECTOR_ITEM_NAME=§e{0}
+SCHEM_SELECTOR_ITEM_NAME_FILTER=§7{0}
+SCHEM_SELECTOR_ITEM_REPLACE=§e{0}§7
+SCHEM_SELECTOR_ITEM_LORE_TYPE=§7{0}
+
+SCHEM_SELECTOR_CREATE_DIR_TITLE=Ordner erstellen
+
+SCHEM_SELECTOR_FILTER_TITLE=Filter
+SCHEM_SELECTOR_FILTER_ENTER_NAME=Name eingeben
+SCHEM_SELECTOR_FILTER_NAME=§7Nach Namen suchen...
+SCHEM_SELECTOR_FILTER_NAME_SEARCH=§7Suchbegriff: §e{0}
+SCHEM_SELECTOR_FILTER_ENTER_OWNER=Besitzer eingeben
+SCHEM_SELECTOR_FILTER_OWNER=§7Nach Besitzer suchen...
+SCHEM_SELECTOR_FILTER_OWNER_SEARCH=§7Besitzer: §e{0}
+SCHEM_SELECTOR_FILTER_SEL_TYPE=Typ wählen...
+SCHEM_SELECTOR_FILTER_TYPE=§7Nach Typ filtern...
+SCHEM_SELECTOR_FILTER_TYPE_SEARCH=§7Typ: §e{0}
+SCHEM_SELECTOR_FILTER_MAT=§7Nach Item filtern...
+SCHEM_SELECTOR_FILTER_MAT_SEARCH=§7Item: §e{0}
+SCHEM_SELECTOR_CANCEL=§eAbbrechen
+SCHEM_SELECTOR_GO=§eSuchen...
+SCHEM_SELECTOR_SCHEMATIC=Schematic
+SCHEM_SELECTOR_DIRECTORY=Ordner
+SCHEM_SELECTOR_SCHEMATIC_NODE=Schematic/Ordner
+
+MATERIAL_SELECTOR_TITLE=Material auswählen
\ No newline at end of file
diff --git a/SpigotCore_Main/src/SpigotCore_en.properties b/SpigotCore_Main/src/SpigotCore_en.properties
new file mode 100644
index 0000000..e69de29
diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
index 52e362e..1d7110f 100644
--- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
+++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java
@@ -19,6 +19,7 @@
package de.steamwar.command;
+import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@@ -72,6 +73,17 @@ public class SWCommandUtils {
return null;
}, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "spectator", "3", "a", "adventure", "2")));
MAPPER_FUNCTIONS.put(SteamwarUser.class.getTypeName(), createMapper(SteamwarUser::get, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList())));
+ MAPPER_FUNCTIONS.put(SchematicNode.class.getTypeName(), new TypeMapper() {
+ @Override
+ public List tabCompletes(CommandSender commandSender, String[] strings, String s) {
+ return SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
+ }
+
+ @Override
+ public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) {
+ return SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s);
+ }
+ });
}
private static void addMapper(Class> clazz, Class> alternativeClazz, TypeMapper> mapper) {
diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java
index 4c28502..b0fc18f 100644
--- a/SpigotCore_Main/src/de/steamwar/core/Core.java
+++ b/SpigotCore_Main/src/de/steamwar/core/Core.java
@@ -25,6 +25,7 @@ import de.steamwar.core.events.ChattingEvent;
import de.steamwar.core.events.ChunkListener;
import de.steamwar.core.events.PlayerJoinedEvent;
import de.steamwar.core.events.WorldLoadEvent;
+import de.steamwar.message.Message;
import de.steamwar.sql.SQL;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@@ -39,6 +40,7 @@ public class Core extends JavaPlugin{
private static Core instance;
private static final int version;
+ public static Message MESSAGE;
static{
String packageName = Bukkit.getServer().getClass().getPackage().getName();
@@ -79,6 +81,8 @@ public class Core extends JavaPlugin{
} catch (IOException e) {
throw new SecurityException("Could not load Hostname", e);
}
+
+ MESSAGE = new Message("SpigotCore", getClassLoader());
}
@Override
diff --git a/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java
new file mode 100644
index 0000000..83e8ef8
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java
@@ -0,0 +1,429 @@
+/*
+ * 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.inventory;
+
+import de.steamwar.core.Core;
+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.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class SchematicSelector {
+
+ @Getter
+ private final Player player;
+ @Getter
+ private SteamwarUser user;
+ @Getter
+ private final Consumer callback;
+ private final SelectorTarget target;
+ @Getter
+ private final SelectorFilter filter = new SelectorFilter();
+ private SchematicSelectorInjectable injectable = SchematicSelectorInjectable.DEFAULT;
+ @Setter
+ @Getter
+ private PublicMode publicMode = PublicMode.ALL;
+ @Setter
+ @Getter
+ private boolean singleDirOpen;
+ private boolean sdoTrigger = false;
+
+ 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.dirs;
+ }
+
+ public SchematicSelector(Player player, SelectorTarget target, SchematicSelectorInjectable injectable, Consumer callback) {
+ this(player, target, callback);
+ this.injectable = injectable;
+ }
+
+ public void open() {
+ injectable.onSelectorCreate(this);
+ if(publicMode == PublicMode.PUBLIC_ONLY) {
+ this.user = SteamwarUser.get(0);
+ }
+ openList(null);
+ }
+
+ private void openList(SchematicNode parent) {
+ List nodes = filter.isFilter()?getFilteredSchematics():getSchematicList(parent);
+
+ if(sdoTrigger) {
+ sdoTrigger = false;
+ return;
+ }
+
+ List> list = new ArrayList<>();
+
+ if(parent != null) {
+ list.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, Core.MESSAGE.parse("SCHEM_SELECTOR_BACK", player), clickType -> {}), null));
+ }
+
+ for (SchematicNode node : nodes) {
+ if(node.getName().equals("//copy")) continue;
+ list.add(renderItem(node));
+ }
+
+ SWListInv inv = new SWListInv<>(player, MessageFormat.format(injectable.createTitle(player), target.target.getName(player), filter.getName() == null?(parent == null?"/":parent.generateBreadcrumbs(user)):filter.getName()), false, list, (clickType, node) -> handleClick(node, parent));
+ if(publicMode == PublicMode.ALL) {
+ if(user.getId() == 0) {
+ inv.setItem(48, Material.BUCKET, Core.MESSAGE.parse("SCHEM_SELECTOR_OWN", player), clickType -> {
+ this.user = SteamwarUser.get(player.getUniqueId());
+ openList(null);
+ });
+ } else {
+ inv.setItem(48, Material.GLASS, Core.MESSAGE.parse("SCHEM_SELECTOR_PUB", player), clickType -> {
+ this.user = SteamwarUser.get(0);
+ openList(null);
+ });
+ }
+ }
+ if(target.target.dirs) {
+ inv.setItem(49, SWItem.getDye(10), Core.MESSAGE.parse("SCHEM_SELECTOR_SEL_DIR", player), clickType -> {
+ player.closeInventory();
+ callback.accept(parent);
+ });
+ }
+ if(user.getId() != 0) {
+ inv.setItem(50, Material.CHEST, Core.MESSAGE.parse("SCHEM_SELECTOR_NEW_DIR", player), clickType -> createFolderIn(parent));
+ }
+ inv.setItem(51, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER", player), clickType -> openFilter());
+
+ injectable.onListRender(this, inv, parent);
+ inv.open();
+ }
+
+ private void handleClick(SchematicNode node, SchematicNode parent) {
+ if(node == null) {
+ openList(getParent(parent));
+ return;
+ }
+ if(node.isDir()) {
+ if(filter.isFilter() && target.target.dirs) {
+ player.closeInventory();
+ callback.accept(node);
+ return;
+ }
+ filter.reset();
+ openList(node);
+ return;
+ }
+ player.closeInventory();
+ callback.accept(node);
+ }
+
+ private SWListInv.SWListEntry renderItem(SchematicNode node) {
+ Material m = SWItem.getMaterial(node.getItem());
+
+ String name = Core.MESSAGE.parse(filter.name == null?"SCHEM_SELECTOR_ITEM_NAME":"SCHEM_SELECTOR_ITEM_NAME_FILTER", player, node.getName());
+
+ if(filter.getName() != null) {
+ name = name.replace(filter.getName(), Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_REPLACE", player, filter.getName()));
+ }
+
+ SWItem item = new SWItem(m, name, Collections.singletonList(node.isDir() ? (Core.MESSAGE.parse("SCHEM_SELECTOR_DIR", player)) : Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name())), !node.isDir() && !node.getSchemtype().writeable(), click -> {
+ });
+ if(!node.isDir() && node.getRank() > 0) {
+ item.setLore(Arrays.asList(Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name()), Core.MESSAGE.parse("SCHEM_SELECTOR_RANK", player)));
+ }
+ return new SWListInv.SWListEntry<>(item, node);
+ }
+
+ private void createFolderIn(SchematicNode parent) {
+ SWAnvilInv inv = new SWAnvilInv(player, Core.MESSAGE.parse("SCHEM_SELECTOR_CREATE_DIR_TITLE", player));
+ inv.setItem(Material.CHEST);
+ inv.setCallback(s -> {
+ if(injectable.onFolderCreate(this, s)) {
+ SchematicNode.createSchematicDirectory(user.getId(), s, parent==null?0:parent.getId());
+ openList(parent);
+ }
+ });
+ inv.open();
+ }
+
+ private void openFilter() {
+ SWInventory inv = new SWInventory(player, 9, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TITLE", player));
+ InvCallback nameCallback = clickType -> {
+ if(clickType.isRightClick()) {
+ filter.setName(null);
+ openFilter();
+ } else {
+ SWAnvilInv swAnvilInv = new SWAnvilInv(player, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_ENTER_NAME", player));
+ swAnvilInv.setItem(Material.NAME_TAG);
+ swAnvilInv.setCallback(s -> {
+ filter.setName(s);
+ openFilter();
+ });
+ swAnvilInv.open();
+ }
+ };
+ if(filter.getName() == null) {
+ inv.setItem(0, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME", player), nameCallback);
+ } else {
+ inv.setItem(0, Material.NAME_TAG, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_NAME_SEARCH", player, filter.getName())), true, nameCallback);
+ }
+
+ InvCallback ownerCallback = clickType -> {
+ if(clickType.isRightClick()) {
+ filter.setOwner(null);
+ openFilter();
+ } else {
+ SWAnvilInv swAnvilInv = new SWAnvilInv(player, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_ENTER_OWNER", player));
+ swAnvilInv.setItem(Material.PLAYER_HEAD);
+ swAnvilInv.setCallback(s -> {
+ filter.setOwner(SteamwarUser.get(s).getId());
+ openFilter();
+ });
+ swAnvilInv.open();
+ }
+ };
+ if(filter.getOwner() == null) {
+ inv.setItem(1, Material.PLAYER_HEAD, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER", player), ownerCallback);
+ } else {
+ SteamwarUser tUser = SteamwarUser.get(filter.getOwner());
+ SWItem item = SWItem.getPlayerSkull(user.getUserName());
+ item.setName(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER", player));
+ item.setEnchanted(true);
+ item.setLore(Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_OWNER_SEARCH", player, tUser.getUserName())));
+ item.setCallback(ownerCallback);
+ inv.setItem(1, item);
+ }
+
+ if(target.target != Target.SCHEMATIC_TYPE) {
+ InvCallback schemTypeCallback = clickType -> {
+ if(clickType.isRightClick()) {
+ filter.setType(null);
+ openFilter();
+ } 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, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_SEL_TYPE", player), types, (clickType1, schematicType) -> {
+ filter.setType(schematicType);
+ openFilter();
+ });
+ listInv.open();
+ }
+ };
+
+ if(filter.getType() == null) {
+ inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE", player), schemTypeCallback);
+ } else {
+ inv.setItem(2, SWItem.getMaterial("STONE_BUTTON"), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_TYPE_SEARCH", player, filter.getType().name())), true, schemTypeCallback);
+ }
+ }
+
+ InvCallback materialCallback = clickType -> {
+ if(clickType.isRightClick()) {
+ filter.setItem(null);
+ openFilter();
+ } else {
+ UtilGui.openMaterialSelector(player, material -> {
+ filter.setItem(material);
+ openFilter();
+ });
+ }
+ };
+
+ final int iSlot = target.target == Target.SCHEMATIC_TYPE?2:3;
+
+ if(filter.getItem() == null) {
+ inv.setItem(iSlot, Material.STONE, Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT", player), materialCallback);
+ } else {
+ inv.setItem(iSlot, filter.getItem(), Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT", player), Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_FILTER_MAT_SEARCH", player, filter.getItem().name())), true, materialCallback);
+ }
+
+ inv.setItem(7, SWItem.getDye(1), Core.MESSAGE.parse("SCHEM_SELECTOR_CANCEL", player), clickType -> {
+ filter.reset();
+ openList(null);
+ });
+ inv.setItem(8, SWItem.getDye(10), Core.MESSAGE.parse("SCHEM_SELECTOR_GO", player), clickType -> {
+ filter.setFilter(true);
+ injectable.onFilterApply(this);
+ openList(null);
+ });
+
+ injectable.onFilterRender(this, inv);
+
+ inv.open();
+ }
+
+ private List getFilteredSchematics() {
+ List nodes = new ArrayList<>(SchematicNode.getAllSchematicsAccessibleByUser(user.getId()));
+ nodes.removeIf(node -> {
+ injectable.onNodeFilter(this, node);
+ return !filter.matches(node);
+ });
+ if(target.target == Target.DIRECTORY) {
+ nodes.removeIf(node -> !node.isDir());
+ }
+ if(target.target == Target.SCHEMATIC_TYPE) {
+ nodes.removeIf(node -> node.isDir() || !node.getType().equals(target.type.toDB()));
+ }
+ return nodes;
+ }
+
+ private List getSchematicList(SchematicNode parent) {
+ List nodes = new ArrayList<>();
+ switch (target.target) {
+ case DIRECTORY:
+ if(parent == null) {
+ nodes.addAll(SchematicNode.getSchematicsAccessibleByUser(user.getId(), null));
+ nodes.removeIf(node -> !node.isDir());
+ } else {
+ nodes.addAll(SchematicNode.getSchematicDirectoryInNode(parent.getId()));
+ }
+ break;
+ case SCHEMATIC_TYPE:
+ nodes.addAll(SchematicNode.getAccessibleSchematicsOfTypeInParent(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(user.getId(), parent == null?0:parent.getId()));
+ }
+
+ if(singleDirOpen && nodes.size() == 1 && nodes.get(0).isDir()) {
+ openList(nodes.get(0));
+ sdoTrigger = true;
+ }
+ return nodes;
+ }
+
+ private static SchematicNode getParent(SchematicNode node) {
+ if(node.getParent() == null) {
+ return null;
+ }
+ return node.getParentNode();
+ }
+
+ public static SelectorTarget selectSchematic() {
+ return new SelectorTarget(Target.SCHEMATIC, null, -1);
+ }
+
+ public static SelectorTarget selectDirectory() {
+ return new SelectorTarget(Target.DIRECTORY, null, -1);
+ }
+
+ public static SelectorTarget selectSchematicNode() {
+ return new SelectorTarget(Target.SCHEMATIC_NODE, null, -1);
+ }
+
+ public static SelectorTarget selectSchematicType(SchematicType type) {
+ return new SelectorTarget(Target.SCHEMATIC_TYPE, type, -1);
+ }
+
+ public static SelectorTarget selectSchematicTypeWithRank(SchematicType type, int rank) {
+ return new SelectorTarget(Target.SCHEMATIC_TYPE, type, rank);
+ }
+
+ @AllArgsConstructor
+ static class SelectorTarget {
+
+ private final Target target;
+ private final SchematicType type;
+ private final int rank;
+ }
+
+ @AllArgsConstructor
+ private enum Target {
+ SCHEMATIC("SCHEM_SELECTOR_SCHEMATIC", false),
+ DIRECTORY("SCHEM_SELECTOR_DIRECTORY", true),
+ SCHEMATIC_NODE("SCHEM_SELECTOR_SCHEMATIC_NODE", true),
+ SCHEMATIC_TYPE("SCHEM_SELECTOR_SCHEMATIC", false);
+
+ private String rawName;
+ private boolean dirs;
+
+ private String getName(Player player) {
+ return Core.MESSAGE.parse(rawName, player);
+ }
+ }
+
+ @NoArgsConstructor
+ @Getter
+ @Setter
+ public static class SelectorFilter {
+
+ private boolean filter;
+
+ private String name = null;
+ private Integer owner = null;
+ private SchematicType type = null;
+ private Material item = null;
+
+ public void reset() {
+ name = null;
+ owner = null;
+ type = null;
+ item = null;
+ filter = false;
+ }
+
+ public boolean matches(SchematicNode node) {
+ boolean matches = true;
+ if(name != null && !node.getName().contains(name)) {
+ matches = false;
+ }
+
+ if(owner != null && node.getOwner() != owner) {
+ matches = false;
+ }
+
+ if(type != null && (node.isDir() || !node.getSchemtype().equals(type))) {
+ 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/inventory/SchematicSelectorInjectable.java b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelectorInjectable.java
new file mode 100644
index 0000000..7c4d718
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelectorInjectable.java
@@ -0,0 +1,45 @@
+/*
+ * 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.inventory;
+
+import de.steamwar.core.Core;
+import de.steamwar.sql.SchematicNode;
+import org.bukkit.entity.Player;
+
+public interface SchematicSelectorInjectable {
+
+ SchematicSelectorInjectable DEFAULT = new SchematicSelectorInjectable() {};
+
+ default String createTitle(Player player) {
+ return Core.MESSAGE.parse("SCHEM_SELECTOR_TITLE", player);
+ }
+
+ default void onSelectorCreate(SchematicSelector selector) {}
+
+ default void onListRender(SchematicSelector selector, SWListInv inv, SchematicNode parent) {}
+
+ default void onFilterRender(SchematicSelector selector, SWInventory inventory) {}
+
+ default void onFilterApply(SchematicSelector selector) {}
+
+ default boolean onFolderCreate(SchematicSelector selector, String name) {return true;}
+
+ default void onNodeFilter(SchematicSelector selector, SchematicNode node) {}
+}
diff --git a/SpigotCore_Main/src/de/steamwar/inventory/UtilGui.java b/SpigotCore_Main/src/de/steamwar/inventory/UtilGui.java
new file mode 100644
index 0000000..298d0c0
--- /dev/null
+++ b/SpigotCore_Main/src/de/steamwar/inventory/UtilGui.java
@@ -0,0 +1,54 @@
+/*
+ * 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.inventory;
+
+import de.steamwar.core.Core;
+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, Core.MESSAGE.parse("MATERIAL_SELECTOR_TITLE", player), 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();
+ }
+}
diff --git a/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java
index 009920c..faea608 100644
--- a/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java
+++ b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java
@@ -22,6 +22,7 @@ package de.steamwar.sql;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.core.Core;
import de.steamwar.core.WorldEditWrapper;
+import de.steamwar.inventory.SWItem;
import org.bukkit.entity.Player;
import java.io.ByteArrayInputStream;
@@ -57,7 +58,7 @@ public class SchematicNode {
private static final SQL.Statement getAccessibleByUserByTypeInNode_Null = new SQL.Statement("WITH RECURSIVE RSNB AS (WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSNB WHERE SN.NodeId = RSNB.ParentNode)SELECT * FROM RSNB WHERE ParentNode is null ORDER BY NodeName");
private static final SQL.Statement getAccessibleByUserByType = new SQL.Statement("WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? ORDER BY NodeName");
private static final SQL.Statement getAllSchematicsAccessibleByUser = new SQL.Statement("WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN ORDER BY NodeName");
- private static final SQL.Statement isSchematicAccessibleForUser = new SQL.Statement("WITH RECURSIVE RSN AS (SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.ParentNode, SN.NodeType, SN.NodeItem, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT COUNT(RSN.NodeId) AS `Accessible` FROM RSN LEFT Join NodeMember NM On NM.NodeId = RSN.NodeId WHERE NodeOwner = ? OR UserId = ? LIMIT 1 ORDER BY NodeName");
+ private static final SQL.Statement isSchematicAccessibleForUser = new SQL.Statement("WITH RECURSIVE RSN AS (SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.ParentNode, SN.NodeType, SN.NodeItem, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT COUNT(RSN.NodeId) AS `Accessible` FROM RSN LEFT Join NodeMember NM On NM.NodeId = RSN.NodeId WHERE NodeOwner = ? OR UserId = ? LIMIT 1");
private static final SQL.Statement getAllParentsOfNode = new SQL.Statement("WITH RECURSIVE RSN AS (SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ? UNION SELECT SN.NodeId, SN.NodeName, SN.NodeOwner, SN.ParentNode, SN.NodeType, SN.NodeItem, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN ORDER BY NodeName");
private static final SQL.Statement countNodes = new SQL.Statement("SELECT COUNT(NodeId) AS 'count' FROM SchematicNode");
private static final SQL.Statement updateDB = new SQL.Statement("UPDATE SchematicNode SET NodeName = ?, NodeOwner = ?, ParentNode = ?, NodeItem = ?, NodeType = ?, NodeRank = ? WHERE NodeId = ?");
@@ -80,8 +81,6 @@ public class SchematicNode {
return getSchematicNode(owner, name, parent);
}
- private Timestamp lastUpdate;
-
public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) {
return getSchematicNode(owner, name, parent.getId());
}
@@ -119,9 +118,8 @@ public class SchematicNode {
parent = null;
}
SQL.Statement.ResultSetUser user = rs -> {
- while (rs.next()) {
- SchematicNode node = new SchematicNode(rs);
- return node;
+ if (rs.next()) {
+ return new SchematicNode(rs);
}
return null;
};
@@ -137,8 +135,9 @@ public class SchematicNode {
parent = null;
SQL.Statement.ResultSetUser> user = rs -> {
List nodes = new ArrayList<>();
- while (rs.next())
+ while (rs.next()) {
nodes.add(new SchematicNode(rs));
+ }
return nodes;
};
if(parent == null) {
@@ -266,11 +265,12 @@ public class SchematicNode {
public static List getSchematicsAccessibleByUser(int user, Integer parent) {
if (parent != null && parent != 0) {
- if(isSchematicAccessibleForUser.select(rs -> {
+ if(Boolean.TRUE.equals(isSchematicAccessibleForUser.select(rs -> {
rs.next();
return rs.getInt("Accessible") > 0;
- }, parent, user, user))
+ }, parent, user, user))) {
return getSchematicNodeInNode(parent);
+ }
} else {
return getAccessibleByUser.select(rs -> {
List nodes = new ArrayList<>();
@@ -322,7 +322,7 @@ public class SchematicNode {
if (currentNode == null) {
node = SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0).stream().filter(node1 -> node1.getName().equals(layers[finalI])).findAny();
} else {
- node = SchematicNode.getSchematicNodeInNode(currentNode).stream().filter(node1 -> node1.getName().equals(layers[finalI])).findAny();
+ node = Optional.ofNullable(SchematicNode.getSchematicNode(layers[i], currentNode.getId()));
}
if (!node.isPresent()) {
return null;
@@ -348,6 +348,7 @@ public class SchematicNode {
private String type;
private boolean schemFormat;
private int rank;
+ private Timestamp lastUpdate;
private final boolean isDir;
private Map brCache = new HashMap<>();
@@ -401,6 +402,9 @@ public class SchematicNode {
}
public String getItem() {
+ if (item.isEmpty()) {
+ return isDir ? "CHEST" : "CAULDRON_ITEM";
+ }
return item;
}
@@ -578,4 +582,24 @@ public class SchematicNode {
SchematicNode node = (SchematicNode) obj;
return node.getId() == id;
}
+
+ public static List getNodeTabcomplete(SteamwarUser user, String s) {
+ List list = new ArrayList<>();
+ boolean sws = s.startsWith("/");
+ if (sws) {
+ s = s.substring(1);
+ }
+ if (s.contains("/")) {
+ String preTab = s.substring(0, s.lastIndexOf("/") + 1);
+ SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab);
+ if (pa == null) return Collections.emptyList();
+ List nodes = SchematicNode.getSchematicNodeInNode(pa);
+ nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs(user)));
+ } else {
+ List nodes = SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0);
+ nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : "")));
+ }
+ list.remove("//copy");
+ return list;
+ }
}