From ab2bf7691f73076fefc25c7a8265a3796bf2ddc2 Mon Sep 17 00:00:00 2001 From: DaTTV <104141141+DrFreezyYT@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:13:29 +0100 Subject: [PATCH 1/2] implemented onCommand --- .../papermc/blazesmp/command/ClanCommand.java | 351 ++++++++++++++++-- 1 file changed, 321 insertions(+), 30 deletions(-) diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java index dfb63f4..da9480f 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java @@ -4,6 +4,7 @@ import me.freezy.plugins.papermc.blazesmp.BlazeSMP; import me.freezy.plugins.papermc.blazesmp.command.util.SimpleCommand; import me.freezy.plugins.papermc.blazesmp.module.Clan; import me.freezy.plugins.papermc.blazesmp.module.manager.Clans; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -12,15 +13,20 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.LinkedList; import java.util.stream.Collectors; import java.util.stream.Stream; +import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage; + public class ClanCommand extends SimpleCommand { private final BlazeSMP plugin; private final Clans clans; - private final LinkedHashMap> clanInvites = new LinkedHashMap<>(); + // Mapping: Clan -> Liste der Join-Anfragen (Spieler, die einer bestehenden Clan beitreten möchten) private final LinkedHashMap> clanJoins = new LinkedHashMap<>(); + // Mapping: Clan -> Liste der Einladungen (Spieler, die vom Clan eingeladen wurden) + private final LinkedHashMap> clanInvites = new LinkedHashMap<>(); public ClanCommand() { super("clan"); @@ -29,31 +35,325 @@ public class ClanCommand extends SimpleCommand { } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String list, @NotNull String[] args) { - return false; + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(miniMessage().deserialize("You must be a player to execute this command!")); + return true; + } + UUID playerUUID = player.getUniqueId(); + + if (args.length == 0) { + // Anzeige der Hilfemeldung – abhängig von der Rolle des Spielers + if (clans.isLeader(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan invite\n"); + Component l4 = miniMessage().deserialize(" - /clan kick\n"); + Component l5 = miniMessage().deserialize(" - /clan transfer\n"); + Component l6 = miniMessage().deserialize(" - /clan promote\n"); + Component l7 = miniMessage().deserialize(" - /clan demote\n"); + Component l8 = miniMessage().deserialize(" - /clan disband\n"); + Component l9 = miniMessage().deserialize(" - /clan leave\n"); + Component l10 = miniMessage().deserialize(" - /clan accept\n"); + Component l11 = miniMessage().deserialize(" - /clan deny\n"); + Component l12 = miniMessage().deserialize(" - /clan modify\n"); + Component l13 = miniMessage().deserialize("====================="); + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) + .append(l6).append(l7).append(l8).append(l9).append(l10).append(l11).append(l12).append(l13)); + } else if (clans.isVice(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan invite\n"); + Component l4 = miniMessage().deserialize(" - /clan kick\n"); + Component l5 = miniMessage().deserialize(" - /clan demote\n"); + Component l6 = miniMessage().deserialize(" - /clan leave\n"); + Component l7 = miniMessage().deserialize(" - /clan accept\n"); + Component l8 = miniMessage().deserialize(" - /clan deny\n"); + Component l9 = miniMessage().deserialize("====================="); + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) + .append(l6).append(l7).append(l8).append(l9)); + } else if (clans.isMember(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan leave\n"); + Component l4 = miniMessage().deserialize("====================="); + player.sendMessage(l1.append(l2).append(l3).append(l4)); + } else { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan create\n"); + Component l3 = miniMessage().deserialize(" - /clan join\n"); + Component l4 = miniMessage().deserialize(" - /clan accept\n"); + Component l5 = miniMessage().deserialize(" - /clan deny\n"); + Component l6 = miniMessage().deserialize("====================="); + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5).append(l6)); + } + return true; + } + + // Verarbeitung der Unterbefehle + String subCommand = args[0].toLowerCase(); + switch (subCommand) { + case "create" -> { + if (clans.isInClan(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are already in a clan!")); + return true; + } + if (args.length < 3) { + player.sendMessage(miniMessage().deserialize("Usage: /clan create ")); + return true; + } + String clanName = args[1]; + String clanTag = args[2]; + Component tagComponent = miniMessage().deserialize(clanTag); + Clan newClan = new Clan(clanName, tagComponent, playerUUID); + clans.addClan(newClan); + newClan.save(); + player.sendMessage(miniMessage().deserialize("Clan created successfully!")); + return true; + } + case "join" -> { + if (clans.isInClan(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are already in a clan!")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan join ")); + return true; + } + String targetClanName = args[1]; + Clan targetClan = clans.getClanByName(targetClanName); + if (targetClan == null) { + player.sendMessage(miniMessage().deserialize("Clan not found!")); + return true; + } + // Füge eine Join-Anfrage hinzu + clanJoins.computeIfAbsent(targetClan, k -> new LinkedList<>()); + LinkedList joinRequests = clanJoins.get(targetClan); + if (joinRequests.contains(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You have already requested to join this clan.")); + return true; + } + joinRequests.add(playerUUID); + player.sendMessage(miniMessage().deserialize("Join request sent to clan " + targetClan.getName() + "!")); + // Benachrichtige den Clan-Leader (sofern online) mit klickbaren Nachrichten + Player leader = Bukkit.getPlayer(targetClan.getLeaderUUID()); + if (leader != null && leader.isOnline()) { + String acceptCommand = "/clan accept " + player.getName(); + String denyCommand = "/clan deny " + player.getName(); + Component notifyMsg = miniMessage().deserialize( + "New join request from " + player.getName() + ".\n" + + "[Accept] " + + "[Deny]" + ); + leader.sendMessage(notifyMsg); + } + return true; + } + case "invite" -> { + if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not authorized to invite players to a clan!")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan invite ")); + return true; + } + String inviteeName = args[1]; + Player invitee = Bukkit.getPlayer(inviteeName); + if (invitee == null || !invitee.isOnline()) { + player.sendMessage(miniMessage().deserialize("Player " + inviteeName + " is not online!")); + return true; + } + if (clans.isInClan(invitee.getUniqueId())) { + player.sendMessage(miniMessage().deserialize("" + inviteeName + " is already in a clan!")); + return true; + } + Clan inviterClan = clans.getClanByMember(playerUUID); + if (inviterClan == null) { + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + return true; + } + clanInvites.computeIfAbsent(inviterClan, k -> new LinkedList<>()); + LinkedList inviteList = clanInvites.get(inviterClan); + if (inviteList.contains(invitee.getUniqueId())) { + player.sendMessage(miniMessage().deserialize("Player " + inviteeName + " has already been invited!")); + return true; + } + inviteList.add(invitee.getUniqueId()); + player.sendMessage(miniMessage().deserialize("Invite sent to " + inviteeName + ".")); + // Benachrichtige den eingeladenen Spieler mit klickbaren Nachrichten + String acceptCmd = "/clan accept " + inviterClan.getName(); + String denyCmd = "/clan deny " + inviterClan.getName(); + Component inviteNotify = miniMessage().deserialize( + "Invite from clan " + inviterClan.getName() + ".\n" + + "[Accept] " + + "[Deny]" + ); + invitee.sendMessage(inviteNotify); + return true; + } + case "accept" -> { + // Unterscheidung: Ist der Spieler noch in keinem Clan? -> Einladung annehmen. + if (!clans.isInClan(playerUUID)) { + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); + return true; + } + String clanNameForInvite = args[1]; + Clan invitedClan = null; + for (var entry : clanInvites.entrySet()) { + if (entry.getValue().contains(playerUUID) && + entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { + invitedClan = entry.getKey(); + break; + } + } + if (invitedClan == null) { + player.sendMessage(miniMessage().deserialize("No invite found from clan " + clanNameForInvite + ".")); + return true; + } + invitedClan.getMembers().add(playerUUID); + clanInvites.get(invitedClan).remove(playerUUID); + player.sendMessage(miniMessage().deserialize("You have joined the clan " + invitedClan.getName() + "!")); + Player leader = Bukkit.getPlayer(invitedClan.getLeaderUUID()); + if (leader != null && leader.isOnline()) { + leader.sendMessage(miniMessage().deserialize("" + player.getName() + " has accepted the clan invite.")); + } + invitedClan.save(); + } else { + // Akzeptiere eine Beitrittsanfrage – nur für Leader oder Vice + if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not authorized to accept join requests.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); + return true; + } + String joinRequesterName = args[1]; + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + return true; + } + LinkedList joinReqs = clanJoins.get(currentClan); + if (joinReqs == null || joinReqs.isEmpty()) { + player.sendMessage(miniMessage().deserialize("No join requests available.")); + return true; + } + UUID requesterUUID = null; + for (UUID uuid : joinReqs) { + Player p = Bukkit.getPlayer(uuid); + if (p != null && p.getName().equalsIgnoreCase(joinRequesterName)) { + requesterUUID = uuid; + break; + } + } + if (requesterUUID == null) { + player.sendMessage(miniMessage().deserialize("No join request found from " + joinRequesterName + ".")); + return true; + } + currentClan.getMembers().add(requesterUUID); + joinReqs.remove(requesterUUID); + player.sendMessage(miniMessage().deserialize("You have accepted " + joinRequesterName + "'s join request.")); + Player requester = Bukkit.getPlayer(requesterUUID); + if (requester != null && requester.isOnline()) { + requester.sendMessage(miniMessage().deserialize("Your join request for clan " + currentClan.getName() + " has been accepted.")); + } + currentClan.save(); + } + return true; + } + case "deny" -> { + if (!clans.isInClan(playerUUID)) { + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); + return true; + } + String clanNameForInvite = args[1]; + Clan invitedClan = null; + for (var entry : clanInvites.entrySet()) { + if (entry.getValue().contains(playerUUID) && + entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { + invitedClan = entry.getKey(); + break; + } + } + if (invitedClan == null) { + player.sendMessage(miniMessage().deserialize("No invite found from clan " + clanNameForInvite + ".")); + return true; + } + clanInvites.get(invitedClan).remove(playerUUID); + player.sendMessage(miniMessage().deserialize("You have declined the clan invite from " + invitedClan.getName() + ".")); + Player leader = Bukkit.getPlayer(invitedClan.getLeaderUUID()); + if (leader != null && leader.isOnline()) { + leader.sendMessage(miniMessage().deserialize("" + player.getName() + " has declined the clan invite.")); + } + } else { + if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not authorized to deny join requests.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); + return true; + } + String joinRequesterName = args[1]; + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + return true; + } + LinkedList joinReqs = clanJoins.get(currentClan); + if (joinReqs == null || joinReqs.isEmpty()) { + player.sendMessage(miniMessage().deserialize("No join requests available.")); + return true; + } + UUID requesterUUID = null; + for (UUID uuid : joinReqs) { + Player p = Bukkit.getPlayer(uuid); + if (p != null && p.getName().equalsIgnoreCase(joinRequesterName)) { + requesterUUID = uuid; + break; + } + } + if (requesterUUID == null) { + player.sendMessage(miniMessage().deserialize("No join request found from " + joinRequesterName + ".")); + return true; + } + joinReqs.remove(requesterUUID); + player.sendMessage(miniMessage().deserialize("You have denied " + joinRequesterName + "'s join request.")); + Player requester = Bukkit.getPlayer(requesterUUID); + if (requester != null && requester.isOnline()) { + requester.sendMessage(miniMessage().deserialize("Your join request for clan " + currentClan.getName() + " has been denied.")); + } + } + return true; + } + default -> { + player.sendMessage(miniMessage().deserialize("Unknown subcommand. Use /clan for help.")); + return true; + } + } } @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String list, @NotNull String[] args) { + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { Player player = (Player) sender; UUID playerUUID = player.getUniqueId(); if (args.length == 1) { if (clans.isLeader(playerUUID)) { return Stream.of("info", "invite", "kick", "transfer", "promote", "demote", "disband", "leave", "accept", "deny", "modify") - .filter(s -> s.startsWith(args[0])) - .toList(); + .filter(s -> s.startsWith(args[0])).toList(); } else if (clans.isVice(playerUUID)) { return Stream.of("info", "invite", "kick", "demote", "leave", "accept", "deny") - .filter(s -> s.startsWith(args[0])) - .toList(); + .filter(s -> s.startsWith(args[0])).toList(); } else if (clans.isMember(playerUUID)) { - return Stream.of("info","leave") - .filter(s -> s.startsWith(args[0])) - .toList(); + return Stream.of("info", "leave") + .filter(s -> s.startsWith(args[0])).toList(); } else { return Stream.of("create", "join", "accept", "deny") - .filter(s -> s.startsWith(args[0])) - .toList(); + .filter(s -> s.startsWith(args[0])).toList(); } } else if (args.length == 2) { if (clans.isLeader(playerUUID)) { @@ -61,18 +361,15 @@ public class ClanCommand extends SimpleCommand { return Bukkit.getOnlinePlayers().stream() .filter(p -> !clans.isMember(p.getUniqueId())) .map(Player::getName) - .filter(name -> name.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(name -> name.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("kick")) { return clans.getClanByMember(playerUUID).getMembers().stream() .map(UUID::toString) - .filter(s -> s.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("promote")) { return clans.getClanByMember(playerUUID).getMembers().stream() .map(UUID::toString) - .filter(s -> s.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("demote")) { return Collections.singletonList(plugin.getServer().getOfflinePlayer(clans.getClanByMember(playerUUID).getViceUUID()).getName()); } else if (args[0].equalsIgnoreCase("accept")) { @@ -82,22 +379,18 @@ public class ClanCommand extends SimpleCommand { List joins = getClanJoinRequests(args, playerUUID); if (joins != null) return joins; } else if (args[0].equalsIgnoreCase("modify")) { - return Stream.of("name", "tag") - .filter(s -> s.startsWith(args[1])) - .toList(); + return Stream.of("name", "tag").filter(s -> s.startsWith(args[1])).toList(); } } else if (clans.isVice(playerUUID)) { if (args[0].equalsIgnoreCase("invite")) { return Bukkit.getOnlinePlayers().stream() .filter(p -> !clans.isMember(p.getUniqueId())) .map(Player::getName) - .filter(name -> name.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(name -> name.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("kick")) { return clans.getClanByMember(playerUUID).getMembers().stream() .map(UUID::toString) - .filter(s -> s.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("accept")) { List joins = getClanJoinRequests(args, playerUUID); if (joins != null) return joins; @@ -121,8 +414,7 @@ public class ClanCommand extends SimpleCommand { } else if (args[0].equalsIgnoreCase("join")) { return clans.getClans().stream() .map(Clan::getName) - .filter(s -> s.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); } else if (args[0].equalsIgnoreCase("create")) { return Collections.singletonList(""); } @@ -150,8 +442,7 @@ public class ClanCommand extends SimpleCommand { return joins.stream() .map(uuid -> plugin.getServer().getOfflinePlayer(uuid).getName()) .filter(Objects::nonNull) - .filter(s -> s.startsWith(args[1])) - .collect(Collectors.toList()); + .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); } return null; } From a5e3bab8f9aa9e5eadf651a147c1b5ff33fb599b Mon Sep 17 00:00:00 2001 From: DaTTV <104141141+DrFreezyYT@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:39:25 +0100 Subject: [PATCH 2/2] implemented missing functions in the clan command --- .../8.8/executionHistory/executionHistory.bin | Bin 40650 -> 70839 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .gradle/8.8/fileHashes/fileHashes.bin | Bin 19397 -> 21347 bytes .gradle/8.8/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../8.8/fileHashes/resourceHashesCache.bin | Bin 18531 -> 18837 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .gradle/buildOutputCleanup/outputFiles.bin | Bin 18929 -> 19361 bytes .gradle/file-system.probe | Bin 8 -> 8 bytes .idea/inspectionProfiles/Project_Default.xml | 10 + .idea/modules.xml | 2 +- ...e.freezy.plugins.papermc.BlazeSMP.main.iml | 14 + .../papermc/blazesmp/command/ClanCommand.java | 926 ++++++++++++++---- 12 files changed, 748 insertions(+), 204 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules/me.freezy.plugins.papermc.BlazeSMP.main.iml diff --git a/.gradle/8.8/executionHistory/executionHistory.bin b/.gradle/8.8/executionHistory/executionHistory.bin index 98058b6eafc02ba8ae678ac3931a8c432de0f877..115517d42d3f991fc7324f555fd70a350202ff42 100644 GIT binary patch literal 70839 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 Y=E(~e%TBJIueLdQzA@WoR{x{^07@%FkN^Mx diff --git a/.gradle/8.8/executionHistory/executionHistory.lock b/.gradle/8.8/executionHistory/executionHistory.lock index 9a696ad7310705e792b3682059ea149513660ca3..269f36e9202a3193e4b827873b6202dce1e0781d 100644 GIT binary patch literal 17 TcmZRMuvi3h(Q0Rj{NDO&?{ literal 17 TcmZRMuvi3h(Q0RlJxDMJHX diff --git a/.gradle/8.8/fileHashes/fileHashes.bin b/.gradle/8.8/fileHashes/fileHashes.bin index 5ab0aa597623892c0e9349dd5043cf69bc5a3552..a06385362be5cab2375fad372fbedeb877ae8f5f 100644 GIT binary patch literal 21347 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 delta 91 zcmaF7jPdAn#tkMCf&R9 r29tSZJSOMLNKAezV=!4)R$_9gtP&IB!HtSP#5Wp5h;4TCXki8bak?G4 diff --git a/.gradle/8.8/fileHashes/fileHashes.lock b/.gradle/8.8/fileHashes/fileHashes.lock index 2732f422f130a76f69a97272aa49464c7cfb73ef..9c366dc77b522f2db74bf0597aec40251121c3a0 100644 GIT binary patch literal 17 UcmZSn-gw=MG5cH=0|c}I05`Y<#{d8T literal 17 UcmZSn-gw=MG5cH=0|ZC{05?knS^xk5 diff --git a/.gradle/8.8/fileHashes/resourceHashesCache.bin b/.gradle/8.8/fileHashes/resourceHashesCache.bin index baf3a03bcaba923310d4226ebedb92f5ebf6ea85..a0c134a045b6868b84b975f294f2a06e7d91f9f6 100644 GIT binary patch literal 18837 zcmeI%+e;Kt0LSqeCCgjh2(%4_0s}8>u1Fh5;SCjGV}%|fNYWnj!DPKHi(t4BtqTPq zDe8lQNDnDq2-|i+Q(L8r5Ly-q2D!MtD2R!b?Xu?}F@J&aJ#c0Yzxi=y&gXTC6(u?T zKn&$@oH|^xLI42-5I_I{1Q0*~0R#|0009ILKmY**5I_Kd|3%g1s8FR zigF<)7`q}a8tVMvMWM&#_45D0*ZV(yZ?2tb3gu-rGT+L%u5%2{wTQf3=0BaDybtE> zII)jj<}o`xQN>oBczu~)=0;!JX;+DDK@`8TOn&ZD|KiRBp zJZl~9s9qiPzPO|&*oQaF+Q#;Y-MysxV_oY-4O5oSf3mcVmAjb*&+T;^`%3DA$KAPa zv<;IQeQ#`FzdGOW{>v}7`<=G2^nIc;I{UoOwl-cB-ch=%ZG=@+MqYWf_vA*(%e1j& Zheg|PWzSCPo!)cC*0x^H>%!4s<1eD;>MH;M delta 43 ucmbO_nep)i#tkMCjEs}-N=WehhXMu$2F;C%Kg2g0ycC~kz&_d0LkR%3XcI92 diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 1678000007404e7dbb401597bd21df06800f921e..b81338f641a904f55d9ca91d8946584b4144581a 100644 GIT binary patch literal 17 UcmZSHAGermD)W;~3=rT705PrvK>z>% literal 17 UcmZSHAGermD)W;~3=kj<05OCF7XSbN diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin index 08bbe90a94010077976fc7bc44acf404cf588aa3..055d6f5e474d10bce8d13ca6d6b86439b93d6f1f 100644 GIT binary patch delta 606 zcmex3nQ`HC#tkMCng;EGqEn6}D~B?Gfk)?mC}>~$BYxp6r6mw?uh_}15*7lJbY-sG z+-Io;5%gA`Tq>cUF(duV|GDq`T%anK!c3UQd-A9PTWTCs+QW9d*qOPFH670G(*?bx3| z#V1eZl~NE$bgWL>Z@w@ID!6^Js+2`U(P@tL`@VdahYB{rOehxFT{~~*tQ1!QA;?-$qU0191=t9N+PY#vRVq%%NQSpcPMuQIF&5j-$7$@)d;GO)z PBWiMjhsWj*9*m3t*IfaO delta 91 zcmZ2Do$=#j#tkMCf)ee4qEn6}D~B?Gfk)@$SP6^CYb7Kmf0am>oGWQKd7Gs8WL+tV s$-O{)RVra}s + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 526e09f..26a7d9b 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/modules/me.freezy.plugins.papermc.BlazeSMP.main.iml b/.idea/modules/me.freezy.plugins.papermc.BlazeSMP.main.iml new file mode 100644 index 0000000..bbeeb3e --- /dev/null +++ b/.idea/modules/me.freezy.plugins.papermc.BlazeSMP.main.iml @@ -0,0 +1,14 @@ + + + + + + + PAPER + ADVENTURE + + 1 + + + + \ No newline at end of file diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java index da9480f..bcde620 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClanCommand.java @@ -6,6 +6,7 @@ import me.freezy.plugins.papermc.blazesmp.module.Clan; import me.freezy.plugins.papermc.blazesmp.module.manager.Clans; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -13,14 +14,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.LinkedList; import java.util.stream.Collectors; import java.util.stream.Stream; import static net.kyori.adventure.text.minimessage.MiniMessage.miniMessage; public class ClanCommand extends SimpleCommand { - private final BlazeSMP plugin; private final Clans clans; // Mapping: Clan -> Liste der Join-Anfragen (Spieler, die einer bestehenden Clan beitreten möchten) @@ -30,420 +29,941 @@ public class ClanCommand extends SimpleCommand { public ClanCommand() { super("clan"); - plugin = BlazeSMP.getInstance(); + BlazeSMP plugin = BlazeSMP.getInstance(); clans = plugin.getClans(); } @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { + public boolean onCommand(@NotNull CommandSender sender, + @NotNull Command cmd, + @NotNull String label, + @NotNull String[] args) { if (!(sender instanceof Player player)) { - sender.sendMessage(miniMessage().deserialize("You must be a player to execute this command!")); + sender.sendMessage(miniMessage().deserialize("You must be a player to execute this command!")); return true; } UUID playerUUID = player.getUniqueId(); + // Keine Subcommands -> zeige Hilfe if (args.length == 0) { - // Anzeige der Hilfemeldung – abhängig von der Rolle des Spielers - if (clans.isLeader(playerUUID)) { - Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); - Component l2 = miniMessage().deserialize(" - /clan info\n"); - Component l3 = miniMessage().deserialize(" - /clan invite\n"); - Component l4 = miniMessage().deserialize(" - /clan kick\n"); - Component l5 = miniMessage().deserialize(" - /clan transfer\n"); - Component l6 = miniMessage().deserialize(" - /clan promote\n"); - Component l7 = miniMessage().deserialize(" - /clan demote\n"); - Component l8 = miniMessage().deserialize(" - /clan disband\n"); - Component l9 = miniMessage().deserialize(" - /clan leave\n"); - Component l10 = miniMessage().deserialize(" - /clan accept\n"); - Component l11 = miniMessage().deserialize(" - /clan deny\n"); - Component l12 = miniMessage().deserialize(" - /clan modify\n"); - Component l13 = miniMessage().deserialize("====================="); - player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) - .append(l6).append(l7).append(l8).append(l9).append(l10).append(l11).append(l12).append(l13)); - } else if (clans.isVice(playerUUID)) { - Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); - Component l2 = miniMessage().deserialize(" - /clan info\n"); - Component l3 = miniMessage().deserialize(" - /clan invite\n"); - Component l4 = miniMessage().deserialize(" - /clan kick\n"); - Component l5 = miniMessage().deserialize(" - /clan demote\n"); - Component l6 = miniMessage().deserialize(" - /clan leave\n"); - Component l7 = miniMessage().deserialize(" - /clan accept\n"); - Component l8 = miniMessage().deserialize(" - /clan deny\n"); - Component l9 = miniMessage().deserialize("====================="); - player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) - .append(l6).append(l7).append(l8).append(l9)); - } else if (clans.isMember(playerUUID)) { - Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); - Component l2 = miniMessage().deserialize(" - /clan info\n"); - Component l3 = miniMessage().deserialize(" - /clan leave\n"); - Component l4 = miniMessage().deserialize("====================="); - player.sendMessage(l1.append(l2).append(l3).append(l4)); - } else { - Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); - Component l2 = miniMessage().deserialize(" - /clan create\n"); - Component l3 = miniMessage().deserialize(" - /clan join\n"); - Component l4 = miniMessage().deserialize(" - /clan accept\n"); - Component l5 = miniMessage().deserialize(" - /clan deny\n"); - Component l6 = miniMessage().deserialize("====================="); - player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5).append(l6)); - } + sendHelpMessage(player, playerUUID); return true; } // Verarbeitung der Unterbefehle String subCommand = args[0].toLowerCase(); switch (subCommand) { + + // ========== CREATE ========== case "create" -> { if (clans.isInClan(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You are already in a clan!")); + player.sendMessage(miniMessage().deserialize("You are already in a clan!")); return true; } if (args.length < 3) { - player.sendMessage(miniMessage().deserialize("Usage: /clan create ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan create ")); return true; } String clanName = args[1]; String clanTag = args[2]; Component tagComponent = miniMessage().deserialize(clanTag); + Clan newClan = new Clan(clanName, tagComponent, playerUUID); + // Clan hinzufügen und speichern clans.addClan(newClan); newClan.save(); - player.sendMessage(miniMessage().deserialize("Clan created successfully!")); + + player.sendMessage(miniMessage().deserialize("Clan created successfully!")); return true; } + + // ========== JOIN ========== case "join" -> { if (clans.isInClan(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You are already in a clan!")); + player.sendMessage(miniMessage().deserialize("You are already in a clan!")); return true; } if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan join ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan join ")); return true; } String targetClanName = args[1]; Clan targetClan = clans.getClanByName(targetClanName); if (targetClan == null) { - player.sendMessage(miniMessage().deserialize("Clan not found!")); + player.sendMessage(miniMessage().deserialize("Clan not found!")); return true; } - // Füge eine Join-Anfrage hinzu + clanJoins.computeIfAbsent(targetClan, k -> new LinkedList<>()); LinkedList joinRequests = clanJoins.get(targetClan); + if (joinRequests.contains(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You have already requested to join this clan.")); + player.sendMessage(miniMessage().deserialize("You have already requested to join this clan.")); return true; } joinRequests.add(playerUUID); - player.sendMessage(miniMessage().deserialize("Join request sent to clan " + targetClan.getName() + "!")); - // Benachrichtige den Clan-Leader (sofern online) mit klickbaren Nachrichten + player.sendMessage(miniMessage().deserialize( + String.format("Join request sent to clan %s!", targetClan.getName()))); + + // Benachrichtige den Clan-Leader (sofern online) Player leader = Bukkit.getPlayer(targetClan.getLeaderUUID()); if (leader != null && leader.isOnline()) { String acceptCommand = "/clan accept " + player.getName(); String denyCommand = "/clan deny " + player.getName(); Component notifyMsg = miniMessage().deserialize( - "New join request from " + player.getName() + ".\n" + - "[Accept] " + - "[Deny]" + String.format("New join request from %s.\n", player.getName()) + + String.format("[Accept] ", acceptCommand) + + String.format("[Deny]", denyCommand) ); leader.sendMessage(notifyMsg); } return true; } + + // ========== INVITE ========== case "invite" -> { if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You are not authorized to invite players to a clan!")); + player.sendMessage(miniMessage().deserialize("You are not authorized to invite players to a clan!")); return true; } if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan invite ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan invite ")); return true; } String inviteeName = args[1]; Player invitee = Bukkit.getPlayer(inviteeName); if (invitee == null || !invitee.isOnline()) { - player.sendMessage(miniMessage().deserialize("Player " + inviteeName + " is not online!")); + player.sendMessage(miniMessage().deserialize(String.format("Player %s is not online!", inviteeName))); return true; } if (clans.isInClan(invitee.getUniqueId())) { - player.sendMessage(miniMessage().deserialize("" + inviteeName + " is already in a clan!")); + player.sendMessage(miniMessage().deserialize(String.format("%s is already in a clan!", inviteeName))); return true; } Clan inviterClan = clans.getClanByMember(playerUUID); if (inviterClan == null) { - player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); return true; } clanInvites.computeIfAbsent(inviterClan, k -> new LinkedList<>()); LinkedList inviteList = clanInvites.get(inviterClan); + if (inviteList.contains(invitee.getUniqueId())) { - player.sendMessage(miniMessage().deserialize("Player " + inviteeName + " has already been invited!")); + player.sendMessage(miniMessage().deserialize(String.format("Player %s has already been invited!", inviteeName))); return true; } inviteList.add(invitee.getUniqueId()); - player.sendMessage(miniMessage().deserialize("Invite sent to " + inviteeName + ".")); - // Benachrichtige den eingeladenen Spieler mit klickbaren Nachrichten + player.sendMessage(miniMessage().deserialize(String.format("Invite sent to %s.", inviteeName))); + + // Benachrichtige den Eingeladenen String acceptCmd = "/clan accept " + inviterClan.getName(); String denyCmd = "/clan deny " + inviterClan.getName(); Component inviteNotify = miniMessage().deserialize( - "Invite from clan " + inviterClan.getName() + ".\n" + - "[Accept] " + - "[Deny]" + String.format("Invite from clan %s.\n", inviterClan.getName()) + + String.format("[Accept] ", acceptCmd) + + String.format("[Deny]", denyCmd) ); invitee.sendMessage(inviteNotify); return true; } + + // ========== ACCEPT ========== case "accept" -> { - // Unterscheidung: Ist der Spieler noch in keinem Clan? -> Einladung annehmen. + // 1) Spieler ist noch in keinem Clan -> Einladung annehmen if (!clans.isInClan(playerUUID)) { if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); return true; } String clanNameForInvite = args[1]; Clan invitedClan = null; - for (var entry : clanInvites.entrySet()) { - if (entry.getValue().contains(playerUUID) && - entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { + for (Map.Entry> entry : clanInvites.entrySet()) { + if (entry.getValue().contains(playerUUID) + && entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { invitedClan = entry.getKey(); break; } } if (invitedClan == null) { - player.sendMessage(miniMessage().deserialize("No invite found from clan " + clanNameForInvite + ".")); + player.sendMessage(miniMessage().deserialize(String.format("No invite found from clan %s.", clanNameForInvite))); return true; } invitedClan.getMembers().add(playerUUID); clanInvites.get(invitedClan).remove(playerUUID); - player.sendMessage(miniMessage().deserialize("You have joined the clan " + invitedClan.getName() + "!")); + + player.sendMessage(miniMessage().deserialize( + String.format("You have joined the clan %s!", invitedClan.getName()))); + Player leader = Bukkit.getPlayer(invitedClan.getLeaderUUID()); if (leader != null && leader.isOnline()) { - leader.sendMessage(miniMessage().deserialize("" + player.getName() + " has accepted the clan invite.")); + leader.sendMessage(miniMessage().deserialize( + String.format("%s has accepted the clan invite.", player.getName()))); } invitedClan.save(); } else { - // Akzeptiere eine Beitrittsanfrage – nur für Leader oder Vice + // 2) Spieler ist bereits in einem Clan -> Beitrittsanfrage annehmen (Leader/Vice) if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You are not authorized to accept join requests.")); + player.sendMessage(miniMessage().deserialize("You are not authorized to accept join requests.")); return true; } if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan accept ")); return true; } String joinRequesterName = args[1]; Clan currentClan = clans.getClanByMember(playerUUID); if (currentClan == null) { - player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); return true; } LinkedList joinReqs = clanJoins.get(currentClan); if (joinReqs == null || joinReqs.isEmpty()) { - player.sendMessage(miniMessage().deserialize("No join requests available.")); + player.sendMessage(miniMessage().deserialize("No join requests available.")); return true; } - UUID requesterUUID = null; - for (UUID uuid : joinReqs) { - Player p = Bukkit.getPlayer(uuid); - if (p != null && p.getName().equalsIgnoreCase(joinRequesterName)) { - requesterUUID = uuid; - break; - } - } + UUID requesterUUID = getUuidByName(joinReqs, joinRequesterName); if (requesterUUID == null) { - player.sendMessage(miniMessage().deserialize("No join request found from " + joinRequesterName + ".")); + player.sendMessage(miniMessage().deserialize(String.format("No join request found from %s.", joinRequesterName))); return true; } currentClan.getMembers().add(requesterUUID); joinReqs.remove(requesterUUID); - player.sendMessage(miniMessage().deserialize("You have accepted " + joinRequesterName + "'s join request.")); + + player.sendMessage(miniMessage().deserialize( + String.format("You have accepted %s's join request.", joinRequesterName))); + Player requester = Bukkit.getPlayer(requesterUUID); if (requester != null && requester.isOnline()) { - requester.sendMessage(miniMessage().deserialize("Your join request for clan " + currentClan.getName() + " has been accepted.")); + requester.sendMessage(miniMessage().deserialize( + String.format("Your join request for clan %s has been accepted.", currentClan.getName()))); } currentClan.save(); } return true; } + + // ========== DENY ========== case "deny" -> { + // 1) Spieler ist noch in keinem Clan -> Einladung ablehnen if (!clans.isInClan(playerUUID)) { if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); return true; } String clanNameForInvite = args[1]; Clan invitedClan = null; - for (var entry : clanInvites.entrySet()) { - if (entry.getValue().contains(playerUUID) && - entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { + for (Map.Entry> entry : clanInvites.entrySet()) { + if (entry.getValue().contains(playerUUID) + && entry.getKey().getName().equalsIgnoreCase(clanNameForInvite)) { invitedClan = entry.getKey(); break; } } if (invitedClan == null) { - player.sendMessage(miniMessage().deserialize("No invite found from clan " + clanNameForInvite + ".")); + player.sendMessage(miniMessage().deserialize(String.format("No invite found from clan %s.", clanNameForInvite))); return true; } clanInvites.get(invitedClan).remove(playerUUID); - player.sendMessage(miniMessage().deserialize("You have declined the clan invite from " + invitedClan.getName() + ".")); + player.sendMessage(miniMessage().deserialize( + String.format("You have declined the clan invite from %s.", invitedClan.getName()))); + Player leader = Bukkit.getPlayer(invitedClan.getLeaderUUID()); if (leader != null && leader.isOnline()) { - leader.sendMessage(miniMessage().deserialize("" + player.getName() + " has declined the clan invite.")); + leader.sendMessage(miniMessage().deserialize( + String.format("%s has declined the clan invite.", player.getName()))); } } else { + // 2) Spieler ist in einem Clan -> Beitrittsanfrage ablehnen (Leader/Vice) if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { - player.sendMessage(miniMessage().deserialize("You are not authorized to deny join requests.")); + player.sendMessage(miniMessage().deserialize("You are not authorized to deny join requests.")); return true; } if (args.length < 2) { - player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); + player.sendMessage(miniMessage().deserialize("Usage: /clan deny ")); return true; } String joinRequesterName = args[1]; Clan currentClan = clans.getClanByMember(playerUUID); if (currentClan == null) { - player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); + player.sendMessage(miniMessage().deserialize("Error: Your clan could not be found.")); return true; } LinkedList joinReqs = clanJoins.get(currentClan); if (joinReqs == null || joinReqs.isEmpty()) { - player.sendMessage(miniMessage().deserialize("No join requests available.")); + player.sendMessage(miniMessage().deserialize("No join requests available.")); return true; } - UUID requesterUUID = null; - for (UUID uuid : joinReqs) { - Player p = Bukkit.getPlayer(uuid); - if (p != null && p.getName().equalsIgnoreCase(joinRequesterName)) { - requesterUUID = uuid; - break; - } - } + UUID requesterUUID = getUuidByName(joinReqs, joinRequesterName); if (requesterUUID == null) { - player.sendMessage(miniMessage().deserialize("No join request found from " + joinRequesterName + ".")); + player.sendMessage(miniMessage().deserialize(String.format("No join request found from %s.", joinRequesterName))); return true; } joinReqs.remove(requesterUUID); - player.sendMessage(miniMessage().deserialize("You have denied " + joinRequesterName + "'s join request.")); + + player.sendMessage(miniMessage().deserialize( + String.format("You have denied %s's join request.", joinRequesterName))); + Player requester = Bukkit.getPlayer(requesterUUID); if (requester != null && requester.isOnline()) { - requester.sendMessage(miniMessage().deserialize("Your join request for clan " + currentClan.getName() + " has been denied.")); + requester.sendMessage(miniMessage().deserialize( + String.format("Your join request for clan %s has been denied.", currentClan.getName()))); } } return true; } + + // ========== LIST ========== + case "list" -> { + // Zeige eine Liste aller existierenden Clans an + sendClanList(player); + return true; + } + + // ========== INFO ========== + case "info" -> { + if (!clans.isInClan(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not in a clan!")); + return true; + } + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + + // Sammle die Daten + UUID leaderUUID = clan.getLeaderUUID(); + UUID viceUUID = clan.getViceUUID(); + List members = clan.getMembers(); + + OfflinePlayer leaderOffline = Bukkit.getOfflinePlayer(leaderUUID); + String leaderName = leaderOffline.getName() != null ? leaderOffline.getName() : leaderUUID.toString(); + + String viceName = ""; + if (viceUUID != null) { + OfflinePlayer viceOffline = Bukkit.getOfflinePlayer(viceUUID); + viceName = (viceOffline.getName() != null) ? viceOffline.getName() : viceUUID.toString(); + } + + // Wir bauen den Info-Text in mehreren Component-Teilen auf + Component infoComponent = Component.empty(); + + // Header + Component l1 = miniMessage().deserialize("=== Clan info ===\n"); + // ID + Component l2 = miniMessage().deserialize(String.format( + " - ID: %s\n", + clan.getUuid() + )); + // Name + Component l3 = miniMessage().deserialize(String.format( + " - Name: %s\n", + clan.getName() + )); + // Leader + Component l4 = miniMessage().deserialize(String.format( + " - Leader: %s\n", + leaderName + )); + // Vice + Component l5 = miniMessage().deserialize(String.format( + " - Vice Leader: %s\n", + viceName + )); + // Member Count + Component l6 = miniMessage().deserialize(String.format( + " - Members: %d\n", + members.size() + )); + // Tag + Component l8 = miniMessage().deserialize(String.format( + " - Tag: %s\n", + miniMessage().serialize(clan.getTag()) + )); + // Member-Liste + Component l7 = miniMessage().deserialize("Members List:\n"); + + infoComponent = infoComponent + .append(l1).append(l2).append(l3) + .append(l4).append(l5).append(l6) + .append(l8).append(l7); + + // Detaillierte Auflistung der Mitglieder + for (UUID mem : members) { + OfflinePlayer off = Bukkit.getOfflinePlayer(mem); + String name = off.getName() != null ? off.getName() : mem.toString(); + Component memberLine = miniMessage().deserialize(String.format( + " - Member: %s\n", + name + )); + infoComponent = infoComponent.append(memberLine); + } + + // Abschlusslinie + Component endLine = miniMessage().deserialize("====================="); + infoComponent = infoComponent.append(endLine); + + player.sendMessage(infoComponent); + return true; + } + + // ========== KICK ========== + case "kick" -> { + if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not authorized to kick players.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan kick ")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + String targetName = args[1]; + OfflinePlayer targetOffline = Bukkit.getOfflinePlayer(targetName); + + if (targetOffline.getName() == null) { + player.sendMessage(miniMessage().deserialize("No such player found.")); + return true; + } + UUID targetUUID = targetOffline.getUniqueId(); + + // Check: Ist der Spieler im Clan? + if (!currentClan.isMember(targetUUID)) { + player.sendMessage(miniMessage().deserialize(String.format("%s is not in your clan!", targetName))); + return true; + } + // Vice kann keinen Leader kicken + if (clans.isVice(playerUUID) && currentClan.isLeader(targetUUID)) { + player.sendMessage(miniMessage().deserialize("You cannot kick the clan leader!")); + return true; + } + + // Vice entfernen, falls der Gekickte Vice war + if (currentClan.isVice(targetUUID)) { + currentClan.setViceUUID(null); + } + currentClan.getMembers().remove(targetUUID); + currentClan.save(); + + player.sendMessage(miniMessage().deserialize(String.format("You kicked %s from the clan.", targetName))); + if (targetOffline.isOnline()) { + Player targetOnline = (Player) targetOffline; + targetOnline.sendMessage(miniMessage().deserialize(String.format("You have been kicked from the clan %s.", currentClan.getName()))); + } + return true; + } + + // ========== TRANSFER ========== + case "transfer" -> { + if (!clans.isLeader(playerUUID)) { + player.sendMessage(miniMessage().deserialize("Only the clan leader can transfer leadership.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan transfer ")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + String newLeaderName = args[1]; + OfflinePlayer newLeaderOffline = Bukkit.getOfflinePlayer(newLeaderName); + if (newLeaderOffline.getName() == null) { + player.sendMessage(miniMessage().deserialize("No such player found.")); + return true; + } + UUID newLeaderUUID = newLeaderOffline.getUniqueId(); + + if (!currentClan.isMember(newLeaderUUID)) { + player.sendMessage(miniMessage().deserialize(String.format("%s is not in your clan!", newLeaderName))); + return true; + } + + // Füge den alten Leader zur Members-Liste hinzu (falls nicht enthalten) + if (!currentClan.getMembers().contains(playerUUID)) { + currentClan.getMembers().add(playerUUID); + } + // Setze neuen Leader + currentClan.setLeaderUUID(newLeaderUUID); + // Falls Vice, entfernen + if (currentClan.isVice(newLeaderUUID)) { + currentClan.setViceUUID(null); + } + currentClan.save(); + + player.sendMessage(miniMessage().deserialize(String.format("You transferred leadership to %s.", newLeaderName))); + if (newLeaderOffline.isOnline()) { + ((Player) newLeaderOffline).sendMessage(miniMessage().deserialize( + String.format("You are now the leader of the clan %s.", currentClan.getName()))); + } + return true; + } + + // ========== PROMOTE ========== + case "promote" -> { + if (!clans.isLeader(playerUUID)) { + player.sendMessage(miniMessage().deserialize("Only the clan leader can promote a member.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan promote ")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + String promoteName = args[1]; + OfflinePlayer promoteOffline = Bukkit.getOfflinePlayer(promoteName); + + if (promoteOffline.getName() == null) { + player.sendMessage(miniMessage().deserialize("No such player found.")); + return true; + } + UUID promoteUUID = promoteOffline.getUniqueId(); + + if (!currentClan.isMember(promoteUUID)) { + player.sendMessage(miniMessage().deserialize(String.format("%s is not in your clan!", promoteName))); + return true; + } + // Vice setzen + currentClan.setViceUUID(promoteUUID); + currentClan.save(); + + player.sendMessage(miniMessage().deserialize(String.format("You promoted %s to vice leader.", promoteName))); + if (promoteOffline.isOnline()) { + ((Player) promoteOffline).sendMessage(miniMessage().deserialize( + String.format("You have been promoted to vice leader of clan %s.", currentClan.getName()))); + } + return true; + } + + // ========== DEMOTE ========== + case "demote" -> { + if (!clans.isLeader(playerUUID) && !clans.isVice(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not authorized to demote anyone.")); + return true; + } + if (args.length < 2) { + player.sendMessage(miniMessage().deserialize("Usage: /clan demote ")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + String demoteName = args[1]; + OfflinePlayer demoteOffline = Bukkit.getOfflinePlayer(demoteName); + + if (demoteOffline.getName() == null) { + player.sendMessage(miniMessage().deserialize("No such player found.")); + return true; + } + UUID demoteUUID = demoteOffline.getUniqueId(); + + // Check, ob der Spieler Vice ist + if (!currentClan.isVice(demoteUUID)) { + player.sendMessage(miniMessage().deserialize(String.format("%s is not the vice leader!", demoteName))); + return true; + } + // Vice kann nur sich selbst demoten (oder Leader kann Vice demoten) + if (!clans.isLeader(playerUUID) && !playerUUID.equals(demoteUUID)) { + player.sendMessage(miniMessage().deserialize("You can only demote yourself!")); + return true; + } + currentClan.setViceUUID(null); + // Sicherstellen, dass der Spieler in der Memberliste bleibt + if (!currentClan.getMembers().contains(demoteUUID)) { + currentClan.getMembers().add(demoteUUID); + } + currentClan.save(); + + player.sendMessage(miniMessage().deserialize(String.format("You demoted %s to a normal member.", demoteName))); + if (demoteOffline.isOnline()) { + ((Player) demoteOffline).sendMessage(miniMessage().deserialize( + String.format("You have been demoted to a normal member of clan %s.", currentClan.getName()))); + } + return true; + } + + // ========== DISBAND ========== + case "disband" -> { + if (!clans.isLeader(playerUUID)) { + player.sendMessage(miniMessage().deserialize("Only the clan leader can disband the clan.")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + + // Benachrichtige alle Mitglieder + for (UUID memberUUID : currentClan.getMembers()) { + Player memberOnline = Bukkit.getPlayer(memberUUID); + if (memberOnline != null && memberOnline.isOnline()) { + memberOnline.sendMessage(miniMessage().deserialize( + String.format("Your clan %s has been disbanded by the leader.", currentClan.getName()))); + } + } + // Clan entfernen + clans.removeClan(currentClan); + player.sendMessage(miniMessage().deserialize("You have disbanded your clan.")); + return true; + } + + // ========== LEAVE ========== + case "leave" -> { + if (!clans.isInClan(playerUUID)) { + player.sendMessage(miniMessage().deserialize("You are not in a clan!")); + return true; + } + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + + // Leader kann nicht einfach gehen, ohne disband oder transfer + if (currentClan.isLeader(playerUUID)) { + if (!currentClan.getMembers().isEmpty()) { + player.sendMessage(miniMessage().deserialize("You must transfer leadership or disband the clan before leaving.")); + } else { + // Keine weiteren Mitglieder -> disband + clans.removeClan(currentClan); + player.sendMessage(miniMessage().deserialize( + "You have disbanded your clan (no other members) and left.")); + } + return true; + } + // Vice -> Vice-Position freigeben + if (currentClan.isVice(playerUUID)) { + currentClan.setViceUUID(null); + } + currentClan.getMembers().remove(playerUUID); + currentClan.save(); + + player.sendMessage(miniMessage().deserialize( + String.format("You have left the clan %s.", currentClan.getName()))); + return true; + } + + // ========== MODIFY (Name/Tag) ========== + case "modify" -> { + if (!clans.isLeader(playerUUID)) { + player.sendMessage(miniMessage().deserialize("Only the clan leader can modify clan settings.")); + return true; + } + if (args.length < 3) { + player.sendMessage(miniMessage().deserialize("Usage: /clan modify ")); + return true; + } + String whatToModify = args[1].toLowerCase(); + String newValue = args[2]; + + Clan currentClan = clans.getClanByMember(playerUUID); + if (currentClan == null) { + player.sendMessage(miniMessage().deserialize("Could not find your clan.")); + return true; + } + + switch (whatToModify) { + case "name" -> { + currentClan.setName(newValue); + currentClan.save(); + player.sendMessage(miniMessage().deserialize(String.format("Clan name changed to %s.", newValue))); + } + case "tag" -> { + Component newTag = miniMessage().deserialize(newValue); + currentClan.setTag(newTag); + currentClan.save(); + player.sendMessage(miniMessage().deserialize(String.format("Clan tag changed to %s.", newValue))); + } + default -> { + player.sendMessage(miniMessage().deserialize("You can only modify 'name' or 'tag'.")); + } + } + return true; + } + + // ========== Fallback für Unbekanntes ========== default -> { - player.sendMessage(miniMessage().deserialize("Unknown subcommand. Use /clan for help.")); + player.sendMessage(miniMessage().deserialize("Unknown subcommand. Use /clan for help.")); return true; } } } + /** + * Zeigt eine Liste aller Clans auf dem Server an. + */ + private void sendClanList(Player player) { + // Hier nehmen wir an, dass 'clans.getClans()' alle existierenden Clans liefert. + Collection allClans = clans.getClans(); + if (allClans.isEmpty()) { + player.sendMessage(miniMessage().deserialize("No clans found!")); + return; + } + + Component clanListComponent = Component.empty(); + clanListComponent = clanListComponent.append( + miniMessage().deserialize("=== List of clans ===\n")); + + for (Clan clan : allClans) { + Component clanComponent = miniMessage().deserialize( + String.format(" - %s\n", clan.getName())); + clanListComponent = clanListComponent.append(clanComponent); + } + clanListComponent = clanListComponent.append( + miniMessage().deserialize("=====================")); + + player.sendMessage(clanListComponent); + } + + /** + * Hilfsfunktion: Zeigt eine übersichtliche Hilfe basierend auf der Rolle (Leader, Vice, Member, Kein-Mitglied). + */ + private void sendHelpMessage(Player player, UUID playerUUID) { + if (clans.isLeader(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan invite\n"); + Component l4 = miniMessage().deserialize(" - /clan kick\n"); + Component l5 = miniMessage().deserialize(" - /clan transfer\n"); + Component l6 = miniMessage().deserialize(" - /clan promote\n"); + Component l7 = miniMessage().deserialize(" - /clan demote\n"); + Component l8 = miniMessage().deserialize(" - /clan disband\n"); + Component l9 = miniMessage().deserialize(" - /clan leave\n"); + Component l10 = miniMessage().deserialize(" - /clan accept\n"); + Component l11 = miniMessage().deserialize(" - /clan deny\n"); + Component l12 = miniMessage().deserialize(" - /clan modify\n"); + Component l13 = miniMessage().deserialize(" - /clan list\n"); + Component l14 = miniMessage().deserialize("====================="); + + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) + .append(l6).append(l7).append(l8).append(l9).append(l10).append(l11).append(l12).append(l13).append(l14)); + } else if (clans.isVice(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan invite\n"); + Component l4 = miniMessage().deserialize(" - /clan kick\n"); + Component l5 = miniMessage().deserialize(" - /clan demote\n"); + Component l6 = miniMessage().deserialize(" - /clan leave\n"); + Component l7 = miniMessage().deserialize(" - /clan accept\n"); + Component l8 = miniMessage().deserialize(" - /clan deny\n"); + Component l9 = miniMessage().deserialize(" - /clan list\n"); + Component l10 = miniMessage().deserialize("====================="); + + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5) + .append(l6).append(l7).append(l8).append(l9).append(l10)); + } else if (clans.isMember(playerUUID)) { + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan info\n"); + Component l3 = miniMessage().deserialize(" - /clan leave\n"); + Component l4 = miniMessage().deserialize(" - /clan list\n"); + Component l5 = miniMessage().deserialize("====================="); + + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5)); + } else { + // Spieler ist in keinem Clan + Component l1 = miniMessage().deserialize("=== Clan Commands ===\n"); + Component l2 = miniMessage().deserialize(" - /clan create\n"); + Component l3 = miniMessage().deserialize(" - /clan join\n"); + Component l4 = miniMessage().deserialize(" - /clan accept\n"); + Component l5 = miniMessage().deserialize(" - /clan deny\n"); + Component l6 = miniMessage().deserialize(" - /clan list\n"); + Component l7 = miniMessage().deserialize("====================="); + + player.sendMessage(l1.append(l2).append(l3).append(l4).append(l5).append(l6).append(l7)); + } + } + @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) { - Player player = (Player) sender; + public @Nullable List onTabComplete(@NotNull CommandSender sender, + @NotNull Command cmd, + @NotNull String label, + @NotNull String[] args) { + if (!(sender instanceof Player player)) return List.of(); UUID playerUUID = player.getUniqueId(); + + // Erste Ebene der Subcommands if (args.length == 1) { if (clans.isLeader(playerUUID)) { - return Stream.of("info", "invite", "kick", "transfer", "promote", "demote", "disband", "leave", "accept", "deny", "modify") - .filter(s -> s.startsWith(args[0])).toList(); + return Stream.of("info", "invite", "kick", "transfer", "promote", + "demote", "disband", "leave", "accept", "deny", + "modify", "list") + .filter(s -> s.startsWith(args[0])) + .collect(Collectors.toList()); } else if (clans.isVice(playerUUID)) { - return Stream.of("info", "invite", "kick", "demote", "leave", "accept", "deny") - .filter(s -> s.startsWith(args[0])).toList(); + return Stream.of("info", "invite", "kick", "demote", + "leave", "accept", "deny", "list") + .filter(s -> s.startsWith(args[0])) + .collect(Collectors.toList()); } else if (clans.isMember(playerUUID)) { - return Stream.of("info", "leave") - .filter(s -> s.startsWith(args[0])).toList(); + return Stream.of("info", "leave", "list") + .filter(s -> s.startsWith(args[0])) + .collect(Collectors.toList()); } else { - return Stream.of("create", "join", "accept", "deny") - .filter(s -> s.startsWith(args[0])).toList(); + return Stream.of("create", "join", "accept", "deny", "list") + .filter(s -> s.startsWith(args[0])) + .collect(Collectors.toList()); } - } else if (args.length == 2) { + } + + // Zweite Ebene + if (args.length == 2) { if (clans.isLeader(playerUUID)) { - if (args[0].equalsIgnoreCase("invite")) { - return Bukkit.getOnlinePlayers().stream() - .filter(p -> !clans.isMember(p.getUniqueId())) - .map(Player::getName) - .filter(name -> name.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("kick")) { - return clans.getClanByMember(playerUUID).getMembers().stream() - .map(UUID::toString) - .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("promote")) { - return clans.getClanByMember(playerUUID).getMembers().stream() - .map(UUID::toString) - .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("demote")) { - return Collections.singletonList(plugin.getServer().getOfflinePlayer(clans.getClanByMember(playerUUID).getViceUUID()).getName()); - } else if (args[0].equalsIgnoreCase("accept")) { - List joins = getClanJoinRequests(args, playerUUID); - if (joins != null) return joins; - } else if (args[0].equalsIgnoreCase("deny")) { - List joins = getClanJoinRequests(args, playerUUID); - if (joins != null) return joins; - } else if (args[0].equalsIgnoreCase("modify")) { - return Stream.of("name", "tag").filter(s -> s.startsWith(args[1])).toList(); + switch (args[0].toLowerCase()) { + case "invite" -> { + return Bukkit.getOnlinePlayers().stream() + .filter(p -> !clans.isMember(p.getUniqueId())) + .map(Player::getName) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "kick", "promote" -> { + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null) return List.of(); + return clan.getMembers().stream() + .map(uuid -> Bukkit.getOfflinePlayer(uuid).getName()) + .filter(Objects::nonNull) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "demote" -> { + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null || clan.getViceUUID() == null) return List.of(); + String viceName = Optional.ofNullable( + Bukkit.getOfflinePlayer(clan.getViceUUID()).getName()) + .orElse(clan.getViceUUID().toString()); + return viceName.startsWith(args[1]) + ? List.of(viceName) + : List.of(); + } + case "accept", "deny" -> { + List joins = getClanJoinRequests(args, playerUUID); + if (joins != null) return joins; + } + case "modify" -> { + return Stream.of("name", "tag") + .filter(s -> s.startsWith(args[1])) + .collect(Collectors.toList()); + } + default -> {} } } else if (clans.isVice(playerUUID)) { - if (args[0].equalsIgnoreCase("invite")) { - return Bukkit.getOnlinePlayers().stream() - .filter(p -> !clans.isMember(p.getUniqueId())) - .map(Player::getName) - .filter(name -> name.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("kick")) { - return clans.getClanByMember(playerUUID).getMembers().stream() - .map(UUID::toString) - .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("accept")) { - List joins = getClanJoinRequests(args, playerUUID); - if (joins != null) return joins; - } else if (args[0].equalsIgnoreCase("deny")) { - List joins = getClanJoinRequests(args, playerUUID); - if (joins != null) return joins; - } else if (args[0].equalsIgnoreCase("demote")) { - return Collections.singletonList(plugin.getServer().getOfflinePlayer(clans.getClanByMember(playerUUID).getViceUUID()).getName()); + switch (args[0].toLowerCase()) { + case "invite" -> { + return Bukkit.getOnlinePlayers().stream() + .filter(p -> !clans.isMember(p.getUniqueId())) + .map(Player::getName) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "kick" -> { + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null) return List.of(); + return clan.getMembers().stream() + .map(uuid -> Bukkit.getOfflinePlayer(uuid).getName()) + .filter(Objects::nonNull) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "demote" -> { + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null || clan.getViceUUID() == null) return List.of(); + String viceName = Optional.ofNullable( + Bukkit.getOfflinePlayer(clan.getViceUUID()).getName()) + .orElse(clan.getViceUUID().toString()); + return viceName.startsWith(args[1]) + ? List.of(viceName) + : List.of(); + } + case "accept", "deny" -> { + List joins = getClanJoinRequests(args, playerUUID); + if (joins != null) return joins; + } + default -> {} } } else { - if (args[0].equalsIgnoreCase("accept")) { - return clanInvites.entrySet().stream() - .filter(entry -> entry.getValue().contains(playerUUID)) - .map(entry -> entry.getKey().getName()) - .collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("deny")) { - return clanInvites.entrySet().stream() - .filter(entry -> entry.getValue().contains(playerUUID)) - .map(entry -> entry.getKey().getName()) - .collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("join")) { - return clans.getClans().stream() - .map(Clan::getName) - .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); - } else if (args[0].equalsIgnoreCase("create")) { - return Collections.singletonList(""); + switch (args[0].toLowerCase()) { + case "accept", "deny" -> { + // Zeige alle Clan-Einladungen an + return clanInvites.entrySet().stream() + .filter(entry -> entry.getValue().contains(playerUUID)) + .map(entry -> entry.getKey().getName()) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "join" -> { + // Zeige alle Clans an + return clans.getClans().stream() + .map(Clan::getName) + .filter(s -> s.startsWith(args[1])) + .collect(Collectors.toList()); + } + case "create" -> { + return Collections.singletonList(""); + } + default -> {} } } - } else if (args.length == 3) { + } + + // Dritte Ebene (z. B. /clan modify name ) + if (args.length == 3) { if (clans.isLeader(playerUUID)) { - if (args[1].equalsIgnoreCase("name")) { - return Collections.singletonList(""); - } else if (args[1].equalsIgnoreCase("tag")) { - return Collections.singletonList(""); - } - } else { - if (args[0].equalsIgnoreCase("create")) { - return Collections.singletonList(""); + if (args[0].equalsIgnoreCase("modify")) { + if (args[1].equalsIgnoreCase("name")) { + return Collections.singletonList(""); + } else if (args[1].equalsIgnoreCase("tag")) { + return Collections.singletonList(""); + } } + } else if (args[0].equalsIgnoreCase("create")) { + return Collections.singletonList(""); } } return List.of(); } + /** + * Liefert zu einem Namen die passende UUID aus einer UUID-Liste (z. B. Join-Anfragen). + */ @Nullable - private List getClanJoinRequests(@NotNull String[] args, UUID playerUUID) { - LinkedList joins = clanJoins.get(clans.getClanByMember(playerUUID)); - if (joins != null) { - return joins.stream() - .map(uuid -> plugin.getServer().getOfflinePlayer(uuid).getName()) - .filter(Objects::nonNull) - .filter(s -> s.startsWith(args[1])).collect(Collectors.toList()); + private UUID getUuidByName(List uuidList, String playerName) { + for (UUID uuid : uuidList) { + OfflinePlayer off = Bukkit.getOfflinePlayer(uuid); + if (off.getName() != null && off.getName().equalsIgnoreCase(playerName)) { + return uuid; + } } return null; } + + /** + * Hilfsfunktion für Tab-Completion (Zeigt Spielernamen von Join-Anfragen). + */ + @Nullable + private List getClanJoinRequests(@NotNull String[] args, UUID playerUUID) { + Clan clan = clans.getClanByMember(playerUUID); + if (clan == null) return null; + + LinkedList joins = clanJoins.get(clan); + if (joins == null) return null; + + return joins.stream() + .map(uuid -> Bukkit.getOfflinePlayer(uuid).getName()) + .filter(Objects::nonNull) + .filter(name -> name.startsWith(args[1])) + .collect(Collectors.toList()); + } }