first version of api-v2

player data still incomplete and only available as a single request.
This commit is contained in:
Jonas_Jones 2024-01-17 17:40:44 +01:00
parent c313040af8
commit aa51d85388
47 changed files with 1334 additions and 182 deletions

View file

@ -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

View file

@ -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) {

View file

@ -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\"}}";
}
}

View file

@ -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<ServerPlayerEntity> SERVER_PLAYER_ENTITY_LIST = new ArrayList<>();
@Getter @Setter
private static Collection<ResourcePackProfile> SERVER_RESOURCE_PACK_PROFILE_COLLECTION = new ArrayList<>();
@Getter @Setter
private static Collection<AdvancementEntry> SERVER_ADVANCEMENT_COLLECTION = new ArrayList<>();
@Getter @Setter
private static Collection<CommandBossBar> 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<ApiServerMetadataPlayer> convertPlayerList(List<GameProfile> list) {
ArrayList<ApiServerMetadataPlayer> 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<Integer> 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<Integer> 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<String> vehicle = new Vec<>();
try {
vehicle.set(0, Objects.requireNonNull(player.getVehicle()).getName().getString());
vehicle.set(1, player.getVehicle().getUuidAsString());
} catch (Exception ignored) {}
Vec<String> controllingVehicle = new Vec<>();
try {
controllingVehicle.set(0, Objects.requireNonNull(player.getControllingVehicle()).getName().getString());
controllingVehicle.set(1, player.getControllingVehicle().getUuidAsString());
} catch (Exception ignored) {}
Vec<String> controllingPassenger = new Vec<>();
try {
controllingPassenger.set(0, Objects.requireNonNull(player.getControllingPassenger()).getName().getString());
controllingPassenger.set(1, player.getControllingPassenger().getUuidAsString());
} catch (Exception ignored) {}
Vec<String> fishHook = new Vec<>();
try {
fishHook.set(0, Objects.requireNonNull(player.fishHook).getName().getString());
fishHook.set(1, player.fishHook.getUuidAsString());
} catch (Exception ignored) {}
ArrayList<ApiPlayerInfoInventoryItemStack> 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<ApiPlayerInfoInventoryItemStack> 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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,14 @@
package me.jonasjones.mcwebserver.web.api.json;
import lombok.Setter;
import java.util.ArrayList;
@Setter
public class ApiPlayerInfoInventoryEnderChest {
private ArrayList<ApiPlayerInfoInventoryItemStack> items;
public ApiPlayerInfoInventoryEnderChest(ArrayList<ApiPlayerInfoInventoryItemStack> items) {
this.items = items;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,14 @@
package me.jonasjones.mcwebserver.web.api.json;
import lombok.Setter;
import java.util.ArrayList;
@Setter
public class ApiPlayerInfoInventoryMain {
private ArrayList<ApiPlayerInfoInventoryItemStack> items;
public ApiPlayerInfoInventoryMain(ArrayList<ApiPlayerInfoInventoryItemStack> items) {
this.items = items;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;

View file

@ -1,4 +1,4 @@
package me.jonasjones.mcwebserver.web.api.v1.json;
package me.jonasjones.mcwebserver.web.api.json;
import lombok.Setter;

View file

@ -0,0 +1,4 @@
package me.jonasjones.mcwebserver.web.api.json;
public class ApiServerMetadataPlayerProperty {
}

View file

@ -1,4 +1,4 @@
package me.jonasjones.mcwebserver.web.api.v1.json;
package me.jonasjones.mcwebserver.web.api.json;
import lombok.Setter;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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<ServerPlayerEntity> SERVER_PLAYER_ENTITY_LIST = new ArrayList<>();
@Getter @Setter
private static Collection<ResourcePackProfile> SERVER_RESOURCE_PACK_PROFILE_COLLECTION = new ArrayList<>();
@Getter @Setter
private static Collection<Advancement> SERVER_ADVANCEMENT_COLLECTION = new ArrayList<>();
@Getter @Setter
private static Collection<CommandBossBar> 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<ApiServerMetadataPlayer> convertPlayerList(List<GameProfile> list) {
ArrayList<ApiServerMetadataPlayer> 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();
}
}

View file

@ -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();
}
});
}*/
}

View file

@ -1,4 +0,0 @@
package me.jonasjones.mcwebserver.web.api.v1.json;
public class ApiServerMetadataPlayerProperty {
}

View file

@ -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 -> {
});
}
});
}
}

View file

@ -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<Token> 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;
}
}