diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java b/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java
new file mode 100644
index 00000000..cd8b0466
--- /dev/null
+++ b/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java
@@ -0,0 +1,32 @@
+package net.hypixel.api.data.type;
+
+/**
+ * Types of achievements that can be earned by guilds on Hypixel.
+ *
+ * Created using slothpixel/hypixelconstants
+ * as a reference.
+ */
+public enum GuildAchievement {
+ /**
+ * A tiered achievement based on the highest amount of experience earned by a guild in a single
+ * day.
+ */
+ EXPERIENCE_KINGS,
+
+ /**
+ * A tiered achievement based on the highest number of members a guild has had online at the
+ * same time.
+ */
+ ONLINE_PLAYERS,
+
+ /**
+ * A tiered achievement based on a guild's highest level.
+ */
+ PRESTIGE,
+
+ /**
+ * A tiered achievement based on the highest number of combined wins (in mini-games) between
+ * members of a guild on the same day.
+ */
+ WINNERS
+}
diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java b/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java
index 862079f4..e23cfbc4 100644
--- a/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java
+++ b/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java
@@ -1,12 +1,23 @@
package net.hypixel.api.reply;
-import net.hypixel.api.util.Banner;
-
+import com.google.gson.annotations.SerializedName;
+import java.time.LocalDate;
import java.time.ZonedDateTime;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.UUID;
+import net.hypixel.api.data.type.GameType;
+import net.hypixel.api.data.type.GuildAchievement;
+import net.hypixel.api.reply.PlayerReply.Player;
+import net.hypixel.api.util.Banner;
+// Suppressed because most fields are assigned by Gson via reflection.
+@SuppressWarnings({"unused", "RedundantSuppression", "MismatchedQueryAndUpdateOfCollection"})
public class GuildReply extends AbstractReply {
+
private Guild guild;
public Guild getGuild() {
@@ -16,127 +27,525 @@ public Guild getGuild() {
@Override
public String toString() {
return "GuildReply{" +
- "guild=" + guild +
- "} " + super.toString();
+ "guild=" + guild +
+ "} " + super.toString();
}
public static class Guild {
- private String _id;
+ // Unclear/unconventionally named fields.
+ @SerializedName("_id")
+ private String id;
+ @SerializedName("created")
+ private ZonedDateTime creationDate;
+ @SerializedName("exp")
+ private long experience;
+ @SerializedName("publiclyListed")
+ private boolean isPubliclyListed;
+ @SerializedName("joinable")
+ private boolean isJoinable;
+
+ // If any of these variables change names, make sure to include a @SerializedName("...").
private String name;
private String description;
private String tag;
private String tagColor;
- private Boolean publiclyListed;
private Banner banner;
private List members;
+ private List ranks;
+ private List preferredGames;
+ private Map guildExpByGameType;
+ private Map achievements;
private int coins;
private int coinsEver;
- private ZonedDateTime created;
- private Boolean joinable;
- private long exp;
- private int legacyRanking;
+ private Integer legacyRanking; // Nullable so that non-ranked guilds don't appear as #1.
+ /**
+ * The unique BSON ObjectId that represents the guild. This should not change during the
+ * guild's lifetime.
+ *
+ * @return the guild's main identifier.
+ * @see ObjectId
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #getId()}.
+ */
+ @Deprecated
public String get_id() {
- return _id;
+ return getId();
}
+ /**
+ * The guild's main display name. This is subject to change at any time.
+ *
+ * @return the guild's display name.
+ */
public String getName() {
return name;
}
+ /**
+ * A short, optional string set by a privileged member of the guild, and displayed in the
+ * in-game guild finder.
+ *
+ * @return the guild's description, or {@code null} if none has been set.
+ */
public String getDescription() {
return description;
}
+ /**
+ * The date when the guild was created. If the guild has been disbanded and recreated in the
+ * past, this is the date when the guild was most recently created.
+ *
+ * @return the date when the guild was created.
+ */
+ public ZonedDateTime getCreationDate() {
+ return creationDate;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #getCreationDate()}.
+ */
+ @Deprecated
+ public ZonedDateTime getCreated() {
+ return getCreationDate();
+ }
+
+ /**
+ * A short string displayed in-game after the names of members of the guild.
+ *
+ * @return the guild's tag, or {@code null} if the guild does not have one (or if it has not
+ * been set).
+ */
public String getTag() {
return tag;
}
+ /**
+ * A Minecraft color code indicating the color of the guild's {@link #getTag() tag}. If this
+ * returns {@code null} but the guild does have a tag, then the color is assumed to be
+ * "{@code GRAY}" (without quotes).
+ *
+ * @return the name of a Minecraft color code (all uppercase), or {@code null} if the guild
+ * has never changed its tag's color.
+ * @see Color codes
+ * table (uses lowercase names)
+ */
public String getTagColor() {
return tagColor;
}
- public Boolean getPubliclyListed() {
- return publiclyListed;
- }
-
+ /**
+ * The Minecraft-style banner displayed on the guild's hypixel.net website profile.
+ *
+ * @return the guild's banner, or {@code null} if none has been set.
+ */
public Banner getBanner() {
return banner;
}
+ /**
+ * Information about the Hypixel players who are currently members of the guild (at the time
+ * the {@code Guild} object was fetched from the API).
+ *
+ * @return an immutable list of all of the guild's members.
+ */
public List getMembers() {
- return members;
+ return members == null
+ ? Collections.emptyList()
+ : Collections.unmodifiableList(members);
}
- public int getCoins() {
- return coins;
+ /**
+ * A list of permission groups created within the guild.
+ *
+ * @return an immutable list of the guild's ranks. May be empty.
+ * @apiNote This list may not be exhaustive, and typically only includes user-generated
+ * ranks. Built-in ranks, and pre-guild-update ranks may not be included in this list,
+ * despite being valid values for a member's {@link Member#getRank() rank} field. Extraneous
+ * rank names include:
+ *
+ * - {@code Guild Master} - Post-guild-update; full privileges
+ * - {@code GUILDMASTER} - Pre-guild-update; full privileges
+ * - {@code OFFICER} - Pre-guild-update; elevated privileges
+ * - {@code MEMBER} - Pre-guild-update; normal privileges
+ *
+ */
+ public List getRanks() {
+ return ranks == null
+ ? Collections.emptyList()
+ : Collections.unmodifiableList(ranks);
}
- public int getCoinsEver() {
- return coinsEver;
+ /**
+ * A list of games that can be used to search for the guild via the in-game guild finder.
+ * Typically, this list represents the games that the guild considers their main focus.
+ *
+ * @return an immutable list of the guild's preferred games. May be empty.
+ */
+ public List getPreferredGames() {
+ return preferredGames == null
+ ? Collections.emptyList()
+ : Collections.unmodifiableList(preferredGames);
}
- public ZonedDateTime getCreated() {
- return created;
+ /**
+ * Retrieves the total amount of {@link #getExperience() experience} that the guild has
+ * earned from a particular game.
+ *
+ * @param game The game to retrieve experience for.
+ * @return the amount of XP earned by the guild for the specified {@code game}.
+ * @throws IllegalArgumentException if the provided {@code game} is {@code null}.
+ */
+ public int getExperienceForGame(GameType game) {
+ if (game == null) {
+ throw new IllegalArgumentException("Cannot get XP for null GameType");
+ }
+
+ return Optional.ofNullable(guildExpByGameType)
+ .map(expByGame -> expByGame.get(game))
+ .orElse(0);
}
- public Boolean getJoinable() {
- return joinable;
+ /**
+ * Retrieves the guild's high-score for a specific guild achievement. The meaning of "score"
+ * varies between achievements, and can be found in the documentation for the desired {@link
+ * GuildAchievement}.
+ *
+ * @param achievement the achievement to get the high-score of.
+ * @return the guild's high-score for the provided achievement.
+ */
+ public int getAchievementHighScore(GuildAchievement achievement) {
+ if (achievement == null) {
+ throw new IllegalArgumentException("Cannot get high-score for null achievement");
+ }
+ return Optional.ofNullable(achievements)
+ .map(highScores -> highScores.get(achievement))
+ .orElse(0);
+ }
+
+ /**
+ * The total amount of experience earned by the guild's members. This is different from a
+ * player's {@link Player#getNetworkExp() network experience}, which is independent of the
+ * guild system.
+ *
+ * @return the guild's total experience count.
+ */
+ public long getExperience() {
+ return experience;
}
+ /**
+ * @deprecated Renamed to {@link #getExperience()}.
+ */
+ @Deprecated
public long getExp() {
- return exp;
+ return getExperience();
+ }
+
+ /**
+ * Whether or not the guild can be discovered via the in-game guild finder.
+ *
+ * @return whether or not the guild is listed publicly.
+ */
+ public boolean isPubliclyListed() {
+ return isPubliclyListed;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #isPubliclyListed()}.
+ */
+ @Deprecated
+ public Boolean getPubliclyListed() {
+ return isPubliclyListed();
+ }
+
+ /**
+ * Whether or not players can request to join the guild. If {@code false}, players must be
+ * invited by a guild member with appropriate privileges.
+ *
+ * @return whether or not the guild can be joined without an invite.
+ */
+ public boolean isJoinable() {
+ return isJoinable;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #isJoinable()}.
+ */
+ @Deprecated
+ public Boolean getJoinable() {
+ return isJoinable();
+ }
+
+ /**
+ * The number of coins that the guild had prior to the 2018 guild update (when they were
+ * replaced with {@link #getExperience() guild experience}). Coins were previously used to
+ * purchase cosmetics for guilds (member slots, tags, etc), but now are only stored for
+ * legacy purposes.
+ *
+ * @return the number of coins the guild has.
+ */
+ public int getCoins() {
+ return coins;
+ }
+
+ /**
+ * The total number of coins earned by the guild prior to the 2018 guild update. Unlike
+ * {@link #getCoins()}, this number did not decrease when the guild purchased cosmetics
+ * using coins.
+ *
+ * @return the number of coins earned during the guild's lifetime.
+ * @see #getCoins()
+ */
+ public int getCoinsEver() {
+ return coinsEver;
}
+ /**
+ * The guild's ranking, out of all guilds, in terms of {@link #getCoins() coins} earned
+ * before the 2018 guild update. The lowest place is {@code 1} (meaning 1st place) for
+ * guilds that this applies to. For guilds created after the update, {@code -1} is
+ * returned.
+ *
+ * @return the guild's position on the legacy coin leaderboard, or {@code -1} if the guild
+ * was created after the guild update.
+ * @see #getCoins()
+ * @see #getCoinsEver()
+ */
public int getLegacyRanking() {
- return legacyRanking;
+ return Optional.ofNullable(legacyRanking)
+ .map(ranking -> ranking + 1)
+ .orElse(-1);
}
@Override
public String toString() {
return "Guild{" +
- "_id='" + _id + '\'' +
- ", name='" + name + '\'' +
- ", description='" + description + '\'' +
- ", tag='" + tag + '\'' +
- ", tagColor='" + tagColor + '\'' +
- ", publiclyListed=" + publiclyListed +
- ", banner=" + banner +
- ", members=" + members +
- ", coins=" + coins +
- ", coinsEver=" + coinsEver +
- ", created=" + created +
- ", joinable=" + joinable +
- ", exp=" + exp +
- ", legacyRanking=" + legacyRanking +
- '}';
+ "id='" + id + '\'' +
+ ", name='" + name + '\'' +
+ ", description='" + description + '\'' +
+ ", creationDate=" + creationDate +
+ ", tag='" + tag + '\'' +
+ ", tagColor='" + tagColor + '\'' +
+ ", banner=" + banner +
+ ", members=" + members +
+ ", ranks=" + ranks +
+ ", experience=" + experience +
+ ", isPubliclyListed=" + isPubliclyListed +
+ ", isJoinable=" + isJoinable +
+ ", coins=" + coins +
+ ", coinsEver=" + coinsEver +
+ ", legacyRanking=" + legacyRanking +
+ '}';
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Guild guild = (Guild) o;
+ return Objects.equals(id, guild.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ /**
+ * Information about a Hypixel player pertaining to their guild.
+ */
public static class Member {
+
private UUID uuid;
private String rank;
- private ZonedDateTime joined;
+ @SerializedName("joined")
+ private ZonedDateTime joinDate;
+ @SerializedName("expHistory")
+ private Map weeklyExperience;
+ /**
+ * The player's Minecraft identifier (version 4 UUID), assigned by Mojang.
+ *
+ * @return the player's UUID.
+ */
public UUID getUuid() {
return uuid;
}
+ /**
+ * The player's permission group in the guild. This rank name may not appear in the
+ * guild's rank list; see {@link Guild#getRanks() here} for details.
+ *
+ * @return the player's guild rank.
+ */
public String getRank() {
return rank;
}
+ /**
+ * The date and time when the player joined the guild. If they have joined and left the
+ * guild previously, this will be the date when they most recently re-joined.
+ *
+ * @return the date when the player joined their guild.
+ */
+ public ZonedDateTime getJoinDate() {
+ return joinDate;
+ }
+
+ /**
+ * Retrieves the amount of guild experience earned by the player on a particular date.
+ * Daily XP information is typically only kept for one week, so results may not be found
+ * for earlier dates.
+ *
+ * @param date The date to get the member's experience earnings for.
+ * @return the amount of guild experience earned by the player on the {@code date}, or
+ * {@code -1} if no total is kept for that day.
+ */
+ public int getExperienceEarned(LocalDate date) {
+ if (date == null) {
+ throw new IllegalArgumentException("Cannot get XP for null date");
+ }
+
+ return Optional.ofNullable(weeklyExperience)
+ .map(expByDate -> expByDate.get(date.toString()))
+ .orElse(-1);
+ }
+
+ /**
+ * @deprecated Renamed to {@link #getJoinDate()}.
+ */
+ @Deprecated
public ZonedDateTime getJoined() {
- return joined;
+ return getJoinDate();
}
@Override
public String toString() {
return "Member{" +
- "uuid=" + uuid +
- ", rank=" + rank +
- ", joined=" + joined +
- '}';
+ "uuid=" + uuid +
+ ", rank='" + rank + '\'' +
+ ", joined=" + joinDate +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Member member = (Member) o;
+ return Objects.equals(uuid, member.uuid);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uuid);
+ }
+ }
+
+ /**
+ * A permission group that can be assigned to members of a Hypixel guild.
+ */
+ public static class Rank {
+
+ private String name;
+ private String tag;
+ private int priority;
+ @SerializedName("default")
+ private boolean isDefault;
+ @SerializedName("created")
+ private ZonedDateTime creationDate;
+
+ /**
+ * The rank's display name, as seen in guild chat and hypixel.net.
+ *
+ * @return the rank's name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * A short string prefixed before the guild-chat messages of members with the rank.
+ *
+ * @return the rank's guild-chat prefix.
+ */
+ public String getChatTag() {
+ return tag;
+ }
+
+ /**
+ * Whether or not the rank is given to members initially upon joining the guild.
+ *
+ * @return a boolean indicating if the rank is the guild's default or not. If no rank in
+ * the guild's list is marked with this, the default is the legacy "{@code MEMBER}" rank
+ * (without quotes).
+ */
+ public boolean isDefault() {
+ return isDefault;
+ }
+
+ /**
+ * The date and time when the rank was added to to the guild.
+ *
+ * @return the rank's creation time.
+ */
+ public ZonedDateTime getCreationDate() {
+ return creationDate;
+ }
+
+ /**
+ * The rank's order in the guild's rank hierarchy. Members with appropriate permissions
+ * cannot modify those of a rank with a higher priority than their own.
+ *
+ * @return the rank's permission priority.
+ * @apiNote Higher Priority = Higher Privilege (and vice-versa)
+ */
+ public int getPriority() {
+ return priority;
+ }
+
+ @Override
+ public String toString() {
+ return "Rank{" +
+ "name='" + name + '\'' +
+ ", tag='" + tag + '\'' +
+ ", isDefault=" + isDefault +
+ ", creationDate=" + creationDate +
+ ", priority=" + priority +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Rank rank = (Rank) o;
+ return Objects.equals(name, rank.name) &&
+ Objects.equals(creationDate, rank.creationDate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, creationDate);
}
}
}
diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java b/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java
index e1cd9e4e..11b2cbae 100644
--- a/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java
+++ b/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java
@@ -1,42 +1,142 @@
package net.hypixel.api.util;
import com.google.gson.annotations.SerializedName;
-
+import java.util.Collections;
import java.util.List;
+import java.util.Objects;
+/**
+ * A Minecraft-style banner design.
+ *
+ *
+ * Color Code Reference
+ *
+ * - {@code 0}: Black
+ * - {@code 1}: Red
+ * - {@code 2}: Green
+ * - {@code 3}: Brown
+ * - {@code 4}: Blue
+ * - {@code 5}: Purple
+ * - {@code 6}: Cyan
+ * - {@code 7}: Silver (Light Grey)
+ * - {@code 8}: Grey (Dark Grey)
+ * - {@code 9}: Pink
+ * - {@code 10}: Lime
+ * - {@code 11}: Yellow
+ * - {@code 12}: Light Blue
+ * - {@code 13}: Magenta
+ * - {@code 14}: Orange
+ * - {@code 15}: White
+ *
+ * These numeric color codes are returned by the following methods:
+ *
+ * - {@link #getBase()}
+ * - {@link Pattern#getColor()}
+ *
+ *
+ * @see Banner (Minecraft Wiki)
+ */
public class Banner {
@SerializedName("Base")
- private String base;
+ private String baseColor;
@SerializedName("Patterns")
private List patterns;
+ /**
+ * An integer (wrapped in a string) indicating the background/base color of the banner. See the
+ * linked cheat-sheet for a list of possible values.
+ *
+ * @return the banner's background color.
+ * @see Color code cheat-sheet
+ */
+ public String getBaseColor() {
+ return baseColor;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #getBaseColor()}.
+ */
+ @Deprecated
public String getBase() {
- return base;
+ return getBaseColor();
}
+ /**
+ * The shapes that compose the banner, minus the {@link #getBaseColor() base/background layer}.
+ * Patterns in the list are ordered from background to foreground, meaning that the last pattern
+ * in the list will always be displayed on top.
+ *
+ * @return an immutable list of the banner's layers.
+ */
public List getPatterns() {
- return patterns;
+ return patterns == null
+ ? Collections.emptyList()
+ : Collections.unmodifiableList(patterns);
}
@Override
public String toString() {
return "Banner{" +
- "base='" + base + '\'' +
- ", patterns=" + patterns +
- '}';
+ "baseColor='" + baseColor + '\'' +
+ ", patterns=" + patterns +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Banner banner = (Banner) o;
+ return Objects.equals(baseColor, banner.baseColor) &&
+ Objects.equals(patterns, banner.patterns);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(baseColor, patterns);
}
+ /**
+ * A colored shape that makes up a layer of a {@link Banner} design.
+ */
public static class Pattern {
+
@SerializedName("Pattern")
- private String pattern;
+ private String type;
@SerializedName("Color")
private String color;
+ /**
+ * A short identifier indicating the shape to be used for the layer. See the link below for
+ * each type's identifier.
+ *
+ * @return the pattern's type identifier.
+ * @see Pattern identifiers
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @deprecated Renamed to {@link #getType()}.
+ */
+ @Deprecated
public String getPattern() {
- return pattern;
+ return getType();
}
+ /**
+ * An integer (wrapped in a string) indicating the color used to draw the pattern's shape.
+ * See the linked cheat-sheet for a list of possible values.
+ *
+ * @return the pattern's color.
+ * @see Banner Color code cheat-sheet
+ */
public String getColor() {
return color;
}
@@ -44,9 +144,27 @@ public String getColor() {
@Override
public String toString() {
return "Pattern{" +
- "pattern='" + pattern + '\'' +
- ", color='" + color + '\'' +
- '}';
+ "type='" + type + '\'' +
+ ", color='" + color + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Pattern pattern = (Pattern) o;
+ return Objects.equals(type, pattern.type) &&
+ Objects.equals(color, pattern.color);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, color);
}
}
}
diff --git a/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java b/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java
index 94190af6..38c15f18 100644
--- a/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java
+++ b/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java
@@ -17,6 +17,7 @@ public class ExampleUtil {
}
public static final UUID HYPIXEL = UUID.fromString("f7c77d99-9f15-4a66-a87d-c4a51ef30d19");
+ public static final String GUILD_ID = "53bd67d7ed503e868873eceb";
/**
* Keep the program alive till we explicitly exit.
diff --git a/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java b/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java
index 91997b7c..45f96ff7 100644
--- a/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java
+++ b/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java
@@ -1,8 +1,263 @@
package net.hypixel.api.example;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import net.hypixel.api.HypixelAPI;
+import net.hypixel.api.data.type.GameType;
+import net.hypixel.api.data.type.GuildAchievement;
+import net.hypixel.api.reply.GuildReply;
+import net.hypixel.api.reply.GuildReply.Guild;
+import net.hypixel.api.reply.GuildReply.Guild.Member;
+import net.hypixel.api.reply.GuildReply.Guild.Rank;
+import net.hypixel.api.util.IGuildLeveling;
+
+/**
+ * A sample app for demonstrating how guilds can be fetched & used from the Hypixel API.
+ */
public class GetGuildExample {
+
public static void main(String[] args) {
- ExampleUtil.API.getGuildByPlayer(ExampleUtil.HYPIXEL).whenComplete(ExampleUtil.getTestConsumer());
- ExampleUtil.await();
+ /*
+ * Make sure you have a HypixelAPI object set up. You can see how this is done by going to
+ * the ExampleUtil class.
+ *
+ * See the finally{} block below for how to shutdown this API once you're all done.
+ */
+ HypixelAPI api = ExampleUtil.API;
+
+ /*
+ * Skip below the try/catch/finally block to see how this is used.
+ */
+ GuildReply apiReply;
+
+ try {
+ /*
+ * We'll be fetching the guild's stats using its ID for this example, but guilds can
+ * also be looked up using their name, or one of their members' Minecraft UUIDs.
+ * - HypixelAPI.getGuildByName(String)
+ * - HypixelAPI.getGuildByPlayer(UUID)
+ */
+ String guildId = ExampleUtil.GUILD_ID;
+
+ /*
+ * Here, we store the response from the API in our variable.
+ *
+ * We call `.get()` at the end so that we can use the reply in the same thread.
+ * The downside is that the current thread freezes (or "blocks") until the API responds.
+ * If this is a problem for you, instead use:
+ *
+ * .whenComplete((apiReply, error) -> {
+ * // Do something with apiReply (in a different thread)...
+ * });
+ *
+ * But for a simple command-line app like this one, `.get()` will do the job.
+ */
+ apiReply = api.getGuildById(guildId).get();
+
+ } catch (ExecutionException e) {
+ System.err.println("Oh no, our API request failed!");
+
+ /*
+ * If an ExecutionException is thrown, it's typically because of an API error.
+ * Use `getCause()` to determine what the actual problem is.
+ */
+ e.getCause().printStackTrace();
+ return;
+
+ } catch (InterruptedException e) {
+ // Shouldn't happen under normal circumstances.
+ System.err.println("Oh no, the guild fetch thread was interrupted!");
+ e.printStackTrace();
+ Thread.currentThread().interrupt();
+ return;
+
+ } finally {
+ /*
+ * Once you're finished with all your requests, you can shutdown your HypixelAPI object.
+ *
+ * If your app is meant to run continuously, you probably don't want to do this until
+ * the app is stopped/closed. For this example though, we only need the one request.
+ */
+ api.shutdown();
+ }
+
+ /*
+ * Now that we have the guild, we can start to read its information and stats!
+ */
+ Guild guild = apiReply.getGuild();
+
+ // ===================================================
+ // Check out the methods referenced below to see how
+ // each type of stat is retrieved! (their code can be
+ // found further down in this file)
+ // ===================================================
+
+ /*
+ * First we'll display some basic information about the guild, like its name, tag,
+ * description, and level.
+ */
+ printGuildSummary(guild);
+ System.out.println();
+
+ /*
+ * After that, we'll print the guild's high-score for each tiered guild achievement.
+ */
+ printAchievementScores(guild);
+ System.out.println();
+
+ /*
+ * Then we'll display how much experience the guild has earned from each game on Hypixel,
+ * as well as an overall total.
+ */
+ printGuildXpPerGame(guild);
+ System.out.println();
+
+ /*
+ * Next, we'll print some info about each of the guild's ranks, if it has any.
+ */
+ List ranks = guild.getRanks();
+ if (!ranks.isEmpty()) {
+ printGuildRanks(ranks);
+ System.out.println();
+ }
+
+ /*
+ * Finally, we'll print some information about each member in the guild.
+ *
+ * This might print out A LOT, so you may want to comment the following line out if you're
+ * focusing on some of the guild's other info.
+ */
+ printGuildMembers(guild.getMembers());
+ }
+
+ private static void printGuildSummary(Guild guild) {
+ /*
+ * First, we'll print the guild's name. If it also has a tag, we'll print that on the same
+ * line.
+ */
+ System.out.print(guild.getName());
+ if (guild.getTag() != null) {
+ System.out.print(" [" + guild.getTag() + "]");
+ }
+ System.out.println();
+
+ int guildLevel = (int) IGuildLeveling.getLevel(guild.getExperience());
+
+ System.out.println("\tID: " + guild.getId());
+ System.out.println("\tLevel: " + guildLevel);
+ System.out.println("\tCreated At: " + guild.getCreationDate());
+ System.out.println("\tDescription: \"" + guild.getDescription() + '"');
+ System.out.println("\tGames: " + guild.getPreferredGames());
+ System.out.println("\tBanner: " + guild.getBanner());
+ }
+
+ private static void printAchievementScores(Guild guild) {
+ System.out.println("Guild Achievement High-Scores");
+
+ /*
+ * Displays the guild's high-score for each tiered achievement. The meaning of "score"
+ * varies between achievements, but an explanation for each can be found in the
+ * `GuildAchievement` class.
+ */
+ for (GuildAchievement achievement : GuildAchievement.values()) {
+ int highScore = guild.getAchievementHighScore(achievement);
+ System.out.println("\t" + achievement + ": " + highScore);
+ }
+ }
+
+ private static void printGuildXpPerGame(Guild guild) {
+ System.out.println("Guild XP Breakdown");
+
+ /*
+ * This line prints the guild's total experience from all games.
+ */
+ System.out.println("\tOVERALL: " + guild.getExperience());
+
+ /*
+ * Then we loop through each game and see how much experience the guild's earned from it.
+ */
+ for (GameType game : GameType.values()) {
+ int experienceForGame = guild.getExperienceForGame(game);
+ System.out.println("\t" + game.getName() + ": " + experienceForGame);
+ }
+ }
+
+ private static void printGuildRanks(List ranks) {
+ System.out.println("Ranks (" + ranks.size() + " total)");
+
+ /*
+ * This just sorts the list in reverse order by priority, so that higher-level ranks (like
+ * officer) are printed before lower-level ones (like member).
+ *
+ * The first line copies the list beforehand, because `Guild.getRanks()` returns an
+ * immutable (unmodifiable) list that can't be altered (including sorting).
+ */
+ ranks = new ArrayList<>(ranks);
+ ranks.sort(Comparator.comparingInt(Rank::getPriority).reversed());
+
+ for (Rank rank : ranks) {
+ /*
+ * Here we print the rank's name. If it also has a chat tag, we print that on the
+ * same line.
+ */
+ System.out.print("\t" + rank.getName());
+ if (rank.getChatTag() != null) {
+ System.out.print(" [" + rank.getChatTag() + "]");
+ }
+ System.out.println();
+
+ System.out.println("\t\tPriority: " + rank.getPriority());
+ System.out.println("\t\tCreated at " + rank.getCreationDate());
+ }
+ }
+
+ private static void printGuildMembers(List members) {
+ System.out.println("Members (" + members.size() + " total)");
+
+ for (Member member : members) {
+ /*
+ * First we'll print some basic information about each member.
+ *
+ * Notice how we only have the member's UUID. If you want to get their name, you'll have
+ * to make a separate request to the API using this UUID. See the GetPlayerExample class
+ * for an example of that.
+ */
+ System.out.println("\tUUID: " + member.getUuid());
+ System.out.println("\tRank: " + member.getRank());
+ System.out.println("\tJoin date: " + member.getJoinDate());
+
+ /*
+ * Then, we'll print how much guild experience they earned for the last 7 days. We'll
+ * sum up these daily totals to print an overall (weekly) total at the end.
+ *
+ * The code for the `getWeekDates()` function can be found at the bottom of the class.
+ */
+ int weeklyExp = 0;
+ System.out.println("\tWeekly Exp: ");
+ for (LocalDate date : getWeekDates()) {
+ int dailyExp = member.getExperienceEarned(date);
+ weeklyExp += dailyExp;
+
+ // ": "
+ System.out.println("\t\t" + date + ": " + dailyExp);
+ }
+ System.out.println("\t\tWeekly Total: " + weeklyExp);
+ System.out.println();
+ }
+ }
+
+ /*
+ * Returns an array containing the date for each of the past 7 days (including today).
+ * We use this to get each member's weekly experience by day (see `main` method above).
+ */
+ private static LocalDate[] getWeekDates() {
+ LocalDate[] week = new LocalDate[7];
+ for (int i = 0; i < 7; i++) {
+ week[i] = LocalDate.now().minusDays(i);
+ }
+ return week;
}
}