Skip to content

Commit

Permalink
Add player object (#260)
Browse files Browse the repository at this point in the history
* Wrap player object in class

* Add utility methods to player

* Add javadocs for player object

* Add javadocs for property accessors

* Add get level method to player

* Update examples

* Fix incorrect network exp

* Use getLongProperty instead of getNumberProperty.longValue

* Use fallback when displayname is not present

* Fix exp calculation

Co-authored-by: mdashlw <[email protected]>

* Add method for recent GameType

* Add method for PetStats

* Add methods to check player api visibility

* Add rank color & mc version methods to player

* Fix incorrect javadocs

* Fix javadoc typo

* Remove methods that access player settings

* Add public constructor to Player

* Check for exception in GetPlayerExample

* Return UUID instead of String from getUuid

* Move GSON into Utilities

* Clarify getUuid javadoc

Co-authored-by: Noe <[email protected]>

* Change getPlusColor to getSelectedPlusColor

* Explicitly exit in GetPlayerExample

* Clean up uuidFromString

Co-authored-by: Noe <[email protected]>

* Add hasProperty() to Player

* Add ComplexHypixelObject for property methods

* Remove extra parenthesis

* Simplify uuidFromString

* Begin property filter

* Let keys be removed from filter

* Check for null keys

* Document PropertyFilter

* Overload player fetch methods w/ filters

* Allow batch filtering

* Detect & fix key collisions

* Respect escapes when applying

* Respect escapes in #getProperty(...)

* Apply suggestions from code review

Co-authored-by: Noe <[email protected]>

* Make raw non-null

* Change "complex" to "unstable"

* Only compile key splitter once

* Private constructor & final for Utilities

* Remove redundant getProperty() logic

* More getProperty() simplifying

* Change with() to including()

* Remove "keys" from method names

* Clarify property javadocs

* Update exists() check

* Formatting & example change

* Fix null players & flip filter/object dependence

* Clarify documentation for players

* Use ZonedDateTime instead of Date

* Use a more informative example

* Add a note about getRaw()

* Suppression on lazily assigned field

* Change toString() for null players

* Fix broken import

Co-authored-by: mdashlw <[email protected]>
Co-authored-by: Noe <[email protected]>
Co-authored-by: Connor Linfoot <[email protected]>
  • Loading branch information
4 people authored Jul 26, 2021
1 parent 85feb8b commit d6f3895
Show file tree
Hide file tree
Showing 14 changed files with 1,019 additions and 43 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ the [Example Code](https://github.com/HypixelDev/PublicAPI/tree/master/hypixel-a
#### Hypixel Maven Repo

```xml

<repository>
<id>Hypixel</id>
<url>https://repo.hypixel.net/repository/Hypixel/</url>
Expand Down
59 changes: 41 additions & 18 deletions hypixel-api-core/src/main/java/net/hypixel/api/HypixelAPI.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
package net.hypixel.api;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.hypixel.api.adapters.*;
import net.hypixel.api.data.type.GameType;
import net.hypixel.api.data.type.ServerType;
import net.hypixel.api.exceptions.BadResponseException;
import net.hypixel.api.exceptions.BadStatusCodeException;
import net.hypixel.api.http.HTTPQueryParams;
import net.hypixel.api.http.HypixelHttpClient;
import net.hypixel.api.http.HypixelHttpResponse;
import net.hypixel.api.reply.*;
import net.hypixel.api.reply.skyblock.*;
import net.hypixel.api.util.PropertyFilter;
import net.hypixel.api.util.ResourceType;
import net.hypixel.api.util.Utilities;

import java.time.ZonedDateTime;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

public class HypixelAPI {

private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter())
.registerTypeAdapter(GameType.class, new GameTypeTypeAdapter())
.registerTypeAdapter(ServerType.class, new ServerTypeTypeAdapter())
.registerTypeAdapter(ZonedDateTime.class, new DateTimeTypeAdapter())
.registerTypeAdapterFactory(new BoostersTypeAdapterFactory<>(BoostersReply.Booster.class))
.create();
private static final String BASE_URL = "https://api.hypixel.net/";

private final HypixelHttpClient httpClient;
Expand Down Expand Up @@ -81,6 +69,31 @@ public CompletableFuture<PlayerReply> getPlayerByUuid(String player) {
);
}

/**
* Same as {@link #getPlayerByUuid(UUID)}, but the resulting player object will only contain
* properties explicitly included via a {@link PropertyFilter filter}.
*/
public CompletableFuture<PlayerReply> getPlayerByUuid(UUID player, PropertyFilter filter) {
return applyFilterFuture(getPlayerByUuid(player), filter);
}

/**
* Same as {@link #getPlayerByUuid(String)}, but the resulting player object will only contain
* properties explicitly included via a {@link PropertyFilter filter}.
*/
public CompletableFuture<PlayerReply> getPlayerByUuid(String player, PropertyFilter filter) {
return applyFilterFuture(getPlayerByUuid(player), filter);
}

/**
* Same as {@link #getPlayerByName(String)}, but the resulting player object will only contain
* properties explicitly included via a {@link PropertyFilter filter}.
*/
@Deprecated
public CompletableFuture<PlayerReply> getPlayerByName(String player, PropertyFilter filter) {
return applyFilterFuture(getPlayerByName(player), filter);
}

/**
* @param player the minecraft username of the player.
* @return {@link CompletableFuture} containing {@link PlayerReply}
Expand Down Expand Up @@ -257,6 +270,16 @@ public CompletableFuture<SkyBlockBazaarReply> getSkyBlockBazaar() {
return get(SkyBlockBazaarReply.class, "skyblock/bazaar");
}

/**
* Applies a {@code filter} to a player object when it is received in an API response.
*/
private CompletableFuture<PlayerReply> applyFilterFuture(CompletableFuture<PlayerReply> future, PropertyFilter filter) {
return future.thenApply(reply -> {
reply.getPlayer().filter(filter);
return reply;
});
}

private <R extends AbstractReply> CompletableFuture<R> get(Class<R> clazz, String request) {
return get(clazz, request, null);
}
Expand All @@ -270,16 +293,16 @@ private <R extends AbstractReply> CompletableFuture<R> get(Class<R> clazz, Strin
.thenApply(this::checkResponse)
.thenApply(response -> {
if (clazz == ResourceReply.class) {
return checkReply((R) new ResourceReply(GSON.fromJson(response.getBody(), JsonObject.class)));
return checkReply((R) new ResourceReply(Utilities.GSON.fromJson(response.getBody(), JsonObject.class)));
}
return checkReply(GSON.fromJson(response.getBody(), clazz));
return checkReply(Utilities.GSON.fromJson(response.getBody(), clazz));
});
}

private CompletableFuture<ResourceReply> requestResource(String resource) {
return httpClient.makeRequest(BASE_URL + "resources/" + resource)
.thenApply(this::checkResponse)
.thenApply(response -> checkReply(new ResourceReply(GSON.fromJson(response.getBody(), JsonObject.class))));
.thenApply(response -> checkReply(new ResourceReply(Utilities.GSON.fromJson(response.getBody(), JsonObject.class))));
}

/**
Expand All @@ -292,7 +315,7 @@ private HypixelHttpResponse checkResponse(HypixelHttpResponse response) {

String cause;
try {
cause = GSON.fromJson(response.getBody(), JsonObject.class).get("cause").getAsString();
cause = Utilities.GSON.fromJson(response.getBody(), JsonObject.class).get("cause").getAsString();
} catch (JsonSyntaxException ignored) {
cause = "Unknown (body is not json)";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.hypixel.api.adapters;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import net.hypixel.api.reply.PlayerReply.Player;

import java.io.IOException;

public class PlayerTypeAdapter extends TypeAdapter<Player> {

private final TypeAdapter<JsonElement> defaultAdapter;

public PlayerTypeAdapter() {
defaultAdapter = new Gson().getAdapter(JsonElement.class);
}

@Override
public void write(JsonWriter out, Player value) throws IOException {
defaultAdapter.write(out, value.getRaw());
}

@Override
public Player read(JsonReader in) throws IOException {
JsonToken type = in.peek();
if (type == JsonToken.NULL) {
in.nextNull();
return new Player(null);
}
return new Player(defaultAdapter.read(in));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.hypixel.api.adapters;

import com.google.gson.*;
import net.hypixel.api.util.Utilities;

import java.lang.reflect.Type;
import java.util.UUID;
Expand All @@ -14,11 +15,6 @@ public JsonElement serialize(UUID src, Type typeOfSrc, JsonSerializationContext

@Override
public UUID deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String uuid = json.getAsString();
if (uuid.contains("-")) {
return UUID.fromString(uuid);
} else {
return UUID.fromString(uuid.substring(0, 8) + "-" + uuid.substring(8, 12) + "-" + uuid.substring(12, 16) + "-" + uuid.substring(16, 20) + "-" + uuid.substring(20, 32));
}
return Utilities.uuidFromString(json.getAsString());
}
}
Loading

0 comments on commit d6f3895

Please sign in to comment.