From 7b4a7c10b564e7a8b1dfcced60f554dbd9c7c5a0 Mon Sep 17 00:00:00 2001 From: AlessioDP Date: Wed, 23 Jan 2019 11:48:54 +0100 Subject: [PATCH] Update 2.5.0 --- api/pom.xml | 2 +- .../parties/api/events/Cancellable.java | 4 +- .../parties/api/events/PartiesEvent.java | 2 + .../BukkitPartiesPlayerPostLeaveEvent.java | 2 +- .../BukkitPartiesPlayerPreLeaveEvent.java | 2 +- ...artiesCombustFriendlyFireBlockedEvent.java | 6 +- ...BukkitPartiesFriendlyFireBlockedEvent.java | 6 +- ...artiesPotionsFriendlyFireBlockedEvent.java | 6 +- .../BungeePartiesPlayerPostLeaveEvent.java | 2 +- .../BungeePartiesPlayerPreLeaveEvent.java | 2 +- .../unique/BungeePartiesPartyFollowEvent.java | 24 +++ .../common/party/IPartyPostCreateEvent.java | 4 +- .../common/party/IPartyPostDeleteEvent.java | 14 +- .../common/party/IPartyPreCreateEvent.java | 18 +- .../common/party/IPartyPreDeleteEvent.java | 16 +- .../common/party/IPartyRenameEvent.java | 18 +- .../api/events/common/player/IChatEvent.java | 12 +- .../common/player/IPlayerPostJoinEvent.java | 8 +- .../common/player/IPlayerPostLeaveEvent.java | 10 +- .../common/player/IPlayerPreJoinEvent.java | 8 +- .../common/player/IPlayerPreLeaveEvent.java | 12 +- .../parties/api/interfaces/Color.java | 42 ++--- .../parties/api/interfaces/HomeLocation.java | 18 +- .../parties/api/interfaces/PartiesAPI.java | 106 +++++------ .../parties/api/interfaces/Party.java | 103 ++++++----- .../parties/api/interfaces/PartyPlayer.java | 40 ++-- .../parties/api/interfaces/Rank.java | 54 +++--- ...ckShot-0.98.8.jar => CrackShot-0.98.9.jar} | Bin 176096 -> 176107 bytes bukkit/pom.xml | 6 +- .../parties/bukkit/BukkitPartiesPlugin.java | 11 +- .../addons/internal/TabCompleterHandler.java | 43 ----- .../commands/BukkitCommandDispatcher.java | 20 -- .../bukkit/commands/BukkitCommandImpl.java | 42 ----- .../bukkit/commands/BukkitCommandManager.java | 117 +++++------- .../bukkit/commands/list/BukkitCommands.java | 7 + .../bukkit/commands/main/BukkitCommandP.java | 11 ++ .../commands/main/BukkitCommandParty.java | 48 +++++ .../BukkitCommandTeleport.java | 8 +- .../{executors => sub}/CommandClaim.java | 21 ++- .../{executors => sub}/CommandConfirm.java | 6 +- .../{executors => sub}/CommandHome.java | 24 ++- .../{executors => sub}/CommandProtection.java | 26 ++- .../{executors => sub}/CommandSetHome.java | 18 +- .../commands/utils/BukkitCommandImpl.java | 41 +++++ .../configuration/data/BukkitConfigMain.java | 8 +- .../configuration/data/BukkitMessages.java | 2 +- .../bukkit/listeners/BukkitChatListener.java | 2 +- .../bukkit/listeners/BukkitExpListener.java | 2 +- .../bukkit/listeners/BukkitFightListener.java | 30 ++- .../listeners/BukkitFollowListener.java | 10 +- .../listeners/BukkitJoinLeaveListener.java | 5 +- .../bukkit/listeners/BukkitMoveListener.java | 82 --------- .../bukkit/messaging/MessageListener.java | 20 +- .../bukkit/messaging/MessageManager.java | 13 +- .../bukkit/parties/BukkitCooldownManager.java | 39 ---- .../parties/bukkit/players/ExpManager.java | 7 +- .../objects/BukkitPartyPlayerImpl.java | 11 +- .../bukkit/players/objects/HomeCooldown.java | 28 --- .../scheduling/BukkitPartiesScheduler.java | 10 +- .../parties/bukkit/tasks/HomeTask.java | 71 +++++++- bukkit/src/main/resources/bukkit/config.yml | 40 ++-- bukkit/src/main/resources/bukkit/messages.yml | 84 +++++---- bukkit/src/main/resources/bukkit/parties.yml | 28 ++- bukkit/src/main/resources/plugin.yml | 6 + bungee/pom.xml | 2 +- .../commands/BungeeCommandDispatcher.java | 11 -- .../commands/BungeeCommandImpl.java | 26 --- .../commands/BungeeCommandManager.java | 31 +--- .../commands/main/BungeeCommandP.java | 11 ++ .../commands/main/BungeeCommandParty.java | 23 +++ .../BungeeCommandTeleport.java | 8 +- .../commands/utils/BungeeCommandImpl.java | 33 ++++ .../configuration/data/BungeeConfigMain.java | 2 + .../bungeecord/events/BungeeEventManager.java | 6 + .../events/bungee/PartyFollowEventHook.java | 38 ++++ .../listeners/BungeeFollowListener.java | 64 ++++--- .../scheduling/BungeePartiesScheduler.java | 6 +- bungee/src/main/resources/bungee/config.yml | 39 ++-- bungee/src/main/resources/bungee/messages.yml | 53 ++++-- bungee/src/main/resources/bungee/parties.yml | 23 ++- common/pom.xml | 2 +- .../parties/common/PartiesPlugin.java | 1 + .../common/addons/internal/ADPUpdater.java | 2 +- .../addons/internal/PartiesPlaceholder.java | 8 +- .../common/commands/CommandDispatcher.java | 99 ---------- .../common/commands/CommandManager.java | 91 ++-------- .../common/commands/executors/CommandP.java | 114 ------------ .../commands/executors/CommandParty.java | 83 --------- .../common/commands/list/CommonCommands.java | 40 +++- .../common/commands/list/PartiesCommand.java | 1 + .../common/commands/main/CommandP.java | 150 +++++++++++++++ .../common/commands/main/CommandParty.java | 171 ++++++++++++++++++ .../{executors => sub}/CommandAccept.java | 6 +- .../{executors => sub}/CommandChat.java | 27 ++- .../{executors => sub}/CommandColor.java | 26 ++- .../{executors => sub}/CommandCreate.java | 18 +- .../{executors => sub}/CommandDelete.java | 22 ++- .../{executors => sub}/CommandDeny.java | 6 +- .../{executors => sub}/CommandDesc.java | 30 ++- .../common/commands/sub/CommandFollow.java | 89 +++++++++ .../{executors => sub}/CommandHelp.java | 9 +- .../{executors => sub}/CommandIgnore.java | 6 +- .../{executors => sub}/CommandInfo.java | 8 +- .../{executors => sub}/CommandInvite.java | 12 +- .../{executors => sub}/CommandJoin.java | 6 +- .../{executors => sub}/CommandKick.java | 14 +- .../{executors => sub}/CommandLeave.java | 6 +- .../{executors => sub}/CommandList.java | 6 +- .../{executors => sub}/CommandMigrate.java | 22 ++- .../{executors => sub}/CommandMotd.java | 28 ++- .../{executors => sub}/CommandMute.java | 26 ++- .../{executors => sub}/CommandPassword.java | 17 +- .../{executors => sub}/CommandRank.java | 31 +++- .../{executors => sub}/CommandReload.java | 6 +- .../{executors => sub}/CommandRename.java | 17 +- .../{executors => sub}/CommandSpy.java | 30 ++- .../{executors => sub}/CommandTeleport.java | 6 +- .../common/commands/sub/CommandVersion.java | 51 ++++++ .../commands/{ => utils}/AbstractCommand.java | 16 +- .../commands/{ => utils}/CommandData.java | 2 +- .../utils/PartiesCommandExecutor.java | 18 ++ .../common/configuration/Constants.java | 32 ++-- .../common/configuration/data/ConfigMain.java | 45 ++--- .../configuration/data/ConfigParties.java | 12 ++ .../common/configuration/data/Messages.java | 57 ++++-- .../common/listeners/ChatListener.java | 32 ++-- .../common/listeners/JoinLeaveListener.java | 7 +- .../common/parties/CooldownManager.java | 6 +- .../common/parties/objects/PartyImpl.java | 22 ++- .../common/players/PartiesPermission.java | 4 + .../players/objects/InviteCooldown.java | 2 +- .../players/objects/PartyPlayerImpl.java | 9 +- .../common/scheduling/PartiesScheduler.java | 4 +- .../storage/dispatchers/FileDispatcher.java | 5 + .../storage/dispatchers/SQLDispatcher.java | 5 +- .../common/storage/sql/SQLUpgradeManager.java | 78 +++++++- .../parties/common/utils/DebugUtils.java | 4 +- .../parties/common/utils/PartiesUtils.java | 153 +++++++++++----- common/src/main/resources/schemas/mysql.sql | 33 ++-- common/src/main/resources/schemas/sqlite.sql | 3 +- images/helppages.jpg | Bin 122166 -> 0 bytes images/logo.png | Bin 48250 -> 0 bytes images/tablist.jpg | Bin 17732 -> 0 bytes output/pom.xml | 2 +- pom.xml | 2 +- 145 files changed, 2156 insertions(+), 1548 deletions(-) create mode 100644 api/src/main/java/com/alessiodp/parties/api/events/bungee/unique/BungeePartiesPartyFollowEvent.java rename bukkit/libs/{CrackShot-0.98.8.jar => CrackShot-0.98.9.jar} (63%) delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/addons/internal/TabCompleterHandler.java delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandDispatcher.java delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandImpl.java create mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandP.java create mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandParty.java rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/BukkitCommandTeleport.java (92%) rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/CommandClaim.java (87%) rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/CommandConfirm.java (89%) rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/CommandHome.java (89%) rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/CommandProtection.java (80%) rename bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/{executors => sub}/CommandSetHome.java (88%) create mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/utils/BukkitCommandImpl.java delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitMoveListener.java delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/parties/BukkitCooldownManager.java delete mode 100644 bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/HomeCooldown.java delete mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandDispatcher.java delete mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandImpl.java create mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandP.java create mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandParty.java rename bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/{executors => sub}/BungeeCommandTeleport.java (92%) create mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/utils/BungeeCommandImpl.java create mode 100644 bungee/src/main/java/com/alessiodp/parties/bungeecord/events/bungee/PartyFollowEventHook.java delete mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/CommandDispatcher.java delete mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandP.java delete mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandParty.java create mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/main/CommandP.java create mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/main/CommandParty.java rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandAccept.java (92%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandChat.java (77%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandColor.java (81%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandCreate.java (90%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandDelete.java (83%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandDeny.java (90%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandDesc.java (80%) create mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandFollow.java rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandHelp.java (89%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandIgnore.java (94%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandInfo.java (94%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandInvite.java (93%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandJoin.java (95%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandKick.java (94%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandLeave.java (95%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandList.java (96%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandMigrate.java (88%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandMotd.java (80%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandMute.java (77%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandPassword.java (88%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandRank.java (87%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandReload.java (89%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandRename.java (90%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandSpy.java (70%) rename common/src/main/java/com/alessiodp/parties/common/commands/{executors => sub}/CommandTeleport.java (87%) create mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandVersion.java rename common/src/main/java/com/alessiodp/parties/common/commands/{ => utils}/AbstractCommand.java (53%) rename common/src/main/java/com/alessiodp/parties/common/commands/{ => utils}/CommandData.java (94%) create mode 100644 common/src/main/java/com/alessiodp/parties/common/commands/utils/PartiesCommandExecutor.java delete mode 100644 images/helppages.jpg delete mode 100644 images/logo.png delete mode 100644 images/tablist.jpg diff --git a/api/pom.xml b/api/pom.xml index 63b89d776..a0c1ef29f 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -4,7 +4,7 @@ com.alessiodp.parties Parties - 2.4.7 + 2.5.0 parties-api diff --git a/api/src/main/java/com/alessiodp/parties/api/events/Cancellable.java b/api/src/main/java/com/alessiodp/parties/api/events/Cancellable.java index 1094965b5..c6d2a2173 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/Cancellable.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/Cancellable.java @@ -3,14 +3,14 @@ public interface Cancellable { /** * Is the event cancelled? - * + * * @return Returns {@code true} if the event is cancelled */ boolean isCancelled(); /** * Set the event as cancelled - * + * * @param cancel {@code True} to cancel */ void setCancelled(boolean cancel); diff --git a/api/src/main/java/com/alessiodp/parties/api/events/PartiesEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/PartiesEvent.java index 20daeeb71..32d9eb5a0 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/PartiesEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/PartiesEvent.java @@ -14,6 +14,8 @@ public interface PartiesEvent { /** * Set the Parties API instance. Used by Parties instance to let you hook directly to the main API. + * + * @param instance {@link PartiesAPI} instance to set */ void setApi(PartiesAPI instance); } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPostLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPostLeaveEvent.java index 451101e47..bfc0fb7b5 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPostLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPostLeaveEvent.java @@ -5,5 +5,5 @@ public abstract class BukkitPartiesPlayerPostLeaveEvent extends BukkitPartiesEvent implements IPlayerPostLeaveEvent { // Dummy class - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPreLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPreLeaveEvent.java index ac2b125e8..f38afb917 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPreLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/player/BukkitPartiesPlayerPreLeaveEvent.java @@ -5,5 +5,5 @@ public abstract class BukkitPartiesPlayerPreLeaveEvent extends BukkitPartiesEvent implements IPlayerPreLeaveEvent { // Dummy class - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesCombustFriendlyFireBlockedEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesCombustFriendlyFireBlockedEvent.java index 0a30b76b3..9ba762b5d 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesCombustFriendlyFireBlockedEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesCombustFriendlyFireBlockedEvent.java @@ -9,7 +9,7 @@ public abstract class BukkitPartiesCombustFriendlyFireBlockedEvent extends BukkitPartiesEvent implements Cancellable { /** * Get the victim of the event - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -17,7 +17,7 @@ public abstract class BukkitPartiesCombustFriendlyFireBlockedEvent extends Bukki /** * Get the attacker - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -25,7 +25,7 @@ public abstract class BukkitPartiesCombustFriendlyFireBlockedEvent extends Bukki /** * Get the original Bukkit event handled by Parties - * + * * @return Returns the original {@link EntityCombustByEntityEvent} */ @NotNull diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesFriendlyFireBlockedEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesFriendlyFireBlockedEvent.java index 37d5ee232..9b0b255c6 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesFriendlyFireBlockedEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesFriendlyFireBlockedEvent.java @@ -10,7 +10,7 @@ public abstract class BukkitPartiesFriendlyFireBlockedEvent extends BukkitPartiesEvent implements Cancellable { /** * Get the victim of the event - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -18,7 +18,7 @@ public abstract class BukkitPartiesFriendlyFireBlockedEvent extends BukkitPartie /** * Get the attacker - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -26,7 +26,7 @@ public abstract class BukkitPartiesFriendlyFireBlockedEvent extends BukkitPartie /** * Get the original Bukkit event handled by Parties - * + * * @return Returns the original {@link EntityDamageByEntityEvent}, or {@code null} if there is no bukkit event */ @Nullable diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesPotionsFriendlyFireBlockedEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesPotionsFriendlyFireBlockedEvent.java index 98d4730c5..d34ca651a 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesPotionsFriendlyFireBlockedEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bukkit/unique/BukkitPartiesPotionsFriendlyFireBlockedEvent.java @@ -9,7 +9,7 @@ public abstract class BukkitPartiesPotionsFriendlyFireBlockedEvent extends BukkitPartiesEvent implements Cancellable { /** * Get the victim of the event - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -17,7 +17,7 @@ public abstract class BukkitPartiesPotionsFriendlyFireBlockedEvent extends Bukki /** * Get the attacker - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -25,7 +25,7 @@ public abstract class BukkitPartiesPotionsFriendlyFireBlockedEvent extends Bukki /** * Gets the original Bukkit event handled by Parties - * + * * @return Returns the original {@link PotionSplashEvent} */ @NotNull diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPostLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPostLeaveEvent.java index 1552f7ea1..3140bd83b 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPostLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPostLeaveEvent.java @@ -5,5 +5,5 @@ public abstract class BungeePartiesPlayerPostLeaveEvent extends BungeePartiesEvent implements IPlayerPostLeaveEvent { // Dummy class - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPreLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPreLeaveEvent.java index 8bf081ae4..69e373f1e 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPreLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/bungee/player/BungeePartiesPlayerPreLeaveEvent.java @@ -5,5 +5,5 @@ public abstract class BungeePartiesPlayerPreLeaveEvent extends BungeePartiesEvent implements IPlayerPreLeaveEvent { // Dummy class - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/bungee/unique/BungeePartiesPartyFollowEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/bungee/unique/BungeePartiesPartyFollowEvent.java new file mode 100644 index 000000000..d271fb024 --- /dev/null +++ b/api/src/main/java/com/alessiodp/parties/api/events/bungee/unique/BungeePartiesPartyFollowEvent.java @@ -0,0 +1,24 @@ +package com.alessiodp.parties.api.events.bungee.unique; + +import com.alessiodp.parties.api.events.Cancellable; +import com.alessiodp.parties.api.events.bungee.BungeePartiesEvent; +import com.alessiodp.parties.api.interfaces.Party; +import org.jetbrains.annotations.NotNull; + +public abstract class BungeePartiesPartyFollowEvent extends BungeePartiesEvent implements Cancellable { + /** + * Get the party + * + * @return Returns the {@link Party} + */ + @NotNull + public abstract Party getParty(); + + /** + * Get the name of the server that the party will join into + * + * @return Returns the name of the server + */ + @NotNull + public abstract String getJoinedServer(); +} diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostCreateEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostCreateEvent.java index 9cfede08f..46fd876f0 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostCreateEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostCreateEvent.java @@ -8,7 +8,7 @@ public interface IPartyPostCreateEvent extends PartiesEvent { /** * Get the creator of the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -16,7 +16,7 @@ public interface IPartyPostCreateEvent extends PartiesEvent { /** * Get the party - * + * * @return Returns the {@link Party} */ @NotNull diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostDeleteEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostDeleteEvent.java index 7fc869c1c..a71b1e8e9 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostDeleteEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPostDeleteEvent.java @@ -10,7 +10,7 @@ public interface IPartyPostDeleteEvent extends PartiesEvent { /** * Get the deleted party name - * + * * @return Returns the name of the deleted party */ @NotNull @@ -18,7 +18,7 @@ public interface IPartyPostDeleteEvent extends PartiesEvent { /** * Get the delete cause - * + * * @return Returns the {@link DeleteCause} of the delete */ @NotNull @@ -26,19 +26,19 @@ public interface IPartyPostDeleteEvent extends PartiesEvent { /** * Get the kicked player - * + * * @return Returns the {@link PartyPlayer} of the kicked player, returns - * {@code null} if the delete cause is {@link DeleteCause#DELETE} or - * {@link DeleteCause#TIMEOUT} + * {@code null} if the delete cause is {@link DeleteCause#DELETE} or + * {@link DeleteCause#TIMEOUT} */ @Nullable PartyPlayer getKickedPlayer(); /** * Get the player who performed the command - * + * * @return Returns the {@link PartyPlayer} who did the command, returns - * {@code null} if the delete cause is {@link DeleteCause#TIMEOUT} + * {@code null} if the delete cause is {@link DeleteCause#TIMEOUT} */ @Nullable PartyPlayer getCommandSender(); diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreCreateEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreCreateEvent.java index 33821974e..8f504d288 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreCreateEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreCreateEvent.java @@ -1,14 +1,14 @@ package com.alessiodp.parties.api.events.common.party; +import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.events.PartiesEvent; import com.alessiodp.parties.api.interfaces.PartyPlayer; -import com.alessiodp.parties.api.events.Cancellable; import org.jetbrains.annotations.NotNull; public interface IPartyPreCreateEvent extends PartiesEvent, Cancellable { /** * Get the player that is creating the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -16,7 +16,7 @@ public interface IPartyPreCreateEvent extends PartiesEvent, Cancellable { /** * Get the name of the party - * + * * @return Returns the party name */ @NotNull @@ -24,24 +24,22 @@ public interface IPartyPreCreateEvent extends PartiesEvent, Cancellable { /** * Set a new name to the party - * - * @param name - * The name to set + * + * @param name The name to set */ void setPartyName(String name); /** * Is the party fixed? - * + * * @return Returns {@code true} if it's fixed */ boolean isFixed(); /** * Set if the party is fixed - * - * @param fixed - * {@code True} to be fixed + * + * @param fixed {@code True} to be fixed */ void setFixed(boolean fixed); } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreDeleteEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreDeleteEvent.java index b343b38e4..f5caff360 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreDeleteEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyPreDeleteEvent.java @@ -1,17 +1,17 @@ package com.alessiodp.parties.api.events.common.party; import com.alessiodp.parties.api.enums.DeleteCause; +import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.events.PartiesEvent; import com.alessiodp.parties.api.interfaces.Party; import com.alessiodp.parties.api.interfaces.PartyPlayer; -import com.alessiodp.parties.api.events.Cancellable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface IPartyPreDeleteEvent extends PartiesEvent, Cancellable { /** * Get the party that is getting cancelled - * + * * @return Returns the the {@link Party} */ @NotNull @@ -19,7 +19,7 @@ public interface IPartyPreDeleteEvent extends PartiesEvent, Cancellable { /** * Get the cause of delete - * + * * @return Returns the {@link DeleteCause} of the delete */ @NotNull @@ -27,19 +27,19 @@ public interface IPartyPreDeleteEvent extends PartiesEvent, Cancellable { /** * Get the kicked player - * + * * @return Returns the {@link PartyPlayer} of the kicked player, returns {@code null} - * if the delete cause is {@link DeleteCause#DELETE} or - * {@link DeleteCause#TIMEOUT} + * if the delete cause is {@link DeleteCause#DELETE} or + * {@link DeleteCause#TIMEOUT} */ @Nullable PartyPlayer getKickedPlayer(); /** * Get the player who performed the command - * + * * @return Returns the {@link PartyPlayer} who did the command, returns - * {@code null} if the delete cause is {@link DeleteCause#TIMEOUT} + * {@code null} if the delete cause is {@link DeleteCause#TIMEOUT} */ @Nullable PartyPlayer getCommandSender(); diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyRenameEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyRenameEvent.java index 6ada4b58e..2f881bb26 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyRenameEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/party/IPartyRenameEvent.java @@ -1,14 +1,15 @@ package com.alessiodp.parties.api.events.common.party; +import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.events.PartiesEvent; import com.alessiodp.parties.api.interfaces.Party; import com.alessiodp.parties.api.interfaces.PartyPlayer; -import com.alessiodp.parties.api.events.Cancellable; import org.jetbrains.annotations.NotNull; public interface IPartyRenameEvent extends PartiesEvent, Cancellable { - /** Get the party that is getting renamed - * + /** + * Get the party that is getting renamed + * * @return Returns the {@link Party} */ @NotNull @@ -16,7 +17,7 @@ public interface IPartyRenameEvent extends PartiesEvent, Cancellable { /** * Get the new party name - * + * * @return Returns the new name of the party */ @NotNull @@ -24,15 +25,14 @@ public interface IPartyRenameEvent extends PartiesEvent, Cancellable { /** * Set the new name of the party - * - * @param name - * The party name to set + * + * @param name The party name to set */ void setNewPartyName(String name); /** * Get the player who performed the command - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -40,7 +40,7 @@ public interface IPartyRenameEvent extends PartiesEvent, Cancellable { /** * Is it an admin renaming? - * + * * @return Returns {@code true} if the rename has been performed by an admin */ boolean isAdmin(); diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IChatEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IChatEvent.java index 5fd5e1aad..85087f1b7 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IChatEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IChatEvent.java @@ -1,15 +1,15 @@ package com.alessiodp.parties.api.events.common.player; +import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.events.PartiesEvent; import com.alessiodp.parties.api.interfaces.Party; -import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.interfaces.PartyPlayer; import org.jetbrains.annotations.NotNull; public interface IChatEvent extends PartiesEvent, Cancellable { /** * Get the player who sent the message - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -17,7 +17,7 @@ public interface IChatEvent extends PartiesEvent, Cancellable { /** * Get the party - * + * * @return Returns the the {@link Party} */ @NotNull @@ -25,7 +25,7 @@ public interface IChatEvent extends PartiesEvent, Cancellable { /** * Get the message of the player - * + * * @return Returns the message */ @NotNull @@ -33,9 +33,9 @@ public interface IChatEvent extends PartiesEvent, Cancellable { /** * Set the message of the player - * + * * @param message The - * message to set + * message to set */ void setMessage(String message); } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostJoinEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostJoinEvent.java index e9e4dfa2d..b28f6a06c 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostJoinEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostJoinEvent.java @@ -11,7 +11,7 @@ public interface IPlayerPostJoinEvent extends PartiesEvent { /** * Get the player that joined the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -19,7 +19,7 @@ public interface IPlayerPostJoinEvent extends PartiesEvent { /** * Get the party - * + * * @return Returns the {@link Party} */ @NotNull @@ -27,14 +27,14 @@ public interface IPlayerPostJoinEvent extends PartiesEvent { /** * Has been invited? - * + * * @return Returns {@code true} if the player has been invited */ boolean isInvited(); /** * Get the inviter - * + * * @return Returns the {@code UUID} of the inviter, {@code null} if the player joined via join command */ @Nullable diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostLeaveEvent.java index cebcdcbe1..1dce75945 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPostLeaveEvent.java @@ -9,7 +9,7 @@ public interface IPlayerPostLeaveEvent extends PartiesEvent { /** * Get the player that left the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -17,7 +17,7 @@ public interface IPlayerPostLeaveEvent extends PartiesEvent { /** * Get the party - * + * * @return Returns the the {@link Party} */ @NotNull @@ -25,18 +25,18 @@ public interface IPlayerPostLeaveEvent extends PartiesEvent { /** * Has the player been kicked? - * + * * @return Returns {@code true} if the player has been kicked */ boolean isKicked(); /** * Get the kicker - * + * * @return Returns the {@link PartyPlayer} that has kicked the player, returns {@code null} if {@link #isKicked()} returns {@code false} */ @Nullable PartyPlayer getKicker(); - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreJoinEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreJoinEvent.java index a8b30712e..8a862df9d 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreJoinEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreJoinEvent.java @@ -12,7 +12,7 @@ public interface IPlayerPreJoinEvent extends PartiesEvent, Cancellable { /** * Get the player that is joining inside the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -20,7 +20,7 @@ public interface IPlayerPreJoinEvent extends PartiesEvent, Cancellable { /** * Get the party - * + * * @return Returns the {@link Party} */ @NotNull @@ -28,14 +28,14 @@ public interface IPlayerPreJoinEvent extends PartiesEvent, Cancellable { /** * Has been invited? - * + * * @return Returns {@code true} if the player has been invited */ boolean isInvited(); /** * Get the inviter - * + * * @return Returns the {@code UUID} of the inviter, {@code null} if the player joined via join command */ @Nullable diff --git a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreLeaveEvent.java b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreLeaveEvent.java index 4b9fcd609..3b056c6a0 100644 --- a/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreLeaveEvent.java +++ b/api/src/main/java/com/alessiodp/parties/api/events/common/player/IPlayerPreLeaveEvent.java @@ -1,8 +1,8 @@ package com.alessiodp.parties.api.events.common.player; -import com.alessiodp.parties.api.interfaces.Party; import com.alessiodp.parties.api.events.Cancellable; import com.alessiodp.parties.api.events.PartiesEvent; +import com.alessiodp.parties.api.interfaces.Party; import com.alessiodp.parties.api.interfaces.PartyPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -10,7 +10,7 @@ public interface IPlayerPreLeaveEvent extends PartiesEvent, Cancellable { /** * Get the player that is leaveing the party - * + * * @return Returns the {@link PartyPlayer} */ @NotNull @@ -18,7 +18,7 @@ public interface IPlayerPreLeaveEvent extends PartiesEvent, Cancellable { /** * Get the party - * + * * @return Returns the the {@link Party} */ @NotNull @@ -26,18 +26,18 @@ public interface IPlayerPreLeaveEvent extends PartiesEvent, Cancellable { /** * Has the player been kicked? - * + * * @return Returns {@code true} if the player has been kicked */ boolean isKicked(); /** * Get the kicker - * + * * @return Returns the {@link PartyPlayer} that has kicked the player, returns {@code null} if {@link #isKicked()} returns {@code false} */ @Nullable PartyPlayer getKicker(); - + } diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/Color.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/Color.java index 71094e5e6..4e7139869 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/Color.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/Color.java @@ -4,90 +4,84 @@ public interface Color { /** * Set the color name - * - * @param name - * The name of the color + * + * @param name The name of the color */ void setName(String name); /** * Get the color name - * + * * @return Returns the name of the color */ String getName(); /** * Set the color command - * - * @param command - * The command to set + * + * @param command The command to set */ void setCommand(String command); /** * Get the color command - * + * * @return Returns the color command */ String getCommand(); /** * Set the color code - * - * @param code - * The code to set + * + * @param code The code to set */ void setCode(String code); /** * Get the color code - * + * * @return Returns the color code */ String getCode(); /** * Set the dynamic priority - * - * @param priority - * The priority to set + * + * @param priority The priority to set */ void setDynamicPriority(int priority); /** * Get the dynamic priority - * + * * @return Returns the color priority */ int getDynamicPriority(); /** * Set the dynamic members minimum - * - * @param members - * The dynamic members minimum number to set + * + * @param members The dynamic members minimum number to set */ void setDynamicMembers(int members); /** * Get the dynamic members minimum - * + * * @return Returns the dynamic members minimum number */ int getDynamicMembers(); /** * Set the dynamic kills minimum - * - * @param kills - * The dynamic kills minimum number to set + * + * @param kills The dynamic kills minimum number to set */ void setDynamicKills(int kills); /** * Get the dynamic kills minimum - * + * * @return Returns the dynamic kills minimum number */ int getDynamicKills(); diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/HomeLocation.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/HomeLocation.java index 24e41d48b..ffa471009 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/HomeLocation.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/HomeLocation.java @@ -12,8 +12,7 @@ public interface HomeLocation { /** * Set the world name * - * @param world - * The world name to set + * @param world The world name to set */ void setWorld(String world); @@ -27,8 +26,7 @@ public interface HomeLocation { /** * Set the x-coordinate * - * @param x - * The x-coordinate to set + * @param x The x-coordinate to set */ void setX(double x); @@ -42,8 +40,7 @@ public interface HomeLocation { /** * Set the y-coordinate * - * @param y - * The y-coordinate to set + * @param y The y-coordinate to set */ void setY(double y); @@ -57,8 +54,7 @@ public interface HomeLocation { /** * Set the z-coordinate * - * @param z - * The z-coordinate to set + * @param z The z-coordinate to set */ void setZ(double z); @@ -72,8 +68,7 @@ public interface HomeLocation { /** * Set the yaw * - * @param yaw - * The yaw to set + * @param yaw The yaw to set */ void setYaw(float yaw); @@ -87,8 +82,7 @@ public interface HomeLocation { /** * Set the pitch * - * @param pitch - * The pitch to set + * @param pitch The pitch to set */ void setPitch(float pitch); } diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/PartiesAPI.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/PartiesAPI.java index ad81ff9aa..318583238 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/PartiesAPI.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/PartiesAPI.java @@ -1,33 +1,32 @@ package com.alessiodp.parties.api.interfaces; +import com.alessiodp.parties.api.enums.Status; + import java.util.List; import java.util.Set; import java.util.UUID; -import com.alessiodp.parties.api.enums.Status; - public interface PartiesAPI { /* * ############ Parties based ############ */ + /** * Send changes to the database. Used to save parties data. - * - * @param party - * The {@link Party} to save + * + * @param party The {@link Party} to save */ void updateParty(Party party); /** * Send changes to the database. Used to save players data. - * - * @param player - * The {@link PartyPlayer} to save + * + * @param player The {@link PartyPlayer} to save */ void updatePartyPlayer(PartyPlayer player); /** - * Reload Parties configuration + * Reload Parties configuration files */ void reloadParties(); @@ -36,124 +35,105 @@ public interface PartiesAPI { * send the message because Parties gets the placeholder info from the player; * If it's a broadcast unrelated on players, you can insert a {@code null} * player. - * - * @param party - * The {@link Party} where broadcast the message - * @param player - * The {@link PartyPlayer} who sent the message - * @param message - * The message to broadcast + * + * @param party The {@link Party} that will see the message + * @param player The {@link PartyPlayer} who sent the message + * @param message The message to broadcast */ void broadcastPartyMessage(Party party, PartyPlayer player, String message); /** * Get online parties * - * @return Returns the executors of online parties; {@code List} + * @return Returns a list of {@link Party} */ List getOnlineParties(); /* * ############ Player based ############ */ + /** * Get the player by his {@link UUID} - * - * @param uuid - * The {@link UUID} of the player - * + * + * @param uuid The {@link UUID} of the player * @return Returns the {@link PartyPlayer} of the relative player */ PartyPlayer getPartyPlayer(UUID uuid); /** * Add the player into the party - * - * @param player - * The {@link PartyPlayer} to insert - * @param party - * The {@link Party} - * + * + * @param player The {@link PartyPlayer} to insert + * @param party The {@link Party} * @return Returns the result of the method as {@link Status} */ Status addPlayerIntoParty(PartyPlayer player, Party party); /** * Remove the player from the party - * - * @param player - * The {@link PartyPlayer} to remove - * + * + * @param player The {@link PartyPlayer} to remove * @return Returns the result of the method as {@link Status} */ Status removePlayerFromParty(PartyPlayer player); /** - * Get the executors of available ranks - * - * @return Returns the executors of ranks; {@code Set} + * Get the list of available ranks + * + * @return Returns a set of {@link Rank} */ Set getRanks(); /* * ############ Party based ############ */ + /** * Get the party by its name - * - * @param party - * The name of the {@link Party} - * + * + * @param party The name of the {@link Party} * @return Returns the {@link Party} */ Party getParty(String party); /** * Create a party - * - * @param player - * The leader of the party as {@link PartyPlayer} - * @param party - * The party name - * + * + * @param player The leader of the party as {@link PartyPlayer} + * @param party The party name * @return Returns the {@link Status} of the method */ Status createParty(PartyPlayer player, String party); /** * Delete the party - * - * @param party - * The {@link Party} to delete - * + * + * @param party The {@link Party} to delete * @return Returns the {@link Status} of the method */ Status deleteParty(Party party); /** - * Get the online players of the party - * - * @param party - * The {@code Party} - * - * @return Returns the player executors of the party members online, if the party - * doesn't exist returns {@code null}; {@code Set} + * Get a list of online players of the party + * + * @param party The {@code Party} + * @return Returns a list of {@code Set}, if the party + * doesn't exist returns {@code null} */ Set getOnlinePlayers(Party party); /** - * Refresh the online players executors of the party - * - * @param party - * The {@link Party} + * Refresh the online players list of the party + * + * @param party The {@link Party} */ void refreshOnlinePlayers(Party party); /** - * Get the executors of available colors - * - * - * @return Returns the executors of colors; {@code Set} + * Get the list of available colors + * + * @return Returns a set of {@link Color} */ Set getColors(); } diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/Party.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/Party.java index 3adf75e71..7f1226e80 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/Party.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/Party.java @@ -7,151 +7,141 @@ public interface Party { /** * Get the party name - * + * * @return Returns the name of the party */ String getName(); /** * Set the party name - * - * @param name - * The name to set + * + * @param name The name to set */ void setName(String name); /** - * Get the party members executors - * - * @return Returns the members executors of the party + * Get the party members sub + * + * @return Returns the members sub of the party */ List getMembers(); /** - * Set the party members executors - * - * @param members - * The executors composed by members UUIDs + * Set the party members sub + * + * @param members The sub composed by members UUIDs */ void setMembers(List members); /** * Get the party leader - * + * * @return Returns the {@link UUID} of the party leader */ UUID getLeader(); /** * Set the party leader - * - * @param leader - * The {@link UUID} of the leader + * + * @param leader The {@link UUID} of the leader */ void setLeader(UUID leader); /** * Is the party fixed? - * + * * @return Returns if the party is fixed */ boolean isFixed(); /** * Toggle a fixed party - * - * @param fixed - * {@code True} to be fixed + * + * @param fixed {@code True} to be fixed */ void setFixed(boolean fixed); /** * Get the party description - * + * * @return Returns party description */ String getDescription(); /** * Set the party description - * - * @param description - * The description of the party + * + * @param description The description of the party */ void setDescription(String description); /** * Get the Message Of The Day of the party - * + * * @return Returns the MOTD of the party */ String getMotd(); /** * Set the Message Of The Day of the party - * - * @param motd - * The MOTD of the party + * + * @param motd The MOTD of the party */ void setMotd(String motd); /** * Get the home of the party - * + * * @return Returns the {@link HomeLocation} of the party home */ HomeLocation getHome(); /** * Set the home of the party - * - * @param home - * The {@code HomeLocation} of the party home + * + * @param home The {@code HomeLocation} of the party home */ void setHome(HomeLocation home); /** * Get the party color - * + * * @return Returns the {@code Color} of the party */ Color getColor(); /** * Set the party color - * - * @param color - * The {@code Color} of the party + * + * @param color The {@code Color} of the party */ void setColor(Color color); /** * Get the kills number of the party - * + * * @return The number of kills of the party */ int getKills(); /** * Set the number of kills of the party - * - * @param kills - * The number of kills of the party + * + * @param kills The number of kills of the party */ void setKills(int kills); /** * Get the party password - * + * * @return Returns the password of the party, HASHED */ String getPassword(); /** * Set the party password - * - * @param password - * The password of the party, HASHED + * + * @param password The password of the party, HASHED */ void setPassword(String password); @@ -165,8 +155,7 @@ public interface Party { /** * Set the party friendly fire protection * - * @param protection - * True if you want protect the party + * @param protection True if you want protect the party */ void setProtection(boolean protection); @@ -189,8 +178,7 @@ public interface Party { /** * Set the party experience * - * @param experience - * The experience number to set + * @param experience The experience number to set */ void setExperience(double experience); @@ -200,4 +188,25 @@ public interface Party { * @return Returns the calculated level of the party */ int getLevel(); + + /** + * Get the party follow option + * + * @return Returns true if the party have follow option enabled + */ + boolean getFollowEnabled(); + + /** + * Set the party follow option + * + * @param follow True if you want enable follow option + */ + void setFollowEnabled(boolean follow); + + /** + * Check if the party have the follow option enabled + * + * @return Returns true if follow option is enabled + */ + boolean isFollowEnabled(); } diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/PartyPlayer.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/PartyPlayer.java index f5651d9f3..32a0c698f 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/PartyPlayer.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/PartyPlayer.java @@ -6,83 +6,78 @@ public interface PartyPlayer { /** * Get the player {@link UUID} - * + * * @return Returns the {@link UUID} of the player */ UUID getPlayerUUID(); /** * Get the name - * + * * @return Returns the name of the player */ String getName(); /** * Set the name - * - * @param name - * The name to set + * + * @param name The name to set */ void setName(String name); /** * Get the name timestamp - * + * * @return Returns the name timestamp */ long getNameTimestamp(); /** * Set the name timestamp - * - * @param nameTimestamp - * The timestamp to set + * + * @param nameTimestamp The timestamp to set */ void setNameTimestamp(long nameTimestamp); /** * Get the rank level - * + * * @return Returns the rank level */ int getRank(); /** * Set the rank level - * - * @param rank - * The rank level to set + * + * @param rank The rank level to set */ void setRank(int rank); /** * Get the party name - * + * * @return Returns the party name, empty if the player is not in a party */ String getPartyName(); /** * Set the party name - * - * @param partyName - * The party name to set + * + * @param partyName The party name to set */ void setPartyName(String partyName); /** * Is the player a spy? - * + * * @return Returns true if the player is a spy */ boolean isSpy(); /** * Set the player as a spy - * - * @param value - * True to be a spy + * + * @param value True to be a spy */ void setSpy(boolean value); @@ -96,8 +91,7 @@ public interface PartyPlayer { /** * Toggle player mute * - * @param value - * True to mute notifications + * @param value True to mute notifications */ void setMuted(boolean value); } diff --git a/api/src/main/java/com/alessiodp/parties/api/interfaces/Rank.java b/api/src/main/java/com/alessiodp/parties/api/interfaces/Rank.java index d5db295e0..fe050d36a 100644 --- a/api/src/main/java/com/alessiodp/parties/api/interfaces/Rank.java +++ b/api/src/main/java/com/alessiodp/parties/api/interfaces/Rank.java @@ -6,100 +6,92 @@ public interface Rank { /** * Set the configuration name of the rank. This should not be touched. - * - * @param hardname - * The configuration name of the rank + * + * @param hardname The configuration name of the rank */ void setHardName(String hardname); /** * Get the configuration name of the rank This should not be touched. - * + * * @return Returns the configuration name of the rank */ String getHardName(); /** * Set the name of the rank - * - * @param name - * The name of the rank + * + * @param name The name of the rank */ void setName(String name); /** * Get the name of the rank - * + * * @return Returns the name of the rank */ String getName(); /** * Set the chat format of the rank - * - * @param chat - * The chat format of the rank + * + * @param chat The chat format of the rank */ void setChat(String chat); /** * Get the chat format of the rank - * + * * @return Returns the chat format of the rank */ String getChat(); /** * Set the level of the rank - * - * @param level - * The level of the rank + * + * @param level The level of the rank */ void setLevel(int level); /** * Get the level of the rank - * + * * @return Returns the level of the rank */ int getLevel(); /** * Set the rank as default - * - * @param def - * {@code True} to set the rank as the default + * + * @param def {@code True} to set the rank as the default */ void setDefault(boolean def); /** * Get if the rank is default - * + * * @return Returns {@code true} if the rank is the default */ boolean isDefault(); /** - * Set the permissions executors of the rank - * - * @param perm - * The permissions executors of the rank + * Set the permissions sub of the rank + * + * @param perm The permissions sub of the rank */ void setPermissions(List perm); /** - * Get the permissions executors of the rank - * - * @return Returns the permissions executors of the rank + * Get the permissions sub of the rank + * + * @return Returns the permissions sub of the rank */ List getPermissions(); /** * Check if the rank have a permission - * - * @param perm - * The permission to check - * + * + * @param perm The permission to check * @return Returns {@code true} if the rank has that permission */ boolean havePermission(String perm); diff --git a/bukkit/libs/CrackShot-0.98.8.jar b/bukkit/libs/CrackShot-0.98.9.jar similarity index 63% rename from bukkit/libs/CrackShot-0.98.8.jar rename to bukkit/libs/CrackShot-0.98.9.jar index 286bcafc42b81032725664adac0f1b0a2da99a57..ff44a0e73a5e8388ac67433c572c81bbd1305c18 100644 GIT binary patch delta 56954 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%0D-vNWF8jF7Mkw+J{HjC% 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 delta 56905 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

u%o1YUEMt zZ@izimiM>T@k6Zje2|6I+uF*9SReDD)_43c>nA?Uw)x?91s`sAYl7Y8=+`GF7kg1{Gi zVc;izWndp)6b$jJf+hT#U^TxscnH5Pcr0HWJdrO6p2Tm`!YP^u2Wfa37fuDIav_H3 ztA@deVkmE~uNVgF#9`=Se~=M8Rty7N?Jx_TFk&hJr@>lrIH?2)XTl?5xDigB3-=pg zjRi~K1~G#60h{!Mle{xv(husy5#mUYWDE=uBgH6CWE>1KN^=(Z82XFR^dOA)E3^?u zVYw35z+x{gu7oSZ7<0~iE~^t`F@?evafA_KS@bn(8!?(qza!hlf6+#PkCC^o zrDVN0MvIzQA9A-iR*SgUIC7a7uSHyJGC5ZqX9QdKK&269W%J+QZBeI{1XT$g?zLC7 zqlb#)#RQP*Ea)muKtD@e0Y&0O^t077q)|-Nby5F-TrmmTW~)79mY8gEX(lsFUj?iQ zBq*lnT3Pep-{K@Oe-%R3-{3aWYZ>+h$MOiq1JuNqUP}y1jv+q(sct?F}q|T5+m44Kf4Ez!9fo zowEWTfMr~nfqgJdoPqt985gK|qrp4iIBT`SCt%1v7^c`RfBZ-6W~lR20eQstGP0>1 zME?iSGgRHIFMp-Q@Z>voi&Q%lpQQN7IuT9WwMj`+sPzS{^h9xSOh+w_X;lb08nRmz zV$}1Jq91_WaD7=$uV7*Dpk~P0Ppx!Bt-=>W7u{tl*SbL&;oWdVUNp)Jy79fR5Tmle z3bv9xFqZ6vf8Ji7bkZ_M8~^L4L|_jTpjS<8Hs%?kT63{wo_nEfT++7HleD#}m*0eJ z28@3pSx~O>SOg=> zQDJdr8Z$5EFoZ#Nl@}~qYcYtq38u>M!hKrk6^L_MfAL6(pm_&8krU^);*kkZ4q>7GF5hqpv#j%IW2;&NCxG$2wIdxCgB!AS0{t=S_EC2402io zElyTGzeUgu$y5a`f^JNvDrB{8i_n{s{L4 zzw%X3=9FvsNqKF%MhI)K6*?!J(b}u9$Z5A|YM&x~ba;4+@|UL6I?^PTc}%g4bGMqQ zEiWwBOl>BwEykS6OisvopV%U&djzP8)n+cL9kyLiHXP1FRNNd$TITU zf9!~H>mFOj!O7RaG}(PleoQ>sB%Y?ATa)FFr&G8bVWL*j&?=FHFvNHp9W1cAMbn;3 zuAp+iVK_iec}%>ZxCXR<5Griu5iMOKdoYH!@veK0kfcRD5HhCK!+bl%iF!!UvK~^ks)w}G>mh@!>LD}I>yg#69yu-Qp}#eLe;w`@ z5pGovr*%CFTGYdBU5_^D^(aaIENfYmBjpNnvFcy=&TxT;B_yc}zJb+_B#3(9X6KRsY31r@J zH!N@qHp2yOfqz@Iz1zMn+IeGbe(rao1*-+8Bi-P(qTU6PMZaDN0A;baXl`Z(gN=_pes2P*7+(n^`Mq!&Ukz6wfB9d@?}Lr} ze)y0-0Kf4ENfv*IRPw)(q5NSonLk1<-xewoPUi$nomAqx2#QOutgW&9OU&fgSm`A4FHe}67I@NYy%{UZe z^cCNUeqx8{FQqs{=8HkHjTkJuibLfU6fs4eDNa)7h^gv2 zak9EmOjoPKY<0glRXr`vRPTth)MsLj`c<55<%)Bx0&%W&h?r*$5_7C0#Dzw4;&-Ug zylO&o;z$ETiFWY{IYuieqe}x;rd__~M5c9!9BVWuI^&+Ge+)PsW(nVwWA!x_&OD>de$`iF71i1}~#zd_LLDtAS1{AtYG_zNSHl1~3;o(L0hMyLPQgkLuxc1s z&PHSCsm5;>w3nypT-aP_BTtuSKwEYZ$2mAEFt4oQ5^}T9x9rXe23G2N^JlfuflXh4TG}G7|q^LZ5;dOvU1;Y9J!F zazgTGe^xWjlal{IHX2+G-whL^#d{C~iU8PIAvZg#YfdwChl>9}hL}gX0!YqoSQP&^ zVmBj)|*!7-_3k2KnEusF54|uk*T^b{&kaF zBw+lS_zf9jjtayAP~sBE6qh2?d^xlg3!zqA0Yk)fFbsc3itAHM@r;TSLtHl3A_>$6 zNQTMla6wXYlR^U710x9#xmaG``kI6F36i$L8nUVTqlsRjZx3)Ud;>h9LW)wtRUfCpX*BT+1vpCb_ zTr1Q0e|ble|5q)78j?XRKrx%qO|l-0CcM+aN2dA@XJjyX8#t#_NtYe=%W^P7pxvnnnUruqA)LOYM;Eqyu#c&mhL-Dix&>A_ONp1a)|f?BEtNOCixzNXkMk8hwwR)K+kSo zll%x{+w~CE(t}J-4Z;Z^R5td*Jjmk;4RXxK$M}(giHzT;UIcxPnB!?Rf6E(O9*N1% zwdlmbYJ7zgMSi^+Y;=EzutEN_&Rjpq!GwIyI{AGxH`&%))7GT+b5~8c#LZADZh?N{ zRv0dBgHhskm?7?fGsK;6p12#X6iZ>bxCfpR%iw*n9DWfiNQPKRI*V20P;oDrC{~m6 zMI*URJV0(250bmYL*yy(e>d`qc$jPxkB|?VAMdW+B4AjJPih%eYge+2!fi?7&u;#+p1 z_$ON+9%hThc6PV;H+w|<#GVm9v&~`$`&j(Rz88Dg9fAm7QUjc@e(d*$hMX

54L7(EENP>%c=R|0w2L2$6~Yr`f&k?|{Lk3fNvh#B(u2*_4SSy(^c zSeTcGvM~>n5?yV~F-H@$DQzZGy%Pkv#A6~fd%!29auNW;koDLH1B?NHf3rOx*j^ax zon>e{2qk}=f8I~V{KF5EWrFQ0*OwRnFH^@^EX}~;&t9y6=DThgX$}&I#}5C`a`ZCN zYOmU_bT=f0Km}WKJ@i!M zdL#yqtBR@6$cR>d0|ft#RAr<(tTK|9e{hmoQen(0YcquOPm{_`>H*C$ z*Fb-WgjLvA7WyI))TA8DwE9_v+sP}{o0O|970ResPYcacW4$1fR0umg5?47j(x*v@Ph{9eMfR^37Uhv9)t0~kxtitr{t#|L z)rn20e~QOc#TuMi*TGG2t7_+Swa0>k-5&%YLlBagP$;vYyUa#dnFkYO0h}uf;R@-( zb+QfIA&cQYSprYWQg~HXz<078{2|*DE<2DC*^vy8oyaKJg&Zv-h6|pKARWgsP9DiP zE|j)^D#&Qn!JJojhb$uqU~mN-raG!l=(-7*f9kBdAfdbidit*0aeh=OeIm_av>~mG zlt8U7M9{o+E!cZ-d9z(@nxT(pn?t^?0fwqVr)swcXP$C*LJiH>3uk#Jb2~BZrK(zW z^$-M`=Upo%N4aWa0~DuPLQ332UDyc9RjfuUt?A=5*J@#YE@^s>FyHi?Yx~S&hMTcb zf87I-RLPy4klYy~TdG@%;O-eWgVn@TkM*ioG}FyM#!2<*o#kc-uiCdIJe|@ zp|0cI1#=xIyj~sNq>eE6v8tk(e^vb>e-qV@Tf^J8N6)&eNfC~iukC{~!^K(G9XiM! zP$hf9XxR(uWGzgV2g8-JH(V{FaI5SKOJzT3l>OleIRIXgL*NzseNzsD_vGR5r5p}F z%Ol`-c_cK;kt9PNMT+EDQYMckLuF4gT8=lfFb27LOcS&4DAL6fOp&9^hD^0fe~t2P z&Xc3)7^5|z{YK-)D2(eU&~{!rkSe89STGuXS7Y^@gF5&@9gU$Ga4TG)#;IdKU*@?; z9jnGe7Owlb>Ns>|!xM0_s#C{94!jA&)dbw6!|)~aQCce@4}OL&>O?gW98v}yjbJ5l zuJ4CU!gZ?W`P&dEI~3>c9&H;3f47Qa2>D3b+X9$xA}6ss4fJg7w2TnnF8o-RL*9Rg zrPO3fxwq5&OD75a7a0#W0)$R~T}KL+vZ-vEzX<0e(Lj zj_m}N?`!r}U;!y=u>vRH3OoT<;6z-3lW+x2!4-HCuE43d0#C*jI2~8u3|xUT;ZZpY zUX*iT3;wkq)T!Ckr6_^E&!VI$lv*C4r1?IwM{t67kc7Fxtkz#)ZW+YbNe|CQb=9v}v>3>*( zng{w1YcLU|#VWj{#VXuiy#Kfk_n-OxS7NKWQVgBR&h|A>u0V#ZCxE@AD&=YlPqPr1 zdPzW}g{V`KAu>J9ik70IM4H(xB}c987A}mYn-*24rCe#LO3`Eurbj!YrJyJga#qTf z@br+m$uybiA?GC1e`KYH%u9x3AJC9wPI{UYeVN?!u1XPag)6Hf+LT0oEz$#R-yp}_ zJ+E@|N@D85s8i+LyiyBXCr@1#`+ zq|E=i$$aJbU$+>3*Vq3jOfxH~v^gk;$H*3}%N_AMO2+I;e`++gEFP^@6yM52%P=kO z=&l7{RW0p=sXG%S@9s4F41vvXm>USIdwgpg=v;2BZgh8KL+gCZO%gAkm8tn?sme`S zli{yY+?$p{@Kt|V&&IUa8B2}bf$aUHNh#s}wChQF{EyOV{lSFc5cQxLmgBwI!B;PZ zp-x@{^8eZzf4gs{y%G9i(nw7GE$X^1>$((FiS8PgqqDq3@3U#KGcYs%=27}Eui4-D zX<6GPdJ?sD3&Lux>FfN|8a{5O(TRUOWA=Ml=&zGFB7R*cHCpN&H#dDXrAUN}($mCO zt%~(&lfF{cCDW9ohcqQaO4CC&Bty#5%Q+`mPI)?Ye@L<5Q;}ZllzVjT(#v@|+0yoI z`?##Sz0c`%a64><-fjnGY(_Uib+luviMBd1(Vj`0Xlcbfo2bD4Rzot2=hNmlF4{(? zT>~z=qQ6{rt#9B}xmvKP@83<=)2c*It6R)!&ehH(#_7|cj;RyvMJ==Lq{}OD+G(v1 ze@*D`e~y}DcG5eV^e%lrIi{V{Lq1G~bV(2SIAs{JtKz0Y5_YB%@jguy zU0dl?E`<^LRe~zRc={I41JNqCY73P5FLp$$f08lWDxc}BayT-b>(%GD#NtN1t8{ah zY*7EG(;e$%tW)1cBT1QZ#FL+6AAMJw;bj-C*3TWd)hQO5@k{5Nu-|-AS}1<8R-vZS zLt^}!+A7b>N=I-x2j;&gMYh*Rwr ze>jDXa*ABn3F9{ER5&Gt<%MmWGDo_B!j5jf)7k0bc37u=bh4eUGYz#-KLw_EOnrB~ zIaN7b8=#}UKItOP_f0_MqtlprYJi|8t7kL({^)_bX;Z-aly+X~7 zX`Z}~_LUFPiSl83fqaxMlxygNaxHyGK0&w282weQqrb@wbfV zDj;X6pq#Bj@&c75?^4Q-2z*oKkC!+G(_MdRxb-UFgatW35As zo#h;Is?}cYHd;AXS^;w@ButiAU~H@8k$ctmYL6HN4tYUsReQ~;f5m5Nt=ea_a`Mzg zs#%{}u&q#Gfu*%=pXBeEOC~OVhd*VmmK5>re1%2D1ZX2HewD?vevYW%r(0T6r&RRg z<1C@iG{mtyYDukaBhKXImeN`|;u!6XA+tF3$BXDb&&Bi2LkwG~EJwe=``ZfV;uU9IQg zIm^MEyV(VBx|NT9-R&cxkELzD^srBWE+hkCZ%zE9#Vge+e}pPOY!cL%la}+LS2Jk< zN8`todkwxe2HB7}4#0f&!C8u*tidH*!1Q&B&ZMGEkD^GA>R_j+w)kkdfn5-!c0~YV zK%BoPZA_VjwAIM}kZmGEqYt9hL0HPsPBY{{`~Ptso~{cm>arUK*H&wdq8dVWLRJ^B zRbU^sL0f|vtKXE_1%J8w;Ao=MKQLLzPN>)i1(;1pr_pG8FZA?~xxS?m`G2WUToXnM zOspcSjj!c0+1GN(H~X1YT!$>lI;%90)K*D(kqjq9ru8^v;jd#ok)oNBpU_Onx7v!+ zG(muTbLdC0vN2wo}a^0J^NsM)(tg9Gu-+;D0H7jy~^IBIAC@Ggg^O4}^^CA*(9Y z;+wzIYTJf0^}|u-$(PQ$!+ehfJJDoSntRFG*Q(YJx}+9ibxSf*qRO+UA*(kgSkH9X zh1KIgvWrv(K7U*1vA}4p#NFA= z^ROyn19V!$eSCq=BRqWJ8CrE5NAq(s0Wz$S2F(Vlh%q&~rZQ}eHYNAcC5_P{0Q4GX zE&^$-@L-kem`Ybxg{@=5)^SPX!D<~{6pc*oUeqF@T>Xg57JoBqd)GtADNWSe(^g7Wbd8^mKV#Bi zsuaVhSiR92`jvZ;%tSRZs?-?Ox>gggR{moyN43f^UXNO>c9h`(#PND0O5**}q7zc8 z=M>gMTa0J~Bsd&eB&1_=CxbKQ^;mube69s7AL(|!s}-g?C9}>z(>o0V^cucL4+r<1{%R;`HFt1IP36my!xduG=bg@&s6n~D_FgdY-1aQulY=)t3NeccnxKs!82cxBK z>1ODN2-+=0)Od29b>?YT;T$b?%BIzpJLOvZC!BIDb%Qkrch}Ui-RuNqbi_LA>}UxV zJu$KImUuwBBxcRSQt;=3TA_a~&bqxGx*AuXGDj>bESr6Ot~M-AdnXt;-U9(UOW=3sWxFd2Gp*2(xV`sHcY$aB`enr_3#N zEH{i4G1JLkXI{UedYgo;cSyDM zE}3k-N2XdIkeSwpWRCR_x!(GiY_L8dpIM)iudFXsxxR^&P$5 z`X{~B`hnhN{Y3A#ex_@!U+6Q|uXLOB8-3IIlfGl^q~BY+=yq#2{n^?>e}A|3vXHfp zWm(Ov#0FMw6V}J3te-8|K-*%6+cukN2iP1t$j-Mj*nB&aU1jI6$Lw78tewxEvt72u zE@p4pCG0c1lN{(OtH_NEt!3~%(u^w{p>mN zFng|?YR{7w+vmy4?DOSK_672G`$DTKVry4g3W-uBJvDEk(5w0)bJWjCl*_FZagV1jxVe?JLKR9^=ssow&V z)y}|477a|bvI8euC4uQiTki+xp}EM!4VBV3Cu)`YZylk_y4Jc5InnNFyFphRE>_E} z#Rdysq3W&c5!p((QGYGAZZKH*K{eM}VzBUws?H!n8$MS9tQ*Y@m7S`C!OTGtRzZV5 zL!?^%Y~5tA@MO8sy4h&!O_dw0TQFW0nTagKt=gagnIj)EXg7ykFPB)i>ElYWK~A-9 zH#by1lLM_gwCVso7s{-9jOWm`=xWe+Rp>ingmtI!`(E_4?tem8KHV<5TX&F8JS@%M^_2kL5{LkXnf2o zNIPq#!N;RukwMwTVj+yNRv8?<3VK-g>Ui>EvfSX=VtEq`vsPnImB=-?HnXfo4Bd>Z z!hQPwihK=G!+-ty{)*g7+9C>g07_H=QPzW4ZmH@9ZLNn8Gnc7V2*+0I6zUTgZ18Nk z`Wm7J&$d;+L8bLK#IqG~JnNN;c(%k3n*8 z*dQ|>uX!*|nWut=A*Ss_hL}@eeJ5eOadlPt!Gjr|&41EeI8PAxDs4S9XAk5XBc>IY zgUEL1UPQ#kwrP;;hEcE=x_Q`8dsUf$91IxLC9^P4(Iul9Cv5S5u2w<|(8rB?us6bA*jOQ7))4CbjlAMS4s$8oTbK!x*i5sj(wEl+W%5~Nnho@~( z0iCZCNC=*juk;RvY=FS&paN$>R$va41pz)( zFl1sC0p_Rk98ab|zC3-dn{D{fNKCHR2O=e&;r14c%2P>3CFn6K8@wQ#RXvC> z8mWh#3g$gIjLjpU#uFgcR%CWOIgY+UsS9zvR=-|XSzNWw+E$&`z7)Yxuq$K+4}XSS z{4EUjPCoGrZlYbT)z)v9OA4??x?QfSL#ocO=(nwRTC4Vw-k67O*OIE3_3p^Z2>yJ) zG~cgXAA2tUJ@LfD1>SoQI=spHjKZku%?L}Y5p{g2jlAR9*3UPsxBd~czB4Cb<{c1L z6Jvd~wbvG@5ueAb?~|UcXtK65NPmuQ6lWU*`-2D`0$ITU;06am+u$JR7#s{$!J*JM zco+-_4ufIA!{PYgaF`Js0rP`LzzxBXrk4)!+L!31CAgFQqE%kuS~JoV`ob~D7i#8KDTYv1QM}NiCdVV~Qt$+D*Wc-nb z{dM9UT0{DAIJMfBhn?Vm_+*%CSd(~@T{a@hl<_y&wQ>DyZNfD1D!cwDtZ&|~>A10t z`>vOpCqqLLo^;MkI;SU{(~{1~zB5Tr$3h+s!dM)HqahR=2YJC`a3GF_(qJ8Q2p$hL z!3i)Zcmhleo(NNd6XA6HJ%1O!F9}Y8YlA1lZNcfVJU9a$3eJRe!P)R!@YIySc|I{X z&*R|iHiNU#ADj-b)KE|cgJ6Vtxtzm9C^RpZi^R+2CX94TgvAGLI*4Yhym_?H+Uakl zNZ)+3)|stB;;)v6^wre^CCl@)nd2cw9=yledq6wZq{tWAF2XsnuYbwr1k6&i6|R|4 z)d?Fw)vTtqD7B$=Xxj5F`WYo#nc0$nyyIOSwk`iGIO6F!MA3ySZ8-= zvODY7fMa&mW*Dr0!gg0rGgj9v%*H1_JTt{9fp+)!M-?`}uF-wbWFO>TOqiDV{A)X% zcJHK6H>sa%N3}sn^E%N8?H#uJMUvlDuEO$?6yO?U(jj;SQh+Ow0xZJWauv>&tC0d+ zhopEh^ax%Ly?=r?z`)=V7!|w`#s_c0S#vX79=rvv!LVC`4RCkxPFNGX3pNMuh1Y_s z;get^{4;nT>&QjH zrsSqhE>38$UW~Kw5Ob5^JfCuOB;)M?`l$oxL5`#~_J2TZ$v_xkjzV#Ng`T+iYYo;l z;Mjxg3iSH~y4!=zbGjYjSaYXAQ!nd0Gl?hAd*GtTW;m}hQtj{0TRe&}vB{o7V68oU zHT2LC#WLvPWqT@Si_==`+=T5j)~jA&`>c#6dydeCLhW~WVt zKXhFX<>nPMtOdr?wWvlKwO z=ox$wdIvW{|KKYyJoqY%32wy+_y(L8+y>VN--MfkZ{Y-d4^{*}fJcHK!usGxurc@< zycGN#UJrf&?+3qxPlI2Yw6~MpDRAVp( zPJi?HhDRXF=Nn#!o`xK9cpp*jZ-#8@$$_lkUg&Qu>Fq#Nilne##x7{H7a_GFjEO5* z_HYf~5Q*;d`R>aw2fbZxu1da1^puC;Mj5aDJT1T@8yldDenY7WM@he#B$9`P!joAF z|IH+whyU(C{IMbQ`q(ciU%L~*+f1;2w|^+ky>#+FH1}e;NU$&uM1x%sC3a0b9^}PI zFc;p)9%kNn_#Vm14-gLi2$A4VNKSr+LxR5`Dftyg@^@q^{(xD*oyb(|LZ)IjTpiqp zOhq%?i&Wsr5Q7&(!i?JChWFZ>*qk;e0NZAJfpr~@S{T+EgOUtKqTav%c?gnr{eNbP zfP0Y`Tw)P_tg`inHQqzmJ-YA2EsnrW+zD8M}QcwFZRn~M!U8|5Wh6)Z*R+3>`( zD)m!%xB*SkzpaeYAJNh`PWDUU4<;ou)Z;aw5ek#uUdhHk*{h|xCqeaj1q; z`znL@Jf0uNzS6UJsYNwyh<*lxz~lbtE6hbRLesQfJ5H%)3C-&e$&>w$?g`zMv)PEOF2ps~aga*K+ zp@DE+XmAS4yExICi~ZhIaHRn!6dX9u^ee-D&9JYw)+gUp^1~*1?Oe|5$?8tHI6tl01VvO2=ejuQyUX|)^(V%O^Ph&%FkaevM zG{XJ*c9*xPm%2f2{BG6xpWxd1ea^)7F!NzA_V0nQ8vpqWp&B5p?{+1=kvfF!8y?be zyk`l_%`fActaCp&{?LYr8*+GqpTPDa={VtN&@;KAu;(H%{(r0!aO5h_dPAz`LpWHM zzz%Y-y##iWj{28Wl3wQ9BRzAV7)N&)6on3lcA?=A35|ebLPx;l(2+1JGzu;XjfP7? zW8sR>(Xco)4(L>mlSyT0 z3h5P^O8SIOCV#_1Gs&pXEOJ8VG&2?NKn4VdKf#tvijy`nDK5-Hmq*%)$WZ$xb91X5 z>1U2E1mdxt=IBDgF(hD)E)=p>I}8c5;3D|SzS*b`UIL#Ri_QU@_8rV&LJ&5>So;?J z2pYT#eeGNI4KLCMGHI24n=k4b1)2L`6p~3#5Fawvv3~}7SDbtly&>I_kmUkysM&Nc z4DhwAc7mI44_5Y)EZj+CtvuMLEstRRGO>&W`@ewb&mr5j>!KMOYeTFS(Zwh?!wJ?z z16nP(lV*Gj^JCvmpwbPv+`NFJv>`$JPGiHbO_i}Rm>zVG*7OY$C+LKhH?K+VupTX* z3#Fm6p?_!S9OxZ77wSUukb;~CXQSWz(1j^ND&&=zljF(YHeFe%0ouQA@7y_kL|Aam0~T zk3wAT8PGiwS^(vtOHy|AibOwF*!m<&_hSW8O|Ks-c!l4O6{gR0KUSDN6F|g=;v>I4 zZ($#5iEaP=Pp0@?a?j3lkvA)>)LCJ4o?0*>S3+TE5l)AzpkL@}Q{@x9LK0Q(pBVc7 ziGQK*pBVc7iJ|YG82bK+q3`bxeIax(DAh8Mp_l?j$>V?UP??3lUhmWoi3_ z{ZNWn30bN1z=xB~Z=rROa-T2#-k|+xa^p$Yy|dRINcYZuJSp=}*S)i2$&kSQ2WE?| zwkyN-db7277k0vAHAXTzX?FY+0`6xI#eZ!F;|}B54h}gXC$Oqz%Ts8GX8<(A&8Um! zY^=>@wONgHyqn`>)#z6^{5{KlDw^x&`Zs#QZg`_wMr~G`=Z0m?dV5oCUL$n%ElztE zf}K3A=VU)0SDdq7OkQRt&8*gGB+s~EbEP?&uN`4~i`m3*V|+Q9uOCJ;p0CC|Uw_k{ zj_3J?@wCGBo0v9#z5RBypb@%93sWy7>%7yhB-`($)L?E^ll=jKDr4EyEoiboWC$RS zix#?JZ5ZnDdKlyuK5Ktk4>@k(Ci_#~WPh#=XjEz6zx%#_N8hhK`%LKjZ9QaY-*202 zD2zd(W`C`{y~+Mf2X=}#PzNFt{jB|GJ%R;Hzsu#D>_40A zJ=8piljrKk)ik+q3wcw3;cr-YHFw>@a6q;)EvNSb6J)gx(#(Tfm|5jnXtr^Z8G&9P zP*>>|t_y@5JMA25p+g+U$y>f}U?Zd%fXz+s@<3Li%NJ%5C(FrRzV|-FGJllJCTEj* zw21sjej|Uxt-ulqgOH>whLX_raB%1b7!z6ovqLu`Lva(_6S^6iLbt#>pFhZGt0>a` zW_MrPUh)!_-b?ZVN(m6Upnvp;(gYL{R74Q5QpAFSg4hMTpi(U4R8&BC5K)Q+JsT?O zc~&fEJ=>{R0P}y}YMO!)>Rw^L`nvE>b)WF9`i5{oeM>A< z|1KV@zAg4q-w_9>?}{g@`^5?PdxrXuI9>fjoT+{)E>l;Ft5i=HbI8MG0U8z81ZY%T z6QEIXO@KzlHL`_QC4cBDPLpkpMo$t?h{!U&5!Jl=G zT8Ak^5_#qqAA%UKP73o1ticI*=@4WRv3-Z2D~^!1>NjkWZc<mf9#FZB7ZlPn;oe?g}3pD2A> zv}(DH02#4bF2Ns1dM^(-$n8b&#!LF+StVjt?ttey@)Sn35>u+*fT4a1rRsOkS^XY* zs6W66^(Q!8{Ta?w55RfquMzkEnIVfXQ;Nx*5VlL9g@4>x?h+=Z6b{0OhWN#0a@RUE z#yt?q6NEMBmAVbjIC3xUiz#iS<~F&HCu~)edU2=ma;~|(Fk)atiF|h;kpn4f^AZ`! zQHSnI{NxijrjrK}rjr6c@W;vC)RL|`@?ifkO^4(^zDXXM6*g@Xw$v(kAy-7Q5~Smm zP@ayLdVeC@8faf4dJh^wbkrAEv+~KgLC1K5Rw2O&)CN5^atDf*&_<~5uSf+rxFUxj zt{w(U{R5h43|eXew9!Opr%6z(C19|YgtIgmZqpRFS5x6W&48Vn39o7ve6HE>tLDH# zEx}@1QBK#0csdZp;<$3-@X2uo@_3Gwn!x9rM}NgJ4uh+U30h#1cZ;PaPlBq5sR|05NkSy1$*!8X~c0|rl4s-}* zY8CWEE>Efz?;uaf2DL1`Z0@|mrF>Q-_MwXPOefRY8dl;W`!SWlCVBe(fi6?0xa5pC ztRr7Q`z4;YU(&AR$QStsR3TCng5H-L*?-%l-n02ZB|JdM5O#Sc82TOxcbJk^?}7HN z%2)em;v(fO6Yk8P zaCR^^;YRSBYh5ENFTwGpURBT}IJ-2rRs9OShd*nG91y&M82eq^tNY>K@N>9lSAQZN z1+4)HT0=0jM!07iLo2Nbbk&-{7_B+nq_uztw3hIU)(T$HO5klR1Mh34uwOeCKGQnF zzqL;Ai`JQyXkA!)tsCp2b!UUMo@}<(i_O>ivHP{-*n?VswnH1hUe*S(&$L18H*K(> zXhVeh+Hj$ZcA{{CHbNMrjTDAzqkn|)+F0Qm=^4RVVYl=UJ$0r zH*xdutvlVQzdg;s$F^3h@%BS zaqEQU>r*R9Y&7HCCErQhGJkTM=2canogj!QVnp(Dp7oy4Y*WaAuH zp4w5C6w4A-Fx*Y06CKOrw2Qm|pepE#Vr*g)m)=UEa)VS$Zum_Bt%h^vdPn>^PkZvSR4QiulddgV-D_dr`jl4pRbO@`Lm6hw|^ z!(?qL%+}6<1==)NsGSQpYtvziHUqZe`Q6$qcvrgse%3C68h`B)CTnw8p*EK_(dMx> z+GVU^1FLwohBa-qV({1KJIOsof|PYc~n~ zwVQ>LwcCVI+A?8`c9(FLcDHb`wo14`TP{azpn7syjiU6-Q@)Q*34KbL*tbzFzT(0_}uKcE*M>L8qO2s*L`f4~*o z4IJ4wrVyIcnCI+XgG532C>_2pl|Inz#8e(8(aMx;{#0e$eb%PP@r9wF;IKaU2}p=ZAjt`@Fd7 zi``^|B{(Sle0h_O1#IDpYWsCK>IrAY~5^kI&;eWU=sYS!CyOcb zSmNPwnc#I8%BAgBL1+4r&MZrLYk$an8&Xl<29)dDd&(k$^eQ-wulU}VIOxM@PMj6Bx(@$BA77r2LSE~V0Ntmv(D?Dr+`zaZEaXzj-$$-Dlnrx^7%Nl9g~Dlq7*uOW)L zQmj^wIPVb)dc!FAKFbvQ)z$kqquKgw$uRjK7>sdr9TVbxg4d(0BuvmWrR_IT{9e?_cTtauaGt?g6 z$ybk_c&ER%7A)dU8zR!k`P^wk!c`IFr+EbJ*>H^Cnv3V2;cWF{(EZjOAaR|6=eg7t z;)h{?N4C-wD9Qh+LFnSFBxk_54gj&jv+|xg^zx76v&p>OuOur!$4%?qvGszwd?g%1 zr>G!OaV9JL)eDL!k$L)m9ijHSrVS)_@h_Y;n%*Z~6dHMkSvp;nX>x;J_nzeIqYD?;p?Wm`Npxh?Um zkJCJ?gND?8nt!HYH6lAVk(Kv{o}DsfeP~k}<^XC~nwR}29a{q_H!+-4gh^kUKO#dj zC*^{{^tU0dzXOf*ccHnyANuJZAr1Z*x63EEUH*w%AEAR8d78;Xjp*ZJ>D1R61 zEKgB)aUiDoe$=h9fp>KQ4?GZCNF7Nnhrl)1m4EQx{xtXx-pyT$OI!&#ShEr`p2MU3 zqsJ2XferrPL39I8G?d9rlt;h+0MbpSP^>fz0g8+mG&YjZ!bm}HLxui^2B#T1oMRX; z-7sOMVZjAP0bFdP;WDETmKsHHyHO8T87{0h>ceKEaV`=8vf)H$efllHW*=x%@UX8s zX@3kOeV_Jo5T765dgjZZyZj43w+ad)QH@1}&kav@_5`91za!G_gJSY0$xr#d z>_K9l2^On?N6zIR^X~e6WJPIiZ8*I(T7Q6Gv;x^^3zks=g+>OBH9A0yN)1k;SpFxTh`^NntBjnN(MFv?-I(E}be`b6RjHim1lF{HN}{jehe9+hw6!EY9v zj*2I>#xHj`35$eo#mwgMt>ik z$3)A2L`=4`IPD}@#;I4JT8UFQTUJpjVKko5IWZnZEu_H&?_3+97`|Us&i-_a8*>!P zKWKpzT5;SMH}5C~fq6$Q^-=dZIXcZYCqH3mXIV-TEd42DyUA#j#46mB$z z!EMHHSZj=c`>@}`#;Azv^&{bgKYt>{lp>t)hOpR|e)_=_4%8By1wEB|6t%@CcOW@H z+MYH_VF8l7$9e|?d=@_W?En1aKlE&j;O@6?u4r@Zk;ohwDeqwj0d0Ejm6r{{lBhiZhR! z;fitP$sJ`0k%X9bZZaM3=tbt?VKX}bmUsh*0>^_6q2`!prO(wjF>tTQY7W3 za#Akj)Qx)H`KXf7sq+r5T9l#}y0U{X6IWd+Q|j;(LRuv7w@f3l@8&4ItChaQh$lS1{kk%; zcDj3#V78Fo@P9qT=;#n$-H&pWoKq8StX%bWk*m5&wK7%&@-RlZM;R}Gt2HtUCRHmF zsL4|UlzYWUb$@TCOeA}NR;^6pDfB|yDc-MFD`!#)OIJhUFg0%;qUC<`YoRES5-|Dc z@s;VhD;7<1aoSi3t;kYv4>YEHE>1B%%2CeCX}QeaRnV800!f>cZ_%oRV*{sayOC?B zt!(VC{?D0{u=5c^aI1uJ{Lo?@q(9Ag?P}T|qxNSqEmU3~dg2X6n zUE&p15(e-bGI6Lc6f2iO&qtW)Om?0??d;0EP#Y+39O*vb|0^O0Yo4LzAK z)cia>98ZfJhVCGiIRwXXxxvKqHSlI6OIPjAB#}y|Cz#_Y^8jM)1OxHKmC99h;HOV; zK8WR;i1=v%XG_OmYvCqk(K;AL=SWGE@nyw5(A}35kL7x!AizD}!%$fq;e^S8PR^e0;vU*`*~!_ zppDP@dtAQo2lVu_$57yZQ&^DFQo7F#yn{QE>WR+knj%Yk8cQh=kS^oUXyTg9J6N zLp>+dL0uUf`I0MFc_Am1RjO90nKG31T>mR=+y)=IiE3eqz#VDa z_&Truai z-%P_$vk*p`MR2-V56(1QIM1vPvwzG6FxzYhi_Au_+-w5(n$6$=vpGCwwt$^xD|pdt z4g1VC@PXM54w=P_nH_R*N%_eQl*bSp`oj*6OavGW>y^!18#)`V=b9Y}mctAVEHQWh zPEocX0L9@ks8F(85B4IIDO>TJ7njr#5@o_+DDz& zUPIZYRM&wLo*)>*-wK?#$Gt^IqWkzZWk)6S%y8Xj7h3&Y%2R|A+Lcx-&yW(dDK?(V zm4&rv!k_135H!>Zl{Y(sY?eU-vn#YPyF(wd90r&@V7S>kqV1{(H&6x6*xz{8n*sie zwSZ#f1?5Fw+m!^wsl!RUWPi#_%FA^~^z9(YnaS(%jb0g^K@g|xyxtCYWtXxqtGt=1 zR^CS7XHF%YO)vj$6->mA@A0a&$_JG&0{iZ-DD@JdO9=PKXJxj=*v;2go1T< zAGT=rG>{HKNkaTx&(9G5qIrn1>)vD$YdoRD>kH z;9#Nf?o~i#VCDqbEPq=12Z1t+9*`u3NtI7QKChKT$vg!da{@FnPlZ2))eH z;W%>=oNS%}XPA>=ra1*JGN(rH@x|dJU5u0T6;4tk80&*mC+N$!od{=u9ib)$hz==@ z_`dob_YYIPR{mATuDQr(^owyOzTwc-+@Gdz5VYv0TKTsRU4Q(OeykPGXwJYLaUP`2 znb6Lh6_El$Qz8`OYyXs!0@~rr{Hz?PW2K&>bXwT{0-yT}$L5|nhYr2B`6c%@&*I_l zyQNbqVLP>khgWwor@}+TN@bYK2H*T3;bBSY=wag6cI6O)erA_+3Yq4%Dt{pQ4wIh5 zy`(4ctjbox1b^BqJu{rm=#mL)fznW3s2vGK2a((4+B3ZD#^_yKNzAH36*LOIfC59s zOtthif>!MHOjeEOrjn;lGcN(fyc7z}+0en91D(yexP|5+O1}(FGB1ZQ<`sz2uR>J5 z0IoByhMUc6;7)T9JYrspsQfy}nv3BD^LlvMTne9?H-ASokza&M@r4vqDL+YPcuZ>U zZ?ko(f?S}8{qIs$ZuvVCu2D6vBAX4fR9!Xv=z}&8SN?$GsSYLbX;l9FOv2O3AqT0y z>*MHO2}i4@YSpp8H~9;^r6jA`c?+!Ce1TOvx4^gIVS0FY?kLNu*2`a3Z1!$Z6H+g2Y!XePqwvY7HSbMROUh)^c2}6}Xr0fMWA6&=uvI ze&$LTXx;_G%)4Q{xf=KM8klOXg*oOuaJ_ji+-TkhtIc(Ak68tq%?Bf^v?W}nEx1Z9 zu2L~vuh!?Q)D!kf?NQm!pl8)a zRUnljGZcUB$Py81(?Bd%n@7dsO=?SIlVUq!YhVy1kEIg6seNRY>|UNaVvsiBAni!t zrhoo)P!bu@7pp0|ECsEi%uo5|$?=X0&uS^@X8oLIQ=Rw|!HB%&rmEErct!PfM%8L3 z!V4(bt7T)uk>j4g&fWH^)p7yGZdZGcD{)hqt!m$LHHTMJzw!!$rEmwV4B|LF%aHj9 zlF&z?)Z75&=0>ClkHJ`TGhAVAfh)~zNPj-7VX3(t?l7N#yUZuyRdY9dWIhF7m`}6j z<}<9=+{1d9&#~jp7ud<>i)^y_5{Isv$Q;V1glycD(6eJo=o&PI%Y>8+VzAoJ%X7oZ z)Z;h>DrfD~{ycy7$;?s*@XV$Q;Y0QK_~*!++=Y@S#UiHQBe+^U0iiX8_~tTopnp0D zWYz=Ps)O;I!cL|dG3pRdIgB1paZD|cHVxze+JdYbY0|#979HlU*D`IGuYqB{4h7~u$e3?H z7xPVI+W(FW``a+V{0B@j-+>Fwci}SgJ-EvJAi^ju2yw##oW+s2dIc~{9mR1&20E*w zIScR-rD3d1mp?%k z_fyc!e?pP@88kG%gyYSxV1J1DHPYtqkT(B-V%EQLpZ*N1%mXN1{Q~!yzr!x`AiQZF zf_Kfsu-~kKuPj_PD-p>X$HG0ya8+k=_Vpa|!|GRfq7au@VdXK`<< zHzA{5z`d>Bh1TkY@q>N}=+>YdqPo&Q9|9fsOWT;|kO!>};fAJSSAT^pA$*rcNVrJ# zt3@Za;Jx+ngZFP!FY$1^vR$1sZmT+PCxU);e4hZDpt2ImkO*Gps8>o)!ad`}P3nS? zS#=Rl=O;ZW^dBcm+tej^>V~mMAn0^fy$zS2LIde&cfzd{uf%m=NDpGW5-wr%czJ3g zA6s*io7Cmi>YajDK7SS$Hmk1oyhhS)Ds--jyD6z7uA-Nd98q{yh@0AdUg9EG7ELu5 zP!jLvRT05%$voE-l=OVvEJx_~BD&@;QRF6z{W7BJ{aN*|)#`f0^+~B(-9V|OII^!+ zH&cn~Otrd&x@9RNk{TRU(~%Y&JwZpLrajx0!+gDlYedqf8-Lza*YFEt82mkzfc7q- z_f&}%c}*?X)V;S460ZAIuFTpQVk2&qR;_DM_es07eMltBwYou z^1^g_6-*@6ZvQm0ZoNH+Mw_z9@;I2r#k8c+NSMqf=@JfG8zX(iAdb*Xr=>G-{`md7 zt3b);Lj~`j!n%tpX^s(lE#>gyB{Z zoNU#Dkyb;PU^Rj%R%1BZY68=&W^k$19Ohds;99FS+-|jjzgTVIKC2x(Xk}oNRSN&G z+QUJs1Ak-IF)VF$VvVgXti&o~-L0-{pw*3ywtC{e?ZeKs`m&3xer$ntJlk#!VozH` z*oW3ocF-Co6j>EQv2~(QYK;(jS|G+~`}hVYm*S=eb!5#F%Q6h5}j5`PX@XNzD>6%*DuqG?SNEo-_s*_t7q zWt}HJV9gRYSQm)Z)`jA3>mutgXkYc{V)(hZsrz6>)>?B_U}@fP7?$~3Xx$KEmV z-Gm_ggfmuz46z8gMbDjP)@ly34Tv;{?#6;T! zsegbj6{q>FODIM>QH)&H?cy-?9iG!^lUS<0OL~4*B5YPV@hH&l!aDUmpvol!g}5NAAvK9}2)dcrA92eaiiIZJ~%g&wY6vp_pyq zNxuq&Qnrcv0jGtXtf~5u&;<&GH<+S+41ZL`^8n0H$=|4+2ryaw6#Kd22I!#v6Zye< zK~h}*`K`h5$2bnp?&IpNfnI+GSL422Y=$J zfaiG@+TUR0LFiAefbk;-gPvg=A?lLNd=S;4f&ogwh6ygvMOqEdOSQs)R?Wv zAQ`Uk@;sDQCmQ%^NZA$0jd|Koc9GX4NssO>Cobyi@&qFZP3njw*3UwkdSaXUFOOW; zN0G_Pdu<}&_A&9#ctgBe{VpJ&GJhTAD5w%1auTYBhn$9LNiUd+tr|H_a^;cZVy-fB zT-;Shj!U@ONKRufj(D)5WQ|lJ^k7Aj%OzA&08~;}BDcQE&LfJhRRrM>t$uooFgzGoUcUjeq_~Zmg#7 z3pI2j_cm^d5Z%J}X1x}gAyS@?2>Eg-u&#gx)>Y8jS^({>tD(1b4I<@*P+={CQPyG@ zYb}8p*7dO1x&c;LH^TkaO|aRz8J@OoflsX4m|)$`bZZ$R-sOmN?_kGUe__L{N;bh- z$tGHNvANdW>^f@|yUkk7?tik@vbENI>^{8j5zA9lyg_0rdo*NQA4Rs6GBQoz<_j$QUX#E z^1Fb)_x=37`DgCgd#!cWK6lQ(&oeX6y$*7$vNqKd_Eo#;@!)SU+G|5eakL#s9U_OF zazFUugWH53CfxTa}_i0(g<K{M|@~`fuby4$tdpp*zU6LW{~F2TRD%^R{8e2KQ)W4!(wxZ zQ-Z9oe4x>6jL&LlMNNeuX`yam7q7BHYKP2?W4v5NsM|Op4Btvgqi^)Gu6IGzdg3-3SQnT_k3T@Z2uqAFWS1^a z!5Epur2?OCR_=PQZlBEVhXs=&bbUZ)Ajb7t!-_TrV3?-UVp~CFnUQ5e>X0rjBegH} zoHdPxXW#pIR@4-!NlrJ{X>hmbww`87M@(n*Z;Qx9x()>7zQMK+x#!xJFJ))>>r`pZ zn=PJqGR`C2n|^JTH2tQ}QY}*Be&c?iei*MEWxZgz&qmaOm?1B)es!Rl1ZQ94Yp(yg zdLuF*a)~^&2xuuc2>OcRj_$6;r=QZWiK1M;D@^#7GR6dFfGEG|k=W_lT@NG2&_a}h zbZ8dQ&eRb?sMluk6fF$9uNyD;c@GnM*ym8!sZ62SQbn5}#FNE2Vc0fpC@_bM^*g?> z7LUXwdGdE%m|HPbGWY%vx!3CCHb28qu6ZM&qYb@F^{kH_Dsgzk6Yp3L@frIf zU16{S)UkU)aU#~)v5u_FaEZN+1TXhfN{)l*&EexmctV*P%z=@vl1$e(F;wHOD<+gl zJxCx%%%QJ`DwauPkZj#VYLl_vYZ`zbmfKf8A*1=l0~y-qPUrYawJT*Jtu?9rRH$?X zyb5DjVQZ_3e%5Gs9aleBq#Zt~3x1E) z`(lQKwqu&;Y2d+RbKBXuP@n!>izBLr!`b^aLSX!m!~P70ta=sDU--;n5D|!pvUiBt zm*~^OHcHS&cl!c?*GdsfKUB01&={BsWIA5;#aOQ~E}d3IuFu`?L|e-jhad5g6c8JHoj>iL4h??gt;$l8)Wyirrn29Iv&(+(YdQDm zM-?PCEDqiT@R%VPlNvHRKB*A4uiYNnL9`WS$x!QxB#g=1X7Wl-7!+!E`tg!knly^v zV2v29LmDKI@WZ$l`;=^_Yfl$ytVx$ARUGucJg4w8A4l(ZO|N@OuQw5%mN-L+H3c`y zn88PuJ!yeTpg&srVO%dLYud(PtlI`82M>@mJq$32-!@}ETx5OqMqo`rns})w1c3u_ zoE4u@m2Hqq%pCYBb%*7;AQQx-%}U?*hZ35SS0jNO>Swu@IZ;(cgSTyJjAx6Y zwwVdy5UGm0PaPXj^Mv1-m7iIuP>YG&n=>P_Az>6r!kDawOKUZmUsb{R!g75Yo=C!{ z#cn|EGxzY!^bOBFl^~{9G@H}R&k%l}eo+~7QfOVvw3GB)-pFdtih_rHI*%6cuHP)0)7Gtrx#kJiM^K!#5Cu{B^6^`^XX_osfBRx~IKsA~Z(Zeznc(eeg%`YG zT4f{Y%=U@PFA%~;Ig5CzV|=Fq<6~{SGI$qGG)lw=ai-Jv#79EPwb_W=5^igJ+N$-c zEKzgi9!n8Rkwq^+ntL<5!(i@}ru3_0VJ61i>!WrmmUtu~6g&0yV|E2g^@#nam_x0H zP2P#Y0vjyPi{^_-Omejuet$d5i?@SA>J*R3%OL+|ab!#kz#4!|n(15?Q1L0PSm?gS*)(xmx z$wpwo@BC2#4GX_#F?zoWX5Q-VM;K^DREKqN^X8Gg&UjNDR$6gDQM8-OMQkJ_@Ub>d zm+16eT>I^aJ*TQ_>N4Se)BGy0)1ldRYJj8!(f&q>Gu5riwWMW?DMBYO^c*5Ymlfo8 z(#353y<^uqp9z!itOIKy%U!Sn?NFPY{kwedV`C;M*bYh4INKIU5BPpyV$jy1MgGu5 zvsEwpkWbEE^fm$_jAg^tIs8^A=9k`%nBlE-pP%Gkmznpfr zKk{jgtf&3{bym#&a<_laH-nBPom6KLrsv)l>$xgns-HYqllfRhnm`P}7MzBYoZv7L}(1 zK1lt@>`T@fqOo1Ec-CV!^sVt$@8@2G;Os=sr(?bAwHO#Do|cw;f#wGU!^kFL&q0H?M;~9*NPlMykYugbA%#a`sWF~#GHD$(h z`8UZ`yewLtRW?cv4gV_D_lmPHYq*}hJupPAk9n_ZyoZ8*%Lhrl@~ny%2x2Sv9>@L2?FWJ)+Dv@F@U_0&w>a1C0kw*$jS(U1 z>-o^l9M#?-ScO2q`h7Y#Z>?rFI*jFCLRqKD%wG5U5(*FGS@Xo*ujy`X7JhD!78h-l zprC##)^(O*y@DAwp}+rut+1DDWK-N{Cg*~fYMoY=J`sdyu(9>A zm%YuAA~s&c1M!}2tWuzfB$X3j*$!Jo?1$g=NpD6yg`!)86Yy`$JCWy{>An z(n#YrOSiZ!u-YG?8u5i^m2~VI< zTtOZ#W~Y8#Xhm%_R_lgxH)<*VT@TV|1l@*ncoyRX?fNEmdUPWl=N$8J_ballDOl9c zFF3%LM8l#+s_LmHQNU0e_JQybs#xCY6gR#)RZgkKpP<^U+~|New!^Ig_vc2=m%xMD z&zpc7u4tN=ld0E$Nx;q(jSjKuE#t0@QTw|k|gx?%X9XBnYUiHW2Q%k(vQf`{Sa8IDD=KG;O9c}>`` zmF4V=FcCRuQiiwG=10nR$GTDIudD2haW;r*Vg)ztM58jtg^qDcZKNFH+KjuwR>#Msjqd+$>Rr*P>z z9YldHaLyvfw`tz8?PCRn9%%<3Jnq+Wy-UV@3ODp*+Y<~?Hzy)Vh~=VO1g~$z?6(%5 zJK+x+t6d9n37)*`@rCkE*1%X)#cvw>?6<9=Ruj9rTX3xxrZrN{`sw*hiXtjvUu%`g z#N-x4y%_F~4W6!BB_P-nZiaKo?S7Tumr8W*tC0Mq!?_~bM)Y*~IP-IIfl5 zi0Btk@kY%!>fX&^ge?iS{;=&b7aRPdpM#nBqtY}qS?77+$orY~N+Ti(+s9QS5t~kL zzKpn^ndP8+&4>jxuF&*1xr&#gtFX5^e8lNgNf_?@&K2hP5jQ4zt4&O$?$+RU)&Un! zJPHZ#fd1sBHrbq1ghS|U20uP~f}NEjv`CKWwRP^&754Bpoke!=yN5RTv>OwaqY-Df zzvFPAjp(eB5BS52_n@=R4IIGceDOGe$tdN3fR)fs0~Mj*&2cM=iY76?hk168Szbtg z;7O&u81^s5fv=)NKB@EWFUS_8r!s%-uHK7gp1X{NN`+*9-P%^wGa`(w>ZvEQ>RA!S?Q(i;GKrs zD=a5EGSi=yR^CudbL}c%--+I9Tt4nm7cqO6ytY#+Ca7YaroLwyeOI@&X=2E$`0e5J zx#%m?hmm0qJhCk6`s;7wkXhUkbP8&LScqzglHckQBj$CIZ;@SPsqLr2Jrw&eFJmES zn#{jVT|MWBQ1RtUb}US|ol@n(R!WG>dtT~HUEh(=QS8E|utsk{{>JtZCa(L0w&&;D z@y6Vpox*`n7ZrGgjWu2P5*8pR%}2G1hWIu)1s{W+>@sDqi4&C?;9zUkICmG+&y&u~ z^E@PXS%fA*A6ur;qTthSpUH~MEGFimC$$WDBrYjCA)NA4x4F8i7xUhcgEs+KZrYVz z#uDERGr$<+m*-V`50v%~Jq~L;UFY#_%aabLez|&glXVxX4l}sf-;t);6D7?&Dr6-KrW!-4g)CW;6*q(M0;#{>c_2)J z8huGh{1Z`^KOqJ)wcxS@AGj9Wd^5?4xYL+Br3LtHla;g5>@?=i-56y-5tHs~KxR&% ztU+ZQ&Z=$Ldq<{DOLvuATI^-Pv%8F9)%P|oOUo^KGLy& z(wiWc7n@YJT|3j0wDaD}R@7N-<0F2AW3dk-GVT_t?pn6^xSTnIaoX28`0dhR_Bh^$ ztJ?Bbh=$!!<0igtSx%&MNC`f@Jlh*#9K&8}%H@-;!TxC6MoeraBKLIUx<)B~FdoHv z$X05*3>$mm5=|A+{QSF*3u&6RqPk%Y4pMEc8Ug;W^Scf$GZIiyh9KXpV))b5=AZSy zv){*-Sh)+5^set}J*Sg2t))sF??yH=K1$7ELS#l|Jw7;#uEJwxKU@?55abyZSb|kKArxfQo-7AzU%zE0QK-&vJowN#hxPc^UZq$ zDuqwmvBi|^2^!>Z;u!r%TYr8QB|1lzt96ot7{ASNi2A9%>!|NBS#Y>89TxtIT8!Bdr= zuc{np?K7IsCBB@WO`gDo_Yfuf2>N}5+fj3gdvjZRVcl#&N#ZdtO8v*oc$}SDG3sP~ z=iR7Qqy4kPbBLNUHV%aL%7=16CFvdrd3m8g)l2r6U zpE6wJ02xE5Xie=yXb1EXicp32pB`7dt2A#f2fJ3Y+aE%Sr`)XcLRHVkv9=dy# zFmZ-*T^&WaLfx-aKs^y4u?R|5qvHV`zLMg631z;*sUo1=bm*ISL;zI^^d1f~DIpxD zXh{T^ra*69R<@l2g#qO$P+EW^70PlMQcZ=zpyaqQGOn~SYn+5UYRYI(GRW2H^Wzf1 z)0S6ft)LKyItB#74f)U4HXcY~i$U^W1KX)kd~^^EoL{Jw6J92w_;3KFv_FZ*X<$N} z_#y!$r9sIUF0{9KntRyrAdoLNAP}Dal!kbbULp@bGqhQP z)^b2=f78R6FOm5m@{-9Is=^+r5+<&jyxWJ`^^@l$aJ|94d zLygN|`~L^OTm(b3!QjpRIU#-@ejjas?f}gHmToh;G?M0r4ZO_!Q($N&sDy2HDUZyA zl3uzSkz2ay07@YKr@%co04)nDc8U7W9m)CE*=h6y^;iK!7Lrx?DF@UO zqy`vsL05j@fC20l@G36)ntKco2<_wlUgQDpD=64Y=q?4)E(9zeUPL*7nupNqfPO9% zpC0Tma3e(BEpv1TWD*+!5&O%F1;CICeQ?RQ0VjqEYF_cdu0zjoL4B?Jf@K(75oN6Z zrYh@PLBVE33fL8b=lPdaw|Hs9`8ELU0=tA&+To?l_d4F8s z<%4`q!z*dEd??MOs{KWD)c7LG2~_3(@#ceq<(7ipSU_*0f0gB9b|nDzITC=k;Ey+{ z0#GI1@+!4r38pSq=(0>xIr>my&>KJKP3AADRGTZj;Y;W>;K&9_{4c2mRt~g+Btl#W zMCvaRz5NvlY@!tZu8nsgIKQ$p(3%J30aBd7wYix8vcT^bDR@i%3%uC_w!3AFt&9+9YSMV-x~yJ^^bJ`AbCv@y~=jp46u2G^c5GvCgjNBBmq5kPhJfx8C>_>$ IGH4R=e^WWk diff --git a/bukkit/pom.xml b/bukkit/pom.xml index cb1bc0141..88bb3b0e3 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -5,7 +5,7 @@ com.alessiodp.parties Parties - 2.4.7 + 2.5.0 parties-bukkit @@ -249,10 +249,10 @@ CrackShot com.shampaggon.crackshot - 0.98.8 + 0.98.9 system jar - ${basedir}/libs/CrackShot-0.98.8.jar + ${basedir}/libs/CrackShot-0.98.9.jar diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/BukkitPartiesPlugin.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/BukkitPartiesPlugin.java index f27e2eae6..d260e31d7 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/BukkitPartiesPlugin.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/BukkitPartiesPlugin.java @@ -11,10 +11,8 @@ import com.alessiodp.parties.bukkit.commands.BukkitCommandManager; import com.alessiodp.parties.bukkit.listeners.BukkitExpListener; import com.alessiodp.parties.bukkit.listeners.BukkitFightListener; -import com.alessiodp.parties.bukkit.listeners.BukkitMoveListener; import com.alessiodp.parties.bukkit.messaging.MessageManager; import com.alessiodp.parties.bukkit.parties.BukkitPartyManager; -import com.alessiodp.parties.bukkit.parties.BukkitCooldownManager; import com.alessiodp.parties.bukkit.players.BukkitPlayerManager; import com.alessiodp.parties.bukkit.players.ExpManager; import com.alessiodp.parties.bukkit.user.BukkitOfflineUser; @@ -90,7 +88,6 @@ protected void postHandle() { getCommandManager().setup(); eventManager = new BukkitEventManager(this); economyManager = new BukkitEconomyManager(this); - cooldownManager = new BukkitCooldownManager(); new MetricsHandler(this); } @@ -103,7 +100,13 @@ protected void registerListeners() { pm.registerEvents(new BukkitFightListener(this), getBootstrap()); pm.registerEvents(new BukkitFollowListener(this), getBootstrap()); pm.registerEvents(new BukkitJoinLeaveListener(this), getBootstrap()); - pm.registerEvents(new BukkitMoveListener(this), getBootstrap()); + } + + @Override + public void reloadConfiguration() { + super.reloadConfiguration(); + expManager.reload(); + messageManager.reload(); } @Override diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/addons/internal/TabCompleterHandler.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/addons/internal/TabCompleterHandler.java deleted file mode 100644 index c2a5fcc85..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/addons/internal/TabCompleterHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.alessiodp.parties.bukkit.addons.internal; - -import java.util.ArrayList; -import java.util.List; - -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.list.PartiesCommand; -import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; - -public class TabCompleterHandler implements TabCompleter { - private PartiesPlugin plugin; - - public TabCompleterHandler(PartiesPlugin instance) { - plugin = instance; - } - - @Override - public List onTabComplete(CommandSender sender, Command cmd, String commandLabel, String[] args) { - if (sender instanceof Player) { - if (cmd.getName().equalsIgnoreCase(ConfigMain.COMMANDS_CMD_PARTY)) { - if (args.length == 1) { - PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(((Player) sender).getUniqueId()); - String tabWord = args[0].toLowerCase(); - - List list = new ArrayList<>(); - for(PartiesCommand pc : pp.getAllowedCommands()) { - if (!pc.getType().equals("P") && pc.getCommand().toLowerCase().startsWith(tabWord)) { - list.add(pc.getCommand()); - } - } - return list; - } - } - } - return null; - } - -} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandDispatcher.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandDispatcher.java deleted file mode 100644 index 3a671b713..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandDispatcher.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.alessiodp.parties.bukkit.commands; - -import com.alessiodp.parties.bukkit.user.BukkitUser; -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.CommandDispatcher; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; - -class BukkitCommandDispatcher extends CommandDispatcher implements CommandExecutor { - - BukkitCommandDispatcher(PartiesPlugin instance) { - super(instance); - } - - @Override - public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) { - return super.onCommand(new BukkitUser(commandSender), command.getName(), args); - } -} \ No newline at end of file diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandImpl.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandImpl.java deleted file mode 100644 index ac9aad9e5..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.alessiodp.parties.bukkit.commands; - -import java.util.List; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; - -class BukkitCommandImpl extends Command { - private CommandExecutor exe = null; - private TabCompleter tabCompleter; - - BukkitCommandImpl(String name) { - super(name); - } - - public boolean execute(CommandSender sender, String commandLabel, String[] args) { - if (exe != null) { - exe.onCommand(sender, this, commandLabel, args); - } - return false; - } - - void setExecutor(CommandExecutor exe) { - this.exe = exe; - } - - void setTabCompleter(TabCompleter tc) { - tabCompleter = tc; - } - - @Override - public List tabComplete(CommandSender sender, String alias, String[] args) { - if (tabCompleter != null) { - List res = tabCompleter.onTabComplete(sender, this, alias, args); - if (res != null) - return res; - } - return super.tabComplete(sender, alias, args); - } -} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandManager.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandManager.java index 50d2b2100..b2dc958bf 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandManager.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/BukkitCommandManager.java @@ -2,27 +2,21 @@ import java.lang.reflect.Field; -import com.alessiodp.parties.bukkit.bootstrap.BukkitPartiesBootstrap; -import com.alessiodp.parties.bukkit.commands.executors.BukkitCommandTeleport; -import com.alessiodp.parties.bukkit.commands.executors.CommandProtection; import com.alessiodp.parties.bukkit.commands.list.BukkitCommands; +import com.alessiodp.parties.bukkit.commands.main.BukkitCommandP; +import com.alessiodp.parties.bukkit.commands.main.BukkitCommandParty; +import com.alessiodp.parties.bukkit.commands.utils.BukkitCommandImpl; import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; -import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigParties; import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.commands.CommandManager; -import com.alessiodp.parties.common.commands.list.CommonCommands; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.logging.LogLevel; import com.alessiodp.parties.common.logging.LoggerManager; import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandMap; - -import com.alessiodp.parties.bukkit.addons.internal.TabCompleterHandler; -import com.alessiodp.parties.bukkit.commands.executors.CommandClaim; -import com.alessiodp.parties.bukkit.commands.executors.CommandConfirm; -import com.alessiodp.parties.bukkit.commands.executors.CommandHome; -import com.alessiodp.parties.bukkit.commands.executors.CommandSetHome; import org.bukkit.command.PluginCommand; public class BukkitCommandManager extends CommandManager { @@ -36,75 +30,64 @@ protected void prepareCommands() { super.prepareCommands(); BukkitCommands.setup(); } - + @Override protected void registerCommands() { - dispatcher = new BukkitCommandDispatcher(plugin); - super.registerCommands(); - - // Claim - if (BukkitConfigMain.ADDONS_GRIEFPREVENTION_ENABLE) - dispatcher.register(BukkitCommands.CLAIM, new CommandClaim(plugin)); - - // Confirm - if (BukkitConfigMain.ADDONS_VAULT_ENABLE && BukkitConfigMain.ADDONS_VAULT_CONFIRM_ENABLE) - dispatcher.register(BukkitCommands.CONFIRM, new CommandConfirm(plugin)); - - // Home - if (BukkitConfigParties.HOME_ENABLE) { - dispatcher.register(BukkitCommands.HOME, new CommandHome(plugin)); - dispatcher.register(BukkitCommands.SETHOME, new CommandSetHome(plugin)); - } - - // Protection - if (BukkitConfigParties.FRIENDLYFIRE_TYPE.equalsIgnoreCase("command")) - dispatcher.register(BukkitCommands.PROTECTION, new CommandProtection(plugin)); - - // Teleport - if (BukkitConfigParties.TELEPORT_ENABLE) - dispatcher.register(CommonCommands.TELEPORT, new BukkitCommandTeleport(plugin)); + commandParty = new BukkitCommandParty(plugin); + commandP = new BukkitCommandP(plugin); } @Override protected void setupCommands() { try { - BukkitCommandImpl cmdParty = new BukkitCommandImpl(ConfigMain.COMMANDS_CMD_PARTY); - BukkitCommandImpl cmdP = new BukkitCommandImpl(ConfigMain.COMMANDS_CMD_P); - cmdParty.setDescription(BukkitConfigMain.COMMANDS_DESC_PARTY); - cmdP.setDescription(BukkitConfigMain.COMMANDS_DESC_P); - - // Register commands final Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); bukkitCommandMap.setAccessible(true); CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); - cmdParty.setExecutor((BukkitCommandDispatcher) dispatcher); - if (BukkitConfigMain.COMMANDS_TABSUPPORT) - cmdParty.setTabCompleter(new TabCompleterHandler(plugin)); - cmdP.setExecutor((BukkitCommandDispatcher) dispatcher); - - commandMap.register(ConfigMain.COMMANDS_CMD_PARTY, cmdParty); - commandMap.register(ConfigMain.COMMANDS_CMD_P, cmdP); - bukkitCommandMap.setAccessible(false); - - - // Force Parties executors instead of other plugins - PluginCommand commandParties = ((BukkitPartiesBootstrap) plugin.getBootstrap()).getServer().getPluginCommand(ConfigMain.COMMANDS_CMD_PARTY); - PluginCommand commandP = ((BukkitPartiesBootstrap) plugin.getBootstrap()).getServer().getPluginCommand(ConfigMain.COMMANDS_CMD_P); - - // Register party command - if (commandParties != null && commandParties.getPlugin() != null && !commandParties.getPlugin().getName().equals("Parties")) { - commandParties.setExecutor((BukkitCommandDispatcher) dispatcher); - if (BukkitConfigMain.COMMANDS_TABSUPPORT) - commandParties.setTabCompleter(new TabCompleterHandler(plugin)); + // Party command + if (commandMap.getCommand(ConfigMain.COMMANDS_CMD_PARTY) == null) { + // New command + BukkitCommandImpl cmdParty = new BukkitCommandImpl(ConfigMain.COMMANDS_CMD_PARTY, commandParty); + commandMap.register("parties", cmdParty); + } else { + // Update the executor and description + Command cmd = commandMap.getCommand(ConfigMain.COMMANDS_CMD_PARTY); + cmd.setDescription(BukkitConfigMain.COMMANDS_DESC_PARTY); + if (cmd instanceof BukkitCommandImpl) { + // Parties command + ((BukkitCommandImpl) cmd).setExecutor(commandParty); + } else { + // External command - overwrite it + LoggerManager.log(LogLevel.BASIC, Constants.DEBUG_COMMANDS_REGISTER_PARTY_EXIST, true); + + if (cmd instanceof PluginCommand){ + ((PluginCommand) cmd).setExecutor((CommandExecutor) commandParty); + } + } } - // Register p command - if (commandP != null && commandP.getPlugin() != null && !commandP.getPlugin().getName().equals("Parties")) - commandP.setExecutor((BukkitCommandDispatcher) dispatcher); - - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_COMMANDS_REGISTER_POST - .replace("{value}", Integer.toString(dispatcher.getCommandsNumber())), true); + // P command + if (commandMap.getCommand(ConfigMain.COMMANDS_CMD_P) == null) { + // New command + BukkitCommandImpl cmdParty = new BukkitCommandImpl(ConfigMain.COMMANDS_CMD_P, commandP); + commandMap.register("parties", cmdParty); + } else { + // Update the executor and description + Command cmd = commandMap.getCommand(ConfigMain.COMMANDS_CMD_P); + cmd.setDescription(BukkitConfigMain.COMMANDS_DESC_P); + if (cmd instanceof BukkitCommandImpl) { + // Parties command + ((BukkitCommandImpl) cmd).setExecutor(commandP); + } else { + // External command - overwrite it + LoggerManager.log(LogLevel.BASIC, Constants.DEBUG_COMMANDS_REGISTER_P_EXIST, true); + + if (cmd instanceof PluginCommand){ + ((PluginCommand) cmd).setExecutor((CommandExecutor) commandP); + } + } + } + bukkitCommandMap.setAccessible(false); }catch (Exception e) { e.printStackTrace(); } diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/list/BukkitCommands.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/list/BukkitCommands.java index 09bb02959..ebb98323c 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/list/BukkitCommands.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/list/BukkitCommands.java @@ -3,6 +3,7 @@ import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.common.commands.list.PartiesCommand; +import com.alessiodp.parties.common.players.PartiesPermission; import lombok.Getter; public enum BukkitCommands implements PartiesCommand { @@ -14,22 +15,28 @@ public enum BukkitCommands implements PartiesCommand { @Getter private String command; @Getter private String help; + @Getter private String permission; BukkitCommands() { command = ""; help = ""; + permission = ""; } public static void setup() { BukkitCommands.CLAIM.command = BukkitConfigMain.COMMANDS_CMD_CLAIM; BukkitCommands.CLAIM.help = BukkitMessages.HELP_ADDCMD_CLAIM; + BukkitCommands.CLAIM.permission = PartiesPermission.CLAIM.toString(); BukkitCommands.CONFIRM.command = BukkitConfigMain.COMMANDS_CMD_CONFIRM; BukkitCommands.HOME.command = BukkitConfigMain.COMMANDS_CMD_HOME; BukkitCommands.HOME.help = BukkitMessages.HELP_ADDCMD_HOME; + BukkitCommands.HOME.permission = PartiesPermission.HOME.toString(); BukkitCommands.PROTECTION.command = BukkitConfigMain.COMMANDS_CMD_PROTECTION; BukkitCommands.PROTECTION.help = BukkitMessages.HELP_ADDCMD_PROTECTION; + BukkitCommands.PROTECTION.permission = PartiesPermission.PROTECTION.toString(); BukkitCommands.SETHOME.command = BukkitConfigMain.COMMANDS_CMD_SETHOME; BukkitCommands.SETHOME.help = BukkitMessages.HELP_ADDCMD_SETHOME; + BukkitCommands.SETHOME.permission = PartiesPermission.SETHOME.toString(); } public String getType() { diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandP.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandP.java new file mode 100644 index 000000000..e6c81db4d --- /dev/null +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandP.java @@ -0,0 +1,11 @@ +package com.alessiodp.parties.bukkit.commands.main; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.main.CommandP; + +public class BukkitCommandP extends CommandP { + + public BukkitCommandP(PartiesPlugin instance) { + super(instance); + } +} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandParty.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandParty.java new file mode 100644 index 000000000..d2a802c30 --- /dev/null +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/main/BukkitCommandParty.java @@ -0,0 +1,48 @@ +package com.alessiodp.parties.bukkit.commands.main; + +import com.alessiodp.parties.bukkit.commands.sub.BukkitCommandTeleport; +import com.alessiodp.parties.bukkit.commands.sub.CommandClaim; +import com.alessiodp.parties.bukkit.commands.sub.CommandConfirm; +import com.alessiodp.parties.bukkit.commands.sub.CommandHome; +import com.alessiodp.parties.bukkit.commands.sub.CommandProtection; +import com.alessiodp.parties.bukkit.commands.sub.CommandSetHome; +import com.alessiodp.parties.bukkit.commands.list.BukkitCommands; +import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; +import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigParties; +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.list.CommonCommands; +import com.alessiodp.parties.common.commands.main.CommandParty; + +public class BukkitCommandParty extends CommandParty { + + public BukkitCommandParty(PartiesPlugin instance) { + super(instance); + } + + @Override + public void reload() { + super.reload(); + + // Claim + if (BukkitConfigMain.ADDONS_GRIEFPREVENTION_ENABLE) + super.register(BukkitCommands.CLAIM, new CommandClaim(plugin)); + + // Confirm + if (BukkitConfigMain.ADDONS_VAULT_ENABLE && BukkitConfigMain.ADDONS_VAULT_CONFIRM_ENABLE) + super.register(BukkitCommands.CONFIRM, new CommandConfirm(plugin)); + + // Home + if (BukkitConfigParties.HOME_ENABLE) { + super.register(BukkitCommands.HOME, new CommandHome(plugin)); + super.register(BukkitCommands.SETHOME, new CommandSetHome(plugin)); + } + + // Protection + if (BukkitConfigParties.FRIENDLYFIRE_TYPE.equalsIgnoreCase("command")) + super.register(BukkitCommands.PROTECTION, new CommandProtection(plugin)); + + // Teleport + if (BukkitConfigParties.TELEPORT_ENABLE) + super.register(CommonCommands.TELEPORT, new BukkitCommandTeleport(plugin)); + } +} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/BukkitCommandTeleport.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/BukkitCommandTeleport.java similarity index 92% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/BukkitCommandTeleport.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/BukkitCommandTeleport.java index e2d3581ab..8a8ab65a8 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/BukkitCommandTeleport.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/BukkitCommandTeleport.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.CommandData; -import com.alessiodp.parties.common.commands.executors.CommandTeleport; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.commands.sub.CommandTeleport; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; @@ -50,7 +50,7 @@ public void onCommand(CommandData commandData) { */ if (unixNow != -1) { plugin.getCooldownManager().getTeleportCooldown().put(pp.getPlayerUUID(), unixNow); - plugin.getPartiesScheduler().scheduleTaskLater(new TeleportTask(plugin, pp.getPlayerUUID()), ConfigParties.TELEPORT_COOLDOWN); + plugin.getPartiesScheduler().scheduleTaskLater(new TeleportTask(plugin, pp.getPlayerUUID()), ConfigParties.TELEPORT_COOLDOWN * 20L); LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_TELEPORT_START .replace("{value}", Integer.toString(ConfigParties.TELEPORT_COOLDOWN * 20)) diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandClaim.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandClaim.java similarity index 87% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandClaim.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandClaim.java index a49aeab6d..f59fab27a 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandClaim.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandClaim.java @@ -1,11 +1,11 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.bukkit.addons.external.GriefPreventionHandler; import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -17,6 +17,9 @@ import com.alessiodp.parties.common.utils.EconomyManager; import org.bukkit.Bukkit; +import java.util.ArrayList; +import java.util.List; + public class CommandClaim extends AbstractCommand { public CommandClaim(PartiesPlugin instance) { @@ -116,7 +119,17 @@ else if (commandData.getArgs()[1].equalsIgnoreCase(BukkitConfigMain.ADDONS_GRIEF } } - + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(BukkitConfigMain.ADDONS_GRIEFPREVENTION_CMD_ACCESS); + ret.add(BukkitConfigMain.ADDONS_GRIEFPREVENTION_CMD_CONTAINER); + ret.add(BukkitConfigMain.ADDONS_GRIEFPREVENTION_CMD_TRUST); + ret.add(BukkitConfigMain.ADDONS_GRIEFPREVENTION_CMD_REMOVE); + } + return ret; + } private enum Selection { TRUST, CONTAINER, ACCESS, REMOVE, FAILED_GENERAL, FAILED_NOEXIST, FAILED_NOMANAGER; diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandConfirm.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandConfirm.java similarity index 89% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandConfirm.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandConfirm.java index 96b804f8d..5e660180f 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandConfirm.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandConfirm.java @@ -1,12 +1,12 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.bukkit.players.objects.BukkitPartyPlayerImpl; import com.alessiodp.parties.bukkit.utils.LastConfirmedCommand; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.user.User; import org.bukkit.Bukkit; diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandHome.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandHome.java similarity index 89% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandHome.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandHome.java index bc4d25814..6bd29cfcc 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandHome.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandHome.java @@ -1,13 +1,12 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigParties; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.bukkit.players.objects.BukkitPartyPlayerImpl; -import com.alessiodp.parties.bukkit.players.objects.HomeCooldown; import com.alessiodp.parties.bukkit.tasks.HomeTask; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -85,7 +84,7 @@ public void onCommand(CommandData commandData) { return; } - if (pp.getHomeCooldown() != null) { + if (pp.getHomeDelayTask() != -1) { pp.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTWAITING, party); return; } @@ -117,10 +116,21 @@ public void onCommand(CommandData commandData) { party.getHome().getPitch()); if (delay > 0) { - int taskId = plugin.getPartiesScheduler().scheduleTaskLater(new HomeTask(pp, loc), delay); + HomeTask homeTask = new HomeTask( + plugin, + pp, + bukkitPlayer, + delay, + loc + ); + int taskId = plugin.getPartiesScheduler().scheduleAsyncTaskTimer(homeTask, 5L); + pp.setHomeDelayTask(taskId); + + /* + int taskId = plugin.getPartiesScheduler().scheduleTaskLater(new HomeTask(pp, loc), delay * 20L); HomeCooldown homeCooldown = new HomeCooldown(plugin, taskId, bukkitPlayer.getLocation()); pp.setHomeCooldown(homeCooldown); - homeCooldown.save(); + homeCooldown.save();*/ pp.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTIN .replace("%time%", Integer.toString(delay))); diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandProtection.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandProtection.java similarity index 80% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandProtection.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandProtection.java index a60eb1981..9a8224084 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandProtection.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandProtection.java @@ -1,9 +1,9 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -13,6 +13,9 @@ import com.alessiodp.parties.common.players.PartiesPermission; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.List; public class CommandProtection extends AbstractCommand { @@ -55,17 +58,7 @@ public void onCommand(CommandData commandData) { /* * Command handling */ - Boolean protection = party.isFriendlyFireProtected(); - if (commandData.getArgs().length > 1) { - if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_ON)) - protection = true; - else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) - protection = false; - else - protection = null; - } else { - protection = !protection; - } + Boolean protection = PartiesUtils.handleOnOffCommand(party.isFriendlyFireProtected(), commandData.getArgs()); if (protection == null) { pp.sendMessage(BukkitMessages.ADDCMD_PROTECTION_WRONGCMD); return; @@ -88,4 +81,9 @@ else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) .replace("{party}", party.getName()), true); } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompleteOnOff(args); + } } \ No newline at end of file diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandSetHome.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandSetHome.java similarity index 88% rename from bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandSetHome.java rename to bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandSetHome.java index 13d29ffd7..789301640 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/executors/CommandSetHome.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/sub/CommandSetHome.java @@ -1,9 +1,9 @@ -package com.alessiodp.parties.bukkit.commands.executors; +package com.alessiodp.parties.bukkit.commands.sub; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -18,6 +18,9 @@ import org.bukkit.Bukkit; import org.bukkit.Location; +import java.util.ArrayList; +import java.util.List; + public class CommandSetHome extends AbstractCommand { public CommandSetHome(PartiesPlugin instance) { @@ -108,4 +111,13 @@ public void onCommand(CommandData commandData) { .replace("{party}", party.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(ConfigMain.COMMANDS_SUB_REMOVE); + } + return ret; + } } \ No newline at end of file diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/utils/BukkitCommandImpl.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/utils/BukkitCommandImpl.java new file mode 100644 index 000000000..78a61c61b --- /dev/null +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/commands/utils/BukkitCommandImpl.java @@ -0,0 +1,41 @@ +package com.alessiodp.parties.bukkit.commands.utils; + +import com.alessiodp.parties.bukkit.user.BukkitUser; +import com.alessiodp.parties.common.commands.utils.PartiesCommandExecutor; +import com.alessiodp.parties.common.configuration.data.ConfigMain; +import lombok.Setter; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.command.TabExecutor; + +import java.util.ArrayList; +import java.util.List; + +public class BukkitCommandImpl extends Command implements CommandExecutor { + @Setter private PartiesCommandExecutor executor; + + public BukkitCommandImpl(String name, PartiesCommandExecutor executor) { + super(name); + this.executor = executor; + } + + @Override + public boolean execute(CommandSender commandSender, String cmd, String[] args) { + return this.onCommand(commandSender,this, cmd, args); + } + + @Override + public boolean onCommand(CommandSender commandSender, Command command, String cmd, String[] args) { + return executor.onCommand(new BukkitUser(commandSender), cmd, args); + } + + @Override + public List tabComplete(CommandSender commandSender, String alias, String[] args) { + if (ConfigMain.COMMANDS_TABSUPPORT) { + return executor.onTabComplete(new BukkitUser(commandSender), args); + } + return new ArrayList<>(); + } +} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitConfigMain.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitConfigMain.java index c3894aca0..1a96a2382 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitConfigMain.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitConfigMain.java @@ -15,7 +15,6 @@ public class BukkitConfigMain extends ConfigMain { public static boolean PARTIES_BUNGEECORDSYNC_DISPATCH_CHAT; // Additional settings - public static boolean ADDITIONAL_FOLLOW_ENABLE; public static int ADDITIONAL_FOLLOW_TYPE; public static int ADDITIONAL_FOLLOW_RANKNEEDED; public static int ADDITIONAL_FOLLOW_RANKMINIMUM; @@ -78,7 +77,6 @@ public class BukkitConfigMain extends ConfigMain { // Commands settings - public static boolean COMMANDS_TABSUPPORT; public static String COMMANDS_DESC_PARTY; public static String COMMANDS_DESC_P; @@ -104,7 +102,6 @@ public void loadDefaults() { PARTIES_BUNGEECORDSYNC_DISPATCH_CHAT = true; // Additional features - ADDITIONAL_FOLLOW_ENABLE = false; ADDITIONAL_FOLLOW_TYPE = 1; ADDITIONAL_FOLLOW_RANKNEEDED = 0; ADDITIONAL_FOLLOW_RANKMINIMUM = 0; @@ -171,7 +168,6 @@ public void loadDefaults() { // Commands settings - COMMANDS_TABSUPPORT = true; COMMANDS_DESC_PARTY = "Parties help page"; COMMANDS_DESC_P = "Send a party message"; @@ -198,6 +194,7 @@ public void loadDefaults() { ConfigMain.COMMANDS_ORDER.add("desc"); ConfigMain.COMMANDS_ORDER.add("motd"); ConfigMain.COMMANDS_ORDER.add("protection"); + ConfigMain.COMMANDS_ORDER.add("follow"); ConfigMain.COMMANDS_ORDER.add("home"); ConfigMain.COMMANDS_ORDER.add("sethome"); ConfigMain.COMMANDS_ORDER.add("color"); @@ -210,6 +207,7 @@ public void loadDefaults() { ConfigMain.COMMANDS_ORDER.add("spy"); ConfigMain.COMMANDS_ORDER.add("delete"); ConfigMain.COMMANDS_ORDER.add("reload"); + ConfigMain.COMMANDS_ORDER.add("version"); ConfigMain.COMMANDS_ORDER.add("migrate"); } @@ -224,7 +222,6 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { PARTIES_BUNGEECORDSYNC_DISPATCH_CHAT = confAdapter.getBoolean("parties.bungeecord-sync.dispatch.chat", PARTIES_BUNGEECORDSYNC_DISPATCH_CHAT); // Additional settings - ADDITIONAL_FOLLOW_ENABLE = confAdapter.getBoolean("additional.follow-party.enable", ADDITIONAL_FOLLOW_ENABLE); ADDITIONAL_FOLLOW_TYPE = confAdapter.getInt("additional.follow-party.type-of-teleport", ADDITIONAL_FOLLOW_TYPE); ADDITIONAL_FOLLOW_RANKNEEDED = confAdapter.getInt("additional.follow-party.rank-needed", ADDITIONAL_FOLLOW_RANKNEEDED); ADDITIONAL_FOLLOW_RANKMINIMUM = confAdapter.getInt("additional.follow-party.minimum-rank-to-follow", ADDITIONAL_FOLLOW_RANKMINIMUM); @@ -290,7 +287,6 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { // Commands settings - COMMANDS_TABSUPPORT = confAdapter.getBoolean("commands.tab-support", COMMANDS_TABSUPPORT); COMMANDS_DESC_PARTY = confAdapter.getString("commands.descriptions.party", COMMANDS_DESC_PARTY); COMMANDS_DESC_P = confAdapter.getString("commands.descriptions.p", COMMANDS_DESC_P); diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitMessages.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitMessages.java index 6549c477a..6f570aeae 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitMessages.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/configuration/data/BukkitMessages.java @@ -127,7 +127,7 @@ public void loadDefaults() { HELP_ADDCMD_CLAIM = "{\"text\":\"\",\"extra\":[{\"text\":\"/party claim \",\"color\":\"aqua\"},{\"text\":\" - Grant permissions to the claim\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party claim \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_HOME = "{\"text\":\"\",\"extra\":[{\"text\":\"/party home [party]\",\"color\":\"aqua\"},{\"text\":\" - Teleport to the party home\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party home \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_PROTECTION = "{\"text\":\"\",\"extra\":[{\"text\":\"/party protection [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Toggle friendly fire protection\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party protection \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_ADDCMD_SETHOME = "{\"text\":\"\",\"extra\":[{\"text\":\"/party sethome [remove]\",\"color\":\"aqua\"},{\"text\":\" - Set the party home\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party sethome \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_ADDCMD_SETHOME = "{\"text\":\"\",\"extra\":[{\"text\":\"/party sethome [remove]\",\"color\":\"aqua\"},{\"text\":\" - Set/remove party home\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party sethome \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; } @Override diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitChatListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitChatListener.java index 9199c377f..b0903d012 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitChatListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitChatListener.java @@ -15,7 +15,7 @@ public BukkitChatListener(PartiesPlugin instance) { super(instance); } - @EventHandler(priority = EventPriority.LOW) + @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) public void onPlayerChat(AsyncPlayerChatEvent event) { if (!event.isCancelled()) { boolean isCancelled = super.onPlayerChat(new BukkitUser(event.getPlayer()), event.getMessage()); diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitExpListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitExpListener.java index 8c52e61f3..fa791e436 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitExpListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitExpListener.java @@ -19,7 +19,7 @@ public BukkitExpListener(BukkitPartiesPlugin instance) { plugin = instance; } - @EventHandler(priority = EventPriority.HIGHEST) + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onEntityDie(EntityDeathEvent event) { if (BukkitConfigMain.ADDITIONAL_EXP_ENABLE && BukkitConfigMain.ADDITIONAL_EXP_DROP_ENABLE) { Entity killedEntity = event.getEntity(); diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFightListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFightListener.java index 41896dac3..ae1e9904a 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFightListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFightListener.java @@ -4,6 +4,7 @@ import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.bukkit.events.BukkitEventManager; import com.alessiodp.parties.bukkit.parties.objects.BukkitPartyImpl; +import com.alessiodp.parties.bukkit.players.objects.BukkitPartyPlayerImpl; import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.logging.LogLevel; @@ -38,7 +39,7 @@ public BukkitFightListener(PartiesPlugin instance) { plugin = instance; } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onPlayerHit(EntityDamageByEntityEvent event) { if (BukkitConfigParties.FRIENDLYFIRE_ENABLE && event.getEntity() instanceof Player) { Player victim = (Player) event.getEntity(); @@ -74,7 +75,6 @@ else if (event.getDamager() instanceof Snowball) if (shooterSource instanceof Player) attacker = (Player) shooterSource; break; - case UNSUPPORTED: } if (attacker != null) { // Found right attacker @@ -112,7 +112,7 @@ else if (event.getDamager() instanceof Snowball) } } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onPotionSplash(PotionSplashEvent event) { if (BukkitConfigParties.FRIENDLYFIRE_ENABLE && event.getEntity() instanceof Player @@ -173,7 +173,7 @@ public void onPotionSplash(PotionSplashEvent event) { } } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { if (BukkitConfigParties.FRIENDLYFIRE_ENABLE && event.getEntity() instanceof Player @@ -217,7 +217,7 @@ public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { } } - @EventHandler + @EventHandler(ignoreCancelled = true) public void onEntityDieKill(EntityDeathEvent event) { if (BukkitConfigParties.KILLS_ENABLE) { if (event.getEntity().getKiller() != null) { @@ -250,6 +250,26 @@ else if (BukkitConfigParties.KILLS_MOB_PLAYERS } } + @EventHandler(ignoreCancelled = true) + public void onPlayerGotHit(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player && BukkitConfigParties.HOME_HIT) { + // Make it async + plugin.getPartiesScheduler().getEventsExecutor().execute(() -> { + BukkitPartyPlayerImpl partyPlayer = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(event.getEntity().getUniqueId()); + // Check if the player is on home cooldown + if (partyPlayer.getHomeDelayTask() != -1) { + // Cancelling home task + plugin.getPartiesScheduler().cancelTask(partyPlayer.getHomeDelayTask()); + partyPlayer.setHomeDelayTask(-1); + + partyPlayer.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTDENIED); + LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_HOME_DENIED_FIGHT + .replace("{player}", partyPlayer.getName()), true); + } + }); + } + } + private enum DamageType { UNSUPPORTED, PLAYER, ARROW, ENDERPEARL, SNOWBALL } diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFollowListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFollowListener.java index 4f1bcacab..7c483e6c1 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFollowListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitFollowListener.java @@ -21,7 +21,7 @@ public BukkitFollowListener(PartiesPlugin instance) { plugin = instance; } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onEntityPortalEvent(PlayerPortalEvent event) { if (!event.isCancelled()) { BukkitPartyPlayerImpl pp = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(event.getPlayer().getUniqueId()); @@ -32,7 +32,7 @@ public void onEntityPortalEvent(PlayerPortalEvent event) { } } - @EventHandler + @EventHandler (ignoreCancelled = true) public void onChangeWorld(PlayerChangedWorldEvent event) { if (BukkitConfigMain.ADDITIONAL_FOLLOW_ENABLE) { // Make it async @@ -44,7 +44,7 @@ public void onChangeWorld(PlayerChangedWorldEvent event) { BukkitPartyPlayerImpl pp = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(bukkitPlayer.getUniqueId()); if (!pp.getPartyName().isEmpty()) { PartyImpl party = plugin.getPartyManager().getParty(pp.getPartyName()); - if (party != null) { + if (party != null && party.isFollowEnabled()) { if (pp.getRank() >= BukkitConfigMain.ADDITIONAL_FOLLOW_RANKNEEDED) { // Init teleport @@ -61,7 +61,7 @@ public void onChangeWorld(PlayerChangedWorldEvent event) { int taskId; switch (BukkitConfigMain.ADDITIONAL_FOLLOW_TYPE) { case 1: - taskId = plugin.getPartiesScheduler().scheduleTaskLater(new PortalTask(plugin, pl.getPlayerUUID()), BukkitConfigMain.ADDITIONAL_FOLLOW_TIMEOUT / 20L); + taskId = plugin.getPartiesScheduler().scheduleTaskLater(new PortalTask(plugin, pl.getPlayerUUID()), BukkitConfigMain.ADDITIONAL_FOLLOW_TIMEOUT); ppVictim.setPortalTimeoutTask(taskId); ppVictim.sendMessage(BukkitMessages.OTHER_FOLLOW_WORLD .replace("%player%", bukkitPlayer.getName()) @@ -69,7 +69,7 @@ public void onChangeWorld(PlayerChangedWorldEvent event) { bukkitPl.teleport(bukkitPlayer.getWorld().getSpawnLocation()); break; case 2: - taskId = plugin.getPartiesScheduler().scheduleTaskLater(new PortalTask(plugin, pl.getPlayerUUID()), BukkitConfigMain.ADDITIONAL_FOLLOW_TIMEOUT / 20L); + taskId = plugin.getPartiesScheduler().scheduleTaskLater(new PortalTask(plugin, pl.getPlayerUUID()), BukkitConfigMain.ADDITIONAL_FOLLOW_TIMEOUT); ppVictim.setPortalTimeoutTask(taskId); ppVictim.sendMessage(BukkitMessages.OTHER_FOLLOW_WORLD .replace("%player%", bukkitPlayer.getName()) diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitJoinLeaveListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitJoinLeaveListener.java index e8206bc0e..f07d49105 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitJoinLeaveListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitJoinLeaveListener.java @@ -28,8 +28,9 @@ public void onPlayerQuit(PlayerQuitEvent event) { // Remove home count if active on the player BukkitPartyPlayerImpl pp = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(user.getUUID()); - if (pp.getHomeCooldown() != null) { - pp.getHomeCooldown().delete(); + if (pp.getHomeDelayTask() != -1){ + plugin.getPartiesScheduler().cancelTask(pp.getHomeDelayTask()); + pp.setHomeDelayTask(-1); } } } diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitMoveListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitMoveListener.java deleted file mode 100644 index 68f84cadf..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/listeners/BukkitMoveListener.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.alessiodp.parties.bukkit.listeners; - -import com.alessiodp.parties.bukkit.BukkitPartiesPlugin; -import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigParties; -import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; -import com.alessiodp.parties.bukkit.parties.BukkitCooldownManager; -import com.alessiodp.parties.bukkit.players.objects.BukkitPartyPlayerImpl; -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.configuration.Constants; -import com.alessiodp.parties.common.logging.LogLevel; -import com.alessiodp.parties.common.logging.LoggerManager; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.player.PlayerMoveEvent; - - -public class BukkitMoveListener implements Listener { - private BukkitPartiesPlugin plugin; - - public BukkitMoveListener(PartiesPlugin instance) { - plugin = (BukkitPartiesPlugin) instance; - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerMove(PlayerMoveEvent event) { - if (BukkitConfigParties.HOME_MOVING) { - // Make it async - plugin.getPartiesScheduler().getEventsExecutor().execute(() -> { - // Check if there is an home command awaiting - if (((BukkitCooldownManager) plugin.getCooldownManager()).getHomeQueue().isAlive()) { - - BukkitPartyPlayerImpl partyPlayer = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(event.getPlayer().getUniqueId()); - // Check if the player is on home cooldown - if (partyPlayer.getHomeCooldown() != null) { - // Check if the new location is different from the old one - if (event.getFrom().getBlockX() != event.getTo().getBlockX() - || event.getFrom().getBlockY() != event.getTo().getBlockY() - || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - // Check how far away is the start position from the new position - if (partyPlayer.getHomeCooldown().getFrom().distance(event.getTo()) > BukkitConfigParties.HOME_DISTANCE) { - // Cancelling home command - plugin.getPartiesScheduler().cancelTask(partyPlayer.getHomeCooldown().getTask()); - partyPlayer.getHomeCooldown().delete(); - partyPlayer.setHomeCooldown(null); - - partyPlayer.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTDENIED); - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_HOME_DENIED_MOVING - .replace("{player}", partyPlayer.getName()), true); - } - } - } - } - }); - } - } - @EventHandler(ignoreCancelled = true) - public void onPlayerGotHit(EntityDamageByEntityEvent event) { - if (event.getEntity() instanceof Player && BukkitConfigParties.HOME_HIT) { - // Make it async - plugin.getPartiesScheduler().getEventsExecutor().execute(() -> { - // Check if there is an home command awaiting - if (((BukkitCooldownManager) plugin.getCooldownManager()).getHomeQueue().isAlive()) { - - BukkitPartyPlayerImpl partyPlayer = (BukkitPartyPlayerImpl) plugin.getPlayerManager().getPlayer(event.getEntity().getUniqueId()); - // Check if the player is on home cooldown - if (partyPlayer.getHomeCooldown() != null) { - // Cancelling home command - plugin.getPartiesScheduler().cancelTask(partyPlayer.getHomeCooldown().getTask()); - partyPlayer.getHomeCooldown().delete(); - partyPlayer.setHomeCooldown(null); - - partyPlayer.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTDENIED); - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_HOME_DENIED_FIGHT - .replace("{player}", partyPlayer.getName()), true); - } - } - }); - } - } -} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageListener.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageListener.java index 3a462d80c..299f5db06 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageListener.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageListener.java @@ -18,11 +18,27 @@ public class MessageListener implements PluginMessageListener { private BukkitPartiesPlugin plugin; + private boolean registered; public MessageListener(PartiesPlugin instance) { plugin = (BukkitPartiesPlugin) instance; - plugin.getBootstrap().getServer().getMessenger().registerOutgoingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL); - plugin.getBootstrap().getServer().getMessenger().registerIncomingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL, this); + registered = false; + } + + public void register() { + if (!registered) { + plugin.getBootstrap().getServer().getMessenger().registerOutgoingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL); + plugin.getBootstrap().getServer().getMessenger().registerIncomingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL, this); + registered = true; + } + } + + public void unregister() { + if (registered) { + plugin.getBootstrap().getServer().getMessenger().unregisterOutgoingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL); + plugin.getBootstrap().getServer().getMessenger().unregisterIncomingPluginChannel(plugin.getBootstrap(), Constants.MESSAGING_CHANNEL); + registered = false; + } } @Override diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageManager.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageManager.java index e98b423bd..528deab23 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageManager.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/messaging/MessageManager.java @@ -16,12 +16,19 @@ public class MessageManager { private BukkitPartiesPlugin plugin; + private MessageListener messageListener; public MessageManager(PartiesPlugin instance) { plugin = (BukkitPartiesPlugin) instance; - if (BukkitConfigMain.PARTIES_BUNGEECORDSYNC_ENABLE) { - new MessageListener(plugin); - } + messageListener = new MessageListener(plugin); + reload(); + } + + public void reload() { + if (BukkitConfigMain.PARTIES_BUNGEECORDSYNC_ENABLE) + messageListener.register(); + else + messageListener.unregister(); } private void sendPacket(PartiesPacket packet) { diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/parties/BukkitCooldownManager.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/parties/BukkitCooldownManager.java deleted file mode 100644 index 883b70fdd..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/parties/BukkitCooldownManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.alessiodp.parties.bukkit.parties; - -import com.alessiodp.parties.common.parties.CooldownManager; -import lombok.Getter; - -public class BukkitCooldownManager extends CooldownManager { - @Getter private NumberedQueue homeQueue; - - public BukkitCooldownManager() { - super(); - } - - @Override - public void reload() { - super.reload(); - homeQueue = new NumberedQueue(); - } - - - public class NumberedQueue { - private int queue; - - NumberedQueue() { - queue = 0; - } - - public boolean isAlive() { - return queue > 0; - } - - public void enter() { - queue++; - } - - public void leave() { - queue--; - } - } -} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/ExpManager.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/ExpManager.java index 680df8752..c0479ed27 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/ExpManager.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/ExpManager.java @@ -29,6 +29,10 @@ public class ExpManager { public ExpManager(PartiesPlugin instance) { plugin = instance; + reload(); + } + + public void reload() { mode = ExpMode.parse(BukkitConfigMain.ADDITIONAL_EXP_LEVELS_MODE); rangeSquared = BukkitConfigMain.ADDITIONAL_EXP_DROP_SHARING_RANGE * BukkitConfigMain.ADDITIONAL_EXP_DROP_SHARING_RANGE; @@ -127,7 +131,8 @@ private boolean shareExperience(int experience, PartyPlayerImpl killer, PartyImp // Calculate experience for each player String formula = BukkitConfigMain.ADDITIONAL_EXP_DROP_SHARING_DIVIDEFORMULA .replace("%exp%", Integer.toString(experience)) - .replace("%number_players%", Integer.toString(playersToShare.size())); + .replace("%number_players%", Integer.toString(playersToShare.size())) + .replace("%level%", Integer.toString(party.getLevel())); try { int singlePlayerExperience = (int) calculateExpression(formula); diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/BukkitPartyPlayerImpl.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/BukkitPartyPlayerImpl.java index bd69914c4..ac7e777ac 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/BukkitPartyPlayerImpl.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/BukkitPartyPlayerImpl.java @@ -22,15 +22,14 @@ import org.bukkit.metadata.MetadataValue; public class BukkitPartyPlayerImpl extends PartyPlayerImpl { - @Getter @Setter private HomeCooldown homeCooldown; - + @Getter @Setter private int homeDelayTask; @Getter @Setter private int portalTimeoutTask; @Getter @Setter private LastConfirmedCommand lastConfirmedCommand; public BukkitPartyPlayerImpl(PartiesPlugin instance, UUID uuid) { super(instance, uuid); - homeCooldown = null; + homeDelayTask = -1; portalTimeoutTask = -1; lastConfirmedCommand = null; } @@ -43,8 +42,12 @@ public void updatePlayer() { @Override public void cleanupPlayer(boolean saveDB) { - homeCooldown = null; // Reset home command (avoiding telepoting to another party home) super.cleanupPlayer(saveDB); + // Reset home command (avoiding teleporting to another party) + if (getHomeDelayTask() != -1) { + plugin.getPartiesScheduler().cancelTask(getHomeDelayTask()); + setHomeDelayTask(-1); + } } @Override diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/HomeCooldown.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/HomeCooldown.java deleted file mode 100644 index a97f79e44..000000000 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/players/objects/HomeCooldown.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.alessiodp.parties.bukkit.players.objects; - -import com.alessiodp.parties.bukkit.BukkitPartiesPlugin; -import com.alessiodp.parties.bukkit.parties.BukkitCooldownManager; -import com.alessiodp.parties.common.PartiesPlugin; -import lombok.Getter; -import org.bukkit.Location; - -public class HomeCooldown { - private BukkitPartiesPlugin plugin; - - @Getter private int task; - @Getter private Location from; - - public HomeCooldown(PartiesPlugin instance, int task, Location from) { - plugin = (BukkitPartiesPlugin) instance; - this.task = task; - this.from = from; - } - - public void save() { - ((BukkitCooldownManager) plugin.getCooldownManager()).getHomeQueue().enter(); - } - - public void delete() { - ((BukkitCooldownManager) plugin.getCooldownManager()).getHomeQueue().leave(); - } -} diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/scheduling/BukkitPartiesScheduler.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/scheduling/BukkitPartiesScheduler.java index 5d8237d5b..20e141aed 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/scheduling/BukkitPartiesScheduler.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/scheduling/BukkitPartiesScheduler.java @@ -44,13 +44,15 @@ public void runAsync(Runnable runnable) { } @Override - public void runAsyncTaskTimer(Runnable runnable, long seconds) { - bukkitScheduler.runTaskTimerAsynchronously(getPlugin(), runnable, 0, seconds * 20); + public int scheduleAsyncTaskTimer(Runnable runnable, long ticks) { + int taskId = bukkitScheduler.runTaskTimerAsynchronously(getPlugin(), runnable, 0, ticks).getTaskId(); + getCurrentTasks().add(taskId); + return taskId; } @Override - public int scheduleTaskLater(Runnable runnable, long seconds) { - int taskId = bukkitScheduler.runTaskLater(getPlugin(), runnable, seconds * 20).getTaskId(); + public int scheduleTaskLater(Runnable runnable, long ticks) { + int taskId = bukkitScheduler.runTaskLater(getPlugin(), runnable, ticks).getTaskId(); getCurrentTasks().add(taskId); return taskId; } diff --git a/bukkit/src/main/java/com/alessiodp/parties/bukkit/tasks/HomeTask.java b/bukkit/src/main/java/com/alessiodp/parties/bukkit/tasks/HomeTask.java index ec8511923..59f358a6c 100644 --- a/bukkit/src/main/java/com/alessiodp/parties/bukkit/tasks/HomeTask.java +++ b/bukkit/src/main/java/com/alessiodp/parties/bukkit/tasks/HomeTask.java @@ -1,24 +1,79 @@ package com.alessiodp.parties.bukkit.tasks; -import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigMain; +import com.alessiodp.parties.bukkit.configuration.data.BukkitConfigParties; import com.alessiodp.parties.bukkit.configuration.data.BukkitMessages; import com.alessiodp.parties.bukkit.players.objects.BukkitPartyPlayerImpl; -import com.alessiodp.parties.bukkit.players.objects.HomeCooldown; +import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.logging.LogLevel; import com.alessiodp.parties.common.logging.LoggerManager; -import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Player; public class HomeTask implements Runnable { - private Location loc; - private BukkitPartyPlayerImpl player; + private PartiesPlugin plugin; + private BukkitPartyPlayerImpl partyPlayer; + private Player player; + private double distanceLimitSquared; - public HomeTask(BukkitPartyPlayerImpl player, Location loc) { + private long startTime; + private Location startLocation; + + private long delayTime; + private Location homeLocation; + + public HomeTask(PartiesPlugin plugin, BukkitPartyPlayerImpl partyPlayer, Player player, long delayTime, Location homeLocation) { + this.plugin = plugin; + this.partyPlayer = partyPlayer; this.player = player; - this.loc = loc; + distanceLimitSquared = BukkitConfigParties.HOME_DISTANCE * BukkitConfigParties.HOME_DISTANCE; + + startTime = System.currentTimeMillis(); + startLocation = player.getLocation(); + + this.delayTime = delayTime * 1000; // Get milliseconds instead of seconds + this.homeLocation = homeLocation; } + @Override + public void run() { + if (partyPlayer.getHomeDelayTask() != -1) { + if (player.isOnline()) { + if (BukkitConfigParties.HOME_MOVING && player.getLocation().distanceSquared(startLocation) > distanceLimitSquared) { + // Cancel teleport + cancel(); + + partyPlayer.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTDENIED); + LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_HOME_DENIED_MOVING + .replace("{player}", partyPlayer.getName()), true); + return; + } + // Check if delay is timed out + long timestamp = System.currentTimeMillis(); + if (timestamp - startTime > delayTime) { + // Teleport player via sync Bukkit API + plugin.getPartiesScheduler().runSync(() -> { + player.teleport(homeLocation); + partyPlayer.sendMessage(BukkitMessages.ADDCMD_HOME_TELEPORTED); + + LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_TELEPORT_DONE + .replace("{player}", player.getName()), true); + + cancel(); + }); + } + } else { + cancel(); // Player offline + } + } + } + + private void cancel() { + plugin.getPartiesScheduler().cancelTask(partyPlayer.getHomeDelayTask()); + partyPlayer.setHomeDelayTask(-1); + } + + /* @Override public void run() { if (Bukkit.getOfflinePlayer(player.getPlayerUUID()).isOnline()) { @@ -42,5 +97,5 @@ public void run() { homeCooldown.delete(); } } - } + }*/ } diff --git a/bukkit/src/main/resources/bukkit/config.yml b/bukkit/src/main/resources/bukkit/config.yml index 77fd71237..d3a052cd3 100644 --- a/bukkit/src/main/resources/bukkit/config.yml +++ b/bukkit/src/main/resources/bukkit/config.yml @@ -77,7 +77,7 @@ storage: log-name: "log.txt" yaml: database-name: "data.yml" - + sql-based: # SQL based DBs: MySQL, SQLite general-settings: @@ -107,7 +107,7 @@ storage: sqlite: # SQLite is a SQL database that store data into a file database-name: "database.db" - + none: disband-on-leader-left: true # Delete empty parties after tot seconds @@ -122,23 +122,10 @@ additional: # All partymates will use the same command that the leader uses (Rank permission: party.autocommand) # You can configure the leader with rank permissions enable: false - # Important: Blacklist/whitelist your commands to prevent exploits (Pay for example) - # Blacklist/whitelist your commands with a "start-with" check (Block /pay to prevent commands like "/pay bla bla", "/paymember bla", "/payment") - # If you whitelist a command, you will bypass it (if it is blacklisted) - # You can insert '*' for all commands - blacklist: - - "/pay" - - "/money" - whitelist: [] - - censor-system: - # This censor system is used when a player create a party or set description/motd/etc.. - enable: false - case-sensitive: false - contains: [] - starts-with: [] - ends-with: [] - regexes: [] + # Choose which command should be repeated + # You need to use regex here + # By default it will allows any command except /party, /pay or /money) + regex-whitelist: '^(?!(\/party|\/pay|\/money)).*' exp-system: # Documentation here: https://alessiodp.com/docs/parties/expsystem/ @@ -183,6 +170,7 @@ additional: # Special tags: # %exp% = Experience dropped # %number_players% = Number of players in range + # %level% = Current level of the party divide-formula: "%exp% / %number_players%" exp-to-get: # Choose which kind of experience to get @@ -217,8 +205,10 @@ additional: handle-only-mm-mobs: true follow-party: - # When player join in a world, the party will be teleported into it + # When the party leader joins a world, the party will follow him enable: false + # Enable the command /party follow to toggle this feature + toggle-command: false # Type of teleport: # 1 = Teleport into world spawn # 2 = Same point of followed player @@ -232,14 +222,14 @@ additional: # List of worlds that would use follow-party feature ('*' = all worlds) list-worlds: - '*' - + mute: # Enable mute command # If an user use mute command, it will stop to receive every notification enable: false block: invite: true - + placeholders: # This options are used to customize Parties placeholders # You can customize every external placeholder @@ -351,6 +341,7 @@ commands: delete: "delete" deny: "deny" desc: "desc" + follow: "follow" home: "home" ignore: "ignore" info: "info" @@ -370,6 +361,7 @@ commands: sethome: "sethome" spy: "spy" teleport: "teleport" + version: "version" sub-commands: on: "on" off: "off" @@ -395,6 +387,7 @@ commands: - desc - motd - protection + - follow - home - sethome - color @@ -407,8 +400,9 @@ commands: - spy - delete - reload + - version - migrate # End of configuration file dont-edit-this: - version: 4 \ No newline at end of file + version: 5 \ No newline at end of file diff --git a/bukkit/src/main/resources/bukkit/messages.yml b/bukkit/src/main/resources/bukkit/messages.yml index c676a486d..818fb9489 100644 --- a/bukkit/src/main/resources/bukkit/messages.yml +++ b/bukkit/src/main/resources/bukkit/messages.yml @@ -33,34 +33,34 @@ main-commands: accept-receipt: "&a%player% accepted your invite" no-invite: "&cYou have not pending invitation" no-exists: "&cThe invite doesn't exist anymore" - + chat: enabled: "&aChat set to party" disabled: "&aChat set to public" wrong-command: "&cWrong variables: Type &7/party chat [on/off]" - + create: created: '[{"text":"You have created the party %party%.\n","color":"aqua","bold":true},{"text":"Type ","color":"aqua","bold":false},{"text":"/party invite","color":"gray","clickEvent":{"action":"suggest_command","value":"/party invite "}},{"text":" to invite your friend.","color":"aqua"}]' - created-fixed: "&l&bYou have created the fixed party %party%" + created-fixed: "&b&lYou have created the fixed party %party%" name-already-exists: "&cThe party name %party% already exists, choose a different name" name-too-long: "&cThe party name is too long!" name-too-short: "&cThe party name is too short!" invalid-name: "&cInvalid characters. Use: a-Z or 0-9." censored: "&cThe party name contains censored words!" wrong-command: "&cWrong variables: Type &7/party create " - + delete: deleted: "&aParty %party% deleted" deleted-silently: "&aParty %party% deleted silently" broadcast: "&6&lYour party has been deleted" wrong-command: "&cWrong variables: Type &7/party delete [silent]" - + deny: denied: "&7You denied the party invite" deny-receipt: "&7%player% denied your invite" no-invite: "&cYou have not pending invitation" no-exists: "&cThe invite doesn't exist anymore" - + ignore: start-ignore: "&7Ignoring %party% invites" stop-ignore: "&7You stopped ignoring %party%" @@ -70,7 +70,7 @@ main-commands: separator: "&7, " empty: "&7None" wrong-command: "&cWrong variables: Type &7/party ignore [party]" - + info: # Special tags: # List rank members: %list_RANK% (Example: %list_member%, %list_moderator% (%list_leader% remember it's unique) @@ -109,7 +109,7 @@ main-commands: player-in-party: "&c%player% is already in a party" already-invited: "&c%player% was already invited" wrong-command: "&cWrong variables: Type &7/party invite " - + kick: sent: "&aYou kicked %player% from your party!" player-kicked: "&bYou have been kicked from %party%" @@ -130,12 +130,12 @@ main-commands: - "&cUse '&7/party kick &c' to kick the right player" player: '{"text":"","extra":[{"text":"[%number%] ","color":"gray"},{"text":"%username%","color":"gold"},{"text":" [","color":"gray"},{"text":"%party%","color":"aqua"},{"text":"]: last login %lastseen%","color":"gray"}],"clickEvent":{"action":"run_command","value":"/party kick %old_username% %number%"},"hoverEvent":{"action":"show_text","value":{"text":"Kick this player","color":"gold"}}}' wrong-command: "&cWrong variables: Type &7/party kick " - + leave: left: "&b&lYou left the party %party%" broadcast: "&b&l%player% left the party" party-disbanded: "&6&lThe party has been disbanded because the leader left" - + migrate: # Special tags: # %database% = Current database @@ -151,8 +151,9 @@ main-commands: p: # Special tag: %seconds% = Remaining time in seconds cooldown: "&cYou still have to wait %seconds% seconds" + censored: "&cThe message contains censored words!" wrong-command: "&cWrong variables: Type &7/p " - + rank: # Special tag: %rank_name% = Rank wrote by the player changed: "&a%player% rank changed into %rank_name%" @@ -166,17 +167,25 @@ main-commands: player-not-in-party: "&c%player% is not in your party" player-not-in-other-party: "&c%player% doesn't have a party" wrong-command: "&cWrong variables: Type &7/party rank " - + rename: # Special tag: %old% = Old player name renamed: "&aThe party %old% has been renamed into %party%" broadcast: "&6Your party has been renamed into %party%!" wrong-command: "&cWrong variables: Type &7/party rename " wrong-command-admin: "&cWrong variables: Type &7/party rename " - + spy: enabled: "&7Now you are a spy!" disabled: "&7You are no longer a spy" + wrong-command: "&cWrong variables: Type &7/party spy [on/off]" + + version: + # Special tags: + # %version% = Parties version + # %newversion% = Latest Parties version + updated: "&b&lParties &b%version% &7- Developed by &6AlessioDP" + outdated: "&b&lParties &b%version% &7- Developed by &6AlessioDP\n&aNew version found: &2%newversion%" # / = = = = = = = = = = = = = = = = \ @@ -189,7 +198,7 @@ additional-commands: no-manager: "&cYou need to be the manager of the claim" claim-no-exists: "&cClaim not found" wrong-command: "&cWrong variables: Type &7/party claim \n&cPermissions: trust, container & access" - + color: info: "&bYour party color is: %color_code%%color_command%" empty: "&bYour party doesn't have a color" @@ -198,7 +207,7 @@ additional-commands: broadcast: "" wrong-color: "&cColor not found. You can select: red, green or special!" wrong-command: "&cWrong variables: Type &7/party color " - + desc: changed: "&bParty description changed" removed: "&bParty description removed" @@ -219,7 +228,12 @@ additional-commands: skillapi: gained-killer: "&bGained %exp% experience for killing the mob" gained-others: "&b%player% has killed a mob, you gained %exp% experience" - + + follow: + toggle-on: "&aNow your party members will follow your leader" + toggle-off: "&aYour party members will not follow your leader anymore" + wrong-command: "&cWrong variables: Type &7/party follow [on/off]" + home: teleported: "&7Teleported to the party home" # Special tag: %time% = Time of cooldown @@ -230,13 +244,13 @@ additional-commands: no-exists: "&cThe party %party% doesn't exist" wrong-command: "&cWrong variables: Type &7/party home" wrong-command-admin: "&cWrong variables: Type &7/party home [party]" - + join: joined: "&aYou joined the party %party%" player-joined: "&b&l%player% joined in the party" wrong-password: "&cWrong password!" wrong-command: "&cWrong variables: Type &7/party join [password]" - + list: # Special tags: %number% = Number of parties online | %page% = Current list page | %maxpages% = How many pages exists header: "&b============ &lOnline Parties List &r&b============" @@ -255,18 +269,18 @@ additional-commands: invalid-chars: "&cInvalid characters. You can also use '. , /'. Min 3 and max 100 chars." censored: "&cThe MOTD contains censored words!" wrong-command: "&cWrong variables: Type &7/party motd " - + mute: toggle-on: "&7You have disabled notifications!" toggle-off: "&7You have enabled notifications!" wrong-command: "&cWrong variables: Type &7/party mute [on/off]" - + password: changed: "&aParty password changed" removed: "&aParty password removed" broadcast: "" invalid-chars: "&cInvalid characters. Use: a-Z or 0-9. Min 1 and max 16 chars." - wrong-command: "&cWrong variables: Type &7/party password " + wrong-command: "&cWrong variables: Type &7/party password " protection: toggle-on: "&aNow your party is protected by friendly fire" @@ -286,7 +300,7 @@ additional-commands: player-teleported: "&bTeleported to %player%" # Special tag: %seconds% = Remaining time in seconds cooldown: "&cYou have to wait %seconds% seconds!" - + vault: # Special tag: %price% = Price of the command no-money: @@ -316,7 +330,7 @@ other: fixed-parties: # Joined into a default party default-join: "&bYou entered into %party%" - + join-leave: server-join: "&b%player% is online!" server-leave: "&7%player% is offline!" @@ -335,11 +349,11 @@ help: main-commands: help: '{"text":"","extra":[{"text":"/party help [page]","color":"aqua"},{"text":" - Show help pages","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party help "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' accept: '{"text":"","extra":[{"text":"/party accept","color":"aqua"},{"text":" - Accept a party invitation","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party accept"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - chat: '{"text":"","extra":[{"text":"/party chat [on/off]","color":"aqua"},{"text":" - Toggle the party chat","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party chat "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + chat: '{"text":"","extra":[{"text":"/party chat [on/off]","color":"aqua"},{"text":" - Toggle party chat","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party chat "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' create: '{"text":"","extra":[{"text":"/party create ","color":"aqua"},{"text":" - Create a new party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party create "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' delete: '{"text":"","extra":[{"text":"/party delete ","color":"aqua"},{"text":" - Delete the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party delete "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' deny: '{"text":"","extra":[{"text":"/party deny","color":"aqua"},{"text":" - Deny a party invitation","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party deny"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - ignore: '{"text":"","extra":[{"text":"/party ignore [party]","color":"aqua"},{"text":" - Add/remove/show parties ignored","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party ignore "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + ignore: '{"text":"","extra":[{"text":"/party ignore [party]","color":"aqua"},{"text":" - Add/remove/show ignored parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party ignore "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' info: '{"text":"","extra":[{"text":"/party info [party]","color":"aqua"},{"text":" - Show party information","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party info "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' invite: '{"text":"","extra":[{"text":"/party invite ","color":"aqua"},{"text":" - Invite a player to your party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party invite "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' kick: '{"text":"","extra":[{"text":"/party kick ","color":"aqua"},{"text":" - Kick a player from your party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party kick "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' @@ -347,22 +361,24 @@ help: migrate: '{"text":"","extra":[{"text":"/party migrate ","color":"aqua"},{"text":" - Copy database into a new one","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party migrate "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' p: '{"text":"","extra":[{"text":"/p ","color":"aqua"},{"text":" - Send a message to the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/p "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' rank: '{"text":"","extra":[{"text":"/party rank ","color":"aqua"},{"text":" - Change rank of the player","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rank "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - reload: '{"text":"","extra":[{"text":"/party reload","color":"aqua"},{"text":" - Reload the configuration","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party reload"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - rename: '{"text":"","extra":[{"text":"/party rename [party] ","color":"aqua"},{"text":" - Renames a party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rename "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - spy: '{"text":"","extra":[{"text":"/party spy","color":"aqua"},{"text":" - See messages from other parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party spy"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + reload: '{"text":"","extra":[{"text":"/party reload","color":"aqua"},{"text":" - Reload Parties configuration files","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party reload"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + rename: '{"text":"","extra":[{"text":"/party rename [party] ","color":"aqua"},{"text":" - Rename the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rename "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + spy: '{"text":"","extra":[{"text":"/party spy [on/off]","color":"aqua"},{"text":" - Spy messages of other parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party spy "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + version: '{"text":"","extra":[{"text":"/party version","color":"aqua"},{"text":" - Show Parties information","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party version"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' additional-commands: claim: '{"text":"","extra":[{"text":"/party claim ","color":"aqua"},{"text":" - Grant permissions to the claim","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party claim "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - color: '{"text":"","extra":[{"text":"/party color ","color":"aqua"},{"text":" - Change color of the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party color "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - desc: '{"text":"","extra":[{"text":"/party desc ","color":"aqua"},{"text":" - Add/remove description","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party desc "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + color: '{"text":"","extra":[{"text":"/party color ","color":"aqua"},{"text":" - Change party color","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party color "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + desc: '{"text":"","extra":[{"text":"/party desc ","color":"aqua"},{"text":" - Set/remove party description","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party desc "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + follow: '{"text":"","extra":[{"text":"/party follow [on/off]","color":"aqua"},{"text":" - Toggle follow leader","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party follow "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' home: '{"text":"","extra":[{"text":"/party home [party]","color":"aqua"},{"text":" - Teleport to the party home","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party home "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - join: '{"text":"","extra":[{"text":"/party join [password]","color":"aqua"},{"text":" - Join into a party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party join "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + join: '{"text":"","extra":[{"text":"/party join [password]","color":"aqua"},{"text":" - Join into the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party join "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' list: '{"text":"","extra":[{"text":"/party list [page]","color":"aqua"},{"text":" - List of online parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party list "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - motd: '{"text":"","extra":[{"text":"/party motd ","color":"aqua"},{"text":" - Add/remove motd","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party motd "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + motd: '{"text":"","extra":[{"text":"/party motd ","color":"aqua"},{"text":" - Set/remove party motd","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party motd "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' mute: '{"text":"","extra":[{"text":"/party mute [on/off]","color":"aqua"},{"text":" - Toggle notifications","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party mute "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' password: '{"text":"","extra":[{"text":"/party password ","color":"aqua"},{"text":" - Change party password","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party password "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' protection: '{"text":"","extra":[{"text":"/party protection [on/off]","color":"aqua"},{"text":" - Toggle friendly fire protection","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party protection "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - sethome: '{"text":"","extra":[{"text":"/party sethome [remove]","color":"aqua"},{"text":" - Set the party home","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party sethome "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + sethome: '{"text":"","extra":[{"text":"/party sethome [remove]","color":"aqua"},{"text":" - Set/remove party home","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party sethome "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' teleport: '{"text":"","extra":[{"text":"/party teleport","color":"aqua"},{"text":" - Teleport your party to you","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party teleport"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' dont-edit-this: - version: 5 \ No newline at end of file + version: 6 \ No newline at end of file diff --git a/bukkit/src/main/resources/bukkit/parties.yml b/bukkit/src/main/resources/bukkit/parties.yml index f08d1732e..0fad0fc35 100644 --- a/bukkit/src/main/resources/bukkit/parties.yml +++ b/bukkit/src/main/resources/bukkit/parties.yml @@ -14,6 +14,8 @@ general: # Regex of chars (Use \\ instead of \ if you use "text" format) # For ALL utf characters use '[\p{L}\s]+' allowed-characters: '[a-zA-Z0-9]+' + # Censor party name with a regex + censor-regex: '' minimum-length: 3 maximum-length: 10 # Cooldown for rename command (in seconds) @@ -32,7 +34,7 @@ general: global: 60 # Prevent to invite the same player for X seconds individual: 0 - + chat: # Allow sending messages with color codes (&1, &2, etc..) # Permission required @@ -41,6 +43,8 @@ general: enable-toggle-command: true # Chat cooldown in seconds chat-cooldown: 0 + # Censor party message with a regex + censor-regex: '' direct: # Directly write in party chat by adding a prefix before (Example: @this is a party message) enable: false @@ -137,7 +141,7 @@ additional: yourcustomcolor: command: "special" code: "&9&n" - + description: enable: true minimum-length: 3 @@ -145,7 +149,9 @@ additional: # Regex of chars (Use \\ instead of \ if you use "text" format) # For ALL utf characters use '[\p{L}\s]+' allowed-characters: '[a-zA-Z0-9\ \.\,\-\_]+' - + # Censor description with a regex + censor-regex: '' + fixed-system: # Allow the creation of parties without leader (they are called "fixed") enable: false @@ -153,7 +159,7 @@ additional: # When a player join into the server, put him into a party (if he doesn't have one) enable: false party: "default" - + friendly-fire: # Prevent fights between players of a party enable: true @@ -167,7 +173,7 @@ additional: # Enable friendly fire protection for CrackShot weapons crackshot: enable: false - + home: enable: false # Party home delay before teleport, in seconds @@ -179,7 +185,7 @@ additional: moving: true # Walk distance to deny the teleport3 distance: 3 - + join-password: # Password system (This will enable "/party join ", you can still disable it via permissions) # Allows the creation of a party with a password (/party create ) @@ -192,14 +198,14 @@ additional: encode: "UTF-8" minimum-length: 1 maximum-length: 16 - + kills: enable: false which-save: neutral-mobs: false hostile-mobs: false players: true - + list: enable: true # Sort system: @@ -216,7 +222,7 @@ additional: limit-parties: -1 # Hide some parties from the list (Type the name of party) hidden-parties: [] - + motd: enable: true minimum-length: 3 @@ -228,7 +234,9 @@ additional: allowed-characters: '[a-zA-Z0-9\ \.\,\-\_]+' # New line code is \n, you need to escape the first \ by adding another \ before new-line-code: '\\n' - + # Censor motd with a regex + censor-regex: '' + teleport: # Enable teleport command, teleport every partymate to the command sender enable: false diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index 00dafd47c..0bf43cab6 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -21,6 +21,8 @@ permissions: description: Allow access to /party deny parties.user.desc: description: Allow access to /party desc + parties.user.follow: + description: Allow access to /party follow parties.user.help: description: Allow access to /party or /party help parties.user.ignore: @@ -89,6 +91,8 @@ permissions: description: Allow access to /party spy parties.admin.updates: description: Send a message if there is an update + parties.admin.version: + description: Allow access to /party version parties.admin.home.others: description: Allow access to /party home on other homes parties.admin.protection.bypass: @@ -106,6 +110,7 @@ permissions: parties.user.create: true parties.user.deny: true parties.user.desc: true + parties.user.follow: true parties.user.help: true parties.user.ignore: true parties.user.info: true @@ -146,6 +151,7 @@ permissions: parties.admin.rename.others: true parties.admin.spy: true parties.admin.updates: true + parties.admin.version: true parties.admin.home.others: true parties.admin.protection.bypass: true parties.admin.vaultbypass: true diff --git a/bungee/pom.xml b/bungee/pom.xml index b2c02e0da..d7ba246ab 100644 --- a/bungee/pom.xml +++ b/bungee/pom.xml @@ -3,7 +3,7 @@ com.alessiodp.parties Parties - 2.4.7 + 2.5.0 parties-bungee diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandDispatcher.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandDispatcher.java deleted file mode 100644 index f4adae7f6..000000000 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandDispatcher.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.alessiodp.parties.bungeecord.commands; - -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.CommandDispatcher; - -public class BungeeCommandDispatcher extends CommandDispatcher { - - public BungeeCommandDispatcher(PartiesPlugin instance) { - super(instance); - } -} \ No newline at end of file diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandImpl.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandImpl.java deleted file mode 100644 index da58de44e..000000000 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.alessiodp.parties.bungeecord.commands; - -import com.alessiodp.parties.bungeecord.user.BungeeUser; -import com.alessiodp.parties.common.commands.CommandDispatcher; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.plugin.Command; - -class BungeeCommandImpl extends Command { - private CommandDispatcher exe = null; - //private TabCompleter tabCompleter; - - BungeeCommandImpl(String name) { - super(name); - } - - @Override - public void execute(CommandSender commandSender, String[] strings) { - if (exe != null) { - exe.onCommand(new BungeeUser(commandSender), super.getName(), strings); - } - } - - void setExecutor(CommandDispatcher exe) { - this.exe = exe; - } -} diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandManager.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandManager.java index 4c74226f1..4e12b95ae 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandManager.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/BungeeCommandManager.java @@ -2,15 +2,12 @@ import com.alessiodp.parties.bungeecord.BungeePartiesPlugin; import com.alessiodp.parties.bungeecord.bootstrap.BungeePartiesBootstrap; -import com.alessiodp.parties.bungeecord.commands.executors.BungeeCommandTeleport; +import com.alessiodp.parties.bungeecord.commands.main.BungeeCommandP; +import com.alessiodp.parties.bungeecord.commands.main.BungeeCommandParty; +import com.alessiodp.parties.bungeecord.commands.utils.BungeeCommandImpl; import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.commands.CommandManager; -import com.alessiodp.parties.common.commands.list.CommonCommands; -import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.configuration.data.ConfigParties; -import com.alessiodp.parties.common.logging.LogLevel; -import com.alessiodp.parties.common.logging.LoggerManager; public class BungeeCommandManager extends CommandManager { @@ -26,12 +23,8 @@ protected void prepareCommands() { @Override protected void registerCommands() { - dispatcher = new BungeeCommandDispatcher(plugin); - super.registerCommands(); - - // Teleport - if (ConfigParties.TELEPORT_ENABLE) - dispatcher.register(CommonCommands.TELEPORT, new BungeeCommandTeleport(plugin)); + commandParty = new BungeeCommandParty(plugin); + commandP = new BungeeCommandP(plugin); } @Override @@ -39,18 +32,12 @@ protected void setupCommands() { try { BungeePartiesBootstrap bungeePlugin = ((BungeePartiesPlugin) plugin).getBootstrap(); - BungeeCommandImpl cmdParty = new BungeeCommandImpl(ConfigMain.COMMANDS_CMD_PARTY); - BungeeCommandImpl cmdP = new BungeeCommandImpl(ConfigMain.COMMANDS_CMD_P); - + BungeeCommandImpl cmdParty = new BungeeCommandImpl(ConfigMain.COMMANDS_CMD_PARTY, commandParty); bungeePlugin.getProxy().getPluginManager().registerCommand(bungeePlugin, cmdParty); - bungeePlugin.getProxy().getPluginManager().registerCommand(bungeePlugin, cmdP); - cmdParty.setExecutor(dispatcher); - cmdP.setExecutor(dispatcher); - - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_COMMANDS_REGISTER_POST - .replace("{value}", Integer.toString(dispatcher.getCommandsNumber())), true); - }catch (Exception e) { + BungeeCommandImpl cmdP = new BungeeCommandImpl(ConfigMain.COMMANDS_CMD_P, commandP); + bungeePlugin.getProxy().getPluginManager().registerCommand(bungeePlugin, cmdP); + } catch (Exception e) { e.printStackTrace(); } } diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandP.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandP.java new file mode 100644 index 000000000..e30e75d6c --- /dev/null +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandP.java @@ -0,0 +1,11 @@ +package com.alessiodp.parties.bungeecord.commands.main; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.main.CommandP; + +public class BungeeCommandP extends CommandP { + + public BungeeCommandP(PartiesPlugin instance) { + super(instance); + } +} diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandParty.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandParty.java new file mode 100644 index 000000000..23049d4ae --- /dev/null +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/main/BungeeCommandParty.java @@ -0,0 +1,23 @@ +package com.alessiodp.parties.bungeecord.commands.main; + +import com.alessiodp.parties.bungeecord.commands.sub.BungeeCommandTeleport; +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.list.CommonCommands; +import com.alessiodp.parties.common.commands.main.CommandParty; +import com.alessiodp.parties.common.configuration.data.ConfigParties; + +public class BungeeCommandParty extends CommandParty { + + public BungeeCommandParty(PartiesPlugin instance) { + super(instance); + } + + @Override + public void reload() { + super.reload(); + + // Teleport + if (ConfigParties.TELEPORT_ENABLE) + super.register(CommonCommands.TELEPORT, new BungeeCommandTeleport(plugin)); + } +} diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/executors/BungeeCommandTeleport.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/sub/BungeeCommandTeleport.java similarity index 92% rename from bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/executors/BungeeCommandTeleport.java rename to bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/sub/BungeeCommandTeleport.java index 5621b9681..c5df8b098 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/executors/BungeeCommandTeleport.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/sub/BungeeCommandTeleport.java @@ -1,10 +1,10 @@ -package com.alessiodp.parties.bungeecord.commands.executors; +package com.alessiodp.parties.bungeecord.commands.sub; import com.alessiodp.parties.bungeecord.BungeePartiesPlugin; import com.alessiodp.parties.bungeecord.configuration.data.BungeeMessages; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.CommandData; -import com.alessiodp.parties.common.commands.executors.CommandTeleport; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.commands.sub.CommandTeleport; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; @@ -54,7 +54,7 @@ public void onCommand(CommandData commandData) { */ if (unixNow != -1) { plugin.getCooldownManager().getTeleportCooldown().put(pp.getPlayerUUID(), unixNow); - plugin.getPartiesScheduler().scheduleTaskLater(new TeleportTask(plugin, pp.getPlayerUUID()), ConfigParties.TELEPORT_COOLDOWN); + plugin.getPartiesScheduler().scheduleTaskLater(new TeleportTask(plugin, pp.getPlayerUUID()), ConfigParties.TELEPORT_COOLDOWN * 20L); LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_TASK_TELEPORT_START .replace("{value}", Integer.toString(ConfigParties.TELEPORT_COOLDOWN * 20)) diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/utils/BungeeCommandImpl.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/utils/BungeeCommandImpl.java new file mode 100644 index 000000000..33adcfe3f --- /dev/null +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/commands/utils/BungeeCommandImpl.java @@ -0,0 +1,33 @@ +package com.alessiodp.parties.bungeecord.commands.utils; + +import com.alessiodp.parties.bungeecord.user.BungeeUser; +import com.alessiodp.parties.common.commands.utils.PartiesCommandExecutor; +import com.alessiodp.parties.common.configuration.data.ConfigMain; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.TabExecutor; + +import java.util.ArrayList; + +public class BungeeCommandImpl extends Command implements TabExecutor { + private PartiesCommandExecutor executor; + + public BungeeCommandImpl(String name, PartiesCommandExecutor executor) { + super(name); + this.executor = executor; + + } + + @Override + public void execute(CommandSender commandSender, String[] args) { + executor.onCommand(new BungeeUser(commandSender), this.getName(), args); + } + + @Override + public Iterable onTabComplete(CommandSender commandSender, String[] args) { + if (ConfigMain.COMMANDS_TABSUPPORT) { + return executor.onTabComplete(new BungeeUser(commandSender), args); + } + return new ArrayList<>(); + } +} diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/configuration/data/BungeeConfigMain.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/configuration/data/BungeeConfigMain.java index 971b5dd15..b91ee1e5f 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/configuration/data/BungeeConfigMain.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/configuration/data/BungeeConfigMain.java @@ -50,6 +50,7 @@ public void loadDefaults() { ConfigMain.COMMANDS_ORDER.add("chat"); ConfigMain.COMMANDS_ORDER.add("desc"); ConfigMain.COMMANDS_ORDER.add("motd"); + ConfigMain.COMMANDS_ORDER.add("follow"); ConfigMain.COMMANDS_ORDER.add("color"); ConfigMain.COMMANDS_ORDER.add("teleport"); ConfigMain.COMMANDS_ORDER.add("password"); @@ -59,6 +60,7 @@ public void loadDefaults() { ConfigMain.COMMANDS_ORDER.add("spy"); ConfigMain.COMMANDS_ORDER.add("delete"); ConfigMain.COMMANDS_ORDER.add("reload"); + ConfigMain.COMMANDS_ORDER.add("version"); ConfigMain.COMMANDS_ORDER.add("migrate"); } diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/BungeeEventManager.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/BungeeEventManager.java index 5fe33a164..e798020fe 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/BungeeEventManager.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/BungeeEventManager.java @@ -1,6 +1,7 @@ package com.alessiodp.parties.bungeecord.events; import com.alessiodp.parties.api.events.bungee.BungeePartiesEvent; +import com.alessiodp.parties.api.events.bungee.unique.BungeePartiesPartyFollowEvent; import com.alessiodp.parties.api.events.common.party.IPartyPostCreateEvent; import com.alessiodp.parties.api.events.common.party.IPartyPostDeleteEvent; import com.alessiodp.parties.api.events.common.party.IPartyPreCreateEvent; @@ -12,6 +13,7 @@ import com.alessiodp.parties.api.events.common.player.IPlayerPreJoinEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPreLeaveEvent; import com.alessiodp.parties.bungeecord.BungeePartiesPlugin; +import com.alessiodp.parties.bungeecord.events.bungee.PartyFollowEventHook; import com.alessiodp.parties.bungeecord.events.common.party.PartyPostCreateEventHook; import com.alessiodp.parties.bungeecord.events.common.party.PartyPostDeleteEventHook; import com.alessiodp.parties.bungeecord.events.common.party.PartyPreCreateEventHook; @@ -87,6 +89,10 @@ public IPlayerPostLeaveEvent preparePlayerPostLeaveEvent(PartyPlayer player, Par return new PlayerPostLeaveEventHook(player, party, isKicked, kickedBy); } + public BungeePartiesPartyFollowEvent preparePartyFollowEvent(Party party, String server) { + return new PartyFollowEventHook(party, server); + } + @Override public void callEvent(PartiesEvent event) { BungeePartiesEvent bungeeEvent = (BungeePartiesEvent) event; diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/bungee/PartyFollowEventHook.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/bungee/PartyFollowEventHook.java new file mode 100644 index 000000000..eb5921bd8 --- /dev/null +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/events/bungee/PartyFollowEventHook.java @@ -0,0 +1,38 @@ +package com.alessiodp.parties.bungeecord.events.bungee; + +import com.alessiodp.parties.api.events.bungee.unique.BungeePartiesPartyFollowEvent; +import com.alessiodp.parties.api.interfaces.Party; +import org.jetbrains.annotations.NotNull; + +public class PartyFollowEventHook extends BungeePartiesPartyFollowEvent { + private boolean cancelled; + private Party party; + private String joinedServer; + + public PartyFollowEventHook(Party party, String joinedServer) { + this.party = party; + this.joinedServer = joinedServer; + } + + @NotNull + @Override + public Party getParty() { + return party; + } + + @NotNull + @Override + public String getJoinedServer() { + return joinedServer; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/listeners/BungeeFollowListener.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/listeners/BungeeFollowListener.java index a5cc0ccf5..8873d4dae 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/listeners/BungeeFollowListener.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/listeners/BungeeFollowListener.java @@ -1,8 +1,10 @@ package com.alessiodp.parties.bungeecord.listeners; +import com.alessiodp.parties.api.events.bungee.unique.BungeePartiesPartyFollowEvent; import com.alessiodp.parties.bungeecord.BungeePartiesPlugin; import com.alessiodp.parties.bungeecord.configuration.data.BungeeConfigMain; import com.alessiodp.parties.bungeecord.configuration.data.BungeeMessages; +import com.alessiodp.parties.bungeecord.events.BungeeEventManager; import com.alessiodp.parties.bungeecord.user.BungeeUser; import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.configuration.Constants; @@ -15,6 +17,7 @@ import net.md_5.bungee.event.EventHandler; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class BungeeFollowListener implements Listener { @@ -33,37 +36,48 @@ public void onConnected(ServerSwitchEvent event) { if (event.getPlayer().getServer() == null) return; - if (allowedServer(event.getPlayer().getServer().getInfo().getName())) { - PartyPlayerImpl player = plugin.getPlayerManager().getPlayer(event.getPlayer().getUniqueId()); - PartyImpl party = plugin.getPartyManager().getParty(player.getPartyName()); - if (party != null) { - if (party.getLeader().equals(player.getPlayerUUID())) { - - // Let other players follow him - String playerServer = event.getPlayer().getServer().getInfo().getName(); - ServerInfo serverInfo = plugin.getBootstrap().getProxy().getServerInfo(playerServer); - for (UUID uuid : party.getMembers()) { - BungeeUser member = (BungeeUser) plugin.getPlayer(uuid); - if (member != null - && !member.getUUID().equals(player.getPlayerUUID()) - && !member.getServerName().equals(serverInfo.getName())) { - - plugin.getPlayerManager().getPlayer(uuid).sendMessage(BungeeMessages.OTHER_FOLLOW_SERVER - .replace("%server%", serverInfo.getName())); - member.connectTo(serverInfo); - - if (BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_ENABLE) { - plugin.getBootstrap().getProxy().getScheduler().schedule(plugin.getBootstrap(), () -> { - for (String command : BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_COMMANDS) { - plugin.getBootstrap().getProxy().getPlayer(member.getUUID()).chat(command); + CompletableFuture.runAsync(() -> { + if (allowedServer(event.getPlayer().getServer().getInfo().getName())) { + PartyPlayerImpl player = plugin.getPlayerManager().getPlayer(event.getPlayer().getUniqueId()); + PartyImpl party = plugin.getPartyManager().getParty(player.getPartyName()); + if (party != null && party.isFollowEnabled()) { + if (party.getLeader().equals(player.getPlayerUUID())) { + String playerServer = event.getPlayer().getServer().getInfo().getName(); + ServerInfo serverInfo = plugin.getBootstrap().getProxy().getServerInfo(playerServer); + + // Calling API event + BungeePartiesPartyFollowEvent partyFollowEvent = ((BungeeEventManager) plugin.getEventManager()).preparePartyFollowEvent(party, playerServer); + plugin.getEventManager().callEvent(partyFollowEvent); + if (!partyFollowEvent.isCancelled()) { + // Let other players follow him + for (UUID uuid : party.getMembers()) { + BungeeUser member = (BungeeUser) plugin.getPlayer(uuid); + if (member != null + && !member.getUUID().equals(player.getPlayerUUID()) + && !member.getServerName().equals(serverInfo.getName())) { + + plugin.getPlayerManager().getPlayer(uuid).sendMessage(BungeeMessages.OTHER_FOLLOW_SERVER + .replace("%server%", serverInfo.getName())); + member.connectTo(serverInfo); + + if (BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_ENABLE) { + plugin.getBootstrap().getProxy().getScheduler().schedule(plugin.getBootstrap(), () -> { + for (String command : BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_COMMANDS) { + plugin.getBootstrap().getProxy().getPlayer(member.getUUID()).chat(command); + } + }, BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_DELAY, TimeUnit.MILLISECONDS); } - }, BungeeConfigMain.ADDITIONAL_FOLLOW_PERFORMCMD_DELAY, TimeUnit.MILLISECONDS); + } } } } } } - } + }, plugin.getPartiesScheduler().getEventsExecutor()) + .exceptionally(ex -> { + ex.printStackTrace(); + return null; + }); } private boolean allowedServer(String serverName) { diff --git a/bungee/src/main/java/com/alessiodp/parties/bungeecord/scheduling/BungeePartiesScheduler.java b/bungee/src/main/java/com/alessiodp/parties/bungeecord/scheduling/BungeePartiesScheduler.java index 6e6584f4a..3b523f659 100644 --- a/bungee/src/main/java/com/alessiodp/parties/bungeecord/scheduling/BungeePartiesScheduler.java +++ b/bungee/src/main/java/com/alessiodp/parties/bungeecord/scheduling/BungeePartiesScheduler.java @@ -45,8 +45,10 @@ public void runAsync(Runnable runnable) { } @Override - public void runAsyncTaskTimer(Runnable runnable, long seconds) { - bungeeScheduler.schedule(getPlugin(), runnable, 0, seconds, TimeUnit.SECONDS); + public int scheduleAsyncTaskTimer(Runnable runnable, long seconds) { + int taskId = bungeeScheduler.schedule(getPlugin(), runnable, seconds * 50, TimeUnit.MILLISECONDS).getId(); + getCurrentTasks().add(taskId); + return taskId; } @Override diff --git a/bungee/src/main/resources/bungee/config.yml b/bungee/src/main/resources/bungee/config.yml index 2eebfb54d..3e0519d66 100644 --- a/bungee/src/main/resources/bungee/config.yml +++ b/bungee/src/main/resources/bungee/config.yml @@ -68,7 +68,7 @@ storage: log-name: "log.txt" yaml: database-name: "data.yml" - + sql-based: # SQL based DBs: MySQL, SQLite general-settings: @@ -98,7 +98,7 @@ storage: sqlite: # SQLite is a SQL database that store data into a file database-name: "database.db" - + none: disband-on-leader-left: true # Delete empty parties after tot seconds @@ -113,27 +113,16 @@ additional: # All partymates will use the same command that the leader uses (Rank permission: party.autocommand) # You can configure the leader with rank permissions enable: false - # Important: Blacklist/whitelist your commands to prevent exploits (Pay for example) - # Blacklist/whitelist your commands with a "start-with" check (Block /pay to prevent commands like "/pay bla bla", "/paymember bla", "/payment") - # If you whitelist a command, you will bypass it (if it is blacklisted) - # You can insert '*' for all commands - blacklist: - - "/pay" - - "/money" - whitelist: [] - - censor-system: - # This censor system is used when a player create a party or set description/motd/etc.. - enable: false - case-sensitive: false - contains: [] - starts-with: [] - ends-with: [] - regexes: [] + # Choose which command should be repeated + # You need to use regex here + # By default it will allows any command except /party, /pay or /money) + regex-whitelist: '^(?!(\/party|\/pay|\/money)).*' follow-party: - # When a player join a server, the entire party will follow him + # When the party leader joins a server, the party will follow him enable: false + # Enable the command /party follow to toggle this feature + toggle-command: false perform-commands: enable: false delay: 2000 @@ -149,7 +138,7 @@ additional: enable: false block: invite: true - + placeholders: # This options are used to customize Parties placeholders # You can customize every external placeholder @@ -172,6 +161,8 @@ additional: # | COMMANDS SETTINGS | # \ = = = = = = = = = = = = = = = = / commands: + # Enable tab support (/party to see every allowed command) + tab-support: true help-pages: commands-per-page: 9 main-commands: @@ -185,6 +176,7 @@ commands: delete: "delete" deny: "deny" desc: "desc" + follow: "follow" ignore: "ignore" info: "info" invite: "invite" @@ -201,6 +193,7 @@ commands: rename: "rename" spy: "spy" teleport: "teleport" + version: "version" sub-commands: on: "on" off: "off" @@ -225,6 +218,7 @@ commands: - chat - desc - motd + - follow - color - teleport - password @@ -234,8 +228,9 @@ commands: - spy - delete - reload + - version - migrate # End of configuration file dont-edit-this: - version: 3 \ No newline at end of file + version: 4 \ No newline at end of file diff --git a/bungee/src/main/resources/bungee/messages.yml b/bungee/src/main/resources/bungee/messages.yml index 571b51a03..8e477a543 100644 --- a/bungee/src/main/resources/bungee/messages.yml +++ b/bungee/src/main/resources/bungee/messages.yml @@ -33,34 +33,34 @@ main-commands: accept-receipt: "&a%player% accepted your invite" no-invite: "&cYou have not pending invitation" no-exists: "&cThe invite doesn't exist anymore" - + chat: enabled: "&aChat set to party" disabled: "&aChat set to public" wrong-command: "&cWrong variables: Type &7/party chat [on/off]" - + create: created: '[{"text":"You have created the party %party%.\n","color":"aqua","bold":true},{"text":"Type ","color":"aqua","bold":false},{"text":"/party invite","color":"gray","clickEvent":{"action":"suggest_command","value":"/party invite "}},{"text":" to invite your friend.","color":"aqua"}]' - created-fixed: "&l&bYou have created the fixed party %party%" + created-fixed: "&b&lYou have created the fixed party %party%" name-already-exists: "&cThe party name %party% already exists, choose a different name" name-too-long: "&cThe party name is too long!" name-too-short: "&cThe party name is too short!" invalid-name: "&cInvalid characters. Use: a-Z or 0-9." censored: "&cThe party name contains censored words!" wrong-command: "&cWrong variables: Type &7/party create " - + delete: deleted: "&aParty %party% deleted" deleted-silently: "&aParty %party% deleted silently" broadcast: "&6&lYour party has been deleted" wrong-command: "&cWrong variables: Type &7/party delete [silent]" - + deny: denied: "&7You denied the party invite" deny-receipt: "&7%player% denied your invite" no-invite: "&cYou have not pending invitation" no-exists: "&cThe invite doesn't exist anymore" - + ignore: start-ignore: "&7Ignoring %party% invites" stop-ignore: "&7You stopped ignoring %party%" @@ -70,7 +70,7 @@ main-commands: separator: "&7, " empty: "&7None" wrong-command: "&cWrong variables: Type &7/party ignore [party]" - + info: # Special tags: # List rank members: %list_RANK% (Example: %list_member%, %list_moderator% (%list_leader% remember it's unique) @@ -151,6 +151,7 @@ main-commands: p: # Special tag: %seconds% = Remaining time in seconds cooldown: "&cYou still have to wait %seconds% seconds" + censored: "&cThe message contains censored words!" wrong-command: "&cWrong variables: Type &7/p " rank: @@ -177,6 +178,14 @@ main-commands: spy: enabled: "&7Now you are a spy!" disabled: "&7You are no longer a spy" + wrong-command: "&cWrong variables: Type &7/party spy [on/off]" + + version: + # Special tags: + # %version% = Parties version + # %newversion% = Latest Parties version + updated: "&b&lParties &b%version% &7- Developed by &6AlessioDP" + outdated: "&b&lParties &b%version% &7- Developed by &6AlessioDP\n&aNew version found: &2%newversion%" # / = = = = = = = = = = = = = = = = \ @@ -200,6 +209,11 @@ additional-commands: censored: "&cThe description contains censored words!" wrong-command: "&cWrong variables: Type &7/party desc " + follow: + toggle-on: "&aNow your party members will follow your leader" + toggle-off: "&aYour party members will not follow your leader anymore" + wrong-command: "&cWrong variables: Type &7/party follow [on/off]" + join: joined: "&aYou joined the party %party%" player-joined: "&b&l%player% joined in the party" @@ -235,7 +249,7 @@ additional-commands: removed: "&aParty password removed" broadcast: "" invalid-chars: "&cInvalid characters. Use: a-Z or 0-9. Min 1 and max 16 chars." - wrong-command: "&cWrong variables: Type &7/party password " + wrong-command: "&cWrong variables: Type &7/party password " teleport: teleporting: "&7Teleporting your party here!" @@ -243,6 +257,7 @@ additional-commands: # Special tag: %seconds% = Remaining time in seconds cooldown: "&cYou have to wait %seconds% seconds!" + # / = = = = = = = = = = = = = = = = \ # | OTHER MESSAGES | # \ = = = = = = = = = = = = = = = = / @@ -254,7 +269,7 @@ other: fixed-parties: # Joined into a default party default-join: "&bYou entered into %party%" - + join-leave: server-join: "&b%player% is online!" server-leave: "&7%player% is offline!" @@ -273,11 +288,11 @@ help: main-commands: help: '{"text":"","extra":[{"text":"/party help [page]","color":"aqua"},{"text":" - Show help pages","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party help "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' accept: '{"text":"","extra":[{"text":"/party accept","color":"aqua"},{"text":" - Accept a party invitation","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party accept"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - chat: '{"text":"","extra":[{"text":"/party chat [on/off]","color":"aqua"},{"text":" - Toggle the party chat","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party chat "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + chat: '{"text":"","extra":[{"text":"/party chat [on/off]","color":"aqua"},{"text":" - Toggle party chat","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party chat "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' create: '{"text":"","extra":[{"text":"/party create ","color":"aqua"},{"text":" - Create a new party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party create "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' delete: '{"text":"","extra":[{"text":"/party delete ","color":"aqua"},{"text":" - Delete the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party delete "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' deny: '{"text":"","extra":[{"text":"/party deny","color":"aqua"},{"text":" - Deny a party invitation","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party deny"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - ignore: '{"text":"","extra":[{"text":"/party ignore [party]","color":"aqua"},{"text":" - Add/remove/show parties ignored","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party ignore "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + ignore: '{"text":"","extra":[{"text":"/party ignore [party]","color":"aqua"},{"text":" - Add/remove/show ignored parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party ignore "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' info: '{"text":"","extra":[{"text":"/party info [party]","color":"aqua"},{"text":" - Show party information","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party info "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' invite: '{"text":"","extra":[{"text":"/party invite ","color":"aqua"},{"text":" - Invite a player to your party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party invite "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' kick: '{"text":"","extra":[{"text":"/party kick ","color":"aqua"},{"text":" - Kick a player from your party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party kick "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' @@ -285,15 +300,17 @@ help: migrate: '{"text":"","extra":[{"text":"/party migrate ","color":"aqua"},{"text":" - Copy database into a new one","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party migrate "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' p: '{"text":"","extra":[{"text":"/p ","color":"aqua"},{"text":" - Send a message to the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/p "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' rank: '{"text":"","extra":[{"text":"/party rank ","color":"aqua"},{"text":" - Change rank of the player","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rank "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - reload: '{"text":"","extra":[{"text":"/party reload","color":"aqua"},{"text":" - Reload the configuration","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party reload"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - rename: '{"text":"","extra":[{"text":"/party rename [party] ","color":"aqua"},{"text":" - Renames a party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rename "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - spy: '{"text":"","extra":[{"text":"/party spy","color":"aqua"},{"text":" - See messages from other parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party spy"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + reload: '{"text":"","extra":[{"text":"/party reload","color":"aqua"},{"text":" - Reload Parties configuration files","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party reload"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + rename: '{"text":"","extra":[{"text":"/party rename [party] ","color":"aqua"},{"text":" - Rename the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party rename "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + spy: '{"text":"","extra":[{"text":"/party spy [on/off]","color":"aqua"},{"text":" - Spy messages of other parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party spy "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + version: '{"text":"","extra":[{"text":"/party version","color":"aqua"},{"text":" - Show Parties information","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party version"},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' additional-commands: - color: '{"text":"","extra":[{"text":"/party color ","color":"aqua"},{"text":" - Change color of the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party color "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - desc: '{"text":"","extra":[{"text":"/party desc ","color":"aqua"},{"text":" - Add/remove description","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party desc "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - join: '{"text":"","extra":[{"text":"/party join [password]","color":"aqua"},{"text":" - Join into a party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party join "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + color: '{"text":"","extra":[{"text":"/party color ","color":"aqua"},{"text":" - Change party color","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party color "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + desc: '{"text":"","extra":[{"text":"/party desc ","color":"aqua"},{"text":" - Set/remove party description","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party desc "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + follow: '{"text":"","extra":[{"text":"/party follow [on/off]","color":"aqua"},{"text":" - Toggle follow leader","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party follow "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + join: '{"text":"","extra":[{"text":"/party join [password]","color":"aqua"},{"text":" - Join into the party","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party join "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' list: '{"text":"","extra":[{"text":"/party list [page]","color":"aqua"},{"text":" - List of online parties","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party list "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' - motd: '{"text":"","extra":[{"text":"/party motd ","color":"aqua"},{"text":" - Add/remove motd","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party motd "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' + motd: '{"text":"","extra":[{"text":"/party motd ","color":"aqua"},{"text":" - Set/remove party motd","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party motd "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' mute: '{"text":"","extra":[{"text":"/party mute [on/off]","color":"aqua"},{"text":" - Toggle notifications","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party mute "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' password: '{"text":"","extra":[{"text":"/party password ","color":"aqua"},{"text":" - Change party password","color":"gray"}],"clickEvent":{"action":"suggest_command","value":"/party password "},"hoverEvent":{"action":"show_text","value":{"text":"Perform the command","color":"gold"}}}' diff --git a/bungee/src/main/resources/bungee/parties.yml b/bungee/src/main/resources/bungee/parties.yml index 4f69bddd3..086c87140 100644 --- a/bungee/src/main/resources/bungee/parties.yml +++ b/bungee/src/main/resources/bungee/parties.yml @@ -1,7 +1,6 @@ # # Parties-related configuration file # -# # You can find a list of available tags here: https://alessiodp.com/docs/parties/placeholders/ # @@ -15,6 +14,8 @@ general: # Regex of chars (Use \\ instead of \ if you use "text" format) # For ALL utf characters use '[\p{L}\s]+' allowed-characters: '[a-zA-Z0-9]+' + # Censor party name with a regex + censor-regex: '' minimum-length: 3 maximum-length: 10 # Cooldown for rename command (in seconds) @@ -33,7 +34,7 @@ general: global: 60 # Prevent to invite the same player for X seconds individual: 0 - + chat: # Allow sending messages with color codes (&1, &2, etc..) # Permission required @@ -42,6 +43,8 @@ general: enable-toggle-command: true # Chat cooldown in seconds chat-cooldown: 0 + # Censor party message with a regex + censor-regex: '' direct: # Directly write in party chat by adding a prefix before (Example: @this is a party message) enable: false @@ -56,7 +59,7 @@ general: # If you use this placeholder, you will bypass vanish check # Format as SimpleDateFormat of Java (example: "yyyy-MM-dd HH:mm:ss.S") time-date-format: "yyyy-MM-dd" - # Special tags: %days%, %hours% and %minutes% + # Special tags: %days%, %hours%, %minutes% and %seconds% time-elapsed-format: "%days% days, %hours% hours, %minutes% minutes" # Special tags: %time_date% and %time_elapsed% format-offline: "[%time_elapsed%]" @@ -138,7 +141,7 @@ additional: yourcustomcolor: command: "special" code: "&9&n" - + description: enable: true minimum-length: 3 @@ -146,7 +149,9 @@ additional: # Regex of chars (Use \\ instead of \ if you use "text" format) # For ALL utf characters use '[\p{L}\s]+' allowed-characters: '[a-zA-Z0-9\ \.\,\-\_]+' - + # Censor description with a regex + censor-regex: '' + fixed-system: # Allow the creation of parties without leader (they are called "fixed") enable: false @@ -154,7 +159,7 @@ additional: # When a player join into the server, put him into a party (if he doesn't have one) enable: false party: "default" - + join-password: # Password system (This will enable "/party join ", you can still disable it via permissions) # Allows the creation of a party with a password (/party create ) @@ -184,7 +189,7 @@ additional: limit-parties: -1 # Hide some parties from the list (Type the name of party) hidden-parties: [] - + motd: enable: true minimum-length: 3 @@ -196,6 +201,8 @@ additional: allowed-characters: '[a-zA-Z0-9\ \.\,\-\_]+' # New line code is \n, you need to escape the first \ by adding another \ before new-line-code: '\\n' + # Censor motd with a regex + censor-regex: '' teleport: # Enable teleport command, teleport every partymate to the command sender @@ -206,4 +213,4 @@ additional: # End of configuration file dont-edit-this: - version: 3 \ No newline at end of file + version: 4 \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml index a3acde0e5..d9c1e4679 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,7 +7,7 @@ Parties com.alessiodp.parties - 2.4.7 + 2.5.0 parties-common diff --git a/common/src/main/java/com/alessiodp/parties/common/PartiesPlugin.java b/common/src/main/java/com/alessiodp/parties/common/PartiesPlugin.java index a6a78ea82..2e46628ef 100644 --- a/common/src/main/java/com/alessiodp/parties/common/PartiesPlugin.java +++ b/common/src/main/java/com/alessiodp/parties/common/PartiesPlugin.java @@ -122,6 +122,7 @@ protected void postHandle() { getPlayerManager().reload(); getAddonManager().loadAddons(); registerListeners(); + cooldownManager = new CooldownManager(); api = new ApiHandler(this); Parties.setApi(api); diff --git a/common/src/main/java/com/alessiodp/parties/common/addons/internal/ADPUpdater.java b/common/src/main/java/com/alessiodp/parties/common/addons/internal/ADPUpdater.java index b68504b55..76f99c3e5 100644 --- a/common/src/main/java/com/alessiodp/parties/common/addons/internal/ADPUpdater.java +++ b/common/src/main/java/com/alessiodp/parties/common/addons/internal/ADPUpdater.java @@ -45,7 +45,7 @@ private static void alertPlayers() { public static void asyncTaskCheckUpdates() { if (ConfigMain.PARTIES_UPDATES_CHECK) { - plugin.getPartiesScheduler().runAsyncTaskTimer(ADPUpdater::checkUpdates, 60*60*24); + plugin.getPartiesScheduler().scheduleAsyncTaskTimer(ADPUpdater::checkUpdates, 20L*60*60*24); } } diff --git a/common/src/main/java/com/alessiodp/parties/common/addons/internal/PartiesPlaceholder.java b/common/src/main/java/com/alessiodp/parties/common/addons/internal/PartiesPlaceholder.java index 8dcd4142a..516fb80c5 100644 --- a/common/src/main/java/com/alessiodp/parties/common/addons/internal/PartiesPlaceholder.java +++ b/common/src/main/java/com/alessiodp/parties/common/addons/internal/PartiesPlaceholder.java @@ -5,6 +5,8 @@ import com.alessiodp.parties.common.parties.objects.PartyImpl; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; +import java.util.Map; + public enum PartiesPlaceholder { COLOR_CODE, COLOR_COMMAND, @@ -70,9 +72,9 @@ public String formatPlaceholder(PartyPlayerImpl pp, PartyImpl party, String iden if (party != null) { if (this.equals(CUSTOM)) { // Custom - for (String key : ConfigMain.ADDITIONAL_PLACEHOLDER_CUSTOMS.keySet()) { - if (identifier.equalsIgnoreCase(CUSTOM_PREFIX + key)) { - ret = plugin.getMessageUtils().convertAllPlaceholders(ConfigMain.ADDITIONAL_PLACEHOLDER_CUSTOMS.get(key), party, pp); + for (Map.Entry entry : ConfigMain.ADDITIONAL_PLACEHOLDER_CUSTOMS.entrySet()) { + if (identifier.equalsIgnoreCase(CUSTOM_PREFIX + entry.getKey())) { + ret = plugin.getMessageUtils().convertAllPlaceholders(entry.getValue(), party, pp); } } } else { diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/CommandDispatcher.java b/common/src/main/java/com/alessiodp/parties/common/commands/CommandDispatcher.java deleted file mode 100644 index dfc710db1..000000000 --- a/common/src/main/java/com/alessiodp/parties/common/commands/CommandDispatcher.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.alessiodp.parties.common.commands; - -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.list.PartiesCommand; -import com.alessiodp.parties.common.configuration.Constants; -import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.configuration.data.Messages; -import com.alessiodp.parties.common.user.User; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public abstract class CommandDispatcher { - private PartiesPlugin plugin; - private HashMap commands; - @Getter private List enabledCommands; - - protected CommandDispatcher(PartiesPlugin instance) { - plugin = instance; - commands = new HashMap<>(); - enabledCommands = new ArrayList<>(); - } - - public void register(PartiesCommand command, AbstractCommand commandExecutor) { - commands.put(command.getCommand().toLowerCase(), commandExecutor); - enabledCommands.add(command); - } - - public int getCommandsNumber() { - return commands.size(); - } - - private boolean exists(String name) { - return commands.containsKey(name.toLowerCase()); - } - - private AbstractCommand getExecutor(String name) { - return commands.get(name); - } - - public boolean onCommand(User sender, String command, String[] args) { - if (sender.isPlayer()) { - // Player - if (command.equalsIgnoreCase(ConfigMain.COMMANDS_CMD_PARTY)) { - if (args.length > 0) { - if (exists(args[0])) { - prepareCommand(sender, command, args[0], args); - } else { - sender.sendMessage(Messages.PARTIES_COMMON_INVALIDCMD, true); - } - } else { - prepareCommand(sender, command, command, args); - } - } else if (command.equalsIgnoreCase(ConfigMain.COMMANDS_CMD_P)) { - prepareCommand(sender, command, command, args); - } - } else { - // Console - if (command.equalsIgnoreCase(ConfigMain.COMMANDS_CMD_PARTY)) { - if (args.length > 0 - && (args[0].equalsIgnoreCase(ConfigMain.COMMANDS_CMD_RELOAD) - || args[0].equalsIgnoreCase(ConfigMain.COMMANDS_CMD_MIGRATE))) { - prepareCommand(sender, command, args[0], args); - } else { - printConsoleHelp(); - } - } else if (command.equalsIgnoreCase(ConfigMain.COMMANDS_CMD_P)) { - sender.sendMessage(Constants.ONLY_PLAYERS, false); - } - } - return true; - } - - private void prepareCommand(User sender, String command, String subCommand, String[] args) { - CommandData cd = new CommandData(); - cd.setSender(sender); - cd.setCommandLabel(command); - cd.setArgs(args); - if (getExecutor(subCommand.toLowerCase()).preRequisites(cd)) { - CompletableFuture.supplyAsync(() -> { - getExecutor(subCommand.toLowerCase()).onCommand(cd); - return true; - }, plugin.getPartiesScheduler().getCommandsExecutor()) - .exceptionally(ex -> { - ex.printStackTrace(); - return false; - }); - } - } - - private void printConsoleHelp() { - for (String str : Messages.HELP_CONSOLEHELP) { - plugin.log(str); - } - } -} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/CommandManager.java b/common/src/main/java/com/alessiodp/parties/common/commands/CommandManager.java index 9109bb0df..9c915fea0 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/CommandManager.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/CommandManager.java @@ -1,45 +1,19 @@ package com.alessiodp.parties.common.commands; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.executors.CommandAccept; -import com.alessiodp.parties.common.commands.executors.CommandChat; -import com.alessiodp.parties.common.commands.executors.CommandColor; -import com.alessiodp.parties.common.commands.executors.CommandCreate; -import com.alessiodp.parties.common.commands.executors.CommandDelete; -import com.alessiodp.parties.common.commands.executors.CommandDeny; -import com.alessiodp.parties.common.commands.executors.CommandDesc; -import com.alessiodp.parties.common.commands.executors.CommandHelp; -import com.alessiodp.parties.common.commands.executors.CommandIgnore; -import com.alessiodp.parties.common.commands.executors.CommandInfo; -import com.alessiodp.parties.common.commands.executors.CommandInvite; -import com.alessiodp.parties.common.commands.executors.CommandJoin; -import com.alessiodp.parties.common.commands.executors.CommandKick; -import com.alessiodp.parties.common.commands.executors.CommandLeave; -import com.alessiodp.parties.common.commands.executors.CommandList; -import com.alessiodp.parties.common.commands.executors.CommandMigrate; -import com.alessiodp.parties.common.commands.executors.CommandMotd; -import com.alessiodp.parties.common.commands.executors.CommandMute; -import com.alessiodp.parties.common.commands.executors.CommandP; -import com.alessiodp.parties.common.commands.executors.CommandParty; -import com.alessiodp.parties.common.commands.executors.CommandPassword; -import com.alessiodp.parties.common.commands.executors.CommandRank; -import com.alessiodp.parties.common.commands.executors.CommandReload; -import com.alessiodp.parties.common.commands.executors.CommandRename; -import com.alessiodp.parties.common.commands.executors.CommandSpy; import com.alessiodp.parties.common.commands.list.CommonCommands; import com.alessiodp.parties.common.commands.list.PartiesCommand; -import com.alessiodp.parties.common.configuration.Constants; +import com.alessiodp.parties.common.commands.main.CommandP; +import com.alessiodp.parties.common.commands.main.CommandParty; import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.configuration.data.ConfigParties; -import com.alessiodp.parties.common.logging.LogLevel; -import com.alessiodp.parties.common.logging.LoggerManager; import lombok.Getter; import java.util.LinkedList; public abstract class CommandManager { protected PartiesPlugin plugin; - protected CommandDispatcher dispatcher; + protected CommandParty commandParty; + protected CommandP commandP; @Getter protected LinkedList orderedCommands; protected CommandManager(PartiesPlugin instance) { @@ -57,63 +31,20 @@ protected void prepareCommands() { CommonCommands.setup(); } - protected void registerCommands() { - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_COMMANDS_REGISTER_PRE, true); - dispatcher.register(CommonCommands.P, new CommandP(plugin)); - dispatcher.register(CommonCommands.PARTY, new CommandParty(plugin)); - dispatcher.register(CommonCommands.HELP, new CommandHelp(plugin)); - - dispatcher.register(CommonCommands.ACCEPT, new CommandAccept(plugin)); - dispatcher.register(CommonCommands.CHAT, new CommandChat(plugin)); - dispatcher.register(CommonCommands.CREATE, new CommandCreate(plugin)); - dispatcher.register(CommonCommands.DELETE, new CommandDelete(plugin)); - dispatcher.register(CommonCommands.DENY, new CommandDeny(plugin)); - dispatcher.register(CommonCommands.IGNORE, new CommandIgnore(plugin)); - dispatcher.register(CommonCommands.INFO, new CommandInfo(plugin)); - dispatcher.register(CommonCommands.INVITE, new CommandInvite(plugin)); - dispatcher.register(CommonCommands.KICK, new CommandKick(plugin)); - dispatcher.register(CommonCommands.LEAVE, new CommandLeave(plugin)); - dispatcher.register(CommonCommands.MIGRATE, new CommandMigrate(plugin)); - dispatcher.register(CommonCommands.RANK, new CommandRank(plugin)); - dispatcher.register(CommonCommands.RELOAD, new CommandReload(plugin)); - dispatcher.register(CommonCommands.RENAME, new CommandRename(plugin)); - dispatcher.register(CommonCommands.SPY, new CommandSpy(plugin)); - - // Color - if (ConfigParties.COLOR_ENABLE) - dispatcher.register(CommonCommands.COLOR, new CommandColor(plugin)); - - // Desc - if (ConfigParties.DESC_ENABLE) - dispatcher.register(CommonCommands.DESC, new CommandDesc(plugin)); - - // Join & Password - if (ConfigParties.PASSWORD_ENABLE) { - dispatcher.register(CommonCommands.JOIN, new CommandJoin(plugin)); - dispatcher.register(CommonCommands.PASSWORD, new CommandPassword(plugin)); - } - - // List - if (ConfigParties.LIST_ENABLE) - dispatcher.register(CommonCommands.LIST, new CommandList(plugin)); - - // Motd - if (ConfigParties.MOTD_ENABLE) - dispatcher.register(CommonCommands.MOTD, new CommandMotd(plugin)); - - // Mute - if (ConfigMain.ADDITIONAL_MUTE_ENABLE) - dispatcher.register(CommonCommands.MUTE, new CommandMute(plugin)); - } - + protected abstract void registerCommands(); protected abstract void setupCommands(); private void orderCommands() { orderedCommands = new LinkedList<>(); for (String command : ConfigMain.COMMANDS_ORDER) { - for (PartiesCommand pc : dispatcher.getEnabledCommands()) { + // P command + if (command.equalsIgnoreCase(CommonCommands.P.getType())) + orderedCommands.add(CommonCommands.P); + // Party sub-commands + for (PartiesCommand pc : commandParty.getEnabledSubCommands()) { if (pc.getType().equalsIgnoreCase(command)) { orderedCommands.add(pc); + break; } } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandP.java b/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandP.java deleted file mode 100644 index 636ddb67d..000000000 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandP.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.alessiodp.parties.common.commands.executors; - -import com.alessiodp.parties.api.events.common.player.IChatEvent; -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; -import com.alessiodp.parties.common.configuration.Constants; -import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.configuration.data.ConfigParties; -import com.alessiodp.parties.common.configuration.data.Messages; -import com.alessiodp.parties.common.logging.LogLevel; -import com.alessiodp.parties.common.logging.LoggerManager; -import com.alessiodp.parties.common.parties.objects.PartyImpl; -import com.alessiodp.parties.common.players.PartiesPermission; -import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; -import com.alessiodp.parties.common.tasks.ChatTask; -import com.alessiodp.parties.common.user.User; - -public class CommandP extends AbstractCommand { - - public CommandP(PartiesPlugin instance) { - super(instance); - } - - @Override - public boolean preRequisites(CommandData commandData) { - User sender = commandData.getSender(); - PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(sender.getUUID()); - - /* - * Checks for command prerequisites - */ - if (!sender.hasPermission(PartiesPermission.SENDMESSAGE.toString())) { - pp.sendNoPermission(PartiesPermission.SENDMESSAGE); - return false; - } - - PartyImpl party = pp.getPartyName().isEmpty() ? null : plugin.getPartyManager().getParty(pp.getPartyName()); - if (party == null) { - pp.sendMessage(Messages.PARTIES_COMMON_NOTINPARTY); - return false; - } - - if (!plugin.getRankManager().checkPlayerRankAlerter(pp, PartiesPermission.PRIVATE_SENDMESSAGE)) - return false; - - if (commandData.getArgs().length == 0) { - pp.sendMessage(Messages.MAINCMD_P_WRONGCMD); - return false; - } - - commandData.setPartyPlayer(pp); - commandData.setParty(party); - commandData.addPermission(PartiesPermission.ADMIN_KICK_OTHERS); - return true; - } - - @Override - public void onCommand(CommandData commandData) { - PartyPlayerImpl pp = commandData.getPartyPlayer(); - PartyImpl party = commandData.getParty(); - - /* - * Command handling - */ - if (ConfigParties.GENERAL_CHAT_CHATCD > 0 - && !plugin.getRankManager().checkPlayerRank(pp, PartiesPermission.PRIVATE_BYPASSCOOLDOWN)) { - Long unixTimestamp = plugin.getCooldownManager().getChatCooldown().get(pp.getPlayerUUID()); - long unixNow = System.currentTimeMillis() / 1000L; - if (unixTimestamp != null && (unixNow - unixTimestamp) < ConfigParties.GENERAL_CHAT_CHATCD) { - pp.sendMessage(Messages.MAINCMD_P_COOLDOWN - .replace("%seconds%", String.valueOf(ConfigParties.GENERAL_CHAT_CHATCD - (unixNow - unixTimestamp)))); - return; - } - - plugin.getCooldownManager().getChatCooldown().put(pp.getPlayerUUID(), unixNow); - plugin.getPartiesScheduler().scheduleTaskLater( - new ChatTask(plugin, pp.getPlayerUUID()), ConfigParties.GENERAL_INVITE_TIMEOUT); - - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_CMD_P_TASK - .replace("{value}", Integer.toString(ConfigParties.GENERAL_CHAT_CHATCD * 20)) - .replace("{player}", pp.getName()), true); - } - - /* - * Command starts - */ - StringBuilder sb = new StringBuilder(); - for (String word : commandData.getArgs()) { - if (sb.length() > 0) { - sb.append(" "); - } - sb.append(word); - } - - // Calling API event - IChatEvent partiesChatEvent = plugin.getEventManager().prepareChatEvent(pp, party, sb.toString()); - plugin.getEventManager().callEvent(partiesChatEvent); - - String newMessage = partiesChatEvent.getMessage(); - if (!partiesChatEvent.isCancelled()) { - party.sendChatMessage(pp, newMessage); - - if (ConfigMain.STORAGE_LOG_CHAT) - LoggerManager.log(LogLevel.BASIC, Constants.DEBUG_CMD_P - .replace("{party}", party.getName()) - .replace("{player}", pp.getName()) - .replace("{message}", newMessage), true); - } else - LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_API_CHATEVENT_DENY - .replace("{player}", pp.getName()) - .replace("{message}", sb.toString()), true); - } -} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandParty.java b/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandParty.java deleted file mode 100644 index 90e010e5b..000000000 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandParty.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.alessiodp.parties.common.commands.executors; - -import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; -import com.alessiodp.parties.common.commands.list.PartiesCommand; -import com.alessiodp.parties.common.configuration.data.ConfigMain; -import com.alessiodp.parties.common.configuration.data.Messages; -import com.alessiodp.parties.common.players.PartiesPermission; -import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; -import com.alessiodp.parties.common.user.User; - -import java.util.ArrayList; -import java.util.List; - -public class CommandParty extends AbstractCommand { - - public CommandParty(PartiesPlugin instance) { - super(instance); - } - - @Override - public boolean preRequisites(CommandData commandData) { - User sender = commandData.getSender(); - PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(sender.getUUID()); - - /* - * Checks for command prerequisites - */ - if (!sender.hasPermission(PartiesPermission.HELP.toString())) { - pp.sendNoPermission(PartiesPermission.HELP); - return false; - } - - commandData.setPartyPlayer(pp); - return true; - } - - @Override - public void onCommand(CommandData commandData) { - PartyPlayerImpl pp = commandData.getPartyPlayer(); - - /* - * Command starts - */ - // Get all allowed commands - List list = new ArrayList<>(); - List allowedCommands = pp.getAllowedCommands(); - for(PartiesCommand pc : plugin.getCommandManager().getOrderedCommands()) { - if (allowedCommands.contains(pc)) { - list.add(pc.getHelp()); - } - } - - // Split commands per page - int page = 1; - int maxpages; - if (list.size() == 0) - maxpages = 1; - else if ((list.size() % ConfigMain.COMMANDS_HELP_PERPAGE) == 0) - maxpages = list.size() / ConfigMain.COMMANDS_HELP_PERPAGE; - else - maxpages = (list.size() / ConfigMain.COMMANDS_HELP_PERPAGE) + 1; - - // Start printing - int commandNumber = 0; - pp.sendMessage(Messages.HELP_HEADER - .replace("%page%", Integer.toString(page)) - .replace("%maxpages%", Integer.toString(maxpages))); - for (String string : list) { - int currentChoosenPage = (page-1) * ConfigMain.COMMANDS_HELP_PERPAGE; - if (commandNumber >= currentChoosenPage - && commandNumber < currentChoosenPage + ConfigMain.COMMANDS_HELP_PERPAGE) { - pp.sendMessage(string); - } - commandNumber++; - } - pp.sendMessage(Messages.HELP_FOOTER - .replace("%page%", Integer.toString(page)) - .replace("%maxpages%", Integer.toString(maxpages))); - } - -} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/list/CommonCommands.java b/common/src/main/java/com/alessiodp/parties/common/commands/list/CommonCommands.java index 8962f520a..f3eaa3091 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/list/CommonCommands.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/list/CommonCommands.java @@ -2,13 +2,14 @@ import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; +import com.alessiodp.parties.common.players.PartiesPermission; import lombok.Getter; public enum CommonCommands implements PartiesCommand { P, PARTY, - HELP, + HELP, ACCEPT, CHAT, CREATE, @@ -24,9 +25,11 @@ public enum CommonCommands implements PartiesCommand { RELOAD, RENAME, SPY, + VERSION, COLOR, DESC, + FOLLOW, JOIN, LIST, MOTD, @@ -37,66 +40,99 @@ public enum CommonCommands implements PartiesCommand { @Getter private String command; @Getter private String help; + @Getter private String permission; CommonCommands() { command = ""; help = ""; + permission = ""; } public static void setup() { CommonCommands.P.command = ConfigMain.COMMANDS_CMD_P; CommonCommands.P.help = Messages.HELP_MAINCMD_P; + CommonCommands.P.permission = PartiesPermission.SENDMESSAGE.toString(); CommonCommands.PARTY.command = ConfigMain.COMMANDS_CMD_PARTY; + CommonCommands.HELP.command = ConfigMain.COMMANDS_CMD_HELP; CommonCommands.HELP.help = Messages.HELP_MAINCMD_HELP; - + CommonCommands.HELP.permission = PartiesPermission.HELP.toString(); CommonCommands.ACCEPT.command = ConfigMain.COMMANDS_CMD_ACCEPT; CommonCommands.ACCEPT.help = Messages.HELP_MAINCMD_ACCEPT; + CommonCommands.ACCEPT.permission = PartiesPermission.ACCEPT.toString(); CommonCommands.CHAT.command = ConfigMain.COMMANDS_CMD_CHAT; CommonCommands.CHAT.help = Messages.HELP_MAINCMD_CHAT; + CommonCommands.CHAT.permission = PartiesPermission.CHAT.toString(); CommonCommands.CREATE.command = ConfigMain.COMMANDS_CMD_CREATE; CommonCommands.CREATE.help = Messages.HELP_MAINCMD_CREATE; + CommonCommands.CREATE.permission = PartiesPermission.CREATE.toString(); CommonCommands.DELETE.command = ConfigMain.COMMANDS_CMD_DELETE; CommonCommands.DELETE.help = Messages.HELP_MAINCMD_DELETE; + CommonCommands.DELETE.permission = PartiesPermission.ADMIN_DELETE.toString(); CommonCommands.DENY.command = ConfigMain.COMMANDS_CMD_DENY; CommonCommands.DENY.help = Messages.HELP_MAINCMD_DENY; + CommonCommands.DENY.permission = PartiesPermission.DENY.toString(); CommonCommands.IGNORE.command = ConfigMain.COMMANDS_CMD_IGNORE; CommonCommands.IGNORE.help = Messages.HELP_MAINCMD_IGNORE; + CommonCommands.IGNORE.permission = PartiesPermission.IGNORE.toString(); CommonCommands.INFO.command = ConfigMain.COMMANDS_CMD_INFO; CommonCommands.INFO.help = Messages.HELP_MAINCMD_INFO; + CommonCommands.INFO.permission = PartiesPermission.INFO.toString(); CommonCommands.INVITE.command = ConfigMain.COMMANDS_CMD_INVITE; CommonCommands.INVITE.help = Messages.HELP_MAINCMD_INVITE; + CommonCommands.INVITE.permission = PartiesPermission.INVITE.toString(); CommonCommands.KICK.command = ConfigMain.COMMANDS_CMD_KICK; CommonCommands.KICK.help = Messages.HELP_MAINCMD_KICK; + CommonCommands.KICK.permission = PartiesPermission.KICK.toString(); CommonCommands.LEAVE.command = ConfigMain.COMMANDS_CMD_LEAVE; CommonCommands.LEAVE.help = Messages.HELP_MAINCMD_LEAVE; + CommonCommands.LEAVE.permission = PartiesPermission.LEAVE.toString(); CommonCommands.MIGRATE.command = ConfigMain.COMMANDS_CMD_MIGRATE; CommonCommands.MIGRATE.help = Messages.HELP_MAINCMD_MIGRATE; + CommonCommands.MIGRATE.permission = PartiesPermission.ADMIN_MIGRATE.toString(); CommonCommands.RANK.command = ConfigMain.COMMANDS_CMD_RANK; CommonCommands.RANK.help = Messages.HELP_MAINCMD_RANK; + CommonCommands.RANK.permission = PartiesPermission.RANK.toString(); CommonCommands.RELOAD.command = ConfigMain.COMMANDS_CMD_RELOAD; CommonCommands.RELOAD.help = Messages.HELP_MAINCMD_RELOAD; + CommonCommands.RELOAD.permission = PartiesPermission.ADMIN_RELOAD.toString(); CommonCommands.RENAME.command = ConfigMain.COMMANDS_CMD_RENAME; CommonCommands.RENAME.help = Messages.HELP_MAINCMD_RENAME; + CommonCommands.RENAME.permission = PartiesPermission.RENAME.toString(); CommonCommands.SPY.command = ConfigMain.COMMANDS_CMD_SPY; CommonCommands.SPY.help = Messages.HELP_MAINCMD_SPY; + CommonCommands.SPY.permission = PartiesPermission.ADMIN_SPY.toString(); + CommonCommands.VERSION.command = ConfigMain.COMMANDS_CMD_VERSION; + CommonCommands.VERSION.help = Messages.HELP_MAINCMD_VERSION; + CommonCommands.VERSION.permission = PartiesPermission.ADMIN_VERSION.toString(); CommonCommands.COLOR.command = ConfigMain.COMMANDS_CMD_COLOR; CommonCommands.COLOR.help = Messages.HELP_ADDCMD_COLOR; + CommonCommands.COLOR.permission = PartiesPermission.COLOR.toString(); CommonCommands.DESC.command = ConfigMain.COMMANDS_CMD_DESC; CommonCommands.DESC.help = Messages.HELP_ADDCMD_DESC; + CommonCommands.DESC.permission = PartiesPermission.DESC.toString(); + CommonCommands.FOLLOW.command = ConfigMain.COMMANDS_CMD_FOLLOW; + CommonCommands.FOLLOW.help = Messages.HELP_ADDCMD_FOLLOW; + CommonCommands.FOLLOW.permission = PartiesPermission.FOLLOW.toString(); CommonCommands.JOIN.command = ConfigMain.COMMANDS_CMD_JOIN; CommonCommands.JOIN.help = Messages.HELP_ADDCMD_JOIN; + CommonCommands.JOIN.permission = PartiesPermission.JOIN.toString(); CommonCommands.LIST.command = ConfigMain.COMMANDS_CMD_LIST; CommonCommands.LIST.help = Messages.HELP_ADDCMD_LIST; + CommonCommands.LIST.permission = PartiesPermission.LIST.toString(); CommonCommands.MOTD.command = ConfigMain.COMMANDS_CMD_MOTD; CommonCommands.MOTD.help = Messages.HELP_ADDCMD_MOTD; + CommonCommands.MOTD.permission = PartiesPermission.MOTD.toString(); CommonCommands.MUTE.command = ConfigMain.COMMANDS_CMD_MUTE; CommonCommands.MUTE.help = Messages.HELP_ADDCMD_MUTE; + CommonCommands.MUTE.permission = PartiesPermission.MUTE.toString(); CommonCommands.PASSWORD.command = ConfigMain.COMMANDS_CMD_PASSWORD; CommonCommands.PASSWORD.help = Messages.HELP_ADDCMD_PASSWORD; + CommonCommands.PASSWORD.permission = PartiesPermission.PASSWORD.toString(); CommonCommands.TELEPORT.command = ConfigMain.COMMANDS_CMD_TELEPORT; CommonCommands.TELEPORT.help = Messages.HELP_ADDCMD_TELEPORT; + CommonCommands.TELEPORT.permission = PartiesPermission.TELEPORT.toString(); } public String getType() { diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/list/PartiesCommand.java b/common/src/main/java/com/alessiodp/parties/common/commands/list/PartiesCommand.java index da09aa864..4e67cdcce 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/list/PartiesCommand.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/list/PartiesCommand.java @@ -4,4 +4,5 @@ public interface PartiesCommand { String getCommand(); String getHelp(); String getType(); + String getPermission(); } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandP.java b/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandP.java new file mode 100644 index 000000000..148ab7a52 --- /dev/null +++ b/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandP.java @@ -0,0 +1,150 @@ +package com.alessiodp.parties.common.commands.main; + +import com.alessiodp.parties.api.events.common.player.IChatEvent; +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.commands.utils.PartiesCommandExecutor; +import com.alessiodp.parties.common.configuration.Constants; +import com.alessiodp.parties.common.configuration.data.ConfigMain; +import com.alessiodp.parties.common.configuration.data.ConfigParties; +import com.alessiodp.parties.common.configuration.data.Messages; +import com.alessiodp.parties.common.logging.LogLevel; +import com.alessiodp.parties.common.logging.LoggerManager; +import com.alessiodp.parties.common.parties.objects.PartyImpl; +import com.alessiodp.parties.common.players.PartiesPermission; +import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; +import com.alessiodp.parties.common.tasks.ChatTask; +import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.ArrayList; +import java.util.List; + +public abstract class CommandP extends PartiesCommandExecutor { + private CommandSendMessage commandSendMessage; + + protected CommandP(PartiesPlugin instance) { + super(instance); + commandSendMessage = new CommandSendMessage(plugin); + } + + @Override + public boolean onCommand(User sender, String command, String[] args) { + if (sender.isPlayer()) { + // Player + PartiesUtils.executeCommand(plugin, sender, ConfigMain.COMMANDS_CMD_P, commandSendMessage, args); + } else { + // Console + sender.sendMessage(Constants.ONLY_PLAYERS, false); + } + return true; + } + + @Override + public List onTabComplete(User sender, String[] args) { + return new ArrayList<>(); + } + + private static class CommandSendMessage extends AbstractCommand { + + private CommandSendMessage(PartiesPlugin instance) { + super(instance); + } + + public boolean preRequisites(CommandData commandData) { + User sender = commandData.getSender(); + PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(sender.getUUID()); + + /* + * Checks for command prerequisites + */ + if (!sender.hasPermission(PartiesPermission.SENDMESSAGE.toString())) { + pp.sendNoPermission(PartiesPermission.SENDMESSAGE); + return false; + } + + PartyImpl party = pp.getPartyName().isEmpty() ? null : plugin.getPartyManager().getParty(pp.getPartyName()); + if (party == null) { + pp.sendMessage(Messages.PARTIES_COMMON_NOTINPARTY); + return false; + } + + if (!plugin.getRankManager().checkPlayerRankAlerter(pp, PartiesPermission.PRIVATE_SENDMESSAGE)) + return false; + + if (commandData.getArgs().length == 0) { + pp.sendMessage(Messages.MAINCMD_P_WRONGCMD); + return false; + } + + commandData.setPartyPlayer(pp); + commandData.setParty(party); + commandData.addPermission(PartiesPermission.ADMIN_KICK_OTHERS); + return true; + } + + public void onCommand(CommandData commandData) { + PartyPlayerImpl pp = commandData.getPartyPlayer(); + PartyImpl party = commandData.getParty(); + + /* + * Command handling + */ + StringBuilder sb = new StringBuilder(); + for (String word : commandData.getArgs()) { + if (sb.length() > 0) { + sb.append(" "); + } + sb.append(word); + } + String message = sb.toString(); + + if (PartiesUtils.checkCensor(ConfigParties.GENERAL_CHAT_CENSORREGEX, message, Constants.DEBUG_CMD_P_REGEXERROR)) { + pp.sendMessage(Messages.MAINCMD_P_CENSORED); + return; + } + + if (ConfigParties.GENERAL_CHAT_CHATCD > 0 + && !plugin.getRankManager().checkPlayerRank(pp, PartiesPermission.PRIVATE_BYPASSCOOLDOWN)) { + Long unixTimestamp = plugin.getCooldownManager().getChatCooldown().get(pp.getPlayerUUID()); + long unixNow = System.currentTimeMillis() / 1000L; + // Check cooldown + if (unixTimestamp != null && (unixNow - unixTimestamp) < ConfigParties.GENERAL_CHAT_CHATCD) { + pp.sendMessage(Messages.MAINCMD_P_COOLDOWN + .replace("%seconds%", String.valueOf(ConfigParties.GENERAL_CHAT_CHATCD - (unixNow - unixTimestamp)))); + return; + } + + plugin.getCooldownManager().getChatCooldown().put(pp.getPlayerUUID(), unixNow); + plugin.getPartiesScheduler().scheduleTaskLater( + new ChatTask(plugin, pp.getPlayerUUID()), ConfigParties.GENERAL_INVITE_TIMEOUT * 20L); + + LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_CMD_P_TASK + .replace("{value}", Integer.toString(ConfigParties.GENERAL_CHAT_CHATCD * 20)) + .replace("{player}", pp.getName()), true); + } + /* + * Command starts + */ + + // Calling API event + IChatEvent partiesChatEvent = plugin.getEventManager().prepareChatEvent(pp, party, message); + plugin.getEventManager().callEvent(partiesChatEvent); + + String newMessage = partiesChatEvent.getMessage(); + if (!partiesChatEvent.isCancelled()) { + party.sendChatMessage(pp, newMessage); + + if (ConfigMain.STORAGE_LOG_CHAT) + LoggerManager.log(LogLevel.BASIC, Constants.DEBUG_CMD_P + .replace("{party}", party.getName()) + .replace("{player}", pp.getName()) + .replace("{message}", newMessage), true); + } else + LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_API_CHATEVENT_DENY + .replace("{player}", pp.getName()) + .replace("{message}", message), true); + } + } +} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandParty.java b/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandParty.java new file mode 100644 index 000000000..4eb4c2a16 --- /dev/null +++ b/common/src/main/java/com/alessiodp/parties/common/commands/main/CommandParty.java @@ -0,0 +1,171 @@ +package com.alessiodp.parties.common.commands.main; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.PartiesCommandExecutor; +import com.alessiodp.parties.common.commands.sub.CommandAccept; +import com.alessiodp.parties.common.commands.sub.CommandChat; +import com.alessiodp.parties.common.commands.sub.CommandColor; +import com.alessiodp.parties.common.commands.sub.CommandCreate; +import com.alessiodp.parties.common.commands.sub.CommandDelete; +import com.alessiodp.parties.common.commands.sub.CommandDeny; +import com.alessiodp.parties.common.commands.sub.CommandDesc; +import com.alessiodp.parties.common.commands.sub.CommandFollow; +import com.alessiodp.parties.common.commands.sub.CommandHelp; +import com.alessiodp.parties.common.commands.sub.CommandIgnore; +import com.alessiodp.parties.common.commands.sub.CommandInfo; +import com.alessiodp.parties.common.commands.sub.CommandInvite; +import com.alessiodp.parties.common.commands.sub.CommandJoin; +import com.alessiodp.parties.common.commands.sub.CommandKick; +import com.alessiodp.parties.common.commands.sub.CommandLeave; +import com.alessiodp.parties.common.commands.sub.CommandList; +import com.alessiodp.parties.common.commands.sub.CommandMigrate; +import com.alessiodp.parties.common.commands.sub.CommandMotd; +import com.alessiodp.parties.common.commands.sub.CommandMute; +import com.alessiodp.parties.common.commands.sub.CommandPassword; +import com.alessiodp.parties.common.commands.sub.CommandRank; +import com.alessiodp.parties.common.commands.sub.CommandReload; +import com.alessiodp.parties.common.commands.sub.CommandRename; +import com.alessiodp.parties.common.commands.sub.CommandSpy; +import com.alessiodp.parties.common.commands.sub.CommandVersion; +import com.alessiodp.parties.common.commands.list.CommonCommands; +import com.alessiodp.parties.common.commands.list.PartiesCommand; +import com.alessiodp.parties.common.configuration.data.ConfigMain; +import com.alessiodp.parties.common.configuration.data.ConfigParties; +import com.alessiodp.parties.common.configuration.data.Messages; +import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; +import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public abstract class CommandParty extends PartiesCommandExecutor { + private HashMap subCommands; + @Getter private List enabledSubCommands; + + protected CommandParty(PartiesPlugin instance) { + super(instance); + reload(); + } + + public void reload() { + subCommands = new HashMap<>(); + enabledSubCommands = new ArrayList<>(); + + register(CommonCommands.HELP, new CommandHelp(plugin)); + register(CommonCommands.ACCEPT, new CommandAccept(plugin)); + register(CommonCommands.CHAT, new CommandChat(plugin)); + register(CommonCommands.CREATE, new CommandCreate(plugin)); + register(CommonCommands.DELETE, new CommandDelete(plugin)); + register(CommonCommands.DENY, new CommandDeny(plugin)); + register(CommonCommands.IGNORE, new CommandIgnore(plugin)); + register(CommonCommands.INFO, new CommandInfo(plugin)); + register(CommonCommands.INVITE, new CommandInvite(plugin)); + register(CommonCommands.KICK, new CommandKick(plugin)); + register(CommonCommands.LEAVE, new CommandLeave(plugin)); + register(CommonCommands.MIGRATE, new CommandMigrate(plugin)); + register(CommonCommands.RANK, new CommandRank(plugin)); + register(CommonCommands.RELOAD, new CommandReload(plugin)); + register(CommonCommands.RENAME, new CommandRename(plugin)); + register(CommonCommands.SPY, new CommandSpy(plugin)); + register(CommonCommands.VERSION, new CommandVersion(plugin)); + + // Color + if (ConfigParties.COLOR_ENABLE) + register(CommonCommands.COLOR, new CommandColor(plugin)); + + // Desc + if (ConfigParties.DESC_ENABLE) + register(CommonCommands.DESC, new CommandDesc(plugin)); + + // Follow + if (ConfigMain.ADDITIONAL_FOLLOW_ENABLE && ConfigMain.ADDITIONAL_FOLLOW_TOGGLECMD) + register(CommonCommands.FOLLOW, new CommandFollow(plugin)); + + + // Join & Password + if (ConfigParties.PASSWORD_ENABLE) { + register(CommonCommands.JOIN, new CommandJoin(plugin)); + register(CommonCommands.PASSWORD, new CommandPassword(plugin)); + } + + // List + if (ConfigParties.LIST_ENABLE) + register(CommonCommands.LIST, new CommandList(plugin)); + + // Motd + if (ConfigParties.MOTD_ENABLE) + register(CommonCommands.MOTD, new CommandMotd(plugin)); + + // Mute + if (ConfigMain.ADDITIONAL_MUTE_ENABLE) + register(CommonCommands.MUTE, new CommandMute(plugin)); + } + + protected void register(PartiesCommand command, AbstractCommand commandExecutor) { + subCommands.put(command.getCommand().toLowerCase(), commandExecutor); + enabledSubCommands.add(command); + } + + @Override + public boolean onCommand(User sender, String command, String[] args) { + if (sender.isPlayer()) { + if (args.length == 0) { + // Set /party to /party help + args = new String[]{ConfigMain.COMMANDS_CMD_HELP}; + } + + if (exists(args[0])) { + PartiesUtils.executeCommand(plugin, sender, ConfigMain.COMMANDS_CMD_PARTY, getExecutor(args[0].toLowerCase()), args); + } else { + sender.sendMessage(Messages.PARTIES_COMMON_INVALIDCMD, true); + } + } else { + // Console + if (args.length > 0 + && (args[0].equalsIgnoreCase(ConfigMain.COMMANDS_CMD_RELOAD) + || args[0].equalsIgnoreCase(ConfigMain.COMMANDS_CMD_MIGRATE))) { + PartiesUtils.executeCommand(plugin, sender, ConfigMain.COMMANDS_CMD_PARTY, getExecutor(args[0].toLowerCase()), args); + } else { + // Print help + for (String str : Messages.HELP_CONSOLEHELP) { + plugin.log(str); + } + } + } + return true; + } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + PartyPlayerImpl player = plugin.getPlayerManager().getPlayer(sender.getUUID()); + if (player != null) { + List commands = new ArrayList<>(); + for (PartiesCommand pc : player.getAllowedCommands()) { + if (enabledSubCommands.contains(pc)) + commands.add(pc.getCommand().toLowerCase()); + } + + if (args.length > 1) { + if (commands.contains(args[0])) { + ret = getExecutor(args[0]).onTabComplete(sender, args); + } + } else { + ret = PartiesUtils.tabCompleteParser(commands, args[0]); + } + } + return ret; + } + + private boolean exists(String name) { + return subCommands.containsKey(name.toLowerCase()); + } + + private AbstractCommand getExecutor(String name) { + return subCommands.get(name); + } +} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandAccept.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandAccept.java similarity index 92% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandAccept.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandAccept.java index 88597b3fd..b9c3bbd4b 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandAccept.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandAccept.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandChat.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandChat.java similarity index 77% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandChat.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandChat.java index 9f2bf78d3..4991e979d 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandChat.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandChat.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -11,6 +11,10 @@ import com.alessiodp.parties.common.players.PartiesPermission; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.ArrayList; +import java.util.List; public class CommandChat extends AbstractCommand { @@ -46,17 +50,7 @@ public void onCommand(CommandData commandData) { /* * Command handling */ - Boolean chat = pp.isChatParty(); - if (commandData.getArgs().length > 1) { - if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_ON)) - chat = true; - else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) - chat = false; - else - chat = null; - } else { - chat = !chat; - } + Boolean chat = PartiesUtils.handleOnOffCommand(pp.isChatParty(), commandData.getArgs()); if (chat == null) { pp.sendMessage(Messages.MAINCMD_CHAT_WRONGCMD); return; @@ -76,4 +70,9 @@ else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) .replace("{player}", pp.getName()) .replace("{value}", chat.toString()), true); } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompleteOnOff(args); + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandColor.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandColor.java similarity index 81% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandColor.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandColor.java index 89d081548..76a6d048f 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandColor.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandColor.java @@ -1,19 +1,25 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; +import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; import com.alessiodp.parties.common.logging.LoggerManager; +import com.alessiodp.parties.common.parties.objects.ColorImpl; import com.alessiodp.parties.common.parties.objects.PartyImpl; import com.alessiodp.parties.common.players.PartiesPermission; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; import com.alessiodp.parties.common.utils.EconomyManager; import com.alessiodp.parties.api.interfaces.Color; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.ArrayList; +import java.util.List; public class CommandColor extends AbstractCommand { @@ -112,4 +118,18 @@ public void onCommand(CommandData commandData) { .replace("{value}", color.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + for (ColorImpl color : ConfigParties.COLOR_LIST) { + ret.add(color.getCommand()); + } + if (!args[1].isEmpty()) { + ret = PartiesUtils.tabCompleteParser(ret, args[1]); + } + } + return ret; + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandCreate.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandCreate.java similarity index 90% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandCreate.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandCreate.java index 0ea600afe..5e27d57cf 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandCreate.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandCreate.java @@ -1,10 +1,10 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.party.IPartyPostCreateEvent; import com.alessiodp.parties.api.events.common.party.IPartyPreCreateEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; @@ -18,7 +18,8 @@ import com.alessiodp.parties.common.utils.EconomyManager; import com.alessiodp.parties.common.utils.PartiesUtils; -import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.List; public class CommandCreate extends AbstractCommand { @@ -71,12 +72,13 @@ public void onCommand(CommandData commandData) { return; } - if (PartiesUtils.checkCensor(partyName)) { - pp.sendMessage(Messages.MAINCMD_CREATE_CENSORED); + if (!PartiesUtils.checkAllowedCharacters(ConfigParties.GENERAL_NAME_ALLOWEDCHARS, partyName, Constants.DEBUG_CMD_CREATE_REGEXERROR_AC)) { + pp.sendMessage(Messages.MAINCMD_CREATE_INVALIDNAME); return; } - if (!Pattern.compile(ConfigParties.GENERAL_NAME_ALLOWEDCHARS).matcher(partyName).matches()) { - pp.sendMessage(Messages.MAINCMD_CREATE_INVALIDNAME); + + if (PartiesUtils.checkCensor(ConfigParties.GENERAL_NAME_CENSORREGEX, partyName, Constants.DEBUG_CMD_CREATE_REGEXERROR_CEN)) { + pp.sendMessage(Messages.MAINCMD_CREATE_CENSORED); return; } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDelete.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDelete.java similarity index 83% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDelete.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDelete.java index 52e843847..f68f0e41b 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDelete.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDelete.java @@ -1,10 +1,10 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.party.IPartyPostDeleteEvent; import com.alessiodp.parties.api.events.common.party.IPartyPreDeleteEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -15,6 +15,10 @@ import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; import com.alessiodp.parties.api.enums.DeleteCause; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.ArrayList; +import java.util.List; public class CommandDelete extends AbstractCommand { @@ -99,4 +103,16 @@ public void onCommand(CommandData commandData) { .replace("{player}", pp.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 3 && sender.hasPermission(PartiesPermission.ADMIN_DELETE_SILENT.toString())) { + ret.add(ConfigMain.COMMANDS_SUB_SILENT); + if (!args[2].isEmpty()) { + ret = PartiesUtils.tabCompleteParser(ret, args[2]); + } + } + return ret; + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDeny.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDeny.java similarity index 90% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDeny.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDeny.java index b07bd244b..0b407b42f 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDeny.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDeny.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDesc.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDesc.java similarity index 80% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDesc.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDesc.java index a560896bc..218e120df 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandDesc.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandDesc.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; @@ -16,7 +16,8 @@ import com.alessiodp.parties.common.utils.EconomyManager; import com.alessiodp.parties.common.utils.PartiesUtils; -import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.List; public class CommandDesc extends AbstractCommand { @@ -77,21 +78,21 @@ public void onCommand(CommandData commandData) { sb.append(" "); sb.append(commandData.getArgs()[word]); } - if (!Pattern.compile(ConfigParties.DESC_ALLOWEDCHARS).matcher(sb.toString()).matches() - || (sb.toString().length() > ConfigParties.DESC_MAXLENGTH) - || (sb.toString().length() < ConfigParties.DESC_MINLENGTH)) { + description = sb.toString(); + + if (!PartiesUtils.checkAllowedCharacters(ConfigParties.DESC_ALLOWEDCHARS, description, Constants.DEBUG_CMD_DESC_REGEXERROR_AC) + || (description.length() > ConfigParties.DESC_MAXLENGTH) + || (description.length() < ConfigParties.DESC_MINLENGTH)) { pp.sendMessage(Messages.ADDCMD_DESC_INVALID); return; } - if (PartiesUtils.checkCensor(sb.toString())) { + if (PartiesUtils.checkCensor(ConfigParties.DESC_CENSORREGEX, description, Constants.DEBUG_CMD_DESC_REGEXERROR_CEN)) { pp.sendMessage(Messages.ADDCMD_DESC_CENSORED); return; } if (plugin.getEconomyManager().payCommand(EconomyManager.PaidCommand.DESC, pp, commandData.getCommandLabel(), commandData.getArgs())) return; - - description = sb.toString(); } /* @@ -115,4 +116,13 @@ public void onCommand(CommandData commandData) { .replace("{party}", party.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(ConfigMain.COMMANDS_SUB_REMOVE); + } + return ret; + } } \ No newline at end of file diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandFollow.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandFollow.java new file mode 100644 index 000000000..37c6b3f30 --- /dev/null +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandFollow.java @@ -0,0 +1,89 @@ +package com.alessiodp.parties.common.commands.sub; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.configuration.Constants; +import com.alessiodp.parties.common.configuration.data.ConfigMain; +import com.alessiodp.parties.common.configuration.data.Messages; +import com.alessiodp.parties.common.logging.LogLevel; +import com.alessiodp.parties.common.logging.LoggerManager; +import com.alessiodp.parties.common.parties.objects.PartyImpl; +import com.alessiodp.parties.common.players.PartiesPermission; +import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; +import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.ArrayList; +import java.util.List; + +public class CommandFollow extends AbstractCommand { + + public CommandFollow(PartiesPlugin instance) { + super(instance); + } + + @Override + public boolean preRequisites(CommandData commandData) { + User sender = commandData.getSender(); + PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(sender.getUUID()); + + /* + * Checks for command prerequisites + */ + if (!sender.hasPermission(PartiesPermission.FOLLOW.toString())) { + pp.sendNoPermission(PartiesPermission.FOLLOW); + return false; + } + + PartyImpl party = pp.getPartyName().isEmpty() ? null : plugin.getPartyManager().getParty(pp.getPartyName()); + if (party == null) { + pp.sendMessage(Messages.PARTIES_COMMON_NOTINPARTY); + return false; + } + + if (!plugin.getRankManager().checkPlayerRankAlerter(pp, PartiesPermission.PRIVATE_EDIT_FOLLOW)) + return false; + + commandData.setPartyPlayer(pp); + commandData.setParty(party); + return true; + } + + @Override + public void onCommand(CommandData commandData) { + PartyPlayerImpl pp = commandData.getPartyPlayer(); + PartyImpl party = commandData.getParty(); + + /* + * Command handling + */ + Boolean follow = PartiesUtils.handleOnOffCommand(party.getFollowEnabled(), commandData.getArgs()); + if (follow == null) { + pp.sendMessage(Messages.ADDCMD_FOLLOW_WRONGCMD); + return; + } + + /* + * Command starts + */ + party.setFollowEnabled(follow); + party.updateParty(); + + if (follow) + pp.sendMessage(Messages.ADDCMD_FOLLOW_ON); + else + pp.sendMessage(Messages.ADDCMD_FOLLOW_OFF); + + LoggerManager.log(LogLevel.MEDIUM, + (follow ? Constants.DEBUG_CMD_FOLLOW_ON : Constants.DEBUG_CMD_FOLLOW_OFF) + .replace("{player}", pp.getName()) + .replace("{party}", party.getName()), + true); + } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompleteOnOff(args); + } +} diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandHelp.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandHelp.java similarity index 89% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandHelp.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandHelp.java index f91bd79d1..bcfef9323 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandHelp.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandHelp.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.commands.list.PartiesCommand; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -49,6 +49,9 @@ public void onCommand(CommandData commandData) { for(PartiesCommand pc : plugin.getCommandManager().getOrderedCommands()) { if (allowedCommands.contains(pc)) { list.add(pc.getHelp()); + System.out.println("Adding: " + pc.getCommand()); + } else { + System.out.println("Skipping: " + pc.getCommand()); } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandIgnore.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandIgnore.java similarity index 94% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandIgnore.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandIgnore.java index b9f7f500c..c5e85709e 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandIgnore.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandIgnore.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInfo.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInfo.java similarity index 94% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInfo.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInfo.java index 664e8c442..ca98e19a9 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInfo.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInfo.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -13,7 +13,9 @@ import com.alessiodp.parties.common.players.objects.RankImpl; import com.alessiodp.parties.common.user.OfflineUser; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; +import java.util.List; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInvite.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInvite.java similarity index 93% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInvite.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInvite.java index ddf1a09ce..8bd39eedf 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandInvite.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandInvite.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; @@ -14,6 +14,7 @@ import com.alessiodp.parties.common.players.objects.InviteCooldown; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; import java.util.List; @@ -179,4 +180,9 @@ public void onCommand(CommandData commandData) { .replace("{party}", party.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompletePlayerList(plugin, args, 1); + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandJoin.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandJoin.java similarity index 95% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandJoin.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandJoin.java index e2a680c06..6531fd96a 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandJoin.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandJoin.java @@ -1,10 +1,10 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.player.IPlayerPostJoinEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPreJoinEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandKick.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandKick.java similarity index 94% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandKick.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandKick.java index dd71c9e4a..55af02eb3 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandKick.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandKick.java @@ -1,12 +1,12 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.party.IPartyPostDeleteEvent; import com.alessiodp.parties.api.events.common.party.IPartyPreDeleteEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPostLeaveEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPreLeaveEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -17,12 +17,14 @@ import com.alessiodp.parties.common.user.OfflineUser; import com.alessiodp.parties.common.user.User; import com.alessiodp.parties.api.enums.DeleteCause; +import com.alessiodp.parties.common.utils.PartiesUtils; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -252,4 +254,10 @@ private String getNameFromMojangAPI(String player, UUID uuid) { } return name; } + + @Override + public List onTabComplete(User sender, String[] args) { + // Filter players is too expensive. You should call the database to get every existing player. + return PartiesUtils.tabCompletePlayerList(plugin, args, 1); + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandLeave.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandLeave.java similarity index 95% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandLeave.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandLeave.java index e9dda5860..c6f6cfccc 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandLeave.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandLeave.java @@ -1,12 +1,12 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.party.IPartyPostDeleteEvent; import com.alessiodp.parties.api.events.common.party.IPartyPreDeleteEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPostLeaveEvent; import com.alessiodp.parties.api.events.common.player.IPlayerPreLeaveEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandList.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandList.java similarity index 96% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandList.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandList.java index bd2b93408..8160d7188 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandList.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandList.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMigrate.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMigrate.java similarity index 88% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMigrate.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMigrate.java index 8b7841d05..784feec4d 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMigrate.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMigrate.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -12,6 +12,9 @@ import com.alessiodp.parties.common.storage.StorageType; import com.alessiodp.parties.common.user.User; +import java.util.ArrayList; +import java.util.List; + public class CommandMigrate extends AbstractCommand { public CommandMigrate(PartiesPlugin instance) { @@ -106,4 +109,17 @@ private void sendMessage(String message, PartyPlayerImpl pp, User sender) { else sender.sendMessage(message, true); } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2 || args.length == 3) { + for (StorageType st : StorageType.values()) { + if (plugin.getDatabaseManager().isStorageOnline(st)) { + ret.add(st.getFormattedName()); + } + } + } + return ret; + } } \ No newline at end of file diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMotd.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMotd.java similarity index 80% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMotd.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMotd.java index 33cab420b..9f4f9395f 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMotd.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMotd.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; @@ -16,7 +16,8 @@ import com.alessiodp.parties.common.utils.EconomyManager; import com.alessiodp.parties.common.utils.PartiesUtils; -import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.List; public class CommandMotd extends AbstractCommand { @@ -76,13 +77,15 @@ public void onCommand(CommandData commandData) { sb.append(" "); sb.append(commandData.getArgs()[word]); } - if (!Pattern.compile(ConfigParties.MOTD_ALLOWEDCHARS).matcher(sb.toString()).matches() - || (sb.toString().length() > ConfigParties.MOTD_MAXLENGTH) - || (sb.toString().length() < ConfigParties.MOTD_MINLENGTH)) { + motd = sb.toString(); + + if (!PartiesUtils.checkAllowedCharacters(ConfigParties.MOTD_ALLOWEDCHARS, motd, Constants.DEBUG_CMD_MOTD_REGEXERROR_AC) + || (motd.length() > ConfigParties.MOTD_MAXLENGTH) + || (motd.length() < ConfigParties.MOTD_MINLENGTH)) { pp.sendMessage(Messages.ADDCMD_MOTD_INVALID); return; } - if (PartiesUtils.checkCensor(sb.toString())) { + if (PartiesUtils.checkCensor(ConfigParties.MOTD_CENSORREGEX, motd, Constants.DEBUG_CMD_MOTD_REGEXERROR_CEN)) { pp.sendMessage(Messages.ADDCMD_MOTD_CENSORED); return; } @@ -114,4 +117,13 @@ public void onCommand(CommandData commandData) { .replace("{party}", party.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(ConfigMain.COMMANDS_SUB_REMOVE); + } + return ret; + } } \ No newline at end of file diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMute.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMute.java similarity index 77% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMute.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMute.java index d82fcc085..dd45ce9ae 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandMute.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandMute.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; @@ -11,6 +11,9 @@ import com.alessiodp.parties.common.players.PartiesPermission; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.List; public class CommandMute extends AbstractCommand { @@ -42,17 +45,7 @@ public void onCommand(CommandData commandData) { /* * Command handling */ - Boolean mute = pp.isMuted(); - if (commandData.getArgs().length > 1) { - if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_ON)) - mute = false; - else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) - mute = true; - else - mute = null; - } else { - mute = !mute; - } + Boolean mute = PartiesUtils.handleOnOffCommand(pp.isMuted(), commandData.getArgs()); if (mute == null) { pp.sendMessage(Messages.ADDCMD_MUTE_WRONGCMD); return; @@ -75,4 +68,9 @@ else if (commandData.getArgs()[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) .replace("{player}", pp.getName()), true); } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompleteOnOff(args); + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandPassword.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandPassword.java similarity index 88% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandPassword.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandPassword.java index af686e9de..2fef923d5 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandPassword.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandPassword.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; @@ -15,6 +15,8 @@ import com.alessiodp.parties.common.user.User; import com.alessiodp.parties.common.utils.PartiesUtils; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Pattern; public class CommandPassword extends AbstractCommand { @@ -101,4 +103,13 @@ public void onCommand(CommandData commandData) { .replace("{party}", party.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(ConfigMain.COMMANDS_SUB_REMOVE); + } + return ret; + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRank.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRank.java similarity index 87% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRank.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRank.java index 58bfc212a..b30623b0e 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRank.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRank.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; @@ -13,7 +13,9 @@ import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.players.objects.RankImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; +import java.util.ArrayList; import java.util.List; public class CommandRank extends AbstractCommand { @@ -105,6 +107,11 @@ public void onCommand(CommandData commandData) { .replace("%rank_chat%", commandData.getArgs()[2])); return; } + if (promoted.getPlayerUUID().equals(pp.getPlayerUUID())) { + pp.sendMessage(Messages.MAINCMD_RANK_CHANGINGYOURSELF); + return; + + } if (rank.getLevel() == promoted.getRank()) { pp.sendMessage(Messages.MAINCMD_RANK_SAMERANK .replace("%rank_name%", rank.getName()) @@ -120,11 +127,6 @@ public void onCommand(CommandData commandData) { .replace("%player%", promoted.getName())); return; } - if (promoted.getPlayerUUID().equals(pp.getPlayerUUID())) { - pp.sendMessage(Messages.MAINCMD_RANK_CHANGINGYOURSELF); - return; - - } if ((rank.getLevel() != ConfigParties.RANK_SET_HIGHER) && (rank.getLevel() >= pp.getRank())) { pp.sendMessage(Messages.MAINCMD_RANK_TOHIGHERRANK .replace("%rank_name%", rank.getName()) @@ -163,4 +165,17 @@ public void onCommand(CommandData commandData) { .replace("{value2}", Integer.toString(rank.getLevel())) .replace("{user}", pp.getName()), true); } + + @Override + public List onTabComplete(User sender, String[] args) { + List ret = new ArrayList<>(); + if (args.length == 2) { + ret = PartiesUtils.tabCompletePlayerList(plugin, args, 1); + } else if (args.length == 3) { + for (RankImpl rank : ConfigParties.RANK_LIST) { + ret.add(rank.getName()); + } + } + return ret; + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandReload.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandReload.java similarity index 89% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandReload.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandReload.java index 373e523e6..25282a235 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandReload.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandReload.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRename.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRename.java similarity index 90% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRename.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRename.java index 19c68c02c..72f381255 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandRename.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandRename.java @@ -1,9 +1,9 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.api.events.common.party.IPartyRenameEvent; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; @@ -15,8 +15,6 @@ import com.alessiodp.parties.common.user.User; import com.alessiodp.parties.common.utils.PartiesUtils; -import java.util.regex.Pattern; - public class CommandRename extends AbstractCommand { public CommandRename(PartiesPlugin instance) { @@ -97,15 +95,14 @@ public void onCommand(CommandData commandData) { pp.sendMessage(Messages.MAINCMD_CREATE_NAMETOOSHORT); return; } - if (PartiesUtils.checkCensor(partyName)) { - pp.sendMessage(Messages.MAINCMD_CREATE_CENSORED); + if (!PartiesUtils.checkAllowedCharacters(ConfigParties.GENERAL_NAME_ALLOWEDCHARS, partyName, Constants.DEBUG_CMD_CREATE_REGEXERROR_AC)) { + pp.sendMessage(Messages.MAINCMD_CREATE_INVALIDNAME); return; } - if (!Pattern.compile(ConfigParties.GENERAL_NAME_ALLOWEDCHARS).matcher(partyName).matches()) { - pp.sendMessage(Messages.MAINCMD_CREATE_INVALIDNAME); + if (PartiesUtils.checkCensor(ConfigParties.GENERAL_NAME_CENSORREGEX, partyName, Constants.DEBUG_CMD_CREATE_REGEXERROR_CEN)) { + pp.sendMessage(Messages.MAINCMD_CREATE_CENSORED); return; } - if (plugin.getPartyManager().existParty(partyName)) { pp.sendMessage(Messages.MAINCMD_CREATE_NAMEEXISTS .replace("%party%", partyName)); diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandSpy.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandSpy.java similarity index 70% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandSpy.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandSpy.java index fdef07592..b18b553d5 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandSpy.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandSpy.java @@ -1,15 +1,19 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; +import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; import com.alessiodp.parties.common.logging.LoggerManager; import com.alessiodp.parties.common.players.PartiesPermission; import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.List; public class CommandSpy extends AbstractCommand { @@ -39,14 +43,21 @@ public void onCommand(CommandData commandData) { PartyPlayerImpl pp = commandData.getPartyPlayer(); /* - * Command starts + * Command handling */ - boolean toggleSpy = !pp.isSpy(); + Boolean spy = PartiesUtils.handleOnOffCommand(pp.isSpy(), commandData.getArgs()); + if (spy == null) { + pp.sendMessage(Messages.MAINCMD_SPY_WRONGCMD); + return; + } - pp.setSpy(toggleSpy); + /* + * Command starts + */ + pp.setSpy(spy); pp.updatePlayer(); - if (toggleSpy) { + if (spy) { plugin.getSpyManager().addSpy(pp.getPlayerUUID()); pp.sendMessage(Messages.MAINCMD_SPY_ENABLED); LoggerManager.log(LogLevel.MEDIUM, Constants.DEBUG_CMD_SPY_ENABLE @@ -58,4 +69,9 @@ public void onCommand(CommandData commandData) { .replace("{player}", pp.getName()), true); } } + + @Override + public List onTabComplete(User sender, String[] args) { + return PartiesUtils.tabCompleteOnOff(args); + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandTeleport.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandTeleport.java similarity index 87% rename from common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandTeleport.java rename to common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandTeleport.java index 7c71d68d9..1d6ad29ad 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/executors/CommandTeleport.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandTeleport.java @@ -1,8 +1,8 @@ -package com.alessiodp.parties.common.commands.executors; +package com.alessiodp.parties.common.commands.sub; import com.alessiodp.parties.common.PartiesPlugin; -import com.alessiodp.parties.common.commands.AbstractCommand; -import com.alessiodp.parties.common.commands.CommandData; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.parties.objects.PartyImpl; import com.alessiodp.parties.common.players.PartiesPermission; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandVersion.java b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandVersion.java new file mode 100644 index 000000000..2d3d7fbd1 --- /dev/null +++ b/common/src/main/java/com/alessiodp/parties/common/commands/sub/CommandVersion.java @@ -0,0 +1,51 @@ +package com.alessiodp.parties.common.commands.sub; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.addons.internal.ADPUpdater; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.configuration.data.Messages; +import com.alessiodp.parties.common.players.PartiesPermission; +import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; +import com.alessiodp.parties.common.user.User; + +public class CommandVersion extends AbstractCommand { + + public CommandVersion(PartiesPlugin instance) { + super(instance); + } + + @Override + public boolean preRequisites(CommandData commandData) { + User sender = commandData.getSender(); + PartyPlayerImpl pp = plugin.getPlayerManager().getPlayer(sender.getUUID()); + + /* + * Checks for command prerequisites + */ + if (!sender.hasPermission(PartiesPermission.ADMIN_VERSION.toString())) { + pp.sendNoPermission(PartiesPermission.ADMIN_VERSION); + return false; + } + + commandData.setPartyPlayer(pp); + return true; + } + + @Override + public void onCommand(CommandData commandData) { + PartyPlayerImpl pp = commandData.getPartyPlayer(); + + /* + * Command starts + */ + + String version = plugin.getVersion(); + String newVersion = ADPUpdater.getFoundVersion().isEmpty() ? version : ADPUpdater.getFoundVersion(); + String message = version.equals(newVersion) ? Messages.MAINCMD_VERSION_UPDATED : Messages.MAINCMD_VERSION_OUTDATED; + + pp.sendMessage(message + .replace("%version%", version) + .replace("%newversion%", newVersion)); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/AbstractCommand.java b/common/src/main/java/com/alessiodp/parties/common/commands/utils/AbstractCommand.java similarity index 53% rename from common/src/main/java/com/alessiodp/parties/common/commands/AbstractCommand.java rename to common/src/main/java/com/alessiodp/parties/common/commands/utils/AbstractCommand.java index 7cc717b57..a5b3fdc2b 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/AbstractCommand.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/utils/AbstractCommand.java @@ -1,6 +1,11 @@ -package com.alessiodp.parties.common.commands; +package com.alessiodp.parties.common.commands.utils; import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.utils.CommandData; +import com.alessiodp.parties.common.user.User; + +import java.util.ArrayList; +import java.util.List; public abstract class AbstractCommand { protected PartiesPlugin plugin; @@ -8,12 +13,21 @@ public abstract class AbstractCommand { protected AbstractCommand(PartiesPlugin instance) { plugin = instance; } + /** * Used to check player before async execution */ public abstract boolean preRequisites(CommandData commandData); + /** * Async command */ public abstract void onCommand(CommandData commandData); + + /** + * Used to tab complete the command + */ + public List onTabComplete(User sender, String[] args){ + return new ArrayList<>(); + } } \ No newline at end of file diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/CommandData.java b/common/src/main/java/com/alessiodp/parties/common/commands/utils/CommandData.java similarity index 94% rename from common/src/main/java/com/alessiodp/parties/common/commands/CommandData.java rename to common/src/main/java/com/alessiodp/parties/common/commands/utils/CommandData.java index 628bffcd9..0e27cb043 100644 --- a/common/src/main/java/com/alessiodp/parties/common/commands/CommandData.java +++ b/common/src/main/java/com/alessiodp/parties/common/commands/utils/CommandData.java @@ -1,4 +1,4 @@ -package com.alessiodp.parties.common.commands; +package com.alessiodp.parties.common.commands.utils; import com.alessiodp.parties.common.parties.objects.PartyImpl; import com.alessiodp.parties.common.players.PartiesPermission; diff --git a/common/src/main/java/com/alessiodp/parties/common/commands/utils/PartiesCommandExecutor.java b/common/src/main/java/com/alessiodp/parties/common/commands/utils/PartiesCommandExecutor.java new file mode 100644 index 000000000..324a4c6b8 --- /dev/null +++ b/common/src/main/java/com/alessiodp/parties/common/commands/utils/PartiesCommandExecutor.java @@ -0,0 +1,18 @@ +package com.alessiodp.parties.common.commands.utils; + +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.user.User; + +import java.util.List; + +public abstract class PartiesCommandExecutor { + protected PartiesPlugin plugin; + + protected PartiesCommandExecutor(PartiesPlugin instance) { + plugin = instance; + } + + public abstract boolean onCommand(User sender, String command, String[] args); + + public abstract List onTabComplete(User sender, String[] args); +} diff --git a/common/src/main/java/com/alessiodp/parties/common/configuration/Constants.java b/common/src/main/java/com/alessiodp/parties/common/configuration/Constants.java index 5aac8006f..24155c283 100644 --- a/common/src/main/java/com/alessiodp/parties/common/configuration/Constants.java +++ b/common/src/main/java/com/alessiodp/parties/common/configuration/Constants.java @@ -5,17 +5,17 @@ public class Constants { public static final boolean DEBUG_ENABLED = false; public static final boolean DEBUG_TIMESTAMPS = false; - public static final int VERSION_BUKKIT_CONFIG_MAIN = 4; + public static final int VERSION_BUKKIT_CONFIG_MAIN = 5; public static final int VERSION_BUKKIT_CONFIG_PARTIES = 4; - public static final int VERSION_BUKKIT_MESSAGES = 5; + public static final int VERSION_BUKKIT_MESSAGES = 6; - public static final int VERSION_BUNGEE_CONFIG_MAIN = 3; + public static final int VERSION_BUNGEE_CONFIG_MAIN = 4; public static final int VERSION_BUNGEE_CONFIG_PARTIES = 3; - public static final int VERSION_BUNGEE_MESSAGES = 3; + public static final int VERSION_BUNGEE_MESSAGES = 4; public static final int VERSION_DATABASE_YAML = 1; - public static final int VERSION_DATABASE_MYSQL = 5; - public static final int VERSION_DATABASE_SQLITE = 3; + public static final int VERSION_DATABASE_MYSQL = 6; + public static final int VERSION_DATABASE_SQLITE = 4; public static final String FIXED_VALUE_TEXT = "fixed"; public static final String FIXED_VALUE_UUID = "00000000-0000-0000-0000-000000000000"; @@ -114,11 +114,10 @@ public class Constants { public static final String DEBUG_AUTOCMD_PERFORM = "Performing autocommand to {player} with '{command}'"; + public static final String DEBUG_AUTOCMD_REGEXERROR = "Wrong regex pattern for auto command system"; - public static final String DEBUG_CENSOR_REGEXERROR = "Wrong regex pattern for allowed servers of follow-server feature"; - - public static final String DEBUG_COMMANDS_REGISTER_PRE = "Registering commands"; - public static final String DEBUG_COMMANDS_REGISTER_POST = "Registered {value} commands"; + public static final String DEBUG_COMMANDS_REGISTER_PARTY_EXIST = "Party command was registered by another plugin, trying to overwrite it. If you have any problem you should change it by editing config.yml."; + public static final String DEBUG_COMMANDS_REGISTER_P_EXIST = "P command was registered by another plugin, trying to overwrite it. If you have any problem you should change it by editing config.yml."; public static final String DEBUG_CMD_ACCEPT = "{player} accepted invite for {party}"; public static final String DEBUG_CMD_CHAT = "{player} changed party chat to {value}"; public static final String DEBUG_CMD_CLAIM = "{player} claimed with {value}"; @@ -126,10 +125,16 @@ public class Constants { public static final String DEBUG_CMD_COLOR_REM = "{player} removed color of the party {party}"; public static final String DEBUG_CMD_CREATE = "{player} created the party {party}"; public static final String DEBUG_CMD_CREATE_FIXED = "{player} created the fixed party {party}"; + public static final String DEBUG_CMD_CREATE_REGEXERROR_AC = "Failed to parse allowed characters regex of create command"; + public static final String DEBUG_CMD_CREATE_REGEXERROR_CEN = "Failed to parse censor regex of create command"; public static final String DEBUG_CMD_DELETE = "{player} deleted the party {party}"; public static final String DEBUG_CMD_DENY = "{player} deleted the party {party}"; public static final String DEBUG_CMD_DESC = "{player} changed the description of {party}"; public static final String DEBUG_CMD_DESC_REM = "{player} removed the description of {party}"; + public static final String DEBUG_CMD_DESC_REGEXERROR_AC = "Failed to parse allowed characters regex of desc command"; + public static final String DEBUG_CMD_DESC_REGEXERROR_CEN = "Failed to parse censor regex of desc command"; + public static final String DEBUG_CMD_FOLLOW_ON = "{player} has enabled follow for {party}"; + public static final String DEBUG_CMD_FOLLOW_OFF = "{player} has disabled follow for {party}"; public static final String DEBUG_CMD_HOME = "{player} used command home, for {party}"; public static final String DEBUG_CMD_IGNORE_START = "{player} started to ignore the party {party}"; public static final String DEBUG_CMD_IGNORE_STOP = "{player} stopped to ignore the party {party}"; @@ -143,10 +148,13 @@ public class Constants { public static final String DEBUG_CMD_LIST = "{player} used the command list"; public static final String DEBUG_CMD_MOTD = "{player} changed the motd of {party}"; public static final String DEBUG_CMD_MOTD_REM = "{player} removed the motd of {party}"; + public static final String DEBUG_CMD_MOTD_REGEXERROR_AC = "Failed to parse allowed characters regex of motd command"; + public static final String DEBUG_CMD_MOTD_REGEXERROR_CEN = "Failed to parse censor regex of motd command"; public static final String DEBUG_CMD_MUTE_ON = "{player} is now muted"; public static final String DEBUG_CMD_MUTE_OFF = "{player} is not muted anymore"; public static final String DEBUG_CMD_P = "Chat of {party} by {player}: {message}"; public static final String DEBUG_CMD_P_TASK = "Started ChatTask for {value} by {player}"; + public static final String DEBUG_CMD_P_REGEXERROR = "Failed to parse censor regex of p command"; public static final String DEBUG_CMD_PASSWORD = "{player} changed the password of {party}"; public static final String DEBUG_CMD_PASSWORD_REM = "{player} removed the password of {party}"; public static final String DEBUG_CMD_PROTECTION_ON = "{player} has enabled protection for {party}"; @@ -252,8 +260,8 @@ public class Constants { public static final String QUERY_PLAYER_GETBYPARTY = "SELECT * FROM {table_players} WHERE `party`=?;"; public static final String QUERY_PLAYER_GETBYNAME = "SELECT * FROM {table_players} WHERE `name`=?;"; - public static final String QUERY_PARTY_INSERT_MYSQL = "INSERT INTO {table_parties} (`name`, `leader`, `description`, `motd`, `color`, `kills`, `password`, `home`, `protection`, `experience`) VALUES (?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `leader`=VALUES(`leader`), `description`=VALUES(`description`), `motd`=VALUES(`motd`), `color`=VALUES(`color`), `kills`=VALUES(`kills`), `password`=VALUES(`password`), `home`=VALUES(`home`), `protection`=VALUES(`protection`), `experience`=VALUES(`experience`);"; - public static final String QUERY_PARTY_INSERT_SQLITE = "INSERT OR REPLACE INTO {table_parties} (`name`, `leader`, `description`, `motd`, `color`, `kills`, `password`, `home`, `protection`, `experience`) VALUES (?,?,?,?,?,?,?,?,?,?);"; + public static final String QUERY_PARTY_INSERT_MYSQL = "INSERT INTO {table_parties} (`name`, `leader`, `description`, `motd`, `color`, `kills`, `password`, `home`, `protection`, `experience`, `follow`) VALUES (?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `leader`=VALUES(`leader`), `description`=VALUES(`description`), `motd`=VALUES(`motd`), `color`=VALUES(`color`), `kills`=VALUES(`kills`), `password`=VALUES(`password`), `home`=VALUES(`home`), `protection`=VALUES(`protection`), `experience`=VALUES(`experience`), `follow`=VALUES(`follow`);"; + public static final String QUERY_PARTY_INSERT_SQLITE = "INSERT OR REPLACE INTO {table_parties} (`name`, `leader`, `description`, `motd`, `color`, `kills`, `password`, `home`, `protection`, `experience`, `follow`) VALUES (?,?,?,?,?,?,?,?,?,?,?);"; public static final String QUERY_PARTY_GET_MYSQL = "SELECT * FROM {table_parties} WHERE `name`=?;"; public static final String QUERY_PARTY_GET_SQLITE = "SELECT * FROM {table_parties} WHERE `name`=? COLLATE NOCASE;"; public static final String QUERY_PARTY_GETALL = "SELECT * FROM {table_parties};"; diff --git a/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigMain.java b/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigMain.java index efd843eee..1a12c2fc1 100644 --- a/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigMain.java +++ b/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigMain.java @@ -6,7 +6,6 @@ import com.alessiodp.parties.common.configuration.adapter.ConfigurationAdapter; import com.alessiodp.parties.common.configuration.adapter.ConfigurationSectionAdapter; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -56,15 +55,10 @@ public abstract class ConfigMain extends ConfigurationFile { // Additional settings public static boolean ADDITIONAL_AUTOCMD_ENABLE; - public static List ADDITIONAL_AUTOCMD_BLACKLIST; - public static List ADDITIONAL_AUTOCMD_WHITELIST; + public static String ADDITIONAL_AUTOCMD_REGEXWHITELIST; - public static boolean ADDITIONAL_CENSOR_ENABLE; - public static boolean ADDITIONAL_CENSOR_CASESENSITIVE; - public static List ADDITIONAL_CENSOR_CONTAINS; - public static List ADDITIONAL_CENSOR_STARTSWITH; - public static List ADDITIONAL_CENSOR_ENDSWITH; - public static List ADDITIONAL_CENSOR_REGEXES; + public static boolean ADDITIONAL_FOLLOW_ENABLE; + public static boolean ADDITIONAL_FOLLOW_TOGGLECMD; public static boolean ADDITIONAL_MUTE_ENABLE; public static boolean ADDITIONAL_MUTE_BLOCK_INVITE; @@ -86,6 +80,7 @@ public abstract class ConfigMain extends ConfigurationFile { // Commands settings + public static boolean COMMANDS_TABSUPPORT; public static int COMMANDS_HELP_PERPAGE; public static String COMMANDS_CMD_HELP; @@ -98,6 +93,7 @@ public abstract class ConfigMain extends ConfigurationFile { public static String COMMANDS_CMD_DELETE; public static String COMMANDS_CMD_DENY; public static String COMMANDS_CMD_DESC; + public static String COMMANDS_CMD_FOLLOW; public static String COMMANDS_CMD_IGNORE; public static String COMMANDS_CMD_INFO; public static String COMMANDS_CMD_INVITE; @@ -114,6 +110,7 @@ public abstract class ConfigMain extends ConfigurationFile { public static String COMMANDS_CMD_RENAME; public static String COMMANDS_CMD_SPY; public static String COMMANDS_CMD_TELEPORT; + public static String COMMANDS_CMD_VERSION; public static String COMMANDS_SUB_ON; public static String COMMANDS_SUB_OFF; @@ -173,17 +170,10 @@ public void loadDefaults() { // Additional features ADDITIONAL_AUTOCMD_ENABLE = false; - ADDITIONAL_AUTOCMD_BLACKLIST = new ArrayList<>(); - ADDITIONAL_AUTOCMD_BLACKLIST.add("/pay"); - ADDITIONAL_AUTOCMD_BLACKLIST.add("/money"); - ADDITIONAL_AUTOCMD_WHITELIST = new ArrayList<>(); + ADDITIONAL_AUTOCMD_REGEXWHITELIST = "^(?!(\\/party|\\/pay|\\/money)).*"; - ADDITIONAL_CENSOR_ENABLE = false; - ADDITIONAL_CENSOR_CASESENSITIVE = false; - ADDITIONAL_CENSOR_CONTAINS = new ArrayList<>(); - ADDITIONAL_CENSOR_STARTSWITH = new ArrayList<>(); - ADDITIONAL_CENSOR_ENDSWITH = new ArrayList<>(); - ADDITIONAL_CENSOR_REGEXES = new ArrayList<>(); + ADDITIONAL_FOLLOW_ENABLE = false; + ADDITIONAL_FOLLOW_TOGGLECMD = false; ADDITIONAL_MUTE_ENABLE = false; ADDITIONAL_MUTE_BLOCK_INVITE = true; @@ -207,6 +197,7 @@ public void loadDefaults() { // Commands settings + COMMANDS_TABSUPPORT = true; COMMANDS_HELP_PERPAGE = 9; COMMANDS_CMD_HELP = "help"; @@ -219,6 +210,7 @@ public void loadDefaults() { COMMANDS_CMD_DELETE = "delete"; COMMANDS_CMD_DENY = "deny"; COMMANDS_CMD_DESC = "desc"; + COMMANDS_CMD_FOLLOW = "follow"; COMMANDS_CMD_IGNORE = "ignore"; COMMANDS_CMD_INFO = "info"; COMMANDS_CMD_INVITE = "invite"; @@ -235,6 +227,7 @@ public void loadDefaults() { COMMANDS_CMD_RENAME = "rename"; COMMANDS_CMD_SPY = "spy"; COMMANDS_CMD_TELEPORT = "teleport"; + COMMANDS_CMD_VERSION = "version"; COMMANDS_SUB_ON = "on"; COMMANDS_SUB_OFF = "off"; @@ -289,15 +282,10 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { // Additional settings ADDITIONAL_AUTOCMD_ENABLE = confAdapter.getBoolean("additional.auto-command.enable", ADDITIONAL_AUTOCMD_ENABLE); - ADDITIONAL_AUTOCMD_BLACKLIST = confAdapter.getStringList("additional.auto-command.blacklist", ADDITIONAL_AUTOCMD_BLACKLIST); - ADDITIONAL_AUTOCMD_WHITELIST = confAdapter.getStringList("additional.auto-command.whitelist", ADDITIONAL_AUTOCMD_WHITELIST); + ADDITIONAL_AUTOCMD_REGEXWHITELIST = confAdapter.getString("additional.auto-command.regex-whitelist", ADDITIONAL_AUTOCMD_REGEXWHITELIST); - ADDITIONAL_CENSOR_ENABLE = confAdapter.getBoolean("additional.censor-system.enable", ADDITIONAL_CENSOR_ENABLE); - ADDITIONAL_CENSOR_CASESENSITIVE = confAdapter.getBoolean("additional.censor-system.case-sensitive", ADDITIONAL_CENSOR_CASESENSITIVE); - ADDITIONAL_CENSOR_CONTAINS = confAdapter.getStringList("additional.censor-system.contains", ADDITIONAL_CENSOR_CONTAINS); - ADDITIONAL_CENSOR_STARTSWITH = confAdapter.getStringList("additional.censor-system.starts-with", ADDITIONAL_CENSOR_STARTSWITH); - ADDITIONAL_CENSOR_ENDSWITH = confAdapter.getStringList("additional.censor-system.ends-with", ADDITIONAL_CENSOR_ENDSWITH); - ADDITIONAL_CENSOR_REGEXES = confAdapter.getStringList("additional.censor-system.regexes", ADDITIONAL_CENSOR_REGEXES); + ADDITIONAL_FOLLOW_ENABLE = confAdapter.getBoolean("additional.follow-party.enable", ADDITIONAL_FOLLOW_ENABLE); + ADDITIONAL_FOLLOW_TOGGLECMD = confAdapter.getBoolean("additional.follow-party.toggle-command", ADDITIONAL_FOLLOW_TOGGLECMD); ADDITIONAL_MUTE_ENABLE = confAdapter.getBoolean("additional.mute.enable", ADDITIONAL_MUTE_ENABLE); ADDITIONAL_MUTE_BLOCK_INVITE = confAdapter.getBoolean("additional.mute.block.INVITE", ADDITIONAL_MUTE_BLOCK_INVITE); @@ -319,6 +307,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { // Commands settings + COMMANDS_TABSUPPORT = confAdapter.getBoolean("commands.tab-support", COMMANDS_TABSUPPORT); COMMANDS_HELP_PERPAGE = confAdapter.getInt("commands.help-pages.commands-per-page", COMMANDS_HELP_PERPAGE); COMMANDS_CMD_HELP = confAdapter.getString("commands.main-commands.help", COMMANDS_CMD_HELP); @@ -331,6 +320,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { COMMANDS_CMD_DELETE = confAdapter.getString("commands.main-commands.delete", COMMANDS_CMD_DELETE); COMMANDS_CMD_DENY = confAdapter.getString("commands.main-commands.deny", COMMANDS_CMD_DENY); COMMANDS_CMD_DESC = confAdapter.getString("commands.main-commands.desc", COMMANDS_CMD_DESC); + COMMANDS_CMD_FOLLOW = confAdapter.getString("commands.main-commands.follow", COMMANDS_CMD_FOLLOW); COMMANDS_CMD_IGNORE = confAdapter.getString("commands.main-commands.ignore", COMMANDS_CMD_IGNORE); COMMANDS_CMD_INFO = confAdapter.getString("commands.main-commands.info", COMMANDS_CMD_INFO); COMMANDS_CMD_INVITE = confAdapter.getString("commands.main-commands.invite", COMMANDS_CMD_INVITE); @@ -347,6 +337,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { COMMANDS_CMD_RENAME = confAdapter.getString("commands.main-commands.rename", COMMANDS_CMD_RENAME); COMMANDS_CMD_SPY = confAdapter.getString("commands.main-commands.spy", COMMANDS_CMD_SPY); COMMANDS_CMD_TELEPORT = confAdapter.getString("commands.main-commands.teleport", COMMANDS_CMD_TELEPORT); + COMMANDS_CMD_VERSION = confAdapter.getString("commands.main-commands.version", COMMANDS_CMD_VERSION); COMMANDS_SUB_ON = confAdapter.getString("commands.sub-commands.on", COMMANDS_SUB_ON); COMMANDS_SUB_OFF = confAdapter.getString("commands.sub-commands.off", COMMANDS_SUB_OFF); diff --git a/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigParties.java b/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigParties.java index af0c10a5c..217c38527 100644 --- a/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigParties.java +++ b/common/src/main/java/com/alessiodp/parties/common/configuration/data/ConfigParties.java @@ -17,6 +17,7 @@ public abstract class ConfigParties extends ConfigurationFile { // General settings public static int GENERAL_MEMBERSLIMIT; public static String GENERAL_NAME_ALLOWEDCHARS; + public static String GENERAL_NAME_CENSORREGEX; public static int GENERAL_NAME_MINLENGTH; public static int GENERAL_NAME_MAXLENGTH; @@ -30,6 +31,7 @@ public abstract class ConfigParties extends ConfigurationFile { public static boolean GENERAL_CHAT_ALLOWCOLORS; public static boolean GENERAL_CHAT_TOGGLECHATCMD; public static int GENERAL_CHAT_CHATCD; + public static String GENERAL_CHAT_CENSORREGEX; public static boolean GENERAL_CHAT_DIRECT_ENABLED; public static String GENERAL_CHAT_DIRECT_PREFIX; public static String GENERAL_CHAT_FORMAT_PARTY; @@ -58,6 +60,7 @@ public abstract class ConfigParties extends ConfigurationFile { public static int DESC_MINLENGTH; public static int DESC_MAXLENGTH; public static String DESC_ALLOWEDCHARS; + public static String DESC_CENSORREGEX; public static boolean FIXED_ENABLE; public static boolean FIXED_DEFAULT_ENABLE; @@ -83,6 +86,7 @@ public abstract class ConfigParties extends ConfigurationFile { public static int MOTD_DELAY; public static String MOTD_ALLOWEDCHARS; public static String MOTD_NEWLINECODE; + public static String MOTD_CENSORREGEX; public static boolean TELEPORT_ENABLE; public static int TELEPORT_COOLDOWN; @@ -96,6 +100,7 @@ public void loadDefaults() { // General settings GENERAL_MEMBERSLIMIT = -1; GENERAL_NAME_ALLOWEDCHARS = "[a-zA-Z0-9]+"; + GENERAL_NAME_CENSORREGEX = ""; GENERAL_NAME_MINLENGTH = 3; GENERAL_NAME_MAXLENGTH = 10; @@ -109,6 +114,7 @@ public void loadDefaults() { GENERAL_CHAT_ALLOWCOLORS = false; GENERAL_CHAT_TOGGLECHATCMD = true; GENERAL_CHAT_CHATCD = 0; + GENERAL_CHAT_CENSORREGEX = ""; GENERAL_CHAT_DIRECT_ENABLED = false; GENERAL_CHAT_DIRECT_PREFIX = "@"; GENERAL_CHAT_FORMAT_PARTY = "&b[Party] %rank_chat% %player%&r&7: &b%message%"; @@ -167,6 +173,7 @@ public void loadDefaults() { DESC_MINLENGTH = 3; DESC_MAXLENGTH = 16; DESC_ALLOWEDCHARS = "[a-zA-Z0-9\\ \\.\\,\\-\\_]+"; + DESC_CENSORREGEX = ""; FIXED_ENABLE = false; FIXED_DEFAULT_ENABLE = false; @@ -192,6 +199,7 @@ public void loadDefaults() { MOTD_DELAY = 20; MOTD_ALLOWEDCHARS = "[a-zA-Z0-9\\ \\.\\,\\-\\_]+"; MOTD_NEWLINECODE = "\\\\n"; + MOTD_CENSORREGEX = ""; TELEPORT_ENABLE = false; TELEPORT_COOLDOWN = 60; @@ -202,6 +210,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { // General settings GENERAL_MEMBERSLIMIT = confAdapter.getInt("general.members-limit", GENERAL_MEMBERSLIMIT); GENERAL_NAME_ALLOWEDCHARS = confAdapter.getString("general.name.allowed-characters", GENERAL_NAME_ALLOWEDCHARS); + GENERAL_NAME_CENSORREGEX = confAdapter.getString("general.name.censor-regex", GENERAL_NAME_CENSORREGEX); GENERAL_NAME_MINLENGTH = confAdapter.getInt("general.name.minimum-length", GENERAL_NAME_MINLENGTH); GENERAL_NAME_MAXLENGTH = confAdapter.getInt("general.name.maximum-length", GENERAL_NAME_MAXLENGTH); @@ -215,6 +224,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { GENERAL_CHAT_ALLOWCOLORS = confAdapter.getBoolean("general.chat.allow-colors", GENERAL_CHAT_ALLOWCOLORS); GENERAL_CHAT_TOGGLECHATCMD = confAdapter.getBoolean("general.chat.enable-toggle-command", GENERAL_CHAT_TOGGLECHATCMD); GENERAL_CHAT_CHATCD = confAdapter.getInt("general.chat.chat-cooldown", GENERAL_CHAT_CHATCD); + GENERAL_CHAT_CENSORREGEX = confAdapter.getString("general.chat.censor-regex", GENERAL_CHAT_CENSORREGEX); GENERAL_CHAT_DIRECT_ENABLED = confAdapter.getBoolean("general.chat.direct.enable", GENERAL_CHAT_DIRECT_ENABLED); GENERAL_CHAT_DIRECT_PREFIX = confAdapter.getString("general.chat.direct.prefix", GENERAL_CHAT_DIRECT_PREFIX); GENERAL_CHAT_FORMAT_PARTY = confAdapter.getString("general.chat.formats.party-chat", GENERAL_CHAT_FORMAT_PARTY); @@ -241,6 +251,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { DESC_MINLENGTH = confAdapter.getInt("additional.description.minimum-length", DESC_MINLENGTH); DESC_MAXLENGTH = confAdapter.getInt("additional.description.maximum-length", DESC_MAXLENGTH); DESC_ALLOWEDCHARS = confAdapter.getString("additional.description.allowed-characters", DESC_ALLOWEDCHARS); + DESC_CENSORREGEX = confAdapter.getString("additional.description.censor-regex", DESC_CENSORREGEX); FIXED_ENABLE = confAdapter.getBoolean("additional.fixed-system.enable", FIXED_ENABLE); FIXED_DEFAULT_ENABLE = confAdapter.getBoolean("additional.fixed-system.default-party.enable", FIXED_DEFAULT_ENABLE); @@ -266,6 +277,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { MOTD_DELAY = confAdapter.getInt("additional.motd.delay", MOTD_DELAY); MOTD_ALLOWEDCHARS = confAdapter.getString("additional.motd.allowed-characters", MOTD_ALLOWEDCHARS); MOTD_NEWLINECODE = confAdapter.getString("additional.motd.new-line-code", MOTD_NEWLINECODE); + MOTD_CENSORREGEX = confAdapter.getString("additional.motd.censor-regex", MOTD_CENSORREGEX); TELEPORT_ENABLE = confAdapter.getBoolean("additional.teleport.enable", TELEPORT_ENABLE); TELEPORT_COOLDOWN = confAdapter.getInt("additional.teleport.cooldown", TELEPORT_COOLDOWN); diff --git a/common/src/main/java/com/alessiodp/parties/common/configuration/data/Messages.java b/common/src/main/java/com/alessiodp/parties/common/configuration/data/Messages.java index 4d23c8668..e1e97b17d 100644 --- a/common/src/main/java/com/alessiodp/parties/common/configuration/data/Messages.java +++ b/common/src/main/java/com/alessiodp/parties/common/configuration/data/Messages.java @@ -105,6 +105,7 @@ public abstract class Messages extends ConfigurationFile { public static String MAINCMD_MIGRATE_WRONGDB; public static String MAINCMD_P_COOLDOWN; + public static String MAINCMD_P_CENSORED; public static String MAINCMD_P_WRONGCMD; public static String MAINCMD_RANK_CHANGED; @@ -126,6 +127,10 @@ public abstract class Messages extends ConfigurationFile { public static String MAINCMD_SPY_ENABLED; public static String MAINCMD_SPY_DISABLED; + public static String MAINCMD_SPY_WRONGCMD; + + public static String MAINCMD_VERSION_UPDATED; + public static String MAINCMD_VERSION_OUTDATED; // Additional commands messages @@ -144,6 +149,10 @@ public abstract class Messages extends ConfigurationFile { public static String ADDCMD_DESC_CENSORED; public static String ADDCMD_DESC_WRONGCMD; + public static String ADDCMD_FOLLOW_ON; + public static String ADDCMD_FOLLOW_OFF; + public static String ADDCMD_FOLLOW_WRONGCMD; + public static String ADDCMD_JOIN_JOINED; public static String ADDCMD_JOIN_PLAYERJOINED; public static String ADDCMD_JOIN_WRONGPASSWORD; @@ -207,9 +216,11 @@ public abstract class Messages extends ConfigurationFile { public static String HELP_MAINCMD_RELOAD; public static String HELP_MAINCMD_RENAME; public static String HELP_MAINCMD_SPY; + public static String HELP_MAINCMD_VERSION; public static String HELP_ADDCMD_COLOR; public static String HELP_ADDCMD_DESC; + public static String HELP_ADDCMD_FOLLOW; public static String HELP_ADDCMD_JOIN; public static String HELP_ADDCMD_LIST; public static String HELP_ADDCMD_MOTD; @@ -249,7 +260,7 @@ public void loadDefaults() { MAINCMD_CHAT_WRONGCMD = "&cWrong variables: Type &7/party chat [on/off]"; MAINCMD_CREATE_CREATED = "[{\"text\":\"You have created the party %party%.\\n\",\"color\":\"aqua\",\"bold\":true},{\"text\":\"Type \",\"color\":\"aqua\",\"bold\":false},{\"text\":\"/party invite\",\"color\":\"gray\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party invite \"}},{\"text\":\" to invite your friend.\",\"color\":\"aqua\"}]"; - MAINCMD_CREATE_CREATEDFIXED = "&l&bYou have created the fixed party %party%"; + MAINCMD_CREATE_CREATEDFIXED = "&b&lYou have created the fixed party %party%"; MAINCMD_CREATE_NAMEEXISTS = "&cThe party name %party% already exists, choose a different name"; MAINCMD_CREATE_NAMETOOLONG = "&cThe party name is too long!"; MAINCMD_CREATE_NAMETOOSHORT = "&cThe party name is too short!"; @@ -330,6 +341,7 @@ public void loadDefaults() { MAINCMD_MIGRATE_WRONGDB = "&cDatabase not found. You can select: YAML, MySQL, SQLite!"; MAINCMD_P_COOLDOWN = "&cYou still have to wait %seconds% seconds"; + MAINCMD_P_CENSORED = "&cThe message contains censored words!"; MAINCMD_P_WRONGCMD = "&cWrong variables: Type &7/p "; MAINCMD_RANK_CHANGED = "&a%player% rank changed into %rank_name%"; @@ -351,6 +363,10 @@ public void loadDefaults() { MAINCMD_SPY_ENABLED = "&7Now you are a spy!"; MAINCMD_SPY_DISABLED = "&7You are no longer a spy"; + MAINCMD_SPY_WRONGCMD = "&cWrong variables: Type &7/party spy [on/off]"; + + MAINCMD_VERSION_UPDATED = "&b&lParties &b%version% &7- Developed by &6AlessioDP"; + MAINCMD_VERSION_OUTDATED = "&b&lParties &b%version% &7- Developed by &6AlessioDP\n&aNew version found: &2%newversion%"; // Additional commands messages @@ -369,6 +385,10 @@ public void loadDefaults() { ADDCMD_DESC_CENSORED = "&cThe description contains censored words!"; ADDCMD_DESC_WRONGCMD = "&cWrong variables: Type &7/party desc "; + ADDCMD_FOLLOW_ON = "&aNow your party members will follow your leader"; + ADDCMD_FOLLOW_OFF = "&aYour party members will not follow your leader anymore"; + ADDCMD_FOLLOW_WRONGCMD = "&cWrong variables: Type &7/party follow [on/off]"; + ADDCMD_JOIN_JOINED = "&aYou joined the party %party%"; ADDCMD_JOIN_PLAYERJOINED = "&b&l%player% joined in the party"; ADDCMD_JOIN_WRONGPASSWORD = "&cWrong password!"; @@ -398,7 +418,7 @@ public void loadDefaults() { ADDCMD_PASSWORD_REMOVED = "&aParty password removed"; ADDCMD_PASSWORD_BROADCAST = ""; ADDCMD_PASSWORD_INVALID = "&cInvalid characters. Use: a-Z or 0-9. Min 1 and max 16 chars."; - ADDCMD_PASSWORD_WRONGCMD = "&cWrong variables: Type &7/party password "; + ADDCMD_PASSWORD_WRONGCMD = "&cWrong variables: Type &7/party password "; ADDCMD_TELEPORT_TELEPORTING = "&7Teleporting your party here!"; ADDCMD_TELEPORT_TELEPORTED = "&bTeleported to %player%"; @@ -421,11 +441,11 @@ public void loadDefaults() { HELP_MAINCMD_HELP = "{\"text\":\"\",\"extra\":[{\"text\":\"/party help [page]\",\"color\":\"aqua\"},{\"text\":\" - Show help pages\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party help \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_ACCEPT = "{\"text\":\"\",\"extra\":[{\"text\":\"/party accept\",\"color\":\"aqua\"},{\"text\":\" - Accept a party invitation\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party accept\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_MAINCMD_CHAT = "{\"text\":\"\",\"extra\":[{\"text\":\"/party chat [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Toggle the party chat\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party chat \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_CHAT = "{\"text\":\"\",\"extra\":[{\"text\":\"/party chat [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Toggle party chat\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party chat \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_CREATE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party create \",\"color\":\"aqua\"},{\"text\":\" - Create a new party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party create \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_DELETE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party delete \",\"color\":\"aqua\"},{\"text\":\" - Delete the party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party delete \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_DENY = "{\"text\":\"\",\"extra\":[{\"text\":\"/party deny\",\"color\":\"aqua\"},{\"text\":\" - Deny a party invitation\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party deny\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_MAINCMD_IGNORE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party ignore [party]\",\"color\":\"aqua\"},{\"text\":\" - Add/remove/show parties ignored\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party ignore \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_IGNORE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party ignore [party]\",\"color\":\"aqua\"},{\"text\":\" - Add/remove/show ignored parties\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party ignore \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_INFO = "{\"text\":\"\",\"extra\":[{\"text\":\"/party info [party]\",\"color\":\"aqua\"},{\"text\":\" - Show party information\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party info \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_INVITE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party invite \",\"color\":\"aqua\"},{\"text\":\" - Invite a player to your party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party invite \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_KICK = "{\"text\":\"\",\"extra\":[{\"text\":\"/party kick \",\"color\":\"aqua\"},{\"text\":\" - Kick a player from your party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party kick \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; @@ -433,15 +453,17 @@ public void loadDefaults() { HELP_MAINCMD_MIGRATE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party migrate \",\"color\":\"aqua\"},{\"text\":\" - Copy database into a new one\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party migrate \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_P = "{\"text\":\"\",\"extra\":[{\"text\":\"/p \",\"color\":\"aqua\"},{\"text\":\" - Send a message to the party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/p \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_MAINCMD_RANK = "{\"text\":\"\",\"extra\":[{\"text\":\"/party rank \",\"color\":\"aqua\"},{\"text\":\" - Change rank of the player\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party rank \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_MAINCMD_RELOAD = "{\"text\":\"\",\"extra\":[{\"text\":\"/party reload\",\"color\":\"aqua\"},{\"text\":\" - Reload the configuration\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party reload\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_MAINCMD_RENAME = "{\"text\":\"\",\"extra\":[{\"text\":\"/party rename [party] \",\"color\":\"aqua\"},{\"text\":\" - Renames a party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party rename \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_MAINCMD_SPY = "{\"text\":\"\",\"extra\":[{\"text\":\"/party spy\",\"color\":\"aqua\"},{\"text\":\" - See messages from other parties\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party spy\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - - HELP_ADDCMD_COLOR = "{\"text\":\"\",\"extra\":[{\"text\":\"/party color \",\"color\":\"aqua\"},{\"text\":\" - Change color of the party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party color \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_ADDCMD_DESC = "{\"text\":\"\",\"extra\":[{\"text\":\"/party desc \",\"color\":\"aqua\"},{\"text\":\" - Add/remove description\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party desc \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_ADDCMD_JOIN = "{\"text\":\"\",\"extra\":[{\"text\":\"/party join [password]\",\"color\":\"aqua\"},{\"text\":\" - Join into a party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party join \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_RELOAD = "{\"text\":\"\",\"extra\":[{\"text\":\"/party reload\",\"color\":\"aqua\"},{\"text\":\" - Reload Parties configuration files\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party reload\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_RENAME = "{\"text\":\"\",\"extra\":[{\"text\":\"/party rename [party] \",\"color\":\"aqua\"},{\"text\":\" - Rename the party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party rename \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_SPY = "{\"text\":\"\",\"extra\":[{\"text\":\"/party spy [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Spy messages of other parties\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party spy \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_MAINCMD_VERSION = "{\"text\":\"\",\"extra\":[{\"text\":\"/party version\",\"color\":\"aqua\"},{\"text\":\" - Show Parties information\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party version\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + + HELP_ADDCMD_COLOR = "{\"text\":\"\",\"extra\":[{\"text\":\"/party color \",\"color\":\"aqua\"},{\"text\":\" - Change party color\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party color \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_ADDCMD_DESC = "{\"text\":\"\",\"extra\":[{\"text\":\"/party desc \",\"color\":\"aqua\"},{\"text\":\" - Set/remove party description\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party desc \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_ADDCMD_FOLLOW = "{\"text\":\"\",\"extra\":[{\"text\":\"/party follow [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Toggle follow leader\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party follow \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_ADDCMD_JOIN = "{\"text\":\"\",\"extra\":[{\"text\":\"/party join [password]\",\"color\":\"aqua\"},{\"text\":\" - Join into the party\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party join \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_LIST = "{\"text\":\"\",\"extra\":[{\"text\":\"/party list [page]\",\"color\":\"aqua\"},{\"text\":\" - List of online parties\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party list \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; - HELP_ADDCMD_MOTD = "{\"text\":\"\",\"extra\":[{\"text\":\"/party motd \",\"color\":\"aqua\"},{\"text\":\" - Add/remove motd\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party motd \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; + HELP_ADDCMD_MOTD = "{\"text\":\"\",\"extra\":[{\"text\":\"/party motd \",\"color\":\"aqua\"},{\"text\":\" - Set/remove party motd\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party motd \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_MUTE = "{\"text\":\"\",\"extra\":[{\"text\":\"/party mute [on/off]\",\"color\":\"aqua\"},{\"text\":\" - Toggle notifications\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party mute \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_PASSWORD = "{\"text\":\"\",\"extra\":[{\"text\":\"/party password \",\"color\":\"aqua\"},{\"text\":\" - Change party password\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party password \"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; HELP_ADDCMD_TELEPORT = "{\"text\":\"\",\"extra\":[{\"text\":\"/party teleport\",\"color\":\"aqua\"},{\"text\":\" - Teleport your party to you\",\"color\":\"gray\"}],\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/party teleport\"},\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"Perform the command\",\"color\":\"gold\"}}}"; @@ -546,6 +568,7 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { MAINCMD_MIGRATE_WRONGDB = confAdapter.getString("main-commands.migrate.wrong-database", MAINCMD_MIGRATE_WRONGDB); MAINCMD_P_COOLDOWN = confAdapter.getString("main-commands.p.cooldown", MAINCMD_P_COOLDOWN); + MAINCMD_P_CENSORED = confAdapter.getString("main-commands.p.censored", MAINCMD_P_CENSORED); MAINCMD_P_WRONGCMD = confAdapter.getString("main-commands.p.wrong-command", MAINCMD_P_WRONGCMD); MAINCMD_RANK_CHANGED = confAdapter.getString("main-commands.rank.changed", MAINCMD_RANK_CHANGED); @@ -567,6 +590,10 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { MAINCMD_SPY_ENABLED = confAdapter.getString("main-commands.spy.enabled", MAINCMD_SPY_ENABLED); MAINCMD_SPY_DISABLED = confAdapter.getString("main-commands.spy.disabled", MAINCMD_SPY_DISABLED); + MAINCMD_SPY_WRONGCMD = confAdapter.getString("main-commands.spy.wrong-command", MAINCMD_SPY_WRONGCMD); + + MAINCMD_VERSION_UPDATED = confAdapter.getString("main-commands.version.updated", MAINCMD_VERSION_UPDATED); + MAINCMD_VERSION_OUTDATED = confAdapter.getString("main-commands.version.outdated", MAINCMD_VERSION_OUTDATED); // Additional commands messages @@ -585,6 +612,10 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { ADDCMD_DESC_CENSORED = confAdapter.getString("additional-commands.desc.censored", ADDCMD_DESC_CENSORED); ADDCMD_DESC_WRONGCMD = confAdapter.getString("additional-commands.desc.wrong-command", ADDCMD_DESC_WRONGCMD); + ADDCMD_FOLLOW_ON = confAdapter.getString("additional-commands.follow.toggle-on", ADDCMD_FOLLOW_ON); + ADDCMD_FOLLOW_OFF = confAdapter.getString("additional-commands.follow.toggle-off", ADDCMD_FOLLOW_OFF); + ADDCMD_FOLLOW_WRONGCMD = confAdapter.getString("additional-commands.follow.wrong-command", ADDCMD_FOLLOW_WRONGCMD); + ADDCMD_JOIN_JOINED = confAdapter.getString("additional-commands.join.joined", ADDCMD_JOIN_JOINED); ADDCMD_JOIN_PLAYERJOINED = confAdapter.getString("additional-commands.join.player-joined", ADDCMD_JOIN_PLAYERJOINED); ADDCMD_JOIN_WRONGPASSWORD = confAdapter.getString("additional-commands.join.wrong-password", ADDCMD_JOIN_WRONGPASSWORD); @@ -648,9 +679,11 @@ public void loadConfiguration(ConfigurationAdapter confAdapter) { HELP_MAINCMD_RELOAD = confAdapter.getString("help.main-commands.reload", HELP_MAINCMD_RELOAD); HELP_MAINCMD_RENAME = confAdapter.getString("help.main-commands.rename", HELP_MAINCMD_RENAME); HELP_MAINCMD_SPY = confAdapter.getString("help.main-commands.spy", HELP_MAINCMD_SPY); + HELP_MAINCMD_VERSION = confAdapter.getString("help.main-commands.version", HELP_MAINCMD_VERSION); HELP_ADDCMD_COLOR = confAdapter.getString("help.additional-commands.color", HELP_ADDCMD_COLOR); HELP_ADDCMD_DESC = confAdapter.getString("help.additional-commands.desc", HELP_ADDCMD_DESC); + HELP_ADDCMD_FOLLOW = confAdapter.getString("help.additional-commands.follow", HELP_ADDCMD_FOLLOW); HELP_ADDCMD_JOIN = confAdapter.getString("help.additional-commands.join", HELP_ADDCMD_JOIN); HELP_ADDCMD_LIST = confAdapter.getString("help.additional-commands.list", HELP_ADDCMD_LIST); HELP_ADDCMD_MOTD = confAdapter.getString("help.additional-commands.motd", HELP_ADDCMD_MOTD); diff --git a/common/src/main/java/com/alessiodp/parties/common/listeners/ChatListener.java b/common/src/main/java/com/alessiodp/parties/common/listeners/ChatListener.java index 0aa379d08..8526024b9 100644 --- a/common/src/main/java/com/alessiodp/parties/common/listeners/ChatListener.java +++ b/common/src/main/java/com/alessiodp/parties/common/listeners/ChatListener.java @@ -13,6 +13,10 @@ import com.alessiodp.parties.common.players.objects.PartyPlayerImpl; import com.alessiodp.parties.common.tasks.ChatTask; import com.alessiodp.parties.common.user.User; +import com.alessiodp.parties.common.utils.PartiesUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; public abstract class ChatListener { private PartiesPlugin plugin; @@ -49,19 +53,24 @@ protected boolean onPlayerChat(User sender, String message) { // Chat allowed boolean mustWait = false; + if (PartiesUtils.checkCensor(ConfigParties.GENERAL_CHAT_CENSORREGEX, finalMessage, Constants.DEBUG_CMD_P_REGEXERROR)) { + pp.sendMessage(Messages.MAINCMD_P_CENSORED); + return; + } + if (ConfigParties.GENERAL_CHAT_CHATCD > 0 && !plugin.getRankManager().checkPlayerRank(pp, PartiesPermission.PRIVATE_BYPASSCOOLDOWN)) { Long unixTimestamp = plugin.getCooldownManager().getChatCooldown().get(pp.getPlayerUUID()); long unixNow = System.currentTimeMillis() / 1000L; // Check cooldown - if (unixTimestamp != null) { + if (unixTimestamp != null && (unixNow - unixTimestamp) < ConfigParties.GENERAL_CHAT_CHATCD) { pp.sendMessage(Messages.MAINCMD_P_COOLDOWN .replace("%seconds%", String.valueOf(ConfigParties.GENERAL_CHAT_CHATCD - (unixNow - unixTimestamp)))); mustWait = true; } else { plugin.getCooldownManager().getChatCooldown().put(pp.getPlayerUUID(), unixNow); - plugin.getPartiesScheduler().scheduleTaskLater(new ChatTask(plugin, pp.getPlayerUUID()), ConfigParties.GENERAL_CHAT_CHATCD); + plugin.getPartiesScheduler().scheduleTaskLater(new ChatTask(plugin, pp.getPlayerUUID()), ConfigParties.GENERAL_CHAT_CHATCD * 20L); LoggerManager.log(LogLevel.DEBUG, Constants.DEBUG_CMD_P_TASK .replace("{value}", Integer.toString(ConfigParties.GENERAL_CHAT_CHATCD * 20)) @@ -110,19 +119,18 @@ protected String onPlayerCommandPreprocess(User sender, String message) { // This is a normal command to replicate // Make it async plugin.getPartiesScheduler().getEventsExecutor().execute(() -> { - boolean cancel = false; + boolean cancel = true; - for (String str : ConfigMain.ADDITIONAL_AUTOCMD_BLACKLIST) { - if (str.equalsIgnoreCase("*") || message.toLowerCase().startsWith(str.toLowerCase())) { - cancel = true; - break; - } - } - for (String str : ConfigMain.ADDITIONAL_AUTOCMD_WHITELIST) { - if (str.equalsIgnoreCase("*") || message.toLowerCase().startsWith(str.toLowerCase())) { + try { + Pattern pattern = Pattern.compile(ConfigMain.ADDITIONAL_AUTOCMD_REGEXWHITELIST, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(message); + + if (matcher.find()) { cancel = false; - break; } + } catch (Exception ex) { + LoggerManager.printError(Constants.DEBUG_AUTOCMD_REGEXERROR); + ex.printStackTrace(); } if (!cancel) { diff --git a/common/src/main/java/com/alessiodp/parties/common/listeners/JoinLeaveListener.java b/common/src/main/java/com/alessiodp/parties/common/listeners/JoinLeaveListener.java index 3af0fe4b2..bb126de48 100644 --- a/common/src/main/java/com/alessiodp/parties/common/listeners/JoinLeaveListener.java +++ b/common/src/main/java/com/alessiodp/parties/common/listeners/JoinLeaveListener.java @@ -55,7 +55,7 @@ protected void onPlayerJoin(User player) { } if (!party.getMotd().isEmpty()) { - plugin.getPartiesScheduler().scheduleTaskLater(new MotdTask(plugin, player.getUUID(), pp.getCreateID()), ConfigParties.MOTD_DELAY / 20L); + plugin.getPartiesScheduler().scheduleTaskLater(new MotdTask(plugin, player.getUUID(), pp.getCreateID()), ConfigParties.MOTD_DELAY); } // Update timestamp @@ -81,7 +81,7 @@ protected void onPlayerJoin(User player) { pp.updatePlayer(); if (!party.getMotd().isEmpty()) { - plugin.getPartiesScheduler().scheduleTaskLater(new MotdTask(plugin, player.getUUID(), pp.getCreateID()), ConfigParties.MOTD_DELAY / 20L); + plugin.getPartiesScheduler().scheduleTaskLater(new MotdTask(plugin, player.getUUID(), pp.getCreateID()), ConfigParties.MOTD_DELAY); } pp.sendMessage(Messages.OTHER_FIXED_DEFAULTJOIN, party); @@ -142,7 +142,8 @@ protected void onPlayerQuit(User player) { if (ConfigMain.STORAGE_SETTINGS_NONE_DELAYDELETEPARTY > 0) { plugin.getPlayerManager().getListPartyPlayersToDelete().add(pp.getPlayerUUID()); - int taskId = plugin.getPartiesScheduler().scheduleTaskLater(new PartyDeleteTask(plugin, party.getName()), ConfigMain.STORAGE_SETTINGS_NONE_DELAYDELETEPARTY); + int taskId = plugin.getPartiesScheduler().scheduleTaskLater( + new PartyDeleteTask(plugin, party.getName()), ConfigMain.STORAGE_SETTINGS_NONE_DELAYDELETEPARTY * 20L); plugin.getPartyManager().getListPartiesToDelete().put(party.getName().toLowerCase(), taskId); removePlFromList = false; diff --git a/common/src/main/java/com/alessiodp/parties/common/parties/CooldownManager.java b/common/src/main/java/com/alessiodp/parties/common/parties/CooldownManager.java index fed88c4f1..156929676 100644 --- a/common/src/main/java/com/alessiodp/parties/common/parties/CooldownManager.java +++ b/common/src/main/java/com/alessiodp/parties/common/parties/CooldownManager.java @@ -7,16 +7,16 @@ import java.util.List; import java.util.UUID; -public abstract class CooldownManager { +public class CooldownManager { @Getter private HashMap chatCooldown; @Getter private HashMap> inviteCooldown; @Getter private HashMap teleportCooldown; - protected CooldownManager() { + public CooldownManager() { reload(); } - public void reload() { + private void reload() { chatCooldown = new HashMap<>(); inviteCooldown = new HashMap<>(); teleportCooldown = new HashMap<>(); diff --git a/common/src/main/java/com/alessiodp/parties/common/parties/objects/PartyImpl.java b/common/src/main/java/com/alessiodp/parties/common/parties/objects/PartyImpl.java index 7b42d2a34..938328abf 100644 --- a/common/src/main/java/com/alessiodp/parties/common/parties/objects/PartyImpl.java +++ b/common/src/main/java/com/alessiodp/parties/common/parties/objects/PartyImpl.java @@ -5,6 +5,7 @@ import com.alessiodp.parties.api.interfaces.PartyPlayer; import com.alessiodp.parties.common.PartiesPlugin; import com.alessiodp.parties.common.configuration.Constants; +import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.configuration.data.Messages; import com.alessiodp.parties.common.logging.LogLevel; @@ -46,6 +47,7 @@ public abstract class PartyImpl implements Party { @Setter private boolean protection; @Getter @Setter private double experience; @Getter @Setter private ExpResult expResult; + @Setter private boolean followEnabled; @Getter @Setter private Color dynamicColor; @Getter private Set onlinePlayers; @@ -142,7 +144,7 @@ public void callChange() { */ public void invitePlayer(UUID invitedBy, UUID invitedPlayer) { int taskId = plugin.getPartiesScheduler().scheduleTaskLater( - new InviteTask(this, invitedPlayer), ConfigParties.GENERAL_INVITE_TIMEOUT); + new InviteTask(this, invitedPlayer), ConfigParties.GENERAL_INVITE_TIMEOUT * 20L); inviteMap.put(invitedPlayer, invitedBy); inviteTasks.put(invitedPlayer, taskId); @@ -346,12 +348,28 @@ public int getLevel() { return expResult.getLevel(); } + @Override + public boolean getProtection() {return protection;} + @Override public boolean isFriendlyFireProtected() { return getProtection(); } @Override - public boolean getProtection() {return protection;} + public boolean getFollowEnabled() {return followEnabled;} + + @Override + public boolean isFollowEnabled() { + boolean ret = false; + if (ConfigMain.ADDITIONAL_FOLLOW_ENABLE) { + if (ConfigMain.ADDITIONAL_FOLLOW_TOGGLECMD) { + ret = getFollowEnabled(); + } else { + ret = true; + } + } + return ret; + } } diff --git a/common/src/main/java/com/alessiodp/parties/common/players/PartiesPermission.java b/common/src/main/java/com/alessiodp/parties/common/players/PartiesPermission.java index 4892a1977..0319631c5 100644 --- a/common/src/main/java/com/alessiodp/parties/common/players/PartiesPermission.java +++ b/common/src/main/java/com/alessiodp/parties/common/players/PartiesPermission.java @@ -10,6 +10,7 @@ public enum PartiesPermission { CREATE ("parties.user.create"), DENY ("parties.user.deny"), DESC ("parties.user.desc"), + FOLLOW ("parties.user.follow"), HELP ("parties.user.help"), IGNORE ("parties.user.ignore"), INFO ("parties.user.info"), @@ -47,6 +48,8 @@ public enum PartiesPermission { ADMIN_RENAME_OTHERS ("parties.admin.rename.others"), ADMIN_SPY ("parties.admin.spy"), ADMIN_UPDATES ("parties.admin.updates"), + ADMIN_VERSION ("parties.admin.version"), + // Bukkit ADMIN_HOME_OTHERS ("parties.admin.home.others"), ADMIN_PROTECTION_BYPASS ("parties.admin.protection.bypass"), @@ -62,6 +65,7 @@ public enum PartiesPermission { PRIVATE_EDIT_HOME("party.edit.home"), PRIVATE_EDIT_DESC("party.edit.desc"), + PRIVATE_EDIT_FOLLOW("party.edit.follow"), PRIVATE_EDIT_MOTD("party.edit.motd"), PRIVATE_EDIT_COLOR("party.edit.color"), PRIVATE_EDIT_PASSWORD("party.edit.password"), diff --git a/common/src/main/java/com/alessiodp/parties/common/players/objects/InviteCooldown.java b/common/src/main/java/com/alessiodp/parties/common/players/objects/InviteCooldown.java index 499cd047a..419fa359d 100644 --- a/common/src/main/java/com/alessiodp/parties/common/players/objects/InviteCooldown.java +++ b/common/src/main/java/com/alessiodp/parties/common/players/objects/InviteCooldown.java @@ -40,7 +40,7 @@ public void createTask(int delay) { List list = plugin.getCooldownManager().getInviteCooldown().computeIfAbsent(from, k -> new ArrayList<>()); startTime = System.currentTimeMillis() / 1000L; // Unix timestamp - task = plugin.getPartiesScheduler().scheduleTaskLater(new InviteCooldownTask(this), delay); + task = plugin.getPartiesScheduler().scheduleTaskLater(new InviteCooldownTask(this), delay * 20L); list.add(this); } diff --git a/common/src/main/java/com/alessiodp/parties/common/players/objects/PartyPlayerImpl.java b/common/src/main/java/com/alessiodp/parties/common/players/objects/PartyPlayerImpl.java index fb1b56c0d..952f3c8fd 100644 --- a/common/src/main/java/com/alessiodp/parties/common/players/objects/PartyPlayerImpl.java +++ b/common/src/main/java/com/alessiodp/parties/common/players/objects/PartyPlayerImpl.java @@ -112,13 +112,18 @@ public List getAllowedCommands() { ret.add(CommonCommands.DESC); if (ConfigParties.MOTD_ENABLE && player.hasPermission(PartiesPermission.MOTD.toString()) && rank.havePermission(PartiesPermission.PRIVATE_EDIT_MOTD.toString())) ret.add(CommonCommands.MOTD); + if (ConfigMain.ADDITIONAL_FOLLOW_ENABLE + && ConfigMain.ADDITIONAL_FOLLOW_TOGGLECMD + && player.hasPermission(PartiesPermission.FOLLOW.toString()) + && rank.havePermission(PartiesPermission.PRIVATE_EDIT_FOLLOW.toString())) + ret.add(CommonCommands.FOLLOW); if (ConfigParties.COLOR_ENABLE && ConfigParties.COLOR_COLORCMD && player.hasPermission(PartiesPermission.COLOR.toString()) && rank.havePermission(PartiesPermission.PRIVATE_EDIT_COLOR.toString())) ret.add(CommonCommands.COLOR); if (ConfigParties.PASSWORD_ENABLE && player.hasPermission(PartiesPermission.PASSWORD.toString()) && rank.havePermission(PartiesPermission.PRIVATE_EDIT_PASSWORD.toString())) ret.add(CommonCommands.PASSWORD); if (player.hasPermission(PartiesPermission.RANK.toString()) && rank.havePermission(PartiesPermission.PRIVATE_ADMIN_RANK.toString())) ret.add(CommonCommands.RANK); - else if (player.hasPermission(PartiesPermission.ADMIN_RENAME_OTHERS.toString()) + if (player.hasPermission(PartiesPermission.ADMIN_RENAME_OTHERS.toString()) || (player.hasPermission(PartiesPermission.RENAME.toString()) && rank.havePermission(PartiesPermission.PRIVATE_ADMIN_RENAME.toString()))) ret.add(CommonCommands.RENAME); if (player.hasPermission(PartiesPermission.KICK.toString()) && rank.havePermission(PartiesPermission.PRIVATE_KICK.toString())) @@ -155,6 +160,8 @@ else if (player.hasPermission(PartiesPermission.ADMIN_RENAME_OTHERS.toString()) ret.add(CommonCommands.DELETE); if (player.hasPermission(PartiesPermission.ADMIN_RELOAD.toString())) ret.add(CommonCommands.RELOAD); + if (player.hasPermission(PartiesPermission.ADMIN_VERSION.toString())) + ret.add(CommonCommands.VERSION); if (player.hasPermission(PartiesPermission.ADMIN_MIGRATE.toString()) && !ConfigMain.STORAGE_MIGRATE_ONLYCONSOLE) ret.add(CommonCommands.MIGRATE); diff --git a/common/src/main/java/com/alessiodp/parties/common/scheduling/PartiesScheduler.java b/common/src/main/java/com/alessiodp/parties/common/scheduling/PartiesScheduler.java index 14a3fd5d8..f18d6dddc 100644 --- a/common/src/main/java/com/alessiodp/parties/common/scheduling/PartiesScheduler.java +++ b/common/src/main/java/com/alessiodp/parties/common/scheduling/PartiesScheduler.java @@ -42,8 +42,8 @@ public void shutdown() { public abstract void runSync(Runnable runnable); public abstract void runAsync(Runnable runnable); - public abstract void runAsyncTaskTimer(Runnable runnable, long seconds); - public abstract int scheduleTaskLater(Runnable runnable, long seconds); + public abstract int scheduleAsyncTaskTimer(Runnable runnable, long ticks); + public abstract int scheduleTaskLater(Runnable runnable, long ticks); public abstract void cancelTask(int taskId); } diff --git a/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/FileDispatcher.java b/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/FileDispatcher.java index a421be901..bc74ef77b 100644 --- a/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/FileDispatcher.java +++ b/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/FileDispatcher.java @@ -186,6 +186,10 @@ public void updateParty(PartyImpl party) { if (plugin.getPartyManager().isBukkit_expSystem() && party.getExperience() > 0) node.getNode("experience").setValue(party.getExperience()); + if (ConfigMain.ADDITIONAL_FOLLOW_ENABLE && ConfigMain.ADDITIONAL_FOLLOW_TOGGLECMD) { + node.getNode("follow").setValue(party.getFollowEnabled() ? null : false); // By default is true, so insert it only if false + } + node.getNode("home").setValue(party.getHome() != null ? party.getHome().toString() : null); node.getNode("leader").setValue(party.isFixed() ? Constants.FIXED_VALUE_TEXT : party.getLeader().toString()); @@ -327,6 +331,7 @@ private PartyImpl getPartyFromNode(ConfigurationNode node) { ret.setHome(HomeLocationImpl.deserialize(node.getNode("home").getString(""))); ret.setProtection(node.getNode("protection").getBoolean(false)); ret.setExperience(node.getNode("experience").getDouble(0)); + ret.setFollowEnabled(node.getNode("follow").getBoolean(true)); // Leader check String leader = node.getNode("leader").getString(""); diff --git a/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/SQLDispatcher.java b/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/SQLDispatcher.java index 3971d3811..4b0d8edf3 100644 --- a/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/SQLDispatcher.java +++ b/common/src/main/java/com/alessiodp/parties/common/storage/dispatchers/SQLDispatcher.java @@ -337,6 +337,7 @@ private void updateParty(PartyImpl party, Connection connection) { preStatement.setString(8, party.getHome() != null ? party.getHome().toString() : ""); preStatement.setBoolean(9, party.getProtection()); preStatement.setDouble(10, party.getExperience()); + preStatement.setBoolean(11, party.getFollowEnabled()); preStatement.executeUpdate(); } catch (SQLException ex) { LoggerManager.printError(LoggerManager.formatErrorCallTrace(Constants.DEBUG_SQL_ERROR, ex)); @@ -406,6 +407,7 @@ public void removeParty(PartyImpl party) { preStatement.setString(1, party.getName()); preStatement.executeUpdate(); + connection.commit(); } } catch (Exception ex) { connection.rollback(); @@ -511,7 +513,7 @@ public void insertLog(LogLine line) { if (connection != null) { try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_LOG_INSERT))) { preStatement.setTimestamp(1, new Timestamp(line.getDate().getTime())); - preStatement.setInt(2, Integer.valueOf(line.getLevel())); + preStatement.setInt(2, Integer.parseInt(line.getLevel())); preStatement.setString(3, line.getPosition()); preStatement.setString(4, line.getMessage()); @@ -554,6 +556,7 @@ private PartyImpl getPartyFromResultSet(Connection connection, ResultSet rs) { ret.setHome(HomeLocationImpl.deserialize(rs.getString("home"))); ret.setProtection(rs.getBoolean("protection")); ret.setExperience(rs.getDouble("experience")); + ret.setFollowEnabled(rs.getBoolean("follow")); String leader = rs.getString("leader"); if (leader != null) { if (leader.equalsIgnoreCase(Constants.FIXED_VALUE_TEXT)) { diff --git a/common/src/main/java/com/alessiodp/parties/common/storage/sql/SQLUpgradeManager.java b/common/src/main/java/com/alessiodp/parties/common/storage/sql/SQLUpgradeManager.java index 96d30fbbe..4b898b926 100644 --- a/common/src/main/java/com/alessiodp/parties/common/storage/sql/SQLUpgradeManager.java +++ b/common/src/main/java/com/alessiodp/parties/common/storage/sql/SQLUpgradeManager.java @@ -58,7 +58,7 @@ public static void checkUpgrades(SQLDispatcher dispatcher, Connection connection if (rs.next()) { String cmnt = rs.getString("table_comment"); if (!cmnt.isEmpty()) { - version = Integer.valueOf(cmnt.split(":")[1]); + version = Integer.parseInt(cmnt.split(":")[1]); if (version >= 3) { // Only needed from new databases @@ -169,6 +169,7 @@ private static void upgradeTableParties(ResultSet rs, int version, Connection co preStatement.setString(8, rs.getString("home")); preStatement.setBoolean(9, false); preStatement.setDouble(10, 0); + preStatement.setBoolean(11, true); preStatement.executeUpdate(); } } @@ -188,6 +189,7 @@ private static void upgradeTableParties(ResultSet rs, int version, Connection co preStatement.setString(8, rs.getString("home")); preStatement.setBoolean(9, false); // Set new pvp preStatement.setDouble(10, 0); // Set new experience + preStatement.setBoolean(11, true); preStatement.executeUpdate(); } } @@ -206,6 +208,26 @@ private static void upgradeTableParties(ResultSet rs, int version, Connection co preStatement.setString(8, rs.getString("home")); preStatement.setBoolean(9, rs.getBoolean("pvp")); // Changed pvp into protection preStatement.setDouble(10, rs.getDouble("experience")); + preStatement.setBoolean(11, true); + preStatement.executeUpdate(); + } + } + break; + case 5: + // Upgrading from 2.4 + while (rs.next()) { + try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_PARTY_INSERT_MYSQL))) { + preStatement.setString(1, rs.getString("name")); + preStatement.setString(2, rs.getString("leader")); + preStatement.setString(3, rs.getString("description")); + preStatement.setString(4, rs.getString("motd")); + preStatement.setString(5, rs.getString("color")); + preStatement.setInt(6, rs.getInt("kills")); + preStatement.setString(7, rs.getString("password")); + preStatement.setString(8, rs.getString("home")); + preStatement.setBoolean(9, rs.getBoolean("protection")); + preStatement.setDouble(10, rs.getDouble("experience")); + preStatement.setBoolean(11, true); // Set new follow preStatement.executeUpdate(); } } @@ -229,6 +251,7 @@ private static void upgradeTableParties(ResultSet rs, int version, Connection co preStatement.setString(8, rs.getString("home")); preStatement.setBoolean(9, false); // Set new pvp preStatement.setDouble(10, 0); // Set new experience + preStatement.setBoolean(11, true); preStatement.executeUpdate(); } } @@ -247,9 +270,30 @@ private static void upgradeTableParties(ResultSet rs, int version, Connection co preStatement.setString(8, rs.getString("home")); preStatement.setBoolean(9, rs.getBoolean("pvp")); // Changed pvp into protection preStatement.setDouble(10, rs.getDouble("experience")); + preStatement.setBoolean(11, true); + preStatement.executeUpdate(); + } + } + break; + case 3: + while (rs.next()) { + try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_PARTY_INSERT_SQLITE))) { + preStatement.setString(1, rs.getString("name")); + preStatement.setString(2, rs.getString("leader")); + preStatement.setString(3, rs.getString("description")); + preStatement.setString(4, rs.getString("motd")); + // Removed prefix & suffix + preStatement.setString(5, rs.getString("color")); + preStatement.setInt(6, rs.getInt("kills")); + preStatement.setString(7, rs.getString("password")); + preStatement.setString(8, rs.getString("home")); + preStatement.setBoolean(9, rs.getBoolean("protection")); + preStatement.setDouble(10, rs.getDouble("experience")); + preStatement.setBoolean(11, true); // Set new follow preStatement.executeUpdate(); } } + break; } } } @@ -305,6 +349,21 @@ private static void upgradeTablePlayers(ResultSet rs, int version, Connection co } } break; + case 5: + // Same table + while (rs.next()) { + try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_PLAYER_INSERT_MYSQL))) { + preStatement.setString(1, rs.getString("uuid")); + preStatement.setString(2, rs.getString("party")); + preStatement.setInt(3, rs.getInt("rank")); + preStatement.setString(4, rs.getString("name")); + preStatement.setInt(5, rs.getInt("timestamp")); + preStatement.setBoolean(6, rs.getBoolean("spy")); + preStatement.setBoolean(7, rs.getBoolean("mute")); + preStatement.executeUpdate(); + } + } + break; } } if (databaseType.isSQLite()) { @@ -326,6 +385,21 @@ private static void upgradeTablePlayers(ResultSet rs, int version, Connection co } } break; + case 3: + // Same table + while (rs.next()) { + try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_PLAYER_INSERT_SQLITE))) { + preStatement.setString(1, rs.getString("uuid")); + preStatement.setString(2, rs.getString("party")); + preStatement.setInt(3, rs.getInt("rank")); + preStatement.setString(4, rs.getString("name")); + preStatement.setInt(5, rs.getInt("timestamp")); + preStatement.setBoolean(6, rs.getBoolean("spy")); + preStatement.setBoolean(7, rs.getBoolean("mute")); + preStatement.executeUpdate(); + } + } + break; } } } @@ -351,6 +425,7 @@ private static void upgradeTableLog(ResultSet rs, int version, Connection connec case 2: case 3: case 4: + case 5: // Same table while (rs.next()) { try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_LOG_MIGRATE))) { @@ -369,6 +444,7 @@ private static void upgradeTableLog(ResultSet rs, int version, Connection connec switch (version) { case 1: case 2: + case 3: // Same table while (rs.next()) { try (PreparedStatement preStatement = connection.prepareStatement(SQLTable.formatQuery(Constants.QUERY_LOG_MIGRATE))) { diff --git a/common/src/main/java/com/alessiodp/parties/common/utils/DebugUtils.java b/common/src/main/java/com/alessiodp/parties/common/utils/DebugUtils.java index 4fb6f68fe..7bc8ad719 100644 --- a/common/src/main/java/com/alessiodp/parties/common/utils/DebugUtils.java +++ b/common/src/main/java/com/alessiodp/parties/common/utils/DebugUtils.java @@ -9,11 +9,11 @@ public class DebugUtils { public static void startDebugTask(PartiesPlugin plugin) { if (Constants.DEBUG_ENABLED) { // Debug task - plugin.getPartiesScheduler().runAsyncTaskTimer(() -> { + plugin.getPartiesScheduler().scheduleAsyncTaskTimer(() -> { int players = plugin.getPlayerManager().getListPartyPlayers().size(); String parties = plugin.getPartyManager().getListParties().keySet().toString(); debugLog("Entities = Players: " + Integer.toString(players) + " - Parties: " + parties); - }, 15); + }, 20L*15); } } diff --git a/common/src/main/java/com/alessiodp/parties/common/utils/PartiesUtils.java b/common/src/main/java/com/alessiodp/parties/common/utils/PartiesUtils.java index 68c031396..62b0844de 100644 --- a/common/src/main/java/com/alessiodp/parties/common/utils/PartiesUtils.java +++ b/common/src/main/java/com/alessiodp/parties/common/utils/PartiesUtils.java @@ -1,78 +1,61 @@ package com.alessiodp.parties.common.utils; +import com.alessiodp.parties.common.PartiesPlugin; +import com.alessiodp.parties.common.commands.utils.AbstractCommand; +import com.alessiodp.parties.common.commands.utils.CommandData; import com.alessiodp.parties.common.configuration.Constants; import com.alessiodp.parties.common.configuration.data.ConfigMain; import com.alessiodp.parties.common.configuration.data.ConfigParties; import com.alessiodp.parties.common.logging.LoggerManager; +import com.alessiodp.parties.common.user.User; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.regex.Matcher; import java.util.regex.Pattern; public class PartiesUtils { /* - * Censor utils + * Regex utils */ - public static boolean checkCensor(String phrase) { + + public static boolean checkCensor(String regex, String text, String regexError) { boolean ret = false; - if (ConfigMain.ADDITIONAL_CENSOR_ENABLE) { - for (String regex : ConfigMain.ADDITIONAL_CENSOR_REGEXES) { - try { - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(phrase); - - if (matcher.find()) { - ret = true; - break; - } - } catch (Exception ex) { - LoggerManager.printError(Constants.DEBUG_CENSOR_REGEXERROR); - ex.printStackTrace(); - } - } - - for (String cen : ConfigMain.ADDITIONAL_CENSOR_CONTAINS) { - // Contains - if (ret) - break; + if (!regex.isEmpty()) { + try { + Matcher matcher = Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(text); - if (!ConfigMain.ADDITIONAL_CENSOR_CASESENSITIVE) { - if (phrase.toLowerCase().contains(cen.toLowerCase())) - ret = true; - } else if (phrase.contains(cen)) - ret = true; - } - for (String cen : ConfigMain.ADDITIONAL_CENSOR_STARTSWITH) { - // Starts with - if (ret) - break; - - if (!ConfigMain.ADDITIONAL_CENSOR_CASESENSITIVE) { - if (phrase.toLowerCase().startsWith(cen.toLowerCase())) - ret = true; - } else if (phrase.startsWith(cen)) - ret = true; - } - for (String cen : ConfigMain.ADDITIONAL_CENSOR_ENDSWITH) { - // Ends with - if (ret) - break; - - if (!ConfigMain.ADDITIONAL_CENSOR_CASESENSITIVE) { - if (phrase.toLowerCase().endsWith(cen.toLowerCase())) - ret = true; - } else if (phrase.endsWith(cen)) + if (matcher.find()) { ret = true; + } + } catch (Exception ex) { + LoggerManager.printError(regexError); + ex.printStackTrace(); } } return ret; } + public static boolean checkAllowedCharacters(String regex, String text, String regexError) { + boolean ret = true; + try { + Matcher matcher = Pattern.compile(regex).matcher(text); + + ret = matcher.matches(); + } catch (Exception ex) { + LoggerManager.printError(regexError); + ex.printStackTrace(); + } + return ret; + } + /* - * Hashing + * Hash utils */ public static String hashText(String text) { String ret = ""; @@ -89,4 +72,76 @@ public static String hashText(String text) { } return ret; } + + /* + * Command utils + */ + public static void executeCommand(PartiesPlugin plugin, User sender, String mainCommand, AbstractCommand command, String[] args) { + CommandData cd = new CommandData(); + cd.setSender(sender); + cd.setCommandLabel(mainCommand); + cd.setArgs(args); + if (command.preRequisites(cd)) { + CompletableFuture.supplyAsync(() -> { + command.onCommand(cd); + return true; + }, plugin.getPartiesScheduler().getCommandsExecutor()) + .exceptionally(ex -> { + ex.printStackTrace(); + return false; + }); + } + } + + public static Boolean handleOnOffCommand(Boolean ret, String[] args) { + if (args.length > 1) { + if (args[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_ON)) + ret = true; + else if (args[1].equalsIgnoreCase(ConfigMain.COMMANDS_SUB_OFF)) + ret = false; + else + ret = null; + } else { + ret = !ret; + } + return ret; + } + + /* + * Tab completation parser + */ + public static List tabCompleteParser(List commands, String word) { + List ret = new ArrayList<>(); + for (String s : commands) { + if (s.toLowerCase().startsWith(word.toLowerCase())) { + ret.add(s); + } + } + return ret; + } + + public static List tabCompleteOnOff(String[] args) { + // args: on/off + List ret = new ArrayList<>(); + if (args.length == 2) { + ret.add(ConfigMain.COMMANDS_SUB_ON); + ret.add(ConfigMain.COMMANDS_SUB_OFF); + if (!args[1].isEmpty()) { + ret = PartiesUtils.tabCompleteParser(ret, args[1]); + } + } + return ret; + } + + public static List tabCompletePlayerList(PartiesPlugin plugin, String[] args, int index) { + // args: ... playerListAtIndex ... + List ret = new ArrayList<>(); + if (args.length == (index + 1)) { + for (User u : plugin.getOnlinePlayers()) { + ret.add(u.getName()); + } + ret = tabCompleteParser(ret, args[index]); + } + return ret; + } } diff --git a/common/src/main/resources/schemas/mysql.sql b/common/src/main/resources/schemas/mysql.sql index 3c14a2082..0621e3a0c 100644 --- a/common/src/main/resources/schemas/mysql.sql +++ b/common/src/main/resources/schemas/mysql.sql @@ -2,40 +2,41 @@ /*START_PARTIES*/ CREATE TABLE `{table_parties}` ( - `name` VARCHAR({varcharsize}) NOT NULL, - `leader` VARCHAR({varcharsize}) NOT NULL, + `name` VARCHAR({varcharsize}) NOT NULL, + `leader` VARCHAR({varcharsize}) NOT NULL, `description` VARCHAR({varcharsize}) DEFAULT '', - `motd` VARCHAR({varcharsize}) DEFAULT '', - `color` VARCHAR({varcharsize}) DEFAULT '', - `kills` INT DEFAULT 0, + `motd` VARCHAR({varcharsize}) DEFAULT '', + `color` VARCHAR({varcharsize}) DEFAULT '', + `kills` INT DEFAULT 0, `password` VARCHAR({varcharsize}) DEFAULT '', - `home` VARCHAR({varcharsize}) DEFAULT '', + `home` VARCHAR({varcharsize}) DEFAULT '', `protection` TINYINT(1) DEFAULT 0 NOT NULL, `experience` DOUBLE DEFAULT 0, + `follow` TINYINT(1) DEFAULT 1 NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET='{charset}'; /*END_PARTIES*/ /*START_PLAYERS*/ CREATE TABLE `{table_players}` ( - `uuid` VARCHAR({varcharsize}) NOT NULL, - `party` VARCHAR({varcharsize}) NOT NULL, - `rank` INT DEFAULT 0, - `name` VARCHAR({varcharsize}) DEFAULT '', + `uuid` VARCHAR({varcharsize}) NOT NULL, + `party` VARCHAR({varcharsize}) NOT NULL, + `rank` INT DEFAULT 0, + `name` VARCHAR({varcharsize}) DEFAULT '', `timestamp` INT, - `spy` TINYINT(1) DEFAULT 0 NOT NULL, - `mute` TINYINT(1) DEFAULT 0 NOT NULL, + `spy` TINYINT(1) DEFAULT 0 NOT NULL, + `mute` TINYINT(1) DEFAULT 0 NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET='{charset}'; /*END_PLAYERS*/ /*START_LOG*/ CREATE TABLE `{table_log}` ( - `id` INT NOT NULL AUTO_INCREMENT, - `date` DATETIME, - `level` TINYINT, + `id` INT NOT NULL AUTO_INCREMENT, + `date` DATETIME, + `level` TINYINT, `position` VARCHAR({varcharsize}), - `message` VARCHAR({varcharsize}), + `message` VARCHAR({varcharsize}), PRIMARY KEY (`id`)) DEFAULT CHARSET='{charset}'; /*END_LOG*/ diff --git a/common/src/main/resources/schemas/sqlite.sql b/common/src/main/resources/schemas/sqlite.sql index 2accd1bca..2f7c32946 100644 --- a/common/src/main/resources/schemas/sqlite.sql +++ b/common/src/main/resources/schemas/sqlite.sql @@ -11,7 +11,8 @@ CREATE TABLE '{table_parties}' ( 'password' VARCHAR({varcharsize}) DEFAULT '', 'home' VARCHAR({varcharsize}) DEFAULT '', 'protection' INTEGER DEFAULT 0 NOT NULL, - 'experience' REAL DEFAULT 0); + 'experience' REAL DEFAULT 0, + 'follow' INTEGER DEFAULT 1 NOT NULL); /*END_PARTIES*/ /*START_PLAYERS*/ diff --git a/images/helppages.jpg b/images/helppages.jpg deleted file mode 100644 index a09804811dd7aeec14f4fc9b724bee2f94a75659..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122166 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

ZOML=vF&bu*(|7v|E6o%NTS=@ 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 Y3u{o1g0)HN?6-Al5%5s|0Es{U*<4f=00000 diff --git a/output/pom.xml b/output/pom.xml index b9456f65a..23e9f9a39 100644 --- a/output/pom.xml +++ b/output/pom.xml @@ -5,7 +5,7 @@ Parties com.alessiodp.parties - 2.4.7 + 2.5.0 4.0.0 diff --git a/pom.xml b/pom.xml index afdd8c866..39bd996b1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.alessiodp.parties Parties - 2.4.7 + 2.5.0 pom Parties