Add Skin and Cape textures to players
This commit is contained in:
parent
035b86920a
commit
16403673d3
24
src/main/java/me/braydon/mc/common/Tuple.java
Normal file
24
src/main/java/me/braydon/mc/common/Tuple.java
Normal file
@ -0,0 +1,24 @@
|
||||
package me.braydon.mc.common;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* A simple tuple utility.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@NoArgsConstructor @AllArgsConstructor @Setter @Getter
|
||||
public class Tuple<L, R> {
|
||||
/**
|
||||
* The left value.
|
||||
*/
|
||||
private L left;
|
||||
|
||||
/**
|
||||
* The right value.
|
||||
*/
|
||||
private R right;
|
||||
}
|
30
src/main/java/me/braydon/mc/model/Cape.java
Normal file
30
src/main/java/me/braydon/mc/model/Cape.java
Normal file
@ -0,0 +1,30 @@
|
||||
package me.braydon.mc.model;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* A cape for a {@link Player}.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @ToString
|
||||
public final class Cape {
|
||||
/**
|
||||
* The texture URL of this cape.
|
||||
*/
|
||||
@NonNull private final String url;
|
||||
|
||||
/**
|
||||
* Build a cape from the given Json object.
|
||||
*
|
||||
* @param jsonObject the json object to build from
|
||||
* @return the built cape
|
||||
*/
|
||||
public static Cape fromJsonObject(JsonObject jsonObject) {
|
||||
if (jsonObject == null) { // No object to parse
|
||||
return null;
|
||||
}
|
||||
return new Cape(jsonObject.get("url").getAsString());
|
||||
}
|
||||
}
|
@ -26,6 +26,16 @@ public class Player {
|
||||
*/
|
||||
@NonNull private String username;
|
||||
|
||||
/**
|
||||
* The skin of this player.
|
||||
*/
|
||||
@NonNull private Skin skin;
|
||||
|
||||
/**
|
||||
* The cape of this player, null if none.
|
||||
*/
|
||||
private Cape cape;
|
||||
|
||||
/**
|
||||
* The profile actions this player has, null if none.
|
||||
*/
|
||||
|
@ -1,7 +1,50 @@
|
||||
package me.braydon.mc.model;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* A skin for a {@link Player}.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter @ToString
|
||||
public final class Skin {
|
||||
public static final Skin DEFAULT_STEVE = new Skin("http://textures.minecraft.net/texture/60a5bd016b3c9a1b9272e4929e30827a67be4ebb219017adbbc4a4d22ebd5b1", Model.DEFAULT);
|
||||
|
||||
/**
|
||||
* The texture URL of this skin.
|
||||
*/
|
||||
@NonNull private final String url;
|
||||
|
||||
/**
|
||||
* The model of this skin.
|
||||
*/
|
||||
@NonNull private final Model model;
|
||||
|
||||
/**
|
||||
* Build a skin from the given Json object.
|
||||
*
|
||||
* @param jsonObject the json object to build from
|
||||
* @return the built skin
|
||||
*/
|
||||
public static Skin fromJsonObject(JsonObject jsonObject) {
|
||||
if (jsonObject == null) { // No object to parse
|
||||
return null;
|
||||
}
|
||||
Model model = Model.DEFAULT; // The skin model
|
||||
|
||||
JsonObject metadataJsonObject = jsonObject.getAsJsonObject("metadata");
|
||||
if (metadataJsonObject != null) { // Parse the skin model
|
||||
model = Model.valueOf(metadataJsonObject.get("model").getAsString().toUpperCase());
|
||||
}
|
||||
return new Skin(jsonObject.get("url").getAsString(), model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible models for a skin.
|
||||
*/
|
||||
public enum Model {
|
||||
SLIM, DEFAULT
|
||||
}
|
||||
}
|
@ -4,8 +4,10 @@ import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import me.braydon.mc.model.Cape;
|
||||
import me.braydon.mc.model.Player;
|
||||
import me.braydon.mc.model.ProfileAction;
|
||||
import me.braydon.mc.model.Skin;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -26,8 +28,9 @@ public final class CachedPlayer extends Player implements Serializable {
|
||||
*/
|
||||
private long cached;
|
||||
|
||||
public CachedPlayer(@NonNull UUID uniqueId, @NonNull String username, ProfileAction[] profileActions, long cached) {
|
||||
super(uniqueId, username, profileActions);
|
||||
public CachedPlayer(@NonNull UUID uniqueId, @NonNull String username,
|
||||
@NonNull Skin skin, Cape cape, ProfileAction[] profileActions, long cached) {
|
||||
super(uniqueId, username, skin, cape, profileActions);
|
||||
this.cached = cached;
|
||||
}
|
||||
}
|
@ -1,7 +1,14 @@
|
||||
package me.braydon.mc.model.token;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.*;
|
||||
import me.braydon.mc.RESTfulMC;
|
||||
import me.braydon.mc.common.Tuple;
|
||||
import me.braydon.mc.model.Cape;
|
||||
import me.braydon.mc.model.ProfileAction;
|
||||
import me.braydon.mc.model.Skin;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* A token representing a Mojang user profile.
|
||||
@ -31,6 +38,37 @@ public final class MojangProfileToken {
|
||||
*/
|
||||
@NonNull private ProfileAction[] profileActions;
|
||||
|
||||
public Tuple<Skin, Cape> getSkinAndCape() {
|
||||
ProfileProperty textures = getPropertyByName("textures"); // Get the profile textures
|
||||
if (textures == null) { // No profile textures
|
||||
return new Tuple<>();
|
||||
}
|
||||
JsonObject jsonObject = RESTfulMC.GSON.fromJson(textures.getDecodedValue(), JsonObject.class); // Get the Json object
|
||||
JsonObject texturesJsonObject = jsonObject.getAsJsonObject("textures"); // Get the textures object
|
||||
|
||||
// Return the tuple containing the skin and cape
|
||||
return new Tuple<>(
|
||||
Skin.fromJsonObject(texturesJsonObject.getAsJsonObject("SKIN")),
|
||||
Cape.fromJsonObject(texturesJsonObject.getAsJsonObject("CAPE"))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the profile property
|
||||
* with the given name.
|
||||
*
|
||||
* @param name the property name
|
||||
* @return the profile property, null if none
|
||||
*/
|
||||
public ProfileProperty getPropertyByName(@NonNull String name) {
|
||||
for (ProfileProperty property : properties) {
|
||||
if (property.getName().equalsIgnoreCase(name)) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property of a Mojang profile.
|
||||
*/
|
||||
@ -51,6 +89,17 @@ public final class MojangProfileToken {
|
||||
*/
|
||||
private String signature;
|
||||
|
||||
/**
|
||||
* Get the decoded Base64
|
||||
* value of this property.
|
||||
*
|
||||
* @return the decoded value
|
||||
*/
|
||||
@NonNull
|
||||
public String getDecodedValue() {
|
||||
return new String(Base64.getDecoder().decode(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this property signed?
|
||||
*
|
||||
|
@ -2,13 +2,16 @@ package me.braydon.mc.service;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import me.braydon.mc.common.Tuple;
|
||||
import me.braydon.mc.common.UUIDUtils;
|
||||
import me.braydon.mc.common.web.JsonWebException;
|
||||
import me.braydon.mc.common.web.JsonWebRequest;
|
||||
import me.braydon.mc.exception.impl.BadRequestException;
|
||||
import me.braydon.mc.exception.impl.ResourceNotFoundException;
|
||||
import me.braydon.mc.model.Cape;
|
||||
import me.braydon.mc.model.Player;
|
||||
import me.braydon.mc.model.ProfileAction;
|
||||
import me.braydon.mc.model.Skin;
|
||||
import me.braydon.mc.model.cache.CachedPlayer;
|
||||
import me.braydon.mc.model.cache.CachedPlayerName;
|
||||
import me.braydon.mc.model.token.MojangProfileToken;
|
||||
@ -60,10 +63,10 @@ public final class MojangService {
|
||||
* and then return the response.
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to search for the player by
|
||||
* @param query the query to search for the player by
|
||||
* @param bypassCache should the cache be bypassed?
|
||||
* @return the player
|
||||
* @throws BadRequestException if the UUID is malformed
|
||||
* @throws BadRequestException if the UUID is malformed
|
||||
* @throws ResourceNotFoundException if the player is not found
|
||||
*/
|
||||
@NonNull
|
||||
@ -100,11 +103,14 @@ public final class MojangService {
|
||||
MojangProfileToken token = JsonWebRequest.makeRequest(
|
||||
UUID_TO_PROFILE.formatted(uuid), HttpMethod.GET
|
||||
).execute(MojangProfileToken.class);
|
||||
Tuple<Skin, Cape> skinAndCape = token.getSkinAndCape(); // Get the skin and cape
|
||||
ProfileAction[] profileActions = token.getProfileActions();
|
||||
|
||||
// Build our player model, cache it, and then return it
|
||||
CachedPlayer player = new CachedPlayer(
|
||||
uuid, token.getName(),
|
||||
skinAndCape.getLeft() == null ? Skin.DEFAULT_STEVE : skinAndCape.getLeft(),
|
||||
skinAndCape.getRight(),
|
||||
profileActions.length == 0 ? null : profileActions,
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user