From 9acd34f371bdcf40a304a95ff50245f9f1488261 Mon Sep 17 00:00:00 2001 From: Sam <49818472+srmullaney@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:18:03 -0400 Subject: [PATCH] Api v1 refactor (#239) --- README.md | 4 +- src/main/java/io/servertap/Constants.java | 1 - src/main/java/io/servertap/ServerTapMain.java | 47 +++-- .../java/io/servertap/WebServerRoutes.java | 80 ++++---- .../io/servertap/api/v1/AdvancementsApi.java | 6 +- .../io/servertap/api/v1/ApiV1Initializer.java | 64 ++++++ .../java/io/servertap/api/v1/EconomyApi.java | 37 ++-- .../java/io/servertap/api/v1/PAPIApi.java | 3 +- .../java/io/servertap/api/v1/PlayerApi.java | 71 ++++--- .../java/io/servertap/api/v1/PluginApi.java | 15 +- .../java/io/servertap/api/v1/ServerApi.java | 191 +++++++----------- .../java/io/servertap/api/v1/WorldApi.java | 70 +++---- .../api/v1/websockets/WebsocketHandler.java | 32 +-- .../servertap/commands/ServerTapCommand.java | 1 + .../mojang/api/MojangApiService.java | 20 +- .../websockets => utils}/ConsoleListener.java | 22 +- .../io/servertap/utils/EconomyWrapper.java | 49 ----- .../io/servertap/utils/GsonJsonMapper.java | 2 +- .../utils/{Lag.java => LagDetector.java} | 12 +- .../utils/ServerExecCommandSender.java | 22 +- .../utils/pluginwrappers/EconomyWrapper.java | 60 ++++++ .../ExternalPluginWrapperRepo.java | 18 ++ .../java/io/servertap/webhooks/Webhook.java | 2 +- .../webhooks/WebhookEventListener.java | 13 +- .../models/events/PlayerChatWebhookEvent.java | 2 +- .../events/PlayerDeathWebhookEvent.java | 2 +- .../models/events/PlayerJoinWebhookEvent.java | 2 +- .../models/events/PlayerKickWebhookEvent.java | 2 +- .../models/events/PlayerQuitWebhookEvent.java | 2 +- .../models/events/WebhookEvent.java | 2 +- 30 files changed, 470 insertions(+), 384 deletions(-) create mode 100644 src/main/java/io/servertap/api/v1/ApiV1Initializer.java rename src/main/java/io/servertap/{api/v1/websockets => utils}/ConsoleListener.java (87%) delete mode 100644 src/main/java/io/servertap/utils/EconomyWrapper.java rename src/main/java/io/servertap/utils/{Lag.java => LagDetector.java} (73%) create mode 100644 src/main/java/io/servertap/utils/pluginwrappers/EconomyWrapper.java create mode 100644 src/main/java/io/servertap/utils/pluginwrappers/ExternalPluginWrapperRepo.java rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/PlayerChatWebhookEvent.java (94%) rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/PlayerDeathWebhookEvent.java (95%) rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/PlayerJoinWebhookEvent.java (93%) rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/PlayerKickWebhookEvent.java (92%) rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/PlayerQuitWebhookEvent.java (93%) rename src/main/java/io/servertap/{api/v1 => webhooks}/models/events/WebhookEvent.java (82%) diff --git a/README.md b/README.md index 2e1e7427..8299d9a2 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,8 @@ $ curl http://localhost:4567/v1/players ``` # ServerTap Command -ServerTap currently supports only one management command in game. The supported subcommands are `reload` & 'info' -which as their names imply let you reload the plugin and display information basic info about it (version, author, etc). +ServerTap currently supports only one management command in game. The supported subcommands are `reload` & `info` +which as their names imply let you reload and display basic information about the plugin (version, author, etc). **Note**: The Permission for the `/servertap` Command is `servertap.admin`. diff --git a/src/main/java/io/servertap/Constants.java b/src/main/java/io/servertap/Constants.java index 99cc0b21..b5518c88 100644 --- a/src/main/java/io/servertap/Constants.java +++ b/src/main/java/io/servertap/Constants.java @@ -4,7 +4,6 @@ public class Constants { public static final String API_V1 = "v1"; - // Economy Related Messages public static final String VAULT_MISSING = "Vault not found or you are missing an economy plugin. Related functionality disabled"; public static final String VAULT_MISSING_PAY_PARAMS = "Missing uuid and/or amount"; diff --git a/src/main/java/io/servertap/ServerTapMain.java b/src/main/java/io/servertap/ServerTapMain.java index 06b59759..b72e8d83 100644 --- a/src/main/java/io/servertap/ServerTapMain.java +++ b/src/main/java/io/servertap/ServerTapMain.java @@ -1,17 +1,18 @@ package io.servertap; import io.servertap.api.v1.models.ConsoleLine; -import io.servertap.api.v1.websockets.ConsoleListener; import io.servertap.commands.ServerTapCommand; import io.servertap.metrics.Metrics; import io.servertap.plugin.api.ServerTapWebserverService; import io.servertap.plugin.api.ServerTapWebserverServiceImpl; -import io.servertap.utils.EconomyWrapper; -import io.servertap.utils.Lag; +import io.servertap.utils.ConsoleListener; +import io.servertap.utils.LagDetector; +import io.servertap.utils.pluginwrappers.ExternalPluginWrapperRepo; import io.servertap.webhooks.WebhookEventListener; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; import org.bukkit.Bukkit; +import org.bukkit.Server; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.ServicePriority; @@ -25,24 +26,30 @@ public class ServerTapMain extends JavaPlugin { - public static ServerTapMain instance; private static final java.util.logging.Logger log = Bukkit.getLogger(); - private WebServer app; - - Logger rootLogger = (Logger) LogManager.getRootLogger(); - + private final Logger rootLogger = (Logger) LogManager.getRootLogger(); private final List consoleBuffer = new ArrayList<>(); - private int maxConsoleBufferSize = 1000; + private ExternalPluginWrapperRepo externalPluginWrapperRepo; private WebhookEventListener webhookEventListener; + private int maxConsoleBufferSize = 1000; + private ConsoleListener consoleListener; + public static ServerTapMain instance; + private final LagDetector lagDetector; + private final Server server; + private WebServer app; public ServerTapMain() { super(); instance = this; + server = getServer(); + lagDetector = new LagDetector(); } public ServerTapMain(@NotNull JavaPluginLoader loader, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file) { super(loader, description, dataFolder, file); instance = this; + server = getServer(); + lagDetector = new LagDetector(); } @Override @@ -50,33 +57,34 @@ public void onEnable() { // Tell bStats what plugin this is new Metrics(this, 9492); - // Initialize any economy integration (if one is installed) - new EconomyWrapper(log).setupEconomy(); + // Initialize any external plugin integrations + externalPluginWrapperRepo = new ExternalPluginWrapperRepo(this, log); // Start the TPS Counter with a 100 tick Delay every 1 tick - Bukkit.getScheduler().runTaskTimer(this, new Lag(), 100, 1); + Bukkit.getScheduler().runTaskTimer(this, lagDetector, 100, 1); // Initialize config file + set defaults saveDefaultConfig(); FileConfiguration bukkitConfig = getConfig(); maxConsoleBufferSize = bukkitConfig.getInt("websocketConsoleBuffer"); - rootLogger.addFilter(new ConsoleListener(this)); + consoleListener = new ConsoleListener(this); + rootLogger.addFilter(consoleListener); setupWebServer(bukkitConfig); new ServerTapCommand(this); - webhookEventListener = new WebhookEventListener(this, bukkitConfig, log); - getServer().getPluginManager().registerEvents(webhookEventListener, this); + webhookEventListener = new WebhookEventListener(this, bukkitConfig, log, externalPluginWrapperRepo.getEconomyWrapper()); + server.getPluginManager().registerEvents(webhookEventListener, this); - getServer().getServicesManager().register(ServerTapWebserverService.class, new ServerTapWebserverServiceImpl(this), this, ServicePriority.Normal); + server.getServicesManager().register(ServerTapWebserverService.class, new ServerTapWebserverServiceImpl(this), this, ServicePriority.Normal); } private void setupWebServer(FileConfiguration bukkitConfig) { app = new WebServer(this, bukkitConfig, log); app.start(bukkitConfig.getInt("port", 4567)); - WebServerRoutes.addV1Routes(app); + WebServerRoutes.addV1Routes(this, log, lagDetector, app, consoleListener, externalPluginWrapperRepo); } public void reload() { @@ -87,7 +95,12 @@ public void reload() { reloadConfig(); FileConfiguration bukkitConfig = getConfig(); maxConsoleBufferSize = bukkitConfig.getInt("websocketConsoleBuffer"); + + externalPluginWrapperRepo = new ExternalPluginWrapperRepo(this, log); + consoleListener.resetListeners(); + setupWebServer(bukkitConfig); + webhookEventListener.loadWebhooksFromConfig(bukkitConfig); log.info("[ServerTap] ServerTap reloaded successfully!"); } diff --git a/src/main/java/io/servertap/WebServerRoutes.java b/src/main/java/io/servertap/WebServerRoutes.java index 93350575..fea2f47d 100644 --- a/src/main/java/io/servertap/WebServerRoutes.java +++ b/src/main/java/io/servertap/WebServerRoutes.java @@ -3,68 +3,74 @@ import io.javalin.http.Handler; import io.javalin.websocket.WsConfig; import io.servertap.api.v1.*; -import io.servertap.api.v1.websockets.WebsocketHandler; - -import java.util.function.Consumer; +import io.servertap.utils.ConsoleListener; +import io.servertap.utils.LagDetector; +import io.servertap.utils.pluginwrappers.ExternalPluginWrapperRepo; import static io.servertap.Constants.*; +import java.util.function.Consumer; +import java.util.logging.Logger; + public final class WebServerRoutes { private WebServerRoutes() {} - public static void addV1Routes(WebServer webServer) { + public static void addV1Routes(ServerTapMain main, Logger log, LagDetector lagDetector, WebServer webServer, + ConsoleListener consoleListener, ExternalPluginWrapperRepo externalPluginWrapperRepo) { PrefixedRouteBuilder pr = new PrefixedRouteBuilder(API_V1, webServer); - pr.get("ping", ServerApi::ping); + ApiV1Initializer api = new ApiV1Initializer(main, log, lagDetector, consoleListener, externalPluginWrapperRepo); + + pr.get("ping", api.getServerApi()::ping); // Server routes - pr.get("server", ServerApi::serverGet); - pr.post("server/exec", ServerApi::postCommand); - pr.get("server/ops", ServerApi::getOps); - pr.post("server/ops", ServerApi::opPlayer); - pr.delete("server/ops", ServerApi::deopPlayer); - pr.get("server/whitelist", ServerApi::whitelistGet); - pr.post("server/whitelist", ServerApi::whitelistPost); - pr.delete("server/whitelist", ServerApi::whitelistDelete); - - pr.get("worlds", WorldApi::worldsGet); - pr.post("worlds/save", WorldApi::saveAllWorlds); - pr.get("worlds/download", WorldApi::downloadWorlds); - pr.get("worlds/{uuid}", WorldApi::worldGet); - pr.post("worlds/{uuid}/save", WorldApi::saveWorld); - pr.get("worlds/{uuid}/download", WorldApi::downloadWorld); - - pr.get("scoreboard", ServerApi::scoreboardGet); - pr.get("scoreboard/{name}", ServerApi::objectiveGet); + pr.get("server", api.getServerApi()::serverGet); + pr.post("server/exec", api.getServerApi()::postCommand); + pr.get("server/ops", api.getServerApi()::getOps); + pr.post("server/ops", api.getServerApi()::opPlayer); + pr.delete("server/ops", api.getServerApi()::deopPlayer); + pr.get("server/whitelist", api.getServerApi()::whitelistGet); + pr.post("server/whitelist", api.getServerApi()::whitelistPost); + pr.delete("server/whitelist", api.getServerApi()::whitelistDelete); + + pr.get("worlds", api.getWorldApi()::worldsGet); + pr.post("worlds/save", api.getWorldApi()::saveAllWorlds); + pr.get("worlds/download", api.getWorldApi()::downloadWorlds); + pr.get("worlds/{uuid}", api.getWorldApi()::worldGet); + pr.post("worlds/{uuid}/save", api.getWorldApi()::saveWorld); + pr.get("worlds/{uuid}/download", api.getWorldApi()::downloadWorld); + + pr.get("scoreboard", api.getServerApi()::scoreboardGet); + pr.get("scoreboard/{name}", api.getServerApi()::objectiveGet); // Chat - pr.post("chat/broadcast", ServerApi::broadcastPost); - pr.post("chat/tell", ServerApi::tellPost); + pr.post("chat/broadcast", api.getServerApi()::broadcastPost); + pr.post("chat/tell", api.getServerApi()::tellPost); // Player routes - pr.get("players", PlayerApi::playersGet); - pr.get("players/all", PlayerApi::offlinePlayersGet); - pr.get("players/{uuid}", PlayerApi::playerGet); - pr.get("players/{playerUuid}/{worldUuid}/inventory", PlayerApi::getPlayerInv); + pr.get("players", api.getPlayerApi()::playersGet); + pr.get("players/all", api.getPlayerApi()::offlinePlayersGet); + pr.get("players/{uuid}", api.getPlayerApi()::playerGet); + pr.get("players/{playerUuid}/{worldUuid}/inventory", api.getPlayerApi()::getPlayerInv); // Economy routes - pr.post("economy/pay", EconomyApi::playerPay); - pr.post("economy/debit", EconomyApi::playerDebit); - pr.get("economy", EconomyApi::getEconomyPluginInformation); + pr.post("economy/pay", api.getEconomyApi()::playerPay); + pr.post("economy/debit", api.getEconomyApi()::playerDebit); + pr.get("economy", api.getEconomyApi()::getEconomyPluginInformation); // Plugin routes - pr.get("plugins", PluginApi::listPlugins); - pr.post("plugins", PluginApi::installPlugin); + pr.get("plugins", api.getPluginApi()::listPlugins); + pr.post("plugins", api.getPluginApi()::installPlugin); // PAPI Routes - pr.post("placeholders/replace", PAPIApi::replacePlaceholders); + pr.post("placeholders/replace", api.getPapiApi()::replacePlaceholders); // Websocket handler - pr.ws("ws/console", WebsocketHandler::events); + pr.ws("ws/console", api.getWebsocketHandler()::events); // Advancement routes - pr.get("advancements", AdvancementsApi::getAdvancements); + pr.get("advancements", api.getAdvancementsApi()::getAdvancements); } private static class PrefixedRouteBuilder { diff --git a/src/main/java/io/servertap/api/v1/AdvancementsApi.java b/src/main/java/io/servertap/api/v1/AdvancementsApi.java index 02f286d5..1bc16fd0 100644 --- a/src/main/java/io/servertap/api/v1/AdvancementsApi.java +++ b/src/main/java/io/servertap/api/v1/AdvancementsApi.java @@ -6,13 +6,11 @@ import io.javalin.openapi.OpenApiParam; import io.javalin.openapi.OpenApiResponse; import io.servertap.api.v1.models.Advancement; -import io.servertap.api.v1.models.Player; import org.bukkit.Bukkit; import java.util.ArrayList; public class AdvancementsApi { - @OpenApi( path = "/v1/advancements", summary = "Gets all server advancements", @@ -24,7 +22,7 @@ public class AdvancementsApi { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Advancement.class)) } ) - public static void getAdvancements(Context ctx) { + public void getAdvancements(Context ctx) { final ArrayList advancements = new ArrayList<>(); Bukkit.advancementIterator().forEachRemaining(advancement -> { @@ -37,4 +35,4 @@ public static void getAdvancements(Context ctx) { ctx.json(advancements); } -} +} \ No newline at end of file diff --git a/src/main/java/io/servertap/api/v1/ApiV1Initializer.java b/src/main/java/io/servertap/api/v1/ApiV1Initializer.java new file mode 100644 index 00000000..f5a5d062 --- /dev/null +++ b/src/main/java/io/servertap/api/v1/ApiV1Initializer.java @@ -0,0 +1,64 @@ +package io.servertap.api.v1; + +import io.servertap.ServerTapMain; +import io.servertap.utils.ConsoleListener; +import io.servertap.api.v1.websockets.WebsocketHandler; +import io.servertap.utils.LagDetector; +import io.servertap.utils.pluginwrappers.ExternalPluginWrapperRepo; + +import java.util.logging.Logger; + +public class ApiV1Initializer { + private final WebsocketHandler websocketHandler; + private final AdvancementsApi advancementsApi; + private final EconomyApi economyApi; + private final PluginApi pluginApi; + private final ServerApi serverApi; + private final PlayerApi playerApi; + private final WorldApi worldApi; + private final PAPIApi papiApi; + + public ApiV1Initializer(ServerTapMain main, Logger log, LagDetector lagDetector, ConsoleListener consoleListener, + ExternalPluginWrapperRepo externalPluginWrapperRepo) { + this.websocketHandler = new WebsocketHandler(main, log, consoleListener); + this.advancementsApi = new AdvancementsApi(); + this.economyApi = new EconomyApi(externalPluginWrapperRepo.getEconomyWrapper()); + this.pluginApi = new PluginApi(main, log); + this.serverApi = new ServerApi(main, log, lagDetector, externalPluginWrapperRepo.getEconomyWrapper()); + this.playerApi = new PlayerApi(log, externalPluginWrapperRepo.getEconomyWrapper()); + this.worldApi = new WorldApi(main, log); + this.papiApi = new PAPIApi(); + } + + public WebsocketHandler getWebsocketHandler() { + return websocketHandler; + } + + public AdvancementsApi getAdvancementsApi() { + return advancementsApi; + } + + public EconomyApi getEconomyApi() { + return economyApi; + } + + public PluginApi getPluginApi() { + return pluginApi; + } + + public ServerApi getServerApi() { + return serverApi; + } + + public PlayerApi getPlayerApi() { + return playerApi; + } + + public WorldApi getWorldApi() { + return worldApi; + } + + public PAPIApi getPapiApi() { + return papiApi; + } +} diff --git a/src/main/java/io/servertap/api/v1/EconomyApi.java b/src/main/java/io/servertap/api/v1/EconomyApi.java index 4343ac11..ce110a76 100644 --- a/src/main/java/io/servertap/api/v1/EconomyApi.java +++ b/src/main/java/io/servertap/api/v1/EconomyApi.java @@ -6,7 +6,7 @@ import io.javalin.http.InternalServerErrorResponse; import io.javalin.openapi.*; import io.servertap.Constants; -import io.servertap.utils.EconomyWrapper; +import io.servertap.utils.pluginwrappers.EconomyWrapper; import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.EconomyResponse; import org.bukkit.Bukkit; @@ -18,6 +18,12 @@ import java.util.UUID; public class EconomyApi { + private final org.bukkit.Server bukkitServer = Bukkit.getServer(); + private final EconomyWrapper economy; + + public EconomyApi(EconomyWrapper economyWrapper) { + this.economy = economyWrapper; + } private enum TransactionType { PAY, DEBIT @@ -36,12 +42,12 @@ private enum TransactionType { @OpenApiResponse(status = "500", content = @OpenApiContent(type = "application/json")) } ) - public static void getEconomyPluginInformation(Context ctx) { + public void getEconomyPluginInformation(Context ctx) { Plugin econPlugin; - if (EconomyWrapper.getInstance().getEconomy() == null) { + if (!economy.isAvailable()) { throw new HttpResponseException(424, Constants.VAULT_MISSING, new HashMap<>()); } else { - RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); + RegisteredServiceProvider rsp = bukkitServer.getServicesManager().getRegistration(Economy.class); if (rsp == null) { throw new InternalServerErrorResponse(Constants.ECONOMY_PLUGIN_MISSING); } @@ -82,7 +88,7 @@ public static void getEconomyPluginInformation(Context ctx) { @OpenApiResponse(status = "500", content = @OpenApiContent(type = "application/json")) } ) - public static void playerPay(Context ctx) { + public void playerPay(Context ctx) { accountManager(ctx, TransactionType.PAY); } @@ -112,37 +118,40 @@ public static void playerPay(Context ctx) { @OpenApiResponse(status = "500", content = @OpenApiContent(type = "application/json")) } ) - public static void playerDebit(Context ctx) { + public void playerDebit(Context ctx) { accountManager(ctx, TransactionType.DEBIT); } - private static void accountManager(Context ctx, TransactionType action) { - if (ctx.formParam("uuid") == null || ctx.formParam("amount") == null) { + private void accountManager(Context ctx, TransactionType action) { + String uuid = ctx.formParam("uuid"); + String amount = ctx.formParam("amount"); + + if (uuid == null || amount == null) { throw new BadRequestResponse(Constants.VAULT_MISSING_PAY_PARAMS); } - if (EconomyWrapper.getInstance().getEconomy() == null) { + if (!economy.isAvailable()) { throw new HttpResponseException(424, Constants.VAULT_MISSING, new HashMap<>()); } - UUID playerUUID = ValidationUtils.safeUUID(ctx.formParam("uuid")); + UUID playerUUID = ValidationUtils.safeUUID(uuid); if (playerUUID == null) { throw new BadRequestResponse(Constants.INVALID_UUID); } OfflinePlayer player = Bukkit.getOfflinePlayer(playerUUID); - double amount = Double.parseDouble(ctx.formParam("amount")); + double amountNum = Double.parseDouble(amount); - if (amount <= 0) { // Make sure pay amount is more than zero + if (amountNum <= 0) { // Make sure pay amount is more than zero throw new BadRequestResponse(Constants.VAULT_GREATER_THAN_ZERO); } EconomyResponse response; if (action == TransactionType.PAY) { - response = EconomyWrapper.getInstance().getEconomy().depositPlayer(player, amount); + response = economy.depositPlayer(player, amountNum); } else { - response = EconomyWrapper.getInstance().getEconomy().withdrawPlayer(player, amount); + response = economy.withdrawPlayer(player, amountNum); } if (response.type != EconomyResponse.ResponseType.SUCCESS) { diff --git a/src/main/java/io/servertap/api/v1/PAPIApi.java b/src/main/java/io/servertap/api/v1/PAPIApi.java index acbcd9bc..bd08df2f 100644 --- a/src/main/java/io/servertap/api/v1/PAPIApi.java +++ b/src/main/java/io/servertap/api/v1/PAPIApi.java @@ -11,7 +11,6 @@ import java.util.UUID; public class PAPIApi { - @OpenApi( path = "/v1/placeholders/replace", methods = {HttpMethod.POST}, @@ -38,7 +37,7 @@ public class PAPIApi { @OpenApiResponse(status = "500", content = @OpenApiContent(type = "application/json")) } ) - public static void replacePlaceholders(Context ctx) { + public void replacePlaceholders(Context ctx) { OfflinePlayer player = null; String passedUuid = ctx.formParam("uuid"); diff --git a/src/main/java/io/servertap/api/v1/PlayerApi.java b/src/main/java/io/servertap/api/v1/PlayerApi.java index 98573214..08b9731f 100644 --- a/src/main/java/io/servertap/api/v1/PlayerApi.java +++ b/src/main/java/io/servertap/api/v1/PlayerApi.java @@ -6,7 +6,7 @@ import io.servertap.Constants; import io.servertap.api.v1.models.ItemStack; import io.servertap.api.v1.models.Player; -import io.servertap.utils.EconomyWrapper; +import io.servertap.utils.pluginwrappers.EconomyWrapper; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; @@ -16,8 +16,16 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.UUID; +import java.util.logging.Logger; public class PlayerApi { + private final EconomyWrapper economy; + private final Logger log; + + public PlayerApi(Logger log, EconomyWrapper economy) { + this.economy = economy; + this.log = log; + } @OpenApi( path = "/v1/players", @@ -30,12 +38,10 @@ public class PlayerApi { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Player.class)) } ) - public static void playersGet(Context ctx) { + public void playersGet(Context ctx) { ArrayList players = new ArrayList<>(); - Bukkit.getOnlinePlayers().forEach((player -> { - players.add(getPlayer(player)); - })); + Bukkit.getOnlinePlayers().forEach(player -> players.add(getPlayer(player))); ctx.json(players); } @@ -55,21 +61,19 @@ public static void playersGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Player.class)) } ) - public static void playerGet(Context ctx) { - if (ctx.pathParam("uuid").isEmpty()) { - throw new BadRequestResponse(Constants.PLAYER_UUID_MISSING); - } + public void playerGet(Context ctx) { + String uuid = ctx.pathParam("uuid"); - UUID playerUUID = ValidationUtils.safeUUID(ctx.pathParam("uuid")); + if (uuid.isEmpty()) throw new BadRequestResponse(Constants.PLAYER_UUID_MISSING); + + UUID playerUUID = ValidationUtils.safeUUID(uuid); if (playerUUID == null) { throw new BadRequestResponse(Constants.INVALID_UUID); } org.bukkit.entity.Player player = Bukkit.getPlayer(playerUUID); - if (player == null) { - throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); - } + if (player == null) throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); ctx.json(getPlayer(player)); } @@ -80,7 +84,7 @@ public static void playerGet(Context ctx) { * @param player The Bukkit player * @return The ServerTap player */ - private static Player getPlayer(org.bukkit.entity.Player player) { + private Player getPlayer(org.bukkit.entity.Player player) { Player p = new Player(); p.setUuid(player.getUniqueId().toString()); p.setDisplayName(player.getDisplayName()); @@ -95,8 +99,8 @@ private static Player getPlayer(org.bukkit.entity.Player player) { p.setBanned(player.isBanned()); p.setOp(player.isOp()); - if (EconomyWrapper.getInstance().getEconomy() != null) { - p.setBalance(EconomyWrapper.getInstance().getEconomy().getBalance(player)); + if (economy.isAvailable()) { + p.setBalance(economy.getPlayerBalance(player)); } p.setHunger(player.getFoodLevel()); @@ -131,27 +135,26 @@ private static Player getPlayer(org.bukkit.entity.Player player) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = io.servertap.api.v1.models.OfflinePlayer.class)) } ) - public static void offlinePlayersGet(Context ctx) { + public void offlinePlayersGet(Context ctx) { ArrayList players = new ArrayList<>(); OfflinePlayer[] offlinePlayers = Bukkit.getOfflinePlayers(); - for (int i = 0; i < offlinePlayers.length; i++) { + for (OfflinePlayer offlinePlayer : offlinePlayers) { io.servertap.api.v1.models.OfflinePlayer p = new io.servertap.api.v1.models.OfflinePlayer(); - OfflinePlayer player = offlinePlayers[i]; - p.setDisplayName(player.getName()); - p.setUuid(player.getUniqueId().toString()); - p.setWhitelisted(player.isWhitelisted()); - p.setBanned(player.isBanned()); - p.setOp(player.isOp()); + p.setDisplayName(offlinePlayer.getName()); + p.setUuid(offlinePlayer.getUniqueId().toString()); + p.setWhitelisted(offlinePlayer.isWhitelisted()); + p.setBanned(offlinePlayer.isBanned()); + p.setOp(offlinePlayer.isOp()); - if (EconomyWrapper.getInstance().getEconomy() != null) { - p.setBalance(EconomyWrapper.getInstance().getEconomy().getBalance(offlinePlayers[i])); + if (economy.isAvailable()) { + p.setBalance(economy.getPlayerBalance(offlinePlayer)); } - p.setLastPlayed(player.getLastPlayed()); + p.setLastPlayed(offlinePlayer.getLastPlayed()); players.add(p); } @@ -175,21 +178,23 @@ public static void offlinePlayersGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = io.servertap.api.v1.models.ItemStack.class)) } ) - public static void getPlayerInv(Context ctx) { - if (ctx.pathParam("playerUuid").isEmpty() || ctx.pathParam("worldUuid").isEmpty()) { + public void getPlayerInv(Context ctx) { + String playerUUIDStr = ctx.pathParam("playerUuid"); + String worldUUIDStr = ctx.pathParam("worldUuid"); + if (playerUUIDStr.isEmpty() || worldUUIDStr.isEmpty()) { throw new BadRequestResponse(Constants.PLAYER_MISSING_PARAMS); } - UUID playerUUID = ValidationUtils.safeUUID(ctx.pathParam("playerUuid")); + UUID playerUUID = ValidationUtils.safeUUID(playerUUIDStr); if (playerUUID == null) { throw new BadRequestResponse(Constants.INVALID_UUID); } - UUID worldUUID = ValidationUtils.safeUUID(ctx.pathParam("worldUuid")); + UUID worldUUID = ValidationUtils.safeUUID(worldUUIDStr); if (worldUUID == null) { throw new BadRequestResponse(Constants.INVALID_UUID); } - ArrayList inv = new ArrayList(); + ArrayList inv = new ArrayList<>(); org.bukkit.entity.Player player = Bukkit.getPlayer(playerUUID); if (player != null) { player.updateInventory(); @@ -240,7 +245,7 @@ public static void getPlayerInv(Context ctx) { // Pass any javalin exceptions up the chain throw e; } catch (Exception e) { - Bukkit.getLogger().warning(e.getMessage()); + log.warning(e.getMessage()); throw new InternalServerErrorResponse(Constants.PLAYER_INV_PARSE_FAIL); } } diff --git a/src/main/java/io/servertap/api/v1/PluginApi.java b/src/main/java/io/servertap/api/v1/PluginApi.java index 7dd5ca3b..f16e983c 100644 --- a/src/main/java/io/servertap/api/v1/PluginApi.java +++ b/src/main/java/io/servertap/api/v1/PluginApi.java @@ -19,8 +19,13 @@ import java.util.logging.Logger; public class PluginApi { + private final Logger log; + private final ServerTapMain main; - private static final Logger log = Bukkit.getLogger(); + public PluginApi(ServerTapMain main, Logger log) { + this.log = log; + this.main = main; + } @OpenApi( path = "/v1/plugins", @@ -35,7 +40,7 @@ public class PluginApi { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/json")) } ) - public static void listPlugins(Context ctx) { + public void listPlugins(Context ctx) { ArrayList pluginList = new ArrayList<>(); for (org.bukkit.plugin.Plugin plugin : Bukkit.getPluginManager().getPlugins()) { @@ -79,8 +84,8 @@ public static void listPlugins(Context ctx) { @OpenApiResponse(status = "201", content = @OpenApiContent(type = "application/json")) } ) - public static void installPlugin(Context ctx) { - String stagingPath = ServerTapMain.instance.getDataFolder().getPath() + File.separator + "downloads"; + public void installPlugin(Context ctx) { + String stagingPath = main.getDataFolder().getPath() + File.separator + "downloads"; File holdingArea = new File(stagingPath); URL url = null; @@ -116,7 +121,7 @@ public static void installPlugin(Context ctx) { String msg = String.format("Downloaded plugin in %.2f seconds", elapsed / 1000.0); log.info("[ServerTap]" + msg); - String targetFilename = ServerTapMain.instance.getDataFolder().getAbsoluteFile().getParent() + File.separator + FilenameUtils.getName(url.getPath()); + String targetFilename = main.getDataFolder().getAbsoluteFile().getParent() + File.separator + FilenameUtils.getName(url.getPath()); boolean success = downloadedFile.renameTo(new File(targetFilename)); if (!success) { throw new InternalServerErrorResponse("Error moving plugin to plugins dir"); diff --git a/src/main/java/io/servertap/api/v1/ServerApi.java b/src/main/java/io/servertap/api/v1/ServerApi.java index bb16d3af..f139f6d9 100644 --- a/src/main/java/io/servertap/api/v1/ServerApi.java +++ b/src/main/java/io/servertap/api/v1/ServerApi.java @@ -6,12 +6,12 @@ import io.javalin.http.ServiceUnavailableResponse; import io.javalin.openapi.*; import io.servertap.Constants; -import io.servertap.utils.Lag; +import io.servertap.ServerTapMain; +import io.servertap.utils.LagDetector; import io.servertap.utils.ServerExecCommandSender; import io.servertap.api.v1.models.*; import io.servertap.mojang.api.MojangApiService; -import io.servertap.mojang.api.models.NameChange; -import io.servertap.utils.EconomyWrapper; +import io.servertap.utils.pluginwrappers.EconomyWrapper; import io.servertap.utils.GsonSingleton; import org.apache.commons.lang.StringUtils; import org.bukkit.BanList; @@ -31,8 +31,19 @@ import java.util.logging.Logger; public class ServerApi { - - private static final Logger log = Bukkit.getLogger(); + private final Logger log; + private final ServerTapMain main; + private final EconomyWrapper economy; + private final org.bukkit.Server bukkitServer = Bukkit.getServer(); + private final ScoreboardManager scoreboardManager = Bukkit.getScoreboardManager(); + private final LagDetector lagDetector; + + public ServerApi(ServerTapMain main, Logger log, LagDetector lagDetector, EconomyWrapper economy) { + this.log = log; + this.main = main; + this.economy = economy; + this.lagDetector = lagDetector; + } @OpenApi( path = "/v1/ping", @@ -45,7 +56,7 @@ public class ServerApi { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/json")) } ) - public static void ping(Context ctx) { + public void ping(Context ctx) { ctx.json("pong"); } @@ -60,9 +71,8 @@ public static void ping(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Server.class)) } ) - public static void serverGet(Context ctx) { + public void serverGet(Context ctx) { Server server = new Server(); - org.bukkit.Server bukkitServer = Bukkit.getServer(); server.setName(bukkitServer.getName()); server.setMotd(bukkitServer.getMotd()); server.setVersion(bukkitServer.getVersion()); @@ -72,7 +82,7 @@ public static void serverGet(Context ctx) { server.setOnlinePlayers(bukkitServer.getOnlinePlayers().size()); // Possibly add 5m and 15m in the future? - server.setTps(Lag.getTPSString()); + server.setTps(lagDetector.getTPSString()); // Get the list of IP bans Set bannedIps = new HashSet<>(); @@ -149,11 +159,10 @@ public static void serverGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/json")) } ) - public static void broadcastPost(Context ctx) { - if (ctx.formParam("message").isEmpty()) { - throw new BadRequestResponse(Constants.CHAT_MISSING_MESSAGE); - } - Bukkit.broadcastMessage(ctx.formParam("message")); + public void broadcastPost(Context ctx) { + String msg = ctx.formParam("message"); + if (msg != null && msg.isEmpty()) throw new BadRequestResponse(Constants.CHAT_MISSING_MESSAGE); + Bukkit.broadcastMessage(msg); ctx.json("success"); } @@ -181,24 +190,18 @@ public static void broadcastPost(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/json")) } ) - public static void tellPost(Context ctx) { - if (ctx.formParam("message").isEmpty()) { - throw new BadRequestResponse(Constants.CHAT_MISSING_MESSAGE); - } - if (ctx.formParam("playerUuid").isEmpty()) { - throw new BadRequestResponse(Constants.PLAYER_UUID_MISSING); - } + public void tellPost(Context ctx) { + String msg = ctx.formParam("message"); + String uuid = ctx.formParam("playerUuid"); + if (msg != null && msg.isEmpty()) throw new BadRequestResponse(Constants.CHAT_MISSING_MESSAGE); + if (uuid != null && uuid.isEmpty()) throw new BadRequestResponse(Constants.PLAYER_UUID_MISSING); - UUID playerUUID = ValidationUtils.safeUUID(ctx.formParam("playerUuid")); - if (playerUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + UUID playerUUID = ValidationUtils.safeUUID(uuid); + if (playerUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); org.bukkit.entity.Player player = Bukkit.getPlayer(playerUUID); - if (player == null) { - throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); - } - player.sendMessage(ctx.formParam("message")); + if (player == null) throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); + player.sendMessage(msg); ctx.json("success"); } @@ -215,9 +218,8 @@ public static void tellPost(Context ctx) { } ) - public static void scoreboardGet(Context ctx) { - ScoreboardManager manager = Bukkit.getScoreboardManager(); - org.bukkit.scoreboard.Scoreboard gameScoreboard = manager.getMainScoreboard(); + public void scoreboardGet(Context ctx) { + org.bukkit.scoreboard.Scoreboard gameScoreboard = scoreboardManager.getMainScoreboard(); Scoreboard scoreboardModel = new Scoreboard(); Set objectives = new HashSet<>(); @@ -245,22 +247,18 @@ public static void scoreboardGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Objective.class)) } ) - public static void objectiveGet(Context ctx) { + public void objectiveGet(Context ctx) { String objectiveName = ctx.pathParam("name"); - ScoreboardManager manager = Bukkit.getScoreboardManager(); - org.bukkit.scoreboard.Scoreboard gameScoreboard = manager.getMainScoreboard(); + org.bukkit.scoreboard.Scoreboard gameScoreboard = scoreboardManager.getMainScoreboard(); org.bukkit.scoreboard.Objective objective = gameScoreboard.getObjective(objectiveName); - if (objective == null) { - throw new NotFoundResponse(); - } + if (objective == null) throw new NotFoundResponse(); ctx.json(fromBukkitObjective(objective)); } - private static Objective fromBukkitObjective(org.bukkit.scoreboard.Objective objective) { - ScoreboardManager manager = Bukkit.getScoreboardManager(); - org.bukkit.scoreboard.Scoreboard gameScoreboard = manager.getMainScoreboard(); + private Objective fromBukkitObjective(org.bukkit.scoreboard.Objective objective) { + org.bukkit.scoreboard.Scoreboard gameScoreboard = scoreboardManager.getMainScoreboard(); Objective o = new Objective(); o.setCriterion(objective.getCriteria()); @@ -289,11 +287,9 @@ private static Objective fromBukkitObjective(org.bukkit.scoreboard.Objective obj return o; } - private static Set getWhitelist() { - Set whitelist = new HashSet(); - Bukkit.getServer().getWhitelistedPlayers().forEach((OfflinePlayer player) -> { - whitelist.add(new Whitelist().offlinePlayer(player)); - }); + private Set getWhitelist() { + Set whitelist = new HashSet<>(); + bukkitServer.getWhitelistedPlayers().forEach((OfflinePlayer player) -> whitelist.add(new Whitelist().offlinePlayer(player))); return whitelist; } @@ -309,8 +305,8 @@ private static Set getWhitelist() { @OpenApiResponse(status = "200", content = @OpenApiContent(from = Whitelist.class)) } ) - public static void whitelistGet(Context ctx) { - if (!Bukkit.getServer().hasWhitelist()) { + public void whitelistGet(Context ctx) { + if (bukkitServer.hasWhitelist()) { // TODO: Handle Errors better ctx.json("error: The server has whitelist disabled"); return; @@ -343,8 +339,7 @@ public static void whitelistGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/json")) } ) - public static void whitelistPost(Context ctx) { - final org.bukkit.Server bukkitServer = Bukkit.getServer(); + public void whitelistPost(Context ctx) { if (!bukkitServer.hasWhitelist()) { ctx.json("No whitelist"); return; @@ -353,9 +348,7 @@ public static void whitelistPost(Context ctx) { String uuid = ctx.formParam("uuid"); String name = ctx.formParam("name"); - if (uuid == null && name == null) { - throw new BadRequestResponse(Constants.WHITELIST_MISSING_PARAMS); - } + if (uuid == null && name == null) throw new BadRequestResponse(Constants.WHITELIST_MISSING_PARAMS); //Check Mojang API for missing param if (uuid == null) { @@ -366,16 +359,7 @@ public static void whitelistPost(Context ctx) { } catch (IOException ignored) { throw new ServiceUnavailableResponse(Constants.WHITELIST_MOJANG_API_FAIL); } - } else if (name == null) { - try { - List nameHistory = MojangApiService.getNameHistory(uuid); - name = nameHistory.get(nameHistory.size() - 1).getName(); - } catch (IllegalArgumentException ignored) { - throw new NotFoundResponse(Constants.WHITELIST_UUID_NOT_FOUND); - } catch (IOException ignored) { - throw new ServiceUnavailableResponse(Constants.WHITELIST_MOJANG_API_FAIL); - } - } + } // **MojangApiService.getNameHistory was deprecated and then removed** //Whitelist file doesn't accept UUIDs without dashes uuid = uuid.replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"); @@ -429,8 +413,7 @@ public static void whitelistPost(Context ctx) { ), responses = {@OpenApiResponse(status = "200")} ) - public static void whitelistDelete(Context ctx) { - final org.bukkit.Server bukkitServer = Bukkit.getServer(); + public void whitelistDelete(Context ctx) { if (!bukkitServer.hasWhitelist()) { ctx.json("No whitelist"); return; @@ -439,9 +422,7 @@ public static void whitelistDelete(Context ctx) { String uuid = ctx.formParam("uuid"); String name = ctx.formParam("name"); - if (uuid == null && name == null) { - throw new BadRequestResponse(Constants.WHITELIST_MISSING_PARAMS); - } + if (uuid == null && name == null) throw new BadRequestResponse(Constants.WHITELIST_MISSING_PARAMS); //Check Mojang API for missing param if (uuid == null) { @@ -452,16 +433,7 @@ public static void whitelistDelete(Context ctx) { } catch (IOException ignored) { throw new ServiceUnavailableResponse(Constants.WHITELIST_MOJANG_API_FAIL); } - } else if (name == null) { - try { - List nameHistory = MojangApiService.getNameHistory(uuid); - name = nameHistory.get(nameHistory.size() - 1).getName(); - } catch (IllegalArgumentException ignored) { - throw new NotFoundResponse(Constants.WHITELIST_UUID_NOT_FOUND); - } catch (IOException ignored) { - throw new ServiceUnavailableResponse(Constants.WHITELIST_MOJANG_API_FAIL); - } - } + } // **MojangApiService.getNameHistory was deprecated and then removed** //Whitelist file doesn't accept UUIDs without dashes uuid = uuid.replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"); @@ -510,20 +482,17 @@ public static void whitelistDelete(Context ctx) { responses = { @OpenApiResponse(status = "200") }) - public static void opPlayer(Context ctx) { - if (ctx.formParam("playerUuid").isEmpty()) { - throw new BadRequestResponse(Constants.PLAYER_MISSING_PARAMS); - } + public void opPlayer(Context ctx) { + String uuid = ctx.formParam("playerUuid"); + String name = ctx.formParam("name"); - UUID playerUUID = ValidationUtils.safeUUID(ctx.formParam("playerUuid")); - if (playerUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + if (name.isEmpty()) throw new BadRequestResponse(Constants.PLAYER_MISSING_PARAMS); + + UUID playerUUID = ValidationUtils.safeUUID(uuid); + if (playerUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); org.bukkit.OfflinePlayer player = Bukkit.getOfflinePlayer(playerUUID); - if (player == null) { - throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); - } + if (player == null) throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); player.setOp(true); ctx.json("success"); } @@ -549,20 +518,16 @@ public static void opPlayer(Context ctx) { ), responses = {@OpenApiResponse(status = "200")} ) - public static void deopPlayer(Context ctx) { - if (ctx.formParam("playerUuid").isEmpty()) { - throw new BadRequestResponse(Constants.PLAYER_MISSING_PARAMS); - } + public void deopPlayer(Context ctx) { + String uuid = ctx.formParam("playerUuid"); - UUID playerUUID = ValidationUtils.safeUUID(ctx.formParam("playerUuid")); - if (playerUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + if (uuid.isEmpty()) throw new BadRequestResponse(Constants.PLAYER_MISSING_PARAMS); + + UUID playerUUID = ValidationUtils.safeUUID(uuid); + if (playerUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); org.bukkit.OfflinePlayer player = Bukkit.getOfflinePlayer(playerUUID); - if (player == null) { - throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); - } + if (player == null) throw new NotFoundResponse(Constants.PLAYER_NOT_FOUND); player.setOp(false); ctx.json("success"); } @@ -584,9 +549,9 @@ public static void deopPlayer(Context ctx) { ) } ) - public static void getOps(Context ctx) { + public void getOps(Context ctx) { Set players = Bukkit.getOperators(); - ArrayList opedPlayers = new ArrayList(); + ArrayList opedPlayers = new ArrayList<>(); for (org.bukkit.OfflinePlayer player : players) { if (!player.isOp()) { continue; @@ -598,8 +563,8 @@ public static void getOps(Context ctx) { p.setBanned(player.isBanned()); p.setOp(player.isOp()); - if (EconomyWrapper.getInstance().getEconomy() != null) { - p.setBalance(EconomyWrapper.getInstance().getEconomy().getBalance(player)); + if (economy.isAvailable()) { + p.setBalance(economy.getPlayerBalance(player)); } opedPlayers.add(p); @@ -636,13 +601,13 @@ public static void getOps(Context ctx) { ) } ) - public static void postCommand(Context ctx) { - String command = ctx.formParam("command"); - if (StringUtils.isBlank(command)) { - throw new BadRequestResponse(Constants.COMMAND_PAYLOAD_MISSING); - } + public void postCommand(Context ctx) { + String command = ctx.formParam("command"); String timeRaw = ctx.formParam("time"); + + if (StringUtils.isBlank(command)) throw new BadRequestResponse(Constants.COMMAND_PAYLOAD_MISSING); + if (StringUtils.isBlank(timeRaw)) { timeRaw = "0"; } @@ -651,7 +616,8 @@ public static void postCommand(Context ctx) { if (time.get() < 0) time.set(0); ctx.future(() -> runCommandAsync(command, time.get()).thenAccept( - output -> { + ret -> { + String output = String.join("\n", ret); if ("application/json".equalsIgnoreCase(ctx.contentType())) { ctx.json(output); } else { @@ -664,8 +630,7 @@ public static void postCommand(Context ctx) { })); } - private static CompletableFuture runCommandAsync(String command, long time) { - return new ServerExecCommandSender().executeCommand(command, time, TimeUnit.MILLISECONDS); + private CompletableFuture> runCommandAsync(String command, long time) { + return new ServerExecCommandSender(main).executeCommand(command, time, TimeUnit.MILLISECONDS); } - } diff --git a/src/main/java/io/servertap/api/v1/WorldApi.java b/src/main/java/io/servertap/api/v1/WorldApi.java index bcedabae..44f0e805 100644 --- a/src/main/java/io/servertap/api/v1/WorldApi.java +++ b/src/main/java/io/servertap/api/v1/WorldApi.java @@ -6,13 +6,13 @@ import io.javalin.http.NotFoundResponse; import io.javalin.openapi.*; import io.servertap.Constants; +import io.servertap.ServerTapMain; import io.servertap.api.v1.models.World; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.io.IOUtils; import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; import java.io.BufferedOutputStream; import java.io.File; @@ -25,8 +25,14 @@ import java.util.logging.Logger; public class WorldApi { + private final Logger log; + private final ServerTapMain main; + private final org.bukkit.Server bukkitServer = Bukkit.getServer(); - private static final Logger log = Bukkit.getLogger(); + public WorldApi(ServerTapMain main, Logger log) { + this.log = log; + this.main = main; + } @OpenApi( path = "/v1/worlds/save", @@ -40,14 +46,10 @@ public class WorldApi { @OpenApiResponse(status = "200") } ) - public static void saveAllWorlds(Context ctx) { - org.bukkit.Server bukkitServer = Bukkit.getServer(); - - Plugin pluginInstance = bukkitServer.getPluginManager().getPlugin("ServerTap"); - - if (pluginInstance != null) { + public void saveAllWorlds(Context ctx) { + if (main != null) { // Run the saves on the main thread, can't use sync methods from here otherwise - bukkitServer.getScheduler().scheduleSyncDelayedTask(pluginInstance, () -> { + bukkitServer.getScheduler().scheduleSyncDelayedTask(main, () -> { for (org.bukkit.World world : Bukkit.getWorlds()) { try { world.save(); @@ -77,23 +79,16 @@ public static void saveAllWorlds(Context ctx) { @OpenApiResponse(status = "200") } ) - public static void saveWorld(Context ctx) { - org.bukkit.Server bukkitServer = Bukkit.getServer(); - + public void saveWorld(Context ctx) { UUID worldUUID = ValidationUtils.safeUUID(ctx.pathParam("uuid")); - if (worldUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + if (worldUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); org.bukkit.World world = bukkitServer.getWorld(worldUUID); if (world != null) { - Plugin pluginInstance = bukkitServer.getPluginManager().getPlugin("ServerTap"); - - if (pluginInstance != null) { + if (main != null) { // Run the saves on the main thread, can't use sync methods from here otherwise - bukkitServer.getScheduler().scheduleSyncDelayedTask(pluginInstance, () -> { - + bukkitServer.getScheduler().scheduleSyncDelayedTask(main, () -> { try { world.save(); } catch (Exception e) { @@ -107,7 +102,7 @@ public static void saveWorld(Context ctx) { ctx.json("success"); } - private static void addFolderToTarGz(File folder, TarArchiveOutputStream tar, String baseName, String rootName) throws IOException { + private void addFolderToTarGz(File folder, TarArchiveOutputStream tar, String baseName, String rootName) throws IOException { File[] files = folder.listFiles(); assert files != null; for (File file : files) { @@ -155,13 +150,9 @@ private static void addFolderToTarGz(File folder, TarArchiveOutputStream tar, St @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/zip")), } ) - public static void downloadWorld(Context ctx) throws IOException { - org.bukkit.Server bukkitServer = Bukkit.getServer(); - + public void downloadWorld(Context ctx) throws IOException { UUID worldUUID = ValidationUtils.safeUUID(ctx.pathParam("uuid")); - if (worldUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + if (worldUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); org.bukkit.World world = bukkitServer.getWorld(worldUUID); @@ -180,9 +171,7 @@ public static void downloadWorld(Context ctx) throws IOException { tar.close(); gzOut.close(); buffOut.close(); - } else { - throw new NotFoundResponse(Constants.WORLD_NOT_FOUND); - } + } else throw new NotFoundResponse(Constants.WORLD_NOT_FOUND); } @OpenApi( @@ -197,11 +186,7 @@ public static void downloadWorld(Context ctx) throws IOException { @OpenApiResponse(status = "200", content = @OpenApiContent(type = "application/zip")), } ) - public static void downloadWorlds(Context ctx) throws IOException { - org.bukkit.Server bukkitServer = Bukkit.getServer(); - - Plugin pluginInstance = bukkitServer.getPluginManager().getPlugin("ServerTap"); - + public void downloadWorlds(Context ctx) throws IOException { ctx.header("Content-Disposition", "attachment; filename=\"worlds.tar.gz\""); ctx.header("Content-Type", "application/zip"); @@ -239,9 +224,9 @@ public static void downloadWorlds(Context ctx) throws IOException { @OpenApiResponse(status = "200", content = @OpenApiContent(from = World.class)) } ) - public static void worldsGet(Context ctx) { + public void worldsGet(Context ctx) { List worlds = new ArrayList<>(); - Bukkit.getServer().getWorlds().forEach(world -> worlds.add(fromBukkitWorld(world))); + bukkitServer.getWorlds().forEach(world -> worlds.add(fromBukkitWorld(world))); ctx.json(worlds); } @@ -260,14 +245,11 @@ public static void worldsGet(Context ctx) { @OpenApiResponse(status = "200", content = @OpenApiContent(from = World.class)) } ) - public static void worldGet(Context ctx) { - + public void worldGet(Context ctx) { UUID worldUUID = ValidationUtils.safeUUID(ctx.pathParam("uuid")); - if (worldUUID == null) { - throw new BadRequestResponse(Constants.INVALID_UUID); - } + if (worldUUID == null) throw new BadRequestResponse(Constants.INVALID_UUID); - org.bukkit.World bukkitWorld = Bukkit.getServer().getWorld(worldUUID); + org.bukkit.World bukkitWorld = bukkitServer.getWorld(worldUUID); // 404 if no world found if (bukkitWorld == null) throw new NotFoundResponse(); @@ -275,7 +257,7 @@ public static void worldGet(Context ctx) { ctx.json(fromBukkitWorld(bukkitWorld)); } - private static World fromBukkitWorld(org.bukkit.World bukkitWorld) { + private World fromBukkitWorld(org.bukkit.World bukkitWorld) { World world = new World(); world.setName(bukkitWorld.getName()); diff --git a/src/main/java/io/servertap/api/v1/websockets/WebsocketHandler.java b/src/main/java/io/servertap/api/v1/websockets/WebsocketHandler.java index c454955b..4465d296 100644 --- a/src/main/java/io/servertap/api/v1/websockets/WebsocketHandler.java +++ b/src/main/java/io/servertap/api/v1/websockets/WebsocketHandler.java @@ -4,22 +4,32 @@ import io.javalin.websocket.WsContext; import io.servertap.ServerTapMain; import io.servertap.api.v1.models.ConsoleLine; +import io.servertap.utils.ConsoleListener; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; public class WebsocketHandler { + private final Map subscribers; + private final ServerTapMain main; + private final Logger log; - private final static Map subscribers = new ConcurrentHashMap<>(); + public WebsocketHandler(ServerTapMain main, Logger log, ConsoleListener consoleListener) { + subscribers = new ConcurrentHashMap<>(); + this.main = main; + this.log = log; - public static void events(WsConfig ws) { + consoleListener.addListener(this::broadcast); + } + + public void events(WsConfig ws) { ws.onConnect(ctx -> { subscribers.put(clientHash(ctx), ctx); - for (ConsoleLine line : ServerTapMain.instance.getConsoleBuffer()) { + for (ConsoleLine line : main.getConsoleBuffer()) { ctx.send(line); } }); @@ -41,18 +51,16 @@ public static void events(WsConfig ws) { } final String command = cmd; - Plugin pluginInstance = ServerTapMain.instance; - - if (pluginInstance != null) { + if (main != null) { // Run the command on the main thread - Bukkit.getScheduler().scheduleSyncDelayedTask(pluginInstance, () -> { + Bukkit.getScheduler().scheduleSyncDelayedTask(main, () -> { try { CommandSender sender = Bukkit.getServer().getConsoleSender(); Bukkit.dispatchCommand(sender, command); } catch (Exception e) { // Just warn about the issue - Bukkit.getLogger().warning("Couldn't execute command over websocket"); + log.warning("Couldn't execute command over websocket"); } }); } @@ -65,7 +73,7 @@ public static void events(WsConfig ws) { * * @param message Object can be any Jackson/JSON serializable object */ - public static void broadcast(Object message) { + public void broadcast(Object message) { subscribers.values().stream().filter(ctx -> ctx.session.isOpen()).forEach(session -> session.send(message)); } @@ -75,7 +83,7 @@ public static void broadcast(Object message) { * @param ctx The WebSocket Context * @return String the hash */ - private static String clientHash(WsContext ctx) { + private String clientHash(WsContext ctx) { return String.format("sub-%s-%s", ctx.host(), ctx.getSessionId()); } -} +} \ No newline at end of file diff --git a/src/main/java/io/servertap/commands/ServerTapCommand.java b/src/main/java/io/servertap/commands/ServerTapCommand.java index b557cc99..bc3c50be 100644 --- a/src/main/java/io/servertap/commands/ServerTapCommand.java +++ b/src/main/java/io/servertap/commands/ServerTapCommand.java @@ -30,6 +30,7 @@ public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command commandSender.sendMessage(String.format("%s[%sServerTap%s] %sYou do not have the permission to do that!", DARK_GRAY, BLUE, DARK_GRAY, AQUA)); return false; } + if (args.length == 1) { switch (args[0]) { case "reload": diff --git a/src/main/java/io/servertap/mojang/api/MojangApiService.java b/src/main/java/io/servertap/mojang/api/MojangApiService.java index 38f2546d..c6a53c8b 100644 --- a/src/main/java/io/servertap/mojang/api/MojangApiService.java +++ b/src/main/java/io/servertap/mojang/api/MojangApiService.java @@ -19,7 +19,6 @@ public class MojangApiService { private static final String getUuidResource = "https://api.mojang.com/users/profiles/minecraft/%s"; - private static final String getNameHistoryResource = "https://api.mojang.com/user/profiles/%s/names"; public static String getUuid(String username) throws IOException { Gson gson = GsonSingleton.getInstance(); @@ -32,21 +31,6 @@ public static String getUuid(String username) throws IOException { return gson.fromJson(apiResponse.getContent(), PlayerInfo.class).getId(); } - public static List getNameHistory(String uuid) throws IOException { - Type listType = new TypeToken>() { - }.getType(); - Gson gson = GsonSingleton.getInstance(); - - //This API call doesn't accept UUIDS with dashes - ApiResponse apiResponse = getApiResponse(String.format(getNameHistoryResource, uuid).replace("-", "")); - if (apiResponse.getHttpStatus() == HttpURLConnection.HTTP_BAD_REQUEST || - apiResponse.getHttpStatus() == HttpURLConnection.HTTP_NO_CONTENT) { - throw new IllegalArgumentException("The given uuid was not found by the Mojang API."); - } - - return gson.fromJson(apiResponse.getContent(), listType); - } - private static ApiResponse getApiResponse(String resource) throws IOException { try { String responseContent; @@ -58,9 +42,7 @@ private static ApiResponse getApiResponse(String resource) throws IOException { http.connect(); - if (http.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) { - return new ApiResponse("", http.getResponseCode()); - } + if (http.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) return new ApiResponse("", http.getResponseCode()); try (InputStream is = http.getInputStream()) { responseContent = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n")); diff --git a/src/main/java/io/servertap/api/v1/websockets/ConsoleListener.java b/src/main/java/io/servertap/utils/ConsoleListener.java similarity index 87% rename from src/main/java/io/servertap/api/v1/websockets/ConsoleListener.java rename to src/main/java/io/servertap/utils/ConsoleListener.java index 5509eb7b..9a29b12e 100644 --- a/src/main/java/io/servertap/api/v1/websockets/ConsoleListener.java +++ b/src/main/java/io/servertap/utils/ConsoleListener.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.websockets; +package io.servertap.utils; import io.servertap.ServerTapMain; import io.servertap.api.v1.models.ConsoleLine; @@ -9,12 +9,16 @@ import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.message.Message; -public class ConsoleListener implements Filter { +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +public class ConsoleListener implements Filter { private final ServerTapMain plugin; + private final List> listeners = new ArrayList<>(); - public ConsoleListener(ServerTapMain plugin) { - this.plugin = plugin; + public ConsoleListener(ServerTapMain main) { + this.plugin = main; } @Override @@ -34,11 +38,19 @@ public Result filter(LogEvent logEvent) { plugin.getConsoleBuffer().add(line); } - WebsocketHandler.broadcast(line); + listeners.forEach(consoleLineConsumer -> consoleLineConsumer.accept(line)); return Result.NEUTRAL; } + public void addListener(Consumer consoleLineConsumer) { + listeners.add(consoleLineConsumer); + } + + public void resetListeners() { + listeners.clear(); + } + @Override public Result getOnMismatch() { return null; diff --git a/src/main/java/io/servertap/utils/EconomyWrapper.java b/src/main/java/io/servertap/utils/EconomyWrapper.java deleted file mode 100644 index 6b309925..00000000 --- a/src/main/java/io/servertap/utils/EconomyWrapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.servertap.utils; - -import net.milkbowl.vault.economy.Economy; -import org.bukkit.Bukkit; -import org.bukkit.plugin.RegisteredServiceProvider; - -import java.util.logging.Logger; - -/** - * We can't simply reference Economy in ServerTapMain due to OpenApi annotation doing reflection, which can fail at - * runtime due to the `scope` of the Vault API being `provided`.
- *
- * More details here: https://github.com/phybros/servertap/issues/175 - */ -public class EconomyWrapper { - - private static Logger log; - - private static EconomyWrapper instance; - private static Economy economy; - - public EconomyWrapper(Logger logger) { - instance = this; - log = logger; - } - - public static EconomyWrapper getInstance() { - return instance; - } - - public Economy getEconomy() { - return economy; - } - - public void setupEconomy() { - if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { - log.info("[ServerTap] No Vault plugin detected"); - return; - } - RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); - if (rsp == null) { - log.info("[ServerTap] No Economy providers detected"); - return; - } - - log.info(String.format("[ServerTap] Hooked economy provider: %s", rsp.getProvider().getName())); - economy = rsp.getProvider(); - } -} diff --git a/src/main/java/io/servertap/utils/GsonJsonMapper.java b/src/main/java/io/servertap/utils/GsonJsonMapper.java index d7836703..7e086fec 100644 --- a/src/main/java/io/servertap/utils/GsonJsonMapper.java +++ b/src/main/java/io/servertap/utils/GsonJsonMapper.java @@ -10,4 +10,4 @@ public class GsonJsonMapper implements io.javalin.json.JsonMapper { public String toJsonString(@NotNull Object obj, @NotNull Type type) { return GsonSingleton.getInstance().toJson(obj); } -} +} \ No newline at end of file diff --git a/src/main/java/io/servertap/utils/Lag.java b/src/main/java/io/servertap/utils/LagDetector.java similarity index 73% rename from src/main/java/io/servertap/utils/Lag.java rename to src/main/java/io/servertap/utils/LagDetector.java index 8e9475ed..d6a0f9b2 100644 --- a/src/main/java/io/servertap/utils/Lag.java +++ b/src/main/java/io/servertap/utils/LagDetector.java @@ -1,11 +1,11 @@ package io.servertap.utils; -public class Lag implements Runnable { +public class LagDetector implements Runnable { - private static final long[] TICKS = new long[600]; - private static int TICK_COUNT = 0; + private final long[] TICKS = new long[600]; + private int TICK_COUNT = 0; - public static String getTPSString() { + public String getTPSString() { try { double tpsDouble = getTPS(); if (tpsDouble > 19.5) tpsDouble = 20; @@ -16,11 +16,11 @@ public static String getTPSString() { } } - public static double getTPS() { + public double getTPS() { return getTPS(100); } - public static double getTPS(int ticks) { + public double getTPS(int ticks) { if (TICK_COUNT < ticks) return 20; int target = (TICK_COUNT - 1 - ticks) % TICKS.length; long elapsed = System.currentTimeMillis() - TICKS[target]; diff --git a/src/main/java/io/servertap/utils/ServerExecCommandSender.java b/src/main/java/io/servertap/utils/ServerExecCommandSender.java index afda7e70..6aef4de5 100644 --- a/src/main/java/io/servertap/utils/ServerExecCommandSender.java +++ b/src/main/java/io/servertap/utils/ServerExecCommandSender.java @@ -16,8 +16,9 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; import java.util.Set; -import java.util.StringJoiner; import java.util.UUID; import java.util.concurrent.*; @@ -26,19 +27,25 @@ public class ServerExecCommandSender implements RemoteConsoleCommandSender { private static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(1); private static final ConsoleCommandSender CONSOLE_COMMAND_SENDER = Bukkit.getConsoleSender(); - private final StringJoiner messageBuffer = new StringJoiner("\n"); + private final ServerTapMain main; + private final List messageBuffer = new ArrayList<>(); - public CompletableFuture executeCommand(String command, long messagingTime, TimeUnit messagingUnit) { + public ServerExecCommandSender(ServerTapMain main) { + this.main = main; + } + + public CompletableFuture> executeCommand(String command, long messagingTime, TimeUnit messagingUnit) { Future commandFuture = Bukkit.getScheduler().callSyncMethod( - ServerTapMain.instance, + main, () -> Bukkit.dispatchCommand(this, command) ); - CompletableFuture future = new CompletableFuture<>(); + CompletableFuture> future = new CompletableFuture<>(); + EXECUTOR.schedule(() -> { try { commandFuture.get(5, TimeUnit.SECONDS); - future.complete(messageBuffer.toString()); + future.complete(messageBuffer); } catch (InterruptedException | ExecutionException | TimeoutException e) { future.completeExceptionally(new RuntimeException(Constants.COMMAND_GENERIC_ERROR, e)); } @@ -48,8 +55,7 @@ public CompletableFuture executeCommand(String command, long messagingTi @Override public void sendMessage(@NotNull String message) { - //TODO should probably cover other control characters besides just section signs - messageBuffer.add(ChatColor.stripColor(message)); + messageBuffer.add(main.getConfig().getBoolean("normalizeMessages") ? ChatColor.stripColor(message) : message); } @Override diff --git a/src/main/java/io/servertap/utils/pluginwrappers/EconomyWrapper.java b/src/main/java/io/servertap/utils/pluginwrappers/EconomyWrapper.java new file mode 100644 index 00000000..79aad258 --- /dev/null +++ b/src/main/java/io/servertap/utils/pluginwrappers/EconomyWrapper.java @@ -0,0 +1,60 @@ +package io.servertap.utils.pluginwrappers; + +import io.servertap.ServerTapMain; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.economy.EconomyResponse; +import org.bukkit.OfflinePlayer; +import org.bukkit.plugin.RegisteredServiceProvider; + +import java.util.logging.Logger; + +/** + * We can't simply reference Economy in ServerTapMain due to OpenApi annotation doing reflection, which can fail at + * runtime due to the `scope` of the Vault API being `provided`.
+ *
+ * More details here: https://github.com/phybros/servertap/issues/175 + */ +public class EconomyWrapper { + + private final ServerTapMain main; + private final Logger log; + private Economy economy; + + public EconomyWrapper(ServerTapMain main, Logger logger) { + this.main = main; + this.log = logger; + + setupEconomy(); + } + + public boolean isAvailable() { + return economy != null; + } + + public double getPlayerBalance(OfflinePlayer player) { + return economy.getBalance(player); + } + + public EconomyResponse depositPlayer(OfflinePlayer player, double amount) { + return economy.depositPlayer(player, amount); + } + + public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount) { + return economy.withdrawPlayer(player, amount); + } + + private void setupEconomy() { + if (main.getServer().getPluginManager().getPlugin("Vault") == null) { + log.info("[ServerTap] No Vault plugin detected"); + return; + } + RegisteredServiceProvider rsp = main.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + log.info("[ServerTap] No Economy providers detected"); + return; + } + + log.info(String.format("[ServerTap] Hooked economy provider: %s", rsp.getProvider().getName())); + economy = rsp.getProvider(); + } +} diff --git a/src/main/java/io/servertap/utils/pluginwrappers/ExternalPluginWrapperRepo.java b/src/main/java/io/servertap/utils/pluginwrappers/ExternalPluginWrapperRepo.java new file mode 100644 index 00000000..2d2813a8 --- /dev/null +++ b/src/main/java/io/servertap/utils/pluginwrappers/ExternalPluginWrapperRepo.java @@ -0,0 +1,18 @@ +package io.servertap.utils.pluginwrappers; + +import io.servertap.ServerTapMain; + +import java.util.logging.Logger; + +public class ExternalPluginWrapperRepo { + + private final EconomyWrapper economyWrapper; + + public ExternalPluginWrapperRepo(ServerTapMain main, Logger logger) { + this.economyWrapper = new EconomyWrapper(main, logger); + } + + public EconomyWrapper getEconomyWrapper() { + return this.economyWrapper; + } +} diff --git a/src/main/java/io/servertap/webhooks/Webhook.java b/src/main/java/io/servertap/webhooks/Webhook.java index 59b59056..10e544b8 100644 --- a/src/main/java/io/servertap/webhooks/Webhook.java +++ b/src/main/java/io/servertap/webhooks/Webhook.java @@ -1,6 +1,6 @@ package io.servertap.webhooks; -import io.servertap.api.v1.models.events.WebhookEvent; +import io.servertap.webhooks.models.events.WebhookEvent; import org.bukkit.configuration.file.FileConfiguration; import java.net.MalformedURLException; diff --git a/src/main/java/io/servertap/webhooks/WebhookEventListener.java b/src/main/java/io/servertap/webhooks/WebhookEventListener.java index ead49422..f15a4466 100644 --- a/src/main/java/io/servertap/webhooks/WebhookEventListener.java +++ b/src/main/java/io/servertap/webhooks/WebhookEventListener.java @@ -4,9 +4,10 @@ import io.servertap.ServerTapMain; import io.servertap.api.v1.models.ItemStack; import io.servertap.api.v1.models.Player; -import io.servertap.api.v1.models.events.*; -import io.servertap.utils.EconomyWrapper; +import io.servertap.utils.pluginwrappers.EconomyWrapper; import io.servertap.utils.GsonSingleton; +import io.servertap.utils.pluginwrappers.ExternalPluginWrapperRepo; +import io.servertap.webhooks.models.events.*; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; @@ -34,11 +35,13 @@ public class WebhookEventListener implements Listener { private final Logger log; private final ServerTapMain main; + private final EconomyWrapper economyWrapper; private List webhooks; - public WebhookEventListener(ServerTapMain main, FileConfiguration bukkitConfig, Logger logger) { + public WebhookEventListener(ServerTapMain main, FileConfiguration bukkitConfig, Logger logger, EconomyWrapper economyWrapper) { this.main = main; this.log = logger; + this.economyWrapper = economyWrapper; loadWebhooksFromConfig(bukkitConfig); } @@ -173,8 +176,8 @@ private static void sendHttpRequest(WebhookEvent eventModel, Webhook webhook) { private Player fromBukkitPlayer(org.bukkit.entity.Player player) { Player p = new Player(); - if (EconomyWrapper.getInstance().getEconomy() != null) { - p.setBalance(EconomyWrapper.getInstance().getEconomy().getBalance(player)); + if (economyWrapper.isAvailable()) { + p.setBalance(economyWrapper.getPlayerBalance(player)); } p.setUuid(player.getUniqueId().toString()); diff --git a/src/main/java/io/servertap/api/v1/models/events/PlayerChatWebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/PlayerChatWebhookEvent.java similarity index 94% rename from src/main/java/io/servertap/api/v1/models/events/PlayerChatWebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/PlayerChatWebhookEvent.java index cbaa1378..3118f1c3 100644 --- a/src/main/java/io/servertap/api/v1/models/events/PlayerChatWebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/PlayerChatWebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose; import io.servertap.api.v1.models.Player; diff --git a/src/main/java/io/servertap/api/v1/models/events/PlayerDeathWebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/PlayerDeathWebhookEvent.java similarity index 95% rename from src/main/java/io/servertap/api/v1/models/events/PlayerDeathWebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/PlayerDeathWebhookEvent.java index 67ee319f..3ef0d5a9 100644 --- a/src/main/java/io/servertap/api/v1/models/events/PlayerDeathWebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/PlayerDeathWebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose; import io.servertap.api.v1.models.ItemStack; diff --git a/src/main/java/io/servertap/api/v1/models/events/PlayerJoinWebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/PlayerJoinWebhookEvent.java similarity index 93% rename from src/main/java/io/servertap/api/v1/models/events/PlayerJoinWebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/PlayerJoinWebhookEvent.java index 7664c64c..9d7f37e6 100644 --- a/src/main/java/io/servertap/api/v1/models/events/PlayerJoinWebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/PlayerJoinWebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose; import io.servertap.api.v1.models.Player; diff --git a/src/main/java/io/servertap/api/v1/models/events/PlayerKickWebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/PlayerKickWebhookEvent.java similarity index 92% rename from src/main/java/io/servertap/api/v1/models/events/PlayerKickWebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/PlayerKickWebhookEvent.java index 0b364e34..686fec96 100644 --- a/src/main/java/io/servertap/api/v1/models/events/PlayerKickWebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/PlayerKickWebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose; import io.servertap.api.v1.models.Player; diff --git a/src/main/java/io/servertap/api/v1/models/events/PlayerQuitWebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/PlayerQuitWebhookEvent.java similarity index 93% rename from src/main/java/io/servertap/api/v1/models/events/PlayerQuitWebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/PlayerQuitWebhookEvent.java index 389ce03c..da6e8c50 100644 --- a/src/main/java/io/servertap/api/v1/models/events/PlayerQuitWebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/PlayerQuitWebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose; import io.servertap.api.v1.models.Player; diff --git a/src/main/java/io/servertap/api/v1/models/events/WebhookEvent.java b/src/main/java/io/servertap/webhooks/models/events/WebhookEvent.java similarity index 82% rename from src/main/java/io/servertap/api/v1/models/events/WebhookEvent.java rename to src/main/java/io/servertap/webhooks/models/events/WebhookEvent.java index 28890311..f7e98494 100644 --- a/src/main/java/io/servertap/api/v1/models/events/WebhookEvent.java +++ b/src/main/java/io/servertap/webhooks/models/events/WebhookEvent.java @@ -1,4 +1,4 @@ -package io.servertap.api.v1.models.events; +package io.servertap.webhooks.models.events; import com.google.gson.annotations.Expose;