From 37f08be28b0f1254785b5c3fc24f8eefa9e06f97 Mon Sep 17 00:00:00 2001
From: Brandon <46827438+disclearing@users.noreply.github.com>
Date: Wed, 3 May 2023 15:21:03 +0100
Subject: [PATCH] ggg
---
.gitignore | 2 +
Bridge.iml | 104 ++++
Jenkinsfile | 18 +
README.md | 1 +
dependency-reduced-pom.xml | 160 ++++++
pom.xml | 257 +++++++++
.../java/rip/bridge/bridge/BridgeGlobal.java | 327 ++++++++++++
.../java/rip/bridge/bridge/bukkit/Bridge.java | 65 +++
.../rip/bridge/bridge/bukkit/BukkitAPI.java | 488 ++++++++++++++++++
.../bridge/bukkit/auth/TotpMapCreator.java | 22 +
.../bridge/bukkit/auth/TotpMapRenderer.java | 29 ++
.../auth/prompt/InitialDisclaimerPrompt.java | 26 +
.../bukkit/auth/prompt/ScanMapPrompt.java | 124 +++++
.../bridge/bukkit/commands/AlertCommand.java | 20 +
.../bridge/bukkit/commands/DemoCommand.java | 19 +
.../bukkit/commands/EndScreenCommand.java | 19 +
.../bukkit/commands/ExecuteCommands.java | 72 +++
.../bridge/bukkit/commands/FindCommand.java | 29 ++
.../bridge/bukkit/commands/ListCommand.java | 70 +++
.../bukkit/commands/PacketLoggerCommands.java | 62 +++
.../bridge/bukkit/commands/PermsCommand.java | 45 ++
.../bridge/bukkit/commands/SeenCommand.java | 34 ++
.../commands/ThreadProfilerCommands.java | 66 +++
.../bukkit/commands/TimelineCommand.java | 98 ++++
.../bukkit/commands/auth/AuthCommand.java | 49 ++
.../commands/auth/ForceAuthCommand.java | 20 +
.../bukkit/commands/auth/Setup2faCommand.java | 24 +
.../commands/disguise/DisguiseCommand.java | 52 ++
.../commands/disguise/RealNameCommand.java | 52 ++
.../bukkit/commands/disguise/SkinCommand.java | 119 +++++
.../bukkit/commands/disguise/TagCommand.java | 67 +++
.../commands/disguise/UnDisguiseCommand.java | 23 +
.../commands/disguise/UnTagCommand.java | 23 +
.../DisguiseProfileCreateCommand.java | 38 ++
.../DisguiseProfileDeleteCommand.java | 22 +
.../DisguiseProfileDisguiseCommand.java | 89 ++++
.../DisguiseProfileInfoCommand.java | 21 +
.../DisguiseProfileListCommand.java | 52 ++
.../DisguiseProfileSetDisplayNameCommand.java | 21 +
.../DisguiseProfileUnDisguiseCommand.java | 28 +
.../disguise/menu/DisguiseRankMenu.java | 99 ++++
.../disguise/menu/DisguiseSkinMenu.java | 464 +++++++++++++++++
.../commands/filter/FilterCreateCommand.java | 27 +
.../filter/FilterCreateMuteCommand.java | 30 ++
.../commands/filter/FilterDeleteCommand.java | 20 +
.../commands/filter/FilterListCommand.java | 40 ++
.../commands/filter/FilterTestCommand.java | 25 +
.../commands/filter/ToggleFilterCommand.java | 37 ++
.../commands/grant/ClearGrantsCommand.java | 27 +
.../bukkit/commands/grant/GrantCommand.java | 15 +
.../bukkit/commands/grant/GrantsCommand.java | 43 ++
.../bukkit/commands/grant/OGrantCommand.java | 30 ++
.../grant/events/GrantCreateEvent.java | 17 +
.../grant/events/GrantRemoveEvent.java | 17 +
.../grant/events/GrantUpdateEvent.java | 17 +
.../grant/menu/grant/GlobalButton.java | 43 ++
.../grant/menu/grant/GrantButton.java | 84 +++
.../commands/grant/menu/grant/RankButton.java | 146 ++++++
.../commands/grant/menu/grant/RanksMenu.java | 65 +++
.../grant/menu/grant/ScopeButton.java | 53 ++
.../commands/grant/menu/grant/ScopesMenu.java | 78 +++
.../grant/menu/grants/GrantsButton.java | 129 +++++
.../grant/menu/grants/GrantsMenu.java | 68 +++
.../commands/punishment/AltsCommand.java | 47 ++
.../punishment/CheckPunishmentsCommand.java | 25 +
.../CheckStaffPunishmentsCommand.java | 15 +
.../punishment/ClearPunishmentsCommand.java | 35 ++
.../ClearStaffPunishmentsCommand.java | 28 +
.../punishment/create/BanCommand.java | 41 ++
.../punishment/create/BanIPCommand.java | 41 ++
.../punishment/create/BlacklistCommand.java | 45 ++
.../punishment/create/KickCommand.java | 36 ++
.../punishment/create/MuteCommand.java | 45 ++
.../punishment/create/MuteIPCommand.java | 47 ++
.../punishment/create/PermMuteCommand.java | 41 ++
.../punishment/create/PermMuteIPCommand.java | 41 ++
.../punishment/create/TempBanCommand.java | 46 ++
.../punishment/create/TempBanIPCommand.java | 46 ++
.../punishment/create/WarnCommand.java | 36 ++
.../punishment/menu/MainPunishmentMenu.java | 98 ++++
.../commands/punishment/menu/ProofMenu.java | 81 +++
.../punishment/menu/PunishmentMenu.java | 72 +++
.../menu/button/ProofAddButton.java | 88 ++++
.../punishment/menu/button/ProofButton.java | 113 ++++
.../menu/button/PunishmentButton.java | 98 ++++
.../MainStaffPunishmentListMenu.java | 97 ++++
.../staffhistory/StaffPunishmentButton.java | 87 ++++
.../staffhistory/StaffPunishmentListMenu.java | 74 +++
.../punishment/remove/UnBanCommand.java | 43 ++
.../punishment/remove/UnBanIPCommand.java | 39 ++
.../punishment/remove/UnBlacklistCommand.java | 39 ++
.../punishment/remove/UnMuteCommand.java | 44 ++
.../punishment/remove/UnWarnCommand.java | 40 ++
.../commands/rank/RankCreateCommand.java | 27 +
.../commands/rank/RankDeleteCommand.java | 22 +
.../bukkit/commands/rank/RankInfoCommand.java | 36 ++
.../commands/rank/RankInheritCommand.java | 22 +
.../bukkit/commands/rank/RankListCommand.java | 57 ++
.../commands/rank/RankManageCommand.java | 23 +
.../commands/rank/RankPermissionCommand.java | 22 +
.../commands/rank/RankRenameCommand.java | 23 +
.../commands/rank/RankSetBuilderCommand.java | 22 +
.../commands/rank/RankSetColorCommand.java | 23 +
.../commands/rank/RankSetDefaultCommand.java | 22 +
.../rank/RankSetDisplayNameCommand.java | 22 +
.../rank/RankSetGrantableCommand.java | 22 +
.../commands/rank/RankSetHiddenCommand.java | 22 +
.../commands/rank/RankSetMediaCommand.java | 22 +
.../commands/rank/RankSetPrefixCommand.java | 23 +
.../commands/rank/RankSetPriorityCommand.java | 22 +
.../commands/rank/RankSetStaffCommand.java | 22 +
.../commands/rank/RankSetSuffixCommand.java | 23 +
.../commands/rank/menu/PermissionsMenu.java | 172 ++++++
.../bukkit/commands/rank/menu/PlayerMenu.java | 85 +++
.../bukkit/commands/rank/menu/RankMenu.java | 142 +++++
.../rank/menu/buttons/PermissionButton.java | 57 ++
.../rank/menu/buttons/PlayerButton.java | 69 +++
.../bukkit/commands/server/BanLobby.java | 18 +
.../commands/server/DeploymentCommand.java | 14 +
.../commands/server/NetworkStatsCommand.java | 21 +
.../commands/server/ServersCommand.java | 19 +
.../commands/server/ShutdownCommand.java | 22 +
.../server/group/GroupInfoCommand.java | 24 +
.../server/group/GroupListCommand.java | 21 +
.../menu/deployment/CompleteButton.java | 67 +++
.../menu/deployment/DeploymentMenu.java | 83 +++
.../server/menu/deployment/PluginButton.java | 56 ++
.../server/menu/groups/GroupMenu.java | 16 +
.../menu/server/ExtraInformationMenu.java | 55 ++
.../server/menu/server/ServerActionMenu.java | 76 +++
.../server/menu/server/ServerMenu.java | 39 ++
.../menu/server/buttons/DataButton.java | 32 ++
.../menu/server/buttons/ServerButton.java | 82 +++
.../server/serverinfo/ServerInfoCommand.java | 36 ++
.../serverinfo/ServerInfoListCommand.java | 21 +
.../updater/UpdaterDisableCommand.java | 23 +
.../updater/UpdaterEnableCommand.java | 23 +
.../commands/updater/UpdaterInfoCommand.java | 28 +
.../commands/updater/UpdaterListCommand.java | 36 ++
.../commands/updater/UpdaterLoadCommand.java | 14 +
.../updater/UpdaterReloadCommand.java | 23 +
.../updater/UpdaterUnloadCommand.java | 15 +
.../updater/UpdaterUpdateCommand.java | 49 ++
.../updater/group/UpdaterGroupAddCommand.java | 27 +
.../group/UpdaterGroupRemoveCommand.java | 28 +
.../commands/updater/menu/CompleteButton.java | 60 +++
.../commands/updater/menu/PluginButton.java | 54 ++
.../commands/updater/menu/UpdaterMenu.java | 65 +++
.../commands/user/UserDeleteCommand.java | 25 +
.../bukkit/commands/user/UserInfoCommand.java | 43 ++
.../commands/user/UserPermissionCommand.java | 19 +
.../commands/user/UserSetColorCommand.java | 19 +
.../commands/user/UserSetPrefixCommand.java | 19 +
.../commands/user/UserSetSuffixCommand.java | 19 +
.../bukkit/listener/BridgeListener.java | 244 +++++++++
.../bukkit/listener/FreezeListener.java | 129 +++++
.../bukkit/listener/GeneralListener.java | 284 ++++++++++
.../bridge/bukkit/parameters/AlertPacket.java | 23 +
.../bukkit/parameters/AnnouncePacket.java | 21 +
.../bukkit/parameters/AnnouncePackets.java | 39 ++
.../parameters/BridgeNameTagProvider.java | 18 +
.../bukkit/parameters/BridgeUUIDCache.java | 29 ++
.../parameters/BukkitStatusImplementer.java | 65 +++
.../bukkit/parameters/DisguiseParameter.java | 44 ++
.../parameters/ExecuteCommandPacket.java | 16 +
.../parameters/FoxtrotRevivePacket.java | 27 +
.../bukkit/parameters/PluginParameter.java | 30 ++
.../bukkit/parameters/ProfileParamater.java | 84 +++
.../bukkit/parameters/RankParamater.java | 47 ++
.../bukkit/parameters/WhitelistPacket.java | 38 ++
.../packets/filter/FilterCreatePacket.java | 20 +
.../packets/filter/FilterDeletePacket.java | 23 +
.../packets/filter/FilterViolationPacket.java | 32 ++
.../param/filter/FilterActionParameter.java | 38 ++
.../param/filter/FilterParameter.java | 35 ++
.../param/filter/FilterTypeParameter.java | 38 ++
.../bridge/bridge/bukkit/util/BaseEvent.java | 26 +
.../bridge/bukkit/util/BukkitUtils.java | 92 ++++
.../rip/bridge/bridge/bukkit/util/Chat.java | 43 ++
.../bridge/bukkit/util/ItemStackBuilder.java | 25 +
.../bridge/bukkit/util/PaginatedResult.java | 46 ++
.../bridge/bridge/bukkit/util/PluginUtil.java | 375 ++++++++++++++
.../bridge/bukkit/util/ReflectUtil.java | 51 ++
.../bridge/bridge/bukkit/util/Reflection.java | 324 ++++++++++++
.../bridge/bridge/bukkit/util/TPSUtil.java | 44 ++
.../bridge/bridge/bungee/BridgeBungee.java | 77 +++
.../bungee/implement/BungeeImplementer.java | 56 ++
.../bungee/listener/BridgeBungeeListener.java | 59 +++
.../listener/GeneralBungeeListener.java | 20 +
.../rip/bridge/bridge/global/GlobalAPI.java | 171 ++++++
.../global/deployment/DeploymentHandler.java | 154 ++++++
.../global/disguise/DisguiseManager.java | 400 ++++++++++++++
.../global/disguise/DisguisePlayer.java | 21 +
.../global/disguise/DisguisePlayerSkin.java | 55 ++
.../global/disguise/DisguiseProfile.java | 16 +
.../disguise/runnable/DisguiseRunnable.java | 156 ++++++
.../bridge/bridge/global/filter/Filter.java | 64 +++
.../bridge/global/filter/FilterAction.java | 8 +
.../bridge/global/filter/FilterType.java | 8 +
.../rip/bridge/bridge/global/grant/Grant.java | 179 +++++++
.../bridge/global/handlers/FilterHandler.java | 71 +++
.../bridge/global/handlers/MongoHandler.java | 448 ++++++++++++++++
.../global/handlers/PacketLogHandler.java | 34 ++
.../bridge/global/handlers/PrefixHandler.java | 77 +++
.../global/handlers/ProfileHandler.java | 127 +++++
.../bridge/global/handlers/RankHandler.java | 105 ++++
.../bridge/bridge/global/packet/Packet.java | 6 +
.../bridge/global/packet/PacketHandler.java | 74 +++
.../bridge/global/packet/PacketPubSub.java | 29 ++
.../global/packet/types/DisguisePacket.java | 20 +
.../packet/types/GrantCreatePacket.java | 32 ++
.../packet/types/NetworkBroadcastPacket.java | 22 +
.../global/packet/types/PunishmentPacket.java | 21 +
.../global/packet/types/RankCreatePacket.java | 23 +
.../global/packet/types/RankDeletePacket.java | 30 ++
.../global/packet/types/RankUpdatePacket.java | 29 ++
.../packet/types/ServerCommandPacket.java | 24 +
.../packet/types/ServerDeployPacket.java | 40 ++
.../types/ServerGroupCommandPacket.java | 23 +
.../packet/types/ServerShutdownPacket.java | 27 +
.../bridge/global/packetlogger/PacketLog.java | 19 +
.../global/packets/GrantCreatePacket.java | 71 +++
.../global/packets/GrantRemovePacket.java | 71 +++
.../global/packets/PunishmentPacket.java | 48 ++
.../global/packets/RankCreatePacket.java | 63 +++
.../global/packets/RankDeletePacket.java | 63 +++
.../global/packets/RankUpdatePacket.java | 63 +++
.../global/packets/ServerDeployPacket.java | 47 ++
.../bridge/bridge/global/prefix/Prefix.java | 30 ++
.../bridge/bridge/global/profile/Profile.java | 283 ++++++++++
.../profile/ProfileWeightComparator.java | 12 +
.../bridge/global/punishment/Evidence.java | 12 +
.../bridge/global/punishment/Punishment.java | 147 ++++++
.../global/punishment/PunishmentType.java | 19 +
.../rip/bridge/bridge/global/ranks/Rank.java | 205 ++++++++
.../bridge/global/status/BridgeServer.java | 88 ++++
.../bridge/global/status/ServerHandler.java | 80 +++
.../bridge/global/status/StatusProvider.java | 85 +++
.../status/start/ServerStartThread.java | 26 +
.../status/threads/StatusFetchThread.java | 70 +++
.../status/threads/StatusUpdateThread.java | 71 +++
.../bridge/global/updater/UpdateStatus.java | 18 +
.../bridge/global/updater/UpdaterManager.java | 155 ++++++
.../bridge/bridge/global/util/Callback.java | 3 +
.../rip/bridge/bridge/global/util/Color.java | 10 +
.../bridge/global/util/EncryptionHandler.java | 100 ++++
.../bridge/bridge/global/util/JsonChain.java | 44 ++
.../bridge/global/util/MojangUtils.java | 78 +++
.../rip/bridge/bridge/global/util/Msg.java | 11 +
.../bridge/bridge/global/util/OtherUtils.java | 15 +
.../bridge/bridge/global/util/SystemType.java | 9 +
.../rip/bridge/bridge/global/util/Tasks.java | 50 ++
.../bridge/bridge/global/util/TimeUtil.java | 180 +++++++
.../global/util/mojang/GameProfileUtil.java | 135 +++++
.../global/util/mojang/UUIDFetcher.java | 102 ++++
src/main/resources/bungee.yml | 4 +
src/main/resources/config.yml | 32 ++
src/main/resources/plugin.yml | 5 +
258 files changed, 15932 insertions(+)
create mode 100644 .gitignore
create mode 100644 Bridge.iml
create mode 100644 Jenkinsfile
create mode 100644 README.md
create mode 100644 dependency-reduced-pom.xml
create mode 100644 pom.xml
create mode 100644 src/main/java/rip/bridge/bridge/BridgeGlobal.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/Bridge.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/Chat.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/ReflectUtil.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/Reflection.java
create mode 100644 src/main/java/rip/bridge/bridge/bukkit/util/TPSUtil.java
create mode 100644 src/main/java/rip/bridge/bridge/bungee/BridgeBungee.java
create mode 100644 src/main/java/rip/bridge/bridge/bungee/implement/BungeeImplementer.java
create mode 100644 src/main/java/rip/bridge/bridge/bungee/listener/BridgeBungeeListener.java
create mode 100644 src/main/java/rip/bridge/bridge/bungee/listener/GeneralBungeeListener.java
create mode 100644 src/main/java/rip/bridge/bridge/global/GlobalAPI.java
create mode 100644 src/main/java/rip/bridge/bridge/global/deployment/DeploymentHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/disguise/DisguiseManager.java
create mode 100644 src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayer.java
create mode 100644 src/main/java/rip/bridge/bridge/global/disguise/DisguisePlayerSkin.java
create mode 100644 src/main/java/rip/bridge/bridge/global/disguise/DisguiseProfile.java
create mode 100644 src/main/java/rip/bridge/bridge/global/disguise/runnable/DisguiseRunnable.java
create mode 100644 src/main/java/rip/bridge/bridge/global/filter/Filter.java
create mode 100644 src/main/java/rip/bridge/bridge/global/filter/FilterAction.java
create mode 100644 src/main/java/rip/bridge/bridge/global/filter/FilterType.java
create mode 100644 src/main/java/rip/bridge/bridge/global/grant/Grant.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/FilterHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/MongoHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/PacketLogHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/PrefixHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/ProfileHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/handlers/RankHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/Packet.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/PacketHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/PacketPubSub.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/DisguisePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/GrantCreatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/NetworkBroadcastPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/PunishmentPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/RankCreatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/RankDeletePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/RankUpdatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/ServerCommandPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/ServerDeployPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/ServerGroupCommandPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packet/types/ServerShutdownPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packetlogger/PacketLog.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/GrantCreatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/GrantRemovePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/PunishmentPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/RankCreatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/RankDeletePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/RankUpdatePacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/packets/ServerDeployPacket.java
create mode 100644 src/main/java/rip/bridge/bridge/global/prefix/Prefix.java
create mode 100644 src/main/java/rip/bridge/bridge/global/profile/Profile.java
create mode 100644 src/main/java/rip/bridge/bridge/global/profile/ProfileWeightComparator.java
create mode 100644 src/main/java/rip/bridge/bridge/global/punishment/Evidence.java
create mode 100644 src/main/java/rip/bridge/bridge/global/punishment/Punishment.java
create mode 100644 src/main/java/rip/bridge/bridge/global/punishment/PunishmentType.java
create mode 100644 src/main/java/rip/bridge/bridge/global/ranks/Rank.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/BridgeServer.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/ServerHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/StatusProvider.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/start/ServerStartThread.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/threads/StatusFetchThread.java
create mode 100644 src/main/java/rip/bridge/bridge/global/status/threads/StatusUpdateThread.java
create mode 100644 src/main/java/rip/bridge/bridge/global/updater/UpdateStatus.java
create mode 100644 src/main/java/rip/bridge/bridge/global/updater/UpdaterManager.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/Callback.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/Color.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/EncryptionHandler.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/JsonChain.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/MojangUtils.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/Msg.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/OtherUtils.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/SystemType.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/Tasks.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/TimeUtil.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/mojang/GameProfileUtil.java
create mode 100644 src/main/java/rip/bridge/bridge/global/util/mojang/UUIDFetcher.java
create mode 100644 src/main/resources/bungee.yml
create mode 100644 src/main/resources/config.yml
create mode 100644 src/main/resources/plugin.yml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..744289d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Project exclude paths
+/target/
\ No newline at end of file
diff --git a/Bridge.iml b/Bridge.iml
new file mode 100644
index 0000000..8924c7a
--- /dev/null
+++ b/Bridge.iml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+ BUNGEECORD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..7e73f6a
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,18 @@
+node {
+ stage('Clone') {
+ checkout scm
+ }
+
+ stage('Build') {
+ sh "mvn clean install -U"
+ }
+
+ stage('Archive') {
+ archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
+ }
+
+ stage('Uploading to Nexus') {
+ pom = readMavenPom file: 'pom.xml'
+ nexusPublisher nexusInstanceId: 'prnex', nexusRepositoryId: 'bridge', packages: [[$class: 'MavenPackage', mavenAssetList: [[classifier: '', extension: 'jar', filePath: "target/${pom.name}.jar"]], mavenCoordinate: [artifactId: pom.artifactId, groupId: 'rip.bridge', packaging: 'jar', version: pom.version]]]
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8e26ec4
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+"# Bridge"
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
new file mode 100644
index 0000000..15ac3d4
--- /dev/null
+++ b/dependency-reduced-pom.xml
@@ -0,0 +1,160 @@
+
+
+ 4.0.0
+ rip.bridge
+ Bridge
+ Bridge
+ 1.0
+
+
+
+ true
+ src/main/resources
+
+ plugin.yml
+
+
+
+ src/main/resources
+
+ plugin.yml
+
+
+
+ ${project.name}
+
+
+ net.md-5
+ scriptus
+ 0.2
+
+
+ initialize
+
+ describe
+
+
+ %s
+ bridge.desc
+
+
+
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+ java-compile
+ compile
+
+ compile
+
+
+
+ java-test-compile
+ test-compile
+
+ testCompile
+
+
+
+
+
+ 1.8
+
+
+ org.projectlombok
+ lombok
+ 1.16.16
+
+
+
+
+
+ maven-shade-plugin
+ 2.4.3
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+ vault-repo
+ http://nexus.hc.to/content/repositories/pub_releases
+
+
+ lunarclient-public
+ https://maven.moonsworth.com/repository/lunarclient-public/
+
+
+ zeroturnaround-repo
+ https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases/
+
+
+ depends
+ redacted
+
+
+ bridge
+ redacted
+
+
+
+
+ rip.bridge
+ mspigot-server
+ 1.7.10-R0.1-SNAPSHOT
+ provided
+
+
+ rip.bridge
+ qLib
+ 1.0
+ provided
+
+
+ org.projectlombok
+ lombok
+ 1.16.16
+ provided
+
+
+ net.md_5.bungee
+ bungee
+ 1.7.10-R0.1-SNAPSHOT
+ system
+ ${project.basedir}/lib/BungeeCord.jar
+
+
+ com.comphenix.protocol
+ ProtocolLib-v1_7_R4
+ 3.7.0-BETA
+ system
+ ${project.basedir}/lib/ProtocolLib-v1_7_R4-3.7.0-BETA.jar
+
+
+
+ UTF-8
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9350b93
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,257 @@
+
+ 4.0.0
+ rip.bridge
+ Bridge
+ Bridge
+ ${git.commit.id.abbrev}
+
+
+ UTF-8
+
+
+
+ ${project.name}
+ src/main/java
+
+
+ pl.project13.maven
+ git-commit-id-plugin
+ 4.0.0
+
+
+ get-the-git-infos
+
+ revision
+
+ initialize
+
+
+
+ true
+ ${project.build.outputDirectory}/git.properties
+
+
+ ^git.build.(time|version)$
+ ^git.commit.id.(abbrev|full)$
+
+ full
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+
+
+ default-compile
+ none
+
+
+
+ default-testCompile
+ none
+
+
+ java-compile
+ compile
+
+ compile
+
+
+
+ java-test-compile
+ test-compile
+
+ testCompile
+
+
+
+
+
+ 1.8
+
+
+ org.projectlombok
+ lombok
+ 1.16.16
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.6
+
+
+ make-assembly
+ package
+
+ single
+
+
+ false
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ sonatype-snapshots
+ Sonatype Snapshots
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+ vault-repo
+ http://nexus.hc.to/content/repositories/pub_releases
+
+
+ lunarclient-public
+ https://maven.moonsworth.com/repository/lunarclient-public/
+
+
+ zeroturnaround-repo
+ https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases/
+
+
+ depends
+ redacted
+ default
+
+
+
+ bridge
+ redacted
+ default
+
+
+
+
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+ compile
+
+
+
+ com.google.auth
+ google-auth-library-oauth2-http
+ 0.25.3
+
+
+
+
+ net.md_5.bungee
+ bungee
+ 1.7.10-R0.1-SNAPSHOT
+ system
+ ${project.basedir}/lib/BungeeCord.jar
+
+
+
+
+ rip.bridge
+ mspigot-server
+ 1.7.10-R0.1-SNAPSHOT
+ provided
+
+
+
+
+
+ rip.bridge
+ qLib
+ LATEST
+ provided
+
+
+
+ javax.mail
+ mail
+ 1.4
+
+
+
+ commons-validator
+ commons-validator
+ 1.7
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.8.1
+ compile
+
+
+
+ redis.clients
+ jedis
+ 2.10.2
+ compile
+
+
+
+ org.mongodb
+ mongo-java-driver
+ 3.10.2
+ compile
+
+
+
+ org.projectlombok
+ lombok
+ 1.16.16
+ provided
+
+
+
+ commons-configuration
+ commons-configuration
+ 1.10
+
+
+
+ com.comphenix.protocol
+ ProtocolLib-v1_7_R4
+ 3.7.0-BETA
+ system
+ ${project.basedir}/lib/ProtocolLib-v1_7_R4-3.7.0-BETA.jar
+
+
+ jakarta.validation
+ jakarta.validation-api
+ 2.0.1
+ compile
+
+
+ com.warrenstrange
+ googleauth
+ 1.4.0
+
+
+
+
diff --git a/src/main/java/rip/bridge/bridge/BridgeGlobal.java b/src/main/java/rip/bridge/bridge/BridgeGlobal.java
new file mode 100644
index 0000000..0f2dcf5
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/BridgeGlobal.java
@@ -0,0 +1,327 @@
+package rip.bridge.bridge;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.listener.GeneralListener;
+import rip.bridge.bridge.bungee.BridgeBungee;
+import rip.bridge.bridge.bungee.listener.GeneralBungeeListener;
+import rip.bridge.bridge.global.disguise.DisguiseManager;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.handlers.PrefixHandler;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.bridge.global.status.ServerHandler;
+import rip.bridge.bridge.global.status.threads.StatusUpdateThread;
+import rip.bridge.bridge.global.updater.UpdaterManager;
+import rip.bridge.bridge.global.util.SystemType;
+import lombok.Getter;
+import lombok.Setter;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+import rip.bridge.bridge.global.handlers.*;
+
+import java.util.*;
+
+public class BridgeGlobal {
+
+ @Getter @Setter public static SystemType systemType = SystemType.UNKNOWN;
+
+ @Getter private static boolean mongoAuth, redisAuth, allowBannedJoins;
+
+ @Getter private static int mongoPort, redisPort, redisDB;
+ @Getter private static String mongoHost, mongoUsername, mongoPassword, mongoDatabase, redisHost, redisPassword, redisChannel, screenName, screenPath, serverName, serverDisplayName, serverWebsite, pluginUpdateDir ="%user_home%/Bridge/updater", groupName = "N/A";
+ private static List updaterGroups;
+ private static String serverDeploymentDir;
+ private static String serverTemplateDir;
+ private static boolean handleServerDeployment;
+ @Getter private static long startTime = -1L;
+ @Getter private static MongoHandler mongoHandler;
+ @Getter private static RankHandler rankHandler;
+ @Getter private static PacketLogHandler packetLogHandler;
+ @Getter private static PrefixHandler prefixHandler;
+ @Getter private static ProfileHandler profileHandler;
+ @Getter private static UpdaterManager updaterManager;
+ @Getter private static FilterHandler filterHandler;
+ @Getter private static ServerHandler serverHandler;
+ @Getter private static JedisPool jedisPool;
+ @Getter private static JsonParser parser = new JsonParser();
+ @Getter private static DisguiseManager disguiseManager;
+
+ @Getter @Setter private static boolean shutdown;
+
+ public BridgeGlobal() {
+ this("", "", "", "", 27017, false, "", "", "", 0, 6379, false, true);
+ }
+
+ public BridgeGlobal(String mongoHost, String mongoUsername, String mongoPassword, String mongoDatabase, int mongoPort, boolean mongoAuth, String redisHost, String redisPassword, String redisChannelKek, int redisDB, int redisPort, boolean redisAuth, boolean getFromConfig) {
+ this(mongoHost, mongoUsername, mongoPassword, mongoDatabase, mongoPort, mongoAuth, redisHost, redisPassword, redisChannelKek, redisDB, redisPort, redisAuth, getFromConfig, null);
+ }
+
+ public BridgeGlobal(String mongoHost, String mongoUsername, String mongoPassword, String mongoDatabase, int mongoPort, boolean mongoAuth, String redisHost, String redisPassword, String redisChannelKek, int redisDB, int redisPort, boolean redisAuth, boolean getFromConfig, String customServerName) {
+ setSystemType(currentSystemType());
+ sendLog("We have detected that Bridge is running on System Type: " + getSystemType().name());
+
+ if (customServerName != null)
+ serverName = customServerName;
+
+ if(getFromConfig) {
+ setupConfigValues();
+ }else {
+ BridgeGlobal.mongoAuth = mongoAuth;
+ BridgeGlobal.mongoPort = mongoPort;
+ BridgeGlobal.mongoHost = mongoHost;
+ BridgeGlobal.mongoUsername = mongoUsername;
+ BridgeGlobal.mongoPassword = mongoPassword;
+ BridgeGlobal.mongoDatabase = mongoDatabase;
+ BridgeGlobal.redisAuth = redisAuth;
+ BridgeGlobal.redisHost = redisHost;
+ BridgeGlobal.redisPort = redisPort;
+ BridgeGlobal.redisPassword = redisPassword;
+ BridgeGlobal.redisChannel = redisChannelKek;
+ BridgeGlobal.redisDB = redisDB;
+ }
+ sendLog("Loading Mongo backend...");
+ mongoHandler = new MongoHandler();
+
+ sendLog("Loading Ranks");
+ rankHandler = new RankHandler();
+ rankHandler.init();
+
+ profileHandler = new ProfileHandler();
+ profileHandler.init();
+ sendLog("Successfully loaded the Profile Handler");
+
+ prefixHandler = new PrefixHandler();
+ prefixHandler.init();
+ sendLog("Successfully loaded the Prefix Handler");
+
+ packetLogHandler = new PacketLogHandler();
+ sendLog("Successfully loaded the PacketLog Handler");
+
+ filterHandler = new FilterHandler();
+ filterHandler.init();
+ sendLog("Successfully loaded the Filter Handler");
+
+ jedisPool = new JedisPool(new JedisPoolConfig(), BridgeGlobal.getRedisHost(), BridgeGlobal.getRedisPort(), 0, (BridgeGlobal.isRedisAuth() ? BridgeGlobal.getRedisPassword() : null), BridgeGlobal.getRedisDB());
+ PacketHandler.init(jedisPool, redisChannel);
+
+// sendLog("Setting up status handler");
+// StatusHandler.init();
+
+ serverHandler = new ServerHandler();
+ serverHandler.init();
+ sendLog("Successfully setup the Server Handler");
+
+
+ if(pluginUpdateDir != null && !pluginUpdateDir.isEmpty()) {
+ sendLog("Setting up the update handler");
+ updaterManager = new UpdaterManager();
+ }
+ startTime = System.currentTimeMillis();
+ sendLog("Completed Bridge Backend - loaded " + getSystemType() + " system type.");
+ }
+
+ public static void loadDisguise(boolean bungee) {
+ disguiseManager = new DisguiseManager(bungee);
+ sendLog("Successfully loaded the Disguise Handler");
+ }
+
+ private void setupConfigValues() {
+ mongoAuth = Boolean.parseBoolean(getFromConfig("mongo.auth.enabled"));
+ mongoPort = Integer.parseInt(getFromConfig("mongo.port"));
+ mongoHost = getFromConfig("mongo.host");
+ mongoUsername = getFromConfig("mongo.auth.username");
+ mongoPassword = getFromConfig("mongo.auth.password");
+ mongoDatabase = getFromConfig("mongo.database");
+
+ redisAuth = !getFromConfig("redis.password").equals("");
+ redisHost = getFromConfig("redis.host");
+ redisPort = Integer.parseInt(getFromConfig("redis.port"));
+ redisPassword = getFromConfig("redis.password");
+ redisChannel = getFromConfig("redis.channel");
+ redisDB = Integer.parseInt(getFromConfig("redis.db"));
+ screenName = getFromConfig("screenName");
+ screenPath = getFromConfig("screenPath");
+ serverName = getFromConfig("serverName");
+ allowBannedJoins = Boolean.parseBoolean(getFromConfig("AllowBannedJoins"));
+ serverDisplayName = getFromConfig("serverDisplayName");
+ serverWebsite = getFromConfig("serverWebsite");
+ pluginUpdateDir = getFromConfig("pluginUpdateDirectory");
+ groupName = getFromConfig("serverGroup");
+ handleServerDeployment = Boolean.parseBoolean(BridgeGlobal.getFromConfig("handleServerDeployment"));
+ serverDeploymentDir = BridgeGlobal.getFromConfig("serverDeploymentDirectory");
+ serverTemplateDir = BridgeGlobal.getFromConfig("serverTemplateDirectory");
+ if(getSystemType() == SystemType.BUKKIT) updaterGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups");
+ }
+
+ public static void shutdown() {
+ shutdown = true;
+ StatusUpdateThread.saveShutdown();
+ getProfileHandler().saveDisable();
+ getRankHandler().saveDisable();
+ getMongoHandler().getMongoClient().close();
+ getJedisPool().close();
+ }
+
+ private static SystemType currentSystemType() {
+ try {
+ Class.forName("net.md_5.bungee.BungeeCord");
+ return SystemType.BUNGEE;
+ } catch (ClassNotFoundException ignored) {}
+ try {
+ Class.forName("org.bukkit.Bukkit");
+ return SystemType.BUKKIT;
+ } catch (ClassNotFoundException ignored) {}
+ return SystemType.UNKNOWN;
+ }
+
+ public static String getSystemName() {
+ switch (getSystemType()) {
+ case BUNGEE:
+ case BUKKIT: {
+ return serverName;
+ }
+ default: {
+ if (serverName != null && !serverName.isEmpty())
+ return serverName;
+
+ return "Custom Java Applet";
+ }
+ }
+ }
+
+ public static void sendLog(String msg, boolean packetIncoming) {
+ String logMessage = "%prefix% §r" + msg;
+ switch (systemType) {
+ case BUNGEE:
+ GeneralBungeeListener.logMessages(msg.replace("%prefix%", "[Bridge]"));
+ return;
+ case BUKKIT:
+ GeneralListener.logMessages(msg.replace("%prefix%", "[Bridge]"), packetIncoming);
+ return;
+ default:
+ System.out.println(logMessage.replace("%prefix%", "[Bridge]").replace("§", ""));
+ }
+ }
+
+ public static void sendLog(String msg) {
+ sendLog(msg, false);
+ }
+
+
+ public static String getFromConfig(String path) {
+ switch(systemType) {
+ case BUNGEE: {
+ return BridgeBungee.getConfig().getString(path);
+ }
+ case UNKNOWN: {
+ return null;
+ }
+ case BUKKIT: {
+ return Bridge.getInstance().getConfig().getString(path);
+ }
+ }
+ return null;
+ }
+
+ public static List getUpdaterGroups() {
+ if(getSystemType() != SystemType.BUKKIT) return null;
+ List list = new ArrayList<>(Collections.singletonList(getGroupName()));
+ if(!updaterGroups.isEmpty()) list.addAll(updaterGroups);
+ return list;
+ }
+
+ public static boolean isHandleServerDeployment() {
+ return handleServerDeployment;
+ }
+
+ public static void setHandleServerDeployment(boolean handleServerDeployment) {
+ BridgeGlobal.handleServerDeployment = handleServerDeployment;
+ }
+
+ public static String getServerDeploymentDir() {
+ return serverDeploymentDir.replace("%user_home%", System.getProperty("user.home"));
+ }
+
+ public static void setServerDeploymentDir(String serverDeploymentDir) {
+ BridgeGlobal.serverDeploymentDir = serverDeploymentDir;
+ }
+
+ public static String getServerTemplateDir() {
+ return serverTemplateDir.replace("%user_home%", System.getProperty("user.home"));
+ }
+
+ public static void setServerTemplateDir(String serverTemplateDir) {
+ BridgeGlobal.serverTemplateDir = serverTemplateDir;
+ }
+
+ public static void addUpdaterGroup(String group) {
+ updaterGroups.add(group);
+ }
+
+ public static void removeUpdaterGroup(String group) {
+ updaterGroups.remove(group);
+ }
+
+ public static void savePlayerData(String key, UUID uuid, JsonObject data) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.hset(key, uuid.toString(), data.toString());
+ }
+ }
+
+ public static void deletePlayerData(String key, UUID uuid) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.hdel(key, uuid.toString());
+ }
+ }
+
+ public static JsonObject getPlayerData(UUID uuid, String key) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ String data = jedis.hget(key, uuid.toString());
+
+ if(data == null) {
+ return null;
+ }
+
+ try {
+ JsonObject object = parser.parse(data).getAsJsonObject();
+
+ if(object.has("data")) {
+ return object.get("data").getAsJsonObject();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
+ public static List getUsedDisguisedNames() {
+ try (Jedis jedis = jedisPool.getResource()) {
+ Map data = jedis.hgetAll("disguise");
+
+ if(data == null) {
+ return null;
+ }
+
+ List names = Lists.newArrayList();
+
+ for(String dataStructure : data.values()) {
+ JsonObject object = parser.parse(dataStructure).getAsJsonObject();
+
+ if(object.has("data")) {
+ JsonObject values = object.get("data").getAsJsonObject();
+
+ if(values.has("disguiseName")) {
+ names.add(values.get("disguiseName").getAsString());
+ }
+ }
+ }
+
+ return names;
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/Bridge.java b/src/main/java/rip/bridge/bridge/bukkit/Bridge.java
new file mode 100644
index 0000000..94a1e59
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/Bridge.java
@@ -0,0 +1,65 @@
+package rip.bridge.bridge.bukkit;
+
+import lombok.Setter;
+import net.minecraft.server.v1_7_R4.Packet;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.listener.BridgeListener;
+import rip.bridge.bridge.bukkit.listener.FreezeListener;
+import rip.bridge.bridge.bukkit.parameters.*;
+import rip.bridge.bridge.bukkit.parameters.param.filter.FilterActionParameter;
+import rip.bridge.bridge.bukkit.parameters.param.filter.FilterParameter;
+import rip.bridge.bridge.bukkit.parameters.param.filter.FilterTypeParameter;
+import rip.bridge.bridge.bukkit.util.BukkitUtils;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.bridge.global.filter.FilterAction;
+import rip.bridge.bridge.global.filter.FilterType;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+import rip.bridge.qlib.command.FrozenCommandHandler;
+import rip.bridge.qlib.nametag.FrozenNametagHandler;
+
+import java.util.ArrayList;
+
+public class Bridge extends JavaPlugin {
+
+ @Getter private static Bridge instance;
+ @Getter private boolean isBooted = false;
+ @Getter private ArrayList blockedPackets = new ArrayList<>();
+ @Getter @Setter public boolean togglePacketLogger = false;
+
+ @Override
+ public void onLoad() {
+ (instance = this).saveDefaultConfig();
+ new BridgeGlobal();
+ BridgeGlobal.getServerHandler().registerProvider(new BukkitStatusImplementer());
+ }
+
+ @Override
+ public void onEnable() {
+ FrozenCommandHandler.registerAll(this);
+ FrozenCommandHandler.registerParameterType(Rank.class, new RankParamater());
+ FrozenCommandHandler.registerParameterType(DisguiseProfile.class, new DisguiseParameter());
+ FrozenCommandHandler.registerParameterType(Profile.class, new ProfileParamater());
+ FrozenCommandHandler.registerParameterType(Plugin.class, new PluginParameter());
+ FrozenCommandHandler.registerParameterType(FilterAction.class, new FilterActionParameter());
+ FrozenCommandHandler.registerParameterType(FilterType.class, new FilterTypeParameter());
+ FrozenCommandHandler.registerParameterType(Filter.class, new FilterParameter());
+ FrozenNametagHandler.registerProvider(new BridgeNameTagProvider());
+
+ BukkitUtils.registerListeners(BridgeListener.class);
+ BukkitUtils.registerListeners(FreezeListener.class);
+ Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> isBooted = true);
+ BridgeGlobal.loadDisguise(false);
+ }
+
+ @Override
+ public void onDisable() {
+ BridgeGlobal.shutdown();
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java b/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java
new file mode 100644
index 0000000..eafcbe2
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/BukkitAPI.java
@@ -0,0 +1,488 @@
+package rip.bridge.bridge.bukkit;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.util.MojangUtils;
+import net.minecraft.server.v1_7_R4.Packet;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.Warning;
+import org.bukkit.command.CommandSender;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class BukkitAPI {
+
+ private static Pattern uuidPattern = Pattern.compile("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}");
+ public static String LINE = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------";
+ public static String RED_LINE = ChatColor.RED.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------";
+ public static String BLUE_LINE = ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "---------------------------------------------";
+ private static final UUID ZERO_UUID = new UUID(0, 0);
+
+ public static boolean isUUID(String string) {
+ return uuidPattern.matcher(string).find();
+ }
+
+ public static Player getPlayer(String string) {
+
+ if (string == null) {
+ return null;
+ } else {
+ return isUUID(string) ? Bukkit.getPlayer(UUID.fromString(string)) : Bukkit.getPlayer(string);
+ }
+ }
+
+ public static Rank getRank(String name) {
+ return BridgeGlobal.getRankHandler().getRankByName(name);
+ }
+
+ public static Rank getRank(UUID uuid) {
+ return BridgeGlobal.getRankHandler().getRankByID(uuid);
+ }
+
+ public static Rank createRank(String name) {
+ if(BridgeGlobal.getRankHandler().getRankByName(name) != null) {
+ return null;
+ }
+ Rank r = new Rank(UUID.randomUUID(), name, false);
+ r.saveRank();
+ BridgeGlobal.getRankHandler().addRank(r);
+ return r;
+ }
+
+ public static Profile getProfile(UUID uuid) {
+ if(uuid == null) return Profile.getConsoleProfile();
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid);
+ }
+
+ public static Profile getProfile(CommandSender sender) {
+ return (sender instanceof Player ? BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(((Player)sender).getUniqueId()) : Profile.getConsoleProfile());
+ }
+
+ public static Profile getProfile(Player player) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId());
+ }
+
+ public static Profile getProfile(OfflinePlayer offlinePlayer) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId());
+ }
+
+ public static Profile getProfile(String name) {
+ Profile disguisedProfile = BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile -> profile.getDisguise() != null && profile.getDisguise().getDisguiseName().equalsIgnoreCase(name)).findAny().orElse(null);
+ if(disguisedProfile != null) return disguisedProfile;
+ return BridgeGlobal.getProfileHandler().getProfileByUsernameOrCreate(name);
+ }
+
+ public static Profile getProfileNotCreate(UUID uuid) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUID(uuid);
+ }
+
+ public static Profile getProfileNotCreate(Player player) {
+ return getProfileNotCreate(player.getUniqueId());
+ }
+
+ public static Profile getProfileNotCreate(OfflinePlayer player) {
+ return getProfileNotCreate(player.getUniqueId());
+ }
+
+
+ @Warning(reason = "This requires to be ran on a seperate thread, otherwise there will be lag on the main server thread.")
+ public static Profile getProfileOrCreateNew(UUID uuid) {
+ String name;
+ try {
+ name = MojangUtils.fetchName(uuid);
+ }catch(Exception e) {
+ return null;
+ }
+ return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(name, uuid);
+ }
+
+ public static Profile getProfileOrCreateNew(String username, UUID uuid) {
+ return BridgeGlobal.getProfileHandler().getNewProfileOrCreate(username, uuid);
+ }
+
+ public static List getOnlineProfiles() {
+ return Bukkit.getOnlinePlayers().stream().filter(player -> getProfile(player) != null).map(BukkitAPI::getProfile).collect(Collectors.toList());
+ }
+
+ public static Rank getDefaultRank() {
+ return BridgeGlobal.getRankHandler().getDefaultRank();
+ }
+
+ public static Rank getPlayerRank(CommandSender player, boolean ignoreDisguise) {
+ if(!(player instanceof Player)) {
+ return getRank("Owner");
+ }
+ if(getProfile(player) == null) {
+ return getDefaultRank();
+ }
+
+ if(ignoreDisguise) {
+ return getPlayerRank(((Player)player), true);
+ }else {
+ if(getProfile(player).getDisguisedRank() != null) {
+ return getProfile(player).getDisguisedRank();
+ }
+ }
+
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(((Player)player).getUniqueId()).getCurrentGrant().getRank();
+ }
+
+ public static Rank getPlayerRank(CommandSender player) {
+ return getPlayerRank(player, false);
+ }
+
+ public static Rank getPlayerRank(Player player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank();
+ }
+ if(getProfile(player).getDisguisedRank() != null) {
+ return getProfile(player).getDisguisedRank();
+ }
+
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getCurrentGrant().getRank();
+ }
+
+ public static Rank getPlayerRank(UUID uuid) {
+ if(getProfile(uuid) == null) {
+ return getDefaultRank();
+ }
+ if(getProfile(uuid).getDisguisedRank() != null) {
+ return getProfile(uuid).getDisguisedRank();
+ }
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank();
+ }
+
+ public static Rank getPlayerRank(OfflinePlayer offlinePlayer) {
+ if(getProfile(offlinePlayer) == null) {
+ return getDefaultRank();
+ }
+ if(getProfile(offlinePlayer).getDisguisedRank() != null) {
+ return getProfile(offlinePlayer).getDisguisedRank();
+ }
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getCurrentGrant().getRank();
+ }
+
+ public static Rank getPlayerRank(Profile profile) {
+ if(profile == null) {
+ return getDefaultRank();
+ }
+ if(profile.getUuid().toString().equals(Profile.getConsoleProfile().getUuid().toString())) {
+ return getRank("Default");
+ }
+ if(profile.getDisguisedRank() != null) {
+ return profile.getDisguisedRank();
+ }
+ return profile.getCurrentGrant().getRank();
+ }
+
+ public boolean canPunish(CommandSender sender, Profile target) {
+ if(!(sender instanceof Player)) return true;
+ return (getPlayerRank(sender).isStaff() && getPlayerRank(target).isStaff()) && getPlayerRank(sender).getPriority() > getPlayerRank(target).getPriority();
+ }
+
+ @Deprecated
+ public static boolean canOverride(CommandSender sender, Profile on) {
+ return canOverride(getProfile(sender), on);
+ }
+
+ public static boolean canOverride(Profile sender, Profile on) {
+ if (compareUUID(sender.getUuid(), ZERO_UUID)) // Always allow to override console
+ return true;
+
+ if (compareUUID(sender.getUuid(), on.getUuid())) // Always allow to override own punishments
+ return true;
+
+ return getRankPriority(sender) >= getRankPriority(on);
+ }
+
+ public static boolean compareUUID(UUID first, UUID second) {
+ return first.getLeastSignificantBits() == second.getLeastSignificantBits() && first.getMostSignificantBits() == second.getMostSignificantBits();
+ }
+
+ public static int getRankPriority(Profile profile) {
+ if (profile == null)
+ return 0;
+
+ Rank rank = getPlayerRank(profile, true);
+
+ if (rank == null)
+ return 0;
+
+ return rank.getPriority();
+ }
+
+ public static Rank getPlayerRank(Player player, boolean ignoreDisguise) {
+ if(getProfile(player) == null) {
+ return getDefaultRank();
+ }
+ if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getCurrentGrant().getRank();
+
+ else if(getProfile(player).getDisguisedRank() != null) {
+ return getProfile(player).getDisguisedRank();
+ }
+ return null;
+
+ }
+
+ public static Rank getPlayerRank(UUID uuid, boolean ignoreDisguise) {
+ if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getCurrentGrant().getRank();
+
+ else if(getProfile(uuid).getDisguisedRank() != null) {
+ return getProfile(uuid).getDisguisedRank();
+ }
+ return null;
+ }
+
+ public static Rank getPlayerRank(OfflinePlayer offlinePlayer, boolean ignoreDisguise) {
+ if(getProfile(offlinePlayer) == null) {
+ return getDefaultRank();
+ }
+ if(ignoreDisguise) return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getCurrentGrant().getRank();
+
+ else if(getProfile(offlinePlayer).getDisguisedRank() != null) {
+ return getProfile(offlinePlayer).getDisguisedRank();
+ }
+ return null;
+ }
+
+ public static Rank getPlayerRank(Profile profile, boolean ignoreDisguise) {
+ if(profile == null) {
+ return getDefaultRank();
+ }
+
+ if (profile.getUuid().getLeastSignificantBits() == 0 && profile.getUuid().getMostSignificantBits() == 0)
+ return null;
+
+ if(ignoreDisguise) return profile.getCurrentGrant().getRank();
+
+ else if(profile.getDisguisedRank() != null) {
+ return profile.getDisguisedRank();
+ }
+ return null;
+ }
+
+ public static String getColor(CommandSender sender) {
+ if(getProfile(sender) == null) {
+ return getDefaultRank().getColor();
+ }
+ if(!getProfile(sender).getColor().equals("")) {
+ return getProfile(sender).getColor();
+ }else {
+ return getPlayerRank(sender).getColor();
+ }
+ }
+
+ public static String getColor(Player player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getColor();
+ }
+ if(!getProfile(player).getColor().equals("")) {
+ return getProfile(player).getColor();
+ }else {
+ return getPlayerRank(player).getColor();
+ }
+ }
+
+ public static String getColor(OfflinePlayer player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getColor();
+ }
+ if(!getProfile(player).getColor().equals("")) {
+ return getProfile(player).getColor();
+ }else {
+ return getPlayerRank(player).getColor();
+ }
+ }
+
+ public static String getColor(UUID player) {
+ if(!getProfile(player).getColor().equals("")) {
+ return getProfile(player).getColor();
+ }else {
+ return getPlayerRank(player).getColor();
+ }
+ }
+
+ public static String getColor(Profile profile) {
+ if(!profile.getColor().equals("")) {
+ return profile.getColor();
+ }else {
+ return getPlayerRank(profile).getColor();
+ }
+ }
+
+ public static String getPrefix(Player player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getPrefix();
+ }
+ if(!getProfile(player).getPrefix().equals("")) {
+ return getProfile(player).getPrefix();
+ }else {
+ return getPlayerRank(player).getPrefix();
+ }
+ }
+
+ public static String getPrefix(OfflinePlayer player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getPrefix();
+ }
+ if(!getProfile(player).getPrefix().equals("")) {
+ return getProfile(player).getPrefix();
+ }else {
+ return getPlayerRank(player).getPrefix();
+ }
+ }
+ public static String getPrefix(UUID player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getPrefix();
+ }
+ if(!getProfile(player).getPrefix().equals("")) {
+ return getProfile(player).getPrefix();
+ }else {
+ return getPlayerRank(player).getPrefix();
+ }
+ }
+
+ public static String getPrefix(Profile profile) {
+ if(profile == null) {
+ return getDefaultRank().getPrefix();
+ }
+ if(!profile.getPrefix().equals("")) {
+ return profile.getPrefix();
+ }else {
+ return getPlayerRank(profile).getPrefix();
+ }
+ }
+
+ public static String getSuffix(Player player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getSuffix();
+ }
+ if(!getProfile(player).getSuffix().equals("")) {
+ return getProfile(player).getSuffix();
+ }else {
+ return getPlayerRank(player).getSuffix();
+ }
+ }
+
+ public static String getSuffix(OfflinePlayer player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getSuffix();
+ }
+ if(!getProfile(player).getSuffix().equals("")) {
+ return getProfile(player).getSuffix();
+ }else {
+ return getPlayerRank(player).getSuffix();
+ }
+ }
+
+ public static String getSuffix(UUID player) {
+ if(getProfile(player) == null) {
+ return getDefaultRank().getSuffix();
+ }
+ if(!getProfile(player).getSuffix().equals("")) {
+ return getProfile(player).getSuffix();
+ }else {
+ return getPlayerRank(player).getSuffix();
+ }
+ }
+
+ public static String getSuffix(Profile profile) {
+ if(profile == null) {
+ return getDefaultRank().getSuffix();
+ }
+ if(!profile.getSuffix().equals("")) {
+ return profile.getSuffix();
+ }else {
+ return getPlayerRank(profile).getSuffix();
+ }
+ }
+
+
+ public static String getName(Profile profile, boolean ignoreDisguise) {
+ return (ignoreDisguise || profile.getDisguise() == null) ? profile.getUsername() : profile.getDisguise().getDisguiseName();
+ }
+
+ public static String getRealName(Profile profile) {
+ return profile.getDisguise() == null ? profile.getUsername() : profile.getDisguise().getName();
+ }
+
+ public static String getRealName(UUID uuid) {
+ return getRealName(getProfile(uuid));
+ }
+
+ public static String getRealName(Player player) {
+ return getRealName(getProfile(player));
+ }
+
+
+ public static void sendPacket(Player player, Packet packet){
+ CraftPlayer cp = (CraftPlayer) player;
+ cp.getHandle().playerConnection.sendPacket(packet);
+ }
+
+ public static List getActiveGrants(Player player) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getActiveGrants();
+ }
+
+ public static List getActiveGrants(UUID uuid) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants();
+ }
+
+ public static List getActiveGrants(OfflinePlayer offlinePlayer) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getActiveGrants();
+ }
+
+ public static List getActiveGrants(Profile profile) {
+ return profile.getActiveGrants();
+ }
+
+ public static List getCurrentScopeRanks(Player player) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList());
+ }
+
+ public static List getCurrentScopeRanks(UUID uuid) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList());
+ }
+
+ public static List getCurrentScopeRanks(OfflinePlayer offlinePlayer) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getActiveGrants().stream().filter(Grant::isGrantActiveOnScope).collect(Collectors.toList());
+ }
+
+ public static List getAllGrants(Player player) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(player.getUniqueId()).getGrants();
+ }
+
+ public static List getAllGrants(UUID uuid) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(uuid).getGrants();
+ }
+
+ public static List getAllGrants(OfflinePlayer offlinePlayer) {
+ return BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(offlinePlayer.getUniqueId()).getGrants();
+ }
+
+ public static void sendToStaff(String message) {
+ BridgeGlobal.sendLog(message);
+ Bukkit.getOnlinePlayers().stream().filter(p -> getPlayerRank(p, true).isStaff()).forEach(p -> {
+ ((Player) p).sendMessage(ChatColor.translateAlternateColorCodes('&', message));
+ });
+ }
+
+ public static void sendToStaff(List message) {
+ message.forEach(BridgeGlobal::sendLog);
+ Bukkit.getOnlinePlayers().stream().filter(p -> getPlayerRank(p, true).isStaff()).forEach(p -> {
+ message.forEach(string -> {
+ ((Player) p).sendMessage(ChatColor.translateAlternateColorCodes('&', string));
+ });
+ });
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java
new file mode 100644
index 0000000..360179f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapCreator.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.auth;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.map.MapView;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+
+import java.awt.image.BufferedImage;
+
+public class TotpMapCreator {
+
+ public ItemStack createMap(Player player, BufferedImage bufferedImage) {
+ MapView mapView = Bridge.getInstance().getServer().createMap(player.getWorld());
+ mapView.getRenderers().forEach(mapView::removeRenderer);
+ mapView.addRenderer(new TotpMapRenderer(player.getUniqueId(), bufferedImage));
+ player.sendMap(mapView);
+ return new ItemStack(Material.MAP, 0, mapView.getId());
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java
new file mode 100644
index 0000000..a0a46da
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/auth/TotpMapRenderer.java
@@ -0,0 +1,29 @@
+package rip.bridge.bridge.bukkit.auth;
+
+import org.bukkit.entity.Player;
+import org.bukkit.map.MapCanvas;
+import org.bukkit.map.MapRenderer;
+import org.bukkit.map.MapView;
+
+import java.awt.image.BufferedImage;
+import java.util.Map;
+import java.util.UUID;
+
+public class TotpMapRenderer extends MapRenderer {
+
+ private final UUID targetPlayer;
+ private BufferedImage image;
+
+ public TotpMapRenderer(UUID targetPlayer, BufferedImage image) {
+ this.targetPlayer = targetPlayer;
+ this.image = image;
+ }
+
+ public void render(MapView mapView, MapCanvas mapCanvas, Player player) {
+ if(player.getUniqueId().equals(this.targetPlayer)) {
+ mapCanvas.drawImage(0, 0, this.image);
+ this.image = null;
+ }
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java
new file mode 100644
index 0000000..dc16400
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/InitialDisclaimerPrompt.java
@@ -0,0 +1,26 @@
+package rip.bridge.bridge.bukkit.auth.prompt;
+
+import org.bukkit.ChatColor;
+import org.bukkit.conversations.ConversationContext;
+import org.bukkit.conversations.Prompt;
+import org.bukkit.conversations.StringPrompt;
+
+public class InitialDisclaimerPrompt extends StringPrompt {
+
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.RED.toString() + ChatColor.BOLD + "Take a minute to read over this, it's important. "
+ + ChatColor.RED + "2FA can be enabled to protect against hackers getting into your Minecraft account. " +
+ "If you enable 2FA, you'll be required to enter a code every time you log in. If you lose your 2FA device, you wont be able to log into the Bridge Network."
+ + ChatColor.GRAY + " If you have read the above and would like to proceed, type \"yes\" in the chat. Otherwise, type anything else.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String s) {
+ if(s.equalsIgnoreCase("yes")) {
+ return new ScanMapPrompt();
+ } else {
+ context.getForWhom().sendRawMessage(ChatColor.GREEN + "Aborted 2FA setup.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java
new file mode 100644
index 0000000..2918d98
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/auth/prompt/ScanMapPrompt.java
@@ -0,0 +1,124 @@
+package rip.bridge.bridge.bukkit.auth.prompt;
+
+import com.google.common.escape.Escaper;
+import com.google.common.net.UrlEscapers;
+import com.warrenstrange.googleauth.GoogleAuthenticator;
+import net.minecraft.util.org.apache.commons.codec.binary.Base32;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.conversations.ConversationContext;
+import org.bukkit.conversations.Prompt;
+import org.bukkit.conversations.StringPrompt;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.auth.TotpMapCreator;
+import rip.bridge.bridge.global.profile.Profile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+
+public class ScanMapPrompt extends StringPrompt {
+
+ private static final String totptImageUrlFormat = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl=%s";
+ private static final TotpMapCreator totpMapCreator = new TotpMapCreator();
+ private static final Base32 base32Encoder = new Base32();
+ private static SecureRandom secureRandom;
+ int failures = 0;
+
+ public String getPromptText(ConversationContext context) {
+ Player player = (Player) context.getForWhom();
+ if(this.failures == 0) {
+ Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> {
+ String totpSecret = generateTotpSecret();
+ BufferedImage totpImage = createTotpImage(player, totpSecret);
+ Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> {
+ ItemStack map = totpMapCreator.createMap(player, totpImage);
+ context.setSessionData("totpSecret", totpSecret);
+ context.setSessionData("totpMap", map);
+ player.getInventory().addItem(map);
+ });
+ });
+ }
+
+ return ChatColor.RED + "On your 2FA device, scan the map given to you. Once you've scanned the map, type the code displayed on your device in chat.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String s) {
+ Player player = (Player) context.getForWhom();
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId());
+ ItemStack totpMap = (ItemStack) context.getSessionData("totpMap");
+ player.getInventory().remove(totpMap);
+ String totpSecret = (String) context.getSessionData("totpSecret");
+
+ if(this.failures >= 3) {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Cancelling 2FA setup due to too many incorrect codes.");
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Contact the Bridge Network staff team for any questions you may have about 2FA.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ int totpCode;
+ try {
+ totpCode = Integer.parseInt(s.replaceAll(" ", ""));
+ } catch(NumberFormatException ex) {
+ context.getForWhom().sendRawMessage(" ");
+ context.getForWhom().sendRawMessage(ChatColor.RED + s + " isn't a valid totp code. Let's try that again");
+ return this;
+ }
+
+ Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> {
+
+ GoogleAuthenticator gAuth = new GoogleAuthenticator();
+ boolean isValid = gAuth.authorize(totpSecret, totpCode);
+
+ if(isValid) {
+ profile.setSecretKey(totpSecret);
+ profile.saveProfile();
+
+ player.removeMetadata("Locked", Bridge.getInstance());
+
+ player.sendMessage(ChatColor.GREEN + "2FA setup completed successfully.");
+ } else {
+ context.getForWhom().sendRawMessage(ChatColor.RED + s + " isn't a valid totp code. Let's try that again");
+ failures++;
+ }
+
+ });
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ private static String generateTotpSecret() {
+ byte[] secretKey = new byte[10];
+ secureRandom.nextBytes(secretKey);
+ return base32Encoder.encodeToString(secretKey);
+ }
+
+ private static BufferedImage createTotpImage(Player player, String secret) {
+ Escaper urlEscaper = UrlEscapers.urlFragmentEscaper();
+ String totpUrl = "otpauth://totp/" + urlEscaper.escape(player.getName()) + "?secret=" + secret + "&issuer=" + urlEscaper.escape("Bridge Network");
+ String totpImageUrl = String.format(totptImageUrlFormat, URLEncoder.encode(totpUrl));
+
+ try {
+ return ImageIO.read(new URL(totpImageUrl));
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ static {
+ try {
+ secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
+ } catch (GeneralSecurityException ex) {
+ ex.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java
new file mode 100644
index 0000000..5107591
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/AlertCommand.java
@@ -0,0 +1,20 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.bukkit.parameters.AlertPacket;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.xpacket.FrozenXPacketHandler;
+
+public class AlertCommand {
+
+ @Command(names = "alert", permission = "bridge.alert", description = "Alert a message to the network", async = true)
+ public static void alert(CommandSender sender, @Param(name = "message", wildcard = true) String msg) {
+ FrozenXPacketHandler.sendToAll(new AlertPacket(msg, false));
+ }
+
+ @Command(names = "rawalert", permission = "bridge.alert", description = "Alert a raw message to the network", async = true)
+ public static void rawalert(CommandSender sender, @Param(name = "message", wildcard = true) String msg) {
+ FrozenXPacketHandler.sendToAll(new AlertPacket(msg, true));
+ }
+ }
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java
new file mode 100644
index 0000000..e8772cd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/DemoCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import net.minecraft.server.v1_7_R4.PacketPlayOutGameStateChange;
+import org.bukkit.ChatColor;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DemoCommand {
+
+ @Command(names = "demo", permission = "op", hidden = true)
+ public static void demo(Player player, @Param(name = "target") Player target) {
+ PacketPlayOutGameStateChange packet = new PacketPlayOutGameStateChange(5, 0);
+ ((CraftPlayer)target).getHandle().playerConnection.sendPacket(packet);
+ player.sendMessage(ChatColor.YELLOW + "Demo screened " + target.getDisplayName() + ChatColor.YELLOW + "!");
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java
new file mode 100644
index 0000000..8e2ec8d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/EndScreenCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import net.minecraft.server.v1_7_R4.PacketPlayOutGameStateChange;
+import org.bukkit.ChatColor;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class EndScreenCommand {
+
+ @Command(names = "endscreen", permission = "op", hidden = true)
+ public static void endscreen(Player player, @Param(name = "target") Player target) {
+ PacketPlayOutGameStateChange packet = new PacketPlayOutGameStateChange(4, 0.0F);
+ ((CraftPlayer)target).getHandle().playerConnection.sendPacket(packet);
+ player.sendMessage(ChatColor.YELLOW + "End screened " + target.getDisplayName() + ChatColor.YELLOW + "!");
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java
new file mode 100644
index 0000000..1f15428
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ExecuteCommands.java
@@ -0,0 +1,72 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.ServerCommandPacket;
+import rip.bridge.bridge.global.packet.types.ServerGroupCommandPacket;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class ExecuteCommands {
+
+ @Command(names = {"execcmd server", "executecommands server"}, permission = "bridge.execute", hidden = true, async = true)
+ public static void server(Player sender, @Param(name = "server") String server, @Param(name = "command", wildcard = true) String command) {
+ promptExecute(sender, server, command);
+ }
+
+ @Command(names = {"execcmd global", "executecommands global"}, permission = "bridge.execute", hidden = true, async = true)
+ public static void global(Player sender, @Param(name = "command", wildcard = true) String command) {
+ promptExecute(sender, "globally", command);
+ }
+
+ @Command(names = {"execcmd group", "executecommands group"}, permission = "bridge.execute", hidden = true, async = true)
+ public static void group(Player sender, @Param(name = "group") String serverGroup, @Param(name = "command", wildcard = true) String command) {
+ promptExecute2(sender, serverGroup, command);
+ }
+
+ private static void promptExecute(Player player, String server, String command) {
+ ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.translateAlternateColorCodes('&', "&eYou are about to execute the command &c\"" + command + "\" &c" + server + " &eare you sure you want to do this? If so type &ayes&c.");
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if (input.equalsIgnoreCase("yes")) {
+ context.getForWhom().sendRawMessage(ChatColor.GREEN + "Sending cross-bungee command...");
+ PacketHandler.sendToAll(new ServerCommandPacket(server, command));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.execute.view", "&8[&eServer Monitor&8] " + player.getDisplayName() + " &fexecuted command &d" + command + (server.equals("globally") ? " &f" : " &fon ") + server));
+ } else {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Executing canclled.");
+ }
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+
+ private static void promptExecute2(Player player, String serverGroup, String command) {
+ ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.translateAlternateColorCodes('&', "&eYou are about to execute the command &c\"" + command + "\" to the server group &c" + serverGroup + " &eare you sure you want to do this? If so type &ayes&c.");
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if (input.equalsIgnoreCase("yes")) {
+ context.getForWhom().sendRawMessage(ChatColor.GREEN + "Sending cross-bungee command...");
+ PacketHandler.sendToAll(new ServerGroupCommandPacket(serverGroup, command));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.execute.view", "&8[&eServer Monitor&8] " + player.getDisplayName() + " &fexecuted command &d" + command + " &fon the server group " + serverGroup));
+ } else {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Executing canclled.");
+ }
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java
new file mode 100644
index 0000000..03b7257
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/FindCommand.java
@@ -0,0 +1,29 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class FindCommand {
+
+ @Command(names = { "find" }, permission = "bridge.find", description = "See the server a player is currently playing on", async = true)
+ public static void find(CommandSender sender, @Param(name = "player", extraData = "get") Profile profile) {
+ findresponse(sender, profile);
+ }
+
+ public static void findresponse(CommandSender sender, Profile profile) {
+ BridgeServer server = BridgeGlobal.getServerHandler().findPlayerServer(profile.getUuid());
+ BridgeServer proxy = BridgeGlobal.getServerHandler().findPlayerProxy(profile.getUuid());
+ if (server == null) {
+ sender.sendMessage(ChatColor.RED + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + " is currently not on the network.");
+ return;
+ }
+
+ sender.sendMessage(ChatColor.YELLOW + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + " is on " + ChatColor.GREEN + server.getName() + (proxy != null ? ChatColor.YELLOW + " (" + ChatColor.GREEN + proxy.getName() + " Proxy" + ChatColor.YELLOW + ")" : ""));
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java
new file mode 100644
index 0000000..324c451
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ListCommand.java
@@ -0,0 +1,70 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.visibility.FrozenVisibilityHandler;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class ListCommand {
+
+ @Command(names = { "list", "who", "players" }, permission = "", description = "See a list of online players", async = true)
+ public static void list(CommandSender sender) {
+ Map> sorted = new TreeMap<>(Comparator.comparingInt(Rank::getPriority).reversed());
+ int online = 0;
+ for (Player player : Bukkit.getOnlinePlayers()) {
+
+ if(!sender.hasPermission("basic.staff") && !canSee(sender, player)) continue;
+ ++online;
+ Profile profile = BukkitAPI.getProfile(player.getUniqueId());
+ Rank rank = BukkitAPI.getPlayerRank(profile);
+
+ String displayName = player.getDisplayName() + ChatColor.WHITE;
+ if (player.hasMetadata("invisible")) {
+ displayName = ChatColor.GRAY + "*" + displayName + ChatColor.WHITE;
+ }
+ sorted.putIfAbsent(rank, new LinkedList<>());
+ sorted.get(rank).add(displayName);
+ }
+ List merged = new LinkedList<>();
+ for (List part : sorted.values()) {
+ part.sort(String.CASE_INSENSITIVE_ORDER);
+ merged.addAll(part);
+ }
+ sender.sendMessage(getHeader(sender));
+ sender.sendMessage("(" + online + "/" + Bukkit.getMaxPlayers() + ") " + merged);
+ }
+
+ private static String getHeader(CommandSender sender) {
+ StringBuilder builder = new StringBuilder();
+ List ranks = BridgeGlobal.getRankHandler().getRanks().parallelStream().sorted(Comparator.comparingInt(Rank::getPriority).reversed()).collect(Collectors.toList());
+ for (Rank rank : ranks) {
+ boolean displayed = rank.getPriority() >= 0;
+ if (displayed) {
+ if(rank.isHidden() && sender.hasPermission("bridge.hiddenranks")) {
+ builder.append(ChatColor.GRAY + "*").append(rank.getColor()).append(rank.getDisplayName()).append(ChatColor.RESET).append(", ");
+ }else if(!rank.isHidden()){
+ builder.append(rank.getColor()).append(rank.getDisplayName()).append(ChatColor.RESET).append(", ");
+ }
+ }
+ }
+ if (builder.length() > 2) {
+ builder.setLength(builder.length() - 2);
+ }
+ return builder.toString();
+ }
+
+ private static boolean canSee(CommandSender sender, CommandSender target) {
+ if(!(sender instanceof Player)) return true;
+ return FrozenVisibilityHandler.treatAsOnline((Player)target, (Player)sender);
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java
new file mode 100644
index 0000000..d1278c6
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/PacketLoggerCommands.java
@@ -0,0 +1,62 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import com.google.common.collect.Maps;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packetlogger.PacketLog;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+import java.util.Map;
+
+public class PacketLoggerCommands {
+
+ @Command(names = {"packetlogger info"}, permission = "op", hidden = true, async = true)
+ public static void packetloggerinfo(CommandSender sender, @Param(name = "target", defaultValue = "self") Player target) {
+
+ sender.sendMessage(ChatColor.GREEN + "Getting Packet Log for " + target.getDisplayName() + ChatColor.GREEN + "...");
+ sender.sendMessage(BukkitAPI.LINE);
+
+ Map packetInfo = Maps.newHashMap();
+ Map canceled = Maps.newHashMap();
+ for (PacketLog packetLog : BridgeGlobal.getPacketLogHandler().getLog(target.getUniqueId())) {
+
+ int amount = 1;
+ if (packetInfo.containsKey(packetLog.getPacket().getClass().getSimpleName())) {
+ amount = packetInfo.get(packetLog.getPacket().getClass().getSimpleName());
+ amount++;
+ }
+ int amountFlagged = 1;
+ if (canceled.containsKey(packetLog.getPacket().getClass().getSimpleName())) {
+ amountFlagged = canceled.get(packetLog.getPacket().getClass().getSimpleName());
+ amountFlagged++;
+ }
+ canceled.put(packetLog.getPacket().getClass().getSimpleName(), amount);
+ }
+ if (packetInfo.size() == 0) {
+ sender.sendMessage(ChatColor.RED + target.getName() + " has no packet logs.");
+ } else {
+ for (Map.Entry entry : packetInfo.entrySet()) {
+ sender.sendMessage(BukkitAPI.LINE);
+ sender.sendMessage(ChatColor.YELLOW + entry.getKey() + ChatColor.GRAY + " (" + ChatColor.RED + entry.getValue() + ChatColor.GRAY + ") " +
+ ChatColor.YELLOW + "Times Flagged: " + canceled.get(entry.getKey()));
+ }
+ sender.sendMessage(BukkitAPI.LINE);
+
+
+ }
+ }
+
+ @Command(names = {"packetlogger toggle "}, permission = "op", hidden = true, async = true)
+ public static void packetloggertoggle(CommandSender sender) {
+ boolean toogled = Bridge.getInstance().togglePacketLogger;
+ Bridge.getInstance().setTogglePacketLogger(!Bridge.getInstance().togglePacketLogger);
+ sender.sendMessage(ChatColor.YELLOW + "PacketLogger: " + (!toogled ? ChatColor.RED + "Disabled" : ChatColor.GREEN + "Enabled") + ChatColor.YELLOW + ".");
+
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java
new file mode 100644
index 0000000..0017700
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/PermsCommand.java
@@ -0,0 +1,45 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.util.PaginatedResult;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.Optional;
+
+public class PermsCommand {
+
+ @Command(names = { "perms" }, permission = "bridge.viewperms", description = "View an player's permissions", async = true)
+ public static void perms(CommandSender sender, @Param(name = "player", defaultValue = "self") Player player, @Param(name = "page", defaultValue = "1") int page) {
+ Optional optionalProfile = Optional.ofNullable(BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()));
+ if (!optionalProfile.isPresent()) {
+ sender.sendMessage(ChatColor.RED + player.getName() + "'s profile isn't loaded.");
+ return;
+ }
+ Rank rank = optionalProfile.get().getCurrentGrant().getRank();
+ List toSend = Lists.newArrayList();
+ for (String permission : rank.getPermissions().keySet()) {
+ toSend.add((player.hasPermission(permission) ? (ChatColor.GREEN + " + ") : (ChatColor.RED + " - ")) + ChatColor.WHITE + permission + " (" + rank.getPermissions().get(permission) + ")");
+ }
+ new PaginatedResult() {
+ @Override
+ public String getHeader(int page, int maxPages) {
+ return ChatColor.translateAlternateColorCodes('&', "&c" + StringUtils.repeat('-', 3) + " &r" + player.getDisplayName() + "&7(&r" + rank.getColor() + rank.getDisplayName() + "&7)'s Permissions (&e" + page + "&7/&e" + maxPages + "&7) &c" + StringUtils.repeat('-', 3));
+ }
+
+ @Override
+ public String format(String entry, int index) {
+ return entry;
+ }
+ }.display(sender, toSend, page);
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java
new file mode 100644
index 0000000..8db553e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/SeenCommand.java
@@ -0,0 +1,34 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import mkremins.fanciful.FancyMessage;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.Date;
+
+public class SeenCommand {
+
+ @Command(names = {"lastseen", "seen"}, permission = "bridge.seen", description = "See when a player was last on", async = true)
+ public static void lastseen(CommandSender sender, @Param(name = "player", extraData = "get") Profile profile) {
+
+ if (profile.isOnline()) {
+ sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36));
+ sender.sendMessage((ChatColor.RED + profile.getUsername() + ChatColor.YELLOW + " is currently on " + ChatColor.RED + profile.getConnectedServer() + ChatColor.YELLOW + "."));
+ sender.sendMessage(ChatColor.GOLD + "Check out their info on the website: bridge.rip/u/" + profile.getUsername());
+ sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36));
+ } else {
+ sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36));
+ sender.sendMessage((ChatColor.RED + profile.getUsername() + ChatColor.YELLOW + " is currently " + ChatColor.RED + "offline" + ChatColor.YELLOW + "."));
+ sender.sendMessage(ChatColor.YELLOW + "Last seen at " + ChatColor.RED + TimeUtils.formatIntoCalendarString(new Date(profile.getLastJoined())) + ChatColor.YELLOW + " on " + ChatColor.RED + profile.getConnectedServer() + ChatColor.YELLOW + ".");
+ sender.sendMessage(ChatColor.GOLD + "Check out their info on the website: bridge.rip/u/" + profile.getUsername());
+ sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 36));
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java b/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java
new file mode 100644
index 0000000..50827f7
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/ThreadProfilerCommands.java
@@ -0,0 +1,66 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import com.google.common.collect.Maps;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitTask;
+import rip.bridge.qlib.command.Command;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import static org.spigotmc.TicksPerSecondCommand.format;
+
+
+public class ThreadProfilerCommands {
+
+ @Command(names = {"threadprofiler list"}, permission = "op", hidden = true, async = true)
+ public static void threadprofilerlist(CommandSender sender) {
+ Set threads = Thread.getAllStackTraces().keySet();
+ for (Thread thread : threads) {
+ sender.sendMessage(ChatColor.translateAlternateColorCodes
+ ('&', " &6* &e"
+ + thread.getName() + " &d(State: "
+ + (thread.getState()) + ", Priority: "
+ + thread.getPriority() + ")"));
+ }
+
+ }
+
+ @Command(names = {"threadprofiler gc"}, permission = "op", hidden = true, async = true)
+ public static void threadprofilergc(CommandSender sender) {
+ Runtime runtime = Runtime.getRuntime();
+ sender.sendMessage(ChatColor.YELLOW + "Trying to run Java garbage collector to free up memory.");
+ long before = System.currentTimeMillis();
+ runtime.gc();
+ long after = System.currentTimeMillis();
+ sender.sendMessage(ChatColor.GOLD
+ + "* "
+ + ChatColor.YELLOW + "Finished! Took "
+ + ChatColor.LIGHT_PURPLE
+ + (after - before)
+ + "ms");
+
+ }
+
+ @Command(names = {"threadprofiler threads"}, permission = "op", hidden = true, async = true)
+ public static void threadprofilerthreads(CommandSender sender) {
+ Set threads = Thread.getAllStackTraces().keySet();
+ Runtime runtime = Runtime.getRuntime();
+ HashMap pending = Maps.newHashMap();
+ for (BukkitTask worker : Bukkit.getScheduler().getPendingTasks()) {
+ pending.put(worker.getOwner(), pending.getOrDefault(worker.getOwner(), 0) + 1);
+ }
+ sender.sendMessage(ChatColor.GOLD + "Alive Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isAlive).count());
+ sender.sendMessage(ChatColor.GOLD + "Daemon Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isDaemon).count());
+ sender.sendMessage(ChatColor.GOLD + "Interrupted Threads: " + ChatColor.LIGHT_PURPLE + Thread.getAllStackTraces().keySet().parallelStream().filter(Thread::isInterrupted).count());
+ sender.sendMessage(ChatColor.GOLD + "Active Workers: " + ChatColor.LIGHT_PURPLE + Bukkit.getScheduler().getActiveWorkers().size());
+ sender.sendMessage(ChatColor.GOLD + "Pending Tasks: " + ChatColor.LIGHT_PURPLE + Bukkit.getScheduler().getPendingTasks().size());
+ sender.sendMessage(ChatColor.GOLD + "Threads: " + ChatColor.YELLOW + "(" + threads.size() + " Active) (Ram " + ChatColor.LIGHT_PURPLE + format(runtime.freeMemory()) + " free out of " + ChatColor.LIGHT_PURPLE + format(runtime.maxMemory()) + " " + ChatColor.LIGHT_PURPLE + format(runtime.maxMemory() - runtime.freeMemory()) + " used" + ChatColor.GOLD + ")");
+ sender.sendMessage("");
+ pending.keySet().stream().sorted((o1, o2) -> pending.get(o2) - pending.get(o1)).forEachOrdered(plugin -> sender.sendMessage(ChatColor.RED + "* " + ChatColor.YELLOW + plugin.getName() + ": " + ChatColor.WHITE + pending.get(plugin)));
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java
new file mode 100644
index 0000000..9586f32
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/TimelineCommand.java
@@ -0,0 +1,98 @@
+package rip.bridge.bridge.bukkit.commands;
+
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.util.TimeUtil;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+public class TimelineCommand {
+
+ public static String blockColors = "▋";
+
+ @Command(names = {"timeline"}, permission = "basic.staff", description = "Check for how long you've been staff!", async = true)
+ public static void timeline(Player sender, @Param(name = "target", defaultValue = "self") Profile target) {
+
+ if (!target.getCurrentGrant().getRank().isStaff() && target.getRemovedStaffOn() == 0) {
+ sender.sendMessage(ChatColor.RED + "That player has never been apart of the staff team.");
+ } else {
+ sender.sendMessage(BukkitAPI.RED_LINE);
+
+ List grants = new ArrayList<>(target.getGrants());
+ List blockLines = new ArrayList<>();
+
+ grants.sort(new SortByDate());
+
+ boolean isFirst = false;
+ for(Grant grant : grants) {
+ if(!grant.getRank().isStaff()) continue;
+
+// Random randie = new Random();
+//
+// int random = randie.nextInt(15);
+
+ blockLines.add(grant.getRank().getColor().replace("§o", "") + ChatColor.STRIKETHROUGH + blockColors + "" + ChatColor.RESET);
+ for (int i = 0; i < Math.abs(TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - grant.getInitialTime()) / 7); ++i) {
+ blockLines.add(ChatColor.DARK_GRAY + ChatColor.STRIKETHROUGH.toString() + blockColors + ChatColor.RESET);
+ }
+
+ if(!isFirst) {
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " joined the team on " + ChatColor.LIGHT_PURPLE + grant.getDate()
+ + ChatColor.YELLOW + " and was given " + grant.getRank().getColor() + grant.getRank().getDisplayName()
+ + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless());
+ isFirst = true;
+ continue;
+ }
+
+ if(grant.getRank().getPriority() > 70) {
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " was" + ChatColor.GREEN + " promoted " + ChatColor.YELLOW + "to " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.YELLOW +
+ " on " + ChatColor.LIGHT_PURPLE + grant.getDate()
+ + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless());
+ } else {
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " was granted " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.YELLOW +
+ " on " + ChatColor.LIGHT_PURPLE + grant.getDate()
+ + ChatColor.YELLOW + " by " + ChatColor.LIGHT_PURPLE + grant.getGrantedByColorless());
+
+ }
+ }
+
+ sender.sendMessage(" ");
+ sender.sendMessage(ChatColor.AQUA + "Timeline:");
+
+ String result = StringUtils.join(blockLines, "");
+
+ sender.sendMessage(result + ChatColor.GOLD + ChatColor.STRIKETHROUGH + "▋");
+
+ sender.sendMessage(" ");
+ if(target.getRemovedStaffOn() != 0) {
+ Date timeAdded = new Date(target.getBecameStaffOn());
+ Date timeRemoved = new Date(target.getRemovedStaffOn());
+ long diffInM = Math.abs(timeRemoved.getTime() - timeAdded.getTime());
+ long diff = TimeUnit.DAYS.convert(diffInM, TimeUnit.MILLISECONDS);
+
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " parted ways with the staff team on " + ChatColor.LIGHT_PURPLE + TimeUtils.formatIntoCalendarStringNoTime(new Date(target.getRemovedStaffOn())) + ChatColor.YELLOW + ".");
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.GREEN + " helped the staff team for " + ChatColor.LIGHT_PURPLE + TimeUtil.millisToRoundedTime(timeRemoved.getTime() - timeAdded.getTime()) + ChatColor.YELLOW + ".");
+ } else {
+ sender.sendMessage(ChatColor.GOLD + target.getUsername() + ChatColor.YELLOW + " has been helping the staff team for " + ChatColor.LIGHT_PURPLE + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - target.getBecameStaffOn()) + ChatColor.YELLOW + ".");
+ }
+
+ sender.sendMessage(BukkitAPI.RED_LINE);
+
+ }
+ }
+
+ static class SortByDate implements Comparator {
+ @Override
+ public int compare(Grant a, Grant b) {
+ return a.getDate().compareTo(b.getDate());
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java
new file mode 100644
index 0000000..0e906df
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/AuthCommand.java
@@ -0,0 +1,49 @@
+package rip.bridge.bridge.bukkit.commands.auth;
+
+import com.warrenstrange.googleauth.GoogleAuthenticator;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class AuthCommand {
+
+ @Command(names = {"auth", "authenticate", "2fa", "otp"}, permission = "basic.staff", description = "Authenticate with the API, verifying your identity", hidden = true)
+ public static void auth(Player sender, @Param(name = "code", wildcard = true) String input) {
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(sender.getUniqueId());
+ if(!sender.hasMetadata("Locked")) {
+ sender.sendMessage(ChatColor.RED + "You don't need to authenticate at the moment.");
+ } else {
+ input = input.replace(" ", "");
+ int code = Integer.parseInt(input);
+ Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> {
+ if (profile == null) {
+ sender.sendMessage(ChatColor.DARK_RED.toString() + ChatColor.BOLD + "Your profile hasn't yet been loaded.");
+ } else {
+
+ if(profile.getSecretKey().isEmpty()) {
+ sender.sendMessage(ChatColor.RED + "You need to setup your 2FA first using: /2fasetup.");
+ return;
+ }
+
+ GoogleAuthenticator gAuth = new GoogleAuthenticator();
+ boolean isValid = gAuth.authorize(profile.getSecretKey(), code);
+
+ if(isValid) {
+ sender.removeMetadata("Locked", Bridge.getInstance());
+
+ sender.sendMessage(ChatColor.DARK_GREEN + "✓ " + ChatColor.GREEN + "Authenticated");
+ } else {
+ sender.sendMessage(ChatColor.RED + "Invalid auth code.");
+ }
+
+ }
+ });
+ }
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java
new file mode 100644
index 0000000..3925bd3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/ForceAuthCommand.java
@@ -0,0 +1,20 @@
+package rip.bridge.bridge.bukkit.commands.auth;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.metadata.FixedMetadataValue;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class ForceAuthCommand {
+
+ @Command(names = {"forceauth"}, permission = "op", description = "Forcefully authenticate a player", hidden = true)
+ public static void forceAuth(CommandSender sender, @Param(name = "player") Player player) {
+ player.removeMetadata("Locked", Bridge.getInstance());
+ player.setMetadata("ForceAuth", new FixedMetadataValue(Bridge.getInstance(), true));
+ sender.sendMessage(ChatColor.YELLOW + player.getName() + " has been forcefully authenticated.");
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java
new file mode 100644
index 0000000..2481853
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/auth/Setup2faCommand.java
@@ -0,0 +1,24 @@
+package rip.bridge.bridge.bukkit.commands.auth;
+
+import org.bukkit.ChatColor;
+import org.bukkit.conversations.Conversation;
+import org.bukkit.conversations.ConversationFactory;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.auth.prompt.InitialDisclaimerPrompt;
+import rip.bridge.qlib.command.Command;
+
+public class Setup2faCommand {
+
+ @Command(names = {"setup2fa", "2fasetup"}, permission = "basic.staff", description = "Sign up to use 2FA to verify your identity", hidden = true)
+ public static void setup2fa(Player sender) {
+ if (!BridgeGlobal.getProfileHandler().getProfileByUUIDOrCreate(sender.getUniqueId()).getSecretKey().isEmpty()) {
+ sender.sendMessage(ChatColor.RED + "You already have 2FA setup!");
+ } else {
+ ConversationFactory factory = (new ConversationFactory(Bridge.getInstance())).withFirstPrompt(new InitialDisclaimerPrompt()).withLocalEcho(false).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(sender);
+ sender.beginConversation(con);
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java
new file mode 100644
index 0000000..bdd7be5
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/DisguiseCommand.java
@@ -0,0 +1,52 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.disguise.menu.DisguiseRankMenu;
+import rip.bridge.bridge.global.util.mojang.GameProfileUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+public class DisguiseCommand {
+
+ @Command(names = {"disguise", "dis", "d", "nick"}, permission = "bridge.disguise", description = "Disguise as another player", hidden = true)
+ public static void disguise(Player player, @Flag(value = {"cc"}, description = "Disable case-correction of the name") boolean caseCorrection, @Param(name = "name") String name) {
+ if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) {
+ player.sendMessage(ChatColor.RED + "Invalid username: " + name);
+ return;
+ }
+
+ String finalName = name;
+ if (Bukkit.getPlayerExact(name) != null || Objects.requireNonNull(BridgeGlobal.getUsedDisguisedNames()).stream().anyMatch(n -> n.equalsIgnoreCase(finalName))) {
+ player.sendMessage(ChatColor.RED + "The name \"" + name + "\" is unavailable.");
+ return;
+ } // try this
+
+ if (BukkitAPI.getProfile(name) != null && BukkitAPI.getPlayerRank(BukkitAPI.getProfile(name)).isStaff()) {
+ player.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name.");
+ return;
+ }
+
+ if (BukkitAPI.getProfile(name) != null) {
+ player.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name.");
+ return;
+ }
+
+ String realName = GameProfileUtil.getRealName(name);
+
+
+ if (!caseCorrection && realName != null && !name.equals(realName)) {
+
+ name = realName;
+ }
+
+ new DisguiseRankMenu(name, realName != null).openMenu(player);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java
new file mode 100644
index 0000000..fc2fd6a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/RealNameCommand.java
@@ -0,0 +1,52 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RealNameCommand {
+
+ @Command(names = {"realname", "realnick", "checkdisguise"}, permission = "basic.staff", description = "Check who the person is!", hidden = true)
+ public static void check(Player sender, @Param(name = "name") String name) {
+ Player player = Bukkit.getPlayer(name);
+
+ if (player == null) {
+ for (DisguisePlayer disguisePlayer : BridgeGlobal.getDisguiseManager().getDisguisePlayers().values()) {
+ if (name.equalsIgnoreCase(disguisePlayer.getName())) {
+ Player dPlayer = Bukkit.getPlayer(disguisePlayer.getDisguiseName());
+
+ if (dPlayer != null) {
+ player = dPlayer;
+ break;
+ }
+ }
+ }
+ }
+
+ if (player == null) {
+ sender.sendMessage("§cNo player with the name" + " \"" + name + "\" found.");
+ return;
+ }
+
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+ Profile data = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId());
+ DisguiseProfile profile = disguisePlayer != null ? BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values()
+ .stream()
+ .filter(dp -> disguisePlayer.getDisguiseSkin() != null && dp.getSkinName().equalsIgnoreCase(disguisePlayer.getDisguiseSkin()))
+ .findFirst()
+ .orElse(null) : null;
+
+ sender.sendMessage(data.getCurrentGrant().getRank().getColor() + data.getUsername() + ChatColor.GOLD + (disguisePlayer != null ? " is disguised" : ChatColor.RED + " is NOT disguised") + '.');
+ if (disguisePlayer != null) {
+ sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Name: " + ChatColor.RESET + disguisePlayer.getDisguiseName());
+ sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Skin: " + ChatColor.WHITE + ChatColor.stripColor((profile != null ? profile.getDisplayName() : disguisePlayer.getDisguiseSkin())));
+ sender.sendMessage(ChatColor.GRAY.toString() + ' ' + "*" + ' ' + ChatColor.GOLD + "Disguise Rank: " + disguisePlayer.getDisguiseRank().getColor() + disguisePlayer.getDisguiseRank().getName());
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java
new file mode 100644
index 0000000..77e978a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/SkinCommand.java
@@ -0,0 +1,119 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.commands.disguise.menu.DisguiseSkinMenu;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.disguise.DisguisePlayerSkin;
+import rip.bridge.bridge.global.disguise.runnable.DisguiseRunnable;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.util.Tasks;
+import rip.bridge.bridge.global.util.mojang.GameProfileUtil;
+import rip.bridge.bridge.global.util.mojang.UUIDFetcher;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.nametag.FrozenNametagHandler;
+
+import java.util.*;
+
+public class SkinCommand {
+
+ @Command(names = {"skin"}, permission = "bridge.disguise", async = true, hidden = true)
+ public static void skin(Player player, @Param(name = "skin", defaultValue = "N/A") String skin) {
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+ Profile playerProfile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId());
+ Rank current = playerProfile.getCurrentGrant().getRank();
+
+ if (skin.equals("N/A")) {
+ skin = disguisePlayer != null ? disguisePlayer.getDisguiseName() : player.getName();
+ new DisguiseSkinMenu(skin, disguisePlayer != null ? disguisePlayer.getDisguiseRank() : current != null ? current : BridgeGlobal.getRankHandler().getDefaultRank(), true, true).openMenu(player);
+ return;
+ }
+
+ if (disguisePlayer != null) {
+ disguisePlayer.setDisguiseSkin(skin);
+
+ GameProfile profile = GameProfileUtil.getSkinCache().get(skin.toLowerCase());
+
+ if (profile == null) {
+ Map fetched = null;
+
+ try {
+ fetched = new UUIDFetcher(Collections.singletonList(skin)).call();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Optional fetchedUuid = Objects.requireNonNull(fetched).values().stream().findFirst();
+ if (!fetchedUuid.isPresent()) {
+ player.sendMessage(ChatColor.RED + "Skin by that name doesn't exist.");
+ return;
+ }
+
+ profile = GameProfileUtil.loadGameProfile(fetchedUuid.get(), skin);
+ }
+
+ DisguisePlayerSkin fakeSkin = BridgeGlobal.getDisguiseManager().setupDisguiseSkin(profile);
+
+ if (fakeSkin == null) {
+ player.sendMessage(ChatColor.RED + "Failed to setup skin.");
+ return;
+ }
+
+ disguisePlayer.setFakeSkin(fakeSkin);
+
+ Tasks.run(new DisguiseRunnable(player, profile, disguisePlayer.getDisguiseName()));
+
+ Tasks.run(() -> {
+ FrozenNametagHandler.reloadPlayer(player);
+ FrozenNametagHandler.reloadOthersFor(player);
+ });
+ Rank rank = disguisePlayer.getDisguiseRank();
+ String nickName = disguisePlayer.getDisguiseName();
+ player.sendMessage(ChatColor.GREEN + "Success! You now look like " + rank.getPrefix() + rank.getColor() + nickName + ChatColor.GREEN + (!nickName.equals(skin) && !nickName.equals(ChatColor.stripColor(skin)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skin) + ChatColor.GREEN + ")" : "") + "!");
+
+ String realName = GameProfileUtil.getRealName(nickName);
+ if (realName != null) {
+ player.sendMessage(ChatColor.RED + nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked.");
+ }
+
+ String realSkin = GameProfileUtil.getRealName(skin);
+ String finalSkin = skin;
+ if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(finalSkin)) || skin.equals("Steve") || skin.equals("Alex")) {
+ player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist.");
+ }
+ } else {
+ try {
+ disguisePlayer = new DisguisePlayer(player.getName());
+
+ disguisePlayer.setDisguiseRank(current != null ? current : BridgeGlobal.getRankHandler().getDefaultRank());
+ disguisePlayer.setDisguiseName(player.getName());
+ disguisePlayer.setDisguiseSkin(skin);
+
+ Rank rank = disguisePlayer.getDisguiseRank();
+ String nickName = disguisePlayer.getDisguiseName();
+
+ if (BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null, false, true, false)) {
+ player.sendMessage(ChatColor.GREEN + "Success! You now look like " + rank.getPrefix() + rank.getColor() + nickName + ChatColor.GREEN + (!nickName.equals(skin) && !nickName.equals(ChatColor.stripColor(skin)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skin) + ChatColor.GREEN + ")" : "") + "!");
+
+ String realName = GameProfileUtil.getRealName(nickName);
+ if (realName != null) {
+ player.sendMessage(ChatColor.RED + nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked.");
+ }
+
+ String realSkin = GameProfileUtil.getRealName(skin);
+ String finalSkin = skin;
+ if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(finalSkin)) || skin.equals("Steve") || skin.equals("Alex")) {
+ player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist.");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer.");
+ }
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java
new file mode 100644
index 0000000..0222fe1
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/TagCommand.java
@@ -0,0 +1,67 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.nametag.FrozenNametagHandler;
+
+public class TagCommand {
+
+ @Command(names = {"tag"}, permission = "bridge.disguise", async = true, hidden = true)
+ public static void tag(Player player, @Param(name = "rank") String rank) {
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId());
+
+ Rank current = profile.getCurrentGrant().getRank();
+ Rank select = BridgeGlobal.getRankHandler().getRankByName(rank);
+
+ if (rank.equalsIgnoreCase("clear")) {
+ select = current;
+ BridgeGlobal.getDisguiseManager().undisguise(player, false, false);
+ }
+
+ if (select == null) {
+ select = BridgeGlobal.getRankHandler().getDefaultRank();
+ }
+
+ if (select.getPriority() > current.getPriority()) {
+ player.sendMessage(ChatColor.RED + "You are not allowed to set your tag to " + select.getColor() + select.getDisplayName() + ChatColor.RED + ".");
+ return;
+ }
+
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+
+ if (disguisePlayer != null) {
+ disguisePlayer.setDisguiseRank(select);
+
+ player.setPlayerListName(select.getColor() + disguisePlayer.getDisguiseName());
+ player.setDisplayName(select.getColor() + disguisePlayer.getDisguiseName());
+ player.setCustomName(select.getColor() + disguisePlayer.getDisguiseName());
+ profile.updateColor();
+ profile.saveProfile();
+
+ BridgeGlobal.getDisguiseManager().save(player.getUniqueId(), false);
+ } else {
+ try {
+ disguisePlayer = new DisguisePlayer(player.getName());
+ disguisePlayer.setDisguiseRank(select);
+ disguisePlayer.setDisguiseName(player.getName());
+ disguisePlayer.setDisguiseSkin(player.getName());
+
+ BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null,false, false, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer.");
+ }
+ }
+
+ FrozenNametagHandler.reloadPlayer(player);
+ FrozenNametagHandler.reloadOthersFor(player);
+
+ player.sendMessage(ChatColor.GREEN + "Setting your tag to " + select.getColor() + select.getDisplayName() + ChatColor.GREEN + "...");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java
new file mode 100644
index 0000000..2506a92
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnDisguiseCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.qlib.command.Command;
+
+public class UnDisguiseCommand {
+
+ @Command(names = {"undisguise", "undis", "ud", "unnick", "und"}, permission = "bridge.disguise", description = "Reveal yourself once again!", hidden = true)
+ public static void undisguise(Player player) {
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+
+ if (disguisePlayer == null) {
+ player.sendMessage(ChatColor.RED + "You're not disguised!");
+ return;
+ }
+
+ player.sendMessage(ChatColor.GREEN + "Removing the disguise...");
+ BridgeGlobal.getDisguiseManager().undisguise(player, true, false);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java
new file mode 100644
index 0000000..45682cf
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/UnTagCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.disguise;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.qlib.command.Command;
+
+public class UnTagCommand {
+
+ @Command(names = {"untag"}, permission = "bridge.disguise", hidden = true)
+ public static void untag(Player player) {
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+
+ if (disguisePlayer == null) {
+ player.sendMessage(ChatColor.RED + "You're not tagged!");
+ return;
+ }
+
+ player.sendMessage(ChatColor.GREEN + "Removing the tag...");
+ BridgeGlobal.getDisguiseManager().undisguise(player, true, false);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java
new file mode 100644
index 0000000..23ac2a4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileCreateCommand.java
@@ -0,0 +1,38 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+import java.util.regex.Pattern;
+
+public class DisguiseProfileCreateCommand {
+
+ @Command(names = {"disguiseprofile create"}, permission = "bridge.disguise.admin", description = "Create a disguise profile", hidden = true)
+ public static void disguise(Player player, @Param(name = "name") String name, @Param(name = "skin") String skin) {
+ if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) {
+ player.sendMessage(ChatColor.RED + "That is not a valid username.");
+ return;
+ }
+
+ if (!Pattern.compile("^\\w{1,16}$").matcher(skin).matches()) {
+ player.sendMessage(ChatColor.RED + "That is not a valid skin.");
+ return;
+ }
+
+ boolean added = BridgeGlobal.getDisguiseManager().addProfile(name, skin);
+
+ if (!added) {
+ player.sendMessage(ChatColor.RED + "Failed to add disguise profile with name " + name + " and skin " + skin + '.');
+ return;
+ }
+
+ DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getProfile(name);
+
+ profile.setDisplayName(ChatColor.translateAlternateColorCodes('&', name));
+ player.sendMessage(ChatColor.GREEN + "You have created a disguise profile with name " + ChatColor.RESET + name + ChatColor.GREEN + " and skin " + ChatColor.RESET + skin + ChatColor.GREEN + '.');
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java
new file mode 100644
index 0000000..0e1e9e3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDeleteCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DisguiseProfileDeleteCommand {
+
+ @Command(names = {"disguiseprofile delete", "disguiseprofile remove"}, permission = "bridge.disguise.admin", description = "Remove disguise profiles", hidden = true)
+ public static void disguise(Player player, @Param(name = "name") String name) {
+ boolean removed = BridgeGlobal.getDisguiseManager().removeProfile(name);
+
+ if (!removed) {
+ player.sendMessage(ChatColor.RED + "Failed to remove disguise profile with name " + name + '.');
+ return;
+ }
+
+ player.sendMessage(ChatColor.GREEN + "You have deleted a disguise profile with name " + ChatColor.RESET + name + ChatColor.GREEN + '.');
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java
new file mode 100644
index 0000000..02a3bd4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileDisguiseCommand.java
@@ -0,0 +1,89 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+public class DisguiseProfileDisguiseCommand {
+
+ @Command(names = {"disguiseprofile disguise"}, permission = "bridge.disguise.admin", description = "Disguise other players", hidden = true)
+ public static void odisguise(Player sender, @Param(name = "player") String playerName, @Param(name = "rank") String rank, @Param(name = "name") String name, @Param(name = "skin") String skin) {
+ Player player = Bukkit.getPlayer(playerName);
+
+ if (player == null) {
+ for (DisguisePlayer disguisePlayer : BridgeGlobal.getDisguiseManager().getDisguisePlayers().values()) {
+ if (playerName.equalsIgnoreCase(disguisePlayer.getName())) {
+ Player dPlayer = Bukkit.getPlayer(disguisePlayer.getDisguiseName());
+
+ if (dPlayer != null) {
+ sender.sendMessage(ChatColor.RED + "That player is already disguised.");
+ return;
+ }
+ }
+ }
+ }
+
+ if (player == null) {
+ sender.sendMessage("§cNo player with the name" + " \"" + name + "\" found.");
+ return;
+ }
+
+ if (!Pattern.compile("^\\w{1,16}$").matcher(name).matches()) {
+ player.sendMessage(ChatColor.RED + "Invalid username: " + name);
+ return;
+ }
+
+ if (Bukkit.getPlayerExact(name) != null || Objects.requireNonNull(BridgeGlobal.getUsedDisguisedNames()).stream().anyMatch(n -> n.equalsIgnoreCase(name))) {
+ player.sendMessage(ChatColor.RED + "The name \"" + name + "\" is unavailable.");
+ return;
+ }
+
+ if (BukkitAPI.getProfile(name) != null && BukkitAPI.getPlayerRank(BukkitAPI.getProfile(name)).isStaff()) {
+ sender.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name.");
+ return;
+ }
+
+ if (BukkitAPI.getProfile(name) != null) {
+ sender.sendMessage(ChatColor.RED + name + " exists as a Bridge player. You cannot impersonate others, please choose another name.");
+ return;
+ }
+
+ if (!Pattern.compile("^\\w{1,16}$").matcher(skin).matches()) {
+ sender.sendMessage(ChatColor.RED + "That is not a valid username.");
+ return;
+ }
+
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(sender.getUniqueId());
+ Rank current = profile.getCurrentGrant().getRank();
+ Rank select = BridgeGlobal.getRankHandler().getRankByName(rank);
+
+ if (select.getPriority() > current.getPriority()) {
+ sender.sendMessage(ChatColor.RED + "You are not allowed to set " + playerName + "'s tag to " + select.getColor() + select.getDisplayName() + ChatColor.RED + ".");
+ return;
+ }
+
+ DisguisePlayer disguisePlayer = new DisguisePlayer(player.getName());
+ disguisePlayer.setDisguiseRank(select);
+ disguisePlayer.setDisguiseName(name);
+ disguisePlayer.setDisguiseSkin(skin);
+
+ try {
+ if (BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, null,false, true, false)) {
+ player.sendMessage(ChatColor.GREEN + "You have been manually disguised by a staff member.");
+ player.sendMessage(ChatColor.GREEN + "Success! You now look like " + select.getPrefix() + select.getColor() + name + ChatColor.GREEN + " (in the skin of " + ChatColor.YELLOW + skin + ChatColor.GREEN + ")!");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java
new file mode 100644
index 0000000..2a54211
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileInfoCommand.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DisguiseProfileInfoCommand {
+
+ @Command(names = {"disguiseprofile info"}, permission = "bridge.disguise.admin", description = "Get information about a disguise profile", hidden = true)
+ public static void disguiseprofileinfo(CommandSender s, @Param(name = "name") DisguiseProfile disguiseProfile) {
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage(disguiseProfile.getDisplayName() + " Disguise Profile §7❘ §fInformation");
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage("§6Name: §f" + disguiseProfile.getName() + " §7(" + net.md_5.bungee.api.ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + net.md_5.bungee.api.ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Skin: §f" + disguiseProfile.getSkinName());
+ s.sendMessage("");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java
new file mode 100644
index 0000000..0e55643
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileListCommand.java
@@ -0,0 +1,52 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.qlib.command.Command;
+
+import java.util.ArrayList;
+
+public class DisguiseProfileListCommand {
+
+ @Command(names = {"disguiseprofile list"}, permission = "bridge.disguise.admin", description = "List all created disguise profiles", hidden = true)
+ public static void disguiseprofilelist(CommandSender s) {
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage("§6§lDisguise Profiles §f(" + BridgeGlobal.getDisguiseManager().getDisguiseProfiles().size() + ")");
+ s.sendMessage(BukkitAPI.LINE);
+ if (BridgeGlobal.getDisguiseManager().getDisguiseProfiles().isEmpty()) {
+ s.sendMessage(ChatColor.RESET + "No disguise profiles were created yet");
+ } else {
+ ArrayList disguiseProfiles = new ArrayList<>(BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values());
+
+ disguiseProfiles.forEach(disguiseProfile -> {
+ if (s instanceof Player) {
+
+ ComponentBuilder cp = new ComponentBuilder(disguiseProfile.getDisplayName() + " §7❘ §f" + disguiseProfile.getName()).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(
+ "§6Name: §f" + disguiseProfile.getName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")" + "\n" +
+ "§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")" + "\n" +
+ "§6Skin: §f" + disguiseProfile.getSkinName() + "\n\n" +
+ "§7§oClick for more information"
+ ))).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/disguiseprofile info " + disguiseProfile.getName()));
+ ((Player) s).spigot().sendMessage(cp.create());
+ } else {
+ s.sendMessage(disguiseProfile.getDisplayName() + " §7❘ §f" + disguiseProfile.getName());
+ s.sendMessage("§6Name: §f" + disguiseProfile.getName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Display Name: §f" + disguiseProfile.getDisplayName() + " §7(" + ChatColor.stripColor(disguiseProfile.getDisplayName().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Skin: §f" + disguiseProfile.getSkinName());
+ s.sendMessage("");
+ }
+ });
+ s.sendMessage("");
+ s.sendMessage(s instanceof Player ? "§7§oHover over the disguise profiles for more information." : "§7§oType /disguise profileinfo for more information.");
+ s.sendMessage(BukkitAPI.LINE);
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java
new file mode 100644
index 0000000..dbf217d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileSetDisplayNameCommand.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DisguiseProfileSetDisplayNameCommand {
+
+ @Command(names = {"disguiseprofile setdisplayname"}, permission = "bridge.disguise.admin", description = "Set a disguise profile display name", hidden = true)
+ public static void disguised(Player player, @Param(name = "name") String name, @Param(name = "displayName", wildcard = true) String displayName) {
+ DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getProfile(name);
+
+ profile.setDisplayName(ChatColor.translateAlternateColorCodes('&', displayName));
+ BridgeGlobal.getDisguiseManager().saveProfiles(true);
+ player.sendMessage(ChatColor.GREEN + "You've changed display name of " + ChatColor.RESET + profile.getName() + ChatColor.GREEN + " to " + displayName + ChatColor.GREEN + '.');
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java
new file mode 100644
index 0000000..522c784
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/disguiseprofile/DisguiseProfileUnDisguiseCommand.java
@@ -0,0 +1,28 @@
+package rip.bridge.bridge.bukkit.commands.disguise.disguiseprofile;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DisguiseProfileUnDisguiseCommand {
+
+ @Command(names = {"disguiseprofile undisguise"}, permission = "bridge.undisguise.admin", description = "UnDisguise other players", hidden = true)
+ public static void undisguiseprofile(Player player, @Param(name = "player") Player target) {
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(target.getUniqueId());
+ Profile target2 = BridgeGlobal.getProfileHandler().getProfileByUUID(target.getUniqueId());
+
+ if (disguisePlayer == null) {
+ player.sendMessage(ChatColor.RED + target2.getUsername() + " is not disguised!");
+ return;
+ }
+
+ player.sendMessage(ChatColor.GREEN + "You have removed the disguise of " + target2.getColor() + target2.getUsername() + ChatColor.GREEN + ".");
+ target.sendMessage(ChatColor.RED + "You have been manually undisguised by a staff member.");
+ target.sendMessage(ChatColor.GREEN + "Removing the disguise...");
+ BridgeGlobal.getDisguiseManager().undisguise(target, true, false);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java
new file mode 100644
index 0000000..01b0255
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseRankMenu.java
@@ -0,0 +1,99 @@
+package rip.bridge.bridge.bukkit.commands.disguise.menu;
+
+import com.google.common.collect.Maps;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.LeatherArmorMeta;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.grant.menu.grant.RankButton;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class DisguiseRankMenu extends Menu {
+
+ private String nickName;
+ private boolean real;
+
+ public DisguiseRankMenu(String nickName, boolean real) {
+ super(ChatColor.DARK_GRAY + "Pick a rank");
+
+ this.nickName = nickName;
+ this.real = real;
+ this.setPlaceholder(true);
+ }
+
+ @Override
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+
+ List ranks = BridgeGlobal.getRankHandler().getRanks().stream()
+ .filter(rank -> {
+ Profile profile = BukkitAPI.getProfile(player);
+ if(rank.isHidden() || !rank.isGrantable()) return false;
+ if(profile.hasPermission("bridge.disguise.all")) return true;
+ if(profile.hasPermission("bridge.disguise." + rank.getName().toLowerCase())) return true;
+ return Objects.requireNonNull(BukkitAPI.getPlayerRank(profile, true)).getPriority() >= rank.getPriority();
+ })
+ .sorted(Comparator.comparingInt(Rank::getPriority))
+ .collect(Collectors.toList());
+
+ int slot = 1;
+ for(Rank rank : ranks) {
+ buttons.put(slot, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return rank.getColor() + rank.getDisplayName();
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.LEATHER_CHESTPLATE;
+ }
+
+ @Override
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack item = super.getButtonItem(player);
+ LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
+ meta.setColor(RankButton.getColor(rank.getColor().charAt(1)).getColor());
+ item.setItemMeta(meta);
+ return item;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+ new DisguiseSkinMenu(nickName, rank, false, real).openMenu(player);
+ }
+ });
+
+ slot += slot == 7 || slot == 16 || slot == 25 || slot == 34
+ || slot == 43 || slot == 52 || slot == 61 || slot == 70 ? 3 : 2;
+ }
+
+ return buttons;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java
new file mode 100644
index 0000000..20346bd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/disguise/menu/DisguiseSkinMenu.java
@@ -0,0 +1,464 @@
+package rip.bridge.bridge.bukkit.commands.disguise.menu;
+
+import com.google.common.collect.Maps;
+import lombok.RequiredArgsConstructor;
+import net.minecraft.server.v1_7_R4.GameProfileSerializer;
+import net.minecraft.server.v1_7_R4.NBTTagCompound;
+import net.minecraft.util.com.mojang.authlib.GameProfile;
+import net.minecraft.util.com.mojang.authlib.properties.Property;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.util.mojang.GameProfileUtil;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+import rip.bridge.qlib.util.ItemBuilder;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+@RequiredArgsConstructor
+public class DisguiseSkinMenu extends PaginatedMenu {
+
+ private final String nickName;
+ private final Rank rank;
+ private final boolean skinCmd;
+ private final boolean real;
+
+ private static final GameProfile QUESTION_MARK_SKIN, STEVE_SKIN, ALEX_SKIN, DSKIN;
+
+ static {
+ QUESTION_MARK_SKIN = new GameProfile(UUID.randomUUID(), "__Q_MARK__");
+ QUESTION_MARK_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYzMjM1NTQwMTk5MSwKICAicHJvZmlsZUlkIiA6ICJkNTI0NjJmOTZlZjA0OThmODhhYzg4ZDI3ZjMyOGEzMCIsCiAgInByb2ZpbGVOYW1lIiA6ICJuaWd3YWciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ViYjQ3YTY1NDcyYjI4MjRmNDNjNDY0Yzc0NmI2Y2I3NGNmYmU5NWJkODk1MTM2Yjg3MWQ3ZTk3ZGM1NDY4MyIKICAgIH0sCiAgICAiQ0FQRSIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjM0MGMwZTAzZGQyNGExMWIxNWE4YjMzYzJhN2U5ZTMyYWJiMjA1MWIyNDgxZDBiYTdkZWZkNjM1Y2E3YTkzMyIKICAgIH0KICB9Cn0=", "jCNxGyWZtXrpgp9iA9z9/cpAkPcbXUz3QyQbBL9y58QaAvwpCC5t/0UReOBppIwS3Kye5JNf4W/sgk37+dSwej9ioiXAGQNQo56jCqaioaq4kKlaFls+dgbw2AJticzWsJicT70omH9O/NHV2kLP1RxPSQBQwkgnmmYBUtMYENf5S/zzUddZtbr3g0G5elpgwGuDaIJiNNdNTGwatUNfUlNLV/a9Z1nAniwfOUWul2U0tGTLnmrSyMLQe6auLyF/ddMneU1ecVTqjqUQZ8USOjva8N9tryRVGgkHujmMgd8zkOlU/FPxdLZeJoii4KQoSHznHx5IJplGvwEwUDR2cgNnzAzl7utMMRTC715TiLtcayqG3VJj1qRERt3uzDCBAidDcghwB+7GWkzZQ5Fq3P+pOGQdaOLyfiOoJojcKskPjAeGyLMq1rZd9VQ1RT/CuCCTgNhuIH8Ro4uyXXi18r63AMuHEhbzsD5wP+Okm6Z3SGzPJPOWQwQxHnmnO+6l11FZaMyJx68w90QCbmbiWXBDC89MVVLkl3rvUXmXKTr2N0HdjRY2uo4myqKugfR4ltT5jNMHLBy2yAg/dt/RminWB3SFbqFaK9iNam2XpOBW+q9Ihrmd81dfLhl663ORN+ikkiZzO2AZozvWCNx36snAPpMeBhs4f4Aehux+DH4="));
+
+ GameProfileUtil.getSkinCache().put(QUESTION_MARK_SKIN.getName().toLowerCase(), QUESTION_MARK_SKIN);
+
+ DSKIN = new GameProfile(UUID.randomUUID(), "__D_SKIN__");
+ DSKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTgwNjE3MDgyNSwKICAicHJvZmlsZUlkIiA6ICIzY2FjYjhkY2YyMzk0ZDgwOTZiMWIyMmUzNjQ2MDlmYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJjcmVlcGVyX2dvZDIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE2ZTRjNTY1NDhiZmM0NjRmZGQ1NmJkMGViMmE2NGEzZWNiMTY4MWVhMDk5MWM0ZWY3NzFmNmQxMThiNGMzYyIKICAgIH0KICB9Cn0=", "FpKriqMG97l8aCmUfsa0Dq8ArVPCFiw6Mt2HwIwxHKUXKfhEK074MyeZwV5MQKaK/kEkqgYrCVK1Upm4y+SIp1znmoz9Qdb9lfdctXwznjwNW6x60qP9u5Wadg9T2CBw3KkogSTlFJpeiKnOb9bT4IezQgu8fL1Or5yX5LGkxrcZpDpCGJgENmLPdwoSaZxfZbOEnEGKRNrhqnPm29ScuUAf3JtQGccElXlJ4wBH02ZbuoFA75mnbCMixNmgiBpBIhqzAq7at+YrFqU1Nn6MYokFP91EbQvfxHP9vNN5ANJVDuhUPHNAvwK3M4XYthJ01Vm0oCRO/WqKDZCepV5j3pAZHKGA9ubeKAA2zTWwILxjgx1BaKBYO9idTdhI5RgsK78hg2ICD6ySZ7S+WFLYx7gTHSgp+TFaMsqeHHy5XGUHFUj7FOAktTu/lMs9KjK8n1FM5V3JDvAU5c7xuuErQ3HoYc5wO+Wm2gj9i5LBucU9qWlVSO51W1guwTSD9U8kzuw8Z4xoikF6of0/ZtmMjUneOGnzDqV2wNKnDbV/V5ASSVDjERvQCyK44YS1w9oO/p3ROjdhuN+JWP4zPCmfFdDxhgLcEhrTBcm7kBNx+b6agudfz4i6i7dAPN2W5AZ2RKbc60kkJncxtgfvfLk3Gw1j8TLAT1EjyDnhcMRitXY="));
+
+ STEVE_SKIN = new GameProfile(UUID.randomUUID(), "Steve");
+ STEVE_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTYxMTkyMjAyNywKICAicHJvZmlsZUlkIiA6ICJiOTgzZmU5YWJjMWI0MTkwYjIxZTUxZmU0Yjg3OTcxNCIsCiAgInByb2ZpbGVOYW1lIiA6ICI5Z3lhciIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82ZDNiMDZjMzg1MDRmZmMwMjI5Yjk0OTIxNDdjNjlmY2Y1OWZkMmVkNzg4NWY3ODUwMjE1MmY3N2I0ZDUwZGUxIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=", "nquy5XsHlcsQn0QTFW0vOVnodhCizG3VlfPtqgkqmTliNsuWd+GxdUV6u00eOhmYrkHOtD52eWF0tYG+j/BYUBwE2SvZHt3V7OjAO3OzMy8sNzuyymEfzoqFXB2+IBAAbWi54TZHI4l03wtDFuUNBhPZ/q0h9KmasFv8zTfCht+TEThmp7gjCkmAs6Tkr1jqAQyQfCQCQwBN0a8Rx0NzsGJAOvQFmfdksxuLzckR8abt9Qb39QXulFAKqkNoVYajvRxG21WTELgJEM+nuVInt0QT91t6Al1E7xExCbrOJITomk2CLAHSJzTx0QBYmKMbPeuXcR1jT50FA4qzqY5LsmmVWb1PkaucFQ2+tHHKncNg44XMju2PaNNLFek39AhOp4FnyLHBK5RuCJEcv0ybcNyCxFmKBSb5Ryv+XxsQQjzcT0fSc5png0NvBVknk4KnWkuimMJp84nBSzJ9htS38mOZWdFcj61ulqk99+7wJfqO8OgtOlfn4Hpk6rbVcFtARnW8TQIPcNzX6/B385fARO5VwFmts7UVxRGenQOJwzbezGPKBTfQyODpPxX2DYTR4v8fGfVpaO3ZReq0vDLvl/x5CpyFISJhorfZSIiAXJeRRKj8qHr6eM1lqzkzwu6tUV8nITzg/QxVuOddik01HJritR/iTgfrCQNI2fjhJY8="));
+
+ GameProfileUtil.getSkinCache().put(STEVE_SKIN.getName().toLowerCase(), STEVE_SKIN);
+
+ ALEX_SKIN = new GameProfile(UUID.randomUUID(), "Alex");
+ ALEX_SKIN.getProperties().put("textures", new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTYwNTYxMTgxNjQ1NiwKICAicHJvZmlsZUlkIiA6ICIwNDQ4NzNiYTMzZDI0Y2Q4YTQ1M2M4ODkwYTFjODM4MCIsCiAgInByb2ZpbGVOYW1lIiA6ICJMQVNEIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzNiNjBhMWY2ZDU2MmY1MmFhZWJiZjE0MzRmMWRlMTQ3OTMzYTNhZmZlMGU3NjRmYTQ5ZWEwNTc1MzY2MjNjZDMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==", "u0w6ba9InsC1Nj1xRxO5Jl6XsiuKEP0oMDQEBGoEEZJ8+thETE2Ics2lRY0jTKkboJV+7FwJunkYCJyoR6sRKYsXW6z5FOxsvCu9biAwIEcmRXljBUnIMzhefCqovZJ07AjA0rM8aKSH9V47BbpfGzBgSaLukdem0VpvV4LfZFIGTvqEZD6QnlYDQUJNEDaIac1X4xOJlPXzXV0d7EwSZSa6zKv6nswgbsp3aWleJoUoXhjqB3Em5wbdJbbvDdr0v7PPPYVzgS2sqD+RpUap21jG8teb4Wan4qjZQLTbmRxJE68IMaaylygwJFinxViZw3ubV7uTz26BSAhvOQ2wLpcNtTqqr+8atIA1+C5ijhBmQLEH6U2aYb7K+qF83YhxTzFeeoHcdoDNHC+7LDgEFEnM0hpIuHPTho2uTJtvAHx2iuLd/Kzau+EFyZDlKHowN7UW6LwNXRldTPr5DHBEuAMTiSGBivYZi778Hx8b3fpb6I7rUN5o4l3RdktCPlrElPnmEYXBGH+4ZLkeNxajCMxvm0WJFEouQcpnxKmON4z9Q6bduFdSqgm+huGACPhMG41J2f6fsnTOFKQDluyekF1ur3KoNCdqEYMDqXHmSobRaaKhvoclQuO1oxjFkFAiKox5cOAOf+pmhwbgq9a26n6MzvYvLb+tVXkbN9V6ewQ="));
+
+ GameProfileUtil.getSkinCache().put(ALEX_SKIN.getName().toLowerCase(), ALEX_SKIN);
+ }
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ return ChatColor.DARK_GRAY + "Pick a skin";
+ }
+
+ @Override
+ public int getMaxItemsPerPage(Player player) {
+ return 36;
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ HashMap buttons = Maps.newHashMap();
+
+ int slot = 0;
+ for(DisguiseProfile profile : BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values()) {
+ buttons.put(slot++, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : ChatColor.BLUE + profile.getName())
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+
+ GameProfile gameProfile = GameProfileUtil.getSkinCache().get(profile.getName().toLowerCase());
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ if (gameProfile == null) {
+ gameProfile = new GameProfile(profile.getSkin().getProfileUuid(), profile.getName());
+ gameProfile.getProperties().put("textures", profile.getSkin().getProperty());
+ GameProfileUtil.getSkinCache().put(profile.getName().toLowerCase(), gameProfile);
+ }
+
+ GameProfileSerializer.serialize(nbtTagCompound, gameProfile);
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+ disguise(player, rank, profile.getSkinName(), nickName, profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : profile.getSkinName(), profile.getName());
+ }
+ });
+ }
+
+ return buttons;
+ }
+
+ @Override
+ public Map getGlobalButtons(Player player) {
+ HashMap buttons = Maps.newHashMap();
+
+ buttons.put(1, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(ChatColor.BLUE + "Your Own")
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+
+ GameProfileSerializer.serialize(nbtTagCompound, ((CraftPlayer) player).getProfile());
+
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(player.getUniqueId());
+ disguise(player, rank, player.getName(), nickName, disguisePlayer != null ? disguisePlayer.getName() : player.getName());
+ }
+ });
+
+ buttons.put(2, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(ChatColor.BLUE + "Random")
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+ GameProfileSerializer.serialize(nbtTagCompound, QUESTION_MARK_SKIN);
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+
+ DisguiseProfile profile = BridgeGlobal.getDisguiseManager().getRandomDisguiseProfile();
+
+ if(profile == null) {
+ player.sendMessage(ChatColor.RED + "Failed to find random disguise profile.");
+ return;
+ }
+
+ disguise(player, rank, profile.getSkinName(), nickName, profile.getDisplayName() != null ? ChatColor.translateAlternateColorCodes('&', profile.getDisplayName()) : profile.getSkinName());
+ }
+ });
+
+ buttons.put(3, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.BLUE + "Pick a Name";
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.SIGN;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance())
+ .withModality(true)
+ .withPrefix(new NullConversationPrefix())
+ .withFirstPrompt(new StringPrompt() {
+
+ @Override
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Enter a name of a player using your desired skin:";
+ }
+
+ @Override
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if(!Pattern.compile("^\\w{1,16}$").matcher(input).matches()) {
+ player.sendMessage(ChatColor.RED + "Invalid username: " + input);
+
+ String realName = GameProfileUtil.getRealName(input);
+
+ new DisguiseSkinMenu(nickName, rank, skinCmd, realName != null).openMenu(player);
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ disguise(player, rank, input, nickName, input);
+ return Prompt.END_OF_CONVERSATION;
+ }
+ })
+
+ .withLocalEcho(false)
+ .withEscapeSequence("/no")
+ .withTimeout(10)
+ .thatExcludesNonPlayersWithMessage("Go away evil console!");
+
+ player.beginConversation(factory.buildConversation(player));
+ }
+ });
+
+ buttons.put(4, Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 7, " "));
+
+ buttons.put(5, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(ChatColor.BLUE + nickName)
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+ GameProfileSerializer.serialize(nbtTagCompound, DSKIN);
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+
+ int version = ((CraftPlayer) player).getHandle().playerConnection.networkManager.getVersion();
+
+ disguise(player, rank, real ? nickName : version == 47 ? ALEX_SKIN.getName() : STEVE_SKIN.getName(), nickName, nickName);
+ }
+ });
+
+ buttons.put(6, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(ChatColor.BLUE + "Steve")
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+ GameProfileSerializer.serialize(nbtTagCompound, STEVE_SKIN);
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+ disguise(player, rank, STEVE_SKIN.getName(), nickName, "Steve");
+ }
+ });
+
+ buttons.put(7, new Button() {
+
+ @Override
+ public String getName(Player player) {
+ return null;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return null;
+ }
+
+ @Override
+ public ItemStack getButtonItem(Player player) {
+ ItemStack stack = ItemBuilder.of(Material.SKULL_ITEM)
+ .data((short) 3)
+ .name(ChatColor.BLUE + "Alex")
+ .setLore(Collections.singletonList("")).build();
+
+ net.minecraft.server.v1_7_R4.ItemStack item = CraftItemStack.asNMSCopy(stack);
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+ GameProfileSerializer.serialize(nbtTagCompound, ALEX_SKIN);
+ NBTTagCompound itemNbtTag = item.getTag();
+ itemNbtTag.set("SkullOwner", nbtTagCompound);
+ stack = CraftItemStack.asCraftMirror(item);
+
+ return stack;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ Button.playSuccess(player);
+ disguise(player, rank, ALEX_SKIN.getName(), nickName, "Alex");
+ }
+ });
+
+ return buttons;
+ }
+
+ private void disguise(Player player, Rank rank, String skin, String name, String skinName) {
+ this.disguise(player, rank, skin, name, skinName, null);
+ }
+
+ private void disguise(Player player, Rank rank, String skin, String name, String skinName, String profileName) {
+ try {
+ // disguise(player, rank, player.getName(), nickName, disguisePlayer != null ? disguisePlayer.getName() : player.getName());
+ DisguisePlayer disguisePlayer = new DisguisePlayer(player.getName());
+ disguisePlayer.setDisguiseRank(rank);
+ disguisePlayer.setDisguiseName(name);
+ disguisePlayer.setDisguiseSkin(skin);
+
+ if(BridgeGlobal.getDisguiseManager().disguise(player, disguisePlayer, profileName,false, true, !this.skinCmd)) {
+ player.sendMessage(ChatColor.GREEN + "Success! You now look like " + this.rank.getPrefix() + this.rank.getColor() + this.nickName + ChatColor.GREEN + (!name.equals(skin) && !name.equals(ChatColor.stripColor(skinName)) ? " (in the skin of " + ChatColor.YELLOW + ChatColor.stripColor(skinName) + ChatColor.GREEN + ")" : "") + "!");
+
+ String realName = GameProfileUtil.getRealName(this.nickName);
+ if (realName != null) {
+ player.sendMessage(ChatColor.RED + this.nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked.");
+ }
+
+ String realSkin = GameProfileUtil.getRealName(skin);
+ if (realSkin == null && BridgeGlobal.getDisguiseManager().getDisguiseProfiles().values().stream().noneMatch(p -> p.getSkinName().equalsIgnoreCase(skin)) || skin.equals(STEVE_SKIN.getName()) || skin.equals(ALEX_SKIN.getName())) {
+ player.sendMessage(ChatColor.YELLOW + "Note: You will look like " + (skin.equals("Alex") ? "Alex" : "Steve") + " since the account \"" + skin + "\" does not exist.");
+ }
+
+ /*
+ String realName = GameProfileUtil.getRealName(this.nickName);
+ if (realName != null) {
+ player.sendMessage(ChatColor.RED + this.nickName + " is an existing Minecraft player, so if they log on for the first time as you're disguised, you will be kicked.");
+ } else {
+ String realSkin = GameProfileUtil.getRealName(skin);
+ if (realSkin != null) {
+ player.sendMessage(ChatColor.YELLOW + "Note: You will look like Steve since the account \"" + skin + "\" does not exist.");
+ }
+ }
+ */
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ player.sendMessage(ChatColor.RED + "Something went wrong while disguising you! Please contact a staff member or any online developer.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java
new file mode 100644
index 0000000..2617091
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateCommand.java
@@ -0,0 +1,27 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterCreatePacket;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.bridge.global.filter.FilterType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.xpacket.FrozenXPacketHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class FilterCreateCommand {
+ @Command(names = "filter create", permission = "bridge.filter", description = "Create a filter", hidden = true)
+ public static void create(CommandSender sender, @Param(name = "filterType") FilterType filterType, @Param(name = "pattern", wildcard = true) String pattern) {
+ Filter filter = BridgeGlobal.getFilterHandler().getFilter(pattern);
+ if (filter != null) {
+ sender.sendMessage(ChatColor.RED + "This filter already exists");
+ return;
+ }
+ (filter = new Filter(filterType, pattern)).save();
+ BridgeGlobal.getFilterHandler().addFilter(filter);
+ FrozenXPacketHandler.sendToAll(new FilterCreatePacket(filter, Bukkit.getServerName()));
+ sender.sendMessage(ChatColor.GREEN + "Successfully created the filter.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java
new file mode 100644
index 0000000..0d5b3c4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterCreateMuteCommand.java
@@ -0,0 +1,30 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterCreatePacket;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.bridge.global.filter.FilterType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.xpacket.FrozenXPacketHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class FilterCreateMuteCommand {
+
+ @Command(names = "filter create mute", permission = "bridge.filter", description = "Create a mute filter", hidden = true)
+ public static void create(CommandSender sender, @Param(name = "filterType") FilterType filterType, @Param(name = "duration") Long duration, @Param(name = "pattern", wildcard = true) String pattern) {
+ Filter filter = BridgeGlobal.getFilterHandler().getFilter(pattern);
+ if (filter != null) {
+ sender.sendMessage(ChatColor.RED + "This filter already exists");
+ return;
+ }
+
+ (filter = new Filter(filterType, pattern, duration)).save();
+ BridgeGlobal.getFilterHandler().addFilter(filter);
+ FrozenXPacketHandler.sendToAll(new FilterCreatePacket(filter, Bukkit.getServerName()));
+ sender.sendMessage(ChatColor.GREEN + "Successfully created the filter.");
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java
new file mode 100644
index 0000000..fb142de
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterDeleteCommand.java
@@ -0,0 +1,20 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterDeletePacket;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.xpacket.FrozenXPacketHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class FilterDeleteCommand {
+
+ @Command(names = "filter delete", permission = "bridge.filter", description = "Delete a filter", hidden = true)
+ public static void delete(CommandSender sender, @Param(name = "filter", wildcard = true) Filter filter) {
+ filter.delete();
+ FrozenXPacketHandler.sendToAll(new FilterDeletePacket(filter, Bukkit.getServerName()));
+ sender.sendMessage(ChatColor.GREEN + "Successfully deleted the filter.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java
new file mode 100644
index 0000000..662daf2
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterListCommand.java
@@ -0,0 +1,40 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.filter.FilterAction;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.command.Command;
+import mkremins.fanciful.FancyMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FilterListCommand {
+
+ @Command(names = "filter list", permission = "bridge.filter", description = "List all created filters", hidden = true)
+ public static void filter(CommandSender sender) {
+ sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34));
+ BridgeGlobal.getFilterHandler().getFilters().forEach(filter -> {
+ FancyMessage fancyMessage = new FancyMessage(ChatColor.RED + (isLong(filter.getPattern()) ? filter.getPattern().substring(0, 20) + "..." : filter.getPattern()));
+ if (isLong(filter.getPattern())) {
+ List lore = new ArrayList<>();
+ int index = 0;
+ while (index < filter.getPattern().length()) {
+ lore.add(filter.getPattern().substring(index, Math.min(index + 40, filter.getPattern().length())));
+ index += 40;
+ }
+ fancyMessage.tooltip(lore);
+ }
+ fancyMessage.then(ChatColor.GRAY + " - " + "[" + filter.getFilterType().name() + "]" + (filter.getFilterAction() == FilterAction.MUTE ? " - Mute: " + TimeUtil.millisToTimer(filter.getMuteTime()) : ""));
+ fancyMessage.send(sender);
+ });
+ sender.sendMessage(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34));
+ }
+
+ private static boolean isLong(String filter) {
+ return filter.length() > 20;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java
new file mode 100644
index 0000000..7df1f76
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/FilterTestCommand.java
@@ -0,0 +1,25 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.bridge.global.filter.FilterAction;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class FilterTestCommand {
+
+ @Command(names = "filter test", permission = "bridge.filter", description = "Test a filter", hidden = true)
+ public static void test(CommandSender sender, @Param(name = "message", wildcard = true) String message) {
+ Filter filter = BridgeGlobal.getFilterHandler().isViolatingFilter(message);
+ if(filter == null) {
+ sender.sendMessage(ChatColor.GREEN + "This message is not filtered.");
+ return;
+ }
+
+ sender.sendMessage(ChatColor.RED + "Your message currently flags for the filter: " + filter.getPattern());
+ if(filter.getFilterAction() == FilterAction.MUTE) sender.sendMessage(ChatColor.RED + "This message would of caused you to be muted for " + TimeUtil.millisToTimer(filter.getMuteTime()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java
new file mode 100644
index 0000000..cf3374a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/filter/ToggleFilterCommand.java
@@ -0,0 +1,37 @@
+package rip.bridge.bridge.bukkit.commands.filter;
+
+import lombok.Getter;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.command.Command;
+
+import java.util.*;
+
+public class ToggleFilterCommand {
+
+ @Getter
+ private final static Map filter = new HashMap<>();
+
+ @Command(names = "togglefilter", permission = "basic.staff", description = "Toggle filter alerts", hidden = true)
+ public static void toggle(Player player) {
+ String value = filter.getOrDefault(player.getUniqueId(), "global");
+ switch (value) {
+ case "global": {
+ filter.put(player.getUniqueId(), "server");
+ player.sendMessage(ChatColor.YELLOW + "You have now limited your filter messages to " + ChatColor.LIGHT_PURPLE + "local server" + ChatColor.YELLOW + ".");
+ return;
+ }
+
+ case "server": {
+ filter.put(player.getUniqueId(), "off");
+ player.sendMessage(ChatColor.RED + "You have disabled your filter messages.");
+ return;
+ }
+
+ case "off": {
+ filter.put(player.getUniqueId(), "global");
+ player.sendMessage(ChatColor.YELLOW + "You have now limited your filter messages to " + ChatColor.LIGHT_PURPLE + "global network" + ChatColor.YELLOW + ".");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java
new file mode 100644
index 0000000..276f7bb
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/ClearGrantsCommand.java
@@ -0,0 +1,27 @@
+package rip.bridge.bridge.bukkit.commands.grant;
+
+import mkremins.fanciful.FancyMessage;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+public class ClearGrantsCommand {
+
+ @Command(names = {"cleargrants"}, permission = "bridge.cleargrants", description = "Clear player's grants from the entire network", async = true)
+ public static void clearGrants(CommandSender s, @Param(name = "target") Profile target) {
+
+ if (target.getGrants().isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " does not have any grants.");
+ return;
+ }
+ s.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s grants.");
+ target.getGrants().clear();
+ target.saveProfile();
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java
new file mode 100644
index 0000000..908efbe
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantCommand.java
@@ -0,0 +1,15 @@
+package rip.bridge.bridge.bukkit.commands.grant;
+
+import rip.bridge.bridge.bukkit.commands.grant.menu.grant.RanksMenu;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.entity.Player;
+
+public class GrantCommand {
+
+ @Command(names = "grant", permission = "bridge.grant", description = "Add a grant to an player's account", async = true)
+ public static void grantCmd(Player p, @Param(name = "player") Profile target) {
+ new RanksMenu(target.getUsername(), target.getUuid()).openMenu(p);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java
new file mode 100644
index 0000000..a37b57a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/GrantsCommand.java
@@ -0,0 +1,43 @@
+package rip.bridge.bridge.bukkit.commands.grant;
+
+import mkremins.fanciful.FancyMessage;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.grant.menu.grants.GrantsMenu;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class GrantsCommand {
+
+ @Command(names = "grants", permission = "bridge.grants", description = "Check a player's grants", async = true)
+ public static void grantsCmd(Player sender, @Flag(value = {"w", "website"}, description = "Check a player's active grants through the website") boolean website, @Param(name = "player", extraData = "get") Profile profile) {
+
+ if (BukkitAPI.getPlayerRank(profile, true).getPriority() > BukkitAPI.getPlayerRank(sender, true).getPriority()) {
+
+ sender.sendMessage(ChatColor.RED + "You cannot view the grants of \"" + (profile.getDisguise() != null ? profile.getDisguise().getDisguiseName() : profile.getUsername()) + "\".");
+ return;
+ }
+
+ if (website) {
+ FancyMessage message = new FancyMessage(org.bukkit.ChatColor.GREEN + "[Click Here]" + org.bukkit.ChatColor.YELLOW + " to view all of " + profile.getUsername() + "'s grants");
+ message.tooltip(org.bukkit.ChatColor.GRAY + "Click here: https://www.bridge.rip/u/" + profile.getUsername() + "/grants").link("https://www.bridge.rip/u/" + profile.getUsername() + "/grants");
+ message.send(sender);
+ } else {
+ List allGrants = profile.getGrants().stream().filter(grant -> !grant.getRank().isDefaultRank()).sorted((first, second) -> {
+ if (first.getInitialTime() > second.getInitialTime()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }).collect(Collectors.toList());
+ new GrantsMenu(profile, allGrants).openMenu(sender);
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java
new file mode 100644
index 0000000..3d930e9
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/OGrantCommand.java
@@ -0,0 +1,30 @@
+package rip.bridge.bridge.bukkit.commands.grant;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.command.CommandSender;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class OGrantCommand {
+
+ @Command(names = {"ogrant"}, permission = "bridge.ogrant", description = "Add a grant to an player's account", async = true)
+ public static void consolegrantCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "rank") Rank r, @Param(name = "duration") String l, @Param(name = "scopes") String scope, @Param(name = "reason", wildcard = true) String reason) {
+ if (!r.isGrantable()) {
+ s.sendMessage("§cThis rank is not grantable.");
+ return;
+ }
+ List scopes = Arrays.asList(scope.split(","));
+ long length = (l.equalsIgnoreCase("Permanent") ? Long.MAX_VALUE : TimeUtil.parseTime(l));
+ pf.applyGrant(new Grant(r, length, scopes, reason, Profile.getConsoleProfile().getUuid().toString(), BridgeGlobal.getSystemName()), null);
+ pf.saveProfile();
+ s.sendMessage("§aSuccessfully granted " + pf.getUsername() + " the rank " + r.getDisplayName() + " on the scopes: " + StringUtils.join(scopes, ", "));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java
new file mode 100644
index 0000000..972afa3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantCreateEvent.java
@@ -0,0 +1,17 @@
+package rip.bridge.bridge.bukkit.commands.grant.events;
+
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.bukkit.util.BaseEvent;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.UUID;
+
+@AllArgsConstructor
+@Getter
+public class GrantCreateEvent extends BaseEvent {
+
+ private UUID uuid;
+ private Grant grant;
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java
new file mode 100644
index 0000000..87dbe40
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantRemoveEvent.java
@@ -0,0 +1,17 @@
+package rip.bridge.bridge.bukkit.commands.grant.events;
+
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.bukkit.util.BaseEvent;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.UUID;
+
+@AllArgsConstructor
+@Getter
+public class GrantRemoveEvent extends BaseEvent {
+
+ private UUID uuid;
+ private Grant grant;
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java
new file mode 100644
index 0000000..884b82c
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/events/GrantUpdateEvent.java
@@ -0,0 +1,17 @@
+package rip.bridge.bridge.bukkit.commands.grant.events;
+
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.bukkit.util.BaseEvent;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.UUID;
+
+@AllArgsConstructor
+@Getter
+public class GrantUpdateEvent extends BaseEvent {
+
+ private UUID uuid;
+ private Grant grant;
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java
new file mode 100644
index 0000000..3400140
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GlobalButton.java
@@ -0,0 +1,43 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.ImmutableList;
+import rip.bridge.qlib.menu.Button;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.List;
+
+public class GlobalButton extends Button {
+
+ private ScopesMenu parent;
+
+ public String getName(Player player) {
+ return ChatColor.BLUE + "Global";
+ }
+
+ public List getDescription(Player player) {
+ return ImmutableList.of();
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ return this.parent.isGlobal() ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ for (String key : this.parent.getStatus().keySet()) {
+ this.parent.getStatus().put(key, false);
+ }
+ this.parent.setGlobal(!this.parent.isGlobal());
+ }
+
+ public GlobalButton(ScopesMenu parent) {
+ this.parent = parent;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java
new file mode 100644
index 0000000..5569ac0
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/GrantButton.java
@@ -0,0 +1,84 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.grant.events.GrantCreateEvent;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.GrantCreatePacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.util.TimeUtils;
+import lombok.AllArgsConstructor;
+import net.md_5.bungee.api.ChatColor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@AllArgsConstructor
+public class GrantButton extends Button {
+ private Rank rank;
+ private String targetName;
+ private UUID targetUUID;
+ private String reason;
+ private ScopesMenu parent;
+ private List scopes;
+ private long duration;
+
+ public String getName(Player player) {
+ return ChatColor.GREEN + "Confirm and Grant";
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ description.add(ChatColor.BLUE + "Click to add the " + ChatColor.WHITE + this.rank.getColor() + this.rank.getDisplayName() + ChatColor.BLUE + " to " + ChatColor.WHITE + this.targetName + ChatColor.BLUE + ".");
+ if (this.parent.isGlobal()) {
+ description.add(ChatColor.BLUE + "This grant will be " + ChatColor.WHITE + "Global" + ChatColor.BLUE + ".");
+ }
+ else {
+ List scopes = new ArrayList<>(this.scopes);
+ description.add(ChatColor.BLUE + "This grant will apply on: " + ChatColor.WHITE + scopes.toString());
+ }
+ description.add(ChatColor.BLUE + "Reasoning: " + ChatColor.WHITE + this.reason);
+ description.add(ChatColor.BLUE + "Duration: " + ChatColor.WHITE + ((this.duration < Long.MAX_VALUE) ? TimeUtils.formatIntoDetailedString((int) (this.duration / 1000)) : "Permanent"));
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.DIAMOND_SWORD;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.grant(this.targetUUID, this.targetName, this.reason, this.scopes, this.rank, this.duration, player);
+ player.closeInventory();
+ }
+
+ private void grant(UUID user, String targetName, String reason, List scopes, Rank rank, long duration, Player sender) {
+ List finalScopes = (this.parent.isGlobal() || scopes.isEmpty() ? new ArrayList< >(Collections.singleton("Global")) : scopes.stream().map(s -> "GR-" + s).collect(Collectors.toList()));
+ Grant grant;
+ Profile pr = BukkitAPI.getProfile(user);
+ pr.applyGrant((grant=new Grant(rank, duration, finalScopes, reason, sender.getUniqueId().toString(), BridgeGlobal.getSystemName())), sender.getUniqueId());
+ pr.saveProfile();
+ PacketHandler.sendToAll(new GrantCreatePacket(grant, user, sender.getDisplayName(), BridgeGlobal.getSystemName()));
+ new GrantCreateEvent(pr.getUuid(), grant).call();
+ sender.sendMessage(ChatColor.GREEN + "Successfully granted " + ChatColor.WHITE + targetName + ChatColor.GREEN + " the " + ChatColor.WHITE + rank.getColor() + rank.getDisplayName() + ChatColor.GREEN + " rank.");
+ this.parent.setComplete(true);
+
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java
new file mode 100644
index 0000000..8844a45
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RankButton.java
@@ -0,0 +1,146 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.menu.Button;
+import lombok.AllArgsConstructor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.List;
+import java.util.UUID;
+
+@AllArgsConstructor
+public class RankButton extends Button
+{
+ private String targetName;
+ private UUID targetUUID;
+ private Rank rank;
+
+ public String getName(Player player) {
+ return this.rank.getColor() + this.rank.getDisplayName();
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ description.add(ChatColor.BLUE + "Click to grant " + ChatColor.WHITE + this.targetName + ChatColor.BLUE + " the " + ChatColor.WHITE + this.rank.getColor() + this.rank.getDisplayName() + ChatColor.BLUE + " rank.");
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ return getColor(this.rank.getColor().charAt(1)).getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Please type a reason for this grant to be added, or type " + ChatColor.RED + "cancel" + ChatColor.YELLOW + " to cancel.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if (input.equalsIgnoreCase("cancel")) {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Granting cancelled.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+ new BukkitRunnable() {
+ public void run() {
+ RankButton.this.promptTime(player, input);
+ }
+ }.runTask(Bridge.getInstance());
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+
+ private void promptTime(Player player, String reason) {
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Please type a duration for this grant, (\"perm\" for permanent) or type " + ChatColor.RED + "cancel" + ChatColor.YELLOW + " to cancel.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if (input.equalsIgnoreCase("cancel")) {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Granting cancelled.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+ long duration = TimeUtil.parseTime(input);
+ if (duration != -1L) {
+ new BukkitRunnable() {
+ public void run() {
+ new ScopesMenu(false, false, RankButton.this.rank, RankButton.this.targetName, RankButton.this.targetUUID, reason, duration).openMenu(player);
+ }
+ }.runTask(Bridge.getInstance());
+ return Prompt.END_OF_CONVERSATION;
+ }
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Invalid duration.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+
+ public static DyeColor getColor(char str) {
+ ChatColor color = ChatColor.getByChar(str);
+ switch (color) {
+ case DARK_BLUE:
+ case BLUE: {
+ return DyeColor.BLUE;
+ }
+ case DARK_GREEN: {
+ return DyeColor.GREEN;
+ }
+ case DARK_AQUA:
+ case AQUA: {
+ return DyeColor.CYAN;
+ }
+ case DARK_RED:
+ case RED: {
+ return DyeColor.RED;
+ }
+ case DARK_PURPLE: {
+ return DyeColor.PURPLE;
+ }
+ case GOLD: {
+ return DyeColor.ORANGE;
+ }
+ case GRAY:
+ case DARK_GRAY: {
+ return DyeColor.GRAY;
+ }
+ case GREEN: {
+ return DyeColor.LIME;
+ }
+ case LIGHT_PURPLE: {
+ return DyeColor.PINK;
+ }
+ case YELLOW: {
+ return DyeColor.YELLOW;
+ }
+ case WHITE: {
+ return DyeColor.WHITE;
+ }
+ default: {
+ return DyeColor.BLACK;
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java
new file mode 100644
index 0000000..dee6e22
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/RanksMenu.java
@@ -0,0 +1,65 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+import lombok.AllArgsConstructor;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@AllArgsConstructor
+public class RanksMenu extends Menu {
+
+ private String targetName;
+ private UUID targetUUID;
+
+ public String getTitle(Player player) {
+ return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Choose a Rank";
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ List ranks = this.getAllowedRanks(player);
+ for (int i = 0; i < ranks.size(); ++i) {
+ buttons.put(i, new RankButton(this.targetName, this.targetUUID, ranks.get(i)));
+ }
+ return buttons;
+ }
+
+ private List getAllowedRanks(Player player) {
+ List allRanks = new ArrayList<>(BridgeGlobal.getRankHandler().getRanks());
+ List ranks = Lists.newArrayList();
+ for (int i = 0; i < allRanks.size(); ++i) {
+ //if (i != 0) {
+ if(allRanks.get(i).isDefaultRank()) continue;
+ if (this.isAllowed(allRanks.get(i), player)) ranks.add(allRanks.get(i));
+ //}
+ }
+ ranks.sort((o1, o2) -> o2.getPriority() - o1.getPriority());
+ return ranks;
+ }
+
+ private boolean isAllowed(Rank rank, Player player) {
+ return BukkitAPI.getProfile(player).hasPermission("bridge.grant.create.*") || BukkitAPI.getProfile(player).hasPermission("bridge.grant.create." + rank.getName());
+ }
+
+ public void onClose(Player player) {
+ new BukkitRunnable() {
+ public void run() {
+ if (!Menu.currentlyOpenedMenus.containsKey(player.getName())) player.sendMessage(ChatColor.RED + "Granting cancelled.");
+ }
+ }.runTaskLater(Bridge.getInstance(), 1L);
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java
new file mode 100644
index 0000000..2d2713b
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopeButton.java
@@ -0,0 +1,53 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.Lists;
+import rip.bridge.qlib.menu.Button;
+import lombok.AllArgsConstructor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.List;
+
+@AllArgsConstructor
+public class ScopeButton extends Button {
+ private ScopesMenu parent;
+ private String scope;
+
+ public String getName(Player player) {
+ boolean status = this.parent.getStatus().get(this.scope);
+ return (status ? ChatColor.GREEN : ChatColor.RED) + this.scope;
+ }
+
+ public List getDescription(Player player) {
+ boolean status = this.parent.getStatus().get(this.scope);
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ if (status) {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.scope + ChatColor.BLUE + " from this grant's scopes.");
+ }
+ else {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.scope + ChatColor.BLUE + " to this grant's scopes.");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ boolean status = this.parent.getStatus().get(this.scope);
+ return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.parent.getStatus().put(this.scope, !this.parent.getStatus().getOrDefault(this.scope, false));
+ this.parent.setGlobal(false);
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java
new file mode 100644
index 0000000..f62fd1f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grant/ScopesMenu.java
@@ -0,0 +1,78 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grant;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+import lombok.Getter;
+import lombok.Setter;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+@Getter @Setter
+public class ScopesMenu extends Menu {
+
+ private Map status;
+ private boolean global;
+ private boolean complete;
+ private Rank rank;
+ private String targetName;
+ private UUID targetUUID;
+ private String reason;
+ private long duration;
+
+ public String getTitle(Player player) {
+ return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Select the Scopes";
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ List groups = Lists.newArrayList();
+ groups.addAll(BridgeGlobal.getServerHandler().getGroups());
+
+ int i = 0;
+ for (String scope : groups) {
+ if(scope == null) continue;
+ this.status.putIfAbsent(scope, false);
+ buttons.put(i, new ScopeButton(this, scope));
+ ++i;
+ }
+ List scopes = Lists.newArrayList();
+ scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList()));
+ buttons.put(22, new GlobalButton(this));
+ buttons.put(31, new GrantButton(this.rank, this.targetName, this.targetUUID, this.reason, this, scopes, this.duration));
+ return buttons;
+ }
+
+ public void onClose(Player player) {
+ new BukkitRunnable() {
+ public void run() {
+ if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !ScopesMenu.this.complete) {
+ player.sendMessage(ChatColor.RED + "Granting cancelled.");
+ }
+ }
+ }.runTaskLater(Bridge.getInstance(), 1L);
+ }
+
+ public ScopesMenu(boolean global, boolean complete, Rank rank, String targetName, UUID targetUUID, String reason, long duration) {
+ this.status = Maps.newHashMap();
+ this.global = false;
+ this.global = global;
+ this.complete = complete;
+ this.rank = rank;
+ this.targetName = targetName;
+ this.targetUUID = targetUUID;
+ this.reason = reason;
+ this.duration = duration;
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java
new file mode 100644
index 0000000..e869f05
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsButton.java
@@ -0,0 +1,129 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grants;
+
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.util.TimeUtils;
+import lombok.AllArgsConstructor;
+import net.md_5.bungee.api.ChatColor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.Date;
+import java.util.List;
+
+@AllArgsConstructor
+public class GrantsButton extends Button {
+
+ private Profile profile;
+ private Grant grant;
+
+ public String getName(Player player) {
+ return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.grant.getInitialTime()));
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ String by = this.grant.getGrantedBy();
+ description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + by);
+ description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.grant.getReason());
+ description.add(ChatColor.YELLOW + "Scopes: " + ChatColor.RED + (this.grant.getScope().isEmpty() ? "Global" : this.grant.getScope()));
+ description.add(ChatColor.YELLOW + "Rank: " + ChatColor.RED + this.grant.getRank().getDisplayName());
+ if (this.grant.isStillActive()) {
+ if (this.grant.getActiveUntil() != Long.MAX_VALUE) {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + TimeUtils.formatIntoDetailedString((int) ((this.grant.getActiveUntil() - System.currentTimeMillis()) / 1000)));
+ }
+ else {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ description.add(ChatColor.YELLOW + "This is a permanent grant.");
+ }
+ if (player.hasPermission("bridge.grant.remove." + this.grant.getRank())) {
+ description.add("");
+ description.add(ChatColor.RED.toString() + ChatColor.BOLD + "Click to remove");
+ description.add(ChatColor.RED.toString() + ChatColor.BOLD + "this grant");
+ }
+ }
+ else if (this.grant.isRemoved()) {
+ String removedBy = this.grant.getRemovedBy();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ description.add(ChatColor.RED + "Removed:");
+ description.add(ChatColor.YELLOW + removedBy + ": " + ChatColor.RED + this.grant.getRemovedReason());
+ description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.grant.getRemovedAt())));
+ if (this.grant.getActiveUntil() != Long.MAX_VALUE) {
+ description.add("");
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int) (this.grant.getLength() / 1000)));
+ }
+ }
+ else if (!this.grant.isStillActive() && this.grant.getActiveUntil() <= Long.MAX_VALUE) {
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.grant.getLength()) / 1000L)));
+ description.add(ChatColor.GREEN + "Expired");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ return this.grant.isStillActive() ? DyeColor.LIME.getWoolData() : DyeColor.RED.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ if (!player.hasPermission("bridge.grant.remove." + this.grant.getRank()) || !this.grant.isStillActive()) {
+ return;
+ }
+ player.closeInventory();
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return "§aType a reason to be used when removing this grant. Type §cno§a to quit.";
+ }
+
+ public Prompt acceptInput(ConversationContext cc, String s) {
+ if (s.equalsIgnoreCase("no")) {
+ cc.getForWhom().sendRawMessage(ChatColor.GREEN + "Grant removal aborted.");
+ }
+ else {
+ grant.setRemoved(true);
+ grant.setRemovedAt(System.currentTimeMillis());
+ grant.setRemovedBy(player.getUniqueId().toString());
+ grant.setRemovedOn(BridgeGlobal.getSystemName());
+ grant.setRemovedReason(s);
+
+ boolean isThereStaff = false;
+ for(Grant g : profile.getGrants()) {
+ if(g.getRank().isStaff() && !g.isRemoved()) {
+ isThereStaff = true;
+ break;
+ }
+ }
+
+ if(!isThereStaff) {
+ if(profile.getBecameStaffOn() != 0) {
+ profile.setRemovedStaffOn(System.currentTimeMillis());
+ }
+ }
+
+ profile.saveProfile();
+
+
+ cc.getForWhom().sendRawMessage(ChatColor.GREEN + "You have removed the grant.");
+ }
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withLocalEcho(false).withEscapeSequence("/no").withTimeout(60).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java
new file mode 100644
index 0000000..fcf998f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/grant/menu/grants/GrantsMenu.java
@@ -0,0 +1,68 @@
+package rip.bridge.bridge.bukkit.commands.grant.menu.grants;
+
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.List;
+import java.util.Map;
+
+public class GrantsMenu extends PaginatedMenu {
+
+ private Profile profile;
+ private List grants;
+
+ public GrantsMenu(Profile profile, List grants) {
+ this.profile = profile;
+ this.grants = grants;
+ setAutoUpdate(true);
+ }
+
+ public String getPrePaginatedTitle(final Player player) {
+ return ChatColor.RED + "Grants";
+ }
+
+ public Map getGlobalButtons(final Player player) {
+ final Map buttons = Maps.newHashMap();
+ buttons.put(4, new Button() {
+ public String getName(final Player player) {
+ return ChatColor.YELLOW + "Back";
+ }
+
+ public List getDescription(final Player player) {
+ return null;
+ }
+
+ public Material getMaterial(final Player player) {
+ return Material.PAPER;
+ }
+
+ public byte getDamageValue(final Player player) {
+ return 0;
+ }
+
+ public void clicked(final Player player, final int i, final ClickType clickType) {
+ player.closeInventory();
+ }
+ });
+ return buttons;
+ }
+
+ public Map getAllPagesButtons(final Player player) {
+ final Map buttons = Maps.newHashMap();
+ int index = 0;
+ for (Grant g : grants) {
+ buttons.put(index, new GrantsButton(profile, g));
+ ++index;
+ }
+ return buttons;
+ }
+
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java
new file mode 100644
index 0000000..08acb95
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/AltsCommand.java
@@ -0,0 +1,47 @@
+package rip.bridge.bridge.bukkit.commands.punishment;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AltsCommand {
+
+ @Command(names = {"alts", "dupeip", "identities"}, permission = "bridge.alts", description = "View player's alt accounts", async = true)
+ public static void alts(CommandSender sender, @Param(name = "player") Profile profile) {
+
+ BridgeGlobal.getMongoHandler().getProfiles(profile.getCurrentIPAddress(), callback -> {
+ if (callback == null || callback.isEmpty() || callback.size() == 1) {
+ sender.sendMessage(BukkitAPI.getColor(profile) + profile.getUsername() + ChatColor.RED + " doesn't have any alts");
+ return;
+ }
+
+ sender.sendMessage(ChatColor.YELLOW + "Fetching identities of " + profile.getUsername() + "...");
+ sender.sendMessage(ChatColor.WHITE + "[" + ChatColor.GREEN + "Online" + ChatColor.WHITE + ", " + ChatColor.GRAY + "Offline" + ChatColor.WHITE + ", " + ChatColor.DARK_RED + "Blacklisted" + ChatColor.WHITE + ", " + ChatColor.RED + "Banned" + ChatColor.WHITE + ", " + ChatColor.WHITE + "Muted" + ChatColor.WHITE + "]");
+ sender.sendMessage(BukkitAPI.getColor(profile) + profile.getUsername() + ChatColor.YELLOW + "'s" + (callback.size() == 1 ? ChatColor.YELLOW + " alt" : ChatColor.YELLOW + " alts") + ChatColor.YELLOW + " (" + ChatColor.RED + callback.size() + ChatColor.YELLOW + ")" + ".");
+ List formattedName = new ArrayList<>();
+ callback.forEach(alt -> {
+ if (Bukkit.getOfflinePlayer(alt.getUuid()).isOnline())
+ formattedName.add(ChatColor.GREEN + alt.getUsername());
+ else if (alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 1)
+ formattedName.add(ChatColor.DARK_RED + alt.getUsername());
+ else if (alt.getActivePunishments(PunishmentType.BAN).size() > 1)
+ formattedName.add(ChatColor.RED + alt.getUsername());
+ else if (alt.getActivePunishments(PunishmentType.MUTE).size() > 1)
+ formattedName.add(ChatColor.GOLD + alt.getUsername());
+ else formattedName.add(ChatColor.GRAY + alt.getUsername());
+ });
+ sender.sendMessage(StringUtils.join(formattedName, ChatColor.WHITE + ", "));
+
+ }, false);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java
new file mode 100644
index 0000000..c91af89
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckPunishmentsCommand.java
@@ -0,0 +1,25 @@
+package rip.bridge.bridge.bukkit.commands.punishment;
+
+import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Flag;
+import mkremins.fanciful.FancyMessage;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class CheckPunishmentsCommand {
+
+ @Command(names = {"checkpunishments", "cp", "c", "history"}, permission = "bridge.checkpunishments", description = "Check a player's active punishments", async = true)
+ public static void checkPunishments(Player sender, @Flag(value = {"gui", "menu"}, description = "Check a player's active punishments ingame") boolean gui, @Param(name = "target", extraData = "get") Profile target) {
+ if (!gui) {
+ FancyMessage message = new FancyMessage(ChatColor.GREEN + "[Click Here]" + ChatColor.YELLOW + " to view all of " + target.getUsername() + "'s punishments");
+ message.tooltip(ChatColor.GRAY + "Click here: https://www.bridge.rip/u/" + target.getUsername() + "/punishments").link("https://www.bridge.rip/u/" + target.getUsername() + "/punishments");
+ message.send(sender);
+ } else {
+ new MainPunishmentMenu(target.getUuid().toString(), target.getUsername()).openMenu(sender);
+ }
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java
new file mode 100644
index 0000000..755ff63
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/CheckStaffPunishmentsCommand.java
@@ -0,0 +1,15 @@
+package rip.bridge.bridge.bukkit.commands.punishment;
+
+import rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory.MainStaffPunishmentListMenu;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.entity.Player;
+
+public class CheckStaffPunishmentsCommand {
+
+ @Command(names = {"staffpunishments", "checkstaffpunishments", "staffhistory", "staffhist"}, permission = "bridge.staffhistory", description = "Check a player's active punishments", async = true)
+ public static void staffPunishments(Player sender, @Param(name = "target") Profile target){
+ new MainStaffPunishmentListMenu(target.getUuid().toString(), target.getUsername()).openMenu(sender);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java
new file mode 100644
index 0000000..5d9e304
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearPunishmentsCommand.java
@@ -0,0 +1,35 @@
+package rip.bridge.bridge.bukkit.commands.punishment;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.MainPunishmentMenu;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Flag;
+import mkremins.fanciful.FancyMessage;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+import java.util.HashSet;
+
+public class ClearPunishmentsCommand {
+
+ @Command(names = {"clearpunishments", "clearhistory"}, permission = "bridge.clearpunishments", description = "Clear player's punishments from the entire network", async = true)
+ public static void clearPunishments(CommandSender s, @Param(name = "target") Profile target) {
+
+ if (target.getPunishments().isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " does not have any punishments.");
+ return;
+ }
+ s.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s punishments.");
+ target.getPunishments().clear();
+ target.saveProfile();
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java
new file mode 100644
index 0000000..a0454e3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/ClearStaffPunishmentsCommand.java
@@ -0,0 +1,28 @@
+package rip.bridge.bridge.bukkit.commands.punishment;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class ClearStaffPunishmentsCommand {
+
+ @Command(names = {"clearstaffpunishments", "clearstaffhistory"}, permission = "bridge.clearstaffpunishments", description = "Clear staff member's punishments from the entire network", async = true)
+ public static void clearPunishments(CommandSender sender, @Param(name = "target") Profile target) {
+
+ if (!target.getCurrentGrant().getRank().isStaff() && target.getRemovedStaffOn() == 0) {
+ sender.sendMessage(ChatColor.RED + "That player has never been apart of the staff team.");
+ return;
+ }
+
+ if (target.getStaffPunishments().isEmpty()) {
+ sender.sendMessage(ChatColor.RED + target.getUsername() + " does not have any staff punishments.");
+ return;
+ }
+ sender.sendMessage(ChatColor.GREEN + "Successfully cleared " + target.getCurrentGrant().getRank().getColor() + target.getUsername() + ChatColor.GREEN + "'s Staff History.");
+ target.getStaffPunishments().clear();
+ target.saveProfile();
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java
new file mode 100644
index 0000000..8de9fbd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanCommand.java
@@ -0,0 +1,41 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+import java.util.HashSet;
+
+public class BanCommand {
+
+ @Command(names = {"ban", "b", "banish"}, permission = "bridge.ban", description = "Ban a player from the network", async = true)
+ public static void banCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (target.getActivePunishments(PunishmentType.BAN).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+ //empty list instead of int instantly as null
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), false, !silent, clear, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java
new file mode 100644
index 0000000..12b1f48
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BanIPCommand.java
@@ -0,0 +1,41 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+
+public class BanIPCommand {
+
+ @Command(names = {"banip", "bip", "baniship"}, permission = "bridge.banip", description = "Ban a player from the network", async = true)
+ public static void banIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (target.getActivePunishments(PunishmentType.BAN).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), true, !silent, clear, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java
new file mode 100644
index 0000000..ff473b1
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/BlacklistCommand.java
@@ -0,0 +1,45 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+import java.util.HashSet;
+
+public class BlacklistCommand {
+
+ @Command(names = {"blacklist", "bl"}, permission = "bridge.blacklist", description = "Blacklist an user from the network. This type of punishment cannot be appealed", async = true)
+ public static void blacklistCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this blacklist to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getCurrentIPAddress() == null) {
+ s.sendMessage(ChatColor.RED + "We can't blacklist a player that never joined before.");
+ return;
+ }
+
+ if (target.getActivePunishments(PunishmentType.BLACKLIST).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already blacklisted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BLACKLIST, new HashSet<>(), true, !silent, clear, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java
new file mode 100644
index 0000000..6a04d81
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/KickCommand.java
@@ -0,0 +1,36 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+
+public class KickCommand
+{
+ @Command(names = { "kick", "k" }, permission = "basic.staff", description = "Kick a player from the server")
+ public static void pMuteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this kick to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", defaultValue = "Kicked by a staff member", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.KICK, new HashSet<>(),false, !silent, false, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java
new file mode 100644
index 0000000..494f717
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteCommand.java
@@ -0,0 +1,45 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+public class MuteCommand {
+
+ @Command(names = {"mute"}, permission = "bridge.mute", description = "Temporarily mute a player, stopping them from talking in public chat", async = true)
+ public static void muteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.MUTE).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ if (!s.hasPermission("bridge.mute.permanent") && TimeUnit.DAYS.toMillis(31L) < length) {
+ s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(),reason, PunishmentType.MUTE, new HashSet<>(), false, !silent, false, length);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java
new file mode 100644
index 0000000..99d2581
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/MuteIPCommand.java
@@ -0,0 +1,47 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+public class MuteIPCommand {
+
+ @Command(names = {"muteip", "ipmute"}, permission = "bridge.muteip", description = "Temporarily mute an user, stopping them from talking in public chat", async = true)
+ public static void muteIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ if (!s.hasPermission("bridge.muteip.permanent") && TimeUnit.DAYS.toMillis(31L) < length) {
+ s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(), true, !silent, false, length);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java
new file mode 100644
index 0000000..3ea758a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteCommand.java
@@ -0,0 +1,41 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+
+public class PermMuteCommand {
+
+ @Command(names = {"pmute", "permmute"}, permission = "bridge.mute.permanent", description = "Permanently mute an user, stopping them from talking in public chat", async = true)
+ public static void pMuteCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(),false, !silent, false, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java
new file mode 100644
index 0000000..5feb402
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/PermMuteIPCommand.java
@@ -0,0 +1,41 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+
+public class PermMuteIPCommand {
+
+ @Command(names = {"pmuteip", "permmuteip"}, permission = "bridge.muteip.permanent", description = "Permanently mute an user, stopping them from talking in public chat", async = true)
+ public static void pMuteIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this mute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (pf.getActivePunishments(PunishmentType.MUTE).size() > 0) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already muted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.MUTE, new HashSet<>(), true, !silent, false, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java
new file mode 100644
index 0000000..06002be
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanCommand.java
@@ -0,0 +1,46 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+public class TempBanCommand {
+
+ @Command(names = {"tempban", "tban", "tb"}, permission = "bridge.tempban", description = "Temporarily ban a player from the network", async = true)
+ public static void tBanCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.BAN).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ if (!s.hasPermission("bridge.ban") && TimeUnit.DAYS.toMillis(31L) < length) {
+ s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), false, !silent, clear, length);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java
new file mode 100644
index 0000000..128ccdc
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/TempBanIPCommand.java
@@ -0,0 +1,46 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+public class TempBanIPCommand {
+
+ @Command(names = {"tempbanip", "tbanip", "tbip"}, permission = "bridge.tempbanip", description = "Temporarily ban a player from the network", async = true)
+ public static void tBanIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this ban to the server") boolean silent, @Flag(value = {"c", "clear"}, description = "Clear the player's inventory") boolean clear, @Param(name = "target") Profile target, @Param(name = "time") Long length, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.BAN).size() > 1) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is already banned.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ if (!s.hasPermission("bridge.ban") && TimeUnit.DAYS.toMillis(31L) < length) {
+ s.sendMessage(ChatColor.RED + "You don't have permission to create a mute this long. Maximum time allowed: 30 days.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.BAN, new HashSet<>(), true, !silent, clear, length);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java
new file mode 100644
index 0000000..63d2aaf
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/create/WarnCommand.java
@@ -0,0 +1,36 @@
+package rip.bridge.bridge.bukkit.commands.punishment.create;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+
+import java.util.HashSet;
+
+public class WarnCommand {
+
+ @Command(names = {"warn"}, permission = "bridge.warn", description = "Add a warning to an player's account", async = true)
+ public static void warnCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this warn to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if (!BukkitAPI.canOverride(pf, target)) {
+ s.sendMessage(ChatColor.RED + "You cannot punish this player.");
+ return;
+ }
+
+ Punishment punishment = new Punishment(target, pf, BridgeGlobal.getSystemName(), reason, PunishmentType.WARN, new HashSet<>(), false, !silent, false, Long.MAX_VALUE);
+ target.getPunishments().add(punishment);
+ pf.getStaffPunishments().add(punishment);
+ target.saveProfile();
+ pf.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java
new file mode 100644
index 0000000..941a35e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/MainPunishmentMenu.java
@@ -0,0 +1,98 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu;
+
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Bukkit;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.*;
+
+public class MainPunishmentMenu extends Menu
+{
+ private String targetUUID;
+ private String targetName;
+
+ public String getTitle(Player player) {
+ return ChatColor.BLUE + "Punishments - " + this.targetName;
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ if (player.hasPermission("bridge.punishments.view.blacklist")) {
+ buttons.put(0, this.button(PunishmentType.WARN));
+ buttons.put(2, this.button(PunishmentType.KICK));
+ buttons.put(4, this.button(PunishmentType.MUTE));
+ buttons.put(6, this.button(PunishmentType.BAN));
+ buttons.put(8, this.button(PunishmentType.BLACKLIST));
+ }
+ else {
+ buttons.put(1, this.button(PunishmentType.WARN));
+ buttons.put(3, this.button(PunishmentType.KICK));
+ buttons.put(5, this.button(PunishmentType.MUTE));
+ buttons.put(7, this.button(PunishmentType.BAN));
+ }
+ return buttons;
+ }
+
+ private Button button(PunishmentType type) {
+ return new Button() {
+
+ public String getName(Player player) {
+ return ChatColor.RED + type.getDisplayName() + "s";
+
+ }
+
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ if (type == PunishmentType.WARN) {
+ return DyeColor.YELLOW.getWoolData();
+ }
+ if (type == PunishmentType.KICK) {
+ return DyeColor.GRAY.getWoolData();
+ }
+ if (type == PunishmentType.MUTE) {
+ return DyeColor.ORANGE.getWoolData();
+ }
+ if (type == PunishmentType.BAN) {
+ return DyeColor.RED.getWoolData();
+ }
+ return DyeColor.BLACK.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ player.sendMessage(ChatColor.GREEN + "Loading " + MainPunishmentMenu.this.targetName + "'s " + type.getDisplayName() + "s...");
+
+ List allPunishments = new ArrayList<>(BukkitAPI.getProfile(UUID.fromString(targetUUID)).getPunishments());
+ Bukkit.getScheduler().scheduleAsyncDelayedTask(Bridge.getInstance(), () -> {
+ allPunishments.sort((first, second) -> Long.compare(second.getTime(), first.getTime()));
+ LinkedHashMap punishments = new LinkedHashMap<>();
+ allPunishments.stream().filter(punishment -> punishment.getPunishmentType() == type).forEach(punishment -> punishments.put(punishment, punishment.getTarget().getUsername()));
+ Bukkit.getScheduler().scheduleSyncDelayedTask(Bridge.getInstance(), () -> new PunishmentMenu(targetUUID, targetName, type, punishments).openMenu(player));
+ });
+ }
+ };
+ }
+
+ public MainPunishmentMenu(String targetUUID, String targetName) {
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ setAutoUpdate(true);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java
new file mode 100644
index 0000000..5bb2964
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/ProofMenu.java
@@ -0,0 +1,81 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu;
+
+import com.google.common.collect.Maps;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.button.ProofAddButton;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.button.ProofButton;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Evidence;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+
+import java.util.List;
+import java.util.Map;
+
+public class ProofMenu extends PaginatedMenu {
+
+ private final Punishment punishment;
+ private String targetUUID;
+ private String targetName;
+ private PunishmentType type;
+ private Map punishments;
+ Profile profile;
+
+ public ProofMenu(Punishment punishment, String targetUUID, PunishmentType type, String targetName, Map punishments){
+ this.punishment = punishment;
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ this.type = type;
+ this.punishments = punishments;
+ profile = punishment.getTarget();
+ }
+
+ public Map getGlobalButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ buttons.put(5, new ProofAddButton(punishment, profile));
+ buttons.put(4, new Button() {
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Back";
+ }
+
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ new PunishmentMenu(ProofMenu.this.targetUUID, ProofMenu.this.targetName, type, punishments).openMenu(player);
+ }
+ });
+ return buttons;
+ }
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ return "Proof Editor";
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ int index = 0;
+ for(Evidence entry : punishment.getProof()){
+ buttons.put(index, new ProofButton(punishment, profile, entry));
+ index++;
+ }
+ return buttons;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java
new file mode 100644
index 0000000..d1dc0ee
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/PunishmentMenu.java
@@ -0,0 +1,72 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu;
+
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.button.PunishmentButton;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.List;
+import java.util.Map;
+
+public class PunishmentMenu extends PaginatedMenu
+{
+ private String targetUUID;
+ private String targetName;
+ private PunishmentType type;
+ private Map punishments;
+
+ public String getPrePaginatedTitle(Player player) {
+ return ChatColor.RED + this.type.getDisplayName() + "s";
+ }
+
+ public Map getGlobalButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ buttons.put(4, new Button() {
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Back";
+ }
+
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ new MainPunishmentMenu(PunishmentMenu.this.targetUUID, PunishmentMenu.this.targetName).openMenu(player);
+ }
+ });
+ return buttons;
+ }
+
+ public Map getAllPagesButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ int index = 0;
+ for (Map.Entry entry : this.punishments.entrySet()) {
+ buttons.put(index, new PunishmentButton(entry.getKey(), entry.getKey().getPunishmentType(), entry.getKey().getTarget().getUuid().toString(), entry.getKey().getTarget().getUsername(), punishments));
+ ++index;
+ }
+ return buttons;
+ }
+
+ public PunishmentMenu(String targetUUID, String targetName, PunishmentType type, Map punishments) {
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ this.punishments = punishments;
+ this.type = type;
+ setAutoUpdate(true);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java
new file mode 100644
index 0000000..dbd6f56
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofAddButton.java
@@ -0,0 +1,88 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.button;
+
+import org.bukkit.scheduler.BukkitRunnable;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Evidence;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.qlib.menu.Button;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.List;
+
+public class ProofAddButton extends Button {
+
+ private final Punishment punishment;
+ private final Profile profile;
+
+ public ProofAddButton(Punishment punishment, Profile profile) {
+ this.punishment = punishment;
+ this.profile = profile;
+ }
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.GREEN + ("Add Proof Entry");
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.SIGN;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ startAddConversation(player);
+ }
+
+ private void startAddConversation(Player player) {
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Please type a proof entry to submit, or type " + ChatColor.RED + "cancel " + ChatColor.YELLOW + "to cancel.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+
+ if (input.equalsIgnoreCase("cancel")) {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Proof entry submission process aborted.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ if (punishment.getProof().contains(new Evidence(player.getName(), input))) {
+ player.sendMessage(ChatColor.RED + "This punishment already has a proof entry similar to the one you input.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ punishment.getProof().add(new Evidence(player.getName(), input));
+ profile.saveProfile();
+ player.sendMessage(ChatColor.GREEN + "Successfully added proof entry: " + ChatColor.RESET + input);
+ }
+ }.runTask(Bridge.getInstance());
+
+ /*punishment.getProof().add(new Evidence(player.getName(), input));
+ profile.saveProfile();
+
+ Bridge.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Bridge.getInstance(), () -> {
+
+ player.sendMessage(ChatColor.GREEN + "Successfully added proof entry: " + ChatColor.RESET + input);
+ }, 1L);*/
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }).withLocalEcho(false);
+
+ player.closeInventory();
+ player.beginConversation(factory.buildConversation(player));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java
new file mode 100644
index 0000000..6a4633f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/ProofButton.java
@@ -0,0 +1,113 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.button;
+
+import com.google.common.collect.Lists;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.scheduler.BukkitRunnable;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Evidence;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.qlib.menu.Button;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.Date;
+import java.util.List;
+
+public class ProofButton extends Button {
+
+ private final Punishment punishment;
+ private final Profile profile;
+ private final Evidence entry;
+
+ public ProofButton(Punishment punishment, Profile profile, Evidence entry){
+ this.punishment = punishment;
+ this.profile = profile;
+ this.entry = entry;
+ }
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(punishment.getTime()));
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ description.add(ChatColor.YELLOW + "Added by: " + ChatColor.RED + entry.getSender());
+ description.add(ChatColor.YELLOW + "Proof: " + ChatColor.RED + entry.getURL());
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ description.add(ChatColor.GREEN.toString() + ChatColor.BOLD + "Left Click to view");
+ description.add(ChatColor.GREEN.toString() + ChatColor.BOLD + "this proof");
+ description.add(" ");
+ description.add(ChatColor.RED.toString() + ChatColor.BOLD + "Right Click to remove");
+ description.add(ChatColor.RED.toString() + ChatColor.BOLD + "this proof");
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 25));
+ return description;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ @Override
+ public byte getDamageValue(Player player) {
+ return (byte) 5;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ switch(clickType){
+ case LEFT: {
+ player.sendMessage(ChatColor.YELLOW + entry.getURL());
+ break;
+ }case RIGHT: {
+ startRemoveConversation(player);
+ } default: {
+
+ }
+ }
+ }
+
+ private void startRemoveConversation(Player player){
+ player.closeInventory();
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Please type " + ChatColor.RED + "confirm" + ChatColor.YELLOW + " to confirm removal of this proof entry, or type " + ChatColor.RED + "cancel " + ChatColor.YELLOW + "to cancel.";
+ }
+
+ public Prompt acceptInput(ConversationContext context, String input) {
+ if (input.equalsIgnoreCase("cancel")) {
+ context.getForWhom().sendRawMessage(ChatColor.RED + "Proof entry removal process aborted.");
+ return Prompt.END_OF_CONVERSATION;
+ } else if (input.equalsIgnoreCase("confirm")) {
+
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ punishment.getProof().remove(entry);
+ profile.saveProfile();
+ player.sendMessage(ChatColor.GREEN + "Successfully removed the proof entry.");
+ }
+ }.runTask(Bridge.getInstance());
+
+ return Prompt.END_OF_CONVERSATION;
+ }else{
+ Bridge.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Bridge.getInstance(), () -> {
+ player.sendMessage(ChatColor.RED + "Invalid response; proof entry removal process aborted.");
+ }, 1L);
+ return Prompt.END_OF_CONVERSATION;
+ }
+ }
+ }).withEscapeSequence("/no").withLocalEcho(false).withTimeout(10).thatExcludesNonPlayersWithMessage("Go away evil console!");
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java
new file mode 100644
index 0000000..5390c8e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/button/PunishmentButton.java
@@ -0,0 +1,98 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.button;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.punishment.menu.ProofMenu;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.util.TimeUtils;
+import net.md_5.bungee.api.ChatColor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.time.DurationFormatUtils;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public class PunishmentButton extends Button
+{
+ private Punishment punishment;
+ private String targetUUID;
+ private String targetName;
+ private PunishmentType type;
+ private Map punishments;
+
+ public PunishmentButton(Punishment punishment, PunishmentType type, String targetUUID, String targetName, Map punishments){
+ this.punishment = punishment;
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ this.type = type;
+ this.punishments = punishments;
+ }
+
+ public String getName(Player player) {
+ return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getTime()));
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ String by = punishment.getExecutor().getUsername();
+ String actor = "Server" + ChatColor.YELLOW + " : " + ChatColor.RED + (this.punishment.getPunishedServer() != null ? this.punishment.getPunishedServer() : "Website");
+
+ final String randomID = ChatColor.MAGIC + UUID.randomUUID().toString().substring(0, 8);
+ description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? by : randomID));
+ description.add(ChatColor.YELLOW + "Added on: " + ChatColor.RED + actor);
+ description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.punishment.getReason());
+
+
+ if (this.punishment.isActive()) {
+ if (!this.punishment.isPermanent()) {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + DurationFormatUtils.formatDurationWords(Math.abs(punishment.getRemainingTime()), true, true));
+ }
+ else {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.YELLOW + "This is a permanent punishment.");
+ }
+ }
+ else if (this.punishment.isPardoned()) {
+ String removedBy = this.punishment.getPardonedBy().getUsername();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.RED + "Removed:");
+ description.add(ChatColor.YELLOW + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? removedBy : randomID) + ": " + ChatColor.RED + this.punishment.getPardonedReason());
+ description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getPardonedAt())));
+ if (!this.punishment.isPermanent()) {
+ description.add("");
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1));
+ }
+ }
+ else if (!this.punishment.isPermanent() && this.punishment.getRemainingTime() <= 0) {
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1));
+ description.add(ChatColor.GREEN + "Expired");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ return description;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ @Override
+ public byte getDamageValue(Player player) {
+ return !this.punishment.isActive() ? DyeColor.RED.getWoolData() : DyeColor.LIME.getWoolData();
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+// new ProofMenu(punishment, PunishmentButton.this.targetUUID,type, PunishmentButton.this.targetName, punishments).openMenu(player);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java
new file mode 100644
index 0000000..dce9bc3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/MainStaffPunishmentListMenu.java
@@ -0,0 +1,97 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory;
+
+import com.google.common.collect.Maps;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.*;
+
+public class MainStaffPunishmentListMenu extends Menu {
+
+ private String targetUUID;
+ private String targetName;
+
+
+ public String getTitle(Player player) {
+ return ChatColor.BLUE + "Staff History - " + this.targetName;
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ if (player.hasPermission("bridge.punishments.view.blacklist")) {
+ buttons.put(0, this.button(PunishmentType.WARN));
+ buttons.put(2, this.button(PunishmentType.KICK));
+ buttons.put(4, this.button(PunishmentType.MUTE));
+ buttons.put(6, this.button(PunishmentType.BAN));
+ buttons.put(8, this.button(PunishmentType.BLACKLIST));
+ }
+ else {
+ buttons.put(1, this.button(PunishmentType.WARN));
+ buttons.put(3, this.button(PunishmentType.KICK));
+ buttons.put(5, this.button(PunishmentType.MUTE));
+ buttons.put(7, this.button(PunishmentType.BAN));
+ }
+ return buttons;
+ }
+
+ private Button button(PunishmentType type) {
+ return new Button() {
+ public String getName(Player player) {
+ return ChatColor.RED + type.getDisplayName() + "s";
+ }
+
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ if (type == PunishmentType.WARN) {
+ return DyeColor.YELLOW.getWoolData();
+ }
+ if (type == PunishmentType.KICK) {
+ return DyeColor.GRAY.getWoolData();
+ }
+ if (type == PunishmentType.MUTE) {
+ return DyeColor.ORANGE.getWoolData();
+ }
+ if (type == PunishmentType.BAN) {
+ return DyeColor.RED.getWoolData();
+ }
+ return DyeColor.BLACK.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ player.sendMessage(ChatColor.GREEN + "Loading " + MainStaffPunishmentListMenu.this.targetName + "'s " + type.getDisplayName() + " Staff History...");
+
+ List allPunishments = new ArrayList<>(BukkitAPI.getProfile(UUID.fromString(targetUUID)).getStaffPunishments());
+ Bukkit.getScheduler().scheduleAsyncDelayedTask(Bridge.getInstance(), () -> {
+ allPunishments.sort((first, second) -> Long.compare(second.getTime(), first.getTime()));
+ LinkedHashMap punishments = new LinkedHashMap<>();
+ allPunishments.stream().filter(punishment -> punishment.getPunishmentType().equals(type)).forEach(punishment -> punishments.put(punishment, punishment.getTarget().getUsername()));
+ Bukkit.getScheduler().scheduleSyncDelayedTask(Bridge.getInstance(), () -> new StaffPunishmentListMenu(targetUUID, targetName, type, punishments).openMenu(player));
+ });
+ }
+ };
+ }
+
+ public MainStaffPunishmentListMenu(String targetUUID, String targetName) {
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ setAutoUpdate(true);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java
new file mode 100644
index 0000000..dafd547
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentButton.java
@@ -0,0 +1,87 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.util.TimeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.time.DurationFormatUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+public class StaffPunishmentButton extends Button {
+
+ private final Punishment punishment;
+
+ public StaffPunishmentButton(Punishment punishment){
+ this.punishment = punishment;
+ }
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(punishment.getTime()));
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ String by = punishment.getExecutor().getUsername();
+ String actor = "Server" + ChatColor.YELLOW + " : " + ChatColor.RED + this.punishment.getPunishedServer();
+
+ final String randomID = ChatColor.MAGIC + UUID.randomUUID().toString().substring(0, 8);
+ description.add(ChatColor.YELLOW + "Target: " + ChatColor.RED + punishment.getTarget().getUsername());
+ description.add(ChatColor.YELLOW + "By: " + ChatColor.RED + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? by : randomID));
+ description.add(ChatColor.YELLOW + "Added on: " + ChatColor.RED + actor);
+ description.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + this.punishment.getReason());
+
+
+ if (this.punishment.isActive()) {
+ if (!this.punishment.isPermanent()) {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.YELLOW + "Time remaining: " + ChatColor.RED + DurationFormatUtils.formatDurationWords(Math.abs(punishment.getRemainingTime()), true, true));
+ }
+ else {
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.YELLOW + "This is a permanent punishment.");
+ }
+ }
+ else if (this.punishment.isPardoned()) {
+ String removedBy = this.punishment.getPardonedBy().getUsername();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ description.add(ChatColor.RED + "Removed:");
+ description.add(ChatColor.YELLOW + (BukkitAPI.getProfile(player).hasPermission("bridge.punishments.view.punisher") ? removedBy : randomID) + ": " + ChatColor.RED + this.punishment.getPardonedReason());
+ description.add(ChatColor.RED + "at " + ChatColor.YELLOW + TimeUtils.formatIntoCalendarString(new Date(this.punishment.getPardonedAt())));
+ if (!this.punishment.isPermanent()) {
+ description.add("");
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1));
+ }
+ }
+ else if (!this.punishment.isPermanent() && this.punishment.getRemainingTime() <= 0) {
+ description.add(ChatColor.YELLOW + "Duration: " + TimeUtils.formatIntoDetailedString((int)((this.punishment.getRemainingTime()) / 1000L) + 1));
+ description.add(ChatColor.GREEN + "Expired");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat("-", 25));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ return !this.punishment.isActive() ? DyeColor.RED.getWoolData() : DyeColor.LIME.getWoolData();
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+// new ProofMenu(punishment, punishment.getTarget().getUuid().toString(), punishment.getPunishmentType(), punishment.getTarget().getUsername().toString(), null).openMenu(player);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java
new file mode 100644
index 0000000..433cf50
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/menu/staffhistory/StaffPunishmentListMenu.java
@@ -0,0 +1,74 @@
+package rip.bridge.bridge.bukkit.commands.punishment.menu.staffhistory;
+
+import com.google.common.collect.Maps;
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.Map;
+
+public class StaffPunishmentListMenu extends PaginatedMenu {
+
+ private String targetName;
+ private String targetUUID;
+ private PunishmentType type;
+ private Map punishments;
+
+
+ public String getPrePaginatedTitle(Player player) {
+ return ChatColor.RED + this.type.getDisplayName() + "s";
+ }
+
+ public Map getGlobalButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ buttons.put(4, new Button() {
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Back";
+ }
+
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ player.closeInventory();
+ new MainStaffPunishmentListMenu(StaffPunishmentListMenu.this.targetUUID, StaffPunishmentListMenu.this.targetName).openMenu(player);
+ }
+ });
+ return buttons;
+ }
+
+ public Map getAllPagesButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ int index = 0;
+ for (Map.Entry entry : this.punishments.entrySet()) {
+ buttons.put(index, new StaffPunishmentButton(entry.getKey()));
+ ++index;
+ }
+
+ return buttons;
+ }
+
+ public StaffPunishmentListMenu(String targetUUID, String targetName, PunishmentType type, Map punishments) {
+ this.targetUUID = targetUUID;
+ this.targetName = targetName;
+ this.punishments = punishments;
+ this.type = type;
+ setAutoUpdate(true);
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java
new file mode 100644
index 0000000..58c53db
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanCommand.java
@@ -0,0 +1,43 @@
+package rip.bridge.bridge.bukkit.commands.punishment.remove;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class UnBanCommand {
+
+ @Command(names = {"unban"}, permission = "bridge.unban", description = "Remove a player's ban", async = true)
+ public static void unbanCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this unban to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.BAN).isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently banned.");
+ return;
+ }
+
+ Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BAN).toArray()[0];
+
+ if (punishment.isIP() && !s.hasPermission("bridge.unbanip")) {
+ s.sendMessage(ChatColor.RED + "You cannot unban " + target.getUsername() + " because they are ip-banned.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) {
+ s.sendMessage(ChatColor.RED + "You cannot undo this punishment.");
+ return;
+ }
+
+ punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java
new file mode 100644
index 0000000..55ae9f5
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBanIPCommand.java
@@ -0,0 +1,39 @@
+package rip.bridge.bridge.bukkit.commands.punishment.remove;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class UnBanIPCommand {
+
+ @Command(names = {"unbanip"}, permission = "bridge.unbanip", description = "Remove a player's ban", async = true)
+ public static void unbanIPCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Publicly unban the player") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.BAN).isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently ip-banned.");
+ return;
+ }
+
+ Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BAN).toArray()[0];
+
+ if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) {
+ s.sendMessage(ChatColor.RED + "You cannot undo this punishment.");
+ return;
+ }
+
+ punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java
new file mode 100644
index 0000000..13767e4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnBlacklistCommand.java
@@ -0,0 +1,39 @@
+package rip.bridge.bridge.bukkit.commands.punishment.remove;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class UnBlacklistCommand {
+
+ @Command(names = {"unblacklist", "unbl"}, permission = "bridge.unblacklist", description = "Remove a player's blacklist", async = true)
+ public static void unblacklistCmd(CommandSender s, @Flag(value = {"a", "announce"}, description = "Announce this blacklist to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+ if (target.getActivePunishments(PunishmentType.BLACKLIST).isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently blacklisted.");
+ return;
+ }
+
+ Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0];
+
+ if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) {
+ s.sendMessage(ChatColor.RED + "You cannot undo this punishment.");
+ return;
+ }
+
+ punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java
new file mode 100644
index 0000000..0f1b4ee
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnMuteCommand.java
@@ -0,0 +1,44 @@
+package rip.bridge.bridge.bukkit.commands.punishment.remove;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class UnMuteCommand {
+
+ @Command(names = {"unmute"}, permission = "bridge.unmute", description = "Remove a player's mute", async = true)
+ public static void unmuteCmd(CommandSender s, @Flag(value = { "a", "announce" }, description = "Announce this unmute to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if(target.getActivePunishments(PunishmentType.MUTE).isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " is not currently muted.");
+ return;
+ }
+ Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.MUTE).toArray()[0];
+
+ if(punishment.isIP() && !s.hasPermission("bridge.unmuteip")) {
+ s.sendMessage(ChatColor.RED + "You cannot unmute " + target.getUsername() + " because they are ip-muted.");
+ return;
+ }
+
+ if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) {
+ s.sendMessage(ChatColor.RED + "You cannot undo this punishment.");
+ return;
+ }
+
+ punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java
new file mode 100644
index 0000000..7aa1367
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/punishment/remove/UnWarnCommand.java
@@ -0,0 +1,40 @@
+package rip.bridge.bridge.bukkit.commands.punishment.remove;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.PunishmentPacket;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Flag;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+public class UnWarnCommand {
+
+ @Command(names = {"unwarn"}, permission = "bridge.unwarn", description = "Remove a player's warn", async = true)
+ public static void unbanCmd(CommandSender s, @Flag(value = { "a", "announce" }, description = "Announce this unwarn to the server") boolean silent, @Param(name = "target") Profile target, @Param(name = "reason", wildcard = true) String reason) {
+ Profile pf = BukkitAPI.getProfile(s);
+
+ if(target.getActivePunishments(PunishmentType.WARN).isEmpty()) {
+ s.sendMessage(ChatColor.RED + target.getUsername() + " does not have an active warning.");
+ return;
+ }
+ Punishment punishment = (Punishment) target.getActivePunishments(PunishmentType.WARN).toArray()[0];
+
+ if (!BukkitAPI.canOverride(pf, punishment.getExecutor())) {
+ s.sendMessage(ChatColor.RED + "You cannot undo this punishment.");
+ return;
+ }
+
+ punishment.pardon(pf, BridgeGlobal.getSystemName(), reason, !silent);
+ target.getPunishments().add(punishment);
+ target.saveProfile();
+ PacketHandler.sendToAll(new PunishmentPacket(punishment));
+ }
+
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java
new file mode 100644
index 0000000..26aa736
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankCreateCommand.java
@@ -0,0 +1,27 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankCreatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankCreateCommand {
+
+ @Command(names = {"rank create"}, permission = "bridge.rank", description = "Create a rank", hidden = true, async = true)
+ public static void RankCreateCmd(CommandSender s, @Param(name = "rank") String name) {
+ Rank r = BukkitAPI.getRank(name);
+ if (r != null) {
+ s.sendMessage("§cThere is already a rank with the name \"" + r.getName() + "\".");
+ return;
+ }
+ r = BukkitAPI.createRank(name);
+ PacketHandler.sendToAll(new RankCreatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fCreated rank " + r.getColor() + r.getDisplayName()));
+ s.sendMessage("§aSuccessfully created the rank " + r.getColor() + r.getName() + "§a!");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java
new file mode 100644
index 0000000..17209aa
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankDeleteCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankDeletePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankDeleteCommand {
+
+ @Command(names = {"rank delete", "rank remove"}, permission = "bridge.rank", description = "Delete a rank", hidden = true, async = true)
+ public static void RankDeleteCmd(CommandSender s, @Param(name = "rank") Rank r) {
+ s.sendMessage("§aSuccessfully deleted the rank " + r.getColor() + r.getName() + "§a!");
+ BridgeGlobal.getMongoHandler().removeRank(r.getUuid(), callback -> {
+ }, true);
+ PacketHandler.sendToAll(new RankDeletePacket(r, s.getName(), BridgeGlobal.getServerName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fDeleted rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java
new file mode 100644
index 0000000..7fc83d1
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInfoCommand.java
@@ -0,0 +1,36 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankInfoCommand {
+
+ @Command(names = {"rank info"}, permission = "bridge.rank", description = "Get information about a rank", hidden = true, async = true)
+ public static void RankInfoCmd(CommandSender s, @Param(name = "rank") Rank r) {
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage(r.getColor() + r.getDisplayName() + " Rank §7❘ §fInformation");
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage("§6Prefix: §f" + r.getPrefix() + " §7(" + ChatColor.stripColor(r.getPrefix().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Suffix: §f" + r.getSuffix() + " §7(" + ChatColor.stripColor(r.getSuffix().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Priority: §f" + r.getPriority());
+ s.sendMessage("§6Staff: §f" + r.isStaff());
+ s.sendMessage("§6Media: §f" + r.isMedia());
+ s.sendMessage("§6Builder: §f" + r.isBuilder());
+ s.sendMessage("§6Default: §f" + r.isDefaultRank());
+ s.sendMessage(ChatColor.GOLD + "Permissions (" + r.getPermissions().size() + ChatColor.GOLD + "): ");
+ if (r.getPermissions().isEmpty()) s.sendMessage(ChatColor.RED + "None...");
+ else r.getPermissions().keySet().forEach(str -> {
+ s.sendMessage(ChatColor.GRAY + " * " + ChatColor.WHITE + str + ChatColor.GRAY + " [" + r.getPermissions().get(str) + "]");
+ });
+ s.sendMessage("");
+ s.sendMessage("§6Inherits (" + r.getInherits().size() + ChatColor.GOLD + "): " + (r.getInherits().isEmpty() ? "§cNone..." : ""));
+ if (!r.getInherits().isEmpty())
+ r.getInherits().forEach(rank -> s.sendMessage(" §7* §f" + rank.getColor() + rank.getDisplayName()));
+
+ s.sendMessage(BukkitAPI.LINE);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java
new file mode 100644
index 0000000..21d9dd7
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankInheritCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankInheritCommand {
+
+ @Command(names = {"rank inherit"}, permission = "bridge.rank", description = "Add/remove a rank inherit", hidden = true, async = true)
+ public static void RankPermissionCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "inherit") Rank inhr) {
+ boolean b = r.toggleInherit(inhr);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the inherit of " + inhr.getColor() + inhr.getDisplayName());
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java
new file mode 100644
index 0000000..a9a4c9d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankListCommand.java
@@ -0,0 +1,57 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+
+import java.util.ArrayList;
+
+public class RankListCommand {
+
+ @Command(names = {"rank list"}, permission = "bridge.rank", description = "List all ranks", hidden = true, async = true)
+ public static void RankListCmd(CommandSender s) {
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage("§6§lRanks §f(" + BridgeGlobal.getRankHandler().getRanks().size() + ")");
+ s.sendMessage(BukkitAPI.LINE);
+ ArrayList rankList = new ArrayList<>(BridgeGlobal.getRankHandler().getRanks());
+ rankList.sort((o1, o2) -> o2.getPriority() - o1.getPriority());
+
+ rankList.forEach(rank -> {
+ if (s instanceof Player) {
+
+ ComponentBuilder cp = new ComponentBuilder(rank.getColor() + rank.getDisplayName() + " §7❘ §f" + rank.getName() + (rank.isHidden() ? " §7[Hidden]" : "")).event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(
+ "§6Prefix: §f" + rank.getPrefix() + " §7(" + ChatColor.stripColor(rank.getPrefix().replaceAll("§", "&")) + ")" + "\n" +
+ "§6Suffix: §f" + rank.getSuffix() + " §7(" + ChatColor.stripColor(rank.getSuffix().replaceAll("§", "&")) + ")" + "\n" +
+ "§6Priority: §f" + rank.getPriority() + "\n" +
+ "§6Staff: §f" + rank.isStaff() + "\n" +
+ "§6Media: §f" + rank.isMedia() + "\n" +
+ "§6Builder: §f" + rank.isBuilder() + "\n" +
+ "§6Default: §f" + rank.isDefaultRank() + "\n\n" +
+ "§7§oClick for more information"
+ ))).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/rank info " + rank.getName()));
+ ((Player) s).spigot().sendMessage(cp.create());
+ } else {
+ s.sendMessage(rank.getColor() + rank.getDisplayName() + " §7❘ §f" + rank.getName() + (rank.isHidden() ? " §7[Hidden]" : ""));
+ s.sendMessage("§6Prefix: §f" + rank.getPrefix() + " §7(" + ChatColor.stripColor(rank.getPrefix().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Suffix: §f" + rank.getSuffix() + " §7(" + ChatColor.stripColor(rank.getSuffix().replaceAll("§", "&")) + ")");
+ s.sendMessage("§6Priority: §f" + rank.getPriority());
+ s.sendMessage("§6Staff: §f" + rank.isStaff());
+ s.sendMessage("§6Media: §f" + rank.isMedia());
+ s.sendMessage("§6Builder: §f" + rank.isBuilder());
+ s.sendMessage("§6Default: §f" + rank.isDefaultRank());
+ s.sendMessage("");
+ }
+ });
+ s.sendMessage("");
+ s.sendMessage(s instanceof Player ? "§7§oHover over the ranks for more information." : "§7§oType /rank info for more information.");
+ s.sendMessage(BukkitAPI.LINE);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java
new file mode 100644
index 0000000..0d28fe3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankManageCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.commands.rank.menu.RankMenu;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankManageCommand {
+
+ @Command(names = {"rank manage"}, permission = "bridge.rank", description = "Manage a rank", hidden = true, async = true)
+ public static void RankMangeCmd(CommandSender s, @Param(name = "rank") String name) {
+ Rank r = BridgeGlobal.getRankHandler().getRankByName(name);
+ if (r == null) {
+ s.sendMessage("§cThere is no such rank with the name \"" + name + "\".");
+ return;
+ }
+
+ new RankMenu(r).openMenu((Player) s);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java
new file mode 100644
index 0000000..17e5e94
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankPermissionCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankPermissionCommand {
+
+ @Command(names = {"rank permission", "rank perm"}, permission = "bridge.rank", description = "Add/remove a permission", hidden = true, async = true)
+ public static void RankPermissionCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "permission") String perm, @Param(name = "group", defaultValue = "§") String serverGroup) {
+ String group = serverGroup.equals("§") ? "Global" : serverGroup;
+ boolean b = r.togglePerm(perm, group);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the permission " + perm + " to the scope: " + group);
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java
new file mode 100644
index 0000000..272aedd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankRenameCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankRenameCommand {
+
+ @Command(names = {"rank rename"}, permission = "bridge.rank", description = "Rename a rank", hidden = true, async = true)
+ public static void RankRenameCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "name") String name) {
+ String original = r.getName();
+ r.setName(name);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully renamed the rank from " + original + " to " + name + "!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java
new file mode 100644
index 0000000..cdc2a36
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetBuilderCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetBuilderCommand {
+
+ @Command(names = {"rank setbuilder"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true)
+ public static void RankSetBuilderCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "builder") boolean builder) {
+ r.setBuilder(builder);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the builder status to " + builder + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java
new file mode 100644
index 0000000..07e7ca7
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetColorCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetColorCommand {
+ @Command(names = {"rank setcolor", "rank setcolour"}, permission = "bridge.rank", description = "Set a ranks color", hidden = true, async = true)
+ public static void RankSetColorCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "color") String col) {
+ String color = ChatColor.translateAlternateColorCodes('&', col);
+ r.setColor(color);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the color to " + color + r.getName() + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java
new file mode 100644
index 0000000..2e3c7b8
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDefaultCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetDefaultCommand {
+
+ @Command(names = {"rank setdefault"}, permission = "bridge.rank", description = "Set a rank default status", hidden = true, async = true)
+ public static void RankSetDefaultCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "default") boolean b) {
+ r.setDefaultRank(b);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the default status to " + b + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java
new file mode 100644
index 0000000..805230f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetDisplayNameCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetDisplayNameCommand {
+
+ @Command(names = {"rank setdisplayname", "rank setname"}, permission = "bridge.rank", description = "Set a ranks display name", hidden = true, async = true)
+ public static void RankSetDisplayNameCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "displayName", wildcard = true) String displayName) {
+ r.setDisplayName(displayName);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the display name to " + displayName + "!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java
new file mode 100644
index 0000000..8136da8
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetGrantableCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetGrantableCommand {
+
+ @Command(names = {"rank setgrantable"}, permission = "bridge.rank", description = "Set a rank grantable status", hidden = true, async = true)
+ public static void RankSetGrantableCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "grantable") boolean grantable) {
+ r.setGrantable(grantable);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the grantable status to " + grantable + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java
new file mode 100644
index 0000000..f526782
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetHiddenCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetHiddenCommand {
+
+ @Command(names = {"rank sethidden"}, permission = "bridge.rank", description = "Set a rank hidden status", hidden = true, async = true)
+ public static void RankSetHiddenCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "hidden") boolean hidden) {
+ r.setHidden(hidden);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the hidden status to " + hidden + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java
new file mode 100644
index 0000000..e6c5953
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetMediaCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetMediaCommand {
+
+ @Command(names = {"rank setmedia"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true)
+ public static void RankSetMediaCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "media") boolean media) {
+ r.setMedia(media);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the media status to " + media + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java
new file mode 100644
index 0000000..eaccaf0
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPrefixCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetPrefixCommand {
+ @Command(names = {"rank setprefix"}, permission = "bridge.rank", description = "Set a ranks prefix", hidden = true, async = true)
+ public static void RankSetPrefixCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "prefix", wildcard = true) String prfx) {
+ String prefix = ChatColor.translateAlternateColorCodes('&', prfx);
+ r.setPrefix(prefix);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the prefix to " + prefix + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java
new file mode 100644
index 0000000..c9c5088
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetPriorityCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetPriorityCommand {
+
+ @Command(names = {"rank setpriority", "rank setweight"}, permission = "bridge.rank", description = "Set a ranks priority", hidden = true, async = true)
+ public static void RankSetPriorityCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "priority") int priority) {
+ r.setPriority(priority);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the priority to " + priority + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java
new file mode 100644
index 0000000..51185a3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetStaffCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetStaffCommand {
+
+ @Command(names = {"rank setstaff"}, permission = "bridge.rank", description = "Set a rank staff status", hidden = true, async = true)
+ public static void RankSetStaffCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "staff") boolean staff) {
+ r.setStaff(staff);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the staff status to " + staff + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java
new file mode 100644
index 0000000..9480c4e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/RankSetSuffixCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.rank;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class RankSetSuffixCommand {
+ @Command(names = {"rank setsuffix"}, permission = "bridge.rank", description = "Set a ranks suffix", hidden = true, async = true)
+ public static void RankSetSuffixCmd(CommandSender s, @Param(name = "rank") Rank r, @Param(name = "suffix", wildcard = true) String sfx) {
+ String suffix = ChatColor.translateAlternateColorCodes('&', sfx);
+ r.setSuffix(suffix);
+ r.saveRank();
+ s.sendMessage("§aSuccessfully changed the suffix to " + sfx + "§a!");
+ PacketHandler.sendToAll(new RankUpdatePacket(r, s.getName(), BridgeGlobal.getSystemName()));
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("bridge.update.view", "&8[&eServer Monitor&8] &fRefreshed rank " + r.getColor() + r.getDisplayName()));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java
new file mode 100644
index 0000000..24ce165
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PermissionsMenu.java
@@ -0,0 +1,172 @@
+package rip.bridge.bridge.bukkit.commands.rank.menu;
+
+import lombok.Getter;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.conversations.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.commands.rank.menu.buttons.PermissionButton;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.buttons.BackButton;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class PermissionsMenu extends PaginatedMenu {
+
+ @Getter private Rank rank;
+ private boolean viewAll = false;
+
+ public PermissionsMenu(Rank rank) {
+ this.rank = rank;
+ setAutoUpdate(true);
+ }
+
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ String str = rank.getColor() + rank.getDisplayName();
+ if(str.length() >= 16) str =str.substring(0, 16);
+ return str + ChatColor.YELLOW + "'s Perms";
+ }
+
+ @Override
+ public Map getGlobalButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+
+ buttonMap.put(2, new Button() {
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + (viewAll ? "Hide All" : "View All");
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Collections.singletonList("");
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return viewAll ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK;
+ }
+
+ @Override
+ public byte getDamageValue(Player var1) {
+ return 0;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ boolean toggle = !viewAll;
+ viewAll = toggle;
+ player.sendMessage(ChatColor.YELLOW + "You are now " + (toggle ? ChatColor.GREEN : ChatColor.RED + "no longer ") + "viewing" + ChatColor.YELLOW + " permissions on all scopes.");
+ }
+ });
+
+ buttonMap.put(4, new BackButton(new RankMenu(rank)));
+
+ buttonMap.put(6, new Button() {
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Add Permission";
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Collections.singletonList("");
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.ANVIL;
+ }
+
+ @Override
+ public byte getDamageValue(Player var1) {
+ return 0;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Please type a permission you wish to add, or type" + ChatColor.RED + " cancel " + ChatColor.YELLOW + "to cancel";
+ }
+
+ @Override
+ public Prompt acceptInput(ConversationContext cc, String s) {
+ if (s.equalsIgnoreCase("cancel")) {
+ cc.getForWhom().sendRawMessage(ChatColor.RED + "Permission adding process cancelled.");
+ return Prompt.END_OF_CONVERSATION;
+ }
+ defineScope((Player) cc.getForWhom(), s);
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ }).withLocalEcho(false).withEscapeSequence("/no").thatExcludesNonPlayersWithMessage("Go away evil console!");
+
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+ });
+
+
+ return buttonMap;
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+
+ AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ if(viewAll)
+ rank.getPermissions().keySet().forEach(str -> buttonMap.put(atomicInteger.getAndIncrement(), new PermissionButton(rank, str)));
+ else
+ rank.getActivePermissions().forEach(str -> buttonMap.put(atomicInteger.getAndIncrement(), new PermissionButton(rank, str)));
+
+ return buttonMap;
+
+ }
+
+ public void defineScope(Player player, String permission) {
+ ConversationFactory factory = new ConversationFactory(Bridge.getInstance()).withModality(true).withPrefix(new NullConversationPrefix()).withFirstPrompt(new StringPrompt() {
+
+ public String getPromptText(ConversationContext context) {
+ return ChatColor.YELLOW + "Type the name of the scope you wish to define this permission to. (Examples: Global, GR|Hub, Hub-1)";
+ }
+
+ @Override
+ public Prompt acceptInput(ConversationContext cc, String s) {
+ if(rank.hasPermission(permission, s)) {
+ cc.getForWhom().sendRawMessage(ChatColor.RED + "This rank already has this permission defined to the scope.");
+ new PermissionsMenu(rank).openMenu(player);
+ return Prompt.END_OF_CONVERSATION;
+ }
+ cc.getForWhom().sendRawMessage(ChatColor.YELLOW + "You have added the permission " + ChatColor.RED + permission + ChatColor.YELLOW + " to the scope " + ChatColor.RED + s + ChatColor.YELLOW + ".") ;
+ rank.togglePerm(permission, s);
+ rank.saveRank();
+ PacketHandler.sendToAll(new RankUpdatePacket(rank, player.getName(), BridgeGlobal.getSystemName()));
+ new PermissionsMenu(rank).openMenu(player);
+ return Prompt.END_OF_CONVERSATION;
+ }
+
+ }).withLocalEcho(false).withEscapeSequence("/no").thatExcludesNonPlayersWithMessage("Go away evil console!");
+
+ Conversation con = factory.buildConversation(player);
+ player.beginConversation(con);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java
new file mode 100644
index 0000000..fc653bd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/PlayerMenu.java
@@ -0,0 +1,85 @@
+package rip.bridge.bridge.bukkit.commands.rank.menu;
+
+import lombok.Getter;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.bukkit.commands.rank.menu.buttons.PlayerButton;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.buttons.BackButton;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class PlayerMenu extends PaginatedMenu {
+
+ @Getter private Rank rank;
+ private boolean viewAll = false;
+
+ public PlayerMenu(Rank rank) {
+ this.rank = rank;
+ setAutoUpdate(true);
+ }
+
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ String str = rank.getColor() + rank.getDisplayName();
+ if(str.length() >= 16) str =str.substring(0, 16);
+ return str + ChatColor.YELLOW + "'s Users";
+ }
+
+ @Override
+ public Map getGlobalButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+
+ buttonMap.put(2, new Button() {
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + (viewAll ? "Hide All" : "View All");
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Collections.singletonList("");
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return viewAll ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ boolean toggle = !viewAll;
+ viewAll = toggle;
+ player.sendMessage(ChatColor.YELLOW + "You are now " + (toggle ? ChatColor.GREEN : ChatColor.RED + "no longer ") + "viewing" + ChatColor.YELLOW + " grants on all scopes.");
+ }
+ });
+
+ buttonMap.put(6, new BackButton(new RankMenu(rank)));
+
+ return buttonMap;
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+
+ AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ if(viewAll)
+ rank.getProfilesInRank().stream().filter(profile -> profile.hasGrantOf(rank)).forEach(profile -> buttonMap.put(atomicInteger.getAndIncrement(), new PlayerButton(profile)));
+ else
+ rank.getProfilesInRank().stream().filter(profile -> profile.hasGrantOf(rank, true)).forEach(profile -> buttonMap.put(atomicInteger.getAndIncrement(), new PlayerButton(profile)));
+
+ return buttonMap;
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java
new file mode 100644
index 0000000..2cfdc8d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/RankMenu.java
@@ -0,0 +1,142 @@
+package rip.bridge.bridge.bukkit.commands.rank.menu;
+
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RankMenu extends Menu {
+
+ @Getter private Rank rank;
+
+ public RankMenu(Rank rank) {
+
+ this.rank = rank;
+ setAutoUpdate(true);
+
+ }
+
+ @Override
+ public String getTitle(Player player) {
+ return rank.getColor() + rank.getDisplayName();
+ }
+
+ @Override
+ public Map getButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+
+ buttonMap.put(2, new Button() {
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Permissions " + ChatColor.GRAY + "(" + rank.getActivePermissions().size() + ")";
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Arrays.asList(ChatColor.GRAY + "Click to view the active", ChatColor.GRAY + "permissions on this rank.");
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+
+ @Override
+ public byte getDamageValue(Player var1) {
+ return 0;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ new PermissionsMenu(rank).openMenu(player);
+ }
+ });
+
+ buttonMap.put(4, new Button() {
+ @Override
+ public String getName(Player player) {
+ return rank.getColor() + rank.getDisplayName();
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Arrays.asList(
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34),
+ ChatColor.YELLOW + "UUID: " + ChatColor.RED + rank.getUuid().toString(),
+ ChatColor.YELLOW + "Name: " + ChatColor.RED + rank.getName(),
+ "",
+ ChatColor.YELLOW + "Prefix: " + ChatColor.RED + rank.getPrefix().replace("§", "&") + "Color",
+ ChatColor.YELLOW + "Suffix: " + ChatColor.RED + rank.getSuffix().replace("§", "&") + "Color",
+ ChatColor.YELLOW + "Color: " + ChatColor.RED + rank.getColor().replace("§", "&") + "Color",
+ "",
+ ChatColor.YELLOW + "Priority: " + ChatColor.RED + rank.getPriority(),
+ ChatColor.YELLOW + "Staff: " + (rank.isStaff() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"),
+ ChatColor.YELLOW + "Hidden: " + (rank.isHidden() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"),
+ ChatColor.YELLOW + "Grantable: " + (rank.isGrantable() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"),
+ ChatColor.YELLOW + "Default: " + (rank.isDefaultRank() ? ChatColor.GREEN + "true" : ChatColor.RED + "false"),
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34)
+ );
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.SIGN;
+ }
+
+ @Override
+ public byte getDamageValue(Player var1) {
+ return 0;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+
+ }
+ });
+
+ buttonMap.put(6, new Button() {
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + "Players " + ChatColor.GRAY + "(" + rank.getProfilesInRank().size() + ")";
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Arrays.asList(
+ ChatColor.GRAY + "List of players that",
+ ChatColor.GRAY + "currently has this rank."
+ );
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.SKULL_ITEM;
+ }
+
+ @Override
+ public byte getDamageValue(Player player) {
+ return 3;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ new PlayerMenu(rank).openMenu(player);
+ }
+ });
+
+
+ return buttonMap;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java
new file mode 100644
index 0000000..ceed862
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PermissionButton.java
@@ -0,0 +1,57 @@
+package rip.bridge.bridge.bukkit.commands.rank.menu.buttons;
+
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.RankUpdatePacket;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.menu.Button;
+
+import java.util.Arrays;
+import java.util.List;
+
+@AllArgsConstructor
+public class PermissionButton extends Button {
+
+ private Rank rank;
+ private String str;
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.YELLOW + str;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Arrays.asList(
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34),
+ ChatColor.YELLOW + "Scope: " + ChatColor.RED + rank.getPermissions().get(str),
+ "",
+ ChatColor.RED.toString() + ChatColor.BOLD + "Click to remove",
+ ChatColor.RED.toString() + ChatColor.BOLD + "this permission",
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34));
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+
+ @Override
+ public byte getDamageValue(Player var1) {
+ return 0;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.sendMessage(ChatColor.YELLOW + "You have removed the permission " + ChatColor.RED + str + ChatColor.YELLOW + ".") ;
+ rank.togglePerm(str, rank.getPermissions().get(str));
+ rank.saveRank();
+ PacketHandler.sendToAll(new RankUpdatePacket(rank, player.getName(), BridgeGlobal.getSystemName()));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java
new file mode 100644
index 0000000..740ed76
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/rank/menu/buttons/PlayerButton.java
@@ -0,0 +1,69 @@
+package rip.bridge.bridge.bukkit.commands.rank.menu.buttons;
+
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.grant.menu.grants.GrantsMenu;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.menu.Button;
+
+import java.util.Arrays;
+import java.util.List;
+
+@AllArgsConstructor
+public class PlayerButton extends Button {
+
+ private Profile profile;
+
+ @Override
+ public String getName(Player player) {
+ return profile.getColor() + profile.getUsername();
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ List lore = Arrays.asList(
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34),
+ ChatColor.YELLOW + "Rank: " + ChatColor.RED + BukkitAPI.getPlayerRank(profile).getColor() + BukkitAPI.getPlayerRank(profile).getDisplayName(),
+ ChatColor.YELLOW + "Ranks: ");
+
+ profile.getActiveGrants().forEach(grant -> {
+ lore.add(ChatColor.GRAY + " * " + grant.getRank().getColor() + grant.getRank().getDisplayName() + ChatColor.GRAY + "(" + StringUtils.join(grant.getScope(), ", ") + ")");
+ });
+ lore.addAll(Arrays.asList("",
+ ChatColor.RED.toString() + ChatColor.BOLD + "Click to open",
+ ChatColor.RED.toString() + ChatColor.BOLD + "players grants",
+ ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 34)));
+ return lore;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.SKULL_ITEM;
+ }
+
+ @Override
+ public byte getDamageValue(Player player) {
+ return 3;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ player.closeInventory();
+ List allGrants = profile.getGrants();
+ allGrants.sort((first, second) -> {
+ if (first.getInitialTime() > second.getInitialTime()) {
+ return -1;
+ }
+ else {
+ return 1;
+ }
+ });
+ new GrantsMenu(profile, allGrants).openMenu(player);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java
new file mode 100644
index 0000000..aaba14c
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/BanLobby.java
@@ -0,0 +1,18 @@
+package rip.bridge.bridge.bukkit.commands.server;
+
+import lombok.Getter;
+import rip.bridge.bridge.bukkit.Bridge;
+
+public class BanLobby {
+
+ @Getter
+ private boolean maintenance, restricted, banLobbyEnabled;
+
+ public BanLobby() {
+ this.banLobbyEnabled = Bridge.getInstance().getConfig().getBoolean("server.ban-lobby");
+ }
+
+ //TODO: Do this shit later
+
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java
new file mode 100644
index 0000000..7b0b8a3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/DeploymentCommand.java
@@ -0,0 +1,14 @@
+package rip.bridge.bridge.bukkit.commands.server;
+
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.bukkit.commands.server.menu.deployment.DeploymentMenu;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class DeploymentCommand {
+
+ @Command(names = {"deploy", "deployment"}, permission = "bridge.deployment", description = "Deploy a server", hidden = true)
+ public static void deployCmd(Player s, @Param(name = "serverName") String serverName) {
+ new DeploymentMenu(serverName).openMenu(s);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java
new file mode 100644
index 0000000..4f9dafc
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/NetworkStatsCommand.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.commands.server;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.qlib.command.Command;
+
+public class NetworkStatsCommand {
+
+ @Command(names = "networkstats", permission = "bridge.server.stats", description = "View all online servers", hidden = true)
+ public static void networkstats(Player player) {
+ player.sendMessage(ChatColor.BLUE + "Network Stats");
+ player.sendMessage(ChatColor.YELLOW + "Online: " + ChatColor.WHITE + BridgeGlobal.getServerHandler().getServer("BungeeCord").getOnline());
+ player.sendMessage(ChatColor.YELLOW + "Total Profiles: " + ChatColor.WHITE + BridgeGlobal.getMongoHandler().getProfiles().size());
+ player.sendMessage(ChatColor.YELLOW + "Total Ranks: " + ChatColor.WHITE + BridgeGlobal.getRankHandler().getRanks().size());
+ player.sendMessage(ChatColor.YELLOW + "Online Servers " + ChatColor.WHITE + BridgeGlobal.getServerHandler().getServers().size());
+ player.sendMessage(ChatColor.YELLOW + "Disguised Players: " + ChatColor.WHITE + BridgeGlobal.getDisguiseManager().getDisguisePlayers().size());
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java
new file mode 100644
index 0000000..268aa70
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ServersCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands.server;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.commands.server.menu.server.ServerMenu;
+import rip.bridge.qlib.command.Command;
+
+public class ServersCommand {
+
+ @Command(names = "servers", permission = "bridge.server.list", description = "View all online servers", hidden = true)
+ public static void servers(Player player) {
+ if (BridgeGlobal.getServerHandler().getServers().isEmpty()) {
+ player.sendMessage(ChatColor.RED + "There are no servers found...");
+ return;
+ }
+ new ServerMenu().openMenu(player);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java
new file mode 100644
index 0000000..94a08d6
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/ShutdownCommand.java
@@ -0,0 +1,22 @@
+package rip.bridge.bridge.bukkit.commands.server;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.ServerShutdownPacket;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class ShutdownCommand {
+
+ @Command(names = {"shutdown"}, permission = "bridge.server.shutdown", description = "Shutdown a server", hidden = true)
+ public static void shutdown(Player s, @Param(name = "server") String serverName) {
+ PacketHandler.sendToAll(new ServerShutdownPacket(serverName));
+ if (serverName.equalsIgnoreCase("all")) {
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fRemoving all servers..."));
+ } else {
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fRemoving server " + serverName + "..."));
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java
new file mode 100644
index 0000000..f67b7d5
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupInfoCommand.java
@@ -0,0 +1,24 @@
+package rip.bridge.bridge.bukkit.commands.server.group;
+
+import mkremins.fanciful.FancyMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class GroupInfoCommand {
+
+ @Command(names = {"group info"}, permission = "bridge.group.info", description = "Get information about a server group", hidden = true)
+ public static void groupList(CommandSender s, @Param(name = "group", wildcard = true) String g) {
+ if (BridgeGlobal.getServerHandler().getServersInGroup(g) == null) {
+ s.sendMessage(ChatColor.RED + "There is no such group with the name \"" + g + "\".");
+ return;
+ }
+ s.sendMessage(StringUtils.repeat(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "-", 35));
+ s.sendMessage(ChatColor.RED + "Servers in the group " + g + ":");
+ BridgeGlobal.getServerHandler().getServersInGroup(g).forEach(serv -> new FancyMessage(ChatColor.RED + serv.getName()).tooltip(ChatColor.GRAY + "Click to view information about the server.").command("/serverinfo info " + serv.getName()).send(s));
+ s.sendMessage(StringUtils.repeat(ChatColor.BLUE.toString() + ChatColor.STRIKETHROUGH + "-", 35));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java
new file mode 100644
index 0000000..948603f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/group/GroupListCommand.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.commands.server.group;
+
+import mkremins.fanciful.FancyMessage;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.command.Command;
+
+public class GroupListCommand {
+
+ @Command(names = {"group list"}, permission = "bridge.group.list", description = "List all available server groups", hidden = true)
+ public static void groupList(CommandSender s) {
+ if (BridgeGlobal.getServerHandler().getGroups() == null) {
+ s.sendMessage(ChatColor.RED + "There are no server groups...");
+ return;
+ }
+ FancyMessage m = new FancyMessage(ChatColor.GREEN + "Available Groups: ");
+ BridgeGlobal.getServerHandler().getGroups().forEach(serv -> m.then(serv + " ").tooltip(ChatColor.GRAY + "Click to view servers in the group.").command("/group info " + serv));
+ m.send(s);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java
new file mode 100644
index 0000000..7862dbb
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/CompleteButton.java
@@ -0,0 +1,67 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.deployment;
+
+import com.google.common.collect.Lists;
+import net.md_5.bungee.api.ChatColor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.packet.PacketHandler;
+import rip.bridge.bridge.global.packet.types.NetworkBroadcastPacket;
+import rip.bridge.bridge.global.packet.types.ServerDeployPacket;
+import rip.bridge.qlib.menu.Button;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CompleteButton
+extends Button {
+ private DeploymentMenu parent;
+ private List plugins;
+
+ public String getName(Player player) {
+ return ChatColor.GREEN + "Confirm and Update";
+ }
+
+ public List getDescription(Player player) {
+ ArrayList description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', (int)30));
+ description.add(ChatColor.BLUE + "Click to deploy " + ChatColor.WHITE + this.plugins.size() + " plugins" + ChatColor.BLUE + " to the server " + ChatColor.WHITE + this.parent.getServerName() + ChatColor.BLUE + ".");
+ description.add("");
+ this.plugins.forEach(file -> description.add(ChatColor.GRAY + " * " + ChatColor.WHITE + file.getName() + ' ' + BridgeGlobal.getUpdaterManager().getStatus((File)file).getPrefix()));
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', (int)30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.DIAMOND_SWORD;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.update(this.plugins, player);
+ }
+
+ private void update(List plugins, Player player) {
+ if (plugins.isEmpty()) {
+ player.sendMessage(ChatColor.RED + "You must select a plugin you wish to deploy!");
+ return;
+ }
+ PacketHandler.sendToAll(new ServerDeployPacket(parent.getServerName(), plugins));
+ player.sendMessage(ChatColor.GREEN + "Attempting to deploy a server with name \"" + parent.getServerName() + "\" now.");
+ this.parent.setComplete(true);
+ PacketHandler.sendToAll(new NetworkBroadcastPacket("basic.staff", "&8[&eServer Monitor&8] &fAdding server " + parent.getServerName() + "..."));
+ player.closeInventory();
+ }
+
+ public CompleteButton(DeploymentMenu parent, List plugins) {
+ this.parent = parent;
+ this.plugins = plugins;
+ }
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java
new file mode 100644
index 0000000..1664631
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/DeploymentMenu.java
@@ -0,0 +1,83 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.deployment;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class DeploymentMenu extends Menu {
+
+ private String serverName;
+
+ private Map status;
+
+ private boolean complete;
+
+ public String getServerName() {
+ return serverName;
+ }
+
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public void setStatus(Map status) {
+ this.status = status;
+ }
+
+ public void setComplete(boolean complete) {
+ this.complete = complete;
+ }
+
+ public Map getStatus() {
+ return this.status;
+ }
+
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+ public String getTitle(Player player) {
+ return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Deployment - " + this.serverName;
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ List plugins = BridgeGlobal.getUpdaterManager().getFilesForGroup("ALL");
+ int i = 0;
+ for (File file : plugins) {
+ this.status.putIfAbsent(file, Boolean.FALSE);
+ buttons.put(i, new PluginButton(this, file));
+ i++;
+ }
+ List scopes = Lists.newArrayList();
+ scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList()));
+ buttons.put(31, new CompleteButton(this, scopes));
+ return buttons;
+ }
+
+ public void onClose(final Player player) {
+ (new BukkitRunnable() {
+ public void run() {
+ if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !DeploymentMenu.this.complete)
+ player.sendMessage(ChatColor.RED + "Server deployment cancelled.");
+ }
+ }).runTaskLater(Bridge.getInstance(), 1L);
+ }
+
+ public DeploymentMenu(String serverName) {
+ this.status = Maps.newHashMap();
+ this.serverName = serverName;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java
new file mode 100644
index 0000000..c1de85d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/deployment/PluginButton.java
@@ -0,0 +1,56 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.deployment;
+
+import com.google.common.collect.Lists;
+import lombok.AllArgsConstructor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.menu.Button;
+
+import java.io.File;
+import java.util.List;
+
+@AllArgsConstructor
+public class PluginButton extends Button {
+
+ private DeploymentMenu parent;
+ private File plugin;
+
+ public String getName(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ return (status ? ChatColor.GREEN : ChatColor.RED) + this.plugin.getName() + " " + BridgeGlobal.getUpdaterManager().getStatus(plugin).getPrefix();
+ }
+
+ public List getDescription(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ if (status) {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " from the deployment list.");
+ }
+ else {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " to the deployment list.");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.parent.getStatus().put(this.plugin, !this.parent.getStatus().getOrDefault(this.plugin, false));
+ }
+
+}
+
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java
new file mode 100644
index 0000000..16c5802
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/groups/GroupMenu.java
@@ -0,0 +1,16 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.groups;
+
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+
+import java.util.Map;
+
+public class GroupMenu extends Menu {
+
+ @Override
+ public Map getButtons(Player player) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java
new file mode 100644
index 0000000..f48df0d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ExtraInformationMenu.java
@@ -0,0 +1,55 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.server;
+
+import lombok.AllArgsConstructor;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.bukkit.commands.server.menu.server.buttons.DataButton;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.bridge.global.status.start.ServerStartThread;
+import rip.bridge.bridge.global.util.JsonChain;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.buttons.BackButton;
+import rip.bridge.qlib.menu.menus.ConfirmMenu;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@AllArgsConstructor
+public class ExtraInformationMenu extends PaginatedMenu {
+
+ private final BridgeServer server;
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ return ChatColor.YELLOW + "Extra information: " + server.getName();
+ }
+
+ @Override
+ public Map getGlobalButtons(Player player) {
+ Map buttons = new HashMap<>();
+ buttons.put(4, new BackButton(new ServerMenu()));
+ return buttons;
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ Map buttons = new HashMap<>();
+
+ AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ try {
+ server.getMetadata().entrySet().forEach(str -> {
+ buttons.put(atomicInteger.getAndIncrement(), new DataButton(str.getKey(), server.getMetadata().get(str.getKey()).toString()));
+ });
+ } catch (Exception ex) {
+ buttons.put(4, Button.placeholder(Material.REDSTONE_BLOCK, ChatColor.RED + "This server has no extra information."));
+ }
+ return buttons;
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java
new file mode 100644
index 0000000..ff483b3
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerActionMenu.java
@@ -0,0 +1,76 @@
+
+package rip.bridge.bridge.bukkit.commands.server.menu.server;
+
+import lombok.AllArgsConstructor;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.bridge.global.status.start.ServerStartThread;
+import rip.bridge.bridge.global.util.JsonChain;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.buttons.BackButton;
+import rip.bridge.qlib.menu.menus.ConfirmMenu;
+import rip.bridge.qlib.menu.pagination.PaginatedMenu;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@AllArgsConstructor
+public class ServerActionMenu extends PaginatedMenu {
+
+ private final BridgeServer server;
+
+ @Override
+ public String getPrePaginatedTitle(Player player) {
+ return ChatColor.YELLOW + "Server Actions: " + server.getName();
+ }
+
+ @Override
+ public Map getGlobalButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+ buttonMap.put(4, new BackButton(new ServerMenu()));
+ return buttonMap;
+ }
+
+ @Override
+ public Map getAllPagesButtons(Player player) {
+ Map buttons = new HashMap<>();
+// buttons.put(4, Button.placeholder(Material.REDSTONE_BLOCK, ChatColor.RED + "This server has no additional actions."));
+ buttons.put(4, new Button() {
+ @Override
+ public String getName(Player player) {
+ return server.isOnline() ? ChatColor.RED + ChatColor.BOLD.toString() + "Shutdown" : ChatColor.GREEN + ChatColor.BOLD.toString() + "Start Up";
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return null;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return server.isOnline() ? Material.REDSTONE_BLOCK : Material.EMERALD_BLOCK;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ new ConfirmMenu("Are you sure?", (b) -> {
+ if (b) {
+ if (server.isOnline()) {
+ new JsonChain().addProperty("server", server.getName()).get();
+ } else {
+ new ServerStartThread(server).start();
+ }
+ }
+ new ServerMenu().openMenu(player);
+ }).openMenu(player);
+ }
+ });
+
+ return buttons;
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java
new file mode 100644
index 0000000..bc8193f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/ServerMenu.java
@@ -0,0 +1,39 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.server;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.commands.server.menu.server.buttons.ServerButton;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class ServerMenu extends Menu {
+
+ public ServerMenu() {
+ super(ChatColor.YELLOW + ChatColor.BOLD.toString() + "Servers");
+ setAutoUpdate(true);
+ }
+
+ @Override
+ public Map getButtons(Player player) {
+ Map buttonMap = new HashMap<>();
+ AtomicInteger atomicInteger = new AtomicInteger(0);
+ BridgeGlobal.getServerHandler().getServers().values().stream().sorted(Comparator.comparingLong(this::getStartTime)).forEach(s -> {
+ buttonMap.put(atomicInteger.getAndIncrement(), new ServerButton(s));
+ });
+ return buttonMap;
+ }
+
+ private long getStartTime(BridgeServer server) {
+ try {
+ return server.getBootTime();
+ } catch (Exception ignored) {}
+ return System.currentTimeMillis();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java
new file mode 100644
index 0000000..925c65b
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/DataButton.java
@@ -0,0 +1,32 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.server.buttons;
+
+import lombok.AllArgsConstructor;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.menu.Button;
+
+import java.util.Collections;
+import java.util.List;
+
+@AllArgsConstructor
+public class DataButton extends Button {
+
+ private String data;
+ private String value;
+
+ @Override
+ public String getName(Player player) {
+ return ChatColor.LIGHT_PURPLE + data;
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ return Collections.singletonList(ChatColor.GRAY + value);
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ return Material.PAPER;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java
new file mode 100644
index 0000000..243f9ff
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/menu/server/buttons/ServerButton.java
@@ -0,0 +1,82 @@
+package rip.bridge.bridge.bukkit.commands.server.menu.server.buttons;
+
+import lombok.AllArgsConstructor;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import rip.bridge.bridge.bukkit.commands.server.menu.server.ExtraInformationMenu;
+import rip.bridge.bridge.bukkit.commands.server.menu.server.ServerActionMenu;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.util.BungeeUtils;
+import rip.bridge.qlib.util.TPSUtils;
+import rip.bridge.qlib.util.TimeUtil;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@AllArgsConstructor
+public class ServerButton extends Button {
+
+ private BridgeServer server;
+
+ @Override
+ public String getName(Player player) {
+ return (!server.isOnline() ? ChatColor.RED : server.isWhitelisted() ? ChatColor.WHITE : ChatColor.GREEN) + server.getName();
+ }
+
+ @Override
+ public List getDescription(Player player) {
+ List lore = new ArrayList<>();
+
+ if(!server.isOnline()) {
+ lore.add(ChatColor.RED + "This server has recently gone offline");
+ }else {
+ if(server.getTps() != 0.0) {
+ lore.add(ChatColor.YELLOW + "TPS: " + ChatColor.WHITE + TPSUtils.formatTPS(server.getTps(), true));
+ }
+ lore.add(ChatColor.YELLOW + "Online: " + ChatColor.WHITE + server.getOnline() + " / " + server.getMaximum());
+ lore.add(ChatColor.YELLOW + "Status: " + ChatColor.WHITE + server.formattedStatus(true));
+ if(!server.getMotd().isEmpty()) {
+ lore.add(ChatColor.YELLOW + "MOTD: " + ChatColor.WHITE + server.getMotd());
+ }
+ lore.add("");
+ lore.add(ChatColor.YELLOW + "System Type: " + ChatColor.WHITE + server.getSystemType());
+ lore.add(ChatColor.YELLOW + "Group: " + ChatColor.WHITE + server.getGroup());
+ lore.add(ChatColor.YELLOW + "Provider: " + ChatColor.WHITE + server.getProvider());
+ lore.add("");
+ lore.add(ChatColor.YELLOW + "Server Started At: " + ChatColor.WHITE + TimeUtils.formatIntoCalendarString(new Date(server.getBootTime())));
+ lore.add(ChatColor.YELLOW + "Uptime: " + ChatColor.WHITE + TimeUtil.millisToTimer(System.currentTimeMillis() - server.getBootTime()));
+ lore.add(ChatColor.YELLOW + "Last Updated: " + ChatColor.WHITE + TimeUtil.millisToTimer(System.currentTimeMillis() - server.getLastHeartbeat()));
+ lore.add("");
+ lore.add(ChatColor.GRAY + "Left click to connect.");
+ lore.add((server.getMetadata() == null ? ChatColor.RED + "This server has no extra information." : ChatColor.GREEN + "Right click to for more information."));
+ }
+
+ return lore;
+ }
+
+ @Override
+ public Material getMaterial(Player player) {
+ if(!server.isOnline()) return Material.REDSTONE_BLOCK;
+ if(server.getStatus().equals("BOOTING")) return Material.GOLD_BLOCK;
+ if(server.isWhitelisted()) return Material.GOLD_BLOCK;
+ if(server.isOnline()) return Material.EMERALD_BLOCK;
+
+ return Material.REDSTONE_BLOCK;
+ }
+
+ @Override
+ public void clicked(Player player, int slot, ClickType clickType) {
+ if(clickType == ClickType.LEFT) {
+ player.closeInventory();
+ BungeeUtils.send(player, server.getName());
+ }else if(clickType == ClickType.RIGHT) {
+ player.closeInventory();
+ new ExtraInformationMenu(server).openMenu(player);
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java
new file mode 100644
index 0000000..445e566
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoCommand.java
@@ -0,0 +1,36 @@
+package rip.bridge.bridge.bukkit.commands.server.serverinfo;
+
+import mkremins.fanciful.FancyMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.status.BridgeServer;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.util.TPSUtils;
+
+public class ServerInfoCommand {
+
+ @Command(names = {"serverinfo info"}, permission = "bridge.server.info", description = "Get information about a server group", hidden = true)
+ public static void serverInfo(CommandSender s, @Param(name = "server", wildcard = true) String server) {
+ if (BridgeGlobal.getServerHandler().getServer(server) == null) {
+ s.sendMessage(ChatColor.RED + "There is no such server with the name \"" + server + "\".");
+ return;
+ }
+ BridgeServer bridgeServer = BridgeGlobal.getServerHandler().getServer(server);
+ s.sendMessage(StringUtils.repeat(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "-", 45));
+ s.sendMessage(ChatColor.GOLD + bridgeServer.getName() + ChatColor.GRAY + " [" + bridgeServer.getOnline() + '/' + bridgeServer.getMaximum() + "]");
+ s.sendMessage(ChatColor.YELLOW + "Provider: " + ChatColor.RED + bridgeServer.getProvider());
+ s.sendMessage(ChatColor.YELLOW + "Status: " + bridgeServer.formattedStatus(true));
+ if (!bridgeServer.getMotd().isEmpty())
+ s.sendMessage(ChatColor.YELLOW + "MOTD: " + ChatColor.RED + bridgeServer.getMotd());
+ if (bridgeServer.getTps() != 0.0)
+ s.sendMessage(ChatColor.YELLOW + "TPS: " + ChatColor.RED + TPSUtils.formatTPS(bridgeServer.getTps(), true));
+ if (bridgeServer.getSystemType().equals("BUKKIT")) {
+ boolean wl = bridgeServer.isWhitelisted();
+ new FancyMessage(ChatColor.YELLOW + "Whitelisted: ").then(ChatColor.RED + (wl ? "True" : "False")).tooltip(ChatColor.AQUA + "Click to change to change whitelist status.").command("/serverinfo whitelist " + bridgeServer.getName()).send(s);
+ }
+ s.sendMessage(StringUtils.repeat(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + "-", 45));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java
new file mode 100644
index 0000000..06cd826
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/server/serverinfo/ServerInfoListCommand.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.commands.server.serverinfo;
+
+import mkremins.fanciful.FancyMessage;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.command.Command;
+
+public class ServerInfoListCommand {
+
+ @Command(names = {"serverinfo list"}, permission = "bridge.server.list", description = "List all available server groups", hidden = true)
+ public static void serverList(CommandSender s) {
+ if (BridgeGlobal.getServerHandler().getServers().isEmpty()) {
+ s.sendMessage(ChatColor.RED + "There are no servers found...");
+ return;
+ }
+ FancyMessage m = new FancyMessage(ChatColor.GREEN + "Available Servers: ");
+ BridgeGlobal.getServerHandler().getServers().values().forEach(serv -> m.then(serv.getName() + " ").tooltip(ChatColor.GRAY + "Click to view information about the server.").command("/serverinfo info " + serv.getName()));
+ m.send(s);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java
new file mode 100644
index 0000000..2beb321
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterDisableCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.bukkit.util.PluginUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+
+public class UpdaterDisableCommand {
+
+ @Command(names = "updater disable", permission = "bridge.updater", hidden = true, description = "Disables a specific plugins")
+ public static void disable(CommandSender sender, @Param(name = "plugin") Plugin plugin) {
+ PluginUtil.disable(plugin);
+ sender.sendMessage(ChatColor.GREEN + "Disabled " + plugin.getName() + ".");
+ }
+
+ @Command(names = "updater disable all", permission = "bridge.updater", hidden = true, description = "Disables all plugins")
+ public static void disableall(CommandSender sender) {
+ PluginUtil.disableAll();
+ sender.sendMessage(ChatColor.GREEN + "Disabled all plugins.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java
new file mode 100644
index 0000000..4da7550
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterEnableCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.bukkit.util.PluginUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+
+public class UpdaterEnableCommand {
+
+ @Command(names = "updater enable", permission = "bridge.updater", hidden = true, description = "Enables a specific plugin")
+ public static void enable(CommandSender sender, @Param(name = "plugin") Plugin plugin) {
+ PluginUtil.enable(plugin);
+ sender.sendMessage(ChatColor.GREEN + "Enabled " + plugin.getName() + ".");
+ }
+
+ @Command(names = "updater enable all", permission = "bridge.updater", hidden = true, description = "Enables all plugins")
+ public static void enableall(CommandSender sender) {
+ PluginUtil.enableAll();
+ sender.sendMessage(ChatColor.GREEN + "Enabled all plugins.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java
new file mode 100644
index 0000000..cb4d3ec
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterInfoCommand.java
@@ -0,0 +1,28 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.qlib.command.Command;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.io.File;
+import java.util.List;
+
+public class UpdaterInfoCommand {
+
+ @Command(names = "updater info", permission = "bridge.updater", hidden = true, description = "Check information about the updater.")
+ public static void info(CommandSender sender) {
+ sender.sendMessage(BukkitAPI.LINE);
+ sender.sendMessage("§6§lUpdater §7❘ §fInformation");
+ sender.sendMessage(BukkitAPI.LINE);
+ sender.sendMessage(ChatColor.YELLOW + "Updating for Group: " + ChatColor.WHITE + StringUtils.join(BridgeGlobal.getUpdaterGroups(), ", ") + " & Global");
+ sender.sendMessage(ChatColor.YELLOW + "Using Root Directory: " + ChatColor.WHITE + BridgeGlobal.getUpdaterManager().getPluginUpdateDir());
+
+ List fileList = BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups());
+ sender.sendMessage(ChatColor.YELLOW + "Plugins available: " + ChatColor.WHITE + (fileList == null || fileList.isEmpty() ? "N/A" : fileList.size()));
+ sender.sendMessage(ChatColor.GRAY.toString() + ChatColor.ITALIC + "Use /updater list to list all available plugins...");
+ sender.sendMessage(BukkitAPI.LINE);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java
new file mode 100644
index 0000000..5c3d5cb
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterListCommand.java
@@ -0,0 +1,36 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.updater.UpdateStatus;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+public class UpdaterListCommand {
+
+ @Command(names = "updater list", permission = "bridge.updater", hidden = true, description = "List all files in your group")
+ public static void list(CommandSender sender, @Param(name = "group", defaultValue = "current") String groupName) {
+ List files = BridgeGlobal.getUpdaterManager().getFilesForGroup((groupName.equals("current") ? BridgeGlobal.getUpdaterGroups() : Collections.singletonList(groupName)));
+ sender.sendMessage(BukkitAPI.LINE);
+ sender.sendMessage("§6§lUpdater §7❘ §fList");
+ sender.sendMessage(BukkitAPI.LINE);
+ if (files == null) {
+ sender.sendMessage(ChatColor.RED + "The directory for the group does not exist...");
+ } else if (files.isEmpty()) {
+ sender.sendMessage(ChatColor.RED + "No available plugins for this group...");
+ } else {
+ files.forEach(file -> {
+ UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file);
+ sender.sendMessage(ChatColor.YELLOW + file.getName() + ChatColor.GRAY + " (" + file.getPath() + ")" + (file.getAbsolutePath().contains("Global") ? ChatColor.RED + " [Global]" : "") + ' ' + updateStatus.getPrefix());
+ });
+ }
+ sender.sendMessage(BukkitAPI.LINE);
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java
new file mode 100644
index 0000000..cefc392
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterLoadCommand.java
@@ -0,0 +1,14 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.bukkit.util.PluginUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.command.CommandSender;
+
+public class UpdaterLoadCommand {
+
+ @Command(names = "updater load", permission = "bridge.updater", hidden = true, description = "Loads a plugin")
+ public static void load(CommandSender sender, @Param(name = "fileName", wildcard = true) String fileName) {
+ sender.sendMessage(PluginUtil.load(fileName));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java
new file mode 100644
index 0000000..8ffaab7
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterReloadCommand.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.bukkit.util.PluginUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+
+public class UpdaterReloadCommand {
+
+ @Command(names = "updater reload", permission = "bridge.updater", hidden = true, description = "Reloads a specific plugin")
+ public static void reload(CommandSender sender, @Param(name = "plugin") Plugin plugin) {
+ PluginUtil.reload(plugin);
+ sender.sendMessage(ChatColor.GREEN + "Reloaded " + plugin.getName() + ".");
+ }
+
+ @Command(names = "updater reload all", permission = "bridge.updater", hidden = true, description = "Reloads all plugins")
+ public static void reloadall(CommandSender sender) {
+ PluginUtil.reloadAll();
+ sender.sendMessage(ChatColor.GREEN + "Reloaded all plugins.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java
new file mode 100644
index 0000000..ad85e8a
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUnloadCommand.java
@@ -0,0 +1,15 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.bukkit.util.PluginUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+
+public class UpdaterUnloadCommand {
+
+ @Command(names = "updater unload", permission = "bridge.updater", hidden = true, description = "Unloads a plugin")
+ public static void load(CommandSender sender, @Param(name = "plugin", wildcard = true) Plugin plugin) {
+ sender.sendMessage(PluginUtil.unload(plugin));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java
new file mode 100644
index 0000000..187270b
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/UpdaterUpdateCommand.java
@@ -0,0 +1,49 @@
+package rip.bridge.bridge.bukkit.commands.updater;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.commands.updater.menu.UpdaterMenu;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+public class UpdaterUpdateCommand {
+
+ @Command(names = "updater update", permission = "bridge.updater", hidden = true, description = "Update specific plugins")
+ public static void update(CommandSender sender, @Param(name = "pluginname", defaultValue = "none") String pluginName) {
+ List group = BridgeGlobal.getUpdaterGroups();
+ List files = BridgeGlobal.getUpdaterManager().getFilesForGroup(group);
+ switch (pluginName) {
+ case "all": {
+ BridgeGlobal.getUpdaterManager().updatePlugins(files, cons -> sender.sendMessage(ChatColor.BLUE + cons));
+ break;
+ }
+
+ case "none": {
+ if (!(sender instanceof Player)) {
+ sender.sendMessage(ChatColor.RED + "Sorry ingame only!");
+ return;
+ }
+ new UpdaterMenu(group).openMenu((Player) sender);
+ break;
+ }
+
+ default: {
+ File pluginFile = files.stream().filter(file -> file.getName().equalsIgnoreCase(pluginName)).findAny().orElse(null);
+ if (pluginFile == null) {
+ sender.sendMessage(ChatColor.RED + "There is no such plugin file by the name \"" + pluginName + "\", use /updater list to get a list of plugins.");
+ return;
+ }
+
+ sender.sendMessage(ChatColor.GREEN + "Attempting to update " + pluginFile.getName() + "!");
+ BridgeGlobal.getUpdaterManager().updatePlugins(Collections.singletonList(pluginFile), cons -> sender.sendMessage(ChatColor.BLUE + cons));
+ }
+
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java
new file mode 100644
index 0000000..3ac5ee2
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupAddCommand.java
@@ -0,0 +1,27 @@
+package rip.bridge.bridge.bukkit.commands.updater.group;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+
+public class UpdaterGroupAddCommand {
+
+ @Command(names = "updater group add", permission = "bridge.updater", hidden = true, description = "Add a group to the update group")
+ public static void groupadd(CommandSender sender, @Param(name = "group") String group) {
+ List configGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups");
+ if (BridgeGlobal.getUpdaterGroups().stream().anyMatch(s -> s.equalsIgnoreCase(group))) {
+ sender.sendMessage(ChatColor.RED + "This group is already in the update list.");
+ return;
+ }
+ BridgeGlobal.addUpdaterGroup(group);
+ configGroups.add(group);
+ Bridge.getInstance().getConfig().set("updaterGroups", configGroups);
+ Bridge.getInstance().saveConfig();
+ sender.sendMessage(ChatColor.GREEN + "Successfully added the group \"" + group + "\" to the update groups.");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java
new file mode 100644
index 0000000..d52ba8e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/group/UpdaterGroupRemoveCommand.java
@@ -0,0 +1,28 @@
+package rip.bridge.bridge.bukkit.commands.updater.group;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+
+public class UpdaterGroupRemoveCommand {
+
+ @Command(names = "updater group remove", permission = "bridge.updater", hidden = true, description = "Remove a group from the update group")
+ public static void groupremove(CommandSender sender, @Param(name = "group") String group) {
+ List configGroups = Bridge.getInstance().getConfig().getStringList("updaterGroups");
+ if(BridgeGlobal.getUpdaterGroups().stream().noneMatch(s -> s.equalsIgnoreCase(group))) {
+ sender.sendMessage(ChatColor.RED + "There is no such group in the list with the name \"" + group + "\".");
+ return;
+ }
+ BridgeGlobal.removeUpdaterGroup(group);
+ configGroups.remove(group);
+ Bridge.getInstance().getConfig().set("updaterGroups", configGroups);
+ Bridge.getInstance().saveConfig();
+ sender.sendMessage(ChatColor.GREEN + "Successfully removed the group \"" + group + "\" from the update groups.");
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java
new file mode 100644
index 0000000..17087e4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/CompleteButton.java
@@ -0,0 +1,60 @@
+package rip.bridge.bridge.bukkit.commands.updater.menu;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.menu.Button;
+import lombok.AllArgsConstructor;
+import net.md_5.bungee.api.ChatColor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.io.File;
+import java.util.List;
+
+@AllArgsConstructor
+public class CompleteButton extends Button {
+
+ private UpdaterMenu parent;
+ private List plugins;
+
+ public String getName(Player player) {
+ return ChatColor.GREEN + "Confirm and Update";
+ }
+
+ public List getDescription(Player player) {
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ description.add(ChatColor.BLUE + "Click to update " + ChatColor.WHITE + this.plugins.size() + " plugins" + ChatColor.BLUE + " for the groups " + ChatColor.WHITE + StringUtils.join(this.parent.getGroups(), ", ") + ChatColor.BLUE + ".");
+ description.add("");
+ plugins.forEach(file -> description.add(ChatColor.GRAY + " * " + ChatColor.WHITE + file.getName() + ' ' + BridgeGlobal.getUpdaterManager().getStatus(file).getPrefix()));
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.DIAMOND_SWORD;
+ }
+
+ public byte getDamageValue(Player player) {
+ return 0;
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.update(this.plugins, player);
+ }
+
+ private void update(List plugins, Player player) {
+ if(plugins.isEmpty()) {
+ player.sendMessage(ChatColor.RED + "You must select a plugin you wish to update!");
+ return;
+ }
+
+ BridgeGlobal.getUpdaterManager().updatePlugins(plugins, cons -> player.sendMessage(ChatColor.BLUE + cons));
+ player.sendMessage(ChatColor.DARK_RED.toString() + ChatColor.BOLD + "! YOU WILL NEED TO RESTART FOR CHANGES TO TAKE PLACE !");
+ this.parent.setComplete(true);
+ player.closeInventory();
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java
new file mode 100644
index 0000000..60c5e6f
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/PluginButton.java
@@ -0,0 +1,54 @@
+package rip.bridge.bridge.bukkit.commands.updater.menu;
+
+import com.google.common.collect.Lists;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.qlib.menu.Button;
+import lombok.AllArgsConstructor;
+import net.minecraft.util.org.apache.commons.lang3.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import java.io.File;
+import java.util.List;
+
+@AllArgsConstructor
+public class PluginButton extends Button {
+ private UpdaterMenu parent;
+ private File plugin;
+
+ public String getName(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ return (status ? ChatColor.GREEN : ChatColor.RED) + this.plugin.getName() + " " + BridgeGlobal.getUpdaterManager().getStatus(plugin).getPrefix();
+ }
+
+ public List getDescription(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ List description = Lists.newArrayList();
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ if (status) {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.RED + "remove " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " from the update list.");
+ }
+ else {
+ description.add(ChatColor.BLUE + "Click to " + ChatColor.GREEN + "add " + ChatColor.YELLOW + this.plugin.getName() + ChatColor.BLUE + " to the update list.");
+ }
+ description.add(ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH + StringUtils.repeat('-', 30));
+ return description;
+ }
+
+ public Material getMaterial(Player player) {
+ return Material.WOOL;
+ }
+
+ public byte getDamageValue(Player player) {
+ boolean status = this.parent.getStatus().get(this.plugin);
+ return status ? DyeColor.LIME.getWoolData() : DyeColor.GRAY.getWoolData();
+ }
+
+ public void clicked(Player player, int i, ClickType clickType) {
+ this.parent.getStatus().put(this.plugin, !this.parent.getStatus().getOrDefault(this.plugin, false));
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java
new file mode 100644
index 0000000..6cf5f45
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/updater/menu/UpdaterMenu.java
@@ -0,0 +1,65 @@
+package rip.bridge.bridge.bukkit.commands.updater.menu;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.global.updater.UpdateStatus;
+import rip.bridge.qlib.menu.Button;
+import rip.bridge.qlib.menu.Menu;
+import lombok.Getter;
+import lombok.Setter;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Getter @Setter
+public class UpdaterMenu extends Menu {
+
+ private List groups;
+ private Map status;
+ private boolean complete;
+
+ public String getTitle(Player player) {
+ return ChatColor.YELLOW.toString() + ChatColor.BOLD + "Updater";
+ }
+
+ public Map getButtons(Player player) {
+ Map buttons = Maps.newHashMap();
+ List plugins = BridgeGlobal.getUpdaterManager().getFilesForGroup(groups).stream().filter(file -> {
+ UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file);
+ return updateStatus != UpdateStatus.ERROR && updateStatus != UpdateStatus.LATEST;
+ }).collect(Collectors.toList());
+
+ int i = 0;
+ for (File file : plugins) {
+ this.status.putIfAbsent(file, false);
+ buttons.put(i, new PluginButton(this, file));
+ ++i;
+ }
+ List scopes = Lists.newArrayList();
+ scopes.addAll(this.status.keySet().stream().filter(this.status::get).collect(Collectors.toList()));
+ buttons.put(31, new CompleteButton(this, scopes));
+ return buttons;
+ }
+
+ public void onClose(Player player) {
+ new BukkitRunnable() {
+ public void run() {
+ if (!Menu.currentlyOpenedMenus.containsKey(player.getName()) && !UpdaterMenu.this.complete) {
+ player.sendMessage(ChatColor.RED + "Updating cancelled.");
+ }
+ }
+ }.runTaskLater(Bridge.getInstance(), 1L);
+ }
+
+ public UpdaterMenu(List groups) {
+ this.status = Maps.newHashMap();
+ this.groups = groups;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java
new file mode 100644
index 0000000..d30cf6c
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserDeleteCommand.java
@@ -0,0 +1,25 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class UserDeleteCommand {
+
+ @Command(names = {"user delete"}, permission = "bridge.user", description = "Delete a players profile", async = true, hidden = true)
+ public static void UserDeleteCmd(CommandSender s, @Param(name = "player", extraData = "get") Profile pf) {
+ BridgeGlobal.getMongoHandler().removeProfile(pf.getUuid(), callback -> {
+ if (callback) {
+ if (Bukkit.getOfflinePlayer(pf.getUuid()).isOnline())
+ Bukkit.getPlayer(pf.getUuid()).kickPlayer("§cYour profile has been deleted - please reconnect.");
+ BridgeGlobal.getProfileHandler().getProfiles().remove(pf);
+ s.sendMessage("§aSuccessfully deleted " + pf.getUsername() + "'s Profile.");
+ } else {
+ s.sendMessage("§cFailed to delete " + pf.getUsername() + "'s Profile.");
+ }
+ }, false);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java
new file mode 100644
index 0000000..dcf587e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserInfoCommand.java
@@ -0,0 +1,43 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.util.TimeUtil;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.Date;
+
+public class UserInfoCommand {
+
+ @Command(names = {"user info", "user check"}, permission = "bridge.user", description = "Get information about a players profile", async = true, hidden = true)
+ public static void UserInfoCmd(CommandSender s, @Param(name = "player", extraData = "get") Profile pf) {
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage(BukkitAPI.getColor(pf) + pf.getUsername() + " §7❘ §fProfile Information");
+ s.sendMessage(BukkitAPI.LINE);
+ s.sendMessage("§6UUID: §f" + pf.getUuid());
+ s.sendMessage("§6Rank: §f" + pf.getCurrentGrant().getRank().getColor() + pf.getCurrentGrant().getRank().getDisplayName());
+ s.sendMessage("§6Grants: §f" + pf.getActiveGrants().size() + " active | " + pf.getGrants().size() + " total");
+ s.sendMessage("§6Punishments: §f" + pf.getActivePunishments().size() + " active | " + pf.getPunishments().size() + " total");
+ s.sendMessage("§6Permissions (" + pf.getPermissions().size() + ChatColor.GOLD + "): ");
+ if (pf.getPermissions().isEmpty()) s.sendMessage(ChatColor.RED + "None...");
+ else pf.getPermissions().keySet().forEach(str -> {
+ s.sendMessage(ChatColor.GRAY + " * " + ChatColor.WHITE + str + ChatColor.GRAY + " [" + pf.getPermissions().get(str) + "]");
+ });
+ s.sendMessage("");
+// s.sendMessage("§6Prefix: §f" + BukkitAPI.getPrefix(pf) + " §7(" + ChatColor.stripColor(BukkitAPI.getPrefix(pf).replace("§", "&")) + ")");
+// s.sendMessage("§6Suffix: §f" + BukkitAPI.getSuffix(pf) + " §7(" + ChatColor.stripColor(BukkitAPI.getSuffix(pf).replace("§", "&")) + ")");
+ s.sendMessage("§6First Joined: §f" + TimeUtils.formatIntoCalendarString(new Date(pf.getFirstJoined())));
+ if (pf.isOnline()) {
+ s.sendMessage("§6Connected to: §f" + BridgeGlobal.getServerHandler().findPlayerServer(pf.getUuid()).getName() + (BridgeGlobal.getServerHandler().findPlayerProxy(pf.getUuid()) != null ? " §7[" + BridgeGlobal.getServerHandler().findPlayerProxy(pf.getUuid()).getName() + "]" : ""));
+ } else {
+// s.sendMessage("§6Last Seen: §7(" + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - pf.getLastQuit()) + " ago)");
+ s.sendMessage("§6Last Server: §f" + pf.getConnectedServer() + " §7(" + TimeUtil.millisToRoundedTime(System.currentTimeMillis() - pf.getLastQuit()) + " ago)");
+ }
+ s.sendMessage(BukkitAPI.LINE);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java
new file mode 100644
index 0000000..f7d91b7
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserPermissionCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.bukkit.listener.GeneralListener;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class UserPermissionCommand {
+
+ @Command(names = {"user permission", "user perm"}, permission = "bridge.user", description = "Add/Remove a player's permission", hidden = true, async = true)
+ public static void UserPermissionCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "permission") String perm, @Param(name = "group", defaultValue = "§") String serverGroup) {
+ String group = serverGroup.equals("§") ? "Global" : serverGroup;
+ boolean b = pf.togglePerm(perm, group);
+ pf.saveProfile();
+ GeneralListener.updatePermissions(pf.getUuid());
+ s.sendMessage("§aSuccessfully " + (b ? "added" : "removed") + " the permission " + perm + " to the scope: " + group);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java
new file mode 100644
index 0000000..de6af15
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetColorCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class UserSetColorCommand {
+
+ @Command(names = {"user setcolor", "user setcolour"}, permission = "bridge.user", description = "Set a players color", async = true, hidden = true)
+ public static void UserSetColorCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "color") String col) {
+ String tag = ChatColor.translateAlternateColorCodes('&', col);
+ if (col.equals("clear")) tag = "";
+ pf.setColor(tag);
+ pf.saveProfile();
+ s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the color of " + pf.getUsername() + (!tag.equals("") ? " to " + tag + pf.getUsername() : ""));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java
new file mode 100644
index 0000000..ff2583e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetPrefixCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class UserSetPrefixCommand {
+
+ @Command(names = {"user setprefix"}, permission = "bridge.user", description = "Set a players prefix", async = true, hidden = true)
+ public static void UserSetPrefixCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "prefix", wildcard = true) String prefix) {
+ String tag = ChatColor.translateAlternateColorCodes('&', prefix);
+ if (prefix.equals("clear")) tag = "";
+ pf.setPrefix(tag);
+ pf.saveProfile();
+ s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the prefix of " + pf.getUsername() + (!tag.equals("") ? " to " + tag : ""));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java
new file mode 100644
index 0000000..8502588
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/commands/user/UserSetSuffixCommand.java
@@ -0,0 +1,19 @@
+package rip.bridge.bridge.bukkit.commands.user;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.command.CommandSender;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.Command;
+import rip.bridge.qlib.command.Param;
+
+public class UserSetSuffixCommand {
+
+ @Command(names = {"user setsuffix"}, permission = "bridge.user", description = "Set a players suffix", async = true, hidden = true)
+ public static void UserSetSuffixCmd(CommandSender s, @Param(name = "player") Profile pf, @Param(name = "suffix", wildcard = true) String suffix) {
+ String tag = ChatColor.translateAlternateColorCodes('&', suffix);
+ if (suffix.equals("clear")) tag = "";
+ pf.setSuffix(tag);
+ pf.saveProfile();
+ s.sendMessage("§aSuccessfully " + (tag.equals("") ? "cleared" : "set") + " the suffix of " + pf.getUsername() + (!tag.equals("") ? " to " + tag : ""));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java
new file mode 100644
index 0000000..8a6a894
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/listener/BridgeListener.java
@@ -0,0 +1,244 @@
+package rip.bridge.bridge.bukkit.listener;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.parameters.packets.filter.FilterViolationPacket;
+import rip.bridge.bridge.bukkit.util.Chat;
+import rip.bridge.bridge.global.handlers.MongoHandler;
+import rip.bridge.bridge.global.disguise.DisguisePlayer;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.bridge.global.filter.FilterAction;
+import rip.bridge.bridge.global.grant.Grant;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.bridge.global.updater.UpdateStatus;
+import rip.bridge.bridge.global.util.EncryptionHandler;
+import rip.bridge.bridge.global.util.Msg;
+import rip.bridge.bridge.global.util.Tasks;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.bukkit.commands.punishment.create.MuteCommand;
+import rip.bridge.qlib.chat.ChatHandler;
+import rip.bridge.qlib.chat.ChatPlayer;
+import rip.bridge.qlib.chat.ChatPopulator;
+import rip.bridge.qlib.nametag.FrozenNametagHandler;
+import rip.bridge.qlib.tab.FrozenTabHandler;
+import rip.bridge.qlib.xpacket.FrozenXPacketHandler;
+import mkremins.fanciful.FancyMessage;
+import net.md_5.bungee.api.ChatColor;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import java.io.File;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class BridgeListener implements Listener {
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onAsyncPlayerPreLoginLOWEST(AsyncPlayerPreLoginEvent event) {
+ Player player = Bukkit.getPlayer(event.getName());
+
+ if (player != null) {
+ BridgeGlobal.getDisguiseManager().undisguise(player, true, true);
+ //event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, ChatColor.RED + "Someone is already online with your name.");
+ Tasks.run(() -> player.kickPlayer(ChatColor.RED + "You were kicked because the owner of this disguised name has joined."));
+ }
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onLogin(AsyncPlayerPreLoginEvent e) {
+ UUID uuid = e.getUniqueId();
+ String loggedInIP = EncryptionHandler.encryptUsingKey(e.getAddress().getHostAddress());
+ AtomicReference atomicReference = new AtomicReference<>();
+
+ BridgeGlobal.getMongoHandler().loadProfile(uuid.toString(), atomicReference::set, false, MongoHandler.LoadType.UUID);
+
+ Profile profile = atomicReference.get();
+ if (profile == null)
+ (profile = new Profile(e.getName(), uuid, false)).applyGrant(Grant.getDefaultGrant(), null, false);
+
+ if (loggedInIP != null) {
+ profile.checkTotpLock(profile.getUuid(), loggedInIP);
+
+ if (profile.getCurrentIPAddress() == null) profile.setCurrentIPAddress(loggedInIP);
+
+ if (profile.getActivePunishments(PunishmentType.BAN).size() > 0) {
+ Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BAN).toArray()[0];
+ e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : ""));
+ saveLatestIP(profile, loggedInIP);
+ return;
+ }
+
+ if (profile.getActivePunishments(PunishmentType.BLACKLIST).size() > 0) {
+ Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0];
+ e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : ""));
+ saveLatestIP(profile, loggedInIP);
+ return;
+ }
+
+ if (!profile.getCurrentIPAddress().equals(loggedInIP)) {
+ List altProfiles = BridgeGlobal.getMongoHandler().getProfiles(loggedInIP);
+
+ for (Profile alt : altProfiles) {
+ if (alt.getActivePunishments(PunishmentType.BAN).size() > 0 || alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 0) {
+ Punishment punishment = (Punishment) profile.getActivePunishments(PunishmentType.BAN).toArray()[0];
+ if (punishment == null)
+ punishment = (Punishment) profile.getActivePunishments(PunishmentType.BLACKLIST).toArray()[0];
+
+ e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, GeneralListener.getPunishmentMessage(punishment, punishment.isIP() ? loggedInIP : ""));
+ return;
+ }
+ }
+ }
+ }
+
+ BridgeGlobal.getProfileHandler().addProfile(profile);
+ profile.setCurrentIPAddress(loggedInIP);
+ profile.getPreviousIPAddresses().add(loggedInIP);
+ }
+
+ private void saveLatestIP(Profile profile, String loggedInIP) {
+ profile.setCurrentIPAddress(loggedInIP);
+ profile.getPreviousIPAddresses().add(loggedInIP);
+ profile.saveProfile();
+ }
+
+ @EventHandler
+ public void onJoin(PlayerJoinEvent e) {
+ Player p = e.getPlayer();
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getPlayer().getUniqueId());
+
+ if (profile != null) {
+ profile.refreshCurrentGrant();
+ FrozenNametagHandler.reloadPlayer(p);
+ }
+
+ Bukkit.getScheduler().runTaskAsynchronously(Bridge.getInstance(), () -> {
+
+ if (profile != null) {
+ if (profile.getFirstJoined() == 0) profile.setFirstJoined(System.currentTimeMillis());
+ profile.setLastJoined(System.currentTimeMillis());
+ profile.setUsername(p.getName());
+ profile.saveProfile();
+
+ BridgeGlobal.getDisguiseManager().load(profile.getUsername(), profile.getUuid());
+
+ Runnable runnable = () -> {
+ DisguisePlayer disguisePlayer = BridgeGlobal.getDisguiseManager().getDisguisePlayers().get(profile.getUuid());
+
+ if (disguisePlayer != null) {
+ if (p.hasPermission("bridge.disguise")) {
+ try {
+ if (BridgeGlobal.getDisguiseManager().disguise(p, disguisePlayer, null, true, true, false)) {
+ p.sendMessage(org.bukkit.ChatColor.GREEN + "");
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ Msg.logConsole(ChatColor.RED + "Failed to disguise " + p.getName() + "!");
+ }
+ } else {
+ p.sendMessage(ChatColor.RED + "Since you don't have disguise permission your disguised profile has been removed.");
+ BridgeGlobal.getDisguiseManager().save(p.getUniqueId(), false);
+ }
+ }
+ };
+
+ if (FrozenTabHandler.getLayoutProvider() != null) {
+ Tasks.runAsyncLater(runnable, 10L);
+ } else {
+ runnable.run();
+ }
+
+ List altProfiles = BridgeGlobal.getMongoHandler().getProfiles(profile.getCurrentIPAddress());
+ List formattedName = new ArrayList<>();
+ if (!altProfiles.isEmpty() && altProfiles.size() > 1) {
+ for (Profile alt : altProfiles) {
+ if (alt.getUuid().equals(profile.getUuid())) return;
+ if (Bukkit.getOfflinePlayer(alt.getUuid()).isOnline())
+ formattedName.add(ChatColor.GREEN + alt.getUsername());
+ else if (alt.getActivePunishments(PunishmentType.BLACKLIST).size() > 1)
+ formattedName.add(ChatColor.DARK_RED + alt.getUsername());
+ else if (alt.getActivePunishments(PunishmentType.BAN).size() > 1)
+ formattedName.add(ChatColor.RED + alt.getUsername());
+ else formattedName.add(ChatColor.GRAY + alt.getUsername());
+ }
+ GeneralListener.broadcastMessage("&6&l[Alts] " + BukkitAPI.getColor(profile) + p.getName() + " &eis possibly &cban evading &7(" + (formattedName.size()) + " accounts)" + "\n" + StringUtils.join(formattedName, ChatColor.WHITE + ", "), "bridge.alts.sendmessage");
+ }
+ }
+//
+// if (p.hasPermission("op") && BridgeGlobal.getUpdaterManager().getFilesForGroup(Objects.requireNonNull(BridgeGlobal.getUpdaterGroups())).stream().anyMatch(file -> BridgeGlobal.getUpdaterManager().getStatus(file).isShouldUpdate())) {
+// p.sendMessage(ChatColor.LIGHT_PURPLE.toString() + (int) BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups()).stream().filter(file -> BridgeGlobal.getUpdaterManager().getStatus(file).isShouldUpdate()).count() + ChatColor.YELLOW + " update is available, install with " + ChatColor.LIGHT_PURPLE + "/updater update" + ChatColor.YELLOW + ".");
+// List files = BridgeGlobal.getUpdaterManager().getFilesForGroup(BridgeGlobal.getUpdaterGroups());
+// files.forEach(file1 -> {
+// UpdateStatus updateStatus = BridgeGlobal.getUpdaterManager().getStatus(file1);
+// p.sendMessage(ChatColor.GRAY + "- " + ChatColor.YELLOW + file1.getName() + " " + updateStatus.getPrefix());
+// });
+// }
+ });
+ }
+
+ @EventHandler
+ public void onChat(AsyncPlayerChatEvent e) {
+ if (e.getPlayer().hasMetadata("NoSpamCheck")) {
+ return;
+ }
+ Profile profile = BukkitAPI.getProfile(e.getPlayer());
+ if (profile == null) {
+ e.setCancelled(true);
+ return;
+ }
+
+ if (profile.isMuted()) {
+ e.setCancelled(true);
+ e.getPlayer().sendMessage(ChatColor.RED + "You are currently muted.");
+ e.getPlayer().sendMessage(ChatColor.RED + (profile.getMute().isPermanent() ? "This mute is permanent." : "Time remaining: " + profile.getMute().getRemainingString()));
+ return;
+ }
+
+ Filter filter = BridgeGlobal.getFilterHandler().isViolatingFilter(ChatColor.stripColor(e.getMessage()));
+
+ if (filter != null && !e.getPlayer().hasPermission("basic.staff")) {
+ if (filter.getFilterAction() == FilterAction.MUTE)
+ MuteCommand.muteCmd(Bukkit.getConsoleSender(), false, profile, filter.getMuteTime(), " \"" + e.getMessage() + "\"");
+ FrozenXPacketHandler.sendToAll(new FilterViolationPacket(Bukkit.getServerName(), e.getPlayer().getName(), null, e.getMessage()));
+ e.setCancelled(true);
+
+ ChatPlayer chatPlayer = ChatHandler.getChatPlayer(e.getPlayer().getUniqueId());
+
+ ChatPopulator chatPopulator = chatPlayer.getRegisteredPopulators().stream().filter(chatPopulator1 -> chatPopulator1.getChatChar() == e.getMessage().charAt(0)).findFirst().orElse(null);
+ if (chatPopulator == null) chatPopulator = chatPlayer.getSelectedPopulator();
+
+ e.getPlayer().sendMessage(chatPopulator.layout(e.getPlayer(), e.getMessage()));
+ return;
+ }
+
+ Rank rank = BukkitAPI.getPlayerRank(e.getPlayer());
+ e.setMessage(rank.isStaff() ? ChatColor.translateAlternateColorCodes('&', e.getMessage()) : e.getMessage());
+ e.setFormat(BukkitAPI.getColor(e.getPlayer()) + BukkitAPI.getPrefix(e.getPlayer()) + e.getPlayer().getName() + BukkitAPI.getSuffix(e.getPlayer()) + "§r: %2$s");
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent e) {
+ Profile profile = BridgeGlobal.getProfileHandler().getProfileByUUID(e.getPlayer().getUniqueId());
+
+ if (profile != null) {
+ profile.setLastQuit(System.currentTimeMillis());
+ profile.setConnectedServer(BridgeGlobal.getSystemName());
+ profile.saveProfile();
+ BridgeGlobal.getProfileHandler().getProfiles().remove(profile);
+ }
+
+ BridgeGlobal.getDisguiseManager().leave(e.getPlayer().getUniqueId());
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java
new file mode 100644
index 0000000..6dbd025
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/listener/FreezeListener.java
@@ -0,0 +1,129 @@
+package rip.bridge.bridge.bukkit.listener;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryOpenEvent;
+import org.bukkit.event.player.*;
+import org.bukkit.metadata.MetadataValue;
+
+public class FreezeListener implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
+ String command = event.getMessage().toLowerCase();
+ boolean whitelistedCommand = command.startsWith("/freezeserver") || command.startsWith("/auth") || command.startsWith("/register") || command.startsWith("/2fasetup") || command.startsWith("/setup2fa");
+ if (!whitelistedCommand && event.getPlayer().hasMetadata("Locked")) {
+ event.getPlayer().sendMessage((event.getPlayer().getMetadata("Locked").get(0)).asString());
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.getPlayer().sendMessage((event.getPlayer().getMetadata("Locked").get(0)).asString());
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onPlayerDropItem(PlayerDropItemEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onInventoryOpen(InventoryOpenEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onBlockBreak(BlockBreakEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onBlockPlace(BlockPlaceEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onEntityDamage(EntityDamageByEntityEvent event) {
+ if (event.getDamager() instanceof Player && event.getDamager().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onPlayerBucketFill(PlayerBucketFillEvent event) {
+ if (event.getPlayer().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(
+ priority = EventPriority.HIGHEST
+ )
+ public void onInventoryClick(InventoryClickEvent event) {
+ if (event.getWhoClicked().hasMetadata("Locked")) {
+ event.setCancelled(true);
+ }
+
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java b/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java
new file mode 100644
index 0000000..a7c3986
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/listener/GeneralListener.java
@@ -0,0 +1,284 @@
+package rip.bridge.bridge.bukkit.listener;
+
+import org.bukkit.scheduler.BukkitRunnable;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import rip.bridge.bridge.bukkit.util.BaseEvent;
+import rip.bridge.bridge.bukkit.util.Chat;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.bridge.global.punishment.PunishmentType;
+import rip.bridge.bridge.global.ranks.Rank;
+import mkremins.fanciful.FancyMessage;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.permissions.PermissionAttachment;
+import org.spigotmc.SpigotConfig;
+import rip.bridge.bridge.global.punishment.Punishment;
+import rip.bridge.qlib.util.PlayerUtils;
+import rip.bridge.qlib.util.TimeUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+public class GeneralListener {
+
+
+ public static void updatePermissions(UUID uuid) {
+ Player player = Bukkit.getPlayer(uuid);
+
+ if (player != null) {
+
+ Profile profile = BukkitAPI.getProfile(uuid);
+ profile.updateColor();
+ PermissionAttachment permissionAttachment = player.addAttachment(Bridge.getInstance());
+ List perms = profile.getPermissions().keySet().stream().filter(profile::hasPermission).collect(Collectors.toList());
+ profile.getPermissions().keySet().stream().filter(profile::hasPermission).forEach(permission->{
+
+ if (permission.startsWith("-")) {
+ permission = permission.substring(1);
+ permissionAttachment.unsetPermission(permission);
+ } else {
+ permissionAttachment.setPermission(permission, true);
+ }
+
+ });
+
+ profile.getActiveGrants().forEach(grant->{
+ perms.addAll(grant.getRank().getPermissions().keySet().stream().filter(s -> grant.getRank().hasPermission(s)).collect(Collectors.toList()));
+ grant.getRank().getPermissions().keySet().stream().filter(s -> grant.getRank().hasPermission(s)).forEach(permission->{
+ if (permission.startsWith("-")) {
+ permission = permission.substring(1);
+ permissionAttachment.unsetPermission(permission);
+ } else {
+ permissionAttachment.setPermission(permission, true);
+ }
+ });
+ grant.getRank().getInherits().forEach(inherit->{
+ perms.addAll(inherit.getPermissions().keySet().stream().filter(inherit::hasPermission).collect(Collectors.toList()));
+ inherit.getPermissions().keySet().stream().filter(inherit::hasPermission).forEach(permission -> {
+ if (permission.startsWith("-")) {
+ permission = permission.substring(1);
+ permissionAttachment.unsetPermission(permission);
+ } else {
+ permissionAttachment.setPermission(permission, true);
+ }
+ });
+ });
+ });
+ player.recalculatePermissions();
+ profile.setActivePermissions(perms);
+
+ String totpMessage = null;
+
+ if (profile.isTotpRequired() && !player.hasMetadata("ForceAuth")) {
+ if (profile.getSecretKey().isEmpty() && profile.getCurrentGrant().getRank().isStaff()) {
+ totpMessage = ChatColor.RED + ChatColor.BOLD.toString() + "Please setup your 2FA code";
+ } else {
+ totpMessage = ChatColor.RED + ChatColor.BOLD.toString() + "Please enter your 2FA code";
+ }
+
+ player.setMetadata("Locked", new FixedMetadataValue(Bridge.getInstance(), totpMessage));
+ } else {
+ player.removeMetadata("Locked", Bridge.getInstance());
+ }
+
+ String finalTotpMessage = totpMessage;
+ (new BukkitRunnable() {
+ public void run() {
+ if (finalTotpMessage != null) {
+ player.sendMessage(finalTotpMessage);
+ }
+
+ }
+ }).runTaskLater(Bridge.getInstance(), 10L);
+
+ }
+ }
+
+ public static void updateColor(UUID uuid) {
+ Player player = Bukkit.getPlayer(uuid);
+ if (player != null) {
+ player.setDisplayName(BukkitAPI.getPlayerRank(player).getColor() + player.getName() + "§r");
+ if(player.hasMetadata("RankPrefix")) player.removeMetadata("RankPrefix", Bridge.getInstance());
+ player.setMetadata("RankPrefix", new FixedMetadataValue(Bridge.getInstance(), (BukkitAPI.getPlayerRank(player).getPrefix())));
+ }
+ }
+
+ public static String getServerStatus() {
+ return (Bridge.getInstance().isBooted() ? (Bukkit.hasWhitelist() ? "WHITELISTED" : "ONLINE") : "BOOTING");
+ }
+
+ public static void refreshPlayersInRank(Rank rank) {
+ BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile-> Bukkit.getPlayer(profile.getUuid()) != null && profile.hasActiveGrantOf(rank)).forEach(Profile::refreshCurrentGrant);
+ }
+
+ public static void logMessages(String msg, boolean packetIncoming) {
+ if(packetIncoming) Bukkit.getOnlinePlayers().stream().filter(Player::isOp).forEach(player -> player.sendMessage(msg));
+ Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', msg));
+ if(BridgeGlobal.getProfileHandler() != null && !BridgeGlobal.getProfileHandler().getProfiles().isEmpty()) BridgeGlobal.getProfileHandler().getProfiles().stream().filter(profile -> Bukkit.getPlayer(profile.getUuid()) != null && profile.isDebug()).forEach(profile -> Bukkit.getPlayer(profile.getUuid()).sendMessage(msg));
+ }
+
+ public static void broadcastMessage(String msg, String permission) {
+ String m = ChatColor.translateAlternateColorCodes('&', msg);
+ Bukkit.getConsoleSender().sendMessage(m);
+ if(permission.equals("")) Bukkit.broadcastMessage(m);
+ else Bukkit.getOnlinePlayers().stream().filter(p -> p.hasPermission(permission)).forEach(p -> p.sendMessage(m));
+ }
+
+ public static void broadcastMessage(String msg) {
+ broadcastMessage(msg, "");
+ }
+
+ public static void broadcastMessage(BaseComponent[] msg, String permission) {
+ Bukkit.getConsoleSender().sendMessage(TextComponent.toPlainText(msg));
+ if(permission.equals("")) {
+ Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(msg));
+ }else {
+ Bukkit.getOnlinePlayers().stream().filter(p -> p.hasPermission(permission)).forEach(p -> p.spigot().sendMessage(msg));
+ }
+ }
+
+ public static void sendMessage(String msg, List players) {
+ players.forEach(p -> p.sendMessage(ChatColor.translateAlternateColorCodes('&', msg)));
+ }
+
+ public static void sendMessage(BaseComponent[] msg, List players) {
+ players.forEach(p -> p.spigot().sendMessage(msg));
+ }
+
+ public static void broadcastMessage(BaseComponent[] msg) {
+ broadcastMessage(msg, "");
+ }
+
+ public static void callEvent(Object cls) {
+ ((BaseEvent)cls).call();
+ }
+
+ public static void shutdown() {
+ Bukkit.shutdown();
+ }
+
+ public static boolean hasPermission(Profile profile, String permisson) {
+ return Bukkit.getOfflinePlayer(profile.getUuid()).isOp() || profile.getActiveGrants().parallelStream().filter(grant -> grant.isGrantActiveOnScope() && grant.isStillActive()).anyMatch(grant -> grant.getRank().hasPermission(permisson) || profile.hasPermission(permisson) || profile.getActivePermissions().contains(permisson));
+ }
+
+ public static boolean isOP(Profile profile) {
+ if(profile == null || Bukkit.getOfflinePlayer(profile.getUuid()) == null) return false;
+ return Bukkit.getOfflinePlayer(profile.getUuid()).isOp();
+ }
+
+ private boolean isRunningOnBungee(){
+ return SpigotConfig.bungee && (!(Bukkit.getServer().getOnlineMode()));
+ }
+
+ public static void handlePunishment(Punishment punishment, boolean pardon) {
+ Bukkit.getOnlinePlayers().forEach(p -> {
+ FancyMessage m = new FancyMessage((punishment.isSilent() ? ChatColor.GRAY + "[Silent] " + ChatColor.GREEN : "") +
+ BukkitAPI.getColor(punishment.getTarget()) + (punishment.getTarget().getDisguise() != null ? punishment.getTarget().getDisguise().getDisguiseName() : punishment.getTarget().getUsername()) +
+ ChatColor.GREEN + " was " + punishment.getDisplayName() +
+ " by " +
+ (pardon ? BukkitAPI.getColor(punishment.getPardonedBy()) + (punishment.getPardonedBy().getDisguise() != null ? punishment.getPardonedBy().getDisguise().getDisguiseName() : punishment.getPardonedBy().getUsername()) + ChatColor.GREEN + "." : BukkitAPI.getColor(punishment.getExecutor()) + (punishment.getExecutor().getDisguise() != null ? punishment.getExecutor().getDisguise().getDisguiseName() : punishment.getExecutor().getUsername()) +
+ ChatColor.GREEN + "."));
+ m.command("/c " + punishment.getTarget().getUsername());
+
+ List lore = new ArrayList<>();
+ lore.add(ChatColor.YELLOW + "Reason: " + ChatColor.RED + (pardon ? punishment.getPardonedReason() : punishment.getReason()));
+ if(!pardon && !punishment.getPunishmentType().equals(PunishmentType.KICK)) lore.add(ChatColor.YELLOW + "Duration: " + ChatColor.RED + punishment.getRemainingString());
+ lore.add(ChatColor.YELLOW + "Click to view on website");
+
+
+ boolean staff = BukkitAPI.getPlayerRank(p, true).isStaff();
+ if(staff) m.tooltip(lore);
+ if(punishment.isSilent()) {
+ if(staff) m.send(p);
+ }else {
+ m.send(p);
+ }
+ });
+
+ if(pardon) {
+ Punishment p = punishment.getTarget().getPunishmentByID(punishment.getUuid());
+ p.setPardoned(pardon);
+ p.setPardonedAt(punishment.getPardonedAt());
+ p.setPardonedBy(punishment.getPardonedBy().getUuid());
+ p.setPardonedReason(punishment.getPardonedReason());
+ p.setPardonedServer(punishment.getPardonedServer());
+ }else {
+
+ if(punishment.isIP()) {
+ Bukkit.getOnlinePlayers().stream().filter(p -> BukkitAPI.getProfile(p) != null && BukkitAPI.getProfile(p).getCurrentIPAddress().equals(punishment.getTarget().getCurrentIPAddress())).forEach(target -> {
+ if(target != null) Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> {
+ BukkitAPI.getProfile(target).getPunishments().add(punishment);
+ if(punishment.isClear()) PlayerUtils.resetInventory(target);
+ if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) {
+ target.kickPlayer(getPunishmentMessage(punishment));
+ }else if(punishment.getPunishmentType() == PunishmentType.WARN){
+ target.sendMessage("");
+ target.sendMessage("");
+ target.sendMessage(ChatColor.RED.toString() + ChatColor.BOLD.toString() + "You have been warned: " + ChatColor.YELLOW.toString() + ChatColor.BOLD + punishment.getReason());
+ target.sendMessage("");
+ target.sendMessage("");
+ }else if(punishment.getPunishmentType() == PunishmentType.MUTE) {
+ target.sendMessage(ChatColor.RED + "You have been muted.");
+ target.sendMessage(ChatColor.RED + (punishment.isPermanent() ? "This mute is permanent." : "Time remaining: " + TimeUtils.formatIntoDetailedString((int) (punishment.getDuration() / 1000))));
+ }
+ });
+ if(punishment.isClear()) PlayerUtils.resetInventory(target);
+ if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) target.kickPlayer(getPunishmentMessage(punishment));
+ });
+ }else {
+ Player target = Bukkit.getPlayer(punishment.getTarget().getUuid());
+ if(target != null) Bukkit.getScheduler().runTask(Bridge.getInstance(), () -> {
+ if(punishment.isClear()) PlayerUtils.resetInventory(target);
+ if(punishment.getPunishmentType() != PunishmentType.WARN && punishment.getPunishmentType() != PunishmentType.MUTE) {
+ target.kickPlayer(getPunishmentMessage(punishment));
+ }else if(punishment.getPunishmentType() == PunishmentType.WARN){
+ target.sendMessage("");
+ target.sendMessage("");
+ target.sendMessage(ChatColor.RED + ChatColor.BOLD.toString() + "You have been warned: " + ChatColor.YELLOW + ChatColor.BOLD + punishment.getReason());
+ target.sendMessage("");
+ target.sendMessage("");
+ }else if(punishment.getPunishmentType() == PunishmentType.MUTE) {
+ target.sendMessage(ChatColor.RED + "You have been muted.");
+ target.sendMessage(ChatColor.RED + (punishment.isPermanent() ? "This mute is permanent." : "Time remaining: " + TimeUtils.formatIntoDetailedString((int) (punishment.getDuration() / 1000))));
+ }
+ });
+ }
+ }
+ }
+
+ public static String getPunishmentMessage(Punishment punishment, String IP) {
+ String msg = "";
+ switch(punishment.getPunishmentType()) {
+ case BLACKLIST: {
+ msg = ChatColor.RED + "Your account has been blacklisted from the " + BridgeGlobal.getServerDisplayName() + "\n\nThis type of punishment cannot be appealed.";
+ break;
+ }
+ case BAN: {
+ msg = ChatColor.RED + "Your account has been suspended from the " + BridgeGlobal.getServerDisplayName() + (!punishment.isPermanent() ? "\n\nExpires in " + punishment.getRemainingString() + "." : ChatColor.RED + "\n\nAppeal at " + BridgeGlobal.getServerWebsite() + "/appeal");
+ break;
+ }
+ case KICK: {
+ msg = ChatColor.RED + "You were kicked: " + punishment.getReason();
+ }
+ }
+ return msg + (punishment.getPunishmentType() != PunishmentType.BLACKLIST && punishment.isIP() && !IP.equals("") && punishment.getTarget().getCurrentIPAddress().equals(IP) ? "\n\n" + ChatColor.RED + "This punishment is assiciated with " + punishment.getTarget().getUsername() : "");
+ }
+
+ public static String getPunishmentMessage(Punishment punishment) {
+ return getPunishmentMessage(punishment, "");
+ }
+
+
+
+
+
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java
new file mode 100644
index 0000000..019f302
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AlertPacket.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Bukkit;
+import rip.bridge.qlib.xpacket.XPacket;
+
+
+public class AlertPacket implements XPacket {
+
+ private String message;
+ private boolean raw;
+
+ public AlertPacket(String message, boolean raw) {
+ this.message = message;
+ this.raw = raw;
+ }
+
+
+ @Override
+ public void onReceive() {
+ Bukkit.broadcastMessage((raw ? "" : ChatColor.DARK_GRAY + "[" + ChatColor.DARK_RED + "Alert" + ChatColor.DARK_GRAY + "] " + ChatColor.WHITE) + ChatColor.translateAlternateColorCodes('&', message));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java
new file mode 100644
index 0000000..56b987b
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePacket.java
@@ -0,0 +1,21 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import net.md_5.bungee.api.ChatColor;
+import org.bukkit.Bukkit;
+import rip.bridge.qlib.xpacket.XPacket;
+
+
+public class AnnouncePacket implements XPacket {
+
+ private String message;
+
+ public AnnouncePacket(String message) {
+ this.message = message;
+ }
+
+
+ @Override
+ public void onReceive() {
+ Bukkit.broadcastMessage(ChatColor.GRAY + "[" + ChatColor.GREEN + "Alert" + ChatColor.GRAY + "] " + ChatColor.WHITE + ChatColor.translateAlternateColorCodes('&', message));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java
new file mode 100644
index 0000000..131e35c
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/AnnouncePackets.java
@@ -0,0 +1,39 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import mkremins.fanciful.FancyMessage;
+import net.minecraft.util.org.apache.commons.lang3.text.WordUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import rip.bridge.qlib.xpacket.XPacket;
+
+
+public class AnnouncePackets implements XPacket {
+
+ private String message = "";
+ private String server;
+
+
+
+ public AnnouncePackets(String message, String server) {
+ this.message = message;
+ this.server = server;
+ }
+
+
+ @Override
+ public void onReceive() {
+ FancyMessage fancyMessage = new FancyMessage(ChatColor.GRAY + "[" + ChatColor.GREEN + "Alert" + ChatColor.GRAY + "] " + ChatColor.WHITE + ChatColor.translateAlternateColorCodes('&', message));
+ if (this.server.contains("Bunkers")) {
+ fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the Bunkers Lobby");
+ } else if (this.server.contains("MineSG")) {
+ fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the MineSG Lobby");
+ } else if (this.server.contains("UHC-Meetup")) {
+ fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the UHC Meetup Lobby");
+ } else if (this.server.contains("Vault-Battles")) {
+ fancyMessage.tooltip(ChatColor.LIGHT_PURPLE + "Click to go to the Vault Battles Lobby");
+ }
+ fancyMessage.command("/joinfastserver " + server);
+ Bukkit.getOnlinePlayers().forEach(fancyMessage::send);
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java
new file mode 100644
index 0000000..4cc3ebe
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeNameTagProvider.java
@@ -0,0 +1,18 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.qlib.nametag.NametagInfo;
+import rip.bridge.qlib.nametag.NametagProvider;
+import org.bukkit.entity.Player;
+
+public class BridgeNameTagProvider extends NametagProvider {
+
+ public BridgeNameTagProvider() {
+ super("Bridge Provider", 1);
+ }
+
+ @Override
+ public NametagInfo fetchNametag(Player player, Player viewer) {
+ return createNametag(BukkitAPI.getColor(player), "");
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java
new file mode 100644
index 0000000..01fc9ac
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BridgeUUIDCache.java
@@ -0,0 +1,29 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.qlib.uuid.UUIDCache;
+
+import java.util.UUID;
+
+public class BridgeUUIDCache implements UUIDCache {
+
+ @Override
+ public UUID uuid(String var1) {
+ return BukkitAPI.getProfile(var1).getUuid();
+ }
+
+ @Override
+ public String name(UUID var1) {
+ return BukkitAPI.getName(BukkitAPI.getProfile(var1), false);
+ }
+
+ @Override
+ public void ensure(UUID var1) {
+
+ }
+
+ @Override
+ public void update(UUID var1, String var2) {
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java
new file mode 100644
index 0000000..340e00b
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/BukkitStatusImplementer.java
@@ -0,0 +1,65 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.listener.GeneralListener;
+import rip.bridge.bridge.global.util.JsonChain;
+import net.minecraft.server.v1_7_R4.MinecraftServer;
+import org.bukkit.Bukkit;
+import rip.bridge.bridge.global.status.StatusProvider;
+import rip.bridge.qlib.uuid.FrozenUUIDCache;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class BukkitStatusImplementer extends StatusProvider {
+
+ public BukkitStatusImplementer() {
+ super("Bridge Bukkit Implementer", 1);
+ }
+
+ @Override
+ public String serverName() {
+ return BridgeGlobal.getServerName();
+ }
+
+ @Override
+ public String serverStatus() {
+ return GeneralListener.getServerStatus();
+ }
+
+ @Override
+ public int online() {
+ return Bukkit.getOnlinePlayers().size();
+ }
+
+ @Override
+ public int maximum() {
+ return Bukkit.getMaxPlayers();
+ }
+
+ @Override
+ public String motd() {
+ return Bukkit.getMotd();
+ }
+
+ @Override
+ public double tps() {
+ return MinecraftServer.getServer().recentTps[0];
+ }
+
+ @Override
+ public List players() {
+ return Bukkit.getOnlinePlayers().stream().map(player -> player.getUniqueId().toString()).collect(Collectors.toList());
+ }
+
+ @Override
+ public JsonObject dataPassthrough() {
+ JsonChain jsonChain = new JsonChain();
+ if(BridgeGlobal.getUpdaterManager().getRunningDirectory().contains("/temp/"))
+ jsonChain.addProperty("tempServer", true).addProperty("runningDirectory", BridgeGlobal.getUpdaterManager().getRunningDirectory()).get();
+ jsonChain.addProperty("port", Bukkit.getPort()).addProperty("vanished", new Gson().toJson(Bukkit.getOnlinePlayers().stream().filter(player -> player.hasMetadata("invisible")).map(player -> FrozenUUIDCache.name(player.getUniqueId())).collect(Collectors.toList())));
+ return jsonChain.get();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java
new file mode 100644
index 0000000..a4c8e1d
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/DisguiseParameter.java
@@ -0,0 +1,44 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.disguise.DisguiseProfile;
+import rip.bridge.qlib.command.ParameterType;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+public class DisguiseParameter implements ParameterType {
+
+ public static boolean isUUID(String str) {
+ try {
+ UUID uuid = UUID.fromString(str);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+
+ @Override
+ public DisguiseProfile transform(CommandSender sender, String source) {
+ DisguiseProfile disguiseProfile;
+ if (isUUID(source)) {
+ disguiseProfile = BridgeGlobal.getDisguiseManager().getDisguiseProfiles().get(UUID.fromString(source));
+ } else {
+ disguiseProfile = BridgeGlobal.getDisguiseManager().getProfile(source);
+ }
+ if (disguiseProfile == null) {
+ sender.sendMessage("§cThere is no such disguise profile with the " + (isUUID(source) ? "uuid" : "name") + " \"" + source + "\".");
+ return null;
+ }
+ return disguiseProfile;
+ }
+
+ @Override
+ public List tabComplete(Player player, Set set, String s) {
+ return null;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java
new file mode 100644
index 0000000..14f49a9
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/ExecuteCommandPacket.java
@@ -0,0 +1,16 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import lombok.AllArgsConstructor;
+import org.bukkit.Bukkit;
+import rip.bridge.qlib.xpacket.XPacket;
+
+@AllArgsConstructor
+public class ExecuteCommandPacket implements XPacket {
+
+ public String command;
+
+ @Override
+ public void onReceive() {
+ Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java
new file mode 100644
index 0000000..26a9f48
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/FoxtrotRevivePacket.java
@@ -0,0 +1,27 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.BridgeGlobal;
+import lombok.AllArgsConstructor;
+import org.bukkit.Bukkit;
+import rip.bridge.qlib.xpacket.XPacket;
+
+import java.util.UUID;
+
+@AllArgsConstructor
+public class FoxtrotRevivePacket implements XPacket {
+
+ private String server;
+ private UUID player;
+ private int lives;
+
+ @Override
+ public void onReceive() {
+ if(BridgeGlobal.getServerName().equalsIgnoreCase(server)) {
+ if(Bukkit.getPluginManager().getPlugin("HCTeams") != null && Bukkit.getPluginManager().getPlugin("HCF").isEnabled()) {
+// Foxtrot.getInstance().getSoulboundLivesMap().setLives(player, lives);
+// Foxtrot.getInstance().getDeathbanMap().revive(player);
+// System.out.println("[HCTeams] " + UUIDUtils.name(player) + " has used a life and revived themselves through Hub. (Lives: " + lives + ")");
+ }
+ }
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java
new file mode 100644
index 0000000..69a7826
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/PluginParameter.java
@@ -0,0 +1,30 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+import rip.bridge.qlib.command.ParameterType;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PluginParameter implements ParameterType {
+
+ @Override
+ public Plugin transform(CommandSender commandSender, String s) {
+ Plugin plugin = Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(pluginOne -> pluginOne.getName().equalsIgnoreCase(s)).findAny().orElse(null);
+
+ if(plugin == null) commandSender.sendMessage(ChatColor.RED + "There is no such plugin by the name \"" + s + "\".");
+ return plugin;
+ }
+
+ @Override
+ public List tabComplete(Player player, Set flags, String source) {
+ return Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(plugin -> StringUtils.startsWithIgnoreCase(plugin.getName(), source)).map(Plugin::getName).collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java
new file mode 100644
index 0000000..5637f43
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/ProfileParamater.java
@@ -0,0 +1,84 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.BukkitAPI;
+import rip.bridge.bridge.global.util.MojangUtils;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.global.profile.Profile;
+import rip.bridge.qlib.command.ParameterType;
+import rip.bridge.qlib.qLib;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+public class ProfileParamater implements ParameterType {
+
+ public static boolean isUUID(String str) {
+ try {
+ UUID uuid = UUID.fromString(str);
+ return true;
+ }catch (Exception e) {
+ return false;
+ }
+ }
+
+ @Override
+ public Profile transform(CommandSender sender, String source) {
+
+ String fixedSource = source.replace("get/", "");
+
+ Profile pf;
+
+ if(fixedSource.equals("self")) {
+ pf = BukkitAPI.getProfile(sender);
+ }
+ else if(isUUID(fixedSource)) {
+ pf = BukkitAPI.getProfile(UUID.fromString(fixedSource));
+ }else {
+
+ pf = BukkitAPI.getProfile(fixedSource);
+
+ if(!source.startsWith("get/")) {
+
+ if(pf == null) {
+ UUID playerUUID = null;
+ try {
+ playerUUID = MojangUtils.fetchUUID(fixedSource);
+ if(playerUUID != null) {
+ pf = BridgeGlobal.getProfileHandler().getNewProfileOrCreate(fixedSource, playerUUID);
+ }else {
+ pf = null;
+ }
+ } catch (Exception e) {
+ pf = null;
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+
+ }
+ if(pf == null) {
+ sender.sendMessage("§cNo such player with the " + (isUUID(fixedSource) ? "uuid" : "name") + " \"" + fixedSource + "\".");
+ return null;
+ }
+ return pf;
+ }
+
+ @Override
+ public List tabComplete(Player sender, Set flags, String source) {
+ List completions = new ArrayList<>();
+
+ for (Player player : qLib.getInstance().getServer().getOnlinePlayers()) {
+ if (StringUtils.startsWithIgnoreCase(player.getName(), source) && sender.canSee(player) && BridgeGlobal.getProfileHandler().getProfileByUUID(player.getUniqueId()) != null) {
+ completions.add(player.getName());
+ }
+ }
+ return completions;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java
new file mode 100644
index 0000000..05b8f48
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/RankParamater.java
@@ -0,0 +1,47 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.global.ranks.Rank;
+import rip.bridge.qlib.command.ParameterType;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+public class RankParamater implements ParameterType {
+
+ public static boolean isUUID(String str) {
+ try {
+ UUID uuid = UUID.fromString(str);
+ return true;
+ }catch (Exception e) {
+ return false;
+ }
+ }
+
+
+ @Override
+ public Rank transform(CommandSender sender, String source) {
+ Rank rank;
+ if(isUUID(source)) {
+ rank = BridgeGlobal.getRankHandler().getRankByID(UUID.fromString(source));
+ }else {
+ rank = BridgeGlobal.getRankHandler().getRankByName(source);
+ }
+ if(rank == null) {
+ sender.sendMessage("§cThere is no such rank with the " + (isUUID(source) ? "uuid" : "name") + " \"" + source + "\".");
+ return null;
+ }
+ return rank;
+ }
+
+ @Override
+ public List tabComplete(Player sender, Set flags, String source) {
+ List ranks = new ArrayList<>();
+ BridgeGlobal.getRankHandler().getRanks().forEach(rank -> ranks.add(rank.getName()));
+ return ranks;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java
new file mode 100644
index 0000000..678be8e
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/WhitelistPacket.java
@@ -0,0 +1,38 @@
+package rip.bridge.bridge.bukkit.parameters;
+
+import org.bukkit.Bukkit;
+import rip.bridge.qlib.xpacket.XPacket;
+
+import java.util.UUID;
+
+
+public class WhitelistPacket implements XPacket {
+
+ private String server;
+ private boolean whitelist;
+ private UUID uuid;
+
+ public WhitelistPacket(String server, boolean whitelist) {
+ this.server = server;
+ this.whitelist = whitelist;
+ }
+
+ public WhitelistPacket(String server, UUID uuid) {
+ this.server = server;
+ this.uuid = uuid;
+ }
+
+ @Override
+ public void onReceive() {
+ if(uuid == null) {
+ if(Bukkit.getServerName().equalsIgnoreCase(server)) {
+ Bukkit.setWhitelist(whitelist);
+ }
+ }else {
+ if(Bukkit.getServerName().equalsIgnoreCase(server)) {
+ Bukkit.getOfflinePlayer(uuid).setWhitelisted(true);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java
new file mode 100644
index 0000000..bb7b3bd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterCreatePacket.java
@@ -0,0 +1,20 @@
+package rip.bridge.bridge.bukkit.parameters.packets.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import lombok.AllArgsConstructor;
+import org.bukkit.Bukkit;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.qlib.xpacket.XPacket;
+
+@AllArgsConstructor
+public class FilterCreatePacket implements XPacket {
+
+ private Filter filter;
+ private String sender;
+
+ @Override
+ public void onReceive() {
+ if(sender.equalsIgnoreCase(Bukkit.getServerName())) return;
+ BridgeGlobal.getFilterHandler().addFilter(filter);
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java
new file mode 100644
index 0000000..e9fe391
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterDeletePacket.java
@@ -0,0 +1,23 @@
+package rip.bridge.bridge.bukkit.parameters.packets.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import org.bukkit.Bukkit;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.qlib.xpacket.XPacket;
+
+public class FilterDeletePacket implements XPacket {
+
+ private String filter;
+ private String sender;
+
+ public FilterDeletePacket(Filter filter, String sender) {
+ this.filter = filter.getPattern();
+ this.sender = sender;
+ }
+
+ @Override
+ public void onReceive() {
+ if(sender.equalsIgnoreCase(Bukkit.getServerName())) return;
+ BridgeGlobal.getFilterHandler().removeFilter(BridgeGlobal.getFilterHandler().getFilter(filter));
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java
new file mode 100644
index 0000000..ddd4dfd
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/packets/filter/FilterViolationPacket.java
@@ -0,0 +1,32 @@
+package rip.bridge.bridge.bukkit.parameters.packets.filter;
+
+import mkremins.fanciful.FancyMessage;
+import rip.bridge.bridge.bukkit.commands.filter.ToggleFilterCommand;
+import lombok.AllArgsConstructor;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import rip.bridge.qlib.xpacket.XPacket;
+
+@AllArgsConstructor
+public class FilterViolationPacket implements XPacket {
+
+ private String server, usernameOne, usernameTwo, message;
+
+ @Override
+ public void onReceive() {
+ for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
+ if(getType(onlinePlayer) == null || getType(onlinePlayer).equalsIgnoreCase("off")) continue;
+ if(getType(onlinePlayer).equals("server") && !server.equals(Bukkit.getServerName())) continue;
+ FancyMessage fancyMessage = new FancyMessage("§e[Filter] ").then((getType(onlinePlayer).equals("global") ? "§7[" + server + "] " : "")).command("/server " + server).tooltip(ChatColor.GREEN + "Click here to teleport to " + server).then("§b" + (usernameTwo == null ? usernameOne : "(" + usernameOne + " to " + usernameTwo + ")") + " §c-> §e" + message);
+// onlinePlayer.sendMessage(ChatColor.translateAlternateColorCodes('§', "§e[Filter] " + (getType(onlinePlayer).equals("global") ? "§7[" + server + "] " : "") + "§b" + (usernameTwo == null ? usernameOne : "(" + usernameOne + " to " + usernameTwo + ")") + " §c-> §e" + message));
+ fancyMessage.send(onlinePlayer);
+ }
+ }
+
+ private String getType(Player player) {
+ if(!player.hasPermission("basic.staff")) return null;
+ if(!ToggleFilterCommand.getFilter().containsKey(player.getUniqueId())) return "global";
+ return ToggleFilterCommand.getFilter().get(player.getUniqueId());
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java
new file mode 100644
index 0000000..1b15362
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterActionParameter.java
@@ -0,0 +1,38 @@
+package rip.bridge.bridge.bukkit.parameters.param.filter;
+
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.global.filter.FilterAction;
+import rip.bridge.qlib.command.ParameterType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class FilterActionParameter implements ParameterType {
+
+ @Override
+ public FilterAction transform(CommandSender sender, String source) {
+ FilterAction filterAction = null;
+ try {
+ filterAction = FilterAction.valueOf(source);
+ }catch (Exception e) {
+ sender.sendMessage(ChatColor.RED + "There is no such filter action by the name of \"" + source + "\".");
+ }
+ return filterAction;
+ }
+
+ @Override
+ public List tabComplete(Player sender, Set flags, String source) {
+ List completions = new ArrayList<>();
+
+ for (FilterAction filterAction : FilterAction.values()) {
+ if (StringUtils.startsWithIgnoreCase(filterAction.name(), source)) {
+ completions.add(filterAction.name());
+ }
+ }
+ return completions;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java
new file mode 100644
index 0000000..0621b51
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterParameter.java
@@ -0,0 +1,35 @@
+package rip.bridge.bridge.bukkit.parameters.param.filter;
+
+import rip.bridge.bridge.BridgeGlobal;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.global.filter.Filter;
+import rip.bridge.qlib.command.ParameterType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class FilterParameter implements ParameterType {
+
+ @Override
+ public Filter transform(CommandSender sender, String source) {
+ Filter filter = BridgeGlobal.getFilterHandler().getFilter(source);
+ if(filter == null) sender.sendMessage(ChatColor.RED + "There is no such filter by the pattern of \"" + source + "\".");
+ return filter;
+ }
+
+ @Override
+ public List tabComplete(Player sender, Set flags, String source) {
+ List completions = new ArrayList<>();
+
+ for (Filter filter : BridgeGlobal.getFilterHandler().getFilters()) {
+ if (StringUtils.startsWithIgnoreCase(filter.getPattern(), source)) {
+ completions.add(filter.getPattern());
+ }
+ }
+ return completions;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java
new file mode 100644
index 0000000..88de3b6
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/parameters/param/filter/FilterTypeParameter.java
@@ -0,0 +1,38 @@
+package rip.bridge.bridge.bukkit.parameters.param.filter;
+
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import rip.bridge.bridge.global.filter.FilterType;
+import rip.bridge.qlib.command.ParameterType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class FilterTypeParameter implements ParameterType {
+
+ @Override
+ public FilterType transform(CommandSender sender, String source) {
+ FilterType filterType = null;
+ try {
+ filterType = FilterType.valueOf(source);
+ }catch (Exception e) {
+ sender.sendMessage(ChatColor.RED + "There is no such filter type by the name of \"" + source + "\".");
+ }
+ return filterType;
+ }
+
+ @Override
+ public List tabComplete(Player sender, Set flags, String source) {
+ List completions = new ArrayList<>();
+
+ for (FilterType filterType : FilterType.values()) {
+ if (StringUtils.startsWithIgnoreCase(filterType.name(), source)) {
+ completions.add(filterType.name());
+ }
+ }
+ return completions;
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java b/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java
new file mode 100644
index 0000000..1bb8824
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/BaseEvent.java
@@ -0,0 +1,26 @@
+package rip.bridge.bridge.bukkit.util;
+
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class BaseEvent extends Event
+{
+ private static final HandlerList handlers;
+
+ public HandlerList getHandlers() {
+ return BaseEvent.handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+ return BaseEvent.handlers;
+ }
+
+ public void call() {
+ Bukkit.getServer().getPluginManager().callEvent(this);
+ }
+
+ static {
+ handlers = new HandlerList();
+ }
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java b/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java
new file mode 100644
index 0000000..79cfdc4
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/BukkitUtils.java
@@ -0,0 +1,92 @@
+package rip.bridge.bridge.bukkit.util;
+
+import rip.bridge.bridge.BridgeGlobal;
+import rip.bridge.bridge.bukkit.Bridge;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.event.Listener;
+
+public class BukkitUtils {
+
+ public static void registerListeners(Class>... listeners) {
+ for (Class> listener : listeners) {
+ if (Listener.class.isAssignableFrom(listener)) {
+ try {
+ Bukkit.getServer().getPluginManager().registerEvents(((Listener) listener.newInstance()), Bridge.getInstance());
+ BridgeGlobal.sendLog("Successfully registered listener " + listener.getSimpleName() + "!");
+ } catch (Exception ex) {
+ BridgeGlobal.sendLog("Failed to registered listener " + listener.getSimpleName() + ". (" + ex.getClass().getSimpleName() + ": " + ex.getMessage() + ")");
+ }
+ } else {
+ BridgeGlobal.sendLog("The class: " + listener.getSimpleName() + " does not parameters Listener!");
+ }
+ }
+ }
+
+ public static Material materialFix(String name) {
+ Material materialFromDB;
+ try {
+ materialFromDB = (Material) Enum.valueOf((Class) Material.class, name);
+ } catch (IllegalArgumentException ignore) {
+ materialFromDB = (Material) Enum.valueOf((Class) Material.class, "LEGACY_" + name);
+ }
+ return materialFromDB;
+
+ }
+
+ public static int stringToWoolColor(String r) {
+ String fixed = r.replaceAll("§l", "").replaceAll("§r", "").replaceAll("§k", "").replaceAll("§n", "").replaceAll("§m", "").replaceAll("§o", "");
+ switch (fixed) {
+ case "§1":
+ return 11;
+ case "§2":
+ return 13;
+
+ case "§3":
+ return 9;
+
+ case "§4":
+ return 14;
+
+ case "§5":
+ return 10;
+
+ case "§6":
+ return 1;
+
+ case "§7":
+ return 8;
+
+ case "§8":
+ return 7;
+
+ case "§9":
+ return 11;
+
+ case "§0":
+ return 15;
+
+ case "§a":
+ return 5;
+
+ case "§b":
+
+ return 3;
+ case "§c":
+ return 14;
+
+ case "§d":
+ return 6;
+
+ case "§e":
+
+ return 4;
+ case "§f":
+ return 0;
+
+ default:
+ return 0;
+ }
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java b/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java
new file mode 100644
index 0000000..4967dde
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/Chat.java
@@ -0,0 +1,43 @@
+package rip.bridge.bridge.bukkit.util;
+
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+
+public class Chat {
+
+ public static String LINE = "--------------------------------";
+ public static ChatColor ITALIC = ChatColor.ITALIC;
+ public static ChatColor BOLD = ChatColor.BOLD;
+ public static ChatColor LIGHT_GREEN = ChatColor.GREEN;
+ public static ChatColor LIGHT_BLUE = ChatColor.AQUA;
+ public static ChatColor LIGHT_RED = ChatColor.RED;
+ public static ChatColor PINK = ChatColor.LIGHT_PURPLE;
+ public static ChatColor YELLOW = ChatColor.YELLOW;
+ public static ChatColor WHITE = ChatColor.WHITE;
+ public static ChatColor RESET = ChatColor.RESET;
+ public static ChatColor OBFUSCATION = ChatColor.MAGIC;
+ public static ChatColor STRIKETHROUGH = ChatColor.STRIKETHROUGH;
+ public static ChatColor UNDERLINE = ChatColor.UNDERLINE;
+ public static ChatColor DARK_BLUE = ChatColor.DARK_BLUE;
+ public static ChatColor DARK_GREEN = ChatColor.DARK_GREEN;
+ public static ChatColor CYAN = ChatColor.DARK_AQUA;
+ public static ChatColor DARK_RED = ChatColor.DARK_RED;
+ public static ChatColor PURPLE = ChatColor.DARK_PURPLE;
+ public static ChatColor ORANGE = ChatColor.GOLD;
+ public static ChatColor LIGHT_GRAY = ChatColor.GRAY;
+ public static ChatColor DARK_GRAY = ChatColor.DARK_GRAY;
+ public static ChatColor INDIGO = ChatColor.BLUE;
+
+ public static String format(String message){
+ return ChatColor.translateAlternateColorCodes('&', message);
+ }
+
+ public static String unformat(String message){
+ return ChatColor.stripColor(message);
+ }
+
+ public static String repeat(String str, int length){
+ return StringUtils.repeat(str, length);
+ }
+
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java b/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java
new file mode 100644
index 0000000..a9db056
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/ItemStackBuilder.java
@@ -0,0 +1,25 @@
+package rip.bridge.bridge.bukkit.util;
+
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.List;
+
+public class ItemStackBuilder {
+
+ public static ItemStack build(Material item, int amount, short data, String name, List lore) {
+ ItemStack is = new ItemStack(item, amount, data);
+
+ ItemMeta im = is.getItemMeta();
+ im.setDisplayName(ChatColor.translateAlternateColorCodes('&', name));
+ if(lore != null) {
+ im.setLore(lore);
+ }
+ is.setItemMeta(im);
+ return is;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java b/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java
new file mode 100644
index 0000000..1588a24
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/PaginatedResult.java
@@ -0,0 +1,46 @@
+package rip.bridge.bridge.bukkit.util;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public abstract class PaginatedResult
+{
+ private int resultsPerPage;
+
+ public PaginatedResult() {
+ this(9);
+ }
+
+ public PaginatedResult(int resultsPerPage) {
+ assert resultsPerPage > 0;
+ this.resultsPerPage = resultsPerPage;
+ }
+
+ public void display(CommandSender sender, Collection extends T> results, int page) {
+ this.display(sender, (List extends T>)new ArrayList(results), page);
+ }
+
+ public void display(CommandSender sender, List extends T> results, int page) {
+ if (results.size() == 0) {
+ sender.sendMessage(ChatColor.RED + "No entries were found.");
+ return;
+ }
+ int maxPages = results.size() / this.resultsPerPage + 1;
+ if (page <= 0 || page > maxPages) {
+ sender.sendMessage(ChatColor.RED + "Page '" + page + "' not found. (" + ChatColor.YELLOW + "1 - " + maxPages + ChatColor.RED + ")");
+ return;
+ }
+ sender.sendMessage(this.getHeader(page, maxPages));
+ for (int i = this.resultsPerPage * (page - 1); i < this.resultsPerPage * page && i < results.size(); ++i) {
+ sender.sendMessage(this.format(results.get(i), i));
+ }
+ }
+
+ public abstract String getHeader(int p0, int p1);
+
+ public abstract String format(T p0, int p1);
+}
diff --git a/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java b/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java
new file mode 100644
index 0000000..7b472b1
--- /dev/null
+++ b/src/main/java/rip/bridge/bridge/bukkit/util/PluginUtil.java
@@ -0,0 +1,375 @@
+package rip.bridge.bridge.bukkit.util;
+
+import com.google.common.base.Joiner;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.URLClassLoader;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import rip.bridge.bridge.bukkit.Bridge;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.command.SimpleCommandMap;
+import org.bukkit.event.Event;
+import org.bukkit.plugin.*;
+
+public class PluginUtil {
+
+ public static void enable(Plugin plugin) {
+ if (plugin != null && !plugin.isEnabled()) {
+ Bukkit.getPluginManager().enablePlugin(plugin);
+ }
+ }
+
+ public static void enableAll() {
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ if (!isIgnored(plugin)) {
+ enable(plugin);
+ }
+ }
+ }
+
+ public static void disable(Plugin plugin) {
+ if (plugin != null && plugin.isEnabled()) {
+ Bukkit.getPluginManager().disablePlugin(plugin);
+ }
+ }
+
+ public static void disableAll() {
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ if (!isIgnored(plugin)) {
+ disable(plugin);
+ }
+ }
+ }
+
+ public static String getFormattedName(Plugin plugin) {
+ return getFormattedName(plugin, false);
+ }
+
+ public static String getFormattedName(Plugin plugin, boolean includeVersions) {
+ ChatColor color = plugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED;
+ String pluginName = color + plugin.getName();
+ if (includeVersions) {
+ pluginName += " (" + plugin.getDescription().getVersion() + ")";
+ }
+ return pluginName;
+ }
+
+ public static Plugin getPluginByName(String[] args, int start) {
+ return getPluginByName(StringUtils.join(args, ' ', start, args.length));
+ }
+
+ public static Plugin getPluginByName(String name) {
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ if (name.equalsIgnoreCase(plugin.getName())) {
+ return plugin;
+ }
+ }
+ return null;
+ }
+
+ public static List getPluginNames(boolean fullName) {
+ List plugins = new ArrayList<>();
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ plugins.add(fullName ? plugin.getDescription().getFullName() : plugin.getName());
+ }
+ return plugins;
+ }
+
+ public static String getPluginVersion(String name) {
+ Plugin plugin = getPluginByName(name);
+ if (plugin != null && plugin.getDescription() != null) {
+ return plugin.getDescription().getVersion();
+ }
+ return null;
+ }
+
+ public static String getUsages(Plugin plugin) {
+
+ List parsedCommands = new ArrayList<>();
+
+ Map commands = plugin.getDescription().getCommands();
+
+ if (commands != null) {
+ Iterator commandsIt = commands.entrySet().iterator();
+ while (commandsIt.hasNext()) {
+ Map.Entry thisEntry = (Map.Entry) commandsIt.next();
+ if (thisEntry != null) {
+ parsedCommands.add((String) thisEntry.getKey());
+ }
+ }
+ }
+
+ if (parsedCommands.isEmpty())
+ return "No commands registered.";
+
+ return Joiner.on(", ").join(parsedCommands);
+
+ }
+
+ public static List findByCommand(String command) {
+
+ List plugins = new ArrayList<>();
+
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+
+ // Map of commands and their attributes.
+ Map> commands = plugin.getDescription().getCommands();
+
+ if (commands != null) {
+
+ // Iterator for all the plugin's commands.
+ Iterator>> commandIterator = commands.entrySet().iterator();
+
+ while (commandIterator.hasNext()) {
+
+ // Current value.
+ Map.Entry> commandNext = commandIterator.next();
+
+ // Plugin name matches - return.
+ if (commandNext.getKey().equalsIgnoreCase(command)) {
+ plugins.add(plugin.getName());
+ continue;
+ }
+
+ // No match - let's iterate over the attributes and see if
+ // it has aliases.
+ Iterator> attributeIterator = commandNext.getValue().entrySet().iterator();
+
+ while (attributeIterator.hasNext()) {
+
+ // Current value.
+ Map.Entry attributeNext = attributeIterator.next();
+
+ // Has an alias attribute.
+ if (attributeNext.getKey().equals("aliases")) {
+
+ Object aliases = attributeNext.getValue();
+
+ if (aliases instanceof String) {
+ if (((String) aliases).equalsIgnoreCase(command)) {
+ plugins.add(plugin.getName());
+ continue;
+ }
+ } else {
+
+ // Cast to a List of Strings.
+ List array = (List) aliases;
+
+ // Check for matches here.
+ for (String str : array) {
+ if (str.equalsIgnoreCase(command)) {
+ plugins.add(plugin.getName());
+ continue;
+ }
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ }
+
+ }
+
+ // No matches.
+ return plugins;
+
+ }
+
+ public static boolean isIgnored(Plugin plugin) {
+ return isIgnored(plugin.getName());
+ }
+
+ public static boolean isIgnored(String plugin) {
+ return false;
+ }
+
+ private static String load(Plugin plugin) {
+ return load(plugin.getName());
+ }
+
+ public static String load(String name) {
+
+ Plugin target = null;
+
+ File pluginDir = new File("plugins");
+
+ File pluginFile = new File(pluginDir, name + (!name.endsWith(".jar") ? ".jar" : ""));
+
+ if (!pluginFile.isFile()) {
+ for (File f : pluginDir.listFiles()) {
+ if (f.getName().endsWith(".jar")) {
+ try {
+ PluginDescriptionFile desc = Bridge.getInstance().getPluginLoader().getPluginDescription(f);
+ if (desc.getName().equalsIgnoreCase(name)) {
+ pluginFile = f;
+ break;
+ }
+ } catch (InvalidDescriptionException e) {
+ return ChatColor.RED + "There is no such file by the name \"" + name + "\".";
+ }
+ }
+ }
+ }
+
+ try {
+ target = Bukkit.getPluginManager().loadPlugin(pluginFile);
+ } catch (InvalidDescriptionException e) {
+ e.printStackTrace();
+ return ChatColor.RED + "The plugin \"" + name + "\" has an invalid description, so we cannot load.";
+ } catch (InvalidPluginException e) {
+ e.printStackTrace();
+ return ChatColor.RED + "The plugin \"" + name + "\" is an invalid plugin, so we cannot load.";
+ }
+
+ target.onLoad();
+ Bukkit.getPluginManager().enablePlugin(target);
+
+ return ChatColor.GREEN + "Successfully loaded the plugin \"" + target.getName() + "\".";
+
+ }
+
+ public static void reload(Plugin plugin) {
+ if (plugin != null) {
+ unload(plugin);
+ load(plugin);
+ }
+ }
+
+ public static void reloadAll() {
+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
+ if (!isIgnored(plugin)) {
+ reload(plugin);
+ }
+ }
+ }
+
+ public static String unload(Plugin plugin) {
+
+ String name = plugin.getName();
+
+ PluginManager pluginManager = Bukkit.getPluginManager();
+
+ SimpleCommandMap commandMap = null;
+
+ List plugins = null;
+
+ Map names = null;
+ Map