Throw MojangApiException and IOException in HeadTexture#of and SkullBuilder constructor

Implements #54
This commit is contained in:
NichtStudioCode 2023-10-28 13:40:05 +02:00
parent 659e9596fc
commit f029914abd
2 changed files with 49 additions and 22 deletions

@ -17,7 +17,9 @@ import org.jetbrains.annotations.Nullable;
import xyz.xenondevs.inventoryaccess.util.ReflectionRegistry; import xyz.xenondevs.inventoryaccess.util.ReflectionRegistry;
import xyz.xenondevs.inventoryaccess.util.ReflectionUtils; import xyz.xenondevs.inventoryaccess.util.ReflectionUtils;
import xyz.xenondevs.invui.util.MojangApiUtils; import xyz.xenondevs.invui.util.MojangApiUtils;
import xyz.xenondevs.invui.util.MojangApiUtils.MojangApiException;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -31,8 +33,10 @@ public final class SkullBuilder extends AbstractItemBuilder<SkullBuilder> {
* Create a {@link SkullBuilder} of a {@link Player Player's} {@link UUID}. * Create a {@link SkullBuilder} of a {@link Player Player's} {@link UUID}.
* *
* @param uuid The {@link UUID} of the skull owner. * @param uuid The {@link UUID} of the skull owner.
* @throws MojangApiException If the Mojang API returns an error.
* @throws IOException If an I/O error occurs.
*/ */
public SkullBuilder(@NotNull UUID uuid) { public SkullBuilder(@NotNull UUID uuid) throws MojangApiException, IOException {
this(HeadTexture.of(uuid)); this(HeadTexture.of(uuid));
} }
@ -40,8 +44,10 @@ public final class SkullBuilder extends AbstractItemBuilder<SkullBuilder> {
* Create a {@link SkullBuilder} with the {@link Player Player's} username. * Create a {@link SkullBuilder} with the {@link Player Player's} username.
* *
* @param username The username of the skull owner. * @param username The username of the skull owner.
* @throws MojangApiException If the Mojang API returns an error.
* @throws IOException If an I/O error occurs.
*/ */
public SkullBuilder(@NotNull String username) { public SkullBuilder(@NotNull String username) throws MojangApiException, IOException {
this(HeadTexture.of(username)); this(HeadTexture.of(username));
} }
@ -128,9 +134,11 @@ public final class SkullBuilder extends AbstractItemBuilder<SkullBuilder> {
* *
* @param offlinePlayer The skull owner. * @param offlinePlayer The skull owner.
* @return The {@link HeadTexture} of that player. * @return The {@link HeadTexture} of that player.
* @throws MojangApiException If the Mojang API returns an error.
* @throws IOException If an I/O error occurs.
* @see HeadTexture#of(UUID) * @see HeadTexture#of(UUID)
*/ */
public static HeadTexture of(@NotNull OfflinePlayer offlinePlayer) { public static @NotNull HeadTexture of(@NotNull OfflinePlayer offlinePlayer) throws MojangApiException, IOException {
return of(offlinePlayer.getUniqueId()); return of(offlinePlayer.getUniqueId());
} }
@ -144,20 +152,28 @@ public final class SkullBuilder extends AbstractItemBuilder<SkullBuilder> {
* *
* @param playerName The username of the player. * @param playerName The username of the player.
* @return The {@link HeadTexture} of that player. * @return The {@link HeadTexture} of that player.
* @throws MojangApiException If the Mojang API returns an error.
* @throws IOException If an I/O error occurs.
* @see HeadTexture#of(UUID) * @see HeadTexture#of(UUID)
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static HeadTexture of(@NotNull String playerName) { public static @NotNull HeadTexture of(@NotNull String playerName) throws MojangApiException, IOException {
if (Bukkit.getServer().getOnlineMode()) { if (Bukkit.getServer().getOnlineMode()) {
// if the server is in online mode, the Minecraft UUID cache (usercache.json) can be used // if the server is in online mode, the Minecraft UUID cache (usercache.json) can be used
return of(Bukkit.getOfflinePlayer(playerName).getUniqueId()); return of(Bukkit.getOfflinePlayer(playerName).getUniqueId());
} else { } else {
// the server isn't in online mode - the UUID has to be retrieved from the Mojang API // the server isn't in online mode - the UUID has to be retrieved from the Mojang API
try { try {
return of(uuidCache.get(playerName, () -> MojangApiUtils.getCurrentUUID(playerName))); return of(uuidCache.get(playerName, () -> MojangApiUtils.getCurrentUuid(playerName)));
} catch (ExecutionException e) { } catch (ExecutionException e) {
e.printStackTrace(); Throwable cause = e.getCause();
return null; if (cause instanceof MojangApiException) {
throw (MojangApiException) cause;
} else if (cause instanceof IOException) {
throw (IOException) cause;
} else {
throw new RuntimeException(cause);
}
} }
} }
} }
@ -169,13 +185,21 @@ public final class SkullBuilder extends AbstractItemBuilder<SkullBuilder> {
* *
* @param uuid The {@link UUID} of the skull owner. * @param uuid The {@link UUID} of the skull owner.
* @return The {@link HeadTexture} of that player. * @return The {@link HeadTexture} of that player.
* @throws MojangApiException If the Mojang API returns an error.
* @throws IOException If an I/O error occurs.
*/ */
public static HeadTexture of(@NotNull UUID uuid) { public static @NotNull HeadTexture of(@NotNull UUID uuid) throws MojangApiException, IOException {
try { try {
return new HeadTexture(textureCache.get(uuid, () -> MojangApiUtils.getSkinData(uuid, false)[0])); return new HeadTexture(textureCache.get(uuid, () -> MojangApiUtils.getSkinData(uuid, false)[0]));
} catch (ExecutionException e) { } catch (ExecutionException e) {
e.printStackTrace(); Throwable cause = e.getCause();
return null; if (cause instanceof MojangApiException) {
throw (MojangApiException) cause;
} else if (cause instanceof IOException) {
throw (IOException) cause;
} else {
throw new RuntimeException(cause);
}
} }
} }

@ -10,13 +10,12 @@ import java.io.Reader;
import java.net.URL; import java.net.URL;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings("deprecation")
public class MojangApiUtils { public class MojangApiUtils {
private static final String SKIN_DATA_URL = "https://sessionserver.mojang.com/session/minecraft/profile/%s?unsigned=%s"; private static final String SKIN_DATA_URL = "https://sessionserver.mojang.com/session/minecraft/profile/%s?unsigned=%s";
private static final String NAME_AT_TIME_URL = "https://api.mojang.com/users/profiles/minecraft/%s?at=%s"; private static final String NAME_AT_TIME_URL = "https://api.mojang.com/users/profiles/minecraft/%s?at=%s";
public static String[] getSkinData(UUID uuid, boolean requestSignature) throws IOException { public static String[] getSkinData(UUID uuid, boolean requestSignature) throws MojangApiException, IOException {
String url = String.format(SKIN_DATA_URL, uuid, !requestSignature); String url = String.format(SKIN_DATA_URL, uuid, !requestSignature);
Reader reader = new InputStreamReader(new URL(url).openConnection().getInputStream()); Reader reader = new InputStreamReader(new URL(url).openConnection().getInputStream());
JsonObject jsonObject = new JsonParser().parse(reader).getAsJsonObject(); JsonObject jsonObject = new JsonParser().parse(reader).getAsJsonObject();
@ -33,11 +32,11 @@ public class MojangApiUtils {
return null; return null;
} }
public static UUID getCurrentUUID(String name) throws IOException { public static UUID getCurrentUuid(String name) throws MojangApiException, IOException {
return getUuidAtTime(name, System.currentTimeMillis() / 1000); return getUuidAtTime(name, System.currentTimeMillis() / 1000);
} }
public static UUID getUuidAtTime(String name, long timestamp) throws IOException { public static UUID getUuidAtTime(String name, long timestamp) throws MojangApiException, IOException {
String url = String.format(NAME_AT_TIME_URL, name, timestamp); String url = String.format(NAME_AT_TIME_URL, name, timestamp);
Reader reader = new InputStreamReader(new URL(url).openConnection().getInputStream()); Reader reader = new InputStreamReader(new URL(url).openConnection().getInputStream());
JsonObject jsonObject = new JsonParser().parse(reader).getAsJsonObject(); JsonObject jsonObject = new JsonParser().parse(reader).getAsJsonObject();
@ -56,17 +55,21 @@ public class MojangApiUtils {
} }
private static void checkForError(JsonObject jsonObject) throws MojangApiException { private static void checkForError(JsonObject jsonObject) throws MojangApiException {
if (jsonObject.has("error") && jsonObject.has("errorMessage")) { if (jsonObject.has("error"))
if (jsonObject.has("errorMessage")) throw new MojangApiException(jsonObject);
throw new MojangApiException(jsonObject.get("errorMessage").getAsString());
else throw new MojangApiException("");
}
} }
public static class MojangApiException extends IOException { public static class MojangApiException extends Exception {
public MojangApiException(String message) { private final JsonObject response;
super(message);
public MojangApiException(JsonObject response) {
super(response.has("errorMessage") ? response.get("errorMessage").getAsString() : "");
this.response = response;
}
public JsonObject getResponse() {
return response;
} }
} }