diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java index f8257b88d3..bf5499d297 100644 --- a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java +++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreClient.java @@ -40,10 +40,11 @@ public class HiscoreClient { private static final Logger logger = LoggerFactory.getLogger(HiscoreClient.class); - public HiscoreResult lookup(String username) throws IOException + public HiscoreResult lookup(String username, HiscoreEndpoint endpoint) throws IOException { HttpUrl.Builder builder = RuneliteAPI.getApiBase().newBuilder() .addPathSegment("hiscore") + .addPathSegment(endpoint.name().toLowerCase()) .addQueryParameter("username", username); HttpUrl url = builder.build(); @@ -67,10 +68,16 @@ public class HiscoreClient } } - public SingleHiscoreSkillResult lookup(String username, HiscoreSkill skill) throws IOException + public HiscoreResult lookup(String username) throws IOException + { + return lookup(username, HiscoreEndpoint.NORMAL); + } + + public SingleHiscoreSkillResult lookup(String username, HiscoreSkill skill, HiscoreEndpoint endpoint) throws IOException { HttpUrl.Builder builder = RuneliteAPI.getApiBase().newBuilder() .addPathSegment("hiscore") + .addPathSegment(endpoint.name()) .addPathSegment(skill.toString().toLowerCase()) .addQueryParameter("username", username); @@ -94,4 +101,9 @@ public class HiscoreClient throw new IOException(ex); } } + + public SingleHiscoreSkillResult lookup(String username, HiscoreSkill skill) throws IOException + { + return lookup(username, skill, HiscoreEndpoint.NORMAL); + } } diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreEndpoint.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreEndpoint.java new file mode 100644 index 0000000000..c9e11529a1 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreEndpoint.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.http.api.hiscore; + +import okhttp3.HttpUrl; + +public enum HiscoreEndpoint +{ + NORMAL("Normal", "http://services.runescape.com/m=hiscore_oldschool/index_lite.ws"), + IRONMAN("Ironman", "http://services.runescape.com/m=hiscore_oldschool_ironman/index_lite.ws"), + HARDCORE_IRONMAN("Hardcore Ironman", "http://services.runescape.com/m=hiscore_oldschool_hardcore_ironman/index_lite.ws"), + ULTIMATE_IRONMAN("Ultimate Ironman", "http://services.runescape.com/m=hiscore_oldschool_ultimate/index_lite.ws"), + DEADMAN("Deadman", "http://services.runescape.com/m=hiscore_oldschool_deadman/index_lite.ws"), + SEASONAL_DEADMAN("Seasonal Deadman", "http://services.runescape.com/m=hiscore_oldschool_seasonal/index_lite.ws"); + + private final String name; + private final HttpUrl hiscoreURL; + + HiscoreEndpoint(String name, String hiscoreURL) + { + this.name = name; + this.hiscoreURL = HttpUrl.parse(hiscoreURL); + } + + public String getName() + { + return name; + } + + public HttpUrl getHiscoreURL() + { + return hiscoreURL; + } +} diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java index a1e41e0fa2..06f2921d99 100644 --- a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java +++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreResult.java @@ -53,6 +53,15 @@ public class HiscoreResult private Skill runecraft; private Skill hunter; private Skill construction; + private Skill clueScrollEasy; + private Skill clueScrollMedium; + private Skill clueScrollAll; + private Skill bountyHunterRogue; + private Skill bountyHunterHunter; + private Skill clueScrollHard; + private Skill lastManStanding; + private Skill clueScrollElite; + private Skill clueScrollMaster; public String getPlayer() { @@ -304,6 +313,96 @@ public class HiscoreResult this.construction = construction; } + public Skill getClueScrollEasy() + { + return clueScrollEasy; + } + + public void setClueScrollEasy(Skill clueScrollEasy) + { + this.clueScrollEasy = clueScrollEasy; + } + + public Skill getClueScrollMedium() + { + return clueScrollMedium; + } + + public void setClueScrollMedium(Skill clueScrollMedium) + { + this.clueScrollMedium = clueScrollMedium; + } + + public Skill getClueScrollAll() + { + return clueScrollAll; + } + + public void setClueScrollAll(Skill clueScrollAll) + { + this.clueScrollAll = clueScrollAll; + } + + public Skill getBountyHunterRogue() + { + return bountyHunterRogue; + } + + public void setBountyHunterRogue(Skill bountyHunterRogue) + { + this.bountyHunterRogue = bountyHunterRogue; + } + + public Skill getBountyHunterHunter() + { + return bountyHunterHunter; + } + + public void setBountyHunterHunter(Skill bountyHunterHunter) + { + this.bountyHunterHunter = bountyHunterHunter; + } + + public Skill getClueScrollHard() + { + return clueScrollHard; + } + + public void setClueScrollHard(Skill clueScrollHard) + { + this.clueScrollHard = clueScrollHard; + } + + public Skill getLastManStanding() + { + return lastManStanding; + } + + public void setLastManStanding(Skill lastManStanding) + { + this.lastManStanding = lastManStanding; + } + + public Skill getClueScrollElite() + { + return clueScrollElite; + } + + public void setClueScrollElite(Skill clueScrollElite) + { + this.clueScrollElite = clueScrollElite; + } + + public Skill getClueScrollMaster() + { + return clueScrollMaster; + } + + public void setClueScrollMaster(Skill clueScrollMaster) + { + this.clueScrollMaster = clueScrollMaster; + } + public Skill getSkill(HiscoreSkill skill) { switch (skill) @@ -356,9 +455,27 @@ public class HiscoreResult return getConstruction(); case OVERALL: return getOverall(); + case CLUE_SCROLL_EASY: + return getClueScrollEasy(); + case CLUE_SCROLL_MEDIUM: + return getClueScrollMedium(); + case CLUE_SCROLL_ALL: + return getClueScrollAll(); + case BOUNTY_HUNTER_ROGUE: + return getBountyHunterRogue(); + case BOUNTY_HUNTER_HUNTER: + return getBountyHunterHunter(); + case CLUE_SCROLL_HARD: + return getClueScrollHard(); + case LAST_MAN_STANDING: + return getLastManStanding(); + case CLUE_SCROLL_ELITE: + return getClueScrollElite(); + case CLUE_SCROLL_MASTER: + return getClueScrollMaster(); } - throw new IllegalArgumentException("Invalid skill"); + throw new IllegalArgumentException("Invalid hiscore item"); } @Override @@ -390,6 +507,15 @@ public class HiscoreResult hash = 29 * hash + Objects.hashCode(this.runecraft); hash = 29 * hash + Objects.hashCode(this.hunter); hash = 29 * hash + Objects.hashCode(this.construction); + hash = 29 * hash + Objects.hashCode(this.clueScrollEasy); + hash = 29 * hash + Objects.hashCode(this.clueScrollMedium); + hash = 29 * hash + Objects.hashCode(this.clueScrollAll); + hash = 29 * hash + Objects.hashCode(this.bountyHunterRogue); + hash = 29 * hash + Objects.hashCode(this.bountyHunterHunter); + hash = 29 * hash + Objects.hashCode(this.clueScrollHard); + hash = 29 * hash + Objects.hashCode(this.lastManStanding); + hash = 29 * hash + Objects.hashCode(this.clueScrollElite); + hash = 29 * hash + Objects.hashCode(this.clueScrollMaster); return hash; } @@ -509,12 +635,48 @@ public class HiscoreResult { return false; } + if (!Objects.equals(this.clueScrollEasy, other.clueScrollEasy)) + { + return false; + } + if (!Objects.equals(this.clueScrollMedium, other.clueScrollMedium)) + { + return false; + } + if (!Objects.equals(this.clueScrollAll, other.clueScrollAll)) + { + return false; + } + if (!Objects.equals(this.bountyHunterRogue, other.bountyHunterRogue)) + { + return false; + } + if (!Objects.equals(this.bountyHunterHunter, other.bountyHunterHunter)) + { + return false; + } + if (!Objects.equals(this.clueScrollHard, other.clueScrollHard)) + { + return false; + } + if (!Objects.equals(this.lastManStanding, other.lastManStanding)) + { + return false; + } + if (!Objects.equals(this.clueScrollElite, other.clueScrollElite)) + { + return false; + } + if (!Objects.equals(this.clueScrollMaster, other.clueScrollMaster)) + { + return false; + } return true; } @Override public String toString() { - return "HiscoreResult{" + "player=" + player + ", overall=" + overall + ", attack=" + attack + ", defence=" + defence + ", strength=" + strength + ", hitpoints=" + hitpoints + ", ranged=" + ranged + ", prayer=" + prayer + ", magic=" + magic + ", cooking=" + cooking + ", woodcutting=" + woodcutting + ", fletching=" + fletching + ", fishing=" + fishing + ", firemaking=" + firemaking + ", crafting=" + crafting + ", smithing=" + smithing + ", mining=" + mining + ", herblore=" + herblore + ", agility=" + agility + ", thieving=" + thieving + ", slayer=" + slayer + ", farming=" + farming + ", runecraft=" + runecraft + ", hunter=" + hunter + ", construction=" + construction + '}'; + return "HiscoreResult{" + "player=" + player + ", overall=" + overall + ", attack=" + attack + ", defence=" + defence + ", strength=" + strength + ", hitpoints=" + hitpoints + ", ranged=" + ranged + ", prayer=" + prayer + ", magic=" + magic + ", cooking=" + cooking + ", woodcutting=" + woodcutting + ", fletching=" + fletching + ", fishing=" + fishing + ", firemaking=" + firemaking + ", crafting=" + crafting + ", smithing=" + smithing + ", mining=" + mining + ", herblore=" + herblore + ", agility=" + agility + ", thieving=" + thieving + ", slayer=" + slayer + ", farming=" + farming + ", runecraft=" + runecraft + ", hunter=" + hunter + ", construction=" + construction + ", clueScrollEasy=" + clueScrollEasy + ", clueScrollMedium=" + clueScrollMedium + ", clueScrollAll=" + clueScrollAll + ", bountyHunterRogue=" + bountyHunterRogue + ", bountyHunterHunter=" + bountyHunterHunter + ", clueScrollHard=" + clueScrollHard + ", lastManStanding=" + lastManStanding + ", clueScrollElite=" + clueScrollElite + ", clueScrollMaster=" + clueScrollMaster + '}'; } } diff --git a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreSkill.java b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreSkill.java index 6eee6ca75d..57cc7423d5 100644 --- a/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreSkill.java +++ b/http-api/src/main/java/net/runelite/http/api/hiscore/HiscoreSkill.java @@ -49,7 +49,16 @@ public enum HiscoreSkill FARMING("Farming"), RUNECRAFT("Runecraft"), HUNTER("Hunter"), - CONSTRUCTION("Construction"); + CONSTRUCTION("Construction"), + CLUE_SCROLL_EASY("Clue Scrolls (easy)"), + CLUE_SCROLL_MEDIUM("Clue Scrolls (medium)"), + CLUE_SCROLL_ALL("Clue Scrolls (all)"), + BOUNTY_HUNTER_ROGUE("Bounty Hunter - Rogue"), + BOUNTY_HUNTER_HUNTER("Bounty Hunter - Hunter"), + CLUE_SCROLL_HARD("Clue Scrolls (hard)"), + LAST_MAN_STANDING("Last Man Standing"), + CLUE_SCROLL_ELITE("Clue Scrolls (elite)"), + CLUE_SCROLL_MASTER("Clue Scrolls (master)"); private final String name; diff --git a/http-service/src/main/java/net/runelite/http/service/InstantConverter.java b/http-service/src/main/java/net/runelite/http/service/InstantConverter.java deleted file mode 100644 index 808479018b..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/InstantConverter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service; - -import java.sql.Timestamp; -import java.time.Instant; -import org.sql2o.converters.Converter; -import org.sql2o.converters.ConverterException; - -public class InstantConverter implements Converter -{ - @Override - public Instant convert(Object val) throws ConverterException - { - Timestamp ts = (Timestamp) val; - return ts.toInstant(); - } - - @Override - public Object toDatabaseParam(Instant val) - { - return Timestamp.from(val); - } - -} diff --git a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java index 5f259427dd..319ecaee9c 100644 --- a/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java +++ b/http-service/src/main/java/net/runelite/http/service/SpringBootWebApplication.java @@ -31,6 +31,8 @@ import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; + +import net.runelite.http.service.util.InstantConverter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; diff --git a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java b/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java index 42ef759231..d1f6251608 100644 --- a/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java +++ b/http-service/src/main/java/net/runelite/http/service/cache/CacheService.java @@ -55,6 +55,7 @@ import net.runelite.cache.fs.jagex.DataFileReadResult; import net.runelite.http.api.cache.Cache; import net.runelite.http.api.cache.CacheArchive; import net.runelite.http.api.cache.CacheIndex; +import net.runelite.http.service.util.exception.NotFoundException; import net.runelite.http.service.cache.beans.ArchiveEntry; import net.runelite.http.service.cache.beans.CacheEntry; import net.runelite.http.service.cache.beans.FileEntry; diff --git a/http-service/src/main/java/net/runelite/http/service/cache/NotFoundException.java b/http-service/src/main/java/net/runelite/http/service/cache/NotFoundException.java deleted file mode 100644 index 4787f0f859..0000000000 --- a/http-service/src/main/java/net/runelite/http/service/cache/NotFoundException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.http.service.cache; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not found") -public class NotFoundException extends RuntimeException -{ - -} diff --git a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java index 1d8034ab38..cefe39b471 100644 --- a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java +++ b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreResultBuilder.java @@ -77,6 +77,15 @@ public class HiscoreResultBuilder hiscoreResult.setRunecraft(skills.get(21)); hiscoreResult.setHunter(skills.get(22)); hiscoreResult.setConstruction(skills.get(23)); + hiscoreResult.setClueScrollEasy(skills.get(24)); + hiscoreResult.setClueScrollMedium(skills.get(25)); + hiscoreResult.setClueScrollAll(skills.get(26)); + hiscoreResult.setBountyHunterRogue(skills.get(27)); + hiscoreResult.setBountyHunterHunter(skills.get(28)); + hiscoreResult.setClueScrollHard(skills.get(29)); + hiscoreResult.setLastManStanding(skills.get(30)); + hiscoreResult.setClueScrollElite(skills.get(31)); + hiscoreResult.setClueScrollMaster(skills.get(32)); return hiscoreResult; } } diff --git a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java index 9d1e1591be..107e9d17f3 100644 --- a/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java +++ b/http-service/src/main/java/net/runelite/http/service/hiscore/HiscoreService.java @@ -26,10 +26,10 @@ package net.runelite.http.service.hiscore; import java.io.IOException; import net.runelite.http.api.RuneliteAPI; -import net.runelite.http.api.hiscore.HiscoreResult; -import net.runelite.http.api.hiscore.SingleHiscoreSkillResult; -import net.runelite.http.api.hiscore.Skill; -import net.runelite.http.api.hiscore.HiscoreSkill; +import net.runelite.http.api.hiscore.*; +import net.runelite.http.service.util.HiscoreEndpointEditor; +import net.runelite.http.service.util.exception.InternalServerErrorException; +import net.runelite.http.service.util.exception.NotFoundException; import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.Response; @@ -39,10 +39,9 @@ import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/hiscore") @@ -50,23 +49,36 @@ public class HiscoreService { private static final Logger logger = LoggerFactory.getLogger(HiscoreService.class); - private static final HttpUrl RUNESCAPE_HISCORE_SERVICE = HttpUrl.parse("http://services.runescape.com/m=hiscore_oldschool/index_lite.ws"); - - private HttpUrl url = RUNESCAPE_HISCORE_SERVICE; - - private HiscoreResultBuilder lookupUsername(String username) throws IOException + HiscoreResultBuilder lookupUsername(String username, HiscoreEndpoint endpoint) throws IOException { - HttpUrl hiscoreUrl = url.newBuilder() - .addQueryParameter("player", username) - .build(); + return lookupUsername(username, endpoint.getHiscoreURL()); + } - logger.info("Built URL {}", hiscoreUrl); + HiscoreResultBuilder lookupUsername(String username, HttpUrl hiscoreUrl) throws IOException + { + HttpUrl url = hiscoreUrl.newBuilder() + .addQueryParameter("player", username) + .build(); + + logger.info("Built URL {}", url); Request okrequest = new Request.Builder() - .url(hiscoreUrl) - .build(); + .url(url) + .build(); Response okresponse = RuneliteAPI.CLIENT.newCall(okrequest).execute(); + + if (!okresponse.isSuccessful()) + { + switch (HttpStatus.valueOf(okresponse.code())) + { + case NOT_FOUND: + throw new NotFoundException(); + default: + throw new InternalServerErrorException("Error retrieving data from Jagex Hiscores: " + okresponse.message()); + } + } + String responseStr; try (ResponseBody body = okresponse.body()) @@ -85,13 +97,20 @@ public class HiscoreService { if (count++ >= HiscoreSkill.values().length) { + logger.warn("Jagex Hiscore API returned unexpected data"); break; // rest is other things? } // rank, level, experience int rank = Integer.parseInt(record.get(0)); int level = Integer.parseInt(record.get(1)); - long experience = Long.parseLong(record.get(2)); + + // items that are not skills do not have an experience parameter + long experience = -1; + if (record.size() == 3) + { + experience = Long.parseLong(record.get(2)); + } Skill skill = new Skill(rank, level, experience); hiscoreBuilder.setNextSkill(skill); @@ -100,20 +119,20 @@ public class HiscoreService return hiscoreBuilder; } - @RequestMapping - public HiscoreResult lookup(@RequestParam String username) throws IOException + @RequestMapping("/{endpoint}") + public HiscoreResult lookup(@PathVariable HiscoreEndpoint endpoint, @RequestParam String username) throws IOException { - HiscoreResultBuilder result = lookupUsername(username); + HiscoreResultBuilder result = lookupUsername(username, endpoint); return result.build(); } - @RequestMapping("/{skillName}") - public SingleHiscoreSkillResult singleSkillLookup(@PathVariable String skillName, @RequestParam String username) throws IOException + @RequestMapping("/{endpoint}/{skillName}") + public SingleHiscoreSkillResult singleSkillLookup(@PathVariable HiscoreEndpoint endpoint, @PathVariable String skillName, @RequestParam String username) throws IOException { HiscoreSkill skill = HiscoreSkill.valueOf(skillName.toUpperCase()); // RS api only supports looking up all stats - HiscoreResultBuilder result = lookupUsername(username); + HiscoreResultBuilder result = lookupUsername(username, endpoint); // Find the skill to return Skill requested = result.getSkill(skill.ordinal()); @@ -126,13 +145,9 @@ public class HiscoreService return skillResult; } - public HttpUrl getUrl() + @InitBinder + public void initBinder(WebDataBinder binder) { - return url; - } - - public void setUrl(HttpUrl url) - { - this.url = url; + binder.registerCustomEditor(HiscoreEndpoint.class, new HiscoreEndpointEditor()); } } diff --git a/http-service/src/main/java/net/runelite/http/service/util/HiscoreEndpointEditor.java b/http-service/src/main/java/net/runelite/http/service/util/HiscoreEndpointEditor.java new file mode 100644 index 0000000000..816981f99a --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/util/HiscoreEndpointEditor.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.http.service.util; + +import net.runelite.http.api.hiscore.HiscoreEndpoint; + +import java.beans.PropertyEditorSupport; + +public class HiscoreEndpointEditor extends PropertyEditorSupport +{ + @Override + public void setAsText(String text) throws IllegalArgumentException + { + setValue(HiscoreEndpoint.valueOf(text.toUpperCase())); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java b/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java new file mode 100644 index 0000000000..785ad00266 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/util/InstantConverter.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.util; + +import java.sql.Timestamp; +import java.time.Instant; +import org.sql2o.converters.Converter; +import org.sql2o.converters.ConverterException; + +public class InstantConverter implements Converter +{ + @Override + public Instant convert(Object val) throws ConverterException + { + Timestamp ts = (Timestamp) val; + return ts.toInstant(); + } + + @Override + public Object toDatabaseParam(Instant val) + { + return Timestamp.from(val); + } + +} diff --git a/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java b/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java new file mode 100644 index 0000000000..62adc5b6fc --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/util/exception/InternalServerErrorException.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.util.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR) +public class InternalServerErrorException extends RuntimeException +{ + public InternalServerErrorException(String message) + { + super(message); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java b/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java new file mode 100644 index 0000000000..83e04ceca6 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/util/exception/NotFoundException.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.util.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not found") +public class NotFoundException extends RuntimeException +{ + +} diff --git a/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java b/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java index 865363ad51..45e5ed35f3 100644 --- a/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java +++ b/http-service/src/test/java/net/runelite/http/service/SpringBootWebApplicationTest.java @@ -28,6 +28,8 @@ import java.time.Instant; import java.util.HashMap; import java.util.Map; import javax.naming.NamingException; + +import net.runelite.http.service.util.InstantConverter; import org.junit.Ignore; import org.junit.Test; import org.springframework.boot.SpringApplication; diff --git a/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java index 2fcf74bcbb..5fc1706dcf 100644 --- a/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java +++ b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreServiceTest.java @@ -25,6 +25,7 @@ package net.runelite.http.service.hiscore; import java.io.IOException; +import net.runelite.http.api.hiscore.HiscoreEndpoint; import net.runelite.http.api.hiscore.HiscoreResult; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; @@ -36,38 +37,38 @@ import org.junit.Test; public class HiscoreServiceTest { private static final String RESPONSE = "654683,705,1304518\n" - + "679419,50,107181\n" - + "550667,48,85764\n" - + "861497,50,101366\n" - + "891591,48,87843\n" - + "-1,1,4\n" - + "840255,27,10073\n" - + "1371912,10,1310\n" - + "432193,56,199795\n" - + "495638,56,198304\n" - + "514466,37,27502\n" - + "456981,54,159727\n" - + "459159,49,93010\n" - + "1028855,8,823\n" - + "862906,29,12749\n" - + "795020,31,16097\n" - + "673591,5,495\n" - + "352676,51,112259\n" - + "428419,40,37235\n" - + "461887,43,51971\n" - + "598582,1,10\n" - + "638177,1,0\n" - + "516239,9,1000\n" - + "492790,1,0\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1\n" - + "-1,-1"; + + "679419,50,107181\n" + + "550667,48,85764\n" + + "861497,50,101366\n" + + "891591,48,87843\n" + + "-1,1,4\n" + + "840255,27,10073\n" + + "1371912,10,1310\n" + + "432193,56,199795\n" + + "495638,56,198304\n" + + "514466,37,27502\n" + + "456981,54,159727\n" + + "459159,49,93010\n" + + "1028855,8,823\n" + + "862906,29,12749\n" + + "795020,31,16097\n" + + "673591,5,495\n" + + "352676,51,112259\n" + + "428419,40,37235\n" + + "461887,43,51971\n" + + "598582,1,10\n" + + "638177,1,0\n" + + "516239,9,1000\n" + + "492790,1,0\n" + + "-1,-1\n" + + "-1,-1\n" + + "531,1432\n" + + "-1,-1\n" + + "-1,-1\n" + + "-1,-1\n" + + "-1,-1\n" + + "-1,-1\n" + + "254,92"; private final MockWebServer server = new MockWebServer(); @@ -86,16 +87,17 @@ public class HiscoreServiceTest } @Test - public void testLookup() throws Exception + public void testNormalLookup() throws Exception { - HiscoreService hiscores = new HiscoreService(); - hiscores.setUrl(server.url("/")); + HiscoreTestService hiscores = new HiscoreTestService(server.url("/")); - HiscoreResult result = hiscores.lookup("zezima"); + HiscoreResult result = hiscores.lookup(HiscoreEndpoint.NORMAL, "zezima"); Assert.assertEquals(50, result.getAttack().getLevel()); Assert.assertEquals(159727L, result.getFishing().getExperience()); Assert.assertEquals(492790, result.getConstruction().getRank()); + Assert.assertEquals(1432, result.getClueScrollAll().getLevel()); + Assert.assertEquals(254, result.getClueScrollMaster().getRank()); } } diff --git a/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreTestService.java b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreTestService.java new file mode 100644 index 0000000000..2ef8b2dd56 --- /dev/null +++ b/http-service/src/test/java/net/runelite/http/service/hiscore/HiscoreTestService.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.http.service.hiscore; + +import net.runelite.http.api.hiscore.HiscoreEndpoint; +import okhttp3.HttpUrl; + +import java.io.IOException; + +class HiscoreTestService extends HiscoreService +{ + private HttpUrl testUrl; + + HiscoreTestService(HttpUrl testUrl) + { + this.testUrl = testUrl; + } + + @Override + HiscoreResultBuilder lookupUsername(String username, HiscoreEndpoint endpoint) throws IOException + { + return super.lookupUsername(username, testUrl); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java index 8f7b771eca..f76c08afd8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java @@ -25,38 +25,27 @@ package net.runelite.client.plugins.hiscore; import com.google.common.base.Strings; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; + +import java.awt.*; import java.awt.event.MouseEvent; import java.io.IOException; import java.text.NumberFormat; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledExecutorService; import javax.imageio.ImageIO; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.UIManager; +import javax.swing.*; import javax.swing.border.Border; import javax.swing.event.MouseInputAdapter; + import net.runelite.api.Experience; import net.runelite.client.RuneLite; import net.runelite.client.ui.IconTextField; import net.runelite.client.ui.PluginPanel; -import net.runelite.http.api.hiscore.HiscoreClient; -import net.runelite.http.api.hiscore.HiscoreResult; -import net.runelite.http.api.hiscore.HiscoreSkill; +import net.runelite.http.api.hiscore.*; + import static net.runelite.http.api.hiscore.HiscoreSkill.*; -import net.runelite.http.api.hiscore.Skill; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,9 +72,10 @@ public class HiscorePanel extends PluginPanel private final IconTextField input; - private final List skillLabels = new LinkedList<>(); + private final List skillLabels = new ArrayList<>(); private final JPanel statsPanel = new JPanel(); + private final ButtonGroup endpointButtonGroup = new ButtonGroup(); private final JTextArea details = new JTextArea(); private final HiscoreClient client = new HiscoreClient(); @@ -134,6 +124,7 @@ public class HiscorePanel extends PluginPanel input = new IconTextField(); input.setIcon(search); + input.setFont(labelFont.deriveFont(Font.BOLD)); input.addActionListener(e -> { ScheduledExecutorService executor = runelite.getExecutor(); @@ -178,6 +169,22 @@ public class HiscorePanel extends PluginPanel gridBag.setConstraints(totalPanel, c); add(totalPanel); + JPanel minigamePanel = new JPanel(); + minigamePanel.setBorder(subPanelBorder); + // These aren't all on one row because when there's a label with four or more digits it causes the details + // panel to change its size for some reason... + minigamePanel.setLayout(new GridLayout(2, 3)); + + minigamePanel.add(makeSkillPanel(CLUE_SCROLL_ALL.getName(), CLUE_SCROLL_ALL)); + minigamePanel.add(makeSkillPanel(LAST_MAN_STANDING.getName(), LAST_MAN_STANDING)); + minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_ROGUE.getName(), BOUNTY_HUNTER_ROGUE)); + minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_HUNTER.getName(), BOUNTY_HUNTER_HUNTER)); + + c.gridx = 0; + c.gridy = 3; + gridBag.setConstraints(minigamePanel, c); + add(minigamePanel); + JPanel detailsPanel = new JPanel(); detailsPanel.setBorder(subPanelBorder); detailsPanel.setLayout(new BorderLayout()); @@ -197,16 +204,57 @@ public class HiscorePanel extends PluginPanel detailsPanel.add(details, BorderLayout.CENTER); c.gridx = 0; - c.gridy = 3; - // Last item has a nonzero weighty so it will expand to fill vertical space - c.weighty = 1; + c.gridy = 4; gridBag.setConstraints(detailsPanel, c); add(detailsPanel); + + JPanel endpointPanel = new JPanel(); + endpointPanel.setBorder(subPanelBorder); + + List endpointButtons = new ArrayList<>(); + + for (HiscoreEndpoint endpoint : HiscoreEndpoint.values()) + { + try + { + Icon icon = new ImageIcon(ImageIO.read(HiscorePanel.class.getResourceAsStream(endpoint.name() + ".png"))); + Icon selected = new ImageIcon(ImageIO.read(HiscorePanel.class.getResourceAsStream(endpoint.name() + "_selected.png"))); + JToggleButton button = new JToggleButton(); + button.setIcon(icon); + button.setSelectedIcon(selected); + button.setPreferredSize(new Dimension(24,24)); + button.setBackground(Color.WHITE); + button.setFocusPainted(false); + button.setActionCommand(endpoint.name()); + button.setToolTipText(endpoint.getName() + " Hiscores"); + button.addActionListener((e -> + { + ScheduledExecutorService executor = runelite.getExecutor(); + executor.execute(this::lookup); + })); + endpointButtons.add(button); + endpointButtonGroup.add(button); + endpointPanel.add(button); + } + catch (IOException ex) + { + logger.warn(null, ex); + } + } + + endpointButtons.get(0).setSelected(true); + + c.gridx = 0; + c.gridy = 5; + // Last item has a nonzero weighty so it will expand to fill vertical space + c.weighty = 1; + gridBag.setConstraints(endpointPanel, c); + add(endpointPanel); } private void changeDetail(String skillName, HiscoreSkill skill) { - if (result == null) + if (result == null || result.getPlayer() == null) { return; } @@ -216,14 +264,6 @@ public class HiscorePanel extends PluginPanel String text; switch (skillName) { - case "Overall": - { - Skill requestedSkill = result.getOverall(); - text = "Total Level" + System.lineSeparator() - + "Rank: " + formatter.format(requestedSkill.getRank()) + System.lineSeparator() - + "Total Experience: " + formatter.format(requestedSkill.getExperience()); - break; - } case "Combat": { double combatLevel = Experience.getCombatLevelPrecise( @@ -235,19 +275,50 @@ public class HiscorePanel extends PluginPanel result.getRanged().getLevel(), result.getPrayer().getLevel() ); - text = "Exact Combat Level: " + formatter.format(combatLevel) + System.lineSeparator() + text = "Skill: Combat" + System.lineSeparator() + + "Exact Combat Level: " + formatter.format(combatLevel) + System.lineSeparator() + "Experience: " + formatter.format(result.getAttack().getExperience() - + result.getStrength().getExperience() + result.getDefence().getExperience() - + result.getHitpoints().getExperience() + result.getMagic().getExperience() - + result.getRanged().getExperience() + result.getPrayer().getExperience()); + + result.getStrength().getExperience() + result.getDefence().getExperience() + + result.getHitpoints().getExperience() + result.getMagic().getExperience() + + result.getRanged().getExperience() + result.getPrayer().getExperience()); + break; + } + case "Clue Scrolls (all)": + { + String rank = (result.getClueScrollAll().getRank() == -1) ? "Unranked" : formatter.format(result.getClueScrollAll().getRank()); + text = "Total Clue Scrolls Completed" + System.lineSeparator() + + "Rank: " + rank; + break; + } + case "Bounty Hunter - Rogue": + { + String rank = (result.getBountyHunterRogue().getRank() == -1) ? "Unranked" : formatter.format(result.getBountyHunterRogue().getRank()); + text = "Bounty Hunter - Rogue Kills" + System.lineSeparator() + + "Rank: " + rank; + break; + } + case "Bounty Hunter - Hunter": + { + String rank = (result.getBountyHunterHunter().getRank() == -1) ? "Unranked" : formatter.format(result.getBountyHunterHunter().getRank()); + text = "Bounty Hunter - Hunter Kills" + System.lineSeparator() + + "Rank: " + rank; + break; + } + case "Last Man Standing": + { + String rank = (result.getLastManStanding().getRank() == -1) ? "Unranked" : formatter.format(result.getLastManStanding().getRank()); + text = "Last Man Standing" + System.lineSeparator() + + "Rank: " + rank; break; } default: { Skill requestedSkill = result.getSkill(skill); + String rank = (requestedSkill.getRank() == -1) ? "Unranked" : formatter.format(requestedSkill.getRank()); + String exp = (requestedSkill.getRank() == -1) ? "Unranked" : formatter.format(requestedSkill.getExperience()); text = "Skill: " + skillName + System.lineSeparator() - + "Rank: " + formatter.format(requestedSkill.getRank()) + System.lineSeparator() - + "Experience: " + formatter.format(requestedSkill.getExperience()); + + "Rank: " + rank + System.lineSeparator() + + "Experience: " + exp; break; } } @@ -265,7 +336,7 @@ public class HiscorePanel extends PluginPanel label.putClientProperty(SKILL_NAME, skillName); label.putClientProperty(SKILL, skill); - String skillIcon = "/skill_icons/" + skillName.toLowerCase() + ".png"; + String skillIcon = "skill_icons_small/" + skillName.toLowerCase() + ".png"; logger.debug("Loading skill icon from {}", skillIcon); try @@ -316,11 +387,14 @@ public class HiscorePanel extends PluginPanel try { - result = client.lookup(lookup); + HiscoreEndpoint endpoint = HiscoreEndpoint.valueOf(endpointButtonGroup.getSelection().getActionCommand()); + logger.debug("Hiscore endpoint " + endpoint.name() + " selected"); + + result = client.lookup(lookup, endpoint); } catch (IOException ex) { - logger.warn(null, ex); + logger.warn("Error fetching Hiscore data " + ex.getMessage()); return; } @@ -331,18 +405,29 @@ public class HiscorePanel extends PluginPanel if (skillName.equals("Combat")) { - int combatLevel = Experience.getCombatLevel( - result.getAttack().getLevel(), - result.getStrength().getLevel(), - result.getDefence().getLevel(), - result.getHitpoints().getLevel(), - result.getMagic().getLevel(), - result.getRanged().getLevel(), - result.getPrayer().getLevel() - ); - label.setText(Integer.toString(combatLevel)); + if (result.getPlayer() != null) + { + int combatLevel = Experience.getCombatLevel( + result.getAttack().getLevel(), + result.getStrength().getLevel(), + result.getDefence().getLevel(), + result.getHitpoints().getLevel(), + result.getMagic().getLevel(), + result.getRanged().getLevel(), + result.getPrayer().getLevel() + ); + label.setText(Integer.toString(combatLevel)); + } + else + { + label.setText("--"); + } } - else if (skill != null) + else if (result.getSkill(skill) == null) + { + label.setText("--"); + } + else if (result.getSkill(skill) != null && result.getSkill(skill).getRank() != -1) { label.setText(Integer.toString(result.getSkill(skill).getLevel())); } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman.png new file mode 100644 index 0000000000..fb55cebf06 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman_selected.png new file mode 100644 index 0000000000..bca0e8dc55 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/deadman_selected.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman.png new file mode 100644 index 0000000000..2f4631d36e Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman_selected.png new file mode 100644 index 0000000000..1cbae387af Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/hardcore_ironman_selected.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman.png new file mode 100644 index 0000000000..a00b92b1f8 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman_selected.png new file mode 100644 index 0000000000..56acded1ba Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ironman_selected.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal.png new file mode 100644 index 0000000000..c00f4ec040 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal_selected.png new file mode 100644 index 0000000000..fbee92c847 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/normal_selected.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman.png new file mode 100644 index 0000000000..831b1aff4a Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman_selected.png new file mode 100644 index 0000000000..ae6c4820e1 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/seasonal_deadman_selected.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/agility.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/agility.png new file mode 100644 index 0000000000..19c26d9022 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/agility.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/attack.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/attack.png new file mode 100644 index 0000000000..4d9aaa87f6 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/attack.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - hunter.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - hunter.png new file mode 100644 index 0000000000..7ac7a92576 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - hunter.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - rogue.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - rogue.png new file mode 100644 index 0000000000..0b74dc96d8 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/bounty hunter - rogue.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/clue scrolls (all).png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/clue scrolls (all).png new file mode 100644 index 0000000000..9a7120c91b Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/clue scrolls (all).png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/combat.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/combat.png new file mode 100644 index 0000000000..b1e17fb28d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/combat.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/construction.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/construction.png new file mode 100644 index 0000000000..3c8e176a3e Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/construction.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/cooking.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/cooking.png new file mode 100644 index 0000000000..2030f1d25b Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/cooking.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/crafting.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/crafting.png new file mode 100644 index 0000000000..7b5fd52464 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/crafting.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/defence.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/defence.png new file mode 100644 index 0000000000..370a1cc729 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/defence.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/farming.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/farming.png new file mode 100644 index 0000000000..0b9becd5f5 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/farming.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/firemaking.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/firemaking.png new file mode 100644 index 0000000000..a9297c8edc Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/firemaking.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fishing.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fishing.png new file mode 100644 index 0000000000..caa5ca9738 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fishing.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fletching.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fletching.png new file mode 100644 index 0000000000..56b50c4067 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/fletching.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/herblore.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/herblore.png new file mode 100644 index 0000000000..fde27351c4 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/herblore.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hitpoints.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hitpoints.png new file mode 100644 index 0000000000..bf431f7518 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hitpoints.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hunter.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hunter.png new file mode 100644 index 0000000000..88be793bbb Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/hunter.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/last man standing.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/last man standing.png new file mode 100644 index 0000000000..a5af05790f Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/last man standing.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/magic.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/magic.png new file mode 100644 index 0000000000..5e9974c7bd Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/magic.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/mining.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/mining.png new file mode 100644 index 0000000000..57430882d0 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/mining.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/overall.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/overall.png new file mode 100644 index 0000000000..4b2dd265a4 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/overall.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/prayer.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/prayer.png new file mode 100644 index 0000000000..7c348987eb Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/prayer.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/ranged.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/ranged.png new file mode 100644 index 0000000000..9b73588023 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/ranged.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/runecraft.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/runecraft.png new file mode 100644 index 0000000000..2c52ffe913 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/runecraft.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/slayer.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/slayer.png new file mode 100644 index 0000000000..f02563044c Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/slayer.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/smithing.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/smithing.png new file mode 100644 index 0000000000..b07ec45b86 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/smithing.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/strength.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/strength.png new file mode 100644 index 0000000000..976c550712 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/strength.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/thieving.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/thieving.png new file mode 100644 index 0000000000..4aca64fdb0 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/thieving.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/woodcutting.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/woodcutting.png new file mode 100644 index 0000000000..379d09b76f Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/skill_icons_small/woodcutting.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman.png new file mode 100644 index 0000000000..efa7643d97 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman_selected.png new file mode 100644 index 0000000000..d171215c16 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/hiscore/ultimate_ironman_selected.png differ