Merge remote-tracking branch 'upstream/master' into master

This commit is contained in:
ThatGamerBlue
2021-03-24 16:58:14 +00:00
40 changed files with 943 additions and 1362 deletions
+2 -2
View File
@@ -25,9 +25,9 @@
object ProjectVersions {
const val launcherVersion = "2.2.0"
const val rlVersion = "1.7.2.2"
const val rlVersion = "1.7.3"
const val openosrsVersion = "4.1.0"
const val openosrsVersion = "4.2.0"
const val rsversion = 194
const val cacheversion = 165
@@ -179,14 +179,14 @@ public class ChatClient
}
}
public boolean submitPb(String username, String boss, int pb) throws IOException
public boolean submitPb(String username, String boss, double pb) throws IOException
{
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("chat")
.addPathSegment("pb")
.addQueryParameter("name", username)
.addQueryParameter("boss", boss)
.addQueryParameter("pb", Integer.toString(pb))
.addQueryParameter("pb", Double.toString(pb))
.build();
Request request = new Request.Builder()
@@ -200,7 +200,7 @@ public class ChatClient
}
}
public int getPb(String username, String boss) throws IOException
public double getPb(String username, String boss) throws IOException
{
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("chat")
@@ -219,7 +219,7 @@ public class ChatClient
{
throw new IOException("Unable to look up personal best!");
}
return Integer.parseInt(response.body().string());
return Double.parseDouble(response.body().string());
}
}
@@ -98,6 +98,7 @@ public class HiscoreResult
private Skill sarachnis;
private Skill scorpia;
private Skill skotizo;
private Skill tempoross;
private Skill gauntlet;
private Skill corruptedGauntlet;
private Skill theatreOfBlood;
@@ -251,6 +252,8 @@ public class HiscoreResult
return scorpia;
case SKOTIZO:
return skotizo;
case TEMPOROSS:
return tempoross;
case THE_GAUNTLET:
return gauntlet;
case THE_CORRUPTED_GAUNTLET:
@@ -123,6 +123,10 @@ class HiscoreResultBuilder
hiscoreResult.setSarachnis(skills.get(index++));
hiscoreResult.setScorpia(skills.get(index++));
hiscoreResult.setSkotizo(skills.get(index++));
if (skills.size() >= 81)
{
hiscoreResult.setTempoross(skills.get(index++));
}
hiscoreResult.setGauntlet(skills.get(index++));
hiscoreResult.setCorruptedGauntlet(skills.get(index++));
hiscoreResult.setTheatreOfBlood(skills.get(index++));
@@ -102,6 +102,7 @@ public enum HiscoreSkill
SARACHNIS("Sarachnis", BOSS),
SCORPIA("Scorpia", BOSS),
SKOTIZO("Skotizo", BOSS),
TEMPOROSS("Tempoross", BOSS),
THE_GAUNTLET("The Gauntlet", BOSS),
THE_CORRUPTED_GAUNTLET("The Corrupted Gauntlet", BOSS),
THEATRE_OF_BLOOD("Theatre of Blood", BOSS),
@@ -1,250 +0,0 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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.chat;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.runelite.http.api.chat.Duels;
import net.runelite.http.api.chat.LayoutRoom;
import net.runelite.http.api.chat.Task;
import net.runelite.http.service.util.exception.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/chat")
public class ChatController
{
private static final Pattern STRING_VALIDATION = Pattern.compile("[^a-zA-Z0-9' -]");
private static final int STRING_MAX_LENGTH = 50;
private static final int MAX_LAYOUT_ROOMS = 16;
private final Cache<KillCountKey, Integer> killCountCache = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.MINUTES)
.maximumSize(128L)
.build();
@Autowired
private ChatService chatService;
@PostMapping("/kc")
public void submitKc(@RequestParam String name, @RequestParam String boss, @RequestParam int kc)
{
if (kc <= 0)
{
return;
}
chatService.setKc(name, boss, kc);
killCountCache.put(new KillCountKey(name, boss), kc);
}
@GetMapping("/kc")
public int getKc(@RequestParam String name, @RequestParam String boss)
{
Integer kc = killCountCache.getIfPresent(new KillCountKey(name, boss));
if (kc == null)
{
kc = chatService.getKc(name, boss);
if (kc != null)
{
killCountCache.put(new KillCountKey(name, boss), kc);
}
}
if (kc == null)
{
throw new NotFoundException();
}
return kc;
}
@PostMapping("/qp")
public void submitQp(@RequestParam String name, @RequestParam int qp)
{
if (qp < 0)
{
return;
}
chatService.setQp(name, qp);
}
@GetMapping("/qp")
public int getQp(@RequestParam String name)
{
Integer kc = chatService.getQp(name);
if (kc == null)
{
throw new NotFoundException();
}
return kc;
}
@PostMapping("/gc")
public void submitGc(@RequestParam String name, @RequestParam int gc)
{
if (gc < 0)
{
return;
}
chatService.setGc(name, gc);
}
@GetMapping("/gc")
public int getKc(@RequestParam String name)
{
Integer gc = chatService.getGc(name);
if (gc == null)
{
throw new NotFoundException();
}
return gc;
}
@PostMapping("/task")
public void submitTask(@RequestParam String name, @RequestParam("task") String taskName, @RequestParam int amount,
@RequestParam int initialAmount, @RequestParam String location)
{
Matcher mTask = STRING_VALIDATION.matcher(taskName);
Matcher mLocation = STRING_VALIDATION.matcher(location);
if (mTask.find() || taskName.length() > STRING_MAX_LENGTH ||
mLocation.find() || location.length() > STRING_MAX_LENGTH)
{
return;
}
Task task = new Task();
task.setTask(taskName);
task.setAmount(amount);
task.setInitialAmount(initialAmount);
task.setLocation(location);
chatService.setTask(name, task);
}
@GetMapping("/task")
public ResponseEntity<Task> getTask(@RequestParam String name)
{
Task task = chatService.getTask(name);
if (task == null)
{
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.build();
}
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(2, TimeUnit.MINUTES).cachePublic())
.body(task);
}
@PostMapping("/pb")
public void submitPb(@RequestParam String name, @RequestParam String boss, @RequestParam int pb)
{
if (pb < 0)
{
return;
}
chatService.setPb(name, boss, pb);
}
@GetMapping("/pb")
public int getPb(@RequestParam String name, @RequestParam String boss)
{
Integer pb = chatService.getPb(name, boss);
if (pb == null)
{
throw new NotFoundException();
}
return pb;
}
@PostMapping("/duels")
public void submitDuels(@RequestParam String name, @RequestParam int wins,
@RequestParam int losses,
@RequestParam int winningStreak, @RequestParam int losingStreak)
{
if (wins < 0 || losses < 0 || winningStreak < 0 || losingStreak < 0)
{
return;
}
Duels duels = new Duels();
duels.setWins(wins);
duels.setLosses(losses);
duels.setWinningStreak(winningStreak);
duels.setLosingStreak(losingStreak);
chatService.setDuels(name, duels);
}
@GetMapping("/duels")
public Duels getDuels(@RequestParam String name)
{
Duels duels = chatService.getDuels(name);
if (duels == null)
{
throw new NotFoundException();
}
return duels;
}
@PostMapping("/layout")
public void submitLayout(@RequestParam String name, @RequestBody LayoutRoom[] rooms)
{
if (rooms.length > MAX_LAYOUT_ROOMS)
{
return;
}
chatService.setLayout(name, rooms);
}
@GetMapping("/layout")
public LayoutRoom[] getLayout(@RequestParam String name)
{
LayoutRoom[] layout = chatService.getLayout(name);
if (layout == null)
{
throw new NotFoundException();
}
return layout;
}
}
@@ -1,134 +0,0 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* 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.config;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.config.Configuration;
import net.runelite.http.service.account.AuthFilter;
import net.runelite.http.service.account.beans.SessionEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
public class ConfigController
{
private final ConfigService configService;
private final AuthFilter authFilter;
@Autowired
public ConfigController(ConfigService configService, AuthFilter authFilter)
{
this.configService = configService;
this.authFilter = authFilter;
}
@GetMapping
public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return null;
}
return configService.get(session.getUser());
}
@PatchMapping
public List<String> patch(
HttpServletRequest request,
HttpServletResponse response,
@RequestBody Configuration changes
) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return null;
}
List<String> failures = configService.patch(session.getUser(), changes);
if (failures.size() != 0)
{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return failures;
}
return null;
}
@RequestMapping(path = "/{key:.+}", method = PUT)
public void setKey(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable String key,
@RequestBody(required = false) String value
) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return;
}
if (!configService.setKey(session.getUser(), key, value))
{
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@RequestMapping(path = "/{key:.+}", method = DELETE)
public void unsetKey(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable String key
) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return;
}
if (!configService.unsetKey(session.getUser(), key))
{
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
@@ -1,341 +0,0 @@
/*
* Copyright (c) 2017-2019, Adam <Adam@sigterm.info>
* 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.config;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import static com.mongodb.client.model.Filters.eq;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.model.UpdateOptions;
import static com.mongodb.client.model.Updates.combine;
import static com.mongodb.client.model.Updates.set;
import static com.mongodb.client.model.Updates.unset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import net.runelite.http.api.RuneLiteAPI;
import net.runelite.http.api.config.ConfigEntry;
import net.runelite.http.api.config.Configuration;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class ConfigService
{
private static final int MAX_DEPTH = 8;
private static final int MAX_VALUE_LENGTH = 262144;
private final Gson GSON = RuneLiteAPI.GSON;
private final UpdateOptions upsertUpdateOptions = new UpdateOptions().upsert(true);
private final MongoCollection<Document> mongoCollection;
@Autowired
public ConfigService(
MongoClient mongoClient,
@Value("${mongo.database}") String databaseName
)
{
MongoDatabase database = mongoClient.getDatabase(databaseName);
MongoCollection<Document> collection = database.getCollection("config");
this.mongoCollection = collection;
// Create unique index on _userId
IndexOptions indexOptions = new IndexOptions().unique(true);
collection.createIndex(Indexes.ascending("_userId"), indexOptions);
}
private Document getConfig(int userId)
{
return mongoCollection.find(eq("_userId", userId)).first();
}
public Configuration get(int userId)
{
Map<String, Object> configMap = getConfig(userId);
if (configMap == null || configMap.isEmpty())
{
return new Configuration(Collections.emptyList());
}
List<ConfigEntry> config = new ArrayList<>();
for (String group : configMap.keySet())
{
// Reserved keys
if (group.startsWith("_") || group.startsWith("$"))
{
continue;
}
Map<String, Object> groupMap = (Map) configMap.get(group);
for (Map.Entry<String, Object> entry : groupMap.entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof Map || value instanceof Collection)
{
value = GSON.toJson(entry.getValue());
}
else if (value == null)
{
continue;
}
ConfigEntry configEntry = new ConfigEntry();
configEntry.setKey(group + "." + key.replace(':', '.'));
configEntry.setValue(value.toString());
config.add(configEntry);
}
}
return new Configuration(config);
}
public List<String> patch(int userID, Configuration config)
{
List<String> failures = new ArrayList<>();
List<Bson> sets = new ArrayList<>(config.getConfig().size());
for (ConfigEntry entry : config.getConfig())
{
Bson s = setForKV(entry.getKey(), entry.getValue());
if (s == null)
{
failures.add(entry.getKey());
}
else
{
sets.add(s);
}
}
if (sets.size() > 0)
{
mongoCollection.updateOne(
eq("_userId", userID),
combine(sets),
upsertUpdateOptions
);
}
return failures;
}
@Nullable
private Bson setForKV(String key, @Nullable String value)
{
if (key.startsWith("$") || key.startsWith("_"))
{
return null;
}
String[] split = key.split("\\.", 2);
if (split.length != 2)
{
return null;
}
String dbKey = split[0] + "." + split[1].replace('.', ':');
if (Strings.isNullOrEmpty(value))
{
return unset(dbKey);
}
if (!validateJson(value))
{
return null;
}
Object jsonValue = parseJsonString(value);
return set(dbKey, jsonValue);
}
public boolean setKey(
int userId,
String key,
@Nullable String value
)
{
Bson set = setForKV(key, value);
if (set == null)
{
return false;
}
mongoCollection.updateOne(eq("_userId", userId),
set,
upsertUpdateOptions);
return true;
}
public boolean unsetKey(
int userId,
String key
)
{
Bson set = setForKV(key, null);
if (set == null)
{
return false;
}
mongoCollection.updateOne(eq("_userId", userId), set);
return true;
}
@VisibleForTesting
static Object parseJsonString(String value)
{
Object jsonValue;
try
{
jsonValue = RuneLiteAPI.GSON.fromJson(value, Object.class);
if (jsonValue == null)
{
return value;
}
else if (jsonValue instanceof Double || jsonValue instanceof Float)
{
Number number = (Number) jsonValue;
if (Math.floor(number.doubleValue()) == number.doubleValue() && !Double.isInfinite(number.doubleValue()))
{
// value is an int or long. 'number' might be truncated so parse it from 'value'
try
{
jsonValue = Integer.parseInt(value);
}
catch (NumberFormatException ex)
{
try
{
jsonValue = Long.parseLong(value);
}
catch (NumberFormatException ex2)
{
}
}
}
}
}
catch (JsonSyntaxException ex)
{
jsonValue = value;
}
return jsonValue;
}
@VisibleForTesting
static boolean validateJson(String value)
{
try
{
// I couldn't figure out a better way to do this than a second json parse
JsonElement jsonElement = RuneLiteAPI.GSON.fromJson(value, JsonElement.class);
if (jsonElement == null)
{
return value.length() < MAX_VALUE_LENGTH;
}
return validateObject(jsonElement, 1);
}
catch (JsonSyntaxException ex)
{
// the client submits the string representation of objects which is not always valid json,
// eg. a value with a ':' in it. We just ignore it now. We can't json encode the values client
// side due to them already being strings, which prevents gson from being able to convert them
// to ints/floats/maps etc.
return value.length() < MAX_VALUE_LENGTH;
}
}
private static boolean validateObject(JsonElement jsonElement, int depth)
{
if (depth >= MAX_DEPTH)
{
return false;
}
if (jsonElement.isJsonObject())
{
JsonObject jsonObject = jsonElement.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet())
{
JsonElement element = entry.getValue();
if (!validateObject(element, depth + 1))
{
return false;
}
}
}
else if (jsonElement.isJsonArray())
{
JsonArray jsonArray = jsonElement.getAsJsonArray();
for (int i = 0; i < jsonArray.size(); ++i)
{
JsonElement element = jsonArray.get(i);
if (!validateObject(element, depth + 1))
{
return false;
}
}
}
else if (jsonElement.isJsonPrimitive())
{
JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive();
String value = jsonPrimitive.getAsString();
if (value.length() >= MAX_VALUE_LENGTH)
{
return false;
}
}
return true;
}
}
@@ -1,158 +0,0 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* 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.ge;
import com.google.gson.Gson;
import java.io.IOException;
import java.time.Instant;
import java.util.Collection;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.RuneLiteAPI;
import net.runelite.http.api.ge.GrandExchangeTrade;
import net.runelite.http.service.account.AuthFilter;
import net.runelite.http.service.account.beans.SessionEntry;
import net.runelite.http.service.util.redis.RedisPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
@RestController
@RequestMapping("/ge")
public class GrandExchangeController
{
private static final Gson GSON = RuneLiteAPI.GSON;
private final GrandExchangeService grandExchangeService;
private final AuthFilter authFilter;
private final RedisPool redisPool;
@Autowired
public GrandExchangeController(GrandExchangeService grandExchangeService, AuthFilter authFilter, RedisPool redisPool)
{
this.grandExchangeService = grandExchangeService;
this.authFilter = authFilter;
this.redisPool = redisPool;
}
@PostMapping
public void submit(HttpServletRequest request, HttpServletResponse response, @RequestBody GrandExchangeTrade grandExchangeTrade) throws IOException
{
SessionEntry session = null;
if (request.getHeader(RuneLiteAPI.RUNELITE_AUTH) != null)
{
session = authFilter.handle(request, response);
if (session == null)
{
// error is set here on the response, so we shouldn't continue
return;
}
}
Integer userId = session == null ? null : session.getUser();
// We don't keep track of pending trades in the web UI, so only add cancelled or completed trades
if (userId != null &&
grandExchangeTrade.getQty() > 0 &&
(grandExchangeTrade.isCancel() || grandExchangeTrade.getQty() == grandExchangeTrade.getTotal()))
{
grandExchangeService.add(userId, grandExchangeTrade);
}
Trade trade = new Trade();
trade.setBuy(grandExchangeTrade.isBuy());
trade.setCancel(grandExchangeTrade.isCancel());
trade.setLogin(grandExchangeTrade.isLogin());
trade.setItemId(grandExchangeTrade.getItemId());
trade.setQty(grandExchangeTrade.getQty());
trade.setDqty(grandExchangeTrade.getDqty());
trade.setTotal(grandExchangeTrade.getTotal());
trade.setSpent(grandExchangeTrade.getDspent());
trade.setOffer(grandExchangeTrade.getOffer());
trade.setSlot(grandExchangeTrade.getSlot());
trade.setTime((int) (System.currentTimeMillis() / 1000L));
trade.setMachineId(request.getHeader(RuneLiteAPI.RUNELITE_MACHINEID));
trade.setUserId(userId);
trade.setIp(request.getHeader("X-Forwarded-For"));
trade.setUa(request.getHeader("User-Agent"));
trade.setWorldType(grandExchangeTrade.getWorldType());
trade.setSeq(grandExchangeTrade.getSeq());
Instant resetTime = grandExchangeTrade.getResetTime();
trade.setResetTime(resetTime == null ? 0L : resetTime.getEpochSecond());
String json = GSON.toJson(trade);
try (Jedis jedis = redisPool.getResource())
{
jedis.publish("ge", json);
}
}
@GetMapping
public Collection<GrandExchangeTradeHistory> get(HttpServletRequest request, HttpServletResponse response,
@RequestParam(required = false, defaultValue = "1024") int limit,
@RequestParam(required = false, defaultValue = "0") int offset) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return null;
}
return grandExchangeService.get(session.getUser(), limit, offset).stream()
.map(GrandExchangeController::convert)
.collect(Collectors.toList());
}
private static GrandExchangeTradeHistory convert(TradeEntry tradeEntry)
{
GrandExchangeTradeHistory grandExchangeTrade = new GrandExchangeTradeHistory();
grandExchangeTrade.setBuy(tradeEntry.getAction() == TradeAction.BUY);
grandExchangeTrade.setItemId(tradeEntry.getItem());
grandExchangeTrade.setQuantity(tradeEntry.getQuantity());
grandExchangeTrade.setPrice(tradeEntry.getPrice());
grandExchangeTrade.setTime(tradeEntry.getTime());
return grandExchangeTrade;
}
@DeleteMapping
public void delete(HttpServletRequest request, HttpServletResponse response) throws IOException
{
SessionEntry session = authFilter.handle(request, response);
if (session == null)
{
return;
}
grandExchangeService.delete(session.getUser());
}
}
@@ -1,56 +0,0 @@
/*
* Copyright (c) 2019, Adam <Adam@sigterm.info>
* 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.config;
import com.google.common.collect.ImmutableMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ConfigServiceTest
{
@Test
public void testParseJsonString()
{
assertEquals(1, ConfigService.parseJsonString("1"));
assertEquals(3.14, ConfigService.parseJsonString("3.14"));
assertEquals(1L << 32, ConfigService.parseJsonString("4294967296"));
assertEquals("test", ConfigService.parseJsonString("test"));
assertEquals("test", ConfigService.parseJsonString("\"test\""));
assertEquals(ImmutableMap.of("key", "value"), ConfigService.parseJsonString("{\"key\": \"value\"}"));
}
@Test
public void testValidateJson()
{
assertTrue(ConfigService.validateJson("1"));
assertTrue(ConfigService.validateJson("3.14"));
assertTrue(ConfigService.validateJson("test"));
assertTrue(ConfigService.validateJson("\"test\""));
assertTrue(ConfigService.validateJson("key:value"));
assertTrue(ConfigService.validateJson("{\"key\": \"value\"}"));
assertTrue(ConfigService.validateJson("\n"));
}
}
@@ -1,161 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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.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;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
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"
+ "2,2460\n" // leagues
+ "-1,-1\n"
+ "73,1738\n"
+ "531,1432\n"
+ "324,212\n"
+ "8008,131\n"
+ "1337,911\n"
+ "42,14113\n"
+ "1,777\n"
+ "254,92\n"
+ "-1,-1\n" // lms
+ "1,241\n" // soul wars
+ "24870,37\n"
+ "15020,388\n"
+ "50463,147\n"
+ "-1,-1\n"
+ "92357,1\n"
+ "22758,637\n"
+ "22744,107\n"
+ "-1,-1\n"
+ "20150,17\n"
+ "29400,18\n"
+ "13465,172\n"
+ "1889,581\n"
+ "42891,11\n"
+ "1624,1957\n"
+ "1243,2465\n"
+ "1548,2020\n"
+ "-1,-1\n"
+ "16781,327\n"
+ "19004,149\n"
+ "-1,-1\n"
+ "72046,5\n"
+ "5158,374\n"
+ "20902,279\n"
+ "702,6495\n"
+ "10170,184\n"
+ "8064,202\n"
+ "6936,2\n"
+ "2335,9\n"
+ "-1,-1\n"
+ "-1,-1\n"
+ "19779,22\n"
+ "58283,10\n"
+ "-1,-1\n"
+ "-1,-1\n"
+ "-1,-1\n"
+ "29347,130\n"
+ "723,4\n"
+ "1264,38\n"
+ "44595,4\n"
+ "24820,4\n"
+ "12116,782\n"
+ "2299,724\n"
+ "19301,62\n"
+ "1498,5847\n";
private final MockWebServer server = new MockWebServer();
@Before
public void before() throws IOException
{
server.enqueue(new MockResponse().setBody(RESPONSE));
server.start();
}
@After
public void after() throws IOException
{
server.shutdown();
}
@Test
public void testNormalLookup() throws Exception
{
HiscoreTestService hiscores = new HiscoreTestService(server.url("/"));
HiscoreResult result = hiscores.lookupUsername("zezima", HiscoreEndpoint.NORMAL.getHiscoreURL());
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(324, result.getClueScrollBeginner().getRank());
Assert.assertEquals(8008, result.getClueScrollEasy().getRank());
Assert.assertEquals(911, result.getClueScrollMedium().getLevel());
Assert.assertEquals(42, result.getClueScrollHard().getRank());
Assert.assertEquals(777, result.getClueScrollElite().getLevel());
Assert.assertEquals(254, result.getClueScrollMaster().getRank());
Assert.assertEquals(-1, result.getLastManStanding().getLevel());
Assert.assertEquals(241, result.getSoulWarsZeal().getLevel());
Assert.assertEquals(2460, result.getLeaguePoints().getLevel());
Assert.assertEquals(37, result.getAbyssalSire().getLevel());
Assert.assertEquals(92357, result.getCallisto().getRank());
Assert.assertEquals(5847, result.getZulrah().getLevel());
}
}
@@ -35,6 +35,19 @@ import net.runelite.api.coords.Angle;
*/
public interface GameObject extends TileObject
{
/**
* Get the size of this object, in tiles, on the x axis
*
* @return
*/
int sizeX();
/**
* Get the size of this object, in tiles, on the y axis
*
* @return
*/
int sizeY();
/**
* Gets the minimum x and y scene coordinate pair for this game object.
@@ -5292,7 +5292,7 @@ public final class ItemID
public static final int ARMILLARY_SPHERE = 8345;
public static final int SMALL_ORRERY = 8346;
public static final int LARGE_ORRERY = 8347;
public static final int WOODEN_TELESCOPE = 8348;
public static final int OAK_TELESCOPE = 8348;
public static final int TEAK_TELESCOPE = 8349;
public static final int MAHOGANY_TELESCOPE = 8350;
public static final int CRYSTAL_BALL = 8351;
@@ -5475,7 +5475,7 @@ public final class ItemID
public static final int ARMILLARY_SPHERE_8638 = 8638;
public static final int SMALL_ORRERY_8640 = 8640;
public static final int LARGE_ORRERY_8642 = 8642;
public static final int WOODEN_TELESCOPE_8644 = 8644;
public static final int OAK_TELESCOPE_8644 = 8644;
public static final int TEAK_TELESCOPE_8646 = 8646;
public static final int MAHOGANY_TELESCOPE_8648 = 8648;
public static final int BANNER = 8650;
@@ -7076,7 +7076,7 @@ public final class ItemID
public static final int HUNTING_MIX1 = 11519;
public static final int ZAMORAK_MIX2 = 11521;
public static final int ZAMORAK_MIX1 = 11523;
public static final int WIMPY_FEATHER = 11525;
public static final int FEATHER_11525 = 11525;
public static final int BOOK_OF_KNOWLEDGE = 11640;
public static final int GLASSBLOWING_BOOK = 11656;
public static final int VOID_MAGE_HELM = 11663;
@@ -11643,7 +11643,7 @@ public final class ItemID
public static final int BLACK_MASK_1_I_25275 = 25275;
public static final int BLACK_MASK_I_25276 = 25276;
public static final int SALVE_AMULETEI_25278 = 25278;
public static final int PURE_ESSENCE_PACK = 25280;
public static final int ESSENCE_PACK = 25280;
public static final int SLED_25282 = 25282;
public static final int RED_FIREFLIES = 25283;
public static final int GREEN_FIREFLIES = 25284;
@@ -11755,21 +11755,56 @@ public final class ItemID
public static final int CLUE_SCROLL_ELITE_25499 = 25499;
public static final int CURSED_BANANA = 25500;
public static final int BANANA_CAPE = 25502;
public static final int LIST_OF_MONKEY_SIGHTINGS = 25504;
public static final int PREMIUM_BANANA = 25505;
public static final int BAMBOO = 25506;
public static final int MONKEY_CAGE = 25507;
public static final int DONIES_CAGED_MONKEY = 25508;
public static final int BOBS_CAGED_MONKEY = 25509;
public static final int AERECKS_CAGED_MONKEY = 25510;
public static final int COWS_CAGED_MONKEY = 25511;
public static final int UNICORNS_CAGED_MONKEY = 25512;
public static final int SHEEPS_CAGED_MONKEY = 25513;
public static final int UNICORN_HORN_25514 = 25514;
public static final int DHAROKS_PLATEBODY_25515 = 25515;
public static final int DHAROKS_GREATAXE_25516 = 25516;
public static final int VOLATILE_NIGHTMARE_STAFF_25517 = 25517;
public static final int ANCESTRAL_HAT_25518 = 25518;
public static final int JALREKJAD = 25519;
public static final int JAR_OF_SPIRITS = 25521;
public static final int JAR_OF_SMOKE = 25524;
public static final int STARDUST = 25527;
public static final int SOFT_CLAY_PACK_25533 = 25533;
public static final int ESSENCE_PACK_25535 = 25535;
public static final int BAG_FULL_OF_GEMS_25537 = 25537;
public static final int CELESTIAL_RING_UNCHARGED = 25539;
public static final int CELESTIAL_RING = 25541;
public static final int CELESTIAL_SIGNET_UNCHARGED = 25543;
public static final int CELESTIAL_SIGNET = 25545;
public static final int STAR_FRAGMENT = 25547;
public static final int GOLDEN_PROSPECTOR_HELMET = 25549;
public static final int GOLDEN_PROSPECTOR_JACKET = 25551;
public static final int GOLDEN_PROSPECTOR_LEGS = 25553;
public static final int GOLDEN_PROSPECTOR_BOOTS = 25555;
public static final int DARK_FLIPPERS = 25557;
public static final int BIG_HARPOONFISH = 25559;
public static final int STUFFED_BIG_HARPOONFISH = 25561;
public static final int MOUNTED_HARPOONFISH = 25563;
public static final int RAW_HARPOONFISH = 25564;
public static final int HARPOONFISH = 25565;
public static final int CRYSTALLISED_HARPOONFISH = 25566;
public static final int THE_DESERT_TROUT__SHIPS_LOG = 25567;
public static final int SPIRIT_ANGLERS_RESEARCH_NOTES = 25569;
public static final int DAMP_EGG = 25571;
public static final int TOME_OF_WATER = 25574;
public static final int TOME_OF_WATER_EMPTY = 25576;
public static final int SOAKED_PAGE = 25578;
public static final int TACKLE_BOX = 25580;
public static final int FISH_BARREL = 25582;
public static final int OPEN_FISH_BARREL = 25584;
public static final int FISH_SACK_BARREL = 25585;
public static final int OPEN_FISH_SACK_BARREL = 25587;
public static final int SPIRIT_FLAKES = 25588;
public static final int CASKET_25590 = 25590;
public static final int SPIRIT_ANGLER_HEADBAND = 25592;
public static final int SPIRIT_ANGLER_TOP = 25594;
public static final int SPIRIT_ANGLER_WADERS = 25596;
public static final int SPIRIT_ANGLER_BOOTS = 25598;
public static final int GREAT_BLUE_HERON = 25600;
public static final int TINY_TEMPOR = 25602;
public static final int GREGGS_EASTDOOR = 25604;
public static final int PROPELLER_HAT = 25606;
public static final int GREGGS_IOU = 25608;
public static final int PASTEL_FLOWERS = 25609;
public static final int THICK_DYE = 25610;
/* This file is automatically generated. Do not edit. */
}
@@ -885,6 +885,7 @@ public final class NpcID
public static final int CLAY_GOLEM = 917;
public static final int CLAY_GOLEM_918 = 918;
public static final int GHOST_920 = 920;
public static final int DONIE = 921;
public static final int RESTLESS_GHOST = 922;
public static final int FATHER_URHNEY = 923;
public static final int SKELETON_924 = 924;
@@ -2637,6 +2638,7 @@ public final class NpcID
public static final int PIGLET_2809 = 2809;
public static final int PIGLET_2810 = 2810;
public static final int PIGLET_2811 = 2811;
public static final int FATHER_AERECK = 2812;
public static final int SHOP_KEEPER = 2813;
public static final int SHOP_ASSISTANT = 2814;
public static final int SHOP_KEEPER_2815 = 2815;
@@ -6162,6 +6164,7 @@ public final class NpcID
public static final int LAMMY_LANGLE = 6814;
public static final int MAN_6815 = 6815;
public static final int GEE = 6816;
public static final int GREAT_BLUE_HERON = 6817;
public static final int MAN_6818 = 6818;
public static final int TOWN_CRIER_6823 = 6823;
public static final int GIANT_BAT_6824 = 6824;
@@ -8924,59 +8927,82 @@ public final class NpcID
public static final int SCRUBFOOT = 10559;
public static final int GARL = 10560;
public static final int RED_FIREFLIES = 10561;
public static final int DONIE = 10562;
public static final int DONIE_10563 = 10563;
public static final int TINY_TEMPOR = 10562;
public static final int CRAB_10563 = 10563;
public static final int GREEN_FIREFLIES = 10564;
public static final int FATHER_AERECK = 10565;
public static final int FISHING_SPOT_10565 = 10565;
public static final int GOBLIN_10566 = 10566;
public static final int GOBLIN_10567 = 10567;
public static final int FATHER_AERECK_10568 = 10568;
public static final int DUKE_HORACIO_10569 = 10569;
public static final int AWOWOGEI_10570 = 10570;
public static final int ZEKE_10571 = 10571;
public static final int ELUNED_10572 = 10572;
public static final int MOFINA_10573 = 10573;
public static final int BOB_10574 = 10574;
public static final int FATHER_AERECK_10575 = 10575;
public static final int DONIE_10576 = 10576;
public static final int MONKEY_ON_COW = 10577;
public static final int SHEEP_10578 = 10578;
public static final int MONKEY_ON_UNICORN = 10579;
public static final int BOB_10580 = 10580;
public static final int BOB_10581 = 10581;
public static final int BOB_10582 = 10582;
public static final int DONIE_10583 = 10583;
public static final int DONIE_10584 = 10584;
public static final int DONIE_10585 = 10585;
public static final int DONIE_10586 = 10586;
public static final int FATHER_AERECK_10587 = 10587;
public static final int FATHER_AERECK_10588 = 10588;
public static final int FISHING_SPOT_10568 = 10568;
public static final int FISHING_SPOT_10569 = 10569;
public static final int INACTIVE_SPIRIT_POOL = 10570;
public static final int SPIRIT_POOL = 10571;
public static final int TEMPOROSS = 10572;
public static final int TEMPOROSS_10574 = 10574;
public static final int TEMPOROSS_10575 = 10575;
public static final int AMMUNITION_CRATE = 10576;
public static final int AMMUNITION_CRATE_10577 = 10577;
public static final int AMMUNITION_CRATE_10578 = 10578;
public static final int AMMUNITION_CRATE_10579 = 10579;
public static final int LIGHTNING_CLOUD = 10580;
public static final int CAPTAIN_PUDI = 10583;
public static final int CAPTAIN_DUDI = 10584;
public static final int CAPTAIN_PUDI_10585 = 10585;
public static final int CAPTAIN_PUDI_10586 = 10586;
public static final int CAPTAIN_DUDI_10587 = 10587;
public static final int CAPTAIN_DUDI_10588 = 10588;
public static final int URIUM_SHADE = 10589;
public static final int DAMPE = 10590;
public static final int UNDEAD_ZEALOT = 10591;
public static final int UNDEAD_ZEALOT_10592 = 10592;
public static final int FATHER_AERECK_10593 = 10593;
public static final int FIRST_MATE_DERI = 10593;
public static final int SHEEP_10594 = 10594;
public static final int SHEEP_10595 = 10595;
public static final int SHEEP_10596 = 10596;
public static final int SHEEP_10597 = 10597;
public static final int FIRST_MATE_DERI_10595 = 10595;
public static final int FIRST_MATE_PERI = 10596;
public static final int FIRST_MATE_PERI_10597 = 10597;
public static final int COW_10598 = 10598;
public static final int MONKEY_ON_COW_10599 = 10599;
public static final int MONKEY_ON_COW_10600 = 10600;
public static final int COW_10601 = 10601;
public static final int MONKEY_ON_UNICORN_10603 = 10603;
public static final int MONKEY_ON_UNICORN_10604 = 10604;
public static final int MONKEY_ON_UNICORN_10605 = 10605;
public static final int UNICORN_10607 = 10607;
public static final int UNICORN_10608 = 10608;
public static final int UNICORN1337KILR = 10609;
public static final int BOB_10610 = 10610;
public static final int BOB_10611 = 10611;
public static final int CANNONEER = 10599;
public static final int CANNONEER_10600 = 10600;
public static final int CANNONEER_10601 = 10601;
public static final int CANNONEER_10602 = 10602;
public static final int MONKEY_ON_UNICORN = 10603;
public static final int SAILOR_10604 = 10604;
public static final int SPIRIT_ANGLER = 10605;
public static final int SPIRIT_ANGLER_10606 = 10606;
public static final int SPIRIT_ANGLER_10607 = 10607;
public static final int SPIRIT_ANGLER_10608 = 10608;
public static final int SPIRIT_ANGLER_10609 = 10609;
public static final int FERRYMAN_SATHWOOD = 10610;
public static final int FERRYMAN_NATHWOOD = 10611;
public static final int RETIRED_SAILOR = 10612;
public static final int GITA_PRYMES = 10613;
public static final int TAIMAN = 10614;
public static final int KOANEE = 10615;
public static final int TIMALLUS = 10616;
public static final int LAURETTA = 10617;
public static final int ISHMAEL = 10618;
public static final int BOB_10619 = 10619;
public static final int JALREKJAD = 10620;
public static final int TZHAARKETRAK = 10621;
public static final int TZHAARKETRAK_10622 = 10622;
public static final int JALTOKJAD_10623 = 10623;
public static final int YTHURKOT_10624 = 10624;
public static final int JALREKJAD_10625 = 10625;
public static final int SHADOW_10628 = 10628;
public static final int DUSURI = 10630;
public static final int DUSURI_10631 = 10631;
public static final int STAR_SPRITE = 10632;
public static final int SHANTAY_GUARD_10634 = 10634;
public static final int FISHING_SPOT_10635 = 10635;
public static final int GREAT_BLUE_HERON_10636 = 10636;
public static final int TINY_TEMPOR_10637 = 10637;
public static final int GREGG = 10638;
public static final int GREGG_10639 = 10639;
public static final int GREGG_10640 = 10640;
public static final int GREGG_10641 = 10641;
public static final int GREGG_10642 = 10642;
public static final int GREGG_10643 = 10643;
public static final int CAT_10644 = 10644;
public static final int AGGIE_10645 = 10645;
/* This file is automatically generated. Do not edit. */
}
@@ -13538,6 +13538,61 @@ public final class NullItemID
public static final int NULL_25483 = 25483;
public static final int NULL_25501 = 25501;
public static final int NULL_25503 = 25503;
public static final int NULL_25504 = 25504;
public static final int NULL_25505 = 25505;
public static final int NULL_25506 = 25506;
public static final int NULL_25507 = 25507;
public static final int NULL_25508 = 25508;
public static final int NULL_25509 = 25509;
public static final int NULL_25510 = 25510;
public static final int NULL_25511 = 25511;
public static final int NULL_25512 = 25512;
public static final int NULL_25513 = 25513;
public static final int NULL_25514 = 25514;
public static final int NULL_25520 = 25520;
public static final int NULL_25522 = 25522;
public static final int NULL_25523 = 25523;
public static final int NULL_25525 = 25525;
public static final int NULL_25526 = 25526;
public static final int NULL_25528 = 25528;
public static final int NULL_25529 = 25529;
public static final int NULL_25530 = 25530;
public static final int NULL_25531 = 25531;
public static final int NULL_25532 = 25532;
public static final int NULL_25534 = 25534;
public static final int NULL_25536 = 25536;
public static final int NULL_25538 = 25538;
public static final int NULL_25540 = 25540;
public static final int NULL_25542 = 25542;
public static final int NULL_25544 = 25544;
public static final int NULL_25546 = 25546;
public static final int NULL_25548 = 25548;
public static final int NULL_25550 = 25550;
public static final int NULL_25552 = 25552;
public static final int NULL_25554 = 25554;
public static final int NULL_25556 = 25556;
public static final int NULL_25558 = 25558;
public static final int NULL_25560 = 25560;
public static final int NULL_25562 = 25562;
public static final int NULL_25568 = 25568;
public static final int NULL_25570 = 25570;
public static final int NULL_25572 = 25572;
public static final int NULL_25573 = 25573;
public static final int NULL_25575 = 25575;
public static final int NULL_25577 = 25577;
public static final int NULL_25579 = 25579;
public static final int NULL_25581 = 25581;
public static final int NULL_25583 = 25583;
public static final int NULL_25586 = 25586;
public static final int NULL_25589 = 25589;
public static final int NULL_25591 = 25591;
public static final int NULL_25593 = 25593;
public static final int NULL_25595 = 25595;
public static final int NULL_25597 = 25597;
public static final int NULL_25599 = 25599;
public static final int NULL_25601 = 25601;
public static final int NULL_25603 = 25603;
public static final int NULL_25605 = 25605;
public static final int NULL_25607 = 25607;
/* This file is automatically generated. Do not edit. */
}
@@ -41,7 +41,6 @@ public final class NullNpcID
public static final int NULL_915 = 915;
public static final int NULL_916 = 916;
public static final int NULL_919 = 919;
public static final int NULL_921 = 921;
public static final int NULL_1023 = 1023;
public static final int NULL_1033 = 1033;
public static final int NULL_1034 = 1034;
@@ -174,7 +173,6 @@ public final class NullNpcID
public static final int NULL_2779 = 2779;
public static final int NULL_2780 = 2780;
public static final int NULL_2781 = 2781;
public static final int NULL_2812 = 2812;
public static final int NULL_2831 = 2831;
public static final int NULL_2934 = 2934;
public static final int NULL_2935 = 2935;
@@ -643,7 +641,6 @@ public final class NullNpcID
public static final int NULL_6808 = 6808;
public static final int NULL_6809 = 6809;
public static final int NULL_6810 = 6810;
public static final int NULL_6817 = 6817;
public static final int NULL_6819 = 6819;
public static final int NULL_6820 = 6820;
public static final int NULL_6821 = 6821;
@@ -1621,16 +1618,16 @@ public final class NullNpcID
public static final int NULL_10553 = 10553;
public static final int NULL_10554 = 10554;
public static final int NULL_10555 = 10555;
public static final int NULL_10602 = 10602;
public static final int NULL_10606 = 10606;
public static final int NULL_10612 = 10612;
public static final int NULL_10613 = 10613;
public static final int NULL_10614 = 10614;
public static final int NULL_10615 = 10615;
public static final int NULL_10616 = 10616;
public static final int NULL_10617 = 10617;
public static final int NULL_10618 = 10618;
public static final int NULL_10619 = 10619;
public static final int NULL_10573 = 10573;
public static final int NULL_10581 = 10581;
public static final int NULL_10582 = 10582;
public static final int NULL_10626 = 10626;
public static final int NULL_10627 = 10627;
public static final int NULL_10629 = 10629;
public static final int NULL_10633 = 10633;
public static final int NULL_10646 = 10646;
public static final int NULL_10647 = 10647;
public static final int NULL_10648 = 10648;
public static final int NULL_10649 = 10649;
/* This file is automatically generated. Do not edit. */
}
@@ -20020,6 +20020,11 @@ public final class NullObjectID
public static final int NULL_40960 = 40960;
public static final int NULL_40961 = 40961;
public static final int NULL_40962 = 40962;
public static final int NULL_40968 = 40968;
public static final int NULL_40969 = 40969;
public static final int NULL_40970 = 40970;
public static final int NULL_40971 = 40971;
public static final int NULL_40972 = 40972;
public static final int NULL_40973 = 40973;
public static final int NULL_40974 = 40974;
public static final int NULL_40975 = 40975;
@@ -20029,6 +20034,7 @@ public final class NullObjectID
public static final int NULL_40979 = 40979;
public static final int NULL_40980 = 40980;
public static final int NULL_40981 = 40981;
public static final int NULL_40982 = 40982;
public static final int NULL_40983 = 40983;
public static final int NULL_40984 = 40984;
public static final int NULL_40985 = 40985;
@@ -20039,27 +20045,15 @@ public final class NullObjectID
public static final int NULL_40990 = 40990;
public static final int NULL_40991 = 40991;
public static final int NULL_40992 = 40992;
public static final int NULL_40993 = 40993;
public static final int NULL_40994 = 40994;
public static final int NULL_40995 = 40995;
public static final int NULL_40996 = 40996;
public static final int NULL_40997 = 40997;
public static final int NULL_40998 = 40998;
public static final int NULL_40999 = 40999;
public static final int NULL_41000 = 41000;
public static final int NULL_41001 = 41001;
public static final int NULL_41002 = 41002;
public static final int NULL_41003 = 41003;
public static final int NULL_41004 = 41004;
public static final int NULL_41005 = 41005;
public static final int NULL_41006 = 41006;
public static final int NULL_41007 = 41007;
public static final int NULL_41008 = 41008;
public static final int NULL_41009 = 41009;
public static final int NULL_41010 = 41010;
public static final int NULL_41011 = 41011;
public static final int NULL_41012 = 41012;
public static final int NULL_41014 = 41014;
public static final int NULL_41019 = 41019;
public static final int NULL_41022 = 41022;
public static final int NULL_41191 = 41191;
public static final int NULL_41192 = 41192;
@@ -20079,5 +20073,150 @@ public final class NullObjectID
public static final int NULL_41208 = 41208;
public static final int NULL_41209 = 41209;
public static final int NULL_41211 = 41211;
public static final int NULL_41231 = 41231;
public static final int NULL_41232 = 41232;
public static final int NULL_41237 = 41237;
public static final int NULL_41246 = 41246;
public static final int NULL_41247 = 41247;
public static final int NULL_41248 = 41248;
public static final int NULL_41249 = 41249;
public static final int NULL_41250 = 41250;
public static final int NULL_41251 = 41251;
public static final int NULL_41252 = 41252;
public static final int NULL_41253 = 41253;
public static final int NULL_41254 = 41254;
public static final int NULL_41255 = 41255;
public static final int NULL_41256 = 41256;
public static final int NULL_41257 = 41257;
public static final int NULL_41258 = 41258;
public static final int NULL_41259 = 41259;
public static final int NULL_41260 = 41260;
public static final int NULL_41261 = 41261;
public static final int NULL_41262 = 41262;
public static final int NULL_41263 = 41263;
public static final int NULL_41264 = 41264;
public static final int NULL_41265 = 41265;
public static final int NULL_41266 = 41266;
public static final int NULL_41267 = 41267;
public static final int NULL_41268 = 41268;
public static final int NULL_41269 = 41269;
public static final int NULL_41270 = 41270;
public static final int NULL_41271 = 41271;
public static final int NULL_41272 = 41272;
public static final int NULL_41273 = 41273;
public static final int NULL_41274 = 41274;
public static final int NULL_41275 = 41275;
public static final int NULL_41276 = 41276;
public static final int NULL_41277 = 41277;
public static final int NULL_41278 = 41278;
public static final int NULL_41279 = 41279;
public static final int NULL_41280 = 41280;
public static final int NULL_41281 = 41281;
public static final int NULL_41282 = 41282;
public static final int NULL_41283 = 41283;
public static final int NULL_41284 = 41284;
public static final int NULL_41285 = 41285;
public static final int NULL_41286 = 41286;
public static final int NULL_41287 = 41287;
public static final int NULL_41288 = 41288;
public static final int NULL_41289 = 41289;
public static final int NULL_41290 = 41290;
public static final int NULL_41291 = 41291;
public static final int NULL_41306 = 41306;
public static final int NULL_41307 = 41307;
public static final int NULL_41313 = 41313;
public static final int NULL_41320 = 41320;
public static final int NULL_41321 = 41321;
public static final int NULL_41322 = 41322;
public static final int NULL_41323 = 41323;
public static final int NULL_41324 = 41324;
public static final int NULL_41325 = 41325;
public static final int NULL_41331 = 41331;
public static final int NULL_41334 = 41334;
public static final int NULL_41335 = 41335;
public static final int NULL_41336 = 41336;
public static final int NULL_41337 = 41337;
public static final int NULL_41338 = 41338;
public static final int NULL_41339 = 41339;
public static final int NULL_41340 = 41340;
public static final int NULL_41341 = 41341;
public static final int NULL_41342 = 41342;
public static final int NULL_41343 = 41343;
public static final int NULL_41344 = 41344;
public static final int NULL_41345 = 41345;
public static final int NULL_41346 = 41346;
public static final int NULL_41347 = 41347;
public static final int NULL_41348 = 41348;
public static final int NULL_41349 = 41349;
public static final int NULL_41350 = 41350;
public static final int NULL_41351 = 41351;
public static final int NULL_41352 = 41352;
public static final int NULL_41353 = 41353;
public static final int NULL_41354 = 41354;
public static final int NULL_41355 = 41355;
public static final int NULL_41356 = 41356;
public static final int NULL_41363 = 41363;
public static final int NULL_41364 = 41364;
public static final int NULL_41372 = 41372;
public static final int NULL_41374 = 41374;
public static final int NULL_41375 = 41375;
public static final int NULL_41376 = 41376;
public static final int NULL_41377 = 41377;
public static final int NULL_41378 = 41378;
public static final int NULL_41379 = 41379;
public static final int NULL_41380 = 41380;
public static final int NULL_41381 = 41381;
public static final int NULL_41382 = 41382;
public static final int NULL_41383 = 41383;
public static final int NULL_41384 = 41384;
public static final int NULL_41385 = 41385;
public static final int NULL_41386 = 41386;
public static final int NULL_41387 = 41387;
public static final int NULL_41388 = 41388;
public static final int NULL_41389 = 41389;
public static final int NULL_41390 = 41390;
public static final int NULL_41391 = 41391;
public static final int NULL_41392 = 41392;
public static final int NULL_41393 = 41393;
public static final int NULL_41394 = 41394;
public static final int NULL_41395 = 41395;
public static final int NULL_41396 = 41396;
public static final int NULL_41397 = 41397;
public static final int NULL_41398 = 41398;
public static final int NULL_41399 = 41399;
public static final int NULL_41400 = 41400;
public static final int NULL_41401 = 41401;
public static final int NULL_41402 = 41402;
public static final int NULL_41403 = 41403;
public static final int NULL_41404 = 41404;
public static final int NULL_41405 = 41405;
public static final int NULL_41406 = 41406;
public static final int NULL_41407 = 41407;
public static final int NULL_41408 = 41408;
public static final int NULL_41409 = 41409;
public static final int NULL_41410 = 41410;
public static final int NULL_41411 = 41411;
public static final int NULL_41412 = 41412;
public static final int NULL_41413 = 41413;
public static final int NULL_41414 = 41414;
public static final int NULL_41415 = 41415;
public static final int NULL_41416 = 41416;
public static final int NULL_41417 = 41417;
public static final int NULL_41418 = 41418;
public static final int NULL_41419 = 41419;
public static final int NULL_41420 = 41420;
public static final int NULL_41421 = 41421;
public static final int NULL_41422 = 41422;
public static final int NULL_41423 = 41423;
public static final int NULL_41424 = 41424;
public static final int NULL_41425 = 41425;
public static final int NULL_41426 = 41426;
public static final int NULL_41427 = 41427;
public static final int NULL_41428 = 41428;
public static final int NULL_41429 = 41429;
public static final int NULL_41430 = 41430;
public static final int NULL_41431 = 41431;
public static final int NULL_41432 = 41432;
public static final int NULL_41433 = 41433;
/* This file is automatically generated. Do not edit. */
}
@@ -20929,18 +20929,31 @@ public final class ObjectID
public static final int ROCKS_40956 = 40956;
public static final int ROCKS_40957 = 40957;
public static final int ROPE_40959 = 40959;
public static final int BAMBOO_MONKEY_TRAP = 40963;
public static final int BANANA_BARREL = 40964;
public static final int BAMBOO_BARREL = 40965;
public static final int CAGED_MONKEY_BOB = 40966;
public static final int CAGED_MONKEY_DONIE = 40967;
public static final int CAGED_MONKEY_AERECK = 40968;
public static final int CAGED_MONKEY_UNICORN = 40969;
public static final int CAGED_MONKEY_COW = 40970;
public static final int CAGED_MONKEY_SHEEP = 40971;
public static final int FIREWORKS = 40972;
public static final int POST_40982 = 40982;
public static final int MOUNTED_HARPOONFISH = 40963;
public static final int HAMMERS_40964 = 40964;
public static final int ROPES = 40965;
public static final int BUCKETS_40966 = 40966;
public static final int HARPOONS = 40967;
public static final int CRATE_40993 = 40993;
public static final int BARREL_40994 = 40994;
public static final int BARREL_40995 = 40995;
public static final int DAMAGED_MAST_40996 = 40996;
public static final int DAMAGED_MAST_40997 = 40997;
public static final int MAST_40998 = 40998;
public static final int MAST_40999 = 40999;
public static final int WATER_PUMP_41000 = 41000;
public static final int WATER_PUMP_41004 = 41004;
public static final int FIRE_41005 = 41005;
public static final int DAMAGED_TOTEM_POLE = 41010;
public static final int DAMAGED_TOTEM_POLE_41011 = 41011;
public static final int TOTEM_POLE_41012 = 41012;
public static final int SCOREBOARD_41013 = 41013;
public static final int ANCIENT_BRAZIER = 41015;
public static final int ANCIENT_BRAZIER_41016 = 41016;
public static final int CORPOREAL_BEAST_DISPLAY_41017 = 41017;
public static final int THERMONUCLEAR_SMOKE_DEVIL_DISPLAY = 41018;
public static final int CRASHED_STAR = 41020;
public static final int CRASHED_STAR_41021 = 41021;
public static final int POTION_OF_POWER_TABLE_41023 = 41023;
public static final int PEDESTAL_SPACE = 41024;
public static final int PEDESTAL_SPACE_41025 = 41025;
@@ -21101,7 +21114,7 @@ public final class ObjectID
public static final int ORNATE_LEAGUE_STATUE = 41180;
public static final int TRAILBLAZER_GLOBE = 41181;
public static final int LEAGUE_ACCOMPLISHMENT_SCROLL = 41182;
public static final int ANCIENT_BRAZIER = 41183;
public static final int ANCIENT_BRAZIER_41183 = 41183;
public static final int ANCIENT_BRAZIER_41184 = 41184;
public static final int ANCIENT_BRAZIER_41185 = 41185;
public static final int ANCIENT_BRAZIER_41186 = 41186;
@@ -21123,5 +21136,71 @@ public final class ObjectID
public static final int GOLD_CHEST_41220 = 41220;
public static final int GOLD_CHEST_41221 = 41221;
public static final int ALTAR_41222 = 41222;
public static final int CRASHED_STAR_41223 = 41223;
public static final int CRASHED_STAR_41224 = 41224;
public static final int CRASHED_STAR_41225 = 41225;
public static final int CRASHED_STAR_41226 = 41226;
public static final int CRASHED_STAR_41227 = 41227;
public static final int CRASHED_STAR_41228 = 41228;
public static final int CRASHED_STAR_41229 = 41229;
public static final int SHOOTING_STAR_NOTICEBOARD = 41230;
public static final int TOTEM_POLE_41233 = 41233;
public static final int MAST_41234 = 41234;
public static final int MAST_41235 = 41235;
public static final int SHRINE_41236 = 41236;
public static final int HARPOONFISH_CANNON = 41238;
public static final int HARPOONFISH_CANNON_41239 = 41239;
public static final int HARPOONFISH_CANNON_41240 = 41240;
public static final int HARPOONFISH_CANNON_41241 = 41241;
public static final int ELECTRIFIED_HARPOONFISH_CANNON = 41242;
public static final int ELECTRIFIED_HARPOONFISH_CANNON_41243 = 41243;
public static final int ELECTRIFIED_HARPOONFISH_CANNON_41244 = 41244;
public static final int ELECTRIFIED_HARPOONFISH_CANNON_41245 = 41245;
public static final int DEBRIS_41292 = 41292;
public static final int DEBRIS_41293 = 41293;
public static final int DEBRIS_41294 = 41294;
public static final int DEBRIS_41295 = 41295;
public static final int EMPTY_POOL = 41296;
public static final int REWARD_POOL = 41297;
public static final int REWARD_POOL_41298 = 41298;
public static final int REWARD_POOL_41299 = 41299;
public static final int REWARD_POOL_41300 = 41300;
public static final int REWARD_POOL_41301 = 41301;
public static final int REWARD_POOL_41302 = 41302;
public static final int REWARD_POOL_41303 = 41303;
public static final int REWARD_POOL_41304 = 41304;
public static final int ROPE_LADDER_41305 = 41305;
public static final int BANNER_41308 = 41308;
public static final int BOOK_TABLE = 41309;
public static final int TABLE_41310 = 41310;
public static final int FERRY = 41311;
public static final int SPIRIT_ANGLER_DOCK = 41312;
public static final int SPIRIT_ANGLER_STATS = 41314;
public static final int BANK_CHEST_41315 = 41315;
public static final int FIRE_41316 = 41316;
public static final int ROCK_41317 = 41317;
public static final int ROCK_41318 = 41318;
public static final int ALTAR_41319 = 41319;
public static final int SHANTAY_PASS_41326 = 41326;
public static final int SLEEPING_BAG_41327 = 41327;
public static final int TABLE_41328 = 41328;
public static final int BARREL_41329 = 41329;
public static final int FISHING_ROD_41330 = 41330;
public static final int CRATES_41332 = 41332;
public static final int WATER_41333 = 41333;
public static final int DOOR_41357 = 41357;
public static final int DOOR_41358 = 41358;
public static final int DOOR_41359 = 41359;
public static final int DOOR_41360 = 41360;
public static final int DOOR_41361 = 41361;
public static final int DOOR_41362 = 41362;
public static final int DOOR_41365 = 41365;
public static final int DOOR_41366 = 41366;
public static final int DOOR_41367 = 41367;
public static final int DOOR_41368 = 41368;
public static final int CRATE_41369 = 41369;
public static final int EASTER_EGGS = 41370;
public static final int BASKET_41371 = 41371;
public static final int POST_41373 = 41373;
/* This file is automatically generated. Do not edit. */
}
@@ -24,11 +24,11 @@
*/
package net.runelite.api;
import net.runelite.api.coords.LocalPoint;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import javax.annotation.Nullable;
import net.runelite.api.coords.LocalPoint;
/**
* Represents an object on a Tile
@@ -24,11 +24,12 @@
*/
package net.runelite.api.events;
import net.runelite.api.widgets.WidgetInfo;
import javax.annotation.Nullable;
import lombok.Data;
import net.runelite.api.widgets.WidgetInfo;
/**
* A MenuManager widget menu was clicked. This event is NOT fired for non-MenuManager menu options
* A MenuManager widget menu was clicked. This event is fired only for MenuManager managed custom menus.
*/
@Data
public class WidgetMenuOptionClicked
@@ -42,7 +43,12 @@ public class WidgetMenuOptionClicked
*/
private String menuTarget;
/**
* The type of widget that was clicked.
* The WidgetInfo of the widget that was clicked, if available.
*/
@Nullable
private WidgetInfo widget;
/**
* The widget id of the widget that was clicked.
*/
private int widgetId;
}
@@ -766,6 +766,10 @@ public class ConfigManager
{
return Integer.parseInt(str);
}
if (type == double.class || type == Double.class)
{
return Double.parseDouble(str);
}
if (type == Color.class)
{
return ColorUtil.fromString(str);
@@ -189,13 +189,13 @@ public enum AgilityShortcut
TAVERLEY_DUNGEON_ROCKS_SOUTH(70, "Rocks", new WorldPoint(2887, 9631, 0), ROCKS, ROCKS_14106),
FOSSIL_ISLAND_HARDWOOD_NORTH(70, "Hole" , new WorldPoint(3712, 3828, 0), HOLE_31481, HOLE_31482),
FOSSIL_ISLAND_HARDWOOD_SOUTH(70, "Hole" , new WorldPoint(3714, 3816, 0), HOLE_31481, HOLE_31482),
AL_KHARID_WINDOW(70, "Window", new WorldPoint(3295, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW)
AL_KHARID_WINDOW(70, "Window", new WorldPoint(3293, 3158, 0), BROKEN_WALL_33344, BIG_WINDOW)
{
@Override
public boolean matches(TileObject object)
{
// there are two BIG_WINDOW objects right next to each other here, but only this one is valid
return object.getId() != BIG_WINDOW || object.getWorldLocation().equals(getWorldLocation());
return object.getId() != BIG_WINDOW || object.getWorldLocation().equals(new WorldPoint(3295, 3158, 0));
}
},
GWD_SARADOMIN_ROPE_NORTH(70, "Rope Descent", new WorldPoint(2912, 5300, 0), NULL_26371, NULL_26561),
@@ -41,7 +41,6 @@ import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.PlayerMenuOptionsChanged;
import net.runelite.api.events.WidgetMenuOptionClicked;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
@@ -78,8 +77,7 @@ public class MenuManager
*/
public void addManagedCustomMenu(WidgetMenuOption customMenuOption)
{
WidgetInfo widget = customMenuOption.getWidget();
managedMenuOptions.put(widget.getId(), customMenuOption);
managedMenuOptions.put(customMenuOption.getWidgetId(), customMenuOption);
}
/**
@@ -89,8 +87,7 @@ public class MenuManager
*/
public void removeManagedCustomMenu(WidgetMenuOption customMenuOption)
{
WidgetInfo widget = customMenuOption.getWidget();
managedMenuOptions.remove(widget.getId(), customMenuOption);
managedMenuOptions.remove(customMenuOption.getWidgetId(), customMenuOption);
}
private boolean menuContainsCustomMenu(WidgetMenuOption customMenuOption)
@@ -208,6 +205,7 @@ public class MenuManager
customMenu.setMenuOption(event.getMenuOption());
customMenu.setMenuTarget(event.getMenuTarget());
customMenu.setWidget(curMenuOption.getWidget());
customMenu.setWidgetId(curMenuOption.getWidgetId());
eventBus.post(customMenu);
return;
}
@@ -24,9 +24,11 @@
*/
package net.runelite.client.menus;
import net.runelite.api.widgets.WidgetInfo;
import java.awt.Color;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.ui.JagexColors;
import net.runelite.client.util.ColorUtil;
@@ -35,20 +37,33 @@ public final class WidgetMenuOption
/**
* The left hand text to be displayed on the menu option. (ex. the menuOption of "Drop Bones" is "Drop")
*/
@Getter
@Setter
private String menuOption;
/**
* The right hand text to be displayed on the menu option. (ex. the menuTarget of "Drop Bones" is "Bones")
*/
@Getter
private String menuTarget;
/**
* The color that the menuTarget should be. Defaults to the brownish color that most menu options have.
*/
@Getter
@Setter
private Color color = JagexColors.MENU_TARGET;
/**
* The widgetinfo to add the option to, if available
*/
@Nullable
@Getter
private final WidgetInfo widget;
/**
* The widget to add the option to
*/
private final WidgetInfo widget;
@Getter
private final int widgetId;
/**
* Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options
@@ -62,11 +77,22 @@ public final class WidgetMenuOption
this.menuOption = menuOption;
setMenuTarget(menuTarget);
this.widget = widget;
this.widgetId = widget.getId();
}
public void setMenuOption(String option)
/**
* Creates a menu to be added to right click menus. The menu will only be added if match is found within the menu options
*
* @param menuOption Option text of this right click option
* @param menuTarget Target text of this right click option
* @param widgetId The widget to attach this option to
*/
public WidgetMenuOption(String menuOption, String menuTarget, int widgetId)
{
menuOption = option;
this.menuOption = menuOption;
setMenuTarget(menuTarget);
this.widget = null;
this.widgetId = widgetId;
}
/**
@@ -78,29 +104,4 @@ public final class WidgetMenuOption
{
menuTarget = ColorUtil.wrapWithColorTag(target, color);
}
public String getMenuOption()
{
return menuOption;
}
public String getMenuTarget()
{
return menuTarget;
}
public WidgetInfo getWidget()
{
return widget;
}
public Color getColor()
{
return color;
}
public void setColor(Color col)
{
color = col;
}
}
@@ -66,7 +66,7 @@ enum CannonSpots
MINIONS_OF_SCARABAS(new WorldPoint(3297, 9252, 0)),
ROGUE(new WorldPoint(3285, 3930, 0)),
SCORPION(new WorldPoint(3233, 10335, 0)),
SKELETON(new WorldPoint(3018, 3592, 0)),
SKELETON(new WorldPoint(3017, 3589, 0)),
SMOKE_DEVIL(new WorldPoint(2398, 9444, 0)),
SPIDER(new WorldPoint(3169, 3886, 0)),
SUQAHS(new WorldPoint(2114, 3943, 0)),
@@ -96,22 +96,22 @@ public class ChatCommandsPlugin extends Plugin
{
private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (?:completion count for |subdued |completed )?(.+?) (?:(?:kill|harvest|lap|completion) )?(?:count )?is: <col=ff0000>(\\d+)</col>");
private static final String COX_TEAM_SIZES = "(?:\\d+(?:\\+|-\\d+)? players|Solo)";
private static final Pattern RAIDS_PB_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>(?<pb>[0-9:]+)</col> \\(new personal best\\)</col>");
private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>[0-9:]+</col> Personal best: </col><col=ff0000>(?<pb>[0-9:]+)</col>");
private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>(?<pb>[0-9:]+)</col> \\(Personal best!\\)");
private static final Pattern TOB_WAVE_DURATION_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>[0-9:]+</col><br></col>Personal best: (?<pb>[0-9:]+)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: <col=ff0000>[0-9:]+</col>\\. Personal best: (?:<col=ff0000>)?(?<pb>[0-9:]+)");
private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: <col=ff0000>(?<pb>[0-9:]+)</col> \\(new personal best\\)");
private static final Pattern RAIDS_PB_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)</col>");
private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + COX_TEAM_SIZES + "</col> Duration:</col> <col=ff0000>[0-9:.]+</col> Personal best: </col><col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col>");
private static final Pattern TOB_WAVE_PB_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(Personal best!\\)");
private static final Pattern TOB_WAVE_DURATION_PATTERN = Pattern.compile("^.*Theatre of Blood wave completion time: <col=ff0000>[0-9:.]+</col><br></col>Personal best: (?<pb>[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: <col=ff0000>[0-9:.]+</col>\\. Personal best: (?:<col=ff0000>)?(?<pb>[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)");
private static final Pattern DUEL_ARENA_WINS_PATTERN = Pattern.compile("You (were defeated|won)! You have(?: now)? won (\\d+) duels?");
private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost (\\d+) duels?");
private static final Pattern ADVENTURE_LOG_TITLE_PATTERN = Pattern.compile("The Exploits of (.+)");
private static final Pattern ADVENTURE_LOG_COX_PB_PATTERN = Pattern.compile("Fastest (?:kill|run)(?: - \\(Team size: " + COX_TEAM_SIZES + "\\))?: ([0-9:]+)");
private static final Pattern ADVENTURE_LOG_COX_PB_PATTERN = Pattern.compile("Fastest (?:kill|run)(?: - \\(Team size: " + COX_TEAM_SIZES + "\\))?: ([0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern ADVENTURE_LOG_BOSS_PB_PATTERN = Pattern.compile("[a-zA-Z]+(?: [a-zA-Z]+)*");
private static final Pattern ADVENTURE_LOG_PB_PATTERN = Pattern.compile("(" + ADVENTURE_LOG_BOSS_PB_PATTERN + "(?: - " + ADVENTURE_LOG_BOSS_PB_PATTERN + ")*) (?:" + ADVENTURE_LOG_COX_PB_PATTERN + "( )*)+");
private static final Pattern HS_PB_PATTERN = Pattern.compile("Floor (?<floor>\\d) time: <col=ff0000>(?<floortime>[0-9:]+)</col>(?: \\(new personal best\\)|. Personal best: (?<floorpb>[0-9:]+))" +
"(?:<br>Overall time: <col=ff0000>(?<otime>[0-9:]+)</col>(?: \\(new personal best\\)|. Personal best: (?<opb>[0-9:]+)))?");
private static final Pattern HS_KC_FLOOR_PATTERN = Pattern.compile("You have completed Floor (\\d) of the Hallowed Sepulchre! Total completions: <col=ff0000>(\\d+)</col>\\.");
private static final Pattern HS_KC_GHC_PATTERN = Pattern.compile("You have opened the Grand Hallowed Coffin <col=ff0000>(\\d+)</col> times?!");
private static final Pattern HS_PB_PATTERN = Pattern.compile("Floor (?<floor>\\d) time: <col=ff0000>(?<floortime>[0-9:]+(?:\\.[0-9]+)?)</col>(?: \\(new personal best\\)|. Personal best: (?<floorpb>[0-9:]+(?:\\.[0-9]+)?))" +
"(?:<br>Overall time: <col=ff0000>(?<otime>[0-9:]+(?:\\.[0-9]+)?)</col>(?: \\(new personal best\\)|. Personal best: (?<opb>[0-9:]+(?:\\.[0-9]+)?)))?");
private static final Pattern HS_KC_FLOOR_PATTERN = Pattern.compile("You have completed Floor (\\d) of the Hallowed Sepulchre! Total completions: <col=ff0000>([0-9,]+)</col>\\.");
private static final Pattern HS_KC_GHC_PATTERN = Pattern.compile("You have opened the Grand Hallowed Coffin <col=ff0000>([0-9,]+)</col> times?!");
private static final String TOTAL_LEVEL_COMMAND_STRING = "!total";
private static final String PRICE_COMMAND_STRING = "!price";
@@ -143,7 +143,7 @@ public class ChatCommandsPlugin extends Plugin
private HiscoreEndpoint hiscoreEndpoint; // hiscore endpoint for current player
private String lastBossKill;
private int lastBossTime = -1;
private int lastPb = -1;
private double lastPb = -1;
@Inject
private Client client;
@@ -251,14 +251,14 @@ public class ChatCommandsPlugin extends Plugin
return killCount == null ? 0 : killCount;
}
private void setPb(String boss, int seconds)
private void setPb(String boss, double seconds)
{
configManager.setRSProfileConfiguration("personalbest", boss.toLowerCase(), seconds);
}
private int getPb(String boss)
private double getPb(String boss)
{
Integer personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), int.class);
Double personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), double.class);
return personalBest == null ? 0 : personalBest;
}
@@ -394,14 +394,14 @@ public class ChatCommandsPlugin extends Plugin
if (matcher.find())
{
int floor = Integer.parseInt(matcher.group(1));
int kc = Integer.parseInt(matcher.group(2));
int kc = Integer.parseInt(matcher.group(2).replaceAll(",", ""));
setKc("Hallowed Sepulchre Floor " + floor, kc);
}
matcher = HS_KC_GHC_PATTERN.matcher(message);
if (matcher.find())
{
int kc = Integer.parseInt(matcher.group(1));
int kc = Integer.parseInt(matcher.group(1).replaceAll(",", ""));
setKc("Hallowed Sepulchre", kc);
}
@@ -412,23 +412,24 @@ public class ChatCommandsPlugin extends Plugin
}
}
private static int timeStringToSeconds(String timeString)
@VisibleForTesting
static double timeStringToSeconds(String timeString)
{
String[] s = timeString.split(":");
if (s.length == 2) // mm:ss
{
return Integer.parseInt(s[0]) * 60 + Integer.parseInt(s[1]);
return Integer.parseInt(s[0]) * 60 + Double.parseDouble(s[1]);
}
else if (s.length == 3) // h:mm:ss
{
return Integer.parseInt(s[0]) * 60 * 60 + Integer.parseInt(s[1]) * 60 + Integer.parseInt(s[2]);
return Integer.parseInt(s[0]) * 60 * 60 + Integer.parseInt(s[1]) * 60 + Double.parseDouble(s[2]);
}
return Integer.parseInt(timeString);
return Double.parseDouble(timeString);
}
private void matchPb(Matcher matcher)
{
int seconds = timeStringToSeconds(matcher.group("pb"));
double seconds = timeStringToSeconds(matcher.group("pb"));
if (lastBossKill != null)
{
// Most bosses sent boss kill message, and then pb message, so we
@@ -514,13 +515,13 @@ public class ChatCommandsPlugin extends Plugin
bossName.equalsIgnoreCase("chambers of xeric challenge mode"))
{
Matcher mCoxRuns = ADVENTURE_LOG_COX_PB_PATTERN.matcher(mCounterText.group());
int bestPbTime = Integer.MAX_VALUE;
double bestPbTime = Double.MAX_VALUE;
while (mCoxRuns.find())
{
bestPbTime = Math.min(timeStringToSeconds(mCoxRuns.group(1)), bestPbTime);
}
// So we don't reset people's already saved PB's if they had one before the update
int currentPb = getPb(bossName);
double currentPb = getPb(bossName);
if (currentPb == 0 || currentPb > bestPbTime)
{
setPb(bossName, bestPbTime);
@@ -841,7 +842,7 @@ public class ChatCommandsPlugin extends Plugin
search = longBossName(search);
final int pb;
final double pb;
try
{
pb = chatClient.getPb(player, search);
@@ -852,8 +853,14 @@ public class ChatCommandsPlugin extends Plugin
return;
}
int minutes = pb / 60;
int seconds = pb % 60;
int minutes = (int) (Math.floor(pb) / 60);
double seconds = pb % 60;
// If the seconds is an integer, it is ambiguous if the pb is a precise
// pb or not. So we always show it without the trailing .00.
final String time = Math.floor(seconds) == seconds ?
String.format("%d:%02d", minutes, (int) seconds) :
String.format("%d:%05.2f", minutes, seconds);
String response = new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
@@ -861,7 +868,7 @@ public class ChatCommandsPlugin extends Plugin
.append(ChatColorType.NORMAL)
.append(" personal best: ")
.append(ChatColorType.HIGHLIGHT)
.append(String.format("%d:%02d", minutes, seconds))
.append(time)
.build();
log.debug("Setting response {}", response);
@@ -876,7 +883,7 @@ public class ChatCommandsPlugin extends Plugin
int idx = value.indexOf(' ');
final String boss = longBossName(value.substring(idx + 1));
final int pb = getPb(boss);
final double pb = getPb(boss);
if (pb <= 0)
{
return false;
@@ -78,7 +78,6 @@ public class MapClue extends ClueScroll implements ObjectClueScroll
new MapClue(CLUE_SCROLL_MEDIUM_7292, new WorldPoint(2578, 3597, 0), "South-east of the Lighthouse. Fairy ring ALP"),
new MapClue(CLUE_SCROLL_MEDIUM_7294, new WorldPoint(2666, 3562, 0), "Between Seers' Village and Rellekka. South-west of Fairy ring CJR"),
new MapClue(CLUE_SCROLL_HARD, new WorldPoint(3309, 3503, 0), CRATE_2620, "A crate in the Lumber Yard, north-east of Varrock."),
new MapClue(CLUE_SCROLL_HARD_2729, new WorldPoint(3190, 3963, 0), "Behind the Magic axe hut in level 56 Wilderness."),
new MapClue(CLUE_SCROLL_HARD_3520, new WorldPoint(2615, 3078, 0), "Yanille anvils, south of the bank. You can dig from inside the building."),
new MapClue(CLUE_SCROLL_HARD_3522, new WorldPoint(2488, 3308, 0), "In the western section of West Ardougne."),
new MapClue(CLUE_SCROLL_HARD_3524, new WorldPoint(2457, 3182, 0), CRATE_18506, "In a crate by the stairs to the Observatory Dungeon."),
@@ -85,6 +85,7 @@ enum DiscordGameEventType
BOSS_SARACHNIS("Sarachnis", DiscordAreaType.BOSSES, 7322),
BOSS_SKOTIZO("Skotizo", DiscordAreaType.BOSSES, 6810),
BOSS_SMOKE_DEVIL("Thermonuclear smoke devil", DiscordAreaType.BOSSES, 9363, 9619),
BOSS_TEMPOROSS("Tempoross", DiscordAreaType.BOSSES, 12078),
BOSS_VORKATH("Vorkath", DiscordAreaType.BOSSES, 9023),
BOSS_WINTERTODT("Wintertodt", DiscordAreaType.BOSSES, 6462),
BOSS_ZALCANO("Zalcano", DiscordAreaType.BOSSES, 12126),
@@ -374,7 +375,7 @@ enum DiscordGameEventType
REGION_KEBOS_LOWLANDS("Kebos Lowlands", DiscordAreaType.REGIONS, 4665, 4666, 4921, 5178),
REGION_KEBOS_SWAMP("Kebos Swamp", DiscordAreaType.REGIONS, 4664, 4920, 5174, 5175, 5176, 5430, 5431),
REGION_KHARAZI_JUNGLE("Kharazi Jungle", DiscordAreaType.REGIONS, 11053, 11309, 11565, 11821),
REGION_KHARIDIAN_DESERT("Kharidian Desert", DiscordAreaType.REGIONS, 12844, 12845, 12846, 12847, 12848, 13100, 13101, 13102, 13103, 13104, 13357, 13359, 13360, 13614, 13615, 13616),
REGION_KHARIDIAN_DESERT("Kharidian Desert", DiscordAreaType.REGIONS, 12587, 12844, 12845, 12846, 12847, 12848, 13100, 13101, 13102, 13103, 13104, 13357, 13359, 13360, 13614, 13615, 13616),
REGION_KILLERWATT_PLANE("Killerwatt Plane", DiscordAreaType.REGIONS, 10577),
REGION_KOUREND("Great Kourend", DiscordAreaType.REGIONS, 6201, 6457, 6713),
REGION_KOUREND_WOODLAND("Kourend Woodland", DiscordAreaType.REGIONS, 5942, 6197, 6453),
@@ -411,10 +412,12 @@ enum DiscordGameEventType
REGION_QUARRY("Quarry", DiscordAreaType.REGIONS, 12589),
REGION_RANGING_GUILD("Ranging Guild", DiscordAreaType.REGIONS, 10549),
REGION_RATCATCHERS_MANSION("Ratcatchers Mansion", DiscordAreaType.REGIONS, 11343),
REGION_RUINS_OF_UNKAH("Ruins of Unkah", DiscordAreaType.REGIONS, 12588),
REGION_RUNE_ESSENCE_MINE("Rune Essence Mine", DiscordAreaType.REGIONS, 11595),
// The Beekeper, Pinball, and Gravedigger randoms share a region (7758), and although they are not technically ScapeRune, that name is most commonly
// associated with random events, so those three have been denoted ScapeRune to avoid leaving multiple random event regions without an assigned name.
REGION_SCAPERUNE("ScapeRune", DiscordAreaType.REGIONS, 10058, 7758, 8261),
REGION_SEA_SPIRIT_DOCK("Sea Spirit Dock", DiscordAreaType.REGIONS, 12332),
REGION_SHIP_YARD("Ship Yard", DiscordAreaType.REGIONS, 11823),
REGION_SILVAREA("Silvarea", DiscordAreaType.REGIONS, 13366),
REGION_SINCLAR_MANSION("Sinclair Mansion", DiscordAreaType.REGIONS, 10807),
@@ -511,7 +511,14 @@ class OpenCLManager
new long[]{(long) largeModels * (LARGE_SIZE / largeFaceCount)}, new long[]{LARGE_SIZE / largeFaceCount}, 1, new cl_event[]{acquireGLBuffers}, computeEvents[numComputeEvents++]);
}
clEnqueueReleaseGLObjects(commandQueue, glBuffers.length, glBuffers, numComputeEvents, computeEvents, null);
if (numComputeEvents == 0)
{
clEnqueueReleaseGLObjects(commandQueue, glBuffers.length, glBuffers, 0, null, null);
}
else
{
clEnqueueReleaseGLObjects(commandQueue, glBuffers.length, glBuffers, numComputeEvents, computeEvents, null);
}
}
void finish()
@@ -107,11 +107,11 @@ public class HiscorePanel extends PluginPanel
KALPHITE_QUEEN, KING_BLACK_DRAGON, KRAKEN,
KREEARRA, KRIL_TSUTSAROTH, MIMIC,
NIGHTMARE, OBOR, SARACHNIS,
SCORPIA, SKOTIZO, THE_GAUNTLET,
THE_CORRUPTED_GAUNTLET, THEATRE_OF_BLOOD, THERMONUCLEAR_SMOKE_DEVIL,
TZKAL_ZUK, TZTOK_JAD, VENENATIS,
VETION, VORKATH, WINTERTODT,
ZALCANO, ZULRAH
SCORPIA, SKOTIZO, TEMPOROSS,
THE_GAUNTLET, THE_CORRUPTED_GAUNTLET, THEATRE_OF_BLOOD,
THERMONUCLEAR_SMOKE_DEVIL, TZKAL_ZUK, TZTOK_JAD,
VENENATIS, VETION, VORKATH,
WINTERTODT, ZALCANO, ZULRAH
);
private static final HiscoreEndpoint[] ENDPOINTS = {
@@ -40,12 +40,12 @@ import net.runelite.api.Tile;
import net.runelite.api.coords.Direction;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.events.ConfigChanged;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@@ -118,14 +118,6 @@ public class HunterPlugin extends Plugin
* ------------------------------------------------------------------------------
*/
case ObjectID.DEADFALL: // Deadfall trap placed
if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2)
{
log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), trapLocation);
traps.put(trapLocation, new HunterTrap(gameObject));
lastActionTime = Instant.now();
}
break;
case ObjectID.MONKEY_TRAP: // Maniacal monkey trap placed
// If player is right next to "object" trap assume that player placed the trap
if (localPlayer.getWorldLocation().distanceTo(trapLocation) <= 2)
@@ -166,15 +158,15 @@ public class HunterPlugin extends Plugin
switch (trapOrientation)
{
case NORTH:
translatedTrapLocation = trapLocation.dy(1);
case SOUTH:
translatedTrapLocation = trapLocation.dy(-1);
break;
case EAST:
translatedTrapLocation = trapLocation.dx(1);
case WEST:
translatedTrapLocation = trapLocation.dx(-1);
break;
}
log.debug("Trap placed by \"{}\" on {}", localPlayer.getName(), translatedTrapLocation);
log.debug("Trap placed by \"{}\" on {} facing {}", localPlayer.getName(), translatedTrapLocation, trapOrientation);
traps.put(translatedTrapLocation, new HunterTrap(gameObject));
lastActionTime = Instant.now();
}
@@ -217,14 +217,12 @@ public class WoodcuttingPlugin extends Plugin
{
if (tree.getRespawnTime() != null && !recentlyLoggedIn && currentPlane == object.getPlane())
{
Point max = object.getSceneMaxLocation();
Point min = object.getSceneMinLocation();
int lenX = max.getX() - min.getX();
int lenY = max.getY() - min.getY();
log.debug("Adding respawn timer for {} tree at {}", tree, object.getLocalLocation());
final int region = client.getLocalPlayer().getWorldLocation().getRegionID();
TreeRespawn treeRespawn = new TreeRespawn(tree, lenX, lenY, WorldPoint.fromScene(client, min.getX(), min.getY(), client.getPlane()), Instant.now(), (int) tree.getRespawnTime(region).toMillis());
Point min = object.getSceneMinLocation();
WorldPoint base = WorldPoint.fromScene(client, min.getX(), min.getY(), client.getPlane());
TreeRespawn treeRespawn = new TreeRespawn(tree, object.sizeX() - 1, object.sizeY() - 1,
base, Instant.now(), (int) tree.getRespawnTime(base.getRegionID()).toMillis());
respawns.add(treeRespawn);
}
@@ -24,19 +24,28 @@
*/
package net.runelite.client.plugins.xpglobes;
import java.awt.image.BufferedImage;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Skill;
@Getter
@Setter
@AllArgsConstructor
class XpGlobe
{
private Skill skill;
private int currentXp;
private int currentLevel;
private Instant time;
private int size;
private BufferedImage skillIcon;
XpGlobe(Skill skill, int currentXp, int currentLevel, Instant time)
{
this.skill = skill;
this.currentXp = currentXp;
this.currentLevel = currentLevel;
this.time = time;
}
}
@@ -56,6 +56,7 @@ import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.tooltip.Tooltip;
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
import net.runelite.client.util.ImageUtil;
public class XpGlobesOverlay extends Overlay
{
@@ -65,6 +66,7 @@ public class XpGlobesOverlay extends Overlay
private static final int TOOLTIP_RECT_SIZE_X = 150;
private static final Color DARK_OVERLAY_COLOR = new Color(0, 0, 0, 180);
static final String FLIP_ACTION = "Flip";
private static final double GLOBE_ICON_RATIO = 0.65;
private final Client client;
private final XpGlobesPlugin plugin;
@@ -235,7 +237,8 @@ public class XpGlobesOverlay extends Overlay
private void drawSkillImage(Graphics2D graphics, XpGlobe xpGlobe, int x, int y)
{
BufferedImage skillImage = iconManager.getSkillImage(xpGlobe.getSkill());
final int orbSize = config.xpOrbSize();
final BufferedImage skillImage = getScaledSkillIcon(xpGlobe, orbSize);
if (skillImage == null)
{
@@ -244,12 +247,42 @@ public class XpGlobesOverlay extends Overlay
graphics.drawImage(
skillImage,
x + (config.xpOrbSize() / 2) - (skillImage.getWidth() / 2),
y + (config.xpOrbSize() / 2) - (skillImage.getHeight() / 2),
x + (orbSize / 2) - (skillImage.getWidth() / 2),
y + (orbSize / 2) - (skillImage.getHeight() / 2),
null
);
}
private BufferedImage getScaledSkillIcon(XpGlobe xpGlobe, int orbSize)
{
// Cache the previous icon if the size hasn't changed
if (xpGlobe.getSkillIcon() != null && xpGlobe.getSize() == orbSize)
{
return xpGlobe.getSkillIcon();
}
BufferedImage icon = iconManager.getSkillImage(xpGlobe.getSkill());
if (icon == null)
{
return null;
}
final int size = orbSize - config.progressArcStrokeWidth();
final int width = (int) (size * GLOBE_ICON_RATIO);
final int height = (int) (size * GLOBE_ICON_RATIO);
if (width <= 0 || height <= 0)
{
return null;
}
icon = ImageUtil.resizeImage(icon, width, height);
xpGlobe.setSkillIcon(icon);
xpGlobe.setSize(orbSize);
return icon;
}
private void drawTooltip(XpGlobe mouseOverSkill, int goalXp)
{
// reset the timer on XpGlobe to prevent it from disappearing while hovered over it
@@ -168,6 +168,7 @@ public class GameEventManager
Arrays.stream(tile.getGameObjects())
.filter(Objects::nonNull)
.filter(object -> object.getSceneMinLocation().equals(tile.getSceneLocation()))
.forEach(object ->
{
final GameObjectSpawned objectSpawned = new GameObjectSpawned();
@@ -184,8 +184,7 @@
],
"unicorn horn": [
237,
1487,
25514
1487
],
"wine of zamorak": [
245,
@@ -251,6 +250,10 @@
303,
6209
],
"feather": [
314,
11525
],
"raw shrimps": [
317,
2514,
@@ -489,7 +492,8 @@
19875,
19877,
19879,
19881
19881,
25590
],
"pigeon cage": [
424,
@@ -5971,7 +5975,7 @@
8347,
8642
],
"wooden telescope": [
"oak telescope": [
8348,
8644
],
@@ -7536,7 +7540,8 @@
"soft clay pack": [
12009,
12010,
24851
24851,
25533
],
"black wizard robe": [
12449,
@@ -8264,7 +8269,8 @@
],
"bag of gems": [
19473,
24853
24853,
25537
],
"heavy ballista": [
19481,
@@ -9645,6 +9651,10 @@
25242,
25243
],
"essence pack": [
25280,
25535
],
"gnome child icon": [
25319,
25338
@@ -9677,5 +9687,25 @@
"gold coffin": [
25467,
25473
],
"celestial ring": [
25539,
25541
],
"celestial signet": [
25543,
25545
],
"tome of water": [
25574,
25576
],
"fish barrel": [
25582,
25584
],
"fish sack barrel": [
25585,
25587
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

@@ -164,7 +164,14 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessageEvent);
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.0);
// Precise times
ChatMessage chatMessagePrecise = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>37:04.20</col> (Personal best!)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessagePrecise);
chatCommandsPlugin.onChatMessage(chatMessageEvent);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.2);
}
@Test
@@ -177,7 +184,14 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessageEvent);
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.0);
// Precise times
ChatMessage chatMessagePrecise = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>38:17.00</col><br></col>Personal best: 37:04.40", null, 0);
chatCommandsPlugin.onChatMessage(chatMessagePrecise);
chatCommandsPlugin.onChatMessage(chatMessageEvent);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4.4);
}
@Test
@@ -238,6 +252,7 @@ public class ChatCommandsPluginTest
public void testPersonalBest()
{
final String FIGHT_DURATION = "Fight duration: <col=ff0000>2:06</col>. Personal best: 1:19.";
final String FIGHT_DURATION_PRECISE = "Fight duration: <col=ff0000>2:06.40</col>. Personal best: 1:19.20.";
// This sets lastBoss
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: <col=ff0000>4</col>.", null, 0);
@@ -246,13 +261,20 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 79);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 79.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION_PRECISE, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 79.2);
}
@Test
public void testPersonalBestNoTrailingPeriod()
{
final String FIGHT_DURATION = "Fight duration: <col=ff0000>0:59</col>. Personal best: 0:55";
final String FIGHT_DURATION_PRECISE = "Fight duration: <col=ff0000>0:59.20</col>. Personal best: 0:55.40";
// This sets lastBoss
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Zulrah kill count is: <col=ff0000>4</col>.", null, 0);
@@ -261,13 +283,20 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 55);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 55.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION_PRECISE, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 55.4);
}
@Test
public void testNewPersonalBest()
{
final String NEW_PB = "Fight duration: <col=ff0000>3:01</col> (new personal best).";
final String NEW_PB_PRECISE = "Fight duration: <col=ff0000>3:01.40</col> (new personal best).";
// This sets lastBoss
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: <col=ff0000>4</col>.", null, 0);
@@ -276,7 +305,13 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 181);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 181.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB_PRECISE, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "kree'arra", 181.4);
}
@Test
@@ -311,6 +346,7 @@ public class ChatCommandsPluginTest
public void testAgilityLap()
{
final String NEW_PB = "Lap duration: <col=ff0000>1:01</col> (new personal best).";
final String NEW_PB_PRECISE = "Lap duration: <col=ff0000>1:01.20</col> (new personal best).";
// This sets lastBoss
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Prifddinas Agility Course lap count is: <col=ff0000>2</col>.", null, 0);
@@ -319,8 +355,14 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "prifddinas agility course", 61);
verify(configManager).setRSProfileConfiguration("personalbest", "prifddinas agility course", 61.0);
verify(configManager).setRSProfileConfiguration("killcount", "prifddinas agility course", 2);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB_PRECISE, null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "prifddinas agility course", 61.2);
}
@Test
@@ -332,8 +374,13 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>104:31</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 104 * 60 + 31);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 104 * 60 + 31.0);
verify(configManager).setRSProfileConfiguration("killcount", "tzkal-zuk", 2);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>104:31.20</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 104 * 60 + 31.2);
}
@Test
@@ -345,8 +392,13 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>172:18</col>. Personal best: 134:52", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 134 * 60 + 52);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 134 * 60 + 52.0);
verify(configManager).setRSProfileConfiguration("killcount", "tzkal-zuk", 3);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>172:18.40</col>. Personal best: 134:52.20", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tzkal-zuk", 134 * 60 + 52.2);
}
@Test
@@ -358,8 +410,17 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>179</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 96);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 96.0);
verify(configManager).setRSProfileConfiguration("killcount", "grotesque guardians", 179);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: <col=ff0000>1:36.40</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>179</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 96.4);
}
@Test
@@ -371,12 +432,21 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>32</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 14);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 14.0);
verify(configManager).setRSProfileConfiguration("killcount", "grotesque guardians", 32);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Fight duration: <col=ff0000>2:41.40</col>. Personal best: 2:14.20", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>32</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 14.2);
}
@Test
public void testGuantletPersonalBest()
public void testGauntletPersonalBest()
{
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>10:24</col>. Personal best: 7:59.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
@@ -385,11 +455,20 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 124);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 7 * 60 + 59);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 7 * 60 + 59.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>10:24.20</col>. Personal best: 7:52.40.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>124</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 7 * 60 + 52.4);
}
@Test
public void testGuantletNewPersonalBest()
public void testGauntletNewPersonalBest()
{
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>10:24</col> (new personal best).", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
@@ -397,8 +476,17 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>124</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 10 * 60 + 24);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 10 * 60 + 24.0);
verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 124);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>10:24.40</col> (new personal best).", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>124</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "gauntlet", 10 * 60 + 24.4);
}
@Test
@@ -411,7 +499,16 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 51);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4.0);
// Precise times
chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>24+ players</col> Duration:</col> <col=ff0000>37:04.20</col> (new personal best)</col>>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: <col=ff0000>51</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4.2);
}
@Test
@@ -424,7 +521,16 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 52);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19.0);
// Precise times
chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>11-15 players</col> Duration:</col> <col=ff0000>23:25.40</col> Personal best: </col><col=ff0000>20:19.20</col>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: <col=ff0000>52</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19.2);
}
@Test
@@ -435,7 +541,7 @@ public class ChatCommandsPluginTest
when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget);
when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + PLAYER_NAME);
when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget);
when(configManager.getRSProfileConfiguration(anyString(), anyString(), any(Class.class))).thenReturn(2224);
when(configManager.getRSProfileConfiguration(anyString(), anyString(), any(Class.class))).thenReturn(2224.0);
WidgetLoaded advLogEvent = new WidgetLoaded();
advLogEvent.setGroupId(ADVENTURE_LOG_ID);
@@ -470,14 +576,14 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onWidgetLoaded(countersLogEvent);
chatCommandsPlugin.onGameTick(new GameTick());
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 38 * 60 + 10);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 5 * 60 + 48);
verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 1 * 60 + 21);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 49);
verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 57);
verify(configManager).setRSProfileConfiguration("personalbest", "nightmare", 3 * 60 + 30);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 24 * 60 + 17);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 22 * 60 + 15);
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 38 * 60 + 10.0);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 5 * 60 + 48.0);
verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 60 + 21.0);
verify(configManager).setRSProfileConfiguration("personalbest", "grotesque guardians", 2 * 60 + 49.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 57.0);
verify(configManager).setRSProfileConfiguration("personalbest", "nightmare", 3 * 60 + 30.0);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 24 * 60 + 17.0);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 22 * 60 + 15.0);
}
@Test
@@ -522,12 +628,62 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onWidgetLoaded(countersLogEvent);
chatCommandsPlugin.onGameTick(new GameTick());
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 65 * 60 + 12);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 2 * 60 + 55);
verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 1 * 60 + 37);
verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 1 * 60 + 42);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 21 * 60 + 23);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 21 * 60 + 26);
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 65 * 60 + 12.0);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 2 * 60 + 55.0);
verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 60 + 37.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 60 + 42.0);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 21 * 60 + 23.0);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 21 * 60 + 26.0);
}
@Test
public void testAdventurerLogCountersPagePrecise()
{
Widget advLogWidget = mock(Widget.class);
Widget advLogExploitsTextWidget = mock(Widget.class);
when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget);
when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + PLAYER_NAME);
when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget);
WidgetLoaded advLogEvent = new WidgetLoaded();
advLogEvent.setGroupId(ADVENTURE_LOG_ID);
chatCommandsPlugin.onWidgetLoaded(advLogEvent);
chatCommandsPlugin.onGameTick(new GameTick());
String COUNTER_TEXT = "Duel Arena<br>Wins: <col=d0c0b0>12</col><br>Losses: <col=d0c0b0>20</col>" +
"<br><br>Last Man Standing<br>Rank: <col=d0c0b0>0</col>" +
"<br><br>Treasure Trails<br>Beginner: <col=d0c0b0>1</col><br>Easy: <col=d0c0b0>4</col>" +
"<br>Medium: <col=d0c0b0>35</col><br>Hard: <col=d0c0b0>66</col><br>Elite: <col=d0c0b0>2</col>" +
"<br>Master: <col=d0c0b0>0</col><br>Rank: <col=d0c0b0>Novice</col>" +
"<br><br>Chompy Hunting<br>Kills: <col=d0c0b0>300</col><br>Rank: <col=d0c0b0>Ogre Forester</col>" +
"<br><br>Order of the White Knights<br>Rank: <col=d0c0b0>Unrated</col><br>with a kill score of <col=d0c0b0>99</col>" +
"<br><br>TzHaar Fight Cave<br>Fastest run: <col=d0c0b0>65:12.00</col>" +
"<br><br>Inferno<br>Fastest run: <col=d0c0b0>-</col><br><br>Zulrah<br>" +
"Fastest kill: <col=d0c0b0>2:55.20</col><br><br>Vorkath<br>Fastest kill: <col=d0c0b0>1:37.20</col>" +
"<br><br>Galvek<br>Fastest kill: <col=d0c0b0>-</col><br><br>Grotesque Guardians<br>" +
"Fastest kill: <col=d0c0b0>-</col><br><br>Alchemical Hydra<br>Fastest kill: <col=d0c0b0>-</col>" +
"<br><br>Hespori<br>Fastest kill: <col=d0c0b0>1:42.40</col><br><br>Nightmare<br>" +
"Fastest kill: <col=d0c0b0>-</col><br><br>The Gauntlet<br>Fastest run: <col=d0c0b0>-</col>" +
"<br><br>The Corrupted Gauntlet<br>Fastest run: <col=d0c0b0>-</col><br><br>Fragment of Seren<br>Fastest kill: <col=d0c0b0>-</col>" +
"<br><br>Chambers of Xeric<br>Fastest run - (Team size: Solo): <col=d0c0b0>21:23.20</col><br>Fastest run - (Team size: 3 players): <col=d0c0b0>27:16.40</col>" +
"<br><br>Chambers of Xeric - Challenge mode<br>Fastest run - (Team size: Solo): <col=d0c0b0>34:30.20</col><br>Fastest run - (Team size: 4 players): <col=d0c0b0>21:26.00</col>" +
"<br><br>Barbarian Assault<br>High-level gambles: <col=d0c0b0>0</col><br><br>Fremennik spirits rested: <col=d0c0b0>0</col>";
Widget countersPage = mock(Widget.class);
when(countersPage.getText()).thenReturn(COUNTER_TEXT);
when(client.getWidget(WidgetInfo.GENERIC_SCROLL_TEXT)).thenReturn(countersPage);
WidgetLoaded countersLogEvent = new WidgetLoaded();
countersLogEvent.setGroupId(GENERIC_SCROLL_GROUP_ID);
chatCommandsPlugin.onWidgetLoaded(countersLogEvent);
chatCommandsPlugin.onGameTick(new GameTick());
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 65 * 60 + 12.0);
verify(configManager).setRSProfileConfiguration("personalbest", "zulrah", 2 * 60 + 55.2);
verify(configManager).setRSProfileConfiguration("personalbest", "vorkath", 60 + 37.2);
verify(configManager).setRSProfileConfiguration("personalbest", "hespori", 60 + 42.40);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 21 * 60 + 23.20);
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 21 * 60 + 26.0);
}
@Test
@@ -580,7 +736,13 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 1 time: <col=ff0000>1:19</col>. Personal best: 0:28", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 1", 28);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 1", 28.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 1 time: <col=ff0000>1:19.20</col>. Personal best: 0:28.40", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 1", 28.4);
}
@Test
@@ -589,7 +751,13 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 2 time: <col=ff0000>0:47</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 2", 47);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 2", 47.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 2 time: <col=ff0000>0:47.20</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 2", 47.2);
}
@Test
@@ -598,8 +766,15 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>4:46</col> (new personal best)<br>Overall time: <col=ff0000>9:53</col> (new personal best)<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 4 * 60 + 46);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 53);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 4 * 60 + 46.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 53.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>4:46.20</col> (new personal best)<br>Overall time: <col=ff0000>9:53.40</col> (new personal best)<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 4 * 60 + 46.2);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 53.4);
}
@Test
@@ -608,8 +783,15 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:26</col> (new personal best)<br>Overall time: <col=ff0000>9:17</col>. Personal best: 9:15<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 26);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 15);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 26.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 15.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:26.20</col> (new personal best)<br>Overall time: <col=ff0000>9:17.00</col>. Personal best: 9:15.40<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 26.2);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 15.4);
}
@Test
@@ -618,8 +800,15 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:56</col>. Personal best: 3:05<br>Overall time: <col=ff0000>9:14</col>. Personal best: 7:49<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 5);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 49);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 5.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 49.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:56.40</col>. Personal best: 3:05.20<br>Overall time: <col=ff0000>9:14.20</col>. Personal best: 7:49.20<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 5.2);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 49.2);
}
@Test
@@ -628,26 +817,33 @@ public class ChatCommandsPluginTest
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:10</col>. Personal best: 3:04<br>Overall time: <col=ff0000>7:47</col> (new personal best)<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 4);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 47);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 4.0);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 47.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:10.00</col>. Personal best: 3:04.40<br>Overall time: <col=ff0000>7:47.20</col> (new personal best)<br>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 4.4);
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 47.2);
}
@Test
public void testHsFloorKc()
{
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have completed Floor 5 of the Hallowed Sepulchre! Total completions: <col=ff0000>81</col>.", null, 0);
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have completed Floor 5 of the Hallowed Sepulchre! Total completions: <col=ff0000>1,114</col>.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre floor 5", 81);
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre floor 5", 1114);
}
@Test
public void testHsGhcKc()
{
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have opened the Grand Hallowed Coffin <col=ff0000>36</col> times!", null, 0);
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have opened the Grand Hallowed Coffin <col=ff0000>1,542</col> times!", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre", 36);
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre", 1542);
}
@Test
@@ -662,8 +858,14 @@ public class ChatCommandsPluginTest
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>21:58</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 21 * 60 + 58);
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 21 * 60 + 58.0);
verify(configManager).setRSProfileConfiguration("killcount", "tztok-jad", 2);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>21:58.40</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "tztok-jad", 21 * 60 + 58.4);
}
@Test
@@ -676,7 +878,13 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 1);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 60 + 46);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 60 + 46.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>1:46.40</col> (new personal best)", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 60 + 46.4);
}
@Test
@@ -689,6 +897,25 @@ public class ChatCommandsPluginTest
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 3);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 59);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 59.0);
// Precise times
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Challenge duration: <col=ff0000>1:10.00</col>. Personal best: <col=ff0000>0:59.20</col>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("personalbest", "TzHaar-Ket-Rak's First Challenge".toLowerCase(), 59.2);
}
@Test
public void testTimeStringToSeconds()
{
final double DELTA = 0.0001;
// ss
assertEquals(55.0, ChatCommandsPlugin.timeStringToSeconds("55.00"), DELTA);
// mm:ss
assertEquals(6 * 60 + 55.4, ChatCommandsPlugin.timeStringToSeconds("6:55.40"), DELTA);
// h:mm:ss
assertEquals(2 * 3600 + 50 * 60 + 30.2, ChatCommandsPlugin.timeStringToSeconds("2:50:30.20"), DELTA);
}
}
@@ -47,14 +47,14 @@ public abstract class RSGameObjectMixin implements RSGameObject
@Override
public Point getSceneMinLocation()
{
return new Point(getRelativeX(), getRelativeY());
return new Point(getStartX(), getStartY());
}
@Inject
@Override
public Point getSceneMaxLocation()
{
return new Point(getOffsetX(), getOffsetY());
return new Point(getEndX(), getEndY());
}
@Inject
@@ -108,4 +108,18 @@ public abstract class RSGameObjectMixin implements RSGameObject
int rotation = (getFlags() >> 6) & 3;
return new Angle(rotation * 512 + orientation);
}
@Override
@Inject
public int sizeX()
{
return getEndX() - getStartX() + 1;
}
@Override
@Inject
public int sizeY()
{
return getEndY() - getStartY() + 1;
}
}
@@ -12,16 +12,16 @@ public interface RSGameObject extends GameObject
int getPlane();
@Import("startX")
int getRelativeX();
int getStartX();
@Import("startY")
int getRelativeY();
int getStartY();
@Import("endX")
int getOffsetX();
int getEndX();
@Import("endY")
int getOffsetY();
int getEndY();
@Import("centerX")
@Override