From aa51d85388e4d26363a9511fd87c999b48fa9470 Mon Sep 17 00:00:00 2001 From: Jonas_Jones <91549607+JonasunderscoreJones@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:40:44 +0100 Subject: [PATCH] first version of api-v2 player data still incomplete and only available as a single request. --- .../jonasjones/mcwebserver/McWebserver.java | 14 +- .../mcwebserver/web/HttpServer.java | 72 ++- .../web/api/{v1 => }/ApiRequests.java | 20 +- .../mcwebserver/web/api/ApiRequestsUtil.java | 508 ++++++++++++++++++ .../mcwebserver/web/api/ErrorHandler.java | 47 ++ .../web/api/json/ApiPlayerInfo.java | 13 + .../web/api/json/ApiPlayerInfoFishhook.java | 14 + .../web/api/json/ApiPlayerInfoInventory.java | 18 + .../api/json/ApiPlayerInfoInventoryArmor.java | 18 + .../ApiPlayerInfoInventoryEnderChest.java | 14 + .../json/ApiPlayerInfoInventoryItemStack.java | 18 + .../api/json/ApiPlayerInfoInventoryMain.java | 14 + .../api/json/ApiPlayerInfoInventoryMisc.java | 15 + .../web/api/json/ApiPlayerInfoMovement.java | 24 + .../json/ApiPlayerInfoMovementCollision.java | 20 + .../json/ApiPlayerInfoMovementDistance.java | 16 + .../api/json/ApiPlayerInfoMovementEnv.java | 26 + .../api/json/ApiPlayerInfoMovementSpeed.java | 20 + .../json/ApiPlayerInfoMovementStepHeight.java | 12 + .../web/api/json/ApiPlayerInfoNames.java | 20 + .../web/api/json/ApiPlayerInfoPose.java | 32 ++ .../json/ApiPlayerInfoPoseBoundingBox.java | 29 + .../json/ApiPlayerInfoPoseChunkPosition.java | 30 ++ .../json/ApiPlayerInfoPoseLimbAnimation.java | 16 + .../api/json/ApiPlayerInfoPoseSpawnPose.java | 16 + ...piPlayerInfoPoseVisibilityBoundingBox.java | 30 ++ .../web/api/json/ApiPlayerInfoProfile.java | 14 + .../json/ApiPlayerInfoVehicleProperties.java | 24 + ...VehiclePropertiesControllingPassanger.java | 14 + ...foVehiclePropertiesControllingVehicle.java | 14 + ...layerInfoVehiclePropertiesRootVehicle.java | 14 + ...ApiPlayerInfoVehiclePropertiesVehicle.java | 14 + .../web/api/{v1 => }/json/ApiServerInfo.java | 2 +- .../api/{v1 => }/json/ApiServerMetadata.java | 2 +- .../json/ApiServerMetadataPlayer.java | 2 +- .../json/ApiServerMetadataPlayerProperty.java | 4 + .../json/ApiServerMetadataPlayers.java | 2 +- .../mcwebserver/web/api/json/Error.java | 10 + .../web/api/json/ThreeDoubleVector.java | 16 + .../web/api/json/ThreeFloatVector.java | 16 + .../web/api/json/ThreeIntegerVector.java | 13 + .../web/api/json/TwoFloatVector.java | 11 + .../web/api/v1/ApiRequestsUtil.java | 121 ----- .../v1/{ApiHandler.java => ApiV1Handler.java} | 26 +- .../json/ApiServerMetadataPlayerProperty.java | 4 - .../mcwebserver/web/api/v2/ApiV2Handler.java | 99 ++++ .../web/api/v2/tokenmgr/TokenManager.java | 18 +- 47 files changed, 1334 insertions(+), 182 deletions(-) rename src/main/java/me/jonasjones/mcwebserver/web/api/{v1 => }/ApiRequests.java (60%) create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequestsUtil.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/ErrorHandler.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfo.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoFishhook.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventory.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryArmor.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryEnderChest.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryItemStack.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMain.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMisc.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovement.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementCollision.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementDistance.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementEnv.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementSpeed.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementStepHeight.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoNames.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPose.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseBoundingBox.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseChunkPosition.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseLimbAnimation.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseSpawnPose.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseVisibilityBoundingBox.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoProfile.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehicleProperties.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingPassanger.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingVehicle.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesRootVehicle.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesVehicle.java rename src/main/java/me/jonasjones/mcwebserver/web/api/{v1 => }/json/ApiServerInfo.java (88%) rename src/main/java/me/jonasjones/mcwebserver/web/api/{v1 => }/json/ApiServerMetadata.java (84%) rename src/main/java/me/jonasjones/mcwebserver/web/api/{v1 => }/json/ApiServerMetadataPlayer.java (74%) create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayerProperty.java rename src/main/java/me/jonasjones/mcwebserver/web/api/{v1 => }/json/ApiServerMetadataPlayers.java (79%) create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/Error.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeDoubleVector.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeFloatVector.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeIntegerVector.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/json/TwoFloatVector.java delete mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequestsUtil.java rename src/main/java/me/jonasjones/mcwebserver/web/api/v1/{ApiHandler.java => ApiV1Handler.java} (77%) delete mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayerProperty.java create mode 100644 src/main/java/me/jonasjones/mcwebserver/web/api/v2/ApiV2Handler.java diff --git a/src/main/java/me/jonasjones/mcwebserver/McWebserver.java b/src/main/java/me/jonasjones/mcwebserver/McWebserver.java index 1058512..4b48832 100644 --- a/src/main/java/me/jonasjones/mcwebserver/McWebserver.java +++ b/src/main/java/me/jonasjones/mcwebserver/McWebserver.java @@ -1,13 +1,13 @@ package me.jonasjones.mcwebserver; +import com.google.gson.Gson; import me.jonasjones.mcwebserver.config.ModConfigs; -import me.jonasjones.mcwebserver.web.api.v1.ApiHandler; +import me.jonasjones.mcwebserver.web.api.v1.ApiV1Handler; import me.jonasjones.mcwebserver.web.ServerHandler; +import me.jonasjones.mcwebserver.web.api.v2.ApiV2Handler; import me.jonasjones.mcwebserver.web.api.v2.tokenmgr.Token; -import me.jonasjones.mcwebserver.web.api.v2.tokenmgr.TokenManager; import net.fabricmc.api.ModInitializer; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +26,7 @@ public class McWebserver implements ModInitializer { public static final Logger VERBOSELOGGER = LoggerFactory.getLogger(MOD_ID + " - VERBOSE LOGGER"); public static Boolean ISFIRSTSTART = false; public static MinecraftServer MC_SERVER; + public static final Gson gson = new Gson(); @Override public void onInitialize() { @@ -41,16 +42,19 @@ public class McWebserver implements ModInitializer { } if (SERVER_API_ENABLED) { - if (API_INGAME_COMMAND_ENABLED) { + if (API_INGAME_COMMAND_ENABLED && ADV_API_ENABLED) { ArrayList< Token > tokens = readOrCreateTokenFile(); LOGGER.info("Loaded " + tokens.size() + " tokens from file."); // register commands registerCommands(); + + // start advanced api handler + ApiV2Handler.startAdvHandler(); } //start collecting api info - ApiHandler.startHandler(); + ApiV1Handler.startHandler(); LOGGER.info("Server API enabled!"); /*if (ADV_API_ENABLED) { //start collecting advanced api info diff --git a/src/main/java/me/jonasjones/mcwebserver/web/HttpServer.java b/src/main/java/me/jonasjones/mcwebserver/web/HttpServer.java index 3a6e38a..3d83548 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/HttpServer.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/HttpServer.java @@ -3,11 +3,12 @@ package me.jonasjones.mcwebserver.web; import me.jonasjones.mcwebserver.config.ModConfigs; import me.jonasjones.mcwebserver.McWebserver; import me.jonasjones.mcwebserver.util.VerboseLogger; -import me.jonasjones.mcwebserver.web.api.v1.ApiHandler; -import me.jonasjones.mcwebserver.web.api.v1.ApiRequests; -import me.jonasjones.mcwebserver.web.api.v1.ApiRequestsUtil; +import me.jonasjones.mcwebserver.web.api.ErrorHandler; +import me.jonasjones.mcwebserver.web.api.v1.ApiV1Handler; +import me.jonasjones.mcwebserver.web.api.ApiRequests; +import me.jonasjones.mcwebserver.web.api.ApiRequestsUtil; +import me.jonasjones.mcwebserver.web.api.v2.ApiV2Handler; -import java.awt.desktop.SystemEventListener; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; @@ -25,7 +26,8 @@ import java.time.Instant; import java.util.StringTokenizer; import static me.jonasjones.mcwebserver.web.ServerHandler.mcserveractive; -import static me.jonasjones.mcwebserver.web.api.v1.ApiHandler.isApiRequest; +import static me.jonasjones.mcwebserver.web.api.v1.ApiV1Handler.isApiV1Request; +import static me.jonasjones.mcwebserver.web.api.v2.ApiV2Handler.isApiV2Request; public class HttpServer implements Runnable { static Path WEB_ROOT; @@ -51,6 +53,7 @@ public class HttpServer implements Runnable { private final Socket connect; private final MimeTypeIdentifier mimetypeidentifier = new MimeTypeIdentifier(); private Boolean isApiv1Request = false; + private Boolean isApiv2Request = false; static { try { @@ -97,7 +100,7 @@ public class HttpServer implements Runnable { PrintWriter out = null; BufferedOutputStream dataOut = null; String fileRequested = null; - String apiToken; + String apiToken = null; try { // we read characters from the client via input stream on the socket @@ -113,15 +116,13 @@ public class HttpServer implements Runnable { StringTokenizer parse = new StringTokenizer(input); String method = parse.nextToken().toUpperCase(); // we get the HTTP method of the client // we get file requested - fileRequested = parse.nextToken().toLowerCase(); + fileRequested = parse.nextToken(); String header; while ((header = in.readLine()) != null && !header.isEmpty()) { // Check if the header contains your API token if (header.startsWith("Authorization: Bearer ")) { apiToken = header.substring("Authorization: Bearer ".length()); - System.out.println("API Token: " + apiToken); - // Now you have the API token, you can use it for authentication. } } @@ -147,7 +148,7 @@ public class HttpServer implements Runnable { // file dataOut.write(fileData, 0, fileData.length); dataOut.flush(); - } else if (isApiRequest(fileRequested)) { + } else if (isApiV1Request(fileRequested)) { isApiv1Request = true; // Check if server API is enabled if (ModConfigs.SERVER_API_ENABLED) { @@ -171,10 +172,10 @@ public class HttpServer implements Runnable { String jsonString = ""; try { // Get JSON data from ApiHandler - jsonString = ApiHandler.handle(fileRequested); + jsonString = ApiV1Handler.handle(fileRequested); } catch (Exception e) { VerboseLogger.error("Error getting JSON data from ApiHandler: " + e.getMessage()); - jsonString = ApiRequests.internalServerError(); + jsonString = ErrorHandler.internalServerErrorString(); } @@ -190,7 +191,7 @@ public class HttpServer implements Runnable { } } else { // Server API is disabled - String jsonString = ApiRequests.forbiddenRequest(); + String jsonString = ErrorHandler.forbiddenRequestString(); byte[] jsonBytes = jsonString.getBytes(StandardCharsets.UTF_8); int contentLength = jsonBytes.length; dataOut.write("HTTP/1.1 403 Forbidden\r\n".getBytes(StandardCharsets.UTF_8)); @@ -201,6 +202,32 @@ public class HttpServer implements Runnable { dataOut.write(jsonBytes, 0, contentLength); dataOut.flush(); } + } else if (isApiV2Request(fileRequested)) { + isApiv1Request = false; + // Check if server API is enabled + if (ModConfigs.SERVER_API_ENABLED) { + dataOut.write("HTTP/1.1 200 OK\r\n".getBytes(StandardCharsets.UTF_8)); + dataOut.write("Date: %s\r\n".formatted(Instant.now()).getBytes(StandardCharsets.UTF_8)); + dataOut.write("Content-Type: application/json\r\n".getBytes(StandardCharsets.UTF_8)); + String jsonString = ""; + try { + // Get JSON data from ApiHandler + jsonString = ApiV2Handler.handle(fileRequested, apiToken); + } catch (Exception e) { + VerboseLogger.error("Error getting JSON data from ApiHandler: " + e.getMessage()); + jsonString = ErrorHandler.internalServerErrorString(); + } + + byte[] jsonBytes = jsonString.getBytes(StandardCharsets.UTF_8); + int contentLength = jsonBytes.length; + + dataOut.write(("Content-Length: " + contentLength + "\r\n").getBytes(StandardCharsets.UTF_8)); + dataOut.write("\r\n".getBytes(StandardCharsets.UTF_8)); // Blank line before content + + // Send JSON data + dataOut.write(jsonBytes, 0, contentLength); + dataOut.flush(); + } } else { isApiv1Request = false; // GET or HEAD method @@ -247,9 +274,26 @@ public class HttpServer implements Runnable { try { assert out != null; assert dataOut != null; + VerboseLogger.error("Error with file not found exception : " + e.getMessage()); fileNotFound(out, dataOut, fileRequested); } catch (IOException ioe) { - VerboseLogger.error("Error with file not found exception : " + ioe.getMessage()); + // send json 404 error + // replace mime type header with application/json + try { + dataOut = new BufferedOutputStream(connect.getOutputStream()); + dataOut.write("HTTP/1.1 404 Not Found\r\n".getBytes(StandardCharsets.UTF_8)); + dataOut.write("Date: %s\r\n".formatted(Instant.now()).getBytes(StandardCharsets.UTF_8)); + dataOut.write("Content-Type: application/json\r\n".getBytes(StandardCharsets.UTF_8)); + String jsonString = ErrorHandler.internalServerErrorString(); + byte[] jsonBytes = jsonString.getBytes(StandardCharsets.UTF_8); + int contentLength = jsonBytes.length; + dataOut.write(("Content-Length: " + contentLength + "\r\n").getBytes(StandardCharsets.UTF_8)); + dataOut.write("\r\n".getBytes(StandardCharsets.UTF_8)); // Blank line before content + dataOut.write(jsonBytes, 0, contentLength); + dataOut.flush(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } } } catch (IOException ioe) { diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequests.java b/src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequests.java similarity index 60% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequests.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequests.java index 885a721..d5e6bca 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequests.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequests.java @@ -1,6 +1,8 @@ -package me.jonasjones.mcwebserver.web.api.v1; +package me.jonasjones.mcwebserver.web.api; import com.google.gson.Gson; +import com.google.gson.JsonObject; +import me.jonasjones.mcwebserver.McWebserver; public class ApiRequests { private static final Gson gson = new Gson(); @@ -13,6 +15,10 @@ public class ApiRequests { return gson.toJsonTree(ApiRequestsUtil.convertPlayerList(ApiRequestsUtil.getSERVER_METADATA().players().get().sample())).getAsJsonArray().toString(); } + public static String playerInfoRequest(String playerName) { + return gson.toJson(ApiRequestsUtil.getPlayerInfo(playerName)); + } + public static String serverMetadataRequest() { return gson.toJson(ApiRequestsUtil.serverMetadata()); } @@ -20,16 +26,4 @@ public class ApiRequests { public static String serverGetAllRequest() { return gson.toJson(ApiRequestsUtil.getAll()); } - - public static String badRequest() { - return "{\"error\":{\"status\":400,\"message\":\"Bad Request\"}}"; - } - - public static String internalServerError() { - return "{\"error\":{\"status\":500,\"message\":\"Internal Server Error\"}}"; - } - - public static String forbiddenRequest() { - return "{\"error\":{\"status\":403,\"message\":\"Forbidden\"}}"; - } } diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequestsUtil.java b/src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequestsUtil.java new file mode 100644 index 0000000..5cbafc5 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/ApiRequestsUtil.java @@ -0,0 +1,508 @@ +package me.jonasjones.mcwebserver.web.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mojang.authlib.GameProfile; +import lombok.Getter; +import lombok.Setter; +import me.jonasjones.mcwebserver.McWebserver; +import me.jonasjones.mcwebserver.web.api.json.*; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.impl.lib.sat4j.core.Vec; +import net.minecraft.advancement.AdvancementEntry; +import net.minecraft.entity.boss.CommandBossBar; +import net.minecraft.resource.ResourcePackProfile; +import net.minecraft.server.ServerMetadata; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.GameMode; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static me.jonasjones.mcwebserver.McWebserver.gson; +import static me.jonasjones.mcwebserver.config.ModConfigs.WEB_PORT; +import static me.jonasjones.mcwebserver.web.api.ErrorHandler.internalServerError; + +public class ApiRequestsUtil { + @Getter @Setter + private static String MOTD; + @Getter @Setter + private static String SERVER_IP; + @Getter @Setter + private static int SERVER_PORT; + @Getter @Setter + private static String SERVER_NAME; + @Getter @Setter + private static String SERVER_VERSION; + @Getter @Setter + private static int CURRENT_PLAYER_COUNT; + @Getter @Setter + private static GameMode DEFAULT_GAME_MODE; + @Getter + private static final String LOADER_VERSION = FabricLoader.getInstance().getModContainer("fabricloader").get().getMetadata().getVersion().getFriendlyString(); + @Getter @Setter + private static int MAX_PLAYER_COUNT; + @Getter @Setter + private static ServerMetadata SERVER_METADATA; + @Getter @Setter + private static int TICKS; + //@Getter @Setter + //private static float TICK_TIME; + @Getter @Setter + private static long TIME_REFERENCE; + @Getter @Setter + private static List SERVER_PLAYER_ENTITY_LIST = new ArrayList<>(); + @Getter @Setter + private static Collection SERVER_RESOURCE_PACK_PROFILE_COLLECTION = new ArrayList<>(); + @Getter @Setter + private static Collection SERVER_ADVANCEMENT_COLLECTION = new ArrayList<>(); + @Getter @Setter + private static Collection SERVER_BOSSBAR_COLLECTION = new ArrayList<>(); + private static final ApiServerInfo apiServerInfo = new ApiServerInfo(); + private static final ApiServerMetadata apiServerMetadata = new ApiServerMetadata(); + private static final ApiServerMetadataPlayers apiServerMetadataPlayers = new ApiServerMetadataPlayers(); + + + + public static JsonObject serverMetadata() { + apiServerMetadataPlayers.setMAX(ApiRequestsUtil.getSERVER_METADATA().players().get().max()); + apiServerMetadataPlayers.setONLINE(ApiRequestsUtil.getSERVER_METADATA().players().get().online()); + apiServerMetadataPlayers.setSAMPLE(convertPlayerList(ApiRequestsUtil.getSERVER_METADATA().players().get().sample())); + + apiServerMetadata.setDESCRIPTION(ApiRequestsUtil.getSERVER_METADATA().description().getString()); + apiServerMetadata.setPLAYERS(JsonParser.parseString(gson.toJson(apiServerMetadataPlayers)).getAsJsonObject()); + apiServerMetadata.setVERSION((JsonObject) JsonParser.parseString("{\"version\":\"" + ApiRequestsUtil.getSERVER_METADATA().version().get().gameVersion() + "\",\"protocol\":" + ApiRequestsUtil.getSERVER_METADATA().version().get().protocolVersion() + "}")); + if (ApiRequestsUtil.getSERVER_METADATA().favicon().isPresent()) { + if (!ApiRequestsUtil.getSERVER_IP().isEmpty()) { + apiServerMetadata.setFAVICON("http://" + ApiRequestsUtil.getSERVER_IP() + ":" + WEB_PORT + "/api/v1/servericon"); + } else { + apiServerMetadata.setFAVICON("/api/v1/servericon"); + } + } else { + apiServerMetadata.setFAVICON(""); // if favicon doesn't exist + } + + apiServerMetadata.setSECURE_CHAT_EINFORCED(ApiRequestsUtil.getSERVER_METADATA().secureChatEnforced()); + + return JsonParser.parseString(gson.toJson(apiServerMetadata)).getAsJsonObject(); + } + + public static JsonObject nbtStringToJson(String nbt) { + if (nbt == null) { + return null; + } + return JsonParser.parseString(nbt).getAsJsonObject(); + } + + public static ArrayList convertPlayerList(List list) { + ArrayList players = new ArrayList<>(); + for (GameProfile profile : list) { + ApiServerMetadataPlayer player = new ApiServerMetadataPlayer(); + player.setID(profile.getId().toString()); + player.setNAME(profile.getName()); + players.add(player); + } + return players; + } + + public static JsonObject getAll() { + apiServerInfo.setSERVER_IP(ApiRequestsUtil.getSERVER_IP()); + apiServerInfo.setSERVER_PORT(ApiRequestsUtil.getSERVER_PORT()); + apiServerInfo.setSERVER_NAME(ApiRequestsUtil.getSERVER_NAME()); + apiServerInfo.setDEFAULT_GAME_MODE(ApiRequestsUtil.getDEFAULT_GAME_MODE().toString()); + apiServerInfo.setLOADER_VERSION(LOADER_VERSION); + apiServerInfo.setMETADATA(serverMetadata()); + apiServerInfo.setTICKS(ApiRequestsUtil.getTICKS()); + apiServerInfo.setTIME_REFERENCE(ApiRequestsUtil.getTIME_REFERENCE()); + + return gson.toJsonTree(apiServerInfo).getAsJsonObject(); + } + + public static byte[] getServerIcon() { + return ApiRequestsUtil.getSERVER_METADATA().favicon().get().iconBytes(); + } + + public static JsonObject getPlayerInfo(String playerName) { + for (ServerPlayerEntity player : ApiRequestsUtil.getSERVER_PLAYER_ENTITY_LIST()) { + if (player.getName().getString().equals(playerName)) { + try { + String sleepDirection = (player.getSleepingDirection() != null) ? player.getSleepingDirection().asString() : null; + Vec sleepPosition = new Vec<>(); + try { + sleepPosition.set(0, player.getSleepingPosition().orElseThrow().getX()); + sleepPosition.set(1, player.getSleepingPosition().orElseThrow().getY()); + sleepPosition.set(2, player.getSleepingPosition().orElseThrow().getZ()); + } catch (Exception ignored) { + } + Vec spawnPointPosition = new Vec<>(); + try { + sleepPosition.set(0, player.getSleepingPosition().orElseThrow().getX()); + sleepPosition.set(1, player.getSleepingPosition().orElseThrow().getY()); + sleepPosition.set(2, player.getSleepingPosition().orElseThrow().getZ()); + } catch (Exception ignored) {} + Vec vehicle = new Vec<>(); + try { + vehicle.set(0, Objects.requireNonNull(player.getVehicle()).getName().getString()); + vehicle.set(1, player.getVehicle().getUuidAsString()); + } catch (Exception ignored) {} + Vec controllingVehicle = new Vec<>(); + try { + controllingVehicle.set(0, Objects.requireNonNull(player.getControllingVehicle()).getName().getString()); + controllingVehicle.set(1, player.getControllingVehicle().getUuidAsString()); + } catch (Exception ignored) {} + Vec controllingPassenger = new Vec<>(); + try { + controllingPassenger.set(0, Objects.requireNonNull(player.getControllingPassenger()).getName().getString()); + controllingPassenger.set(1, player.getControllingPassenger().getUuidAsString()); + } catch (Exception ignored) {} + Vec fishHook = new Vec<>(); + try { + fishHook.set(0, Objects.requireNonNull(player.fishHook).getName().getString()); + fishHook.set(1, player.fishHook.getUuidAsString()); + } catch (Exception ignored) {} + ArrayList mainInventory = new ArrayList<>(); + for (int i = 0; i < player.getInventory().main.size(); i++) { + String nbt; + try { + nbt = Objects.requireNonNull(player.getInventory().main.get(i).getNbt()).toString(); + } catch (Exception ignored) { + nbt = null; + } + ApiPlayerInfoInventoryItemStack itemStack = new ApiPlayerInfoInventoryItemStack( + player.getInventory().main.get(i).getTranslationKey(), + player.getInventory().main.get(i).getCount(), + nbtStringToJson(nbt) + ); + mainInventory.add(itemStack); + } + ArrayList enderChestInventory = new ArrayList<>(); + for (int i = 0; i < player.getEnderChestInventory().size(); i++) { + String nbt; + try { + nbt = Objects.requireNonNull(player.getEnderChestInventory().getStack(i).getNbt()).toString(); + } catch (Exception ignored) { + nbt = null; + } + ApiPlayerInfoInventoryItemStack itemStack = new ApiPlayerInfoInventoryItemStack( + player.getEnderChestInventory().getStack(i).getTranslationKey(), + player.getEnderChestInventory().getStack(i).getCount(), + nbtStringToJson(nbt) + ); + enderChestInventory.add(itemStack); + } + String armornbt0; + try { + armornbt0 = Objects.requireNonNull(player.getInventory().armor.get(0).getNbt()).toString(); + } catch (Exception ignored) { + armornbt0 = null; + } + String armornbt1; + try { + armornbt1 = Objects.requireNonNull(player.getInventory().armor.get(1).getNbt()).toString(); + } catch (Exception ignored) { + armornbt1 = null; + } + String armornbt2; + try { + armornbt2 = Objects.requireNonNull(player.getInventory().armor.get(2).getNbt()).toString(); + } catch (Exception ignored) { + armornbt2 = null; + } + String armornbt3; + try { + armornbt3 = Objects.requireNonNull(player.getInventory().armor.get(3).getNbt()).toString(); + } catch (Exception ignored) { + armornbt3 = null; + } + String offhandnbt; + try { + offhandnbt = Objects.requireNonNull(player.getInventory().offHand.get(0).getNbt()).toString(); + } catch (Exception ignored) { + offhandnbt = null; + } + String pickblocktranslationkey; + try { + pickblocktranslationkey = Objects.requireNonNull(player.getPickBlockStack()).getTranslationKey(); + } catch (Exception ignored) { + pickblocktranslationkey = null; + } + int pickblockcount; + try { + pickblockcount = Objects.requireNonNull(player.getPickBlockStack()).getCount(); + } catch (Exception ignored) { + pickblockcount = 0; + } + String pickblocknbt; + try { + pickblocknbt = Objects.requireNonNull(player.getPickBlockStack()).toString(); + } catch (Exception ignored) { + pickblocknbt = null; + } + ApiPlayerInfoInventoryArmor apiPlayerInfoInventoryArmor = new ApiPlayerInfoInventoryArmor( + new ApiPlayerInfoInventoryItemStack( + player.getInventory().armor.get(0).getTranslationKey(), + player.getInventory().armor.get(0).getCount(), + nbtStringToJson(armornbt0) + ), + new ApiPlayerInfoInventoryItemStack( + player.getInventory().armor.get(1).getTranslationKey(), + player.getInventory().armor.get(1).getCount(), + nbtStringToJson(armornbt1) + ), + new ApiPlayerInfoInventoryItemStack( + player.getInventory().armor.get(2).getTranslationKey(), + player.getInventory().armor.get(2).getCount(), + nbtStringToJson(armornbt2) + ), + new ApiPlayerInfoInventoryItemStack( + player.getInventory().armor.get(3).getTranslationKey(), + player.getInventory().armor.get(3).getCount(), + nbtStringToJson(armornbt3) + ) + ); + ApiPlayerInfo apiPlayerInfo = new ApiPlayerInfo(); + apiPlayerInfo.setProfile( + new ApiPlayerInfoProfile( + new ApiPlayerInfoNames( + player.getName().getString(), + player.getGameProfile().getId().toString(), + (player.getCustomName() != null) ? player.getCustomName().getString() : "", + Objects.requireNonNull(player.getDisplayName()).getString(), + player.getStyledDisplayName().getString() + ), + player.age + ) + ); + ApiPlayerInfoPose pose = new ApiPlayerInfoPose(); + pose.setBodyYaw(player.bodyYaw); + pose.setRandomBodyY(player.getRandomBodyY()); + pose.setHeadYaw(player.headYaw); + pose.setCapePosition( + new ThreeDoubleVector( + player.capeX, + player.capeY, + player.capeZ + ) + ); + pose.setEyePosition( + new ThreeDoubleVector(player.getEyePos().x, + player.getEyePos().y, + player.getEyePos().z + ) + ); + pose.setStandingEyeHeight(player.getStandingEyeHeight()); + pose.setSwimHeight(player.getSwimHeight()); + pose.setHeight(player.getHeight()); + pose.setInvisible(player.isInvisible()); + pose.setPitch(player.getPitch()); + pose.setYaw(player.getYaw()); + pose.setMainArm(player.getMainArm().asString()); + pose.setX(player.getX()); + pose.setY(player.getY()); + pose.setZ(player.getZ()); + pose.setLimbAnimation( + new ApiPlayerInfoPoseLimbAnimation(player.limbAnimator.getPos(), + player.limbAnimator.getSpeed(), + player.limbAnimator.isLimbMoving() + ) + ); + pose.setRotationClient( + new TwoFloatVector( + player.getRotationClient().x, + player.getRotationClient().y + ) + ); + pose.setRotation( + new ThreeDoubleVector( + player.getRotationVector().x, + player.getRotationVector().y, + player.getRotationVector().z + ) + ); + pose.setBoundingBox( + new ApiPlayerInfoPoseBoundingBox( + player.getBoundingBox().minX, + player.getBoundingBox().minY, + player.getBoundingBox().minZ, + player.getBoundingBox().maxX, + player.getBoundingBox().maxY, + player.getBoundingBox().maxZ, + player.getBoundingBox().getAverageSideLength(), + new ThreeDoubleVector( + player.getBoundingBox().getCenter().x, + player.getBoundingBox().getCenter().y, + player.getBoundingBox().getCenter().z + ), + new ThreeDoubleVector( + player.getBoundingBox().getLengthX(), + player.getBoundingBox().getLengthY(), + player.getBoundingBox().getLengthZ()), + player.getBoundingBox().isNaN() + ) + ); + pose.setChunkPosition( + new ApiPlayerInfoPoseChunkPosition( + player.getChunkPos().x, + player.getChunkPos().z, + player.getChunkPos().getStartX(), + player.getChunkPos().getStartZ(), + player.getChunkPos().getCenterX(), + player.getChunkPos().getCenterZ(), + player.getChunkPos().getEndX(), + player.getChunkPos().getEndZ(), + player.getChunkPos().getRegionX(), + player.getChunkPos().getRegionZ() + ) + ); + pose.setScaleFactor(player.getScaleFactor()); + pose.setSleepingDirection(sleepDirection); + pose.setSleepingPosition( + new ThreeIntegerVector( + sleepPosition.get(0), + sleepPosition.get(1), + sleepPosition.get(2) + ) + ); + pose.setVisibilityBoundingBox( + new ApiPlayerInfoPoseVisibilityBoundingBox( + player.getVisibilityBoundingBox().minX, + player.getVisibilityBoundingBox().minY, + player.getVisibilityBoundingBox().minZ, + player.getVisibilityBoundingBox().maxX, + player.getVisibilityBoundingBox().maxY, + player.getVisibilityBoundingBox().maxZ, + player.getVisibilityBoundingBox().getAverageSideLength(), + new ThreeDoubleVector( + player.getVisibilityBoundingBox().getCenter().x, + player.getVisibilityBoundingBox().getCenter().y, + player.getVisibilityBoundingBox().getCenter().z + ), + new ThreeDoubleVector( + player.getVisibilityBoundingBox().getLengthX(), + player.getVisibilityBoundingBox().getLengthY(), + player.getVisibilityBoundingBox().getLengthZ() + ), + player.getVisibilityBoundingBox().isNaN() + ) + ); + pose.setSpawnPose( + new ApiPlayerInfoPoseSpawnPose( + new ThreeIntegerVector( + spawnPointPosition.get(0), + spawnPointPosition.get(1), + spawnPointPosition.get(2) + ), + player.getSpawnAngle(), + player.getSpawnPointDimension().getValue().toUnderscoreSeparatedString() + ) + ); + apiPlayerInfo.setPose(pose); + apiPlayerInfo.setMovement( + new ApiPlayerInfoMovement( + player.getMovementDirection().asString(), + new ThreeDoubleVector( + player.getVelocity().x, + player.getVelocity().y, + player.getVelocity().z + ), + new ApiPlayerInfoMovementDistance( + player.distanceTraveled, + player.fallDistance, + player.strideDistance + ), + new ApiPlayerInfoMovementSpeed( + player.speed, + player.forwardSpeed, + player.horizontalSpeed, + player.sidewaysSpeed, + player.upwardSpeed + ), + new ApiPlayerInfoMovementCollision( + player.horizontalCollision, + player.verticalCollision, + player.groundCollision, + player.collidedSoftly, + player.isCollidable() + ), + new ApiPlayerInfoMovementEnv( + player.isTouchingWater(), + player.isTouchingWaterOrRain(), + player.isSubmergedInWater(), + player.isInLava(), + player.inPowderSnow, + player.isClimbing(), + player.isFallFlying(), + player.isSleeping() + ), + new ApiPlayerInfoMovementStepHeight( + player.getStepHeight() + ) + ) + ); + apiPlayerInfo.setVehicleProperties( + new ApiPlayerInfoVehicleProperties( + player.hasVehicle(), + player.shouldControlVehicles(), + new ApiPlayerInfoVehiclePropertiesVehicle( + vehicle.get(0), + vehicle.get(1) + ), + new ApiPlayerInfoVehiclePropertiesRootVehicle( + player.getRootVehicle().getName().getString(), + player.getRootVehicle().getUuidAsString() + ), + new ApiPlayerInfoVehiclePropertiesControllingVehicle( + controllingVehicle.get(0), + controllingVehicle.get(1) + ), + new ApiPlayerInfoVehiclePropertiesControllingPassanger( + controllingPassenger.get(0), + controllingPassenger.get(1) + ), + player.canSprintAsVehicle() + ) + ); + apiPlayerInfo.setFishhook( + new ApiPlayerInfoFishhook( + fishHook.get(0), + fishHook.get(1) + ) + ); + apiPlayerInfo.setInventory( + new ApiPlayerInfoInventory( + new ApiPlayerInfoInventoryMain( + mainInventory + ), + new ApiPlayerInfoInventoryEnderChest( + enderChestInventory + ), + apiPlayerInfoInventoryArmor, + new ApiPlayerInfoInventoryMisc( + new ApiPlayerInfoInventoryItemStack( + player.getInventory().offHand.get(0).getTranslationKey(), + player.getInventory().offHand.get(0).getCount(), + nbtStringToJson(offhandnbt) + ), + new ApiPlayerInfoInventoryItemStack( + pickblocktranslationkey, + pickblockcount, + nbtStringToJson(pickblocknbt) + ), + player.getInventory().selectedSlot + ) + ) + ); + //return gson.toJsonTree(ErrorHandler.customError(404, "Player Not Found")).getAsJsonObject(); + return gson.toJsonTree(apiPlayerInfo).getAsJsonObject(); + } catch (Exception e) { + McWebserver.LOGGER.error("Error while getting player info: " + e); + return gson.toJsonTree(internalServerError()).getAsJsonObject(); + + } + } + } + return gson.toJsonTree(ErrorHandler.customError(404, "Player Not Found")).getAsJsonObject(); + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/ErrorHandler.java b/src/main/java/me/jonasjones/mcwebserver/web/api/ErrorHandler.java new file mode 100644 index 0000000..9fe87cb --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/ErrorHandler.java @@ -0,0 +1,47 @@ +package me.jonasjones.mcwebserver.web.api; + +import me.jonasjones.mcwebserver.web.api.json.Error; + +import static me.jonasjones.mcwebserver.McWebserver.gson; + +public class ErrorHandler { + public static Error badRequest() { + return new Error(400, "Bad Request"); + } + + public static String badRequestString() { + return gson.toJsonTree(badRequest()).getAsJsonObject().toString(); + } + + public static Error internalServerError() { + return new Error(500, "Internal Server Error"); + } + + public static String internalServerErrorString() { + return gson.toJsonTree(internalServerError()).getAsJsonObject().toString(); + } + + public static Error forbiddenRequest() { + return new Error(403, "Forbidden"); + } + + public static String forbiddenRequestString() { + return gson.toJsonTree(forbiddenRequest()).getAsJsonObject().toString(); + } + + public static Error notFoundError() { + return new Error(404, "Not Found"); + } + + public static String notFoundErrorString() { + return gson.toJsonTree(notFoundError()).getAsJsonObject().toString(); + } + + public static Error customError(int status, String message) { + return new Error(status, message); + } + + public static String customErrorString(int status, String message) { + return gson.toJsonTree(customError(status, message)).getAsJsonObject().toString(); + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfo.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfo.java new file mode 100644 index 0000000..a014027 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfo.java @@ -0,0 +1,13 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfo { + private ApiPlayerInfoProfile profile; + private ApiPlayerInfoPose pose; + private ApiPlayerInfoMovement movement; + private ApiPlayerInfoVehicleProperties vehicleProperties; + private ApiPlayerInfoFishhook fishhook; + private ApiPlayerInfoInventory inventory; +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoFishhook.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoFishhook.java new file mode 100644 index 0000000..517e99d --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoFishhook.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoFishhook { + private String name; + private String uuid; + + public ApiPlayerInfoFishhook(String name, String uuid) { + this.name = name; + this.uuid = uuid; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventory.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventory.java new file mode 100644 index 0000000..0cfd0db --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventory.java @@ -0,0 +1,18 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoInventory { + private ApiPlayerInfoInventoryMain main; + private ApiPlayerInfoInventoryEnderChest enderChest; + private ApiPlayerInfoInventoryArmor armor; + private ApiPlayerInfoInventoryMisc misc; + + public ApiPlayerInfoInventory(ApiPlayerInfoInventoryMain main, ApiPlayerInfoInventoryEnderChest enderChest, ApiPlayerInfoInventoryArmor armor, ApiPlayerInfoInventoryMisc misc) { + this.main = main; + this.enderChest = enderChest; + this.armor = armor; + this.misc = misc; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryArmor.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryArmor.java new file mode 100644 index 0000000..7272bf5 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryArmor.java @@ -0,0 +1,18 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoInventoryArmor { + private ApiPlayerInfoInventoryItemStack head; + private ApiPlayerInfoInventoryItemStack chest; + private ApiPlayerInfoInventoryItemStack legs; + private ApiPlayerInfoInventoryItemStack feet; + + public ApiPlayerInfoInventoryArmor(ApiPlayerInfoInventoryItemStack head, ApiPlayerInfoInventoryItemStack chest, ApiPlayerInfoInventoryItemStack legs, ApiPlayerInfoInventoryItemStack feet) { + this.head = head; + this.chest = chest; + this.legs = legs; + this.feet = feet; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryEnderChest.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryEnderChest.java new file mode 100644 index 0000000..d8a4603 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryEnderChest.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +import java.util.ArrayList; + +@Setter +public class ApiPlayerInfoInventoryEnderChest { + private ArrayList items; + + public ApiPlayerInfoInventoryEnderChest(ArrayList items) { + this.items = items; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryItemStack.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryItemStack.java new file mode 100644 index 0000000..04ccc0a --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryItemStack.java @@ -0,0 +1,18 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; +import lombok.Setter; + +@Setter +public class ApiPlayerInfoInventoryItemStack { + private String translationKey; + private Integer count; + private JsonObject nbt; + + public ApiPlayerInfoInventoryItemStack(String translationKey, Integer count, JsonObject nbt) { + this.translationKey = translationKey; + this.count = count; + this.nbt = nbt; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMain.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMain.java new file mode 100644 index 0000000..a48c670 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMain.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +import java.util.ArrayList; + +@Setter +public class ApiPlayerInfoInventoryMain { + private ArrayList items; + + public ApiPlayerInfoInventoryMain(ArrayList items) { + this.items = items; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMisc.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMisc.java new file mode 100644 index 0000000..0c6003e --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoInventoryMisc.java @@ -0,0 +1,15 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoInventoryMisc { + private ApiPlayerInfoInventoryItemStack offHand; + private ApiPlayerInfoInventoryItemStack pickBlock; + private int selectedSlot; + + public ApiPlayerInfoInventoryMisc(ApiPlayerInfoInventoryItemStack offHand, ApiPlayerInfoInventoryItemStack pickBlock, int selectedSlot) { + this.offHand = offHand; + this.pickBlock = pickBlock; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovement.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovement.java new file mode 100644 index 0000000..dfee1ab --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovement.java @@ -0,0 +1,24 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovement { + private String direction; + private ThreeDoubleVector velocity; + private ApiPlayerInfoMovementDistance distance; + private ApiPlayerInfoMovementSpeed speed; + private ApiPlayerInfoMovementCollision collision; + private ApiPlayerInfoMovementEnv env; + private ApiPlayerInfoMovementStepHeight stepHeight; + + public ApiPlayerInfoMovement(String direction, ThreeDoubleVector velocity, ApiPlayerInfoMovementDistance distance, ApiPlayerInfoMovementSpeed speed, ApiPlayerInfoMovementCollision collision, ApiPlayerInfoMovementEnv env, ApiPlayerInfoMovementStepHeight stepHeight) { + this.direction = direction; + this.velocity = velocity; + this.distance = distance; + this.speed = speed; + this.collision = collision; + this.env = env; + this.stepHeight = stepHeight; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementCollision.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementCollision.java new file mode 100644 index 0000000..38196b1 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementCollision.java @@ -0,0 +1,20 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovementCollision { + private boolean horizontal; + private boolean vertical; + private boolean ground; + private boolean softly; + private boolean iscollidable; + + public ApiPlayerInfoMovementCollision(boolean horizontal, boolean vertical, boolean ground, boolean softly, boolean iscollidable) { + this.horizontal = horizontal; + this.vertical = vertical; + this.ground = ground; + this.softly = softly; + this.iscollidable = iscollidable; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementDistance.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementDistance.java new file mode 100644 index 0000000..0b8c1a5 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementDistance.java @@ -0,0 +1,16 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovementDistance { + private float traveled; + private float falling; + private float stride; + + public ApiPlayerInfoMovementDistance(float traveled, float falling, float stride) { + this.traveled = traveled; + this.falling = falling; + this.stride = stride; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementEnv.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementEnv.java new file mode 100644 index 0000000..e8cc08f --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementEnv.java @@ -0,0 +1,26 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovementEnv { + private boolean touchingWater; + private boolean touchingWaterOrRain; + private boolean submergedInWater; + private boolean inLava; + private boolean inPowderSnow; + private boolean isClimbing; + private boolean isFallFlying; + private boolean isSleeping; + + public ApiPlayerInfoMovementEnv(boolean touchingWater, boolean touchingWaterOrRain, boolean submergedInWater, boolean inLava, boolean inPowderSnow, boolean isClimbing, boolean isFallFlying, boolean isSleeping) { + this.touchingWater = touchingWater; + this.touchingWaterOrRain = touchingWaterOrRain; + this.submergedInWater = submergedInWater; + this.inLava = inLava; + this.inPowderSnow = inPowderSnow; + this.isClimbing = isClimbing; + this.isFallFlying = isFallFlying; + this.isSleeping = isSleeping; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementSpeed.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementSpeed.java new file mode 100644 index 0000000..1f1807e --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementSpeed.java @@ -0,0 +1,20 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovementSpeed { + private float speed; + private float forward; + private float horizontal; + private float sideways; + private float upward; + + public ApiPlayerInfoMovementSpeed(float speed, float forward, float horizontal, float sideways, float upward) { + this.speed = speed; + this.forward = forward; + this.horizontal = horizontal; + this.sideways = sideways; + this.upward = upward; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementStepHeight.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementStepHeight.java new file mode 100644 index 0000000..70a1152 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoMovementStepHeight.java @@ -0,0 +1,12 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoMovementStepHeight { + private float stepHeight; + + public ApiPlayerInfoMovementStepHeight(float stepHeight) { + this.stepHeight = stepHeight; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoNames.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoNames.java new file mode 100644 index 0000000..da850d9 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoNames.java @@ -0,0 +1,20 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoNames { + private String name; + private String playerListName; + private String customName; + private String displayName; + private String styledDisplayName; + + public ApiPlayerInfoNames(String name, String playerListName, String customName, String displayName, String styledDisplayName) { + this.name = name; + this.playerListName = playerListName; + this.customName = customName; + this.displayName = displayName; + this.styledDisplayName = styledDisplayName; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPose.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPose.java new file mode 100644 index 0000000..c995a34 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPose.java @@ -0,0 +1,32 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPose { + private float bodyYaw; + private double randomBodyY; + private float headYaw; + private ThreeDoubleVector capePosition; + private ThreeDoubleVector eyePosition; + private float standingEyeHeight; + private double swimHeight; + private float height; + private boolean isInvisible; + private float pitch; + private float yaw; + private String mainArm; + private double x; + private double y; + private double z; + private ApiPlayerInfoPoseLimbAnimation limbAnimation; + private TwoFloatVector rotationClient; + private ThreeDoubleVector rotation; + private ApiPlayerInfoPoseBoundingBox boundingBox; + private ApiPlayerInfoPoseChunkPosition chunkPosition; + private float scaleFactor; + private String sleepingDirection; + private ThreeIntegerVector sleepingPosition; + private ApiPlayerInfoPoseVisibilityBoundingBox visibilityBoundingBox; + private ApiPlayerInfoPoseSpawnPose spawnPose; +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseBoundingBox.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseBoundingBox.java new file mode 100644 index 0000000..702d86b --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseBoundingBox.java @@ -0,0 +1,29 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPoseBoundingBox { + private double minX; + private double minY; + private double minZ; + private double maxX; + private double maxY; + private double maxZ; + private double averageSideLength; + private ThreeDoubleVector center; + private ThreeDoubleVector size; + private boolean isEmpty; + + public ApiPlayerInfoPoseBoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, double averageSideLength, ThreeDoubleVector center, ThreeDoubleVector size, boolean isEmpty) { + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + this.averageSideLength = averageSideLength; + this.center = center; + this.isEmpty = isEmpty; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseChunkPosition.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseChunkPosition.java new file mode 100644 index 0000000..ec1cf4d --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseChunkPosition.java @@ -0,0 +1,30 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPoseChunkPosition { + private int x; + private int z; + private int startX; + private int startZ; + private int centerX; + private int centerZ; + private int endX; + private int endZ; + private int regionX; + private int regionZ; + + public ApiPlayerInfoPoseChunkPosition(int x, int z, int startX, int startZ, int centerX, int centerZ, int endX, int endZ, int regionX, int regionZ) { + this.x = x; + this.z = z; + this.startX = startX; + this.startZ = startZ; + this.centerX = centerX; + this.centerZ = centerZ; + this.endX = endX; + this.endZ = endZ; + this.regionX = regionX; + this.regionZ = regionZ; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseLimbAnimation.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseLimbAnimation.java new file mode 100644 index 0000000..b9eecf7 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseLimbAnimation.java @@ -0,0 +1,16 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPoseLimbAnimation { + private float position; + private float speed; + private boolean isMoving; + + public ApiPlayerInfoPoseLimbAnimation(float position, float speed, boolean isMoving) { + this.position = position; + this.speed = speed; + this.isMoving = isMoving; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseSpawnPose.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseSpawnPose.java new file mode 100644 index 0000000..95b0fca --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseSpawnPose.java @@ -0,0 +1,16 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPoseSpawnPose { + private ThreeIntegerVector position; + private float angle; + private String dimension; + + public ApiPlayerInfoPoseSpawnPose(ThreeIntegerVector position, float angle, String dimension) { + this.position = position; + this.angle = angle; + this.dimension = dimension; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseVisibilityBoundingBox.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseVisibilityBoundingBox.java new file mode 100644 index 0000000..249cc50 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoPoseVisibilityBoundingBox.java @@ -0,0 +1,30 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoPoseVisibilityBoundingBox { + private double minX; + private double minY; + private double minZ; + private double maxX; + private double maxY; + private double maxZ; + private double averageSideLength; + private ThreeDoubleVector center; + private ThreeDoubleVector size; + private Boolean isEmpty; + + public ApiPlayerInfoPoseVisibilityBoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, double averageSideLength, ThreeDoubleVector center, ThreeDoubleVector size, Boolean isEmpty) { + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + this.averageSideLength = averageSideLength; + this.center = center; + this.size = size; + this.isEmpty = isEmpty; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoProfile.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoProfile.java new file mode 100644 index 0000000..5495b66 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoProfile.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoProfile { + private ApiPlayerInfoNames names; + private int age; + + public ApiPlayerInfoProfile(ApiPlayerInfoNames names, int age) { + this.names = names; + this.age = age; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehicleProperties.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehicleProperties.java new file mode 100644 index 0000000..c5942f8 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehicleProperties.java @@ -0,0 +1,24 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoVehicleProperties { + private boolean hasVehicle; + private boolean shouldControlVehicles; + private ApiPlayerInfoVehiclePropertiesVehicle vehicle; + private ApiPlayerInfoVehiclePropertiesRootVehicle rootVehicle; + private ApiPlayerInfoVehiclePropertiesControllingPassanger controllingPassanger; + private ApiPlayerInfoVehiclePropertiesControllingVehicle controllingVehicle; + private boolean canSprintAsVehicle; + + public ApiPlayerInfoVehicleProperties(boolean hasVehicle, boolean shouldControlVehicles, ApiPlayerInfoVehiclePropertiesVehicle vehicle, ApiPlayerInfoVehiclePropertiesRootVehicle rootVehicle, ApiPlayerInfoVehiclePropertiesControllingVehicle controllingVehicle, ApiPlayerInfoVehiclePropertiesControllingPassanger controllingPassanger, boolean canSprintAsVehicle) { + this.hasVehicle = hasVehicle; + this.shouldControlVehicles = shouldControlVehicles; + this.vehicle = vehicle; + this.rootVehicle = rootVehicle; + this.controllingPassanger = controllingPassanger; + this.controllingVehicle = controllingVehicle; + this.canSprintAsVehicle = canSprintAsVehicle; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingPassanger.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingPassanger.java new file mode 100644 index 0000000..9d652a7 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingPassanger.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoVehiclePropertiesControllingPassanger { + private String name; + private String uuid; + + public ApiPlayerInfoVehiclePropertiesControllingPassanger(String name, String uuid) { + this.name = name; + this.uuid = uuid; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingVehicle.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingVehicle.java new file mode 100644 index 0000000..ceb3d1c --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesControllingVehicle.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoVehiclePropertiesControllingVehicle { + private String name; + private String uuid; + + public ApiPlayerInfoVehiclePropertiesControllingVehicle(String name, String uuid) { + this.name = name; + this.uuid = uuid; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesRootVehicle.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesRootVehicle.java new file mode 100644 index 0000000..c1542bc --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesRootVehicle.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoVehiclePropertiesRootVehicle { + private String name; + private String uuid; + + public ApiPlayerInfoVehiclePropertiesRootVehicle(String name, String uuid) { + this.name = name; + this.uuid = uuid; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesVehicle.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesVehicle.java new file mode 100644 index 0000000..d2e3b8c --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiPlayerInfoVehiclePropertiesVehicle.java @@ -0,0 +1,14 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ApiPlayerInfoVehiclePropertiesVehicle { + private String name; + private String uuid; + + public ApiPlayerInfoVehiclePropertiesVehicle(String name, String uuid) { + this.name = name; + this.uuid = uuid; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerInfo.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerInfo.java similarity index 88% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerInfo.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerInfo.java index 6746d12..660eea7 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerInfo.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerInfo.java @@ -1,4 +1,4 @@ -package me.jonasjones.mcwebserver.web.api.v1.json; +package me.jonasjones.mcwebserver.web.api.json; import com.google.gson.JsonObject; import lombok.Setter; diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadata.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadata.java similarity index 84% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadata.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadata.java index 2998599..954f73d 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadata.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadata.java @@ -1,4 +1,4 @@ -package me.jonasjones.mcwebserver.web.api.v1.json; +package me.jonasjones.mcwebserver.web.api.json; import com.google.gson.JsonObject; import lombok.Setter; diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayer.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayer.java similarity index 74% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayer.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayer.java index 8ca0ae9..820d211 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayer.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayer.java @@ -1,4 +1,4 @@ -package me.jonasjones.mcwebserver.web.api.v1.json; +package me.jonasjones.mcwebserver.web.api.json; import lombok.Setter; diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayerProperty.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayerProperty.java new file mode 100644 index 0000000..874e8ac --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayerProperty.java @@ -0,0 +1,4 @@ +package me.jonasjones.mcwebserver.web.api.json; + +public class ApiServerMetadataPlayerProperty { +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayers.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayers.java similarity index 79% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayers.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayers.java index 5ac2fb1..1d39227 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayers.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ApiServerMetadataPlayers.java @@ -1,4 +1,4 @@ -package me.jonasjones.mcwebserver.web.api.v1.json; +package me.jonasjones.mcwebserver.web.api.json; import lombok.Setter; diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/Error.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/Error.java new file mode 100644 index 0000000..cc70cf0 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/Error.java @@ -0,0 +1,10 @@ +package me.jonasjones.mcwebserver.web.api.json; + +public class Error { + private int status; + private String message; + public Error(int status, String badRequest) { + this.status = status; + this.message = badRequest; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeDoubleVector.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeDoubleVector.java new file mode 100644 index 0000000..0862212 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeDoubleVector.java @@ -0,0 +1,16 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ThreeDoubleVector { + private double x; + private double y; + private double z; + + public ThreeDoubleVector(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeFloatVector.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeFloatVector.java new file mode 100644 index 0000000..e281151 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeFloatVector.java @@ -0,0 +1,16 @@ +package me.jonasjones.mcwebserver.web.api.json; + +import lombok.Setter; + +@Setter +public class ThreeFloatVector { + private float x; + private float y; + private float z; + + public ThreeFloatVector(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeIntegerVector.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeIntegerVector.java new file mode 100644 index 0000000..1eeacee --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/ThreeIntegerVector.java @@ -0,0 +1,13 @@ +package me.jonasjones.mcwebserver.web.api.json; + +public class ThreeIntegerVector { + private Integer x; + private Integer y; + private Integer z; + + public ThreeIntegerVector(Integer x, Integer y, Integer z) { + this.x = x; + this.y = y; + this.z = z; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/json/TwoFloatVector.java b/src/main/java/me/jonasjones/mcwebserver/web/api/json/TwoFloatVector.java new file mode 100644 index 0000000..90d3e62 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/json/TwoFloatVector.java @@ -0,0 +1,11 @@ +package me.jonasjones.mcwebserver.web.api.json; + +public class TwoFloatVector { + private float x; + private float y; + + public TwoFloatVector(float x, float y) { + this.x = x; + this.y = y; + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequestsUtil.java b/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequestsUtil.java deleted file mode 100644 index 2083f98..0000000 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiRequestsUtil.java +++ /dev/null @@ -1,121 +0,0 @@ -package me.jonasjones.mcwebserver.web.api.v1; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.mojang.authlib.GameProfile; -import lombok.Getter; -import lombok.Setter; -import me.jonasjones.mcwebserver.web.api.v1.json.ApiServerInfo; -import me.jonasjones.mcwebserver.web.api.v1.json.ApiServerMetadata; -import me.jonasjones.mcwebserver.web.api.v1.json.ApiServerMetadataPlayer; -import me.jonasjones.mcwebserver.web.api.v1.json.ApiServerMetadataPlayers; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.advancement.Advancement; -import net.minecraft.entity.boss.CommandBossBar; -import net.minecraft.resource.ResourcePackProfile; -import net.minecraft.server.ServerMetadata; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.world.GameMode; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static me.jonasjones.mcwebserver.config.ModConfigs.WEB_PORT; - -public class ApiRequestsUtil { - @Getter @Setter - private static String MOTD; - @Getter @Setter - private static String SERVER_IP; - @Getter @Setter - private static int SERVER_PORT; - @Getter @Setter - private static String SERVER_NAME; - @Getter @Setter - private static String SERVER_VERSION; - @Getter @Setter - private static int CURRENT_PLAYER_COUNT; - @Getter @Setter - private static GameMode DEFAULT_GAME_MODE; - @Getter - private static final String LOADER_VERSION = FabricLoader.getInstance().getModContainer("fabricloader").get().getMetadata().getVersion().getFriendlyString(); - @Getter @Setter - private static int MAX_PLAYER_COUNT; - @Getter @Setter - private static ServerMetadata SERVER_METADATA; - @Getter @Setter - private static int TICKS; - //@Getter @Setter - //private static float TICK_TIME; - @Getter @Setter - private static long TIME_REFERENCE; - @Getter @Setter - private static List SERVER_PLAYER_ENTITY_LIST = new ArrayList<>(); - @Getter @Setter - private static Collection SERVER_RESOURCE_PACK_PROFILE_COLLECTION = new ArrayList<>(); - @Getter @Setter - private static Collection SERVER_ADVANCEMENT_COLLECTION = new ArrayList<>(); - @Getter @Setter - private static Collection SERVER_BOSSBAR_COLLECTION = new ArrayList<>(); - private static final ApiServerInfo apiServerInfo = new ApiServerInfo(); - private static final ApiServerMetadata apiServerMetadata = new ApiServerMetadata(); - private static final ApiServerMetadataPlayers apiServerMetadataPlayers = new ApiServerMetadataPlayers(); - private static final Gson gson = new Gson(); - - - public static JsonObject serverMetadata() { - apiServerMetadataPlayers.setMAX(ApiRequestsUtil.getSERVER_METADATA().players().get().max()); - apiServerMetadataPlayers.setONLINE(ApiRequestsUtil.getSERVER_METADATA().players().get().online()); - apiServerMetadataPlayers.setSAMPLE(convertPlayerList(ApiRequestsUtil.getSERVER_METADATA().players().get().sample())); - - apiServerMetadata.setDESCRIPTION(ApiRequestsUtil.getSERVER_METADATA().description().getString()); - apiServerMetadata.setPLAYERS(JsonParser.parseString(gson.toJson(apiServerMetadataPlayers)).getAsJsonObject()); - apiServerMetadata.setVERSION((JsonObject) JsonParser.parseString("{\"version\":\"" + ApiRequestsUtil.getSERVER_METADATA().version().get().gameVersion() + "\",\"protocol\":" + ApiRequestsUtil.getSERVER_METADATA().version().get().protocolVersion() + "}")); - if (ApiRequestsUtil.getSERVER_METADATA().favicon().isPresent()) { - if (!ApiRequestsUtil.getSERVER_IP().equals("")) { - apiServerMetadata.setFAVICON("http://" + ApiRequestsUtil.getSERVER_IP() + ":" + WEB_PORT + "/api/v1/servericon"); - } else { - apiServerMetadata.setFAVICON("/api/v1/servericon"); - } - } else { - apiServerMetadata.setFAVICON(""); // if favicon doesn't exist - } - - apiServerMetadata.setSECURE_CHAT_EINFORCED(ApiRequestsUtil.getSERVER_METADATA().secureChatEnforced()); - - return JsonParser.parseString(gson.toJson(apiServerMetadata)).getAsJsonObject(); - } - - public static ArrayList convertPlayerList(List list) { - ArrayList players = new ArrayList<>(); - for (GameProfile profile : list) { - ApiServerMetadataPlayer player = new ApiServerMetadataPlayer(); - player.setID(profile.getId().toString()); - player.setNAME(profile.getName()); - //player.setPROPERTIES(profile.getProperties().toString()); //Add support for the properties later - players.add(player); - } - return players; - } - - public static JsonObject getAll() { - apiServerInfo.setSERVER_IP(ApiRequestsUtil.getSERVER_IP()); - apiServerInfo.setSERVER_PORT(ApiRequestsUtil.getSERVER_PORT()); - apiServerInfo.setSERVER_NAME(ApiRequestsUtil.getSERVER_NAME()); - apiServerInfo.setDEFAULT_GAME_MODE(ApiRequestsUtil.getDEFAULT_GAME_MODE().toString()); - apiServerInfo.setLOADER_VERSION(LOADER_VERSION); - apiServerInfo.setMETADATA(serverMetadata()); - apiServerInfo.setTICKS(ApiRequestsUtil.getTICKS()); - //apiServerInfo.setTICK_TIME(ApiRequestsUtil.getTICK_TIME()); - apiServerInfo.setTIME_REFERENCE(ApiRequestsUtil.getTIME_REFERENCE()); - - return gson.toJsonTree(apiServerInfo).getAsJsonObject(); - } - - public static byte[] getServerIcon() { - return ApiRequestsUtil.getSERVER_METADATA().favicon().get().iconBytes(); - } - -} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiHandler.java b/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiV1Handler.java similarity index 77% rename from src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiHandler.java rename to src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiV1Handler.java index 5a5572f..29befb1 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiHandler.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/v1/ApiV1Handler.java @@ -1,12 +1,15 @@ package me.jonasjones.mcwebserver.web.api.v1; +import me.jonasjones.mcwebserver.web.api.ApiRequests; +import me.jonasjones.mcwebserver.web.api.ApiRequestsUtil; +import me.jonasjones.mcwebserver.web.api.ErrorHandler; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import static me.jonasjones.mcwebserver.McWebserver.MC_SERVER; -public class ApiHandler { +public class ApiV1Handler { - public static Boolean isApiRequest(String request) { + public static Boolean isApiV1Request(String request) { return request.startsWith("/api/v1/"); } public static String handle(String request) { @@ -58,7 +61,7 @@ public class ApiHandler { return ApiRequests.serverGetAllRequest(); } default -> { - return ApiRequests.badRequest(); + return ErrorHandler.notFoundErrorString(); } } } @@ -77,25 +80,8 @@ public class ApiHandler { ApiRequestsUtil.setMAX_PLAYER_COUNT(server.getMaxPlayerCount()); ApiRequestsUtil.setSERVER_METADATA(server.getServerMetadata()); ApiRequestsUtil.setTICKS(server.getTicks()); - //ApiRequestsUtil.setTICK_TIME(server.getTickTime()); ApiRequestsUtil.setTIME_REFERENCE(server.getTimeReference()); } }); } - - /*public static void startAdvHandler() { - ServerTickEvents.END_SERVER_TICK.register(server -> { - if (server.isRunning()) { - ApiRequestsUtil.setSERVER_PLAYER_ENTITY_LIST(server.getPlayerManager().getPlayerList()); - ApiRequestsUtil.setSERVER_RESOURCE_PACK_PROFILE_COLLECTION(server.getDataPackManager().getProfiles()); - ApiRequestsUtil.setSERVER_ADVANCEMENT_COLLECTION(server.getAdvancementLoader().getAdvancements()); - ApiRequestsUtil.setSERVER_BOSSBAR_COLLECTION(server.getBossBarManager().getAll()); - ApiRequestsUtil.getSERVER_PLAYER_ENTITY_LIST().forEach(serverPlayerEntity -> { - - }); - //SERVER_PLAYER_ENTITY_LIST = server.getPlayerInteractionManager().getPlayerList(); - } - }); - }*/ - } diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayerProperty.java b/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayerProperty.java deleted file mode 100644 index fd93fe3..0000000 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v1/json/ApiServerMetadataPlayerProperty.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.jonasjones.mcwebserver.web.api.v1.json; - -public class ApiServerMetadataPlayerProperty { -} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v2/ApiV2Handler.java b/src/main/java/me/jonasjones/mcwebserver/web/api/v2/ApiV2Handler.java new file mode 100644 index 0000000..7c29da9 --- /dev/null +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/v2/ApiV2Handler.java @@ -0,0 +1,99 @@ +package me.jonasjones.mcwebserver.web.api.v2; + +import me.jonasjones.mcwebserver.McWebserver; +import me.jonasjones.mcwebserver.web.api.ApiRequests; +import me.jonasjones.mcwebserver.web.api.ApiRequestsUtil; +import me.jonasjones.mcwebserver.web.api.ErrorHandler; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; + +import java.security.NoSuchAlgorithmException; + +import static me.jonasjones.mcwebserver.web.api.v2.tokenmgr.TokenManager.isTokenValid; + +public class ApiV2Handler { + public static Boolean isApiV2Request(String request) { + return request.startsWith("/api/v2/"); + } + + public static String handle(String request, String token) throws NoSuchAlgorithmException { + if (token == null) { + return ErrorHandler.forbiddenRequestString(); + } + + boolean isTokenValid = isTokenValid(token); + + switch (request.replace("/api/v2/", "")) { + // Simple API Requests + case "motd" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getMOTD()); + } + case "serverip" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getSERVER_IP()); + } + case "serverport" -> { + return ApiRequests.singleValueRequest(String.valueOf(ApiRequestsUtil.getSERVER_PORT())); + } + case "servername" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getSERVER_NAME()); + } + case "serverversion" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getSERVER_VERSION()); + } + case "loaderversion" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getLOADER_VERSION()); + } + case "currentplayercount" -> { + return ApiRequests.singleValueRequest(String.valueOf(ApiRequestsUtil.getCURRENT_PLAYER_COUNT())); + } + case "defaultgamemode" -> { + return ApiRequests.singleValueRequest(ApiRequestsUtil.getDEFAULT_GAME_MODE().toString()); + } + case "maxplayercount" -> { + return ApiRequests.singleValueRequest(String.valueOf(ApiRequestsUtil.getMAX_PLAYER_COUNT())); + } + case "playernames" -> { + return ApiRequests.playerNamesRequest(); + } + case "servermetadata" -> { + return ApiRequests.serverMetadataRequest(); + } + case "ticks" -> { + return ApiRequests.singleValueRequest(String.valueOf(ApiRequestsUtil.getTICKS())); + } + case "timereference" -> { + return ApiRequests.singleValueRequest(String.valueOf(ApiRequestsUtil.getTIME_REFERENCE())); + } + case "getall" -> { + return ApiRequests.serverGetAllRequest(); + } + } + + if (isTokenValid) { + request = request.replace("/api/v2/", ""); + if (request.startsWith("playerinfo?playername=")) { + String playerName = request.replace("playerinfo?playername=", ""); + return ApiRequests.playerInfoRequest(playerName); + } else if (request.startsWith("playerinfo?playeruuid=")) { + return ErrorHandler.badRequestString(); + } else { + return ErrorHandler.notFoundErrorString(); + } + } else { + return ErrorHandler.forbiddenRequestString(); + } + } + + public static void startAdvHandler() { + ServerTickEvents.END_SERVER_TICK.register(server -> { + if (server.isRunning()) { + ApiRequestsUtil.setSERVER_PLAYER_ENTITY_LIST(server.getPlayerManager().getPlayerList()); + ApiRequestsUtil.setSERVER_RESOURCE_PACK_PROFILE_COLLECTION(server.getDataPackManager().getProfiles()); + ApiRequestsUtil.setSERVER_ADVANCEMENT_COLLECTION(server.getAdvancementLoader().getAdvancements()); + ApiRequestsUtil.setSERVER_BOSSBAR_COLLECTION(server.getBossBarManager().getAll()); + ApiRequestsUtil.getSERVER_PLAYER_ENTITY_LIST().forEach(serverPlayerEntity -> { + + }); + } + }); + } +} diff --git a/src/main/java/me/jonasjones/mcwebserver/web/api/v2/tokenmgr/TokenManager.java b/src/main/java/me/jonasjones/mcwebserver/web/api/v2/tokenmgr/TokenManager.java index 3f065bf..91bdf3d 100644 --- a/src/main/java/me/jonasjones/mcwebserver/web/api/v2/tokenmgr/TokenManager.java +++ b/src/main/java/me/jonasjones/mcwebserver/web/api/v2/tokenmgr/TokenManager.java @@ -11,6 +11,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -20,7 +21,7 @@ public class TokenManager { @Getter private static ArrayList tokens = new ArrayList<>(); - private static String hashString(String input) throws NoSuchAlgorithmException { + public static String hashString(String input) throws NoSuchAlgorithmException { try { // Create a MessageDigest instance for SHA-256 MessageDigest digest = MessageDigest.getInstance("SHA-256"); @@ -177,4 +178,19 @@ public class TokenManager { } return tokenNames; } + + public static Boolean isTokenValid(String token) throws NoSuchAlgorithmException { + tokens = readTokensFromFile(); + for (Token tokenObj : tokens) { + if (tokenObj.getTokenHash().equals(hashString(token))) { + if (tokenObj.getExpires() == 0) { + return true; + } + if (tokenObj.getExpires() > Instant.now().getEpochSecond()) { + return true; + } + } + } + return false; + } }