@@ -55,6 +55,7 @@ public boolean run(
5555 return switch (args [0 ]) {
5656 case "citizens" , "members" , "subjects" , "nationals" , "people" , "residents" , "population" , "cits" , "pop" -> citizens (member .orElse (null ), nation .orElse (null ), sender , command , argsSubset );
5757 case "join" , "request" , "req" -> join (member .orElse (null ), sender , command , argsSubset );
58+ case "cancel" , "reject" , "decline" , "withdraw" , "refuse" , "deny" -> memberCancel (member .orElse (null ), sender , command , argsSubset );
5859 case "leave" , "abandon" , "renounce" -> leave (member .orElse (null ), nation .orElse (null ), sender );
5960 default -> helpSubCommands (member .orElse (null ), nation .orElse (null ), sender , label );
6061 };
@@ -106,6 +107,19 @@ public static boolean helpSubCommands(
106107 new Messages .SubCommandArgument ("nation" , true )
107108 }, "Request to join a nation."
108109 ));
110+ if (member != null && !CitizenRequest .get (member , true ).isEmpty ())
111+ subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
112+ command + " cancel " , "cancel" , new Messages .SubCommandArgument []{
113+ new Messages .SubCommandArgument ("nation" , true )
114+ }, "Cancel request to join nation."
115+ ));
116+
117+ if (member != null && !CitizenRequest .get (member , false ).isEmpty ())
118+ subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
119+ command + " reject " , "reject" , new Messages .SubCommandArgument []{
120+ new Messages .SubCommandArgument ("nation" , true )
121+ }, "Reject invitation to join nation."
122+ ));
109123 }
110124
111125 return sendMessage (sender , subCommandBuilder .build ());
@@ -129,6 +143,7 @@ public static boolean citizens(
129143 case "list" , "show" , "get" -> listCitizens (member , nation , sender );
130144 case "kick" , "remove" , "delete" , "rm" , "del" -> kickCitizen (member , nation , sender , command , argsSubset );
131145 case "invite" , "request" , "req" -> inviteCitizen (member , nation , sender , command , argsSubset );
146+ case "cancel" , "reject" , "decline" , "withdraw" , "refuse" , "deny" -> nationCancel (member , nation , sender , command , argsSubset );
132147 case "add" -> addCitizen (member , nation , sender , command , argsSubset );
133148 default -> citizensSubcommands (member , nation , sender , label );
134149 };
@@ -165,13 +180,28 @@ public static boolean citizensSubcommands(
165180 ));
166181
167182 if ((!other && sender .hasPermission (Permission .NATION_INVITE ))
168- || sender .hasPermission (Permission .NATION_INVITE_OTHER ))
183+ || sender .hasPermission (Permission .NATION_INVITE_OTHER )) {
169184 subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
170185 label + " invite " , "invite" , new Messages .SubCommandArgument []{
171186 new Messages .SubCommandArgument ("member" , true )
172187 }, "Invite to join nation."
173188 ));
174189
190+ if (!CitizenRequest .get (nation , true ).isEmpty ())
191+ subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
192+ label + " reject " , "reject" , new Messages .SubCommandArgument []{
193+ new Messages .SubCommandArgument ("member" , true )
194+ }, "Reject request to join nation."
195+ ));
196+
197+ if (!CitizenRequest .get (nation , false ).isEmpty ())
198+ subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
199+ label + " cancel " , "cancel" , new Messages .SubCommandArgument []{
200+ new Messages .SubCommandArgument ("member" , true )
201+ }, "Cancel invitation to join nation."
202+ ));
203+ }
204+
175205 if ((!other && sender .hasPermission (Permission .NATION_CITIZEN_ADD ))
176206 || sender .hasPermission (Permission .NATION_CITIZEN_ADD_OTHER ))
177207 subCommandBuilder .append (Component .newline ()).append (SMPCore .messages ().subCommandEntry (
@@ -381,6 +411,70 @@ public static boolean join(
381411 return true ;
382412 }
383413
414+ public static boolean memberCancel (
415+ final @ Nullable Member member ,
416+ final @ NotNull CommandSender sender ,
417+ final @ NotNull String label ,
418+ final @ NotNull String @ NotNull [] args
419+ ) {
420+ if (member == null )
421+ return sendMessage (sender , SMPCore .messages ().errorNotMember ());
422+
423+ if (!hasAnyPermission (sender , Permission .NATION_JOIN_REQUEST , Permission .NATION_INVITE_ACCEPT ))
424+ return sendMessage (sender , SMPCore .messages ().errorNoPermission ());
425+
426+ if (args .length < 1 )
427+ return sendMessage (sender , SMPCore .messages ().usage (label , "<nation>" ));
428+
429+ final var nation = Nation .get (args [0 ]);
430+ if (nation .isEmpty ())
431+ return sendMessage (sender , SMPCore .messages ().errorNationNotFound (args [0 ]));
432+
433+ final var request = CitizenRequest .get (member , nation .get ());
434+ if (request .isEmpty ())
435+ return sendMessage (sender , SMPCore .messages ().errorNoRequest (nation .get ()));
436+
437+ request .get ().delete ();
438+ if (request .get ().mode )
439+ return sendMessage (sender , SMPCore .messages ().nationJoinRequestCancelled (nation .get ()));
440+ return sendMessage (sender , SMPCore .messages ().nationJoinInviteRejected (nation .get ()));
441+ }
442+
443+ public static boolean nationCancel (
444+ final @ Nullable Member member ,
445+ final @ NotNull Nation nation ,
446+ final @ NotNull CommandSender sender ,
447+ final @ NotNull String label ,
448+ final @ NotNull String @ NotNull [] args
449+ ) {
450+ if (
451+ !sender .hasPermission (Permission .NATION_INVITE )
452+ || (
453+ (member == null || !nation .id .equals (member .nationID ))
454+ && !sender .hasPermission (Permission .NATION_INVITE_OTHER )
455+ )
456+ )
457+ return sendMessage (sender , SMPCore .messages ().errorNoPermission ());
458+
459+ if (args .length < 1 )
460+ return sendMessage (sender , SMPCore .messages ().usage (label , "<member>" ));
461+
462+ final var targetPlayer = sender .getServer ().getOfflinePlayer (args [0 ]);
463+ final @ NotNull var target = Member .get (targetPlayer );
464+
465+ if (target .isEmpty ())
466+ return sendMessage (sender , SMPCore .messages ().errorNotMember (targetPlayer ));
467+
468+ final var request = CitizenRequest .get (target .get (), nation );
469+ if (request .isEmpty ())
470+ return sendMessage (sender , SMPCore .messages ().errorNoRequest (target .get ()));
471+
472+ request .get ().delete ();
473+ if (request .get ().mode )
474+ return sendMessage (sender , SMPCore .messages ().nationJoinRequestRejected (target .get (), nation ));
475+ return sendMessage (sender , SMPCore .messages ().nationJoinInviteCancelled (target .get (), nation ));
476+ }
477+
384478 public static boolean leave (
385479 final @ Nullable Member member ,
386480 final @ Nullable Nation nation ,
0 commit comments