This commit is contained in:
parent
205ae144c0
commit
3f7f1864a6
@ -1,9 +1,9 @@
|
|||||||
package cc.fascinated.controller;
|
package cc.fascinated.controller;
|
||||||
|
|
||||||
import cc.fascinated.player.PlayerService;
|
import cc.fascinated.service.player.PlayerService;
|
||||||
import cc.fascinated.player.impl.Player;
|
import cc.fascinated.service.player.impl.Player;
|
||||||
import cc.fascinated.player.impl.Skin;
|
import cc.fascinated.service.player.impl.Skin;
|
||||||
import cc.fascinated.player.impl.SkinPart;
|
import cc.fascinated.service.player.impl.SkinPart;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.CacheControl;
|
import org.springframework.http.CacheControl;
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
package cc.fascinated.mojang.types;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Getter @ToString
|
|
||||||
public class MojangSessionServerProfile {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UUID of the player.
|
|
||||||
*/
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the player.
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The properties for the player.
|
|
||||||
*/
|
|
||||||
private final List<MojangSessionServerProfileProperties> properties = new ArrayList<>();
|
|
||||||
|
|
||||||
public MojangSessionServerProfile() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the texture property for the player.
|
|
||||||
*
|
|
||||||
* @return the texture property
|
|
||||||
*/
|
|
||||||
public MojangSessionServerProfileProperties getTextureProperty() {
|
|
||||||
for (MojangSessionServerProfileProperties property : properties) {
|
|
||||||
if (property.getName().equals("textures")) {
|
|
||||||
return property;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package cc.fascinated.mojang.types;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Getter @ToString
|
|
||||||
public class MojangSessionServerProfileProperties {
|
|
||||||
private String name;
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
public MojangSessionServerProfileProperties() {}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package cc.fascinated.player.impl;
|
|
||||||
|
|
||||||
import cc.fascinated.Main;
|
|
||||||
import cc.fascinated.config.Config;
|
|
||||||
import cc.fascinated.mojang.types.MojangSessionServerProfile;
|
|
||||||
import cc.fascinated.mojang.types.MojangSessionServerProfileProperties;
|
|
||||||
import cc.fascinated.util.UUIDUtils;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class Player {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UUID of the player
|
|
||||||
*/
|
|
||||||
private final UUID uuid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the player
|
|
||||||
*/
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The skin of the player
|
|
||||||
* <p>
|
|
||||||
* This will be null if the player does not have a skin.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
private Skin skin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cape of the player
|
|
||||||
* <p>
|
|
||||||
* This will be null if the player does not have a cape.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
private Cape cape;
|
|
||||||
|
|
||||||
public Player(MojangSessionServerProfile profile) {
|
|
||||||
this.uuid = UUID.fromString(UUIDUtils.addUUIDDashes(profile.getId()));
|
|
||||||
this.name = profile.getName();
|
|
||||||
|
|
||||||
MojangSessionServerProfileProperties textureProperty = profile.getTextureProperty();
|
|
||||||
if (textureProperty == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the texture property
|
|
||||||
String decoded = new String(java.util.Base64.getDecoder().decode(textureProperty.getValue()));
|
|
||||||
|
|
||||||
// Parse the decoded JSON
|
|
||||||
JsonObject json = Main.getGSON().fromJson(decoded, JsonObject.class);
|
|
||||||
JsonObject texturesJson = json.getAsJsonObject("textures");
|
|
||||||
JsonObject skinJson = texturesJson.getAsJsonObject("SKIN");
|
|
||||||
JsonObject capeJson = texturesJson.getAsJsonObject("CAPE");
|
|
||||||
JsonObject metadataJson = skinJson.get("metadata").getAsJsonObject();
|
|
||||||
|
|
||||||
this.skin = new Skin(this.uuid.toString(), skinJson.get("url").getAsString(),
|
|
||||||
Skin.SkinType.valueOf(metadataJson.get("model").getAsString().toUpperCase()));
|
|
||||||
this.cape = new Cape(capeJson.get("url").getAsString());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
package cc.fascinated.mojang;
|
package cc.fascinated.service.mojang;
|
||||||
|
|
||||||
import cc.fascinated.mojang.types.MojangApiProfile;
|
import cc.fascinated.service.mojang.types.MojangProfile;
|
||||||
import cc.fascinated.mojang.types.MojangSessionServerProfile;
|
import cc.fascinated.service.mojang.types.MojangUsernameToUuid;
|
||||||
import cc.fascinated.util.WebRequest;
|
import cc.fascinated.util.WebRequest;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -17,22 +17,24 @@ public class MojangAPIService {
|
|||||||
private String mojangApiUrl;
|
private String mojangApiUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Session Server profile of the player with the given UUID.
|
* Gets the Session Server profile of the
|
||||||
|
* player with the given UUID.
|
||||||
*
|
*
|
||||||
* @param id the uuid or name of the player
|
* @param id the uuid or name of the player
|
||||||
* @return the profile
|
* @return the profile
|
||||||
*/
|
*/
|
||||||
public MojangSessionServerProfile getSessionServerProfile(String id) {
|
public MojangProfile getProfile(String id) {
|
||||||
return WebRequest.get(mojangSessionServerUrl + "/session/minecraft/profile/" + id, MojangSessionServerProfile.class);
|
return WebRequest.get(mojangSessionServerUrl + "/session/minecraft/profile/" + id, MojangProfile.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Mojang API profile of the player with the given UUID.
|
* Gets the UUID of the player using
|
||||||
|
* the name of the player.
|
||||||
*
|
*
|
||||||
* @param id the name of the player
|
* @param id the name of the player
|
||||||
* @return the profile
|
* @return the profile
|
||||||
*/
|
*/
|
||||||
public MojangApiProfile getApiProfile(String id) {
|
public MojangUsernameToUuid getUuidFromUsername(String id) {
|
||||||
return WebRequest.get(mojangApiUrl + "/users/profiles/minecraft/" + id, MojangApiProfile.class);
|
return WebRequest.get(mojangApiUrl + "/users/profiles/minecraft/" + id, MojangUsernameToUuid.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package cc.fascinated.service.mojang.types;
|
||||||
|
|
||||||
|
import cc.fascinated.Main;
|
||||||
|
import cc.fascinated.service.player.impl.Cape;
|
||||||
|
import cc.fascinated.service.player.impl.Skin;
|
||||||
|
import cc.fascinated.util.Tuple;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter @NoArgsConstructor
|
||||||
|
public class MojangProfile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UUID of the player.
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the player.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The properties of the player.
|
||||||
|
*/
|
||||||
|
private final List<ProfileProperty> properties = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the skin and cape of the player.
|
||||||
|
*
|
||||||
|
* @return the skin and cape of the player
|
||||||
|
*/
|
||||||
|
public Tuple<Skin, Cape> getSkinAndCape() {
|
||||||
|
ProfileProperty textureProperty = getTextureProperty();
|
||||||
|
if (textureProperty == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the texture property
|
||||||
|
String decoded = new String(java.util.Base64.getDecoder().decode(textureProperty.getValue()));
|
||||||
|
|
||||||
|
// Parse the decoded JSON
|
||||||
|
JsonObject json = Main.getGSON().fromJson(decoded, JsonObject.class);
|
||||||
|
JsonObject texturesJson = json.getAsJsonObject("textures");
|
||||||
|
JsonObject skinJson = texturesJson.getAsJsonObject("SKIN");
|
||||||
|
JsonObject capeJson = texturesJson.getAsJsonObject("CAPE");
|
||||||
|
JsonObject metadataJson = skinJson.get("metadata").getAsJsonObject();
|
||||||
|
|
||||||
|
Skin skin = new Skin(id, skinJson.get("url").getAsString(),
|
||||||
|
Skin.SkinType.valueOf(metadataJson.get("model").getAsString().toUpperCase()));
|
||||||
|
Cape cape = new Cape(capeJson.get("url").getAsString());
|
||||||
|
|
||||||
|
return new Tuple<>(skin, cape);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the texture property of the player.
|
||||||
|
*
|
||||||
|
* @return the texture property
|
||||||
|
*/
|
||||||
|
public ProfileProperty getTextureProperty() {
|
||||||
|
for (ProfileProperty property : properties) {
|
||||||
|
if (property.getName().equals("textures")) {
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter @AllArgsConstructor
|
||||||
|
public static class ProfileProperty {
|
||||||
|
/**
|
||||||
|
* The name of the property.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base64 value of the property.
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature of the property.
|
||||||
|
*/
|
||||||
|
private String signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the property is signed.
|
||||||
|
*
|
||||||
|
* @return true if the property is signed, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isSigned() {
|
||||||
|
return signature != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,20 @@
|
|||||||
package cc.fascinated.mojang.types;
|
package cc.fascinated.service.mojang.types;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@Getter @ToString
|
@Getter @NoArgsConstructor
|
||||||
public class MojangApiProfile {
|
public class MojangUsernameToUuid {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UUID of the player.
|
||||||
|
*/
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
|
||||||
|
|
||||||
public MojangApiProfile() {}
|
/**
|
||||||
|
* The name of the player.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the profile is valid.
|
* Check if the profile is valid.
|
@ -1,9 +1,9 @@
|
|||||||
package cc.fascinated.player;
|
package cc.fascinated.service.player;
|
||||||
|
|
||||||
import cc.fascinated.mojang.MojangAPIService;
|
import cc.fascinated.service.mojang.MojangAPIService;
|
||||||
import cc.fascinated.mojang.types.MojangApiProfile;
|
import cc.fascinated.service.mojang.types.MojangProfile;
|
||||||
import cc.fascinated.mojang.types.MojangSessionServerProfile;
|
import cc.fascinated.service.mojang.types.MojangUsernameToUuid;
|
||||||
import cc.fascinated.player.impl.Player;
|
import cc.fascinated.service.player.impl.Player;
|
||||||
import cc.fascinated.util.UUIDUtils;
|
import cc.fascinated.util.UUIDUtils;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.jodah.expiringmap.ExpirationPolicy;
|
import net.jodah.expiringmap.ExpirationPolicy;
|
||||||
@ -47,25 +47,28 @@ public class PlayerService {
|
|||||||
*/
|
*/
|
||||||
public Player getPlayer(String id) {
|
public Player getPlayer(String id) {
|
||||||
UUID uuid = null;
|
UUID uuid = null;
|
||||||
if (id.length() == 32 || id.length() == 36) {
|
if (id.length() == 32 || id.length() == 36) { // Check if the id is a UUID
|
||||||
try {
|
try {
|
||||||
uuid = UUID.fromString(id.length() == 32 ? UUIDUtils.addUUIDDashes(id) : id);
|
uuid = UUID.fromString(id.length() == 32 ? UUIDUtils.addUUIDDashes(id) : id);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
} else {
|
} else { // Check if the id is a name
|
||||||
uuid = playerNameToUUIDCache.get(id.toUpperCase());
|
uuid = playerNameToUUIDCache.get(id.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the player is cached
|
||||||
if (uuid != null && players.containsKey(uuid)) {
|
if (uuid != null && players.containsKey(uuid)) {
|
||||||
return players.get(uuid);
|
return players.get(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
MojangSessionServerProfile profile = uuid == null ? null : mojangAPIService.getSessionServerProfile(uuid.toString());
|
MojangProfile profile = uuid == null ? null : mojangAPIService.getProfile(uuid.toString());
|
||||||
if (profile == null) {
|
if (profile == null) { // The player cannot be found using their UUID
|
||||||
MojangApiProfile apiProfile = mojangAPIService.getApiProfile(id);
|
MojangUsernameToUuid apiProfile = mojangAPIService.getUuidFromUsername(id); // Get the UUID of the player using their name
|
||||||
if (apiProfile == null || !apiProfile.isValid()) {
|
if (apiProfile == null || !apiProfile.isValid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
profile = mojangAPIService.getSessionServerProfile(apiProfile.getId().length() == 32 ? UUIDUtils.addUUIDDashes(apiProfile.getId()) : apiProfile.getId());
|
// Get the profile of the player using their UUID
|
||||||
|
profile = mojangAPIService.getProfile(apiProfile.getId().length() == 32 ?
|
||||||
|
UUIDUtils.addUUIDDashes(apiProfile.getId()) : apiProfile.getId());
|
||||||
}
|
}
|
||||||
if (profile == null) { // The player cannot be found using their name or UUID
|
if (profile == null) { // The player cannot be found using their name or UUID
|
||||||
log.info("Player with id {} could not be found", id);
|
log.info("Player with id {} could not be found", id);
|
@ -1,4 +1,4 @@
|
|||||||
package cc.fascinated.player.impl;
|
package cc.fascinated.service.player.impl;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
50
src/main/java/cc/fascinated/service/player/impl/Player.java
Normal file
50
src/main/java/cc/fascinated/service/player/impl/Player.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package cc.fascinated.service.player.impl;
|
||||||
|
|
||||||
|
import cc.fascinated.service.mojang.types.MojangProfile;
|
||||||
|
import cc.fascinated.util.Tuple;
|
||||||
|
import cc.fascinated.util.UUIDUtils;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Player {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UUID of the player
|
||||||
|
*/
|
||||||
|
private final UUID uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the player
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The skin of the player
|
||||||
|
* <p>
|
||||||
|
* This will be null if the player does not have a skin.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private Skin skin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cape of the player
|
||||||
|
* <p>
|
||||||
|
* This will be null if the player does not have a cape.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private Cape cape;
|
||||||
|
|
||||||
|
public Player(MojangProfile profile) {
|
||||||
|
this.uuid = UUID.fromString(UUIDUtils.addUUIDDashes(profile.getId()));
|
||||||
|
this.name = profile.getName();
|
||||||
|
|
||||||
|
// Get the skin and cape
|
||||||
|
Tuple<Skin, Cape> skinAndCape = profile.getSkinAndCape();
|
||||||
|
if (skinAndCape != null) {
|
||||||
|
this.skin = skinAndCape.getLeft();
|
||||||
|
this.cape = skinAndCape.getRight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cc.fascinated.player.impl;
|
package cc.fascinated.service.player.impl;
|
||||||
|
|
||||||
import cc.fascinated.Main;
|
import cc.fascinated.Main;
|
||||||
import cc.fascinated.config.Config;
|
import cc.fascinated.config.Config;
|
@ -1,4 +1,4 @@
|
|||||||
package cc.fascinated.player.impl;
|
package cc.fascinated.service.player.impl;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
18
src/main/java/cc/fascinated/util/Tuple.java
Normal file
18
src/main/java/cc/fascinated/util/Tuple.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package cc.fascinated.util;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter @AllArgsConstructor
|
||||||
|
public class Tuple<L, R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The left value of the tuple.
|
||||||
|
*/
|
||||||
|
private final L left;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The right value of the tuple.
|
||||||
|
*/
|
||||||
|
private final R right;
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package cc.fascinated.util;
|
package cc.fascinated.util;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class UUIDUtils {
|
public class UUIDUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package cc.fascinated.util;
|
package cc.fascinated.util;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
import org.springframework.web.client.HttpClientErrorException;
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
import org.springframework.web.client.RestClient;
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
public class WebRequest {
|
public class WebRequest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
<p>Wrapper for the Minecraft APIs to make them easier to use.</p>
|
<p>Wrapper for the Minecraft APIs to make them easier to use.</p>
|
||||||
|
|
||||||
<div class="flex flex-col mt-3">
|
<div class="flex flex-col mt-3">
|
||||||
<p>Player Data: <a class="text-blue-600" th:href="${url}" th:text="${url}">???</a></p>
|
<p>Player Data: <a class="text-blue-600" th:href="${player_example_url}" th:text="${player_example_url}">???</a></p>
|
||||||
<p>Avatar Url: <a class="text-blue-600" th:href="${avatar_url}" th:text="${avatar_url}">???</a></p>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user