Skip to content

Commit 0a5defa

Browse files
committed
5. Add mcMMO endpoint
1 parent 26e3448 commit 0a5defa

3 files changed

Lines changed: 187 additions & 0 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package net.earthmc.emcapi.endpoint;
2+
3+
import com.gmail.nossr50.datatypes.player.PlayerProfile;
4+
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
5+
import com.google.gson.JsonElement;
6+
import com.google.gson.JsonObject;
7+
import io.javalin.http.BadRequestResponse;
8+
import net.earthmc.emcapi.EMCAPI;
9+
import net.earthmc.emcapi.integration.Integrations;
10+
import net.earthmc.emcapi.integration.McMMOIntegration;
11+
import net.earthmc.emcapi.manager.KeyManager;
12+
import net.earthmc.emcapi.object.endpoint.PostEndpoint;
13+
import net.earthmc.emcapi.util.CooldownUtil;
14+
import net.earthmc.emcapi.util.HttpExceptions;
15+
import net.earthmc.emcapi.util.JSONUtil;
16+
import org.jspecify.annotations.Nullable;
17+
18+
import java.util.UUID;
19+
20+
public class McMMOEndpoint extends PostEndpoint<PlayerProfile> {
21+
private final McMMOIntegration integration;
22+
private static final long COOLDOWN_SECONDS = 3600;
23+
24+
public McMMOEndpoint(EMCAPI plugin) {
25+
super(plugin);
26+
this.integration = Integrations.getIntegration("mcMMO");
27+
}
28+
29+
@Override
30+
public PlayerProfile getObjectOrNull(JsonElement element, @Nullable String key) {
31+
String string = JSONUtil.getJsonElementAsStringOrNull(element);
32+
if (string == null) throw new BadRequestResponse("Your query contains a value that is not a string");
33+
34+
UUID player;
35+
try {
36+
player = UUID.fromString(string);
37+
} catch (IllegalArgumentException ignored) {
38+
throw new BadRequestResponse("Your query contains an invalid UUID");
39+
}
40+
41+
UUID keyOwner = KeyManager.getKeyOwner(key);
42+
if (keyOwner == null) {
43+
throw HttpExceptions.MISSING_API_KEY;
44+
}
45+
if (!player.equals(keyOwner)) {
46+
throw HttpExceptions.FORBIDDEN;
47+
}
48+
49+
CooldownUtil.checkAndAddCooldownOrThrow("mcmmo", keyOwner.toString(), COOLDOWN_SECONDS);
50+
return integration.getPlayerProfile(player);
51+
}
52+
53+
@Override
54+
public JsonElement getJsonElement(PlayerProfile object, @Nullable String key) {
55+
JsonObject json = new JsonObject();
56+
json.addProperty("name", object.getPlayerName());
57+
for (PrimarySkillType skill : PrimarySkillType.values()) {
58+
json.addProperty(skill.name(), object.getSkillLevel(skill));
59+
}
60+
61+
return json;
62+
}
63+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package net.earthmc.emcapi.endpoint;
2+
3+
import com.gmail.nossr50.datatypes.database.PlayerStat;
4+
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
5+
import com.gmail.nossr50.mcMMO;
6+
import com.gmail.nossr50.util.skills.SkillTools;
7+
import com.google.gson.JsonElement;
8+
import com.google.gson.JsonObject;
9+
import io.javalin.http.BadRequestResponse;
10+
import net.earthmc.emcapi.EMCAPI;
11+
import net.earthmc.emcapi.integration.Integrations;
12+
import net.earthmc.emcapi.manager.KeyManager;
13+
import net.earthmc.emcapi.object.endpoint.PostEndpoint;
14+
import net.earthmc.emcapi.util.CooldownUtil;
15+
import net.earthmc.emcapi.util.HttpExceptions;
16+
import net.earthmc.emcapi.util.JSONUtil;
17+
import org.jspecify.annotations.Nullable;
18+
19+
import java.time.Instant;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.UUID;
23+
import java.util.concurrent.ConcurrentHashMap;
24+
import java.util.concurrent.TimeUnit;
25+
26+
public class McMMOTopEndpoint extends PostEndpoint<McMMOTopEndpoint.McMMOLeaderboard> {
27+
private static final Map<String, List<PlayerStat>> CACHE = new ConcurrentHashMap<>();
28+
private static final long COOLDOWN_SECONDS = 120;
29+
private Long lastUpdated;
30+
31+
public McMMOTopEndpoint(EMCAPI plugin) {
32+
super(plugin);
33+
if (Integrations.getIntegration("mcMMO").isEnabled()) {
34+
plugin.getServer().getAsyncScheduler().runAtFixedRate(plugin, t -> {
35+
for (PrimarySkillType skill : PrimarySkillType.values()) {
36+
if (SkillTools.isChildSkill(skill)) continue;
37+
loadSkill(skill);
38+
}
39+
loadSkill(null); // Main power
40+
lastUpdated = Instant.now().getEpochSecond();
41+
}, 1, 15, TimeUnit.MINUTES);
42+
}
43+
}
44+
45+
private static List<PlayerStat> loadSkill(@Nullable PrimarySkillType skill) {
46+
List<PlayerStat> data = mcMMO.getDatabaseManager().readLeaderboard(skill, 1, 25);
47+
CACHE.put(skillName(skill), data);
48+
return data;
49+
}
50+
51+
@Override
52+
public McMMOLeaderboard getObjectOrNull(JsonElement element, @Nullable String key) {
53+
String string = JSONUtil.getJsonElementAsStringOrNull(element);
54+
if (string == null) throw new BadRequestResponse("Your query contains a value that is not a string");
55+
56+
UUID keyOwner = KeyManager.getKeyOwner(key);
57+
if (keyOwner == null) {
58+
throw HttpExceptions.MISSING_API_KEY;
59+
}
60+
61+
PrimarySkillType skill;
62+
if (string.equalsIgnoreCase("power")) {
63+
skill = null;
64+
} else {
65+
try {
66+
skill = PrimarySkillType.valueOf(string.toUpperCase());
67+
} catch (IllegalArgumentException ignored) {
68+
throw new BadRequestResponse("Invalid skill name queried.");
69+
}
70+
if (SkillTools.isChildSkill(skill)) {
71+
throw new BadRequestResponse(skill.name() + " is a child skill and does not have a leaderboard!");
72+
}
73+
}
74+
CooldownUtil.checkAndAddCooldownOrThrow("mcmmo-top", keyOwner.toString(), COOLDOWN_SECONDS);
75+
76+
String skillName = skillName(skill);
77+
if (CACHE.containsKey(skillName)) {
78+
return new McMMOLeaderboard(skill, CACHE.get(skillName));
79+
}
80+
81+
return new McMMOLeaderboard(skill, loadSkill(skill));
82+
}
83+
84+
@Override
85+
public JsonElement getJsonElement(McMMOLeaderboard object, @Nullable String key) {
86+
JsonObject json = new JsonObject();
87+
json.addProperty("skill", skillName(object.skill()));
88+
89+
int index = 1;
90+
for (PlayerStat entry : object.data()) {
91+
JsonObject element = new JsonObject();
92+
element.addProperty("player", entry.playerName());
93+
element.addProperty("level", entry.value());
94+
95+
json.add(String.valueOf(index++), element);
96+
}
97+
98+
json.addProperty("lastUpdated", lastUpdated);
99+
return json;
100+
}
101+
102+
private static String skillName(@Nullable PrimarySkillType skill) {
103+
return skill != null ? skill.name() : "power";
104+
}
105+
106+
public record McMMOLeaderboard(@Nullable PrimarySkillType skill, List<PlayerStat> data) {}
107+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package net.earthmc.emcapi.integration;
2+
3+
import com.gmail.nossr50.datatypes.player.PlayerProfile;
4+
import com.gmail.nossr50.mcMMO;
5+
6+
import java.util.UUID;
7+
8+
public class McMMOIntegration extends Integration {
9+
10+
public McMMOIntegration() {
11+
super("mcMMO");
12+
}
13+
14+
public PlayerProfile getPlayerProfile(UUID uuid) {
15+
return mcMMO.getDatabaseManager().loadPlayerProfile(uuid);
16+
}
17+
}

0 commit comments

Comments
 (0)