client: Async-ify or improve data loading methods (#1782)
client: Async-ify or improve data loading methods
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -9,6 +9,7 @@ dependencies {
|
||||
compileOnly group: 'org.projectlombok', name: 'lombok', version: lombok
|
||||
|
||||
implementation group: 'com.google.code.gson', name: 'gson', version: gson
|
||||
implementation group: 'com.google.guava', name: 'guava', version: guava
|
||||
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: okhttp3
|
||||
implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: rxjava
|
||||
implementation group: 'org.apache.commons', name: 'commons-csv', version: apacheCommonsCsv
|
||||
|
||||
@@ -26,6 +26,10 @@ package net.runelite.http.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import net.runelite.http.api.item.ItemEquipmentStats;
|
||||
import net.runelite.http.api.item.ItemPrice;
|
||||
import net.runelite.http.api.item.ItemStats;
|
||||
import net.runelite.http.api.util.TypeAdapters;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
@@ -37,7 +41,6 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
@@ -52,26 +55,33 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RuneLiteAPI
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(RuneLiteAPI.class);
|
||||
|
||||
public static final String RUNELITE_AUTH = "RUNELITE-AUTH";
|
||||
|
||||
public static final OkHttpClient CLIENT;
|
||||
public static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ItemStats.class, TypeAdapters.ITEMSTATS)
|
||||
.registerTypeAdapter(ItemEquipmentStats.class, TypeAdapters.EQUIPMENTSTATS)
|
||||
.registerTypeAdapter(ItemPrice.class, TypeAdapters.ITEMPRICE)
|
||||
.create();
|
||||
|
||||
private static final String BASE = "https://api.runelite.net";
|
||||
private static final String WSBASE = "https://api.runelite.net/ws";
|
||||
private static final String STATICBASE = "https://static.runelite.net";
|
||||
|
||||
private static final String OPENOSRS_BASE = /*"https://api.openosrs.com*/ "https://api.runelitepl.us";
|
||||
private static final String OPENOSRS_SESSION = "https://session.openosrs.com";
|
||||
private static final String MAVEN_METADATA = "http://repo.runelite.net/net/runelite/runelite-parent/maven-metadata.xml";
|
||||
|
||||
private static final Properties properties = new Properties();
|
||||
private static String userAgent;
|
||||
|
||||
private static String version;
|
||||
private static String upstreamVersion;
|
||||
private static int rsVersion;
|
||||
|
||||
public static final String RUNELITE_AUTH = "RUNELITE-AUTH";
|
||||
public static final OkHttpClient CLIENT;
|
||||
public static final OkHttpClient RLP_CLIENT;
|
||||
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Logger logger = LoggerFactory.getLogger(RuneLiteAPI.class);
|
||||
private static final String BASE = "https://api.runelite.net";
|
||||
private static final String OPENOSRS_BASE = /*"https://api.openosrs.com*/ "https://api.runelitepl.us";
|
||||
private static final String OPENOSRS_SESSION = "https://session.openosrs.com";
|
||||
private static final String WSBASE = "https://api.runelite.net/ws";
|
||||
private static final String STATICBASE = "https://static.runelite.net";
|
||||
private static final String MAVEN_METADATA =
|
||||
"http://repo.runelite.net/net/runelite/runelite-parent/maven-metadata.xml";
|
||||
private static final Properties properties = new Properties();
|
||||
private static String rlUserAgent;
|
||||
private static String openosrsUserAgent;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
@@ -80,11 +90,11 @@ public class RuneLiteAPI
|
||||
properties.load(in);
|
||||
|
||||
version = properties.getProperty("runelite.version");
|
||||
String rlpCommit = properties.getProperty("runelite.commit");
|
||||
String commit = properties.getProperty("runelite.commit");
|
||||
boolean dirty = Boolean.parseBoolean(properties.getProperty("runelite.dirty"));
|
||||
|
||||
openosrsUserAgent = "openosrs/" + version + "-" + rlpCommit + (dirty ? "+" : "");
|
||||
rlUserAgent = "openosrs/" + version;
|
||||
userAgent = "OpenOSRS/" + version + "-" + commit + (dirty ? "+" : "");
|
||||
|
||||
rsVersion = Integer.parseInt(properties.getProperty("rs.version"));
|
||||
|
||||
parseMavenVersion();
|
||||
@@ -101,8 +111,6 @@ public class RuneLiteAPI
|
||||
|
||||
CLIENT = new OkHttpClient.Builder()
|
||||
.pingInterval(30, TimeUnit.SECONDS)
|
||||
.connectTimeout(8655, TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(8655, TimeUnit.MILLISECONDS)
|
||||
.addNetworkInterceptor(new Interceptor()
|
||||
{
|
||||
@Override
|
||||
@@ -110,25 +118,7 @@ public class RuneLiteAPI
|
||||
{
|
||||
Request userAgentRequest = chain.request()
|
||||
.newBuilder()
|
||||
.header("User-Agent", rlUserAgent)
|
||||
.build();
|
||||
return chain.proceed(userAgentRequest);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
||||
RLP_CLIENT = new OkHttpClient.Builder()
|
||||
.pingInterval(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(5655, TimeUnit.MILLISECONDS)
|
||||
.connectTimeout(2655, TimeUnit.MILLISECONDS)
|
||||
.addNetworkInterceptor(new Interceptor()
|
||||
{
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException
|
||||
{
|
||||
Request userAgentRequest = chain.request()
|
||||
.newBuilder()
|
||||
.header("User-Agent", openosrsUserAgent)
|
||||
.header("User-Agent", userAgent)
|
||||
.build();
|
||||
return chain.proceed(userAgentRequest);
|
||||
}
|
||||
@@ -136,7 +126,7 @@ public class RuneLiteAPI
|
||||
.build();
|
||||
}
|
||||
|
||||
public static HttpUrl getopenosrsSessionBase()
|
||||
public static HttpUrl getSessionBase()
|
||||
{
|
||||
return HttpUrl.parse(OPENOSRS_SESSION);
|
||||
}
|
||||
@@ -153,7 +143,7 @@ public class RuneLiteAPI
|
||||
return HttpUrl.parse(BASE + "/runelite-" + getVersion());
|
||||
}
|
||||
|
||||
public static HttpUrl getPlusApiBase()
|
||||
public static HttpUrl getOpenOSRSApiBase()
|
||||
{
|
||||
return HttpUrl.parse(OPENOSRS_BASE + "/http-service-" + getRlpVersion());
|
||||
}
|
||||
@@ -206,7 +196,7 @@ public class RuneLiteAPI
|
||||
byte[] chunk = new byte[4096];
|
||||
int bytesRead;
|
||||
URLConnection conn = toDownload.openConnection();
|
||||
conn.setRequestProperty("User-Agent", openosrsUserAgent);
|
||||
conn.setRequestProperty("User-Agent", userAgent);
|
||||
stream = conn.getInputStream();
|
||||
|
||||
while ((bytesRead = stream.read(chunk)) > 0)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.http.api.account;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import io.reactivex.Observable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -96,7 +97,7 @@ public class AccountClient
|
||||
}
|
||||
}
|
||||
|
||||
public boolean sessionCheck()
|
||||
public Observable<Boolean> sessionCheck()
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
|
||||
.addPathSegment("account")
|
||||
@@ -105,19 +106,22 @@ public class AccountClient
|
||||
|
||||
logger.debug("Built URI: {}", url);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
||||
.url(url)
|
||||
.build();
|
||||
return Observable.fromCallable(() ->
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
return response.isSuccessful();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug("Unable to verify session", ex);
|
||||
return true; // assume it is still valid if the server is unreachable
|
||||
}
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
return response.isSuccessful();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug("Unable to verify session", ex);
|
||||
return true; // assume it is still valid if the server is unreachable
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class AnimationClient
|
||||
{
|
||||
String json = RuneLiteAPI.GSON.toJson(animationRequest);
|
||||
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("animation")
|
||||
.build();
|
||||
|
||||
@@ -65,7 +65,7 @@ public class AnimationClient
|
||||
|
||||
try
|
||||
{
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
logger.debug("animation response " + response.code());
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class AnimationClient
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
RuneLiteAPI.RLP_CLIENT.newCall(request).enqueue(new Callback()
|
||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
@@ -103,7 +103,7 @@ public class AnimationClient
|
||||
|
||||
public List<AnimationKey> get() throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("animation")
|
||||
.build();
|
||||
|
||||
@@ -111,7 +111,7 @@ public class AnimationClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
InputStream in = response.body().byteStream();
|
||||
// CHECKSTYLE:OFF
|
||||
@@ -128,7 +128,7 @@ public class AnimationClient
|
||||
|
||||
public AnimationKey get(int npcid) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("animation")
|
||||
.addPathSegment(Integer.toString(npcid))
|
||||
.build();
|
||||
@@ -137,7 +137,7 @@ public class AnimationClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
InputStream in = response.body().byteStream();
|
||||
return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), AnimationKey.class);
|
||||
|
||||
@@ -275,7 +275,7 @@ public class ChatClient
|
||||
throw new IOException("Layout " + layout + " is not valid!");
|
||||
}
|
||||
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("chat")
|
||||
.addPathSegment("layout")
|
||||
.addQueryParameter("name", username)
|
||||
@@ -287,7 +287,7 @@ public class ChatClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
return response.isSuccessful();
|
||||
}
|
||||
@@ -318,7 +318,7 @@ public class ChatClient
|
||||
|
||||
public String getLayout(String username) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("chat")
|
||||
.addPathSegment("layout")
|
||||
.addQueryParameter("name", username)
|
||||
@@ -328,7 +328,7 @@ public class ChatClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
{
|
||||
@@ -353,7 +353,7 @@ public class ChatClient
|
||||
|
||||
public House[] getHosts(int world, String location) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("chat")
|
||||
.addPathSegment("hosts")
|
||||
.addQueryParameter("world", Integer.toString(world))
|
||||
@@ -364,7 +364,7 @@ public class ChatClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
{
|
||||
@@ -411,7 +411,7 @@ public class ChatClient
|
||||
|
||||
public boolean submitHost(int world, String location, House house) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("chat")
|
||||
.addPathSegment("hosts")
|
||||
.addQueryParameter("world", Integer.toString(world))
|
||||
@@ -431,7 +431,7 @@ public class ChatClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
return response.isSuccessful();
|
||||
}
|
||||
@@ -439,7 +439,7 @@ public class ChatClient
|
||||
|
||||
public boolean removeHost(int world, String location, House house) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("chat")
|
||||
.addPathSegment("hosts")
|
||||
.addQueryParameter("world", Integer.toString(world))
|
||||
@@ -460,7 +460,7 @@ public class ChatClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.RLP_CLIENT.newCall(request).execute())
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
return response.isSuccessful();
|
||||
}
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
*/
|
||||
package net.runelite.http.api.item;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import io.reactivex.Observable;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
@@ -190,7 +189,7 @@ public class ItemClient
|
||||
});
|
||||
}
|
||||
|
||||
public Observable<ItemPrice[]> getPrices()
|
||||
public Observable<ImmutableMap<Integer, ItemPrice>> getPrices()
|
||||
{
|
||||
HttpUrl.Builder urlBuilder = RuneLiteAPI.getApiBase().newBuilder()
|
||||
.addPathSegment("item")
|
||||
@@ -200,66 +199,64 @@ public class ItemClient
|
||||
|
||||
logger.debug("Built URI: {}", url);
|
||||
|
||||
|
||||
return Observable.defer(() ->
|
||||
return Observable.fromCallable(() ->
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(request).execute())
|
||||
try (JsonReader reader = new JsonReader(client.newCall(request).execute().body().charStream()))
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
ImmutableMap.Builder<Integer, ItemPrice> builder = ImmutableMap.builderWithExpectedSize(3666);
|
||||
reader.beginArray();
|
||||
|
||||
while (reader.hasNext())
|
||||
{
|
||||
logger.warn("Error looking up prices: {}", response);
|
||||
return Observable.just(null);
|
||||
ItemPrice price = RuneLiteAPI.GSON.fromJson(reader, ItemPrice.class);
|
||||
|
||||
builder.put(
|
||||
price.getId(),
|
||||
price
|
||||
);
|
||||
}
|
||||
|
||||
InputStream in = response.body().byteStream();
|
||||
return Observable.just(RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), ItemPrice[].class));
|
||||
}
|
||||
catch (JsonParseException ex)
|
||||
{
|
||||
return Observable.error(ex);
|
||||
reader.endArray();
|
||||
return builder.build();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Observable<Map<Integer, ItemStats>> getStats()
|
||||
public Observable<ImmutableMap<Integer, ItemStats>> getStats()
|
||||
{
|
||||
HttpUrl.Builder urlBuilder = RuneLiteAPI.getStaticBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getStaticBase()
|
||||
.newBuilder()
|
||||
.addPathSegment("item")
|
||||
// TODO: Change this to stats.min.json later after release is undeployed
|
||||
.addPathSegment("stats.ids.min.json");
|
||||
.addPathSegment("stats.ids.min.json")
|
||||
.build();
|
||||
|
||||
HttpUrl url = urlBuilder.build();
|
||||
|
||||
logger.debug("Built URI: {}", url);
|
||||
|
||||
|
||||
return Observable.defer(() ->
|
||||
logger.debug("Built URI {}", url);
|
||||
return Observable.fromCallable(() ->
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(request).execute())
|
||||
try (JsonReader reader = new JsonReader(client.newCall(request).execute().body().charStream()))
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
// This is the size the items are as I wrote this. the builder gets increased by 1 every time otherwise
|
||||
ImmutableMap.Builder<Integer, ItemStats> builder = ImmutableMap.builderWithExpectedSize(7498);
|
||||
reader.beginObject();
|
||||
|
||||
while (reader.hasNext())
|
||||
{
|
||||
logger.warn("Error looking up item stats: {}", response);
|
||||
return Observable.just(null);
|
||||
builder.put(
|
||||
Integer.parseInt(reader.nextName()),
|
||||
RuneLiteAPI.GSON.fromJson(reader, ItemStats.class)
|
||||
);
|
||||
}
|
||||
|
||||
InputStream in = response.body().byteStream();
|
||||
final Type typeToken = new TypeToken<Map<Integer, ItemStats>>()
|
||||
{
|
||||
}.getType();
|
||||
return Observable.just(RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), typeToken));
|
||||
}
|
||||
catch (JsonParseException ex)
|
||||
{
|
||||
return Observable.error(ex);
|
||||
reader.endObject();
|
||||
return builder.build();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@Builder(builderClassName = "Builder")
|
||||
public class ItemEquipmentStats
|
||||
{
|
||||
private int slot;
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
*/
|
||||
package net.runelite.http.api.item;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
@Builder(builderClassName = "Builder")
|
||||
public class ItemStats
|
||||
{
|
||||
private String name;
|
||||
private boolean quest;
|
||||
private boolean equipable;
|
||||
private double weight;
|
||||
@@ -51,9 +54,9 @@ public class ItemStats
|
||||
{
|
||||
final ItemEquipmentStats equipment = this.equipment != null
|
||||
? this.equipment
|
||||
: new ItemEquipmentStats.ItemEquipmentStatsBuilder().build();
|
||||
: new ItemEquipmentStats.Builder().build();
|
||||
|
||||
newEquipment = new ItemEquipmentStats.ItemEquipmentStatsBuilder()
|
||||
newEquipment = new ItemEquipmentStats.Builder()
|
||||
.slot(equipment.getSlot())
|
||||
.astab(equipment.getAstab() - other.equipment.getAstab())
|
||||
.aslash(equipment.getAslash() - other.equipment.getAslash())
|
||||
@@ -77,7 +80,7 @@ public class ItemStats
|
||||
newEquipment = equipment;
|
||||
}
|
||||
|
||||
return new ItemStats(name, quest, equipable, newWeight, newEquipment);
|
||||
return new ItemStats(quest, equipable, newWeight, newEquipment);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* 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.api.util;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import net.runelite.http.api.item.ItemEquipmentStats;
|
||||
import net.runelite.http.api.item.ItemPrice;
|
||||
import net.runelite.http.api.item.ItemStats;
|
||||
|
||||
/**
|
||||
* A class to put GSON TypeAdapters. These make just as fast the first time you
|
||||
* deserialize something as it would otherwise be after creating these itself.
|
||||
* Kinda funny actually, cause the first time probably matters the most, especially
|
||||
* for jsons that only get deserialized once.
|
||||
*/
|
||||
public class TypeAdapters
|
||||
{
|
||||
public static final TypeAdapter<ItemStats> ITEMSTATS = new TypeAdapter<ItemStats>()
|
||||
{
|
||||
@Deprecated
|
||||
@Override
|
||||
public void write(JsonWriter out, ItemStats value)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStats read(JsonReader in) throws IOException
|
||||
{
|
||||
in.beginObject();
|
||||
|
||||
boolean quest = false;
|
||||
boolean equip = false;
|
||||
double weight = 0;
|
||||
ItemEquipmentStats stats = null;
|
||||
while (in.peek() != JsonToken.END_OBJECT)
|
||||
{
|
||||
switch (in.nextName())
|
||||
{
|
||||
case "quest":
|
||||
quest = in.nextBoolean();
|
||||
break;
|
||||
case "equipable":
|
||||
equip = in.nextBoolean();
|
||||
break;
|
||||
case "weight":
|
||||
weight = in.nextDouble();
|
||||
break;
|
||||
case "equipment":
|
||||
stats = EQUIPMENTSTATS.read(in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
in.endObject();
|
||||
|
||||
return new ItemStats(quest, equip, weight, stats);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TypeAdapter<ItemEquipmentStats> EQUIPMENTSTATS = new TypeAdapter<ItemEquipmentStats>()
|
||||
{
|
||||
@Deprecated
|
||||
@Override
|
||||
public void write(JsonWriter out, ItemEquipmentStats value)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemEquipmentStats read(JsonReader in) throws IOException
|
||||
{
|
||||
ItemEquipmentStats.Builder builder = ItemEquipmentStats.builder();
|
||||
|
||||
in.beginObject();
|
||||
while (in.peek() != JsonToken.END_OBJECT)
|
||||
{
|
||||
String name = in.nextName();
|
||||
int val = in.nextInt();
|
||||
switch (name)
|
||||
{
|
||||
case "slot":
|
||||
builder.slot(val);
|
||||
break;
|
||||
case "astab":
|
||||
builder.astab(val);
|
||||
break;
|
||||
case "aslash":
|
||||
builder.aslash(val);
|
||||
break;
|
||||
case "acrush":
|
||||
builder.acrush(val);
|
||||
break;
|
||||
case "amagic":
|
||||
builder.amagic(val);
|
||||
break;
|
||||
case "arange":
|
||||
builder.arange(val);
|
||||
break;
|
||||
case "dstab":
|
||||
builder.dstab(val);
|
||||
break;
|
||||
case "dslash":
|
||||
builder.dslash(val);
|
||||
break;
|
||||
case "dcrush":
|
||||
builder.dcrush(val);
|
||||
break;
|
||||
case "dmagic":
|
||||
builder.dmagic(val);
|
||||
break;
|
||||
case "drange":
|
||||
builder.drange(val);
|
||||
break;
|
||||
case "str":
|
||||
builder.str(val);
|
||||
break;
|
||||
case "rstr":
|
||||
builder.rstr(val);
|
||||
break;
|
||||
case "mdmg":
|
||||
builder.mdmg(val);
|
||||
break;
|
||||
case "prayer":
|
||||
builder.prayer(val);
|
||||
break;
|
||||
case "aspeed":
|
||||
builder.aspeed(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
in.endObject();
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
};
|
||||
|
||||
public static final TypeAdapter<ItemPrice> ITEMPRICE = new TypeAdapter<ItemPrice>()
|
||||
{
|
||||
@Override
|
||||
public void write(JsonWriter out, ItemPrice value)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPrice read(JsonReader in) throws IOException
|
||||
{
|
||||
/*
|
||||
* The ItemPrice json hosted by runelite is 'perfect'
|
||||
* by that I mean every field always exists, even with value 0.
|
||||
* This is why we can skip names and known-0 values
|
||||
*/
|
||||
ItemPrice ret = new ItemPrice();
|
||||
|
||||
in.beginObject();
|
||||
|
||||
// ID
|
||||
in.skipValue();
|
||||
ret.setId(in.nextInt());
|
||||
|
||||
// Name
|
||||
in.skipValue();
|
||||
ret.setName(in.nextString());
|
||||
|
||||
// Price
|
||||
in.skipValue();
|
||||
ret.setPrice(in.nextInt());
|
||||
|
||||
// Time
|
||||
in.skipValue();
|
||||
in.beginObject();
|
||||
|
||||
// Secs
|
||||
in.skipValue();
|
||||
ret.setTime(Instant.ofEpochSecond(in.nextLong()));
|
||||
|
||||
// Nanos
|
||||
in.skipValue();
|
||||
in.skipValue();
|
||||
|
||||
in.endObject();
|
||||
in.endObject();
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class XteaClient
|
||||
{
|
||||
String json = RuneLiteAPI.GSON.toJson(xteaRequest);
|
||||
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("xtea")
|
||||
.build();
|
||||
|
||||
@@ -63,7 +63,7 @@ public class XteaClient
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.RLP_CLIENT.newCall(request).enqueue(new Callback()
|
||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
@@ -91,7 +91,7 @@ public class XteaClient
|
||||
|
||||
public List<XteaKey> get() throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("xtea")
|
||||
.build();
|
||||
|
||||
@@ -116,7 +116,7 @@ public class XteaClient
|
||||
|
||||
public XteaKey get(int region) throws IOException
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getPlusApiBase().newBuilder()
|
||||
HttpUrl url = RuneLiteAPI.getOpenOSRSApiBase().newBuilder()
|
||||
.addPathSegment("xtea")
|
||||
.addPathSegment(Integer.toString(region))
|
||||
.build();
|
||||
|
||||
@@ -24,77 +24,78 @@
|
||||
*/
|
||||
package net.runelite.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.task.Schedule;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class ClientSessionManager
|
||||
{
|
||||
private final SessionClient sessionClient = new SessionClient(this);
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
private ScheduledFuture<?> scheduledFuture;
|
||||
private final SessionClient sessionClient;
|
||||
private final ClientThread clientThread;
|
||||
private UUID sessionId;
|
||||
|
||||
|
||||
@Inject
|
||||
ClientSessionManager(ScheduledExecutorService executorService)
|
||||
ClientSessionManager(ClientThread clientThread)
|
||||
{
|
||||
this.executorService = executorService;
|
||||
this.sessionClient = new SessionClient();
|
||||
this.clientThread = clientThread;
|
||||
}
|
||||
|
||||
public void start()
|
||||
void start()
|
||||
{
|
||||
sessionClient.open();
|
||||
|
||||
scheduledFuture = executorService.scheduleWithFixedDelay(this::ping, 1, 10, TimeUnit.MINUTES);
|
||||
sessionClient.openSession()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.from(clientThread))
|
||||
.subscribe(this::setUuid, this::error);
|
||||
}
|
||||
|
||||
void setUuid(UUID uuid)
|
||||
@Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true)
|
||||
private void ping()
|
||||
{
|
||||
this.sessionId = uuid;
|
||||
log.debug("Opened session {}", sessionId);
|
||||
}
|
||||
if (sessionId == null)
|
||||
{
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
void error(IOException e)
|
||||
{
|
||||
log.warn("Client session error, resetting UUID", e.getCause());
|
||||
sessionId = null;
|
||||
sessionClient.pingSession(sessionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.from(clientThread))
|
||||
.doOnError(e -> this.error((Throwable) e))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
if (sessionId != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sessionClient.delete(sessionId);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn(null, ex);
|
||||
}
|
||||
sessionClient.delete(sessionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.from(clientThread))
|
||||
.doOnError(e -> this.error((Throwable) e))
|
||||
.subscribe();
|
||||
|
||||
sessionId = null;
|
||||
}
|
||||
|
||||
scheduledFuture.cancel(true);
|
||||
}
|
||||
|
||||
private void ping()
|
||||
private void setUuid(UUID uuid)
|
||||
{
|
||||
if (sessionId == null)
|
||||
{
|
||||
sessionClient.open();
|
||||
return;
|
||||
}
|
||||
this.sessionId = uuid;
|
||||
log.debug("Opened session {}.", sessionId);
|
||||
}
|
||||
|
||||
sessionClient.ping(sessionId);
|
||||
private void error(Throwable error)
|
||||
{
|
||||
log.debug("Error in client session.");
|
||||
log.trace(null, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +375,7 @@ public class RuneLite
|
||||
if (this.client != null)
|
||||
{
|
||||
scheduler.registerObject(modelOutlineRenderer.get());
|
||||
scheduler.registerObject(clientSessionManager);
|
||||
}
|
||||
|
||||
// Close the splash screen
|
||||
|
||||
@@ -24,106 +24,68 @@
|
||||
*/
|
||||
package net.runelite.client;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.UUID;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class SessionClient
|
||||
{
|
||||
private final ClientSessionManager manager;
|
||||
|
||||
SessionClient(ClientSessionManager manager)
|
||||
Observable<UUID> openSession()
|
||||
{
|
||||
this.manager = manager;
|
||||
}
|
||||
final HttpUrl url = RuneLiteAPI.getSessionBase();
|
||||
|
||||
void open()
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getopenosrsSessionBase().newBuilder()
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
||||
return Observable.fromCallable(() ->
|
||||
{
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e)
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
manager.error(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response)
|
||||
{
|
||||
try
|
||||
{
|
||||
ResponseBody body = response.body();
|
||||
|
||||
InputStream in = body.byteStream();
|
||||
|
||||
manager.setUuid(RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), UUID.class));
|
||||
}
|
||||
catch (JsonParseException | IllegalArgumentException ex) // UUID.fromString can throw IllegalArgumentException
|
||||
{
|
||||
manager.error(new IOException(ex));
|
||||
}
|
||||
return RuneLiteAPI.GSON.fromJson(response.body().string(), UUID.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ping(UUID uuid)
|
||||
Observable pingSession(UUID uuid)
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getopenosrsSessionBase().newBuilder()
|
||||
final HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
|
||||
.addPathSegment("ping")
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
||||
return Observable.defer(() ->
|
||||
{
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e)
|
||||
{
|
||||
manager.error(e);
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response)
|
||||
|
||||
try (Response response = RuneLiteAPI.CLIENT.newCall(request).execute())
|
||||
{
|
||||
if (!response.isSuccessful())
|
||||
{
|
||||
manager.error(new IOException("Failed ping"));
|
||||
}
|
||||
return Observable.empty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void delete(UUID uuid) throws IOException
|
||||
Observable delete(UUID uuid)
|
||||
{
|
||||
HttpUrl url = RuneLiteAPI.getopenosrsSessionBase().newBuilder()
|
||||
final HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder()
|
||||
.addQueryParameter("session", uuid.toString())
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.delete()
|
||||
.url(url)
|
||||
.build();
|
||||
return Observable.defer(() ->
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.delete()
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
RuneLiteAPI.CLIENT.newCall(request).execute().close();
|
||||
RuneLiteAPI.CLIENT.newCall(request).execute().close();
|
||||
return Observable.empty();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.client.account;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
@@ -37,7 +38,6 @@ import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.SessionClose;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
@@ -57,13 +57,11 @@ public class SessionManager
|
||||
private AccountSession accountSession;
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final ConfigManager configManager;
|
||||
private final WSClient wsClient;
|
||||
|
||||
@Inject
|
||||
private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient)
|
||||
private SessionManager(EventBus eventBus, WSClient wsClient)
|
||||
{
|
||||
this.configManager = configManager;
|
||||
this.eventBus = eventBus;
|
||||
this.wsClient = wsClient;
|
||||
|
||||
@@ -94,13 +92,26 @@ public class SessionManager
|
||||
|
||||
// Check if session is still valid
|
||||
AccountClient accountClient = new AccountClient(session.getUuid());
|
||||
if (!accountClient.sessionCheck())
|
||||
{
|
||||
log.debug("Loaded session {} is invalid", session.getUuid());
|
||||
return;
|
||||
}
|
||||
|
||||
openSession(session, false);
|
||||
accountClient.sessionCheck()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(b ->
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
log.debug("Loaded session {} is invalid", session.getUuid());
|
||||
}
|
||||
else
|
||||
{
|
||||
openSession(session, false);
|
||||
}
|
||||
}, ex ->
|
||||
{
|
||||
if (ex instanceof IOException)
|
||||
{
|
||||
log.debug("Unable to verify session", ex);
|
||||
openSession(session, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveSession()
|
||||
@@ -143,13 +154,6 @@ public class SessionManager
|
||||
|
||||
accountSession = session;
|
||||
|
||||
if (session.getUsername() != null)
|
||||
{
|
||||
// Initialize config for new session
|
||||
// If the session isn't logged in yet, don't switch to the new config
|
||||
configManager.switchSession();
|
||||
}
|
||||
|
||||
eventBus.post(SessionOpen.class, new SessionOpen());
|
||||
}
|
||||
|
||||
@@ -176,9 +180,6 @@ public class SessionManager
|
||||
|
||||
accountSession = null; // No more account
|
||||
|
||||
// Restore config
|
||||
configManager.switchSession();
|
||||
|
||||
eventBus.post(SessionClose.class, new SessionClose());
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,10 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -137,12 +133,11 @@ public class ItemManager
|
||||
private final Client client;
|
||||
private final ClientThread clientThread;
|
||||
private final ItemClient itemClient;
|
||||
private final ImmutableMap<Integer, ItemStats> itemStatMap;
|
||||
private final LoadingCache<ImageKey, AsyncBufferedImage> itemImages;
|
||||
private final LoadingCache<Integer, ItemDefinition> itemDefinitions;
|
||||
private final LoadingCache<OutlineKey, BufferedImage> itemOutlines;
|
||||
private Map<Integer, ItemPrice> itemPrices = Collections.emptyMap();
|
||||
private Map<Integer, ItemStats> itemStats = Collections.emptyMap();
|
||||
private ImmutableMap<Integer, ItemStats> itemStats = ImmutableMap.of();
|
||||
|
||||
@Inject
|
||||
public ItemManager(
|
||||
@@ -166,7 +161,7 @@ public class ItemManager
|
||||
.build(new CacheLoader<ImageKey, AsyncBufferedImage>()
|
||||
{
|
||||
@Override
|
||||
public AsyncBufferedImage load(@NotNull ImageKey key) throws Exception
|
||||
public AsyncBufferedImage load(@NotNull ImageKey key)
|
||||
{
|
||||
return loadImage(key.itemId, key.itemQuantity, key.stackable);
|
||||
}
|
||||
@@ -178,7 +173,7 @@ public class ItemManager
|
||||
.build(new CacheLoader<Integer, ItemDefinition>()
|
||||
{
|
||||
@Override
|
||||
public ItemDefinition load(@NotNull Integer key) throws Exception
|
||||
public ItemDefinition load(@NotNull Integer key)
|
||||
{
|
||||
return client.getItemDefinition(key);
|
||||
}
|
||||
@@ -190,24 +185,21 @@ public class ItemManager
|
||||
.build(new CacheLoader<OutlineKey, BufferedImage>()
|
||||
{
|
||||
@Override
|
||||
public BufferedImage load(@NotNull OutlineKey key) throws Exception
|
||||
public BufferedImage load(@NotNull OutlineKey key)
|
||||
{
|
||||
return loadItemOutline(key.itemId, key.itemQuantity, key.outlineColor);
|
||||
}
|
||||
});
|
||||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
final Type typeToken = new TypeToken<Map<Integer, ItemStats>>()
|
||||
{
|
||||
}.getType();
|
||||
|
||||
final InputStream statsFile = getClass().getResourceAsStream("/item_stats.json");
|
||||
final Map<Integer, ItemStats> stats = gson.fromJson(new InputStreamReader(statsFile), typeToken);
|
||||
itemStatMap = ImmutableMap.copyOf(stats);
|
||||
|
||||
eventbus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventbus.subscribe(PostItemDefinition.class, this, this::onPostItemDefinition);
|
||||
|
||||
Completable.fromAction(ItemVariationMapping::load)
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.subscribe(
|
||||
() -> log.debug("Loaded {} item variations", ItemVariationMapping.getSize()),
|
||||
ex -> log.warn("Error loading item variations", ex)
|
||||
);
|
||||
}
|
||||
|
||||
private void loadPrices()
|
||||
@@ -215,21 +207,9 @@ public class ItemManager
|
||||
itemClient.getPrices()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
(prices) ->
|
||||
{
|
||||
if (prices != null)
|
||||
{
|
||||
ImmutableMap.Builder<Integer, ItemPrice> map = ImmutableMap.builderWithExpectedSize(prices.length);
|
||||
for (ItemPrice price : prices)
|
||||
{
|
||||
map.put(price.getId(), price);
|
||||
}
|
||||
itemPrices = map.build();
|
||||
}
|
||||
|
||||
log.debug("Loaded {} prices", itemPrices.size());
|
||||
},
|
||||
(e) -> log.warn("error loading prices!", e)
|
||||
m -> itemPrices = m,
|
||||
e -> log.warn("Error loading prices", e),
|
||||
() -> log.debug("Loaded {} prices", itemPrices.size())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -238,16 +218,9 @@ public class ItemManager
|
||||
itemClient.getStats()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
(stats) ->
|
||||
{
|
||||
if (stats != null)
|
||||
{
|
||||
itemStats = ImmutableMap.copyOf(stats);
|
||||
}
|
||||
|
||||
log.debug("Loaded {} stats", itemStats.size());
|
||||
},
|
||||
(e) -> log.warn("error loading stats!", e)
|
||||
m -> itemStats = m,
|
||||
e -> log.warn("Error fetching stats", e),
|
||||
() -> log.debug("Loaded {} stats", itemStats.size())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -376,12 +349,12 @@ public class ItemManager
|
||||
{
|
||||
ItemDefinition itemDefinition = getItemDefinition(itemId);
|
||||
|
||||
if (itemDefinition.getName() == null || !allowNote && itemDefinition.getNote() != -1)
|
||||
if (!allowNote && itemDefinition.getNote() != -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return itemStatMap.get(canonicalize(itemId));
|
||||
return itemStats.get(canonicalize(itemId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class ItemStat
|
||||
{
|
||||
private int slot;
|
||||
|
||||
private int astab;
|
||||
private int aslash;
|
||||
private int acrush;
|
||||
private int amagic;
|
||||
private int arange;
|
||||
|
||||
private int dstab;
|
||||
private int dslash;
|
||||
private int dcrush;
|
||||
private int dmagic;
|
||||
private int drange;
|
||||
|
||||
private int str;
|
||||
private int rstr;
|
||||
private int mdmg;
|
||||
private int prayer;
|
||||
private int aspeed;
|
||||
}
|
||||
@@ -26,44 +26,20 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.InputStream;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Converts variation items to it's base item counterparts
|
||||
*/
|
||||
@Slf4j
|
||||
public class ItemVariationMapping
|
||||
{
|
||||
private static final Map<Integer, Integer> MAPPINGS;
|
||||
|
||||
static
|
||||
{
|
||||
final Gson gson = new Gson();
|
||||
final TypeToken<Map<String, Collection<Integer>>> typeToken = new TypeToken<Map<String, Collection<Integer>>>()
|
||||
{
|
||||
};
|
||||
|
||||
final InputStream geLimitData = ItemVariationMapping.class.getResourceAsStream("/item_variations.json");
|
||||
final Map<String, Collection<Integer>> itemVariations = gson.fromJson(new InputStreamReader(geLimitData), typeToken.getType());
|
||||
|
||||
ImmutableMap.Builder<Integer, Integer> builder = new ImmutableMap.Builder<>();
|
||||
for (Collection<Integer> value : itemVariations.values())
|
||||
{
|
||||
final Iterator<Integer> iterator = value.iterator();
|
||||
final int base = iterator.next();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
builder.put(iterator.next(), base);
|
||||
}
|
||||
}
|
||||
MAPPINGS = builder.build();
|
||||
}
|
||||
private static Map<Integer, Integer> MAPPINGS;
|
||||
|
||||
/**
|
||||
* Get base item id for provided variation item id.
|
||||
@@ -75,4 +51,39 @@ public class ItemVariationMapping
|
||||
{
|
||||
return MAPPINGS.getOrDefault(itemId, itemId);
|
||||
}
|
||||
|
||||
static void load() throws IOException
|
||||
{
|
||||
try (JsonReader reader = new JsonReader(new InputStreamReader(ItemVariationMapping.class.getResourceAsStream("/item_variations.json"), StandardCharsets.UTF_8)))
|
||||
{
|
||||
ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builderWithExpectedSize(5039);
|
||||
reader.beginObject();
|
||||
|
||||
while (reader.hasNext())
|
||||
{
|
||||
// Names are useless
|
||||
reader.skipValue();
|
||||
reader.beginArray();
|
||||
|
||||
int base = reader.nextInt();
|
||||
while (reader.hasNext())
|
||||
{
|
||||
builder.put(
|
||||
reader.nextInt(),
|
||||
base
|
||||
);
|
||||
}
|
||||
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
MAPPINGS = builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
static int getSize()
|
||||
{
|
||||
return MAPPINGS.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.InputStream;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -41,20 +41,37 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@Singleton
|
||||
public class NPCManager
|
||||
{
|
||||
private final ImmutableMap<Integer, NPCStats> statsMap;
|
||||
private ImmutableMap<Integer, NPCStats> statsMap;
|
||||
|
||||
@Inject
|
||||
private NPCManager()
|
||||
{
|
||||
final Gson gson = new Gson();
|
||||
Completable.fromAction(this::loadStats)
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.subscribe(
|
||||
() -> log.debug("Loaded {} NPC stats", statsMap.size()),
|
||||
ex -> log.warn("Error loading NPC stats", ex)
|
||||
);
|
||||
}
|
||||
|
||||
final Type typeToken = new TypeToken<Map<Integer, NPCStats>>()
|
||||
private void loadStats() throws IOException
|
||||
{
|
||||
try (JsonReader reader = new JsonReader(new InputStreamReader(NPCManager.class.getResourceAsStream("/npc_stats.json"), StandardCharsets.UTF_8)))
|
||||
{
|
||||
}.getType();
|
||||
ImmutableMap.Builder<Integer, NPCStats> builder = ImmutableMap.builderWithExpectedSize(2821);
|
||||
reader.beginObject();
|
||||
|
||||
final InputStream statsFile = getClass().getResourceAsStream("/npc_stats.json");
|
||||
final Map<Integer, NPCStats> stats = gson.fromJson(new InputStreamReader(statsFile), typeToken);
|
||||
statsMap = ImmutableMap.copyOf(stats);
|
||||
while (reader.hasNext())
|
||||
{
|
||||
builder.put(
|
||||
Integer.parseInt(reader.nextName()),
|
||||
NPCStats.NPC_STATS_TYPE_ADAPTER.read(reader)
|
||||
);
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
statsMap = builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,9 +24,15 @@
|
||||
*/
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder(builderClassName = "Builder")
|
||||
public class NPCStats
|
||||
{
|
||||
private final String name;
|
||||
@@ -77,4 +83,120 @@ public class NPCStats
|
||||
|
||||
return (1 + Math.floor(averageLevel * (averageDefBonus + bonusStrength + bonusAttack) / 5120) / 40);
|
||||
}
|
||||
|
||||
// Because this class is here we can't add the TypeAdapter to gson (easily)
|
||||
// doesn't mean we can't use one to do it a bit quicker
|
||||
public static final TypeAdapter<NPCStats> NPC_STATS_TYPE_ADAPTER = new TypeAdapter<NPCStats>()
|
||||
{
|
||||
@Override
|
||||
public void write(JsonWriter out, NPCStats value)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NPCStats read(JsonReader in) throws IOException
|
||||
{
|
||||
in.beginObject();
|
||||
NPCStats.Builder builder = NPCStats.builder();
|
||||
|
||||
// Name is the only one that's guaranteed
|
||||
in.skipValue();
|
||||
builder.name(in.nextString());
|
||||
|
||||
while (in.hasNext())
|
||||
{
|
||||
switch (in.nextName())
|
||||
{
|
||||
case "hitpoints":
|
||||
builder.hitpoints(in.nextInt());
|
||||
break;
|
||||
case "combatLevel":
|
||||
builder.combatLevel(in.nextInt());
|
||||
break;
|
||||
case "slayerLevel":
|
||||
builder.slayerLevel(in.nextInt());
|
||||
break;
|
||||
case "attackSpeed":
|
||||
builder.attackSpeed(in.nextInt());
|
||||
break;
|
||||
case "attackLevel":
|
||||
builder.attackLevel(in.nextInt());
|
||||
break;
|
||||
case "strengthLevel":
|
||||
builder.strengthLevel(in.nextInt());
|
||||
break;
|
||||
case "defenceLevel":
|
||||
builder.defenceLevel(in.nextInt());
|
||||
break;
|
||||
case "rangeLevel":
|
||||
builder.rangeLevel(in.nextInt());
|
||||
break;
|
||||
case "magicLevel":
|
||||
builder.magicLevel(in.nextInt());
|
||||
break;
|
||||
case "stab":
|
||||
builder.stab(in.nextInt());
|
||||
break;
|
||||
case "slash":
|
||||
builder.slash(in.nextInt());
|
||||
break;
|
||||
case "crush":
|
||||
builder.crush(in.nextInt());
|
||||
break;
|
||||
case "range":
|
||||
builder.range(in.nextInt());
|
||||
break;
|
||||
case "magic":
|
||||
builder.magic(in.nextInt());
|
||||
break;
|
||||
case "stabDef":
|
||||
builder.stabDef(in.nextInt());
|
||||
break;
|
||||
case "slashDef":
|
||||
builder.slashDef(in.nextInt());
|
||||
break;
|
||||
case "crushDef":
|
||||
builder.crushDef(in.nextInt());
|
||||
break;
|
||||
case "rangeDef":
|
||||
builder.rangeDef(in.nextInt());
|
||||
break;
|
||||
case "magicDef":
|
||||
builder.magicDef(in.nextInt());
|
||||
break;
|
||||
case "bonusAttack":
|
||||
builder.bonusAttack(in.nextInt());
|
||||
break;
|
||||
case "bonusStrength":
|
||||
builder.bonusStrength(in.nextInt());
|
||||
break;
|
||||
case "bonusRangeStrength":
|
||||
builder.bonusRangeStrength(in.nextInt());
|
||||
break;
|
||||
case "bonusMagicDamage":
|
||||
builder.bonusMagicDamage(in.nextInt());
|
||||
break;
|
||||
case "poisonImmune":
|
||||
builder.poisonImmune(in.nextBoolean());
|
||||
break;
|
||||
case "venomImmune":
|
||||
builder.venomImmune(in.nextBoolean());
|
||||
break;
|
||||
case "dragon":
|
||||
builder.dragon(in.nextBoolean());
|
||||
break;
|
||||
case "demon":
|
||||
builder.demon(in.nextBoolean());
|
||||
break;
|
||||
case "undead":
|
||||
builder.undead(in.nextBoolean());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in.endObject();
|
||||
return builder.build();
|
||||
}
|
||||
};
|
||||
}
|
||||
+2
-2
@@ -56,9 +56,9 @@ public class HighAlchemyOverlay extends WidgetItemOverlay
|
||||
this.itemManager = itemManager;
|
||||
this.plugin = plugin;
|
||||
|
||||
int natPrice = itemManager.getItemPrice(ItemID.NATURE_RUNE);
|
||||
int natPrice = itemManager.getItemPrice(ItemID.NATURE_RUNE, true);
|
||||
this.alchPrice = natPrice;
|
||||
this.alchPriceNoStaff = natPrice + 5 * itemManager.getItemPrice(ItemID.FIRE_RUNE);
|
||||
this.alchPriceNoStaff = natPrice + 5 * itemManager.getItemPrice(ItemID.FIRE_RUNE, true);
|
||||
|
||||
showOnBank();
|
||||
showOnInventory();
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ import net.runelite.http.api.item.ItemStats;
|
||||
public class ItemStatOverlay extends Overlay
|
||||
{
|
||||
// Unarmed attack speed is 6
|
||||
private static final ItemStats UNARMED = new ItemStats("", false, true, 0,
|
||||
private static final ItemStats UNARMED = new ItemStats(false, true, 0,
|
||||
ItemEquipmentStats.builder()
|
||||
.aspeed(6)
|
||||
.build());
|
||||
|
||||
+2
-1
@@ -551,6 +551,7 @@ public class PlayerScouter extends Plugin
|
||||
}
|
||||
|
||||
ItemStats item = itemManager.getItemStats(gear, false);
|
||||
String name = itemManager.getItemDefinition(gear).getName();
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
@@ -559,7 +560,7 @@ public class PlayerScouter extends Plugin
|
||||
}
|
||||
|
||||
fieldList.add(FieldEmbed.builder()
|
||||
.name(item.getName())
|
||||
.name(name)
|
||||
.value("Value: " + StackFormatter.quantityToRSDecimalStack(value))
|
||||
.inline(true)
|
||||
.build());
|
||||
|
||||
+3
@@ -77,10 +77,13 @@ public class StonedTrackerPlugin extends Plugin
|
||||
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
|
||||
@Inject
|
||||
public StonedTrackerConfig config;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
|
||||
+46
-42
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.timetracking.farming;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -42,7 +43,7 @@ import net.runelite.client.plugins.timetracking.Tab;
|
||||
class FarmingWorld
|
||||
{
|
||||
@Getter
|
||||
private Map<Integer, FarmingRegion> regions = new HashMap<>();
|
||||
private final ImmutableMap<Integer, FarmingRegion> regions;
|
||||
|
||||
@Getter
|
||||
private Map<Tab, Set<FarmingPatch>> tabs = new HashMap<>();
|
||||
@@ -54,58 +55,60 @@ class FarmingWorld
|
||||
|
||||
FarmingWorld()
|
||||
{
|
||||
ImmutableMap.Builder<Integer, FarmingRegion> regionBuilder = ImmutableMap.builderWithExpectedSize(40);
|
||||
|
||||
// Some of these patches get updated in multiple regions.
|
||||
// It may be worth it to add a specialization for these patches
|
||||
add(new FarmingRegion("Al Kharid", 13106,
|
||||
add(regionBuilder, new FarmingRegion("Al Kharid", 13106,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CACTUS)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Ardougne", 10290,
|
||||
add(regionBuilder, new FarmingRegion("Ardougne", 10290,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||
));
|
||||
add(new FarmingRegion("Ardougne", 10548,
|
||||
add(regionBuilder, new FarmingRegion("Ardougne", 10548,
|
||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Brimhaven", 11058,
|
||||
add(regionBuilder, new FarmingRegion("Brimhaven", 11058,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE),
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Catherby", 11062,
|
||||
add(regionBuilder, new FarmingRegion("Catherby", 11062,
|
||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||
));
|
||||
add(new FarmingRegion("Catherby", 11317,
|
||||
add(regionBuilder, new FarmingRegion("Catherby", 11317,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Champions' Guild", 12596,
|
||||
add(regionBuilder, new FarmingRegion("Champions' Guild", 12596,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Draynor Manor", 12340,
|
||||
add(regionBuilder, new FarmingRegion("Draynor Manor", 12340,
|
||||
new FarmingPatch("Belladonna", Varbits.FARMING_4771, PatchImplementation.BELLADONNA)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Entrana", 11060,
|
||||
add(regionBuilder, new FarmingRegion("Entrana", 11060,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Etceteria", 10300,
|
||||
add(regionBuilder, new FarmingRegion("Etceteria", 10300,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH),
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Falador", 11828,
|
||||
add(regionBuilder, new FarmingRegion("Falador", 11828,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||
));
|
||||
add(new FarmingRegion("Falador", 12083,
|
||||
add(regionBuilder, new FarmingRegion("Falador", 12083,
|
||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
@@ -119,36 +122,36 @@ class FarmingWorld
|
||||
}
|
||||
});
|
||||
|
||||
add(new FarmingRegion("Fossil Island", 14651,
|
||||
add(regionBuilder, new FarmingRegion("Fossil Island", 14651,
|
||||
new FarmingPatch("East", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE),
|
||||
new FarmingPatch("Middle", Varbits.FARMING_4772, PatchImplementation.HARDWOOD_TREE),
|
||||
new FarmingPatch("West", Varbits.FARMING_4773, PatchImplementation.HARDWOOD_TREE)
|
||||
), 14907);
|
||||
add(new FarmingRegion("Seaweed", 15008,
|
||||
add(regionBuilder, new FarmingRegion("Seaweed", 15008,
|
||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.SEAWEED),
|
||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.SEAWEED)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Gnome Stronghold", 9781,
|
||||
add(regionBuilder, new FarmingRegion("Gnome Stronghold", 9781,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE),
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.FRUIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Harmony", 15148,
|
||||
add(regionBuilder, new FarmingRegion("Harmony", 15148,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.HERB)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Kourend", 6967,
|
||||
add(regionBuilder, new FarmingRegion("Kourend", 6967,
|
||||
new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||
));
|
||||
add(new FarmingRegion("Kourend", 6711,
|
||||
add(regionBuilder, new FarmingRegion("Kourend", 6711,
|
||||
new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE)
|
||||
));
|
||||
add(new FarmingRegion("Kourend", 7223,
|
||||
add(regionBuilder, new FarmingRegion("Kourend", 7223,
|
||||
new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 3", Varbits.GRAPES_4955, PatchImplementation.GRAPES),
|
||||
@@ -163,21 +166,21 @@ class FarmingWorld
|
||||
new FarmingPatch("West 6", Varbits.GRAPES_4964, PatchImplementation.GRAPES)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Lletya", 9265,
|
||||
add(regionBuilder, new FarmingRegion("Lletya", 9265,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Lumbridge", 12851,
|
||||
add(regionBuilder, new FarmingRegion("Lumbridge", 12851,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||
));
|
||||
add(new FarmingRegion("Lumbridge", 12594,
|
||||
add(regionBuilder, new FarmingRegion("Lumbridge", 12594,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Morytania", 13622,
|
||||
add(regionBuilder, new FarmingRegion("Morytania", 13622,
|
||||
new FarmingPatch("Mushroom", Varbits.FARMING_4771, PatchImplementation.MUSHROOM)
|
||||
));
|
||||
add(new FarmingRegion("Morytania", 14391,
|
||||
add(regionBuilder, new FarmingRegion("Morytania", 14391,
|
||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
@@ -185,51 +188,51 @@ class FarmingWorld
|
||||
));
|
||||
|
||||
|
||||
add(new FarmingRegion("Port Sarim", 12082,
|
||||
add(regionBuilder, new FarmingRegion("Port Sarim", 12082,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Rimmington", 11570,
|
||||
add(regionBuilder, new FarmingRegion("Rimmington", 11570,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||
), 11826);
|
||||
|
||||
add(new FarmingRegion("Seers' Village", 10551,
|
||||
add(regionBuilder, new FarmingRegion("Seers' Village", 10551,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Tai Bwo Wannai", 11056,
|
||||
add(regionBuilder, new FarmingRegion("Tai Bwo Wannai", 11056,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.CALQUAT)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Taverley", 11573,
|
||||
add(regionBuilder, new FarmingRegion("Taverley", 11573,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Tree Gnome Village", 9777,
|
||||
add(regionBuilder, new FarmingRegion("Tree Gnome Village", 9777,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Troll Stronghold", 11321,
|
||||
add(regionBuilder, new FarmingRegion("Troll Stronghold", 11321,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Varrock", 12854,
|
||||
add(regionBuilder, new FarmingRegion("Varrock", 12854,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||
), 12853);
|
||||
|
||||
add(new FarmingRegion("Yanille", 10288,
|
||||
add(regionBuilder, new FarmingRegion("Yanille", 10288,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Weiss", 11325,
|
||||
add(regionBuilder, new FarmingRegion("Weiss", 11325,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HERB)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Farming Guild", 5021,
|
||||
add(regionBuilder, new FarmingRegion("Farming Guild", 5021,
|
||||
new FarmingPatch("Hespori", Varbits.FARMING_7908, PatchImplementation.HESPORI)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Farming Guild", 4922,
|
||||
add(regionBuilder, new FarmingRegion("Farming Guild", 4922,
|
||||
new FarmingPatch("", Varbits.FARMING_7905, PatchImplementation.TREE),
|
||||
new FarmingPatch("", Varbits.FARMING_4775, PatchImplementation.HERB),
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.BUSH),
|
||||
@@ -244,7 +247,7 @@ class FarmingWorld
|
||||
new FarmingPatch("", Varbits.FARMING_7907, PatchImplementation.REDWOOD)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Prifddinas", 13151,
|
||||
add(regionBuilder, new FarmingRegion("Prifddinas", 13151,
|
||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
@@ -252,7 +255,8 @@ class FarmingWorld
|
||||
));
|
||||
|
||||
// Finalize
|
||||
this.regions = Collections.unmodifiableMap(regions);
|
||||
this.regions = regionBuilder.build();
|
||||
|
||||
Map<Tab, Set<FarmingPatch>> umtabs = new TreeMap<>();
|
||||
for (Map.Entry<Tab, Set<FarmingPatch>> e : tabs.entrySet())
|
||||
{
|
||||
@@ -261,12 +265,12 @@ class FarmingWorld
|
||||
this.tabs = Collections.unmodifiableMap(umtabs);
|
||||
}
|
||||
|
||||
private void add(FarmingRegion r, int... extraRegions)
|
||||
private void add(ImmutableMap.Builder<Integer, FarmingRegion> builder, FarmingRegion r, int... extraRegions)
|
||||
{
|
||||
regions.put(r.getRegionID(), r);
|
||||
builder.put(r.getRegionID(), r);
|
||||
for (int er : extraRegions)
|
||||
{
|
||||
regions.put(er, r);
|
||||
builder.put(er, r);
|
||||
}
|
||||
for (FarmingPatch p : r.getPatches())
|
||||
{
|
||||
|
||||
+20
@@ -25,8 +25,10 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.worldmap;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@Getter
|
||||
enum TeleportLocationData
|
||||
@@ -188,6 +190,24 @@ enum TeleportLocationData
|
||||
private final String tooltip;
|
||||
private final WorldPoint location;
|
||||
private final String iconPath;
|
||||
private BufferedImage image;
|
||||
|
||||
BufferedImage getImage()
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
image = ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, this.getIconPath());
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
return WorldMapPlugin.BLANK_ICON;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
TeleportLocationData(TeleportType type, String destination, int magicLevel, WorldPoint location, String iconPath)
|
||||
{
|
||||
|
||||
+1
-3
@@ -26,14 +26,12 @@
|
||||
package net.runelite.client.plugins.worldmap;
|
||||
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
class TeleportPoint extends WorldMapPoint
|
||||
{
|
||||
TeleportPoint(TeleportLocationData data)
|
||||
{
|
||||
super(data.getLocation(), WorldMapPlugin.BLANK_ICON);
|
||||
super(data.getLocation(), data.getImage());
|
||||
setTooltip(data.getTooltip());
|
||||
setImage(ImageUtil.getResourceStreamFromClass(WorldMapPlugin.class, data.getIconPath()));
|
||||
}
|
||||
}
|
||||
|
||||
+30
-23
@@ -29,6 +29,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Experience;
|
||||
import net.runelite.api.GameState;
|
||||
@@ -127,6 +128,9 @@ public class WorldMapPlugin extends Plugin
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private int agilityLevel = 0;
|
||||
private int woodcuttingLevel = 0;
|
||||
|
||||
@@ -308,30 +312,33 @@ public class WorldMapPlugin extends Plugin
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(TeleportPoint.class::isInstance);
|
||||
Arrays.stream(TeleportLocationData.values())
|
||||
.filter(data ->
|
||||
{
|
||||
switch (data.getType())
|
||||
// This next part gets 142 icons from disk, and does so on the EDT (at first run)
|
||||
executor.submit(() ->
|
||||
Arrays.stream(TeleportLocationData.values())
|
||||
.filter(data ->
|
||||
{
|
||||
case NORMAL_MAGIC:
|
||||
return this.normalTeleportIcon;
|
||||
case ANCIENT_MAGICKS:
|
||||
return this.ancientTeleportIcon;
|
||||
case LUNAR_MAGIC:
|
||||
return this.lunarTeleportIcon;
|
||||
case ARCEUUS_MAGIC:
|
||||
return this.arceuusTeleportIcon;
|
||||
case JEWELLERY:
|
||||
return this.jewelleryTeleportIcon;
|
||||
case SCROLL:
|
||||
return this.scrollTeleportIcon;
|
||||
case OTHER:
|
||||
return this.miscellaneousTeleportIcon;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}).map(TeleportPoint::new)
|
||||
.forEach(worldMapPointManager::add);
|
||||
switch (data.getType())
|
||||
{
|
||||
case NORMAL_MAGIC:
|
||||
return this.normalTeleportIcon;
|
||||
case ANCIENT_MAGICKS:
|
||||
return this.ancientTeleportIcon;
|
||||
case LUNAR_MAGIC:
|
||||
return this.lunarTeleportIcon;
|
||||
case ARCEUUS_MAGIC:
|
||||
return this.arceuusTeleportIcon;
|
||||
case JEWELLERY:
|
||||
return this.jewelleryTeleportIcon;
|
||||
case SCROLL:
|
||||
return this.scrollTeleportIcon;
|
||||
case OTHER:
|
||||
return this.miscellaneousTeleportIcon;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}).map(TeleportPoint::new)
|
||||
.forEach(worldMapPointManager::add)
|
||||
);
|
||||
}
|
||||
|
||||
private void updateQuestStartPointIcons()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1
-4153
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
-1
@@ -340,8 +340,10 @@ public class ItemVariationMappingTest
|
||||
}};
|
||||
|
||||
@Test
|
||||
public void testMappedNames()
|
||||
public void testMappedNames() throws Exception
|
||||
{
|
||||
ItemVariationMapping.load();
|
||||
|
||||
ITEMS_MAP.forEach((key, value) ->
|
||||
{
|
||||
assertEquals(value, (Integer) ItemVariationMapping.map(key));
|
||||
|
||||
Reference in New Issue
Block a user