/* * This file is a part of the SteamWar software. * * Copyright (C) 2025 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.schematicsystem.commands.schematiccommand; import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.core.Core; import de.steamwar.data.CMDs; import de.steamwar.inventory.*; import de.steamwar.schematicsystem.SafeSchematicNode; import de.steamwar.schematicsystem.SchematicSystem; import de.steamwar.schematicsystem.autocheck.AutoChecker; import de.steamwar.sql.*; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static de.steamwar.schematicsystem.commands.schematiccommand.SchematicCommandUtils.getUser; public class GUI { private GUI() { } public static void list(Player player) { SchematicSelector selector = new SchematicSelector(player, SchematicSelector.selectSchematic(), new SchematicSelectorInjectable() { @Override public String createTitle(Player player) { return SchematicSystem.MESSAGE.parse("GUI_TITLE", player); } @Override public void onListRender(SchematicSelector selector, SWListInv inv, SchematicNode parent) { inv.setCallback(-999, (ClickType click) -> { if (parent == null) { player.closeInventory(); } else { selector.reOpenDirUp(); } }); if (parent == null) { inv.setItem(49, Material.AIR, "", clickType -> { }); } else { inv.setItem(49, Material.ANVIL, SchematicSystem.MESSAGE.parse("GUI_FOLDER_PROPERTIES", player), clickType -> { info(selector.getPlayer(), parent, selector); }); } } @Override public AnvilInvCloseAction onAnvilInvCloseAction(SchematicSelector selector) { return AnvilInvCloseAction.REOPEN; } }, node -> { }); selector.setCallback(node -> info(player, node, selector)); selector.setSingleDirOpen(false); selector.open(); } private static void setCloseLeftCallback(SWAnvilInv inv, Runnable action) { AtomicBoolean left = new AtomicBoolean(false); inv.addCloseCallback(() -> { if (!left.get()) { Bukkit.getScheduler().runTaskLater(SchematicSystem.getInstance(), action, 1); } }); inv.addLeftCallback(() -> { left.set(true); action.run(); }); } private static void info(Player player, SchematicNode node, SchematicSelector back) { SteamwarUser user = getUser(player); SWInventory inv = new SWInventory(player, 9 * 2, node.generateBreadcrumbs(user)); if (!node.isDir()) { inv.setItem(0, Material.WOODEN_AXE, SchematicSystem.MESSAGE.parse("GUI_INFO_LOAD", player), Arrays.asList( SchematicSystem.MESSAGE.parse("GUI_LOAD_LATEST", player), SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION", player) ), false, click -> { if (click.isLeftClick()) { player.closeInventory(); SchematicCommandUtils.loadSchem(player, node, -1); } else if (click.isRightClick()) { List> entries = new ArrayList<>(); List datas = NodeData.get(node); for (int i = 0; i < datas.size(); i++) { entries.add(new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(node.getItem()), "§e" + SchematicSystem.MESSAGE.parse("BLANK", player, datas.get(i).getCreatedAt())), i)); } SWListInv listInv = new SWListInv<>(player, SchematicSystem.MESSAGE.parse("GUI_LOAD_REVISION_TITLE", player, node.generateBreadcrumbs(user)), entries, (clickType, revision) -> { if (revision == null) return; player.closeInventory(); SchematicCommandUtils.loadSchem(player, node, revision); }); listInv.setCallback(-999, click2 -> player.closeInventory()); listInv.open(); } }); } inv.setItem(9, new SWItem(Material.LEAD, SchematicSystem.MESSAGE.parse("GUI_INFO_BACK", player), clickType -> { back.reOpen(); }).setCustomModelData(CMDs.Schematic.BACK)); if (node.getOwner() == user.getId()) { if (!node.isDir() && node.getSchemtype().writeable()) { CheckedSchematic.getLastDeclinedOfNode(node.getId()).stream().findFirst().ifPresent(checkedSchematic -> inv.setItem(1, Material.LIME_DYE, (byte) 10, SchematicSystem.MESSAGE.parse("GUI_INFO_STATUS", player, node.getSchemtype().name()), Collections.singletonList(SchematicSystem.MESSAGE.parse("GUI_INFO_STATUS_LORE", player, checkedSchematic.getDeclineReason().replaceAll("&", "§"))), false, click -> { })); } Material mat = SWItem.getMaterial(node.getItem()); inv.setItemEvent(node.isDir() ? 7 : 5, mat, SchematicSystem.MESSAGE.parse("GUI_INFO_MAT", player, mat.name()), Arrays.asList(SchematicSystem.MESSAGE.parse("CHANGE", player), SchematicSystem.MESSAGE.parse("CLICK_DRAG_ITEM", player)), false, event -> { if (event.getCursor() != null && event.getCursor().getType() != Material.AIR) { node.setItem(event.getCursor().getType().name()); info(player, node, back); } else { changeItem(player, node, back); } }); if (!node.isDir()) { inv.setItem(6, SWItem.getMaterial(node.getSchemtype().getMaterial()), SchematicSystem.MESSAGE.parse("GUI_INFO_TYPE", player, node.getSchemtype().name()), Arrays.asList(SchematicSystem.MESSAGE.parse("CHANGE", player), SchematicSystem.MESSAGE.parse("CLICK", player)), node.getSchemtype().fightType(), click -> { changeType(player, node); }); inv.setItem(7, Material.MAGENTA_GLAZED_TERRACOTTA, SchematicSystem.MESSAGE.parse("GUI_INFO_DOWNLOAD", player), click -> { player.closeInventory(); SchematicCommandUtils.download(player, node); }); if (node.getSchemtype().fightType()) { inv.setItem(14, node.replaceColor() ? Material.PINK_WOOL : Material.LIGHT_GRAY_WOOL, SchematicSystem.MESSAGE.parse("GUI_INFO_COLOR", player), Arrays.asList(SchematicSystem.MESSAGE.parse("CURRENT", player, SchematicSystem.MESSAGE.parse(node.replaceColor() ? "ON" : "OFF", player)), SchematicSystem.MESSAGE.parse("CHANGE", player), SchematicSystem.MESSAGE.parse("CLICK", player)), false, clickType -> { node.setReplaceColor(!node.replaceColor()); info(player, node, back); }); inv.setItem(13, node.allowReplay() ? Material.ENDER_EYE : Material.ENDER_PEARL, SchematicSystem.MESSAGE.parse("GUI_INFO_REPLAY", player), Arrays.asList(SchematicSystem.MESSAGE.parse("CURRENT", player, SchematicSystem.MESSAGE.parse(node.allowReplay() ? "ON" : "OFF", player)), SchematicSystem.MESSAGE.parse("GUI_INFO_REPLAY_OFF", player), SchematicSystem.MESSAGE.parse("CLICK", player)), false, clickType -> { if (node.allowReplay()) { SWInventory confInv = new SWInventory(player, 9, SchematicSystem.MESSAGE.parse("GUI_INFO_REPLAY_TITLE", player)); confInv.setItem(0, Material.LIME_DYE, (byte) 10, SchematicSystem.MESSAGE.parse("CONFIRM", player), type -> { node.setAllowReplay(false); info(player, node, back); }); confInv.setItem(8, Material.RED_DYE, (byte) 1, SchematicSystem.MESSAGE.parse("CANCEL", player), type -> { info(player, node, back); }); confInv.open(); } }); } } SWItem skull = SWItem.getPlayerSkull("MHF_STEVE"); skull.setCallback(click -> { player.closeInventory(); delmembers(player, node); }); skull.setName(SchematicSystem.MESSAGE.parse("GUI_INFO_MEMBER", player)); inv.setItem(8, skull); inv.setItem(16, Material.NAME_TAG, SchematicSystem.MESSAGE.parse("GUI_INFO_RENAME", player), clickType -> { SWAnvilInv anvilInv = new SWAnvilInv(player, SchematicSystem.MESSAGE.parse("GUI_INFO_RENAME_TITLE", player, node.getName()), node.getName()); anvilInv.setItem(mat, Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_CLICK_BACK", player)), false); anvilInv.setCallback(s -> { SafeSchematicNode.Result result = SafeSchematicNode.setName(user, node, s); if (result.isSuccessful()) { info(player, SchematicNode.byIdAndUser(user, node.getId()), back); } else { result.sendError(player); } }); setCloseLeftCallback(anvilInv, () -> info(player, node, back)); anvilInv.open(); }); if (node.getOwner() != 0) { inv.setItem(17, Material.RED_DYE, (byte) 1, SchematicSystem.MESSAGE.parse("GUI_INFO_DELETE", player), click -> { delete(player, node, back); }); } } else { if (!node.isDir()) { inv.setItem(4, Material.CAULDRON, SchematicSystem.MESSAGE.parse("GUI_INFO_TYPE", player, node.getSchemtype().name()), Collections.emptyList(), node.getSchemtype().fightType(), click -> { }); } SteamwarUser owneruser = SteamwarUser.byId(node.getOwner()); SWItem skull = SWItem.getPlayerSkull(owneruser.getUserName()); skull.setName(SchematicSystem.MESSAGE.parse("GUI_INFO_MEMBER_FROM", player, owneruser.getUserName())); inv.setItem(8, skull.getItemStack(), clickType -> { }); if (NodeMember.getNodeMember(node.getId(), user.getId()) != null) { inv.setItem(17, Material.RED_DYE, (byte) 1, SchematicSystem.MESSAGE.parse("GUI_INFO_MEMBER_REMOVE", player), click -> { delete(player, node, back); }); } } if (node.getOwner() == user.getId() || NodeMember.getNodeMember(node.getId(), user.getId()) != null) { inv.setItem(15, Material.ARROW, SchematicSystem.MESSAGE.parse("GUI_INFO_MOVE", player), clickType -> { SchematicSelector selector = new SchematicSelector(player, SchematicSelector.selectDirectory(), npar -> { if (npar != null && SchematicNode.parentsOfNode(user, npar.getId()).stream().anyMatch(n -> n.getId() == node.getId())) { SchematicSystem.MESSAGE.send("COMMAND_MOVE_RECURSIVE", player); return; } if (node.getOwner() == user.getId()) { SafeSchematicNode.Result result = SafeSchematicNode.setParent(user, node, npar); if (result.isSuccessful()) { info(player, SchematicNode.getSchematicNode(node.getId()), back); } else { result.sendError(player); } } else { NodeMember.getNodeMember(node.getId(), user.getId()).setParentId(Optional.ofNullable(npar).map(SchematicNode::getId).orElse(null)); } }); selector.open(); }); } inv.setCallback(-999, click -> back.reOpen()); inv.open(); } static void changeType(Player p, SchematicNode schem) { Clipboard clipboard = null; try { clipboard = new SchematicData(schem).load(); } catch (IOException ignored) { } Clipboard finalClipboard = clipboard; List types = SchematicType.values().parallelStream() .filter(SchematicType::isAssignable) .filter(type -> finalClipboard == null || SchematicSystem.getGameModeConfig(type) == null || AutoChecker.impl.sizeCheck(finalClipboard, SchematicSystem.getGameModeConfig(type)).fastOk()) .collect(Collectors.toList()); List> items = types.stream() .map(type -> new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(type.getMaterial()), type.name(), Collections.emptyList(), type.fightType(), null), type)) .collect(Collectors.toList()); items.addAll(SchematicType.values().stream() .filter(SchematicType::isAssignable) .filter(type -> !types.contains(type)) .map(type -> new SWListInv.SWListEntry<>(new SWItem(SWItem.getMaterial(type.getMaterial()), SchematicSystem.MESSAGE.parse("GUI_CHANGE_TYPE_NOT_POSSIBLE_COLOR", p, type.name()), Collections.singletonList(SchematicSystem.MESSAGE.parse("GUI_CHANGE_TYPE_NOT_POSSIBLE", p)), false, null), (SchematicType) null)) .collect(Collectors.toList())); SWListInv inv = new SWListInv<>(p, SchematicSystem.MESSAGE.parse("GUI_CHANGE_TYPE", p), items, (clickType, schematicType) -> { if (schematicType == null) return; p.closeInventory(); SchematicCommandUtils.changeType(p, schem, schematicType, null); }); inv.setCallback(-999, (ClickType click) -> p.closeInventory()); inv.open(); } private static void deleteOwn(Player p, SchematicNode schem, SchematicSelector back) { SteamwarUser user = getUser(p); SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_OWN_TITLE", p, schem.generateBreadcrumbs(user))); inv.setItem(0, Material.RED_DYE, (byte) 1, SchematicSystem.MESSAGE.parse("CONFIRM", p), click -> { p.performCommand("schematic delete " + schem.generateBreadcrumbs(user)); if (back != null) { if (schem.isDir()) { back.reOpenDirUp(); } else { back.reOpen(); } } }); inv.setItem(8, Material.ORANGE_DYE, (byte) 14, SchematicSystem.MESSAGE.parse("CANCEL", p), click -> p.closeInventory()); inv.setCallback(-999, click -> p.closeInventory()); inv.open(); } private static void deleteMembership(Player p, SchematicNode schem, SchematicSelector back) { SteamwarUser user = getUser(p); SWInventory inv = new SWInventory(p, 9, SchematicSystem.MESSAGE.parse("GUI_DELETE_MEMBER_TITLE", p, schem.generateBreadcrumbs(user))); inv.setItem(0, Material.RED_DYE, (byte) 1, SchematicSystem.MESSAGE.parse("CONFIRM", p), click -> { NodeMember member = NodeMember.getNodeMember(schem.getId(), user.getId()); if (member != null) member.delete(); SchematicSystem.MESSAGE.send("GUI_DELETE_MEMBER_DONE", p, schem.generateBreadcrumbs(user)); if (back != null) { if (schem.isDir()) { back.reOpenDirUp(); } else { back.reOpen(); } } }); inv.setItem(8, Material.ORANGE_DYE, (byte) 14, SchematicSystem.MESSAGE.parse("CANCEL", p), click -> p.closeInventory()); inv.setCallback(-999, click -> p.closeInventory()); inv.open(); } static void delete(Player p, SchematicNode schem, SchematicSelector back) { if (SteamwarUser.get(p.getUniqueId()).getId() == schem.getOwner()) { deleteOwn(p, schem, back); } else { deleteMembership(p, schem, back); } } static void delmembers(Player p, SchematicNode schem) { List> members = new LinkedList<>(); for (NodeMember member : schem.getMembers()) { SteamwarUser user = SteamwarUser.byId(member.getMember()); members.add(new SWListInv.SWListEntry<>(SWItem.getPlayerSkull(user.getUserName()), member)); } SWListInv inv = new SWListInv<>(p, SchematicSystem.MESSAGE.parse("GUI_DELETE_MEMBERS_TITLE", p), members, (clickType, member) -> { member.delete(); p.closeInventory(); delmembers(p, schem); }); inv.setCallback(-999, (ClickType click) -> p.closeInventory()); inv.open(); } private static void changeItem(Player p, SchematicNode schem, SchematicSelector back) { UtilGui.openMaterialSelector(p, SchematicSystem.MESSAGE.parse("GUI_CHANGE_ITEM", p), material -> { schem.setItem(material.name()); p.closeInventory(); info(p, schem, back); }); } }