Merge remote-tracking branch 'runelite/master'
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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 com.jagex.oldscape.pub;
|
||||||
|
|
||||||
|
public interface OAuthApi
|
||||||
|
{
|
||||||
|
boolean isOnLoginScreen();
|
||||||
|
|
||||||
|
void setOtlTokenRequester(OtlTokenRequester otlTokenRequester);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a unique per-RuneScape-Account identifier or {@code -1} if the client has not logged in yet
|
||||||
|
*/
|
||||||
|
long getAccountHash();
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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 com.jagex.oldscape.pub;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
public interface OtlTokenRequester
|
||||||
|
{
|
||||||
|
Future<OtlTokenResponse> request(URL url);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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 com.jagex.oldscape.pub;
|
||||||
|
|
||||||
|
public interface OtlTokenResponse
|
||||||
|
{
|
||||||
|
boolean isSuccess();
|
||||||
|
|
||||||
|
String getToken();
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.api;
|
package net.runelite.api;
|
||||||
|
|
||||||
|
import com.jagex.oldscape.pub.OAuthApi;
|
||||||
import java.awt.Canvas;
|
import java.awt.Canvas;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@@ -52,7 +53,7 @@ import org.intellij.lang.annotations.MagicConstant;
|
|||||||
/**
|
/**
|
||||||
* Represents the RuneScape client.
|
* Represents the RuneScape client.
|
||||||
*/
|
*/
|
||||||
public interface Client extends GameEngine
|
public interface Client extends OAuthApi, GameEngine
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The injected client invokes these callbacks to send events to us
|
* The injected client invokes these callbacks to send events to us
|
||||||
@@ -199,10 +200,13 @@ public interface Client extends GameEngine
|
|||||||
void setWorldSelectOpen(boolean open);
|
void setWorldSelectOpen(boolean open);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED. See getAccountHash instead.
|
||||||
* Gets the current logged in username.
|
* Gets the current logged in username.
|
||||||
*
|
*
|
||||||
* @return the logged in username
|
* @return the logged in username
|
||||||
|
* @see OAuthApi#getAccountHash()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
String getUsername();
|
String getUsername();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public final class ParamID
|
|||||||
* Long name for NPCs used in the HP hud
|
* Long name for NPCs used in the HP hud
|
||||||
*/
|
*/
|
||||||
public static final int NPC_HP_NAME = 510;
|
public static final int NPC_HP_NAME = 510;
|
||||||
|
public static final int QUEST_NAME = 610;
|
||||||
/**
|
/**
|
||||||
* @see SettingID
|
* @see SettingID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -275,6 +275,12 @@ public final class ScriptID
|
|||||||
@ScriptArguments(integer = 3)
|
@ScriptArguments(integer = 3)
|
||||||
public static final int GE_ITEM_SEARCH = 752;
|
public static final int GE_ITEM_SEARCH = 752;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On load listener for building the quest list interface
|
||||||
|
*/
|
||||||
|
@ScriptArguments(integer = 8)
|
||||||
|
public static final int QUESTLIST_INIT = 1350;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the friends list is updated
|
* Called when the friends list is updated
|
||||||
* <ul>
|
* <ul>
|
||||||
@@ -428,4 +434,16 @@ public final class ScriptID
|
|||||||
*/
|
*/
|
||||||
@ScriptArguments(integer = 1)
|
@ScriptArguments(integer = 1)
|
||||||
public static final int NOTIFICATION_DELAY = 3347;
|
public static final int NOTIFICATION_DELAY = 3347;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a quest should be filtered from the quest list
|
||||||
|
* <ul>
|
||||||
|
* <li> int (StructID) Quest struct </li>
|
||||||
|
* <li> int State filter </li>
|
||||||
|
* <li> int Requirement filter </li>
|
||||||
|
* <li> int Stats filter </li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@ScriptArguments(integer = 4)
|
||||||
|
public static final int QUEST_FILTER = 3238;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Abex
|
||||||
|
* 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.api.events;
|
||||||
|
|
||||||
|
public class AccountHashChanged
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -132,6 +132,7 @@ public final class WidgetID
|
|||||||
public static final int SKOTIZO_GROUP_ID = 308;
|
public static final int SKOTIZO_GROUP_ID = 308;
|
||||||
public static final int ENTERING_HOUSE_GROUP_ID = 71;
|
public static final int ENTERING_HOUSE_GROUP_ID = 71;
|
||||||
public static final int FULLSCREEN_CONTAINER_TLI = 165;
|
public static final int FULLSCREEN_CONTAINER_TLI = 165;
|
||||||
|
public static final int QUESTLIST_GROUP_ID = 399;
|
||||||
public static final int SKILLS_GROUP_ID = 320;
|
public static final int SKILLS_GROUP_ID = 320;
|
||||||
public static final int MUSIC_GROUP_ID = 239;
|
public static final int MUSIC_GROUP_ID = 239;
|
||||||
public static final int BARROWS_PUZZLE_GROUP_ID = 25;
|
public static final int BARROWS_PUZZLE_GROUP_ID = 25;
|
||||||
@@ -889,6 +890,12 @@ public final class WidgetID
|
|||||||
static final int CONTAINER = 2;
|
static final int CONTAINER = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class QuestList
|
||||||
|
{
|
||||||
|
static final int BOX = 0;
|
||||||
|
static final int CONTAINER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
static class Music
|
static class Music
|
||||||
{
|
{
|
||||||
static final int CONTAINER = 0;
|
static final int CONTAINER = 0;
|
||||||
|
|||||||
@@ -521,6 +521,9 @@ public enum WidgetInfo
|
|||||||
|
|
||||||
SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER),
|
SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER),
|
||||||
|
|
||||||
|
QUESTLIST_BOX(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.BOX),
|
||||||
|
QUESTLIST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.CONTAINER),
|
||||||
|
|
||||||
SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER),
|
SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER),
|
||||||
SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER),
|
SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER),
|
||||||
SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT),
|
SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT),
|
||||||
|
|||||||
@@ -27,9 +27,12 @@ package net.runelite.client;
|
|||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
import com.jagex.oldscape.pub.OAuthApi;
|
||||||
|
import com.jagex.oldscape.pub.OtlTokenResponse;
|
||||||
import com.openosrs.client.OpenOSRS;
|
import com.openosrs.client.OpenOSRS;
|
||||||
import com.openosrs.client.game.PlayerManager;
|
import com.openosrs.client.game.PlayerManager;
|
||||||
import com.openosrs.client.ui.OpenOSRSSplashScreen;
|
import com.openosrs.client.ui.OpenOSRSSplashScreen;
|
||||||
@@ -50,6 +53,7 @@ import java.security.SecureRandom;
|
|||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -92,6 +96,8 @@ import net.runelite.http.api.RuneLiteAPI;
|
|||||||
import net.runelite.http.api.worlds.World;
|
import net.runelite.http.api.worlds.World;
|
||||||
import net.runelite.http.api.worlds.WorldResult;
|
import net.runelite.http.api.worlds.WorldResult;
|
||||||
import okhttp3.Cache;
|
import okhttp3.Cache;
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.Callback;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
@@ -120,6 +126,9 @@ public class RuneLite
|
|||||||
@Inject
|
@Inject
|
||||||
private net.runelite.client.plugins.PluginManager pluginManager;
|
private net.runelite.client.plugins.PluginManager pluginManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ExternalPluginManager externalPluginManager;
|
private ExternalPluginManager externalPluginManager;
|
||||||
|
|
||||||
@@ -290,8 +299,8 @@ public class RuneLite
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode), (String) options.valueOf("jav_config"));
|
|
||||||
final RuntimeConfigLoader runtimeConfigLoader = new RuntimeConfigLoader(okHttpClient);
|
final RuntimeConfigLoader runtimeConfigLoader = new RuntimeConfigLoader(okHttpClient);
|
||||||
|
final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode), runtimeConfigLoader, (String) options.valueOf("jav_config"));
|
||||||
|
|
||||||
new Thread(() ->
|
new Thread(() ->
|
||||||
{
|
{
|
||||||
@@ -330,6 +339,7 @@ public class RuneLite
|
|||||||
log.error("Failure during startup", e);
|
log.error("Failure during startup", e);
|
||||||
SwingUtilities.invokeLater(() ->
|
SwingUtilities.invokeLater(() ->
|
||||||
new FatalErrorDialog("OpenOSRS has encountered an unexpected error during startup.")
|
new FatalErrorDialog("OpenOSRS has encountered an unexpected error during startup.")
|
||||||
|
.addHelpButtons()
|
||||||
.open());
|
.open());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -371,6 +381,11 @@ public class RuneLite
|
|||||||
}
|
}
|
||||||
|
|
||||||
applet.start();
|
applet.start();
|
||||||
|
|
||||||
|
if (applet instanceof OAuthApi)
|
||||||
|
{
|
||||||
|
setupJxAuth((OAuthApi) applet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SplashScreen.stage(.57, null, "Loading configuration");
|
SplashScreen.stage(.57, null, "Loading configuration");
|
||||||
@@ -661,4 +676,83 @@ public class RuneLite
|
|||||||
System.setProperty(key, value);
|
System.setProperty(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupJxAuth(OAuthApi oAuthApi)
|
||||||
|
{
|
||||||
|
String accessToken = System.getenv("JX_ACCESS_TOKEN");
|
||||||
|
if (Strings.isNullOrEmpty(accessToken))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
log.info("Initializing OTL token requester with access token");
|
||||||
|
oAuthApi.setOtlTokenRequester(url ->
|
||||||
|
{
|
||||||
|
CompletableFuture<OtlTokenResponse> f = new CompletableFuture<>();
|
||||||
|
okHttpClient.newCall(new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
|
.get()
|
||||||
|
.build())
|
||||||
|
.enqueue(new Callback()
|
||||||
|
{
|
||||||
|
private void complete(boolean success, String token)
|
||||||
|
{
|
||||||
|
f.complete(new OtlTokenResponse()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean isSuccess()
|
||||||
|
{
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getToken()
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call call, IOException e)
|
||||||
|
{
|
||||||
|
log.error("HTTP error while performing OTL request", e);
|
||||||
|
complete(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call call, Response response) throws IOException
|
||||||
|
{
|
||||||
|
if (response.code() != 200)
|
||||||
|
{
|
||||||
|
log.error("Non-OK response performing OTL request: {}", response.code());
|
||||||
|
complete(false, null);
|
||||||
|
response.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.body() == null)
|
||||||
|
{
|
||||||
|
log.error("OK response with empty body from OTL request");
|
||||||
|
complete(false, null);
|
||||||
|
response.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Successful OTL response");
|
||||||
|
complete(true, response.body().string());
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (LinkageError ex)
|
||||||
|
{
|
||||||
|
log.error("error setting up OTL requester", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class RuneLiteProperties
|
|||||||
private static final String PLUGINHUB_VERSION = "runelite.pluginhub.version";
|
private static final String PLUGINHUB_VERSION = "runelite.pluginhub.version";
|
||||||
private static final String API_BASE = "runelite.api.base";
|
private static final String API_BASE = "runelite.api.base";
|
||||||
private static final String RUNELITE_CONFIG = "runelite.config";
|
private static final String RUNELITE_CONFIG = "runelite.config";
|
||||||
|
private static final String OSRS_TWITTER_LINK = "runelite.osrstwitter.link";
|
||||||
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
@Getter(AccessLevel.PACKAGE)
|
||||||
private static final Properties properties = new Properties();
|
private static final Properties properties = new Properties();
|
||||||
@@ -148,4 +149,9 @@ public class RuneLiteProperties
|
|||||||
{
|
{
|
||||||
return properties.getProperty(RUNELITE_CONFIG);
|
return properties.getProperty(RUNELITE_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getOSRSTwitterLink()
|
||||||
|
{
|
||||||
|
return properties.getProperty(OSRS_TWITTER_LINK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -24,13 +24,46 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client;
|
package net.runelite.client;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.runelite.client.ui.FatalErrorDialog;
|
||||||
|
import net.runelite.client.util.LinkBrowser;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class RuntimeConfig
|
public class RuntimeConfig
|
||||||
{
|
{
|
||||||
private Map<String, ?> props = Collections.emptyMap();
|
private Map<String, ?> props = Collections.emptyMap();
|
||||||
private Map<String, String> sysProps = Collections.emptyMap();
|
private Map<String, String> sysProps = Collections.emptyMap();
|
||||||
|
|
||||||
|
private String outageMessage;
|
||||||
|
private Map<String, String> outageLinks;
|
||||||
|
|
||||||
|
public boolean showOutageMessage()
|
||||||
|
{
|
||||||
|
if (Strings.isNullOrEmpty(getOutageMessage()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() ->
|
||||||
|
{
|
||||||
|
FatalErrorDialog fed = new FatalErrorDialog(getOutageMessage());
|
||||||
|
if (getOutageLinks() != null)
|
||||||
|
{
|
||||||
|
for (Map.Entry<String, String> e : getOutageLinks().entrySet())
|
||||||
|
{
|
||||||
|
fed.addButton(e.getKey(), () -> LinkBrowser.browse(e.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fed.addButton("OSRS Twitter", () -> LinkBrowser.browse(RuneLiteProperties.getOSRSTwitterLink()));
|
||||||
|
}
|
||||||
|
fed.open();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,10 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.http.api.RuneLiteAPI;
|
import net.runelite.http.api.RuneLiteAPI;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
@@ -41,7 +44,7 @@ import okhttp3.Request;
|
|||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class RuntimeConfigLoader implements Supplier<RuntimeConfig>
|
public class RuntimeConfigLoader implements Supplier<RuntimeConfig>
|
||||||
{
|
{
|
||||||
private final OkHttpClient okHttpClient;
|
private final OkHttpClient okHttpClient;
|
||||||
private final CompletableFuture<RuntimeConfig> configFuture;
|
private final CompletableFuture<RuntimeConfig> configFuture;
|
||||||
@@ -66,6 +69,19 @@ class RuntimeConfigLoader implements Supplier<RuntimeConfig>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public RuntimeConfig tryGet()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return configFuture.get(0, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
catch (InterruptedException | ExecutionException | TimeoutException e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CompletableFuture<RuntimeConfig> fetch()
|
private CompletableFuture<RuntimeConfig> fetch()
|
||||||
{
|
{
|
||||||
CompletableFuture<RuntimeConfig> future = new CompletableFuture<>();
|
CompletableFuture<RuntimeConfig> future = new CompletableFuture<>();
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class ClientThread implements Executor
|
|||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
log.warn("Exception in invoke", e);
|
log.error("Exception in invoke", e);
|
||||||
}
|
}
|
||||||
if (remove)
|
if (remove)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Player;
|
import net.runelite.api.Player;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
|
import net.runelite.api.events.AccountHashChanged;
|
||||||
import net.runelite.api.events.PlayerChanged;
|
import net.runelite.api.events.PlayerChanged;
|
||||||
import net.runelite.api.events.UsernameChanged;
|
import net.runelite.api.events.UsernameChanged;
|
||||||
import net.runelite.api.events.WorldChanged;
|
import net.runelite.api.events.WorldChanged;
|
||||||
@@ -115,6 +116,7 @@ public class ConfigManager
|
|||||||
private static final String RSPROFILE_TYPE = "type";
|
private static final String RSPROFILE_TYPE = "type";
|
||||||
private static final String RSPROFILE_LOGIN_HASH = "loginHash";
|
private static final String RSPROFILE_LOGIN_HASH = "loginHash";
|
||||||
private static final String RSPROFILE_LOGIN_SALT = "loginSalt";
|
private static final String RSPROFILE_LOGIN_SALT = "loginSalt";
|
||||||
|
private static final String RSPROFILE_ACCOUNT_HASH = "accountHash";
|
||||||
|
|
||||||
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||||
|
|
||||||
@@ -544,17 +546,17 @@ public class ConfigManager
|
|||||||
displayName = p.getName();
|
displayName = p.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = client.getUsername();
|
RuneScapeProfile prof = findRSProfile(getRSProfiles(), RuneScapeProfileType.getCurrent(client), displayName, true);
|
||||||
if (Strings.isNullOrEmpty(username))
|
if (prof == null)
|
||||||
{
|
{
|
||||||
log.warn("trying to create profile without a set username");
|
log.warn("trying to create a profile while not logged in");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuneScapeProfile prof = findRSProfile(getRSProfiles(), username, RuneScapeProfileType.getCurrent(client), displayName, true);
|
|
||||||
rsProfileKey = prof.getKey();
|
rsProfileKey = prof.getKey();
|
||||||
this.rsProfileKey = rsProfileKey;
|
this.rsProfileKey = rsProfileKey;
|
||||||
|
|
||||||
|
log.debug("RS profile changed to {}", rsProfileKey);
|
||||||
eventBus.post(new RuneScapeProfileChanged());
|
eventBus.post(new RuneScapeProfileChanged());
|
||||||
}
|
}
|
||||||
setConfiguration(groupName, rsProfileKey, key, value);
|
setConfiguration(groupName, rsProfileKey, key, value);
|
||||||
@@ -790,6 +792,10 @@ public class ConfigManager
|
|||||||
{
|
{
|
||||||
return Integer.parseInt(str);
|
return Integer.parseInt(str);
|
||||||
}
|
}
|
||||||
|
if (type == long.class || type == Long.class)
|
||||||
|
{
|
||||||
|
return Long.parseLong(str);
|
||||||
|
}
|
||||||
if (type == double.class || type == Double.class)
|
if (type == double.class || type == Double.class)
|
||||||
{
|
{
|
||||||
return Double.parseDouble(str);
|
return Double.parseDouble(str);
|
||||||
@@ -1129,10 +1135,12 @@ public class ConfigManager
|
|||||||
return profileKeys.stream()
|
return profileKeys.stream()
|
||||||
.map(key ->
|
.map(key ->
|
||||||
{
|
{
|
||||||
|
Long accid = getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_ACCOUNT_HASH, long.class);
|
||||||
RuneScapeProfile prof = new RuneScapeProfile(
|
RuneScapeProfile prof = new RuneScapeProfile(
|
||||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_DISPLAY_NAME),
|
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_DISPLAY_NAME),
|
||||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_TYPE, RuneScapeProfileType.class),
|
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_TYPE, RuneScapeProfileType.class),
|
||||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_LOGIN_HASH, byte[].class),
|
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_LOGIN_HASH, byte[].class),
|
||||||
|
accid == null ? RuneScapeProfile.ACCOUNT_HASH_INVALID : accid,
|
||||||
key
|
key
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1141,26 +1149,54 @@ public class ConfigManager
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized RuneScapeProfile findRSProfile(List<RuneScapeProfile> profiles, String username, RuneScapeProfileType type, String displayName, boolean create)
|
private synchronized RuneScapeProfile findRSProfile(List<RuneScapeProfile> profiles, RuneScapeProfileType type, String displayName, boolean create)
|
||||||
{
|
{
|
||||||
byte[] salt = getConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, byte[].class);
|
String username = client.getUsername();
|
||||||
if (salt == null)
|
long accountHash = client.getAccountHash();
|
||||||
|
|
||||||
|
if (accountHash == RuneScapeProfile.ACCOUNT_HASH_INVALID && username == null)
|
||||||
{
|
{
|
||||||
salt = new byte[15];
|
return null;
|
||||||
new SecureRandom()
|
|
||||||
.nextBytes(salt);
|
|
||||||
log.info("creating new salt as there is no existing one {}", Base64.getUrlEncoder().encodeToString(salt));
|
|
||||||
setConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, salt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Hasher h = Hashing.sha512().newHasher();
|
final byte[] loginHash;
|
||||||
h.putBytes(salt);
|
byte[] salt = null;
|
||||||
h.putString(username.toLowerCase(Locale.US), StandardCharsets.UTF_8);
|
if (username != null)
|
||||||
byte[] loginHash = h.hash().asBytes();
|
{
|
||||||
|
salt = getConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, byte[].class);
|
||||||
|
if (salt == null)
|
||||||
|
{
|
||||||
|
salt = new byte[15];
|
||||||
|
new SecureRandom()
|
||||||
|
.nextBytes(salt);
|
||||||
|
log.info("creating new salt as there is no existing one {}", Base64.getUrlEncoder().encodeToString(salt));
|
||||||
|
setConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, salt);
|
||||||
|
}
|
||||||
|
|
||||||
Set<RuneScapeProfile> matches = profiles.stream()
|
Hasher h = Hashing.sha512().newHasher();
|
||||||
.filter(p -> Arrays.equals(p.getLoginHash(), loginHash) && p.getType() == type)
|
h.putBytes(salt);
|
||||||
|
h.putString(username.toLowerCase(Locale.US), StandardCharsets.UTF_8);
|
||||||
|
loginHash = h.hash().asBytes();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loginHash = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<RuneScapeProfile> matches = Collections.emptySet();
|
||||||
|
if (accountHash != RuneScapeProfile.ACCOUNT_HASH_INVALID)
|
||||||
|
{
|
||||||
|
matches = profiles.stream()
|
||||||
|
.filter(p -> p.getType() == type && accountHash == p.getAccountHash())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches.isEmpty() && loginHash != null)
|
||||||
|
{
|
||||||
|
matches = profiles.stream()
|
||||||
|
.filter(p -> p.getType() == type && Arrays.equals(loginHash, p.getLoginHash()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
if (matches.size() > 1)
|
if (matches.size() > 1)
|
||||||
{
|
{
|
||||||
@@ -1169,7 +1205,21 @@ public class ConfigManager
|
|||||||
|
|
||||||
if (matches.size() >= 1)
|
if (matches.size() >= 1)
|
||||||
{
|
{
|
||||||
return matches.iterator().next();
|
RuneScapeProfile profile = matches.iterator().next();
|
||||||
|
if (profile.getAccountHash() == RuneScapeProfile.ACCOUNT_HASH_INVALID && accountHash != RuneScapeProfile.ACCOUNT_HASH_INVALID)
|
||||||
|
{
|
||||||
|
int upgrades = 0;
|
||||||
|
for (RuneScapeProfile p : profiles)
|
||||||
|
{
|
||||||
|
if (p.getAccountHash() == RuneScapeProfile.ACCOUNT_HASH_INVALID && Arrays.equals(p.getLoginHash(), loginHash))
|
||||||
|
{
|
||||||
|
setConfiguration(RSPROFILE_GROUP, p.getKey(), RSPROFILE_ACCOUNT_HASH, accountHash);
|
||||||
|
upgrades++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("Attaching account id to {} profiles", upgrades);
|
||||||
|
}
|
||||||
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!create)
|
if (!create)
|
||||||
@@ -1179,22 +1229,41 @@ public class ConfigManager
|
|||||||
|
|
||||||
// generate the new key deterministically so if you "create" the same profile on 2 different clients it doesn't duplicate
|
// generate the new key deterministically so if you "create" the same profile on 2 different clients it doesn't duplicate
|
||||||
Set<String> keys = profiles.stream().map(RuneScapeProfile::getKey).collect(Collectors.toSet());
|
Set<String> keys = profiles.stream().map(RuneScapeProfile::getKey).collect(Collectors.toSet());
|
||||||
byte[] key = Arrays.copyOf(loginHash, 6);
|
byte[] key = accountHash == RuneScapeProfile.ACCOUNT_HASH_INVALID
|
||||||
|
? Arrays.copyOf(loginHash, 6)
|
||||||
|
: new byte[]
|
||||||
|
{
|
||||||
|
(byte) accountHash,
|
||||||
|
(byte) (accountHash >> 8),
|
||||||
|
(byte) (accountHash >> 16),
|
||||||
|
(byte) (accountHash >> 24),
|
||||||
|
(byte) (accountHash >> 32),
|
||||||
|
(byte) (accountHash >> 40),
|
||||||
|
};
|
||||||
key[0] += type.ordinal();
|
key[0] += type.ordinal();
|
||||||
for (int i = 0; i < 0xFF; i++, key[1]++)
|
for (int i = 0; i < 0xFF; i++, key[1]++)
|
||||||
{
|
{
|
||||||
String keyStr = RSPROFILE_GROUP + "." + Base64.getUrlEncoder().encodeToString(key);
|
String keyStr = RSPROFILE_GROUP + "." + Base64.getUrlEncoder().encodeToString(key);
|
||||||
if (!keys.contains(keyStr))
|
if (!keys.contains(keyStr))
|
||||||
{
|
{
|
||||||
log.info("creating new profile {} for user {} ({}) salt {}", keyStr, username, type, Base64.getUrlEncoder().encodeToString(salt));
|
log.info("creating new profile {} for username {} account hash {} ({}) salt {}",
|
||||||
|
keyStr, username, accountHash, type,
|
||||||
|
salt == null ? "null" : Base64.getUrlEncoder().encodeToString(salt));
|
||||||
|
|
||||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_LOGIN_HASH, loginHash);
|
if (loginHash != null)
|
||||||
|
{
|
||||||
|
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_LOGIN_HASH, loginHash);
|
||||||
|
}
|
||||||
|
if (accountHash != RuneScapeProfile.ACCOUNT_HASH_INVALID)
|
||||||
|
{
|
||||||
|
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_ACCOUNT_HASH, accountHash);
|
||||||
|
}
|
||||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_TYPE, type);
|
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_TYPE, type);
|
||||||
if (displayName != null)
|
if (displayName != null)
|
||||||
{
|
{
|
||||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_DISPLAY_NAME, displayName);
|
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_DISPLAY_NAME, displayName);
|
||||||
}
|
}
|
||||||
return new RuneScapeProfile(displayName, type, loginHash, keyStr);
|
return new RuneScapeProfile(displayName, type, loginHash, accountHash, keyStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("too many rs profiles");
|
throw new RuntimeException("too many rs profiles");
|
||||||
@@ -1208,7 +1277,7 @@ public class ConfigManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<RuneScapeProfile> profiles = getRSProfiles();
|
List<RuneScapeProfile> profiles = getRSProfiles();
|
||||||
RuneScapeProfile prof = findRSProfile(profiles, client.getUsername(), RuneScapeProfileType.getCurrent(client), null, false);
|
RuneScapeProfile prof = findRSProfile(profiles, RuneScapeProfileType.getCurrent(client), null, false);
|
||||||
|
|
||||||
String key = prof == null ? null : prof.getKey();
|
String key = prof == null ? null : prof.getKey();
|
||||||
if (Objects.equals(key, rsProfileKey))
|
if (Objects.equals(key, rsProfileKey))
|
||||||
@@ -1217,6 +1286,7 @@ public class ConfigManager
|
|||||||
}
|
}
|
||||||
rsProfileKey = key;
|
rsProfileKey = key;
|
||||||
|
|
||||||
|
log.debug("RS profile changed to {}", key);
|
||||||
eventBus.post(new RuneScapeProfileChanged());
|
eventBus.post(new RuneScapeProfileChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1226,6 +1296,12 @@ public class ConfigManager
|
|||||||
updateRSProfile();
|
updateRSProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
private void onAccountHashChanged(AccountHashChanged ev)
|
||||||
|
{
|
||||||
|
updateRSProfile();
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
private void onWorldChanged(WorldChanged ev)
|
private void onWorldChanged(WorldChanged ev)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,9 +33,12 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class RuneScapeProfile
|
public class RuneScapeProfile
|
||||||
{
|
{
|
||||||
|
public static final int ACCOUNT_HASH_INVALID = -1;
|
||||||
|
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
private final RuneScapeProfileType type;
|
private final RuneScapeProfileType type;
|
||||||
private final byte[] loginHash;
|
private final byte[] loginHash;
|
||||||
|
private final long accountHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profile key used to save configs for this profile to the config store. This will
|
* Profile key used to save configs for this profile to the config store. This will
|
||||||
|
|||||||
@@ -110,10 +110,8 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
private static final String TEAM_SIZES = "(?:\\d+(?:\\+|-\\d+)? players|Solo)";
|
private static final String 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>" + TEAM_SIZES + "</col> Duration:</col> <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)</col>");
|
private static final Pattern RAIDS_PB_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + 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>" + 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 RAIDS_DURATION_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + 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> \\(new personal best\\)");
|
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in|(?<!total )completion time:) <col=[0-9a-f]{6}>[0-9:.]+</col>\\. Personal best: (?:<col=ff0000>)?(?<pb>[0-9:]+(?:\\.[0-9]+)?)");
|
||||||
private static final Pattern TOB_WAVE_DURATION_PATTERN = Pattern.compile("Theatre of Blood wave completion time: <col=ff0000>[0-9:.]+</col>\\. Personal best: (?<pb>[0-9:]+(?:\\.[0-9]+)?)");
|
private static final Pattern NEW_PB_PATTERN = Pattern.compile("(?i)(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in|(?<!total )completion time:) <col=[0-9a-f]{6}>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)");
|
||||||
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in) <col=[0-9a-f]{6}>[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:|Subdued in) <col=[0-9a-f]{6}>(?<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,]+|one) duels?");
|
private static final Pattern DUEL_ARENA_WINS_PATTERN = Pattern.compile("You (were defeated|won)! You have(?: now)? won ([\\d,]+|one) duels?");
|
||||||
private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost ([\\d,]+|one) duels?");
|
private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost ([\\d,]+|one) duels?");
|
||||||
private static final Pattern ADVENTURE_LOG_TITLE_PATTERN = Pattern.compile("The Exploits of (.+)");
|
private static final Pattern ADVENTURE_LOG_TITLE_PATTERN = Pattern.compile("The Exploits of (.+)");
|
||||||
@@ -123,6 +121,7 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
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_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 Pattern HS_KC_GHC_PATTERN = Pattern.compile("You have opened the Grand Hallowed Coffin <col=ff0000>([0-9,]+)</col> times?!");
|
||||||
private static final Pattern COLLECTION_LOG_ITEM_PATTERN = Pattern.compile("New item added to your collection log: (.*)");
|
private static final Pattern COLLECTION_LOG_ITEM_PATTERN = Pattern.compile("New item added to your collection log: (.*)");
|
||||||
|
private static final Pattern GUARDIANS_OF_THE_RIFT_PATTERN = Pattern.compile("Amount of Rifts you have closed: <col=ff0000>([0-9,]+)</col>.");
|
||||||
|
|
||||||
private static final String TOTAL_LEVEL_COMMAND_STRING = "!total";
|
private static final String TOTAL_LEVEL_COMMAND_STRING = "!total";
|
||||||
private static final String PRICE_COMMAND_STRING = "!price";
|
private static final String PRICE_COMMAND_STRING = "!price";
|
||||||
@@ -469,18 +468,6 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
matchPb(matcher);
|
matchPb(matcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher = TOB_WAVE_PB_PATTERN.matcher(message);
|
|
||||||
if (matcher.find())
|
|
||||||
{
|
|
||||||
matchPb(matcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher = TOB_WAVE_DURATION_PATTERN.matcher(message);
|
|
||||||
if (matcher.find())
|
|
||||||
{
|
|
||||||
matchPb(matcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher = HS_PB_PATTERN.matcher(message);
|
matcher = HS_PB_PATTERN.matcher(message);
|
||||||
if (matcher.find())
|
if (matcher.find())
|
||||||
{
|
{
|
||||||
@@ -538,6 +525,13 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matcher = GUARDIANS_OF_THE_RIFT_PATTERN.matcher(message);
|
||||||
|
if (matcher.find())
|
||||||
|
{
|
||||||
|
int kc = Integer.parseInt(matcher.group(1));
|
||||||
|
setKc("Guardians of the Rift", kc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -1970,6 +1964,7 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
case "tob hm":
|
case "tob hm":
|
||||||
case "tob hard mode":
|
case "tob hard mode":
|
||||||
case "tob hard":
|
case "tob hard":
|
||||||
|
case "hmt":
|
||||||
return "Theatre of Blood Hard Mode";
|
return "Theatre of Blood Hard Mode";
|
||||||
|
|
||||||
// agility course
|
// agility course
|
||||||
@@ -2152,6 +2147,11 @@ public class ChatCommandsPlugin extends Plugin
|
|||||||
case "jad 6":
|
case "jad 6":
|
||||||
return "TzHaar-Ket-Rak's Sixth Challenge";
|
return "TzHaar-Ket-Rak's Sixth Challenge";
|
||||||
|
|
||||||
|
// Guardians of the Rift
|
||||||
|
case "gotr":
|
||||||
|
case "runetodt":
|
||||||
|
return "Guardians of the Rift";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return WordUtils.capitalize(boss);
|
return WordUtils.capitalize(boss);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ enum DiscordGameEventType
|
|||||||
MG_TZHAAR_FIGHT_PITS("Tzhaar Fight Pits", DiscordAreaType.MINIGAMES, 9552),
|
MG_TZHAAR_FIGHT_PITS("Tzhaar Fight Pits", DiscordAreaType.MINIGAMES, 9552),
|
||||||
MG_VARROCK_RAT_PITS("Varrock Rat Pits", DiscordAreaType.MINIGAMES, 11599),
|
MG_VARROCK_RAT_PITS("Varrock Rat Pits", DiscordAreaType.MINIGAMES, 11599),
|
||||||
MG_VOLCANIC_MINE("Volcanic Mine", DiscordAreaType.MINIGAMES, 15263, 15262),
|
MG_VOLCANIC_MINE("Volcanic Mine", DiscordAreaType.MINIGAMES, 15263, 15262),
|
||||||
|
MG_GUARDIANS_OF_THE_RIFT("Guardians of the Rift", DiscordAreaType.MINIGAMES, 14484),
|
||||||
|
|
||||||
// Raids
|
// Raids
|
||||||
RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, 12889, 13136, 13137, 13138, 13139, 13140, 13141, 13145, 13393, 13394, 13395, 13396, 13397, 13401),
|
RAIDS_CHAMBERS_OF_XERIC("Chambers of Xeric", DiscordAreaType.RAIDS, 12889, 13136, 13137, 13138, 13139, 13140, 13141, 13145, 13393, 13394, 13395, 13396, 13397, 13401),
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
private boolean wasFuzzySearch;
|
private boolean wasFuzzySearch;
|
||||||
|
|
||||||
private String machineUuid;
|
private String machineUuid;
|
||||||
private String lastUsername;
|
private long lastAccount;
|
||||||
private int tradeSeq;
|
private int tradeSeq;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -298,7 +298,8 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
clientToolbar.removeNavigation(button);
|
clientToolbar.removeNavigation(button);
|
||||||
mouseManager.unregisterMouseListener(inputListener);
|
mouseManager.unregisterMouseListener(inputListener);
|
||||||
keyManager.unregisterKeyListener(inputListener);
|
keyManager.unregisterKeyListener(inputListener);
|
||||||
lastUsername = machineUuid = null;
|
machineUuid = null;
|
||||||
|
lastAccount = -1L;
|
||||||
tradeSeq = 0;
|
tradeSeq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,13 +894,13 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
|
|
||||||
private String getMachineUuid()
|
private String getMachineUuid()
|
||||||
{
|
{
|
||||||
String username = client.getUsername();
|
long accountHash = client.getAccountHash();
|
||||||
if (lastUsername == username)
|
if (lastAccount == accountHash)
|
||||||
{
|
{
|
||||||
return machineUuid;
|
return machineUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUsername = username;
|
lastAccount = accountHash;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -922,7 +923,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
hasher.putBytes(hardwareAddress);
|
hasher.putBytes(hardwareAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasher.putUnencodedChars(username);
|
hasher.putLong(accountHash);
|
||||||
machineUuid = hasher.hash().toString();
|
machineUuid = hasher.hash().toString();
|
||||||
tradeSeq = 0;
|
tradeSeq = 0;
|
||||||
return machineUuid;
|
return machineUuid;
|
||||||
|
|||||||
@@ -263,6 +263,12 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
private static final String TEMPOROSS_LOOT_STRING = "You found some loot: ";
|
private static final String TEMPOROSS_LOOT_STRING = "You found some loot: ";
|
||||||
private static final int TEMPOROSS_REGION = 12588;
|
private static final int TEMPOROSS_REGION = 12588;
|
||||||
|
|
||||||
|
// Guardians of the Rift
|
||||||
|
private static final String GUARDIANS_OF_THE_RIFT_EVENT = "Guardians of the Rift";
|
||||||
|
private static final String INTRICATE_POUCH_EVENT = "Intricate pouch";
|
||||||
|
private static final String GUARDIANS_OF_THE_RIFT_LOOT_STRING = "You found some loot: ";
|
||||||
|
private static final int GUARDIANS_OF_THE_RIFT_REGION = 14484;
|
||||||
|
|
||||||
// Mahogany Homes
|
// Mahogany Homes
|
||||||
private static final String MAHOGANY_CRATE_EVENT = "Supply crate (Mahogany Homes)";
|
private static final String MAHOGANY_CRATE_EVENT = "Supply crate (Mahogany Homes)";
|
||||||
|
|
||||||
@@ -480,6 +486,13 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
|
|
||||||
clientThread.invokeLater(() ->
|
clientThread.invokeLater(() ->
|
||||||
{
|
{
|
||||||
|
// convertToLootTrackerRecord requires item compositions to be available to get the item name,
|
||||||
|
// so it can't be run while the client is starting
|
||||||
|
if (client.getGameState().getState() < GameState.LOGIN_SCREEN.getState())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// convertToLootTrackerRecord must be called on client thread
|
// convertToLootTrackerRecord must be called on client thread
|
||||||
List<LootTrackerRecord> records = loots.stream()
|
List<LootTrackerRecord> records = loots.stream()
|
||||||
.map(this::convertToLootTrackerRecord)
|
.map(this::convertToLootTrackerRecord)
|
||||||
@@ -489,6 +502,8 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
panel.clearRecords();
|
panel.clearRecords();
|
||||||
panel.addRecords(records);
|
panel.addRecords(records);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -887,6 +902,12 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (regionID == GUARDIANS_OF_THE_RIFT_REGION && message.startsWith(GUARDIANS_OF_THE_RIFT_LOOT_STRING))
|
||||||
|
{
|
||||||
|
onInvChange(collectInvItems(LootRecordType.EVENT, GUARDIANS_OF_THE_RIFT_EVENT, client.getBoostedSkillLevel(Skill.RUNECRAFT)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.equals(IMPLING_CATCH_MESSAGE))
|
if (message.equals(IMPLING_CATCH_MESSAGE))
|
||||||
{
|
{
|
||||||
onInvChange(collectInvItems(LootRecordType.EVENT, client.getLocalPlayer().getInteracting().getName()));
|
onInvChange(collectInvItems(LootRecordType.EVENT, client.getLocalPlayer().getInteracting().getName()));
|
||||||
@@ -977,6 +998,9 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
case ItemID.CASKET_25590:
|
case ItemID.CASKET_25590:
|
||||||
onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT));
|
onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, TEMPOROSS_CASKET_EVENT));
|
||||||
break;
|
break;
|
||||||
|
case ItemID.INTRICATE_POUCH:
|
||||||
|
onInvChange(collectInvAndGroundItems(LootRecordType.EVENT, INTRICATE_POUCH_EVENT));
|
||||||
|
break;
|
||||||
case ItemID.SIMPLE_LOCKBOX_25647:
|
case ItemID.SIMPLE_LOCKBOX_25647:
|
||||||
case ItemID.ELABORATE_LOCKBOX_25649:
|
case ItemID.ELABORATE_LOCKBOX_25649:
|
||||||
case ItemID.ORNATE_LOCKBOX_25651:
|
case ItemID.ORNATE_LOCKBOX_25651:
|
||||||
|
|||||||
@@ -826,4 +826,34 @@ public interface MenuEntrySwapperConfig extends Config
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "swapDepositPool",
|
||||||
|
name = "Deposit Pool - Only Runes",
|
||||||
|
description = "Swap Deposit with Deposit Runes on the Deposit Pool in Guardians of the Rift.",
|
||||||
|
section = objectSection
|
||||||
|
)
|
||||||
|
default boolean swapDepositPool()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UnchargedCellsMode
|
||||||
|
{
|
||||||
|
TAKE,
|
||||||
|
TAKE_1,
|
||||||
|
TAKE_5,
|
||||||
|
TAKE_10
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "swapUnchargedCells",
|
||||||
|
name = "Uncharged Cells",
|
||||||
|
description = "Swap the take option for Uncharged Cells in Guardians of the Rift.",
|
||||||
|
section = objectSection
|
||||||
|
)
|
||||||
|
default UnchargedCellsMode swapUnchargedCells()
|
||||||
|
{
|
||||||
|
return UnchargedCellsMode.TAKE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfi
|
|||||||
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.KaramjaGlovesMode;
|
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.KaramjaGlovesMode;
|
||||||
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.MorytaniaLegsMode;
|
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.MorytaniaLegsMode;
|
||||||
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.RadasBlessingMode;
|
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.RadasBlessingMode;
|
||||||
|
import static net.runelite.client.plugins.menuentryswapper.MenuEntrySwapperConfig.UnchargedCellsMode;
|
||||||
import net.runelite.client.util.Text;
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
@@ -419,6 +420,12 @@ public class MenuEntrySwapperPlugin extends Plugin
|
|||||||
|
|
||||||
swap("climb", "climb-up", () -> (shiftModifier() ? config.swapStairsShiftClick() : config.swapStairsLeftClick()) == MenuEntrySwapperConfig.StairsMode.CLIMB_UP);
|
swap("climb", "climb-up", () -> (shiftModifier() ? config.swapStairsShiftClick() : config.swapStairsLeftClick()) == MenuEntrySwapperConfig.StairsMode.CLIMB_UP);
|
||||||
swap("climb", "climb-down", () -> (shiftModifier() ? config.swapStairsShiftClick() : config.swapStairsLeftClick()) == MenuEntrySwapperConfig.StairsMode.CLIMB_DOWN);
|
swap("climb", "climb-down", () -> (shiftModifier() ? config.swapStairsShiftClick() : config.swapStairsLeftClick()) == MenuEntrySwapperConfig.StairsMode.CLIMB_DOWN);
|
||||||
|
|
||||||
|
swap("deposit", "deposit-runes", config::swapDepositPool);
|
||||||
|
|
||||||
|
swap("take", "uncharged cells", "take-1", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_1);
|
||||||
|
swap("take", "uncharged cells", "take-5", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_5);
|
||||||
|
swap("take", "uncharged cells", "take-10", () -> config.swapUnchargedCells() == UnchargedCellsMode.TAKE_10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Swap swap(String option, String swappedOption, Supplier<Boolean> enabled)
|
public Swap swap(String option, String swappedOption, Supplier<Boolean> enabled)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class NpcAggroAreaNotWorkingOverlay extends OverlayPanel
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
|
||||||
panelComponent.getChildren().add(LineComponent.builder()
|
panelComponent.getChildren().add(LineComponent.builder()
|
||||||
.left("Unaggressive NPC timers will start working when you teleport far away or enter a dungeon.")
|
.left("Unaggressive NPC timers require calibration. Teleport far away or enter a dungeon, then run until this overlay disappears.")
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
setPriority(OverlayPriority.LOW);
|
setPriority(OverlayPriority.LOW);
|
||||||
@@ -53,7 +53,7 @@ class NpcAggroAreaNotWorkingOverlay extends OverlayPanel
|
|||||||
@Override
|
@Override
|
||||||
public Dimension render(Graphics2D graphics)
|
public Dimension render(Graphics2D graphics)
|
||||||
{
|
{
|
||||||
if (!plugin.isActive() || plugin.getSafeCenters()[1] != null)
|
if (plugin.getSafeCenters()[1] != null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
|
||||||
|
* Copyright (c) 2022 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.client.plugins.questlist;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.ParamID;
|
||||||
|
import net.runelite.api.ScriptID;
|
||||||
|
import net.runelite.api.SoundEffectID;
|
||||||
|
import net.runelite.api.SpriteID;
|
||||||
|
import net.runelite.api.VarClientInt;
|
||||||
|
import net.runelite.api.Varbits;
|
||||||
|
import net.runelite.api.events.ScriptCallbackEvent;
|
||||||
|
import net.runelite.api.events.ScriptPostFired;
|
||||||
|
import net.runelite.api.events.VarClientIntChanged;
|
||||||
|
import net.runelite.api.events.VarbitChanged;
|
||||||
|
import net.runelite.api.widgets.JavaScriptCallback;
|
||||||
|
import net.runelite.api.widgets.Widget;
|
||||||
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.api.widgets.WidgetPositionMode;
|
||||||
|
import net.runelite.api.widgets.WidgetType;
|
||||||
|
import net.runelite.client.callback.ClientThread;
|
||||||
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
|
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||||
|
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||||
|
import net.runelite.client.plugins.Plugin;
|
||||||
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
|
||||||
|
@PluginDescriptor(
|
||||||
|
name = "Quest List",
|
||||||
|
description = "Adds a search filter to the quest list"
|
||||||
|
)
|
||||||
|
public class QuestListPlugin extends Plugin
|
||||||
|
{
|
||||||
|
private static final String MENU_OPEN = "Open";
|
||||||
|
private static final String MENU_CLOSE = "Close";
|
||||||
|
private static final String MENU_SEARCH = "Search";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ChatboxPanelManager chatboxPanelManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ClientThread clientThread;
|
||||||
|
|
||||||
|
private ChatboxTextInput searchInput;
|
||||||
|
private Widget questSearchButton;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startUp()
|
||||||
|
{
|
||||||
|
clientThread.invoke(this::addQuestButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void shutDown()
|
||||||
|
{
|
||||||
|
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
header.deleteAllChildren();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onScriptPostFired(ScriptPostFired event)
|
||||||
|
{
|
||||||
|
if (event.getScriptId() == ScriptID.QUESTLIST_INIT)
|
||||||
|
{
|
||||||
|
addQuestButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addQuestButtons()
|
||||||
|
{
|
||||||
|
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
header.deleteAllChildren();
|
||||||
|
|
||||||
|
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||||
|
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||||
|
questSearchButton.setOriginalWidth(18);
|
||||||
|
questSearchButton.setOriginalHeight(17);
|
||||||
|
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||||
|
questSearchButton.setOriginalX(5);
|
||||||
|
questSearchButton.setOriginalY(0);
|
||||||
|
questSearchButton.setHasListener(true);
|
||||||
|
questSearchButton.setAction(1, MENU_OPEN);
|
||||||
|
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||||
|
questSearchButton.setName(MENU_SEARCH);
|
||||||
|
questSearchButton.revalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||||
|
{
|
||||||
|
if (isChatboxOpen() && !isOnQuestTab())
|
||||||
|
{
|
||||||
|
chatboxPanelManager.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||||
|
{
|
||||||
|
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
|
||||||
|
{
|
||||||
|
if (isChatboxOpen() && !isOnQuestTab())
|
||||||
|
{
|
||||||
|
chatboxPanelManager.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||||
|
{
|
||||||
|
if (!"questFilter".equals(scriptCallbackEvent.getEventName()) || !isChatboxOpen())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String filter = searchInput.getValue();
|
||||||
|
if (Strings.isNullOrEmpty(filter))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] intStack = client.getIntStack();
|
||||||
|
final int intStackSize = client.getIntStackSize();
|
||||||
|
|
||||||
|
final int questStruct = intStack[intStackSize - 1];
|
||||||
|
final String questName = client.getStructComposition(questStruct)
|
||||||
|
.getStringValue(ParamID.QUEST_NAME);
|
||||||
|
|
||||||
|
intStack[intStackSize - 2] = questName.toLowerCase().contains(filter.toLowerCase()) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOnQuestTab()
|
||||||
|
{
|
||||||
|
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isChatboxOpen()
|
||||||
|
{
|
||||||
|
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeSearch()
|
||||||
|
{
|
||||||
|
chatboxPanelManager.close();
|
||||||
|
redrawQuests();
|
||||||
|
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openSearch()
|
||||||
|
{
|
||||||
|
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||||
|
questSearchButton.setAction(1, MENU_CLOSE);
|
||||||
|
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||||
|
searchInput = chatboxPanelManager.openTextInput("Search quest list")
|
||||||
|
.onChanged(s -> redrawQuests())
|
||||||
|
.onDone(s -> false)
|
||||||
|
.onClose(() ->
|
||||||
|
{
|
||||||
|
redrawQuests();
|
||||||
|
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||||
|
questSearchButton.setAction(1, MENU_OPEN);
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void redrawQuests()
|
||||||
|
{
|
||||||
|
Widget w = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
|
||||||
|
if (w == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] onVarTransmitListener = w.getOnVarTransmitListener();
|
||||||
|
if (onVarTransmitListener == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientThread.invokeLater(() ->
|
||||||
|
client.runScript(onVarTransmitListener));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,6 @@ import java.awt.image.BufferedImage;
|
|||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -123,7 +122,7 @@ public class XpTrackerPlugin extends Plugin
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
private XpPanel xpPanel;
|
private XpPanel xpPanel;
|
||||||
private XpWorldType lastWorldType;
|
private XpWorldType lastWorldType;
|
||||||
private String lastUsername;
|
private long lastAccount;
|
||||||
private long lastTickMillis = 0;
|
private long lastTickMillis = 0;
|
||||||
private boolean fetchXp; // fetch lastXp for the online xp tracker
|
private boolean fetchXp; // fetch lastXp for the online xp tracker
|
||||||
private long lastXp = 0;
|
private long lastXp = 0;
|
||||||
@@ -162,6 +161,7 @@ public class XpTrackerPlugin extends Plugin
|
|||||||
// Initialize the tracker & last xp if already logged in
|
// Initialize the tracker & last xp if already logged in
|
||||||
fetchXp = true;
|
fetchXp = true;
|
||||||
initializeTracker = true;
|
initializeTracker = true;
|
||||||
|
lastAccount = -1L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -182,15 +182,15 @@ public class XpTrackerPlugin extends Plugin
|
|||||||
// Check that the username changed or the world type changed.
|
// Check that the username changed or the world type changed.
|
||||||
XpWorldType type = worldSetToType(client.getWorldType());
|
XpWorldType type = worldSetToType(client.getWorldType());
|
||||||
|
|
||||||
if (!Objects.equals(client.getUsername(), lastUsername) || lastWorldType != type)
|
if (client.getAccountHash() != lastAccount || lastWorldType != type)
|
||||||
{
|
{
|
||||||
// Reset
|
// Reset
|
||||||
log.debug("World change: {} -> {}, {} -> {}",
|
log.debug("World change: {} -> {}, {} -> {}",
|
||||||
lastUsername, client.getUsername(),
|
lastAccount, client.getAccountHash(),
|
||||||
firstNonNull(lastWorldType, "<unknown>"),
|
firstNonNull(lastWorldType, "<unknown>"),
|
||||||
firstNonNull(type, "<unknown>"));
|
firstNonNull(type, "<unknown>"));
|
||||||
|
|
||||||
lastUsername = client.getUsername();
|
lastAccount = client.getAccountHash();
|
||||||
// xp is not available until after login is finished, so fetch it on the next gametick
|
// xp is not available until after login is finished, so fetch it on the next gametick
|
||||||
fetchXp = true;
|
fetchXp = true;
|
||||||
lastWorldType = type;
|
lastWorldType = type;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ package net.runelite.client.plugins.xpupdater;
|
|||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -74,7 +73,7 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
@Inject
|
@Inject
|
||||||
private OkHttpClient okHttpClient;
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
private String lastUsername;
|
private long lastAccount;
|
||||||
private boolean fetchXp;
|
private boolean fetchXp;
|
||||||
private long lastXp;
|
private long lastXp;
|
||||||
|
|
||||||
@@ -88,6 +87,7 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
protected void startUp()
|
protected void startUp()
|
||||||
{
|
{
|
||||||
fetchXp = true;
|
fetchXp = true;
|
||||||
|
lastAccount = -1L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -96,9 +96,9 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
GameState state = gameStateChanged.getGameState();
|
GameState state = gameStateChanged.getGameState();
|
||||||
if (state == GameState.LOGGED_IN)
|
if (state == GameState.LOGGED_IN)
|
||||||
{
|
{
|
||||||
if (!Objects.equals(client.getUsername(), lastUsername))
|
if (lastAccount != client.getAccountHash())
|
||||||
{
|
{
|
||||||
lastUsername = client.getUsername();
|
lastAccount = client.getAccountHash();
|
||||||
fetchXp = true;
|
fetchXp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,8 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
// Don't submit update unless xp threshold is reached
|
// Don't submit update unless xp threshold is reached
|
||||||
if (Math.abs(totalXp - lastXp) > XP_THRESHOLD)
|
if (Math.abs(totalXp - lastXp) > XP_THRESHOLD)
|
||||||
{
|
{
|
||||||
log.debug("Submitting update for {}", local.getName());
|
log.debug("Submitting update for {} accountHash {}", local.getName(), lastAccount);
|
||||||
update(local.getName());
|
update(lastAccount, local.getName());
|
||||||
lastXp = totalXp;
|
lastXp = totalXp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,12 +131,12 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update(String username)
|
private void update(long accountHash, String username)
|
||||||
{
|
{
|
||||||
EnumSet<WorldType> worldTypes = client.getWorldType();
|
EnumSet<WorldType> worldTypes = client.getWorldType();
|
||||||
username = username.replace(" ", "_");
|
username = username.replace(" ", "_");
|
||||||
updateCml(username, worldTypes);
|
updateCml(username, worldTypes);
|
||||||
updateTempleosrs(username, worldTypes);
|
updateTempleosrs(accountHash, username, worldTypes);
|
||||||
updateWom(username, worldTypes);
|
updateWom(username, worldTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTempleosrs(String username, EnumSet<WorldType> worldTypes)
|
private void updateTempleosrs(long accountHash, String username, EnumSet<WorldType> worldTypes)
|
||||||
{
|
{
|
||||||
if (config.templeosrs()
|
if (config.templeosrs()
|
||||||
&& !worldTypes.contains(WorldType.SEASONAL)
|
&& !worldTypes.contains(WorldType.SEASONAL)
|
||||||
@@ -178,6 +178,7 @@ public class XpUpdaterPlugin extends Plugin
|
|||||||
.addPathSegment("php")
|
.addPathSegment("php")
|
||||||
.addPathSegment("add_datapoint.php")
|
.addPathSegment("add_datapoint.php")
|
||||||
.addQueryParameter("player", username)
|
.addQueryParameter("player", username)
|
||||||
|
.addQueryParameter("accountHash", Long.toString(accountHash))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.client.RuneLite;
|
import net.runelite.client.RuneLite;
|
||||||
import net.runelite.client.RuneLiteProperties;
|
import net.runelite.client.RuneLiteProperties;
|
||||||
|
import net.runelite.client.RuntimeConfig;
|
||||||
|
import net.runelite.client.RuntimeConfigLoader;
|
||||||
import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO;
|
import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO;
|
||||||
import static net.runelite.client.rs.ClientUpdateCheckMode.NONE;
|
import static net.runelite.client.rs.ClientUpdateCheckMode.NONE;
|
||||||
import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA;
|
import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA;
|
||||||
@@ -74,7 +76,7 @@ import okhttp3.Request;
|
|||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings({"deprecation", "removal"})
|
||||||
public class ClientLoader implements Supplier<Applet>
|
public class ClientLoader implements Supplier<Applet>
|
||||||
{
|
{
|
||||||
private static final String INJECTED_CLIENT_NAME = "/injected-client.oprs";
|
private static final String INJECTED_CLIENT_NAME = "/injected-client.oprs";
|
||||||
@@ -87,16 +89,18 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
private final ClientConfigLoader clientConfigLoader;
|
private final ClientConfigLoader clientConfigLoader;
|
||||||
private ClientUpdateCheckMode updateCheckMode;
|
private ClientUpdateCheckMode updateCheckMode;
|
||||||
private final WorldSupplier worldSupplier;
|
private final WorldSupplier worldSupplier;
|
||||||
|
private final RuntimeConfigLoader runtimeConfigLoader;
|
||||||
private final String javConfigUrl;
|
private final String javConfigUrl;
|
||||||
|
|
||||||
private Object client;
|
private Object client;
|
||||||
|
|
||||||
public ClientLoader(OkHttpClient okHttpClient, ClientUpdateCheckMode updateCheckMode, String javConfigUrl)
|
public ClientLoader(OkHttpClient okHttpClient, ClientUpdateCheckMode updateCheckMode, RuntimeConfigLoader runtimeConfigLoader, String javConfigUrl)
|
||||||
{
|
{
|
||||||
this.okHttpClient = okHttpClient;
|
this.okHttpClient = okHttpClient;
|
||||||
this.clientConfigLoader = new ClientConfigLoader(okHttpClient);
|
this.clientConfigLoader = new ClientConfigLoader(okHttpClient);
|
||||||
this.updateCheckMode = updateCheckMode;
|
this.updateCheckMode = updateCheckMode;
|
||||||
this.worldSupplier = new WorldSupplier(okHttpClient);
|
this.worldSupplier = new WorldSupplier(okHttpClient);
|
||||||
|
this.runtimeConfigLoader = runtimeConfigLoader;
|
||||||
this.javConfigUrl = javConfigUrl;
|
this.javConfigUrl = javConfigUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,12 +187,19 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
catch (OutageException e)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException
|
catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException
|
||||||
| VerificationException | SecurityException e)
|
| VerificationException | SecurityException e)
|
||||||
{
|
{
|
||||||
log.error("Error loading RS!", e);
|
log.error("Error loading RS!", e);
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> FatalErrorDialog.showNetErrorWindow("loading the client", e));
|
if (!checkOutages())
|
||||||
|
{
|
||||||
|
SwingUtilities.invokeLater(() -> FatalErrorDialog.showNetErrorWindow("loading the client", e));
|
||||||
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,6 +224,10 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
log.info("Failed to get jav_config from host \"{}\" ({})", url.host(), e.getMessage());
|
log.info("Failed to get jav_config from host \"{}\" ({})", url.host(), e.getMessage());
|
||||||
|
if (checkOutages())
|
||||||
|
{
|
||||||
|
throw new OutageException(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()))
|
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()))
|
||||||
{
|
{
|
||||||
@@ -301,6 +316,11 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
}
|
}
|
||||||
vanilla.position(0);
|
vanilla.position(0);
|
||||||
|
|
||||||
|
if (!vanillaCacheIsInvalid && "false".equals(System.getProperty("runelite.updateVanilla")))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Start downloading the vanilla client
|
// Start downloading the vanilla client
|
||||||
HttpUrl url;
|
HttpUrl url;
|
||||||
if (config.isFallback())
|
if (config.isFallback())
|
||||||
@@ -412,6 +432,10 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
log.warn("Failed to download gamepack from \"{}\"", url, e);
|
log.warn("Failed to download gamepack from \"{}\"", url, e);
|
||||||
|
if (checkOutages())
|
||||||
|
{
|
||||||
|
throw new OutageException(e);
|
||||||
|
}
|
||||||
|
|
||||||
// With fallback config do 1 attempt (there are no additional urls to try)
|
// With fallback config do 1 attempt (there are no additional urls to try)
|
||||||
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()) || config.isFallback() || attempt >= NUM_ATTEMPTS)
|
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()) || config.isFallback() || attempt >= NUM_ATTEMPTS)
|
||||||
@@ -438,6 +462,7 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
SwingUtilities.invokeLater(() ->
|
SwingUtilities.invokeLater(() ->
|
||||||
new FatalErrorDialog("The client-patch is missing from the classpath. If you are building " +
|
new FatalErrorDialog("The client-patch is missing from the classpath. If you are building " +
|
||||||
"the client you need to re-run maven")
|
"the client you need to re-run maven")
|
||||||
|
.addHelpButtons()
|
||||||
.addBuildingGuide()
|
.addBuildingGuide()
|
||||||
.open());
|
.open());
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
@@ -605,7 +630,7 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
Class<?> clientClass = classLoader.loadClass(initialClass);
|
Class<?> clientClass = classLoader.loadClass(initialClass);
|
||||||
|
|
||||||
Applet rs = (Applet) clientClass.newInstance();
|
Applet rs = (Applet) clientClass.newInstance();
|
||||||
rs.setStub(new RSAppletStub(config));
|
rs.setStub(new RSAppletStub(config, runtimeConfigLoader));
|
||||||
|
|
||||||
if (rs instanceof Client)
|
if (rs instanceof Client)
|
||||||
{
|
{
|
||||||
@@ -658,4 +683,22 @@ public class ClientLoader implements Supplier<Applet>
|
|||||||
verifyJarEntry(je, chains);
|
verifyJarEntry(je, chains);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class OutageException extends RuntimeException
|
||||||
|
{
|
||||||
|
private OutageException(Throwable cause)
|
||||||
|
{
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkOutages()
|
||||||
|
{
|
||||||
|
RuntimeConfig rtc = runtimeConfigLoader.tryGet();
|
||||||
|
if (rtc != null)
|
||||||
|
{
|
||||||
|
return rtc.showOutageMessage();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,28 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.rs;
|
package net.runelite.client.rs;
|
||||||
|
|
||||||
|
import java.applet.Applet;
|
||||||
import java.applet.AppletContext;
|
import java.applet.AppletContext;
|
||||||
import java.applet.AppletStub;
|
import java.applet.AppletStub;
|
||||||
|
import java.applet.AudioClip;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.runelite.client.RuntimeConfig;
|
||||||
|
import net.runelite.client.RuntimeConfigLoader;
|
||||||
|
import net.runelite.client.ui.FatalErrorDialog;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
class RSAppletStub implements AppletStub
|
class RSAppletStub implements AppletStub
|
||||||
{
|
{
|
||||||
private final RSConfig config;
|
private final RSConfig config;
|
||||||
|
private final RuntimeConfigLoader runtimeConfigLoader;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive()
|
public boolean isActive()
|
||||||
@@ -70,7 +82,89 @@ class RSAppletStub implements AppletStub
|
|||||||
@Override
|
@Override
|
||||||
public AppletContext getAppletContext()
|
public AppletContext getAppletContext()
|
||||||
{
|
{
|
||||||
return null;
|
return new AppletContext()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public AudioClip getAudioClip(URL url)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image getImage(URL url)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Applet getApplet(String name)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enumeration<Applet> getApplets()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showDocument(URL url)
|
||||||
|
{
|
||||||
|
if (url.getPath().startsWith("/error_game_"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RuntimeConfig rtc = runtimeConfigLoader.get();
|
||||||
|
if (rtc.showOutageMessage())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String code = url.getPath()
|
||||||
|
.replace("/", "")
|
||||||
|
.replace(".ws", "");
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() ->
|
||||||
|
new FatalErrorDialog("OldSchool RuneScape has crashed with the message: " + code + "")
|
||||||
|
.setTitle("OpenOSRS", "OldSchool RuneScape has crashed")
|
||||||
|
.addHelpButtons()
|
||||||
|
.open());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showDocument(URL url, String target)
|
||||||
|
{
|
||||||
|
showDocument(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showStatus(String status)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStream(String key, InputStream stream) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getStream(String key)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<String> getStreamKeys()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public class FatalErrorDialog extends JDialog
|
|||||||
|
|
||||||
private final JPanel rightColumn = new JPanel();
|
private final JPanel rightColumn = new JPanel();
|
||||||
private final Font font = new Font(Font.DIALOG, Font.PLAIN, 12);
|
private final Font font = new Font(Font.DIALOG, Font.PLAIN, 12);
|
||||||
|
private final JLabel title;
|
||||||
|
|
||||||
public FatalErrorDialog(String message)
|
public FatalErrorDialog(String message)
|
||||||
{
|
{
|
||||||
@@ -114,7 +115,7 @@ public class FatalErrorDialog extends JDialog
|
|||||||
leftPane.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
leftPane.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
leftPane.setLayout(new BorderLayout());
|
leftPane.setLayout(new BorderLayout());
|
||||||
|
|
||||||
JLabel title = new JLabel("There was a fatal error starting OpenOSRS");
|
title = new JLabel("There was a fatal error starting OpenOSRS");
|
||||||
title.setForeground(Color.WHITE);
|
title.setForeground(Color.WHITE);
|
||||||
title.setFont(font.deriveFont(16.f));
|
title.setFont(font.deriveFont(16.f));
|
||||||
title.setBorder(new EmptyBorder(10, 10, 10, 10));
|
title.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
@@ -137,13 +138,6 @@ public class FatalErrorDialog extends JDialog
|
|||||||
rightColumn.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
rightColumn.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
rightColumn.setMaximumSize(new Dimension(200, Integer.MAX_VALUE));
|
rightColumn.setMaximumSize(new Dimension(200, Integer.MAX_VALUE));
|
||||||
|
|
||||||
addButton("Open logs folder", () ->
|
|
||||||
{
|
|
||||||
LinkBrowser.open(RuneLite.LOGS_DIR.toString());
|
|
||||||
});
|
|
||||||
addButton("Get help on Discord", () -> LinkBrowser.browse(RuneLiteProperties.getDiscordInvite()));
|
|
||||||
addButton("Troubleshooting steps", () -> LinkBrowser.browse(RuneLiteProperties.getTroubleshootingLink()));
|
|
||||||
|
|
||||||
pane.add(rightColumn, BorderLayout.EAST);
|
pane.add(rightColumn, BorderLayout.EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +187,20 @@ public class FatalErrorDialog extends JDialog
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FatalErrorDialog setTitle(String windowTitle, String header)
|
||||||
|
{
|
||||||
|
super.setTitle(windowTitle);
|
||||||
|
title.setText(header);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FatalErrorDialog addHelpButtons()
|
||||||
|
{
|
||||||
|
return addButton("Open logs folder", () -> LinkBrowser.open(RuneLite.LOGS_DIR.toString()))
|
||||||
|
.addButton("Get help on Discord", () -> LinkBrowser.browse(RuneLiteProperties.getDiscordInvite()))
|
||||||
|
.addButton("Troubleshooting steps", () -> LinkBrowser.browse(RuneLiteProperties.getTroubleshootingLink()));
|
||||||
|
}
|
||||||
|
|
||||||
public FatalErrorDialog addBuildingGuide()
|
public FatalErrorDialog addBuildingGuide()
|
||||||
{
|
{
|
||||||
return addButton("Building guide", () -> LinkBrowser.browse(RuneLiteProperties.getBuildingLink()));
|
return addButton("Building guide", () -> LinkBrowser.browse(RuneLiteProperties.getBuildingLink()));
|
||||||
@@ -205,6 +213,7 @@ public class FatalErrorDialog extends JDialog
|
|||||||
new FatalErrorDialog("OpenOSRS was unable to verify the security of its connection to the internet while " +
|
new FatalErrorDialog("OpenOSRS was unable to verify the security of its connection to the internet while " +
|
||||||
action + ". You may have a misbehaving antivirus, internet service provider, a proxy, or an incomplete" +
|
action + ". You may have a misbehaving antivirus, internet service provider, a proxy, or an incomplete" +
|
||||||
" java installation.")
|
" java installation.")
|
||||||
|
.addHelpButtons()
|
||||||
.open();
|
.open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -213,6 +222,7 @@ public class FatalErrorDialog extends JDialog
|
|||||||
{
|
{
|
||||||
new FatalErrorDialog("OpenOSRS is unable to connect to a required server while " + action + ". " +
|
new FatalErrorDialog("OpenOSRS is unable to connect to a required server while " + action + ". " +
|
||||||
"Please check your internet connection")
|
"Please check your internet connection")
|
||||||
|
.addHelpButtons()
|
||||||
.open();
|
.open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -222,11 +232,14 @@ public class FatalErrorDialog extends JDialog
|
|||||||
new FatalErrorDialog("OpenOSRS is unable to resolve the address of a required server while " + action + ". " +
|
new FatalErrorDialog("OpenOSRS is unable to resolve the address of a required server while " + action + ". " +
|
||||||
"Your DNS resolver may be misconfigured, pointing to an inaccurate resolver, or your internet connection may " +
|
"Your DNS resolver may be misconfigured, pointing to an inaccurate resolver, or your internet connection may " +
|
||||||
"be down. ")
|
"be down. ")
|
||||||
|
.addHelpButtons()
|
||||||
.addButton("Change your DNS resolver", () -> LinkBrowser.browse(RuneLiteProperties.getDNSChangeLink()))
|
.addButton("Change your DNS resolver", () -> LinkBrowser.browse(RuneLiteProperties.getDNSChangeLink()))
|
||||||
.open();
|
.open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new FatalErrorDialog("OpenOSRS encountered a fatal error while " + action + ".").open();
|
new FatalErrorDialog("RuneLite encountered a fatal error while " + action + ".")
|
||||||
|
.addHelpButtons()
|
||||||
|
.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ runelite.api.base=https://api.runelite.net/runelite-@project.version@
|
|||||||
runelite.session=https://session.openosrs.dev
|
runelite.session=https://session.openosrs.dev
|
||||||
runelite.static.base=https://static.runelite.net
|
runelite.static.base=https://static.runelite.net
|
||||||
runelite.ws=https://api.runelite.net/ws
|
runelite.ws=https://api.runelite.net/ws
|
||||||
runelite.config=https://static.runelite.net/config.json
|
runelite.config=https://static.runelite.net/config.json
|
||||||
|
runelite.osrstwitter.link=https://twitter.com/OldSchoolRS
|
||||||
1
runelite-client/src/main/scripts/QuestFilter.hash
Normal file
1
runelite-client/src/main/scripts/QuestFilter.hash
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3FA5FFC8DB18A42971CED41A9BC7CEA407A0EC98061D56B2822F66CD910E4BAF
|
||||||
129
runelite-client/src/main/scripts/QuestFilter.rs2asm
Normal file
129
runelite-client/src/main/scripts/QuestFilter.rs2asm
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
.id 3238
|
||||||
|
.int_stack_count 4
|
||||||
|
.string_stack_count 0
|
||||||
|
.int_var_count 5 ; +1 for filter result
|
||||||
|
.string_var_count 0
|
||||||
|
iconst -1 ; set to 1 to hide, 0 to show
|
||||||
|
iload 0 ; quest struct
|
||||||
|
sconst "questFilter"
|
||||||
|
runelite_callback
|
||||||
|
pop_int ; quest struct
|
||||||
|
istore 4 ; save result
|
||||||
|
; compare with -1
|
||||||
|
iload 4 ; load result
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq continue
|
||||||
|
; return value
|
||||||
|
iload 4
|
||||||
|
return
|
||||||
|
|
||||||
|
continue:
|
||||||
|
iload 0
|
||||||
|
iconst 611
|
||||||
|
struct_param
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL6
|
||||||
|
jump LABEL12
|
||||||
|
LABEL6:
|
||||||
|
invoke 4025
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL10
|
||||||
|
jump LABEL12
|
||||||
|
LABEL10:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL12:
|
||||||
|
iload 0
|
||||||
|
iconst 611
|
||||||
|
struct_param
|
||||||
|
iconst 0
|
||||||
|
if_icmpeq LABEL18
|
||||||
|
jump LABEL24
|
||||||
|
LABEL18:
|
||||||
|
get_varbit 13774
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL22
|
||||||
|
jump LABEL24
|
||||||
|
LABEL22:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL24:
|
||||||
|
iload 1
|
||||||
|
iconst 0
|
||||||
|
if_icmpeq LABEL28
|
||||||
|
jump LABEL34
|
||||||
|
LABEL28:
|
||||||
|
get_varbit 13775
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL32
|
||||||
|
jump LABEL34
|
||||||
|
LABEL32:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL34:
|
||||||
|
iload 1
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL38
|
||||||
|
jump LABEL44
|
||||||
|
LABEL38:
|
||||||
|
get_varbit 13776
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL42
|
||||||
|
jump LABEL44
|
||||||
|
LABEL42:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL44:
|
||||||
|
iload 1
|
||||||
|
iconst 2
|
||||||
|
if_icmpeq LABEL48
|
||||||
|
jump LABEL54
|
||||||
|
LABEL48:
|
||||||
|
get_varbit 13777
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL52
|
||||||
|
jump LABEL54
|
||||||
|
LABEL52:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL54:
|
||||||
|
iload 1
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL58
|
||||||
|
jump LABEL68
|
||||||
|
LABEL58:
|
||||||
|
get_varbit 13778
|
||||||
|
iconst 2
|
||||||
|
if_icmpeq LABEL62
|
||||||
|
jump LABEL68
|
||||||
|
LABEL62:
|
||||||
|
iload 2
|
||||||
|
iconst 0
|
||||||
|
if_icmpeq LABEL66
|
||||||
|
jump LABEL68
|
||||||
|
LABEL66:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL68:
|
||||||
|
iload 1
|
||||||
|
iconst 1
|
||||||
|
if_icmpeq LABEL72
|
||||||
|
jump LABEL82
|
||||||
|
LABEL72:
|
||||||
|
get_varbit 13779
|
||||||
|
iconst 2
|
||||||
|
if_icmpeq LABEL76
|
||||||
|
jump LABEL82
|
||||||
|
LABEL76:
|
||||||
|
iload 3
|
||||||
|
iconst 0
|
||||||
|
if_icmpeq LABEL80
|
||||||
|
jump LABEL82
|
||||||
|
LABEL80:
|
||||||
|
iconst 1
|
||||||
|
return
|
||||||
|
LABEL82:
|
||||||
|
iconst 0
|
||||||
|
return
|
||||||
|
iconst -1
|
||||||
|
return
|
||||||
@@ -165,11 +165,16 @@ public class ChatCommandsPluginTest
|
|||||||
public void testTheatreOfBlood()
|
public void testTheatreOfBlood()
|
||||||
{
|
{
|
||||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
||||||
"Wave 'The Final Challenge' (Normal Mode) complete!<br>Duration: <col=ff0000>2:42.0</col><br>Theatre of Blood wave completion time: <col=ff0000>17:00.20</col> (new personal best)", null, 0);
|
"Wave 'The Final Challenge' (Normal Mode) complete!<br>" +
|
||||||
|
"Duration: <col=ff0000>2:42.0</col><br>" +
|
||||||
|
"Theatre of Blood completion time: <col=ff0000>17:00.20</col> (new personal best)", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Theatre of Blood total completion time: <col=ff0000>24:40.20</col>. Personal best: 20:45.00", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
||||||
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
||||||
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 17 * 60 + .2);
|
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 17 * 60 + .2);
|
||||||
@@ -179,11 +184,16 @@ public class ChatCommandsPluginTest
|
|||||||
public void testTheatreOfBloodNoPb()
|
public void testTheatreOfBloodNoPb()
|
||||||
{
|
{
|
||||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
||||||
"Wave 'The Final Challenge' (Normal Mode) complete!<br>Duration: <col=ff0000>2:42</col><br>Theatre of Blood wave completion time: <col=ff0000>17:00</col>. Personal best: 13:52.80", null, 0);
|
"Wave 'The Final Challenge' (Normal Mode) complete!<br>" +
|
||||||
|
"Duration: <col=ff0000>2:42</col><br>" +
|
||||||
|
"Theatre of Blood completion time: <col=ff0000>17:00</col>. Personal best: 13:52.80", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Theatre of Blood total completion time: <col=ff0000>24:40.20</col>. Personal best: 20:45.00", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
||||||
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
||||||
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 13 * 60 + 52.8);
|
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 13 * 60 + 52.8);
|
||||||
@@ -193,11 +203,16 @@ public class ChatCommandsPluginTest
|
|||||||
public void testTheatreOfBloodEntryMode()
|
public void testTheatreOfBloodEntryMode()
|
||||||
{
|
{
|
||||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
|
||||||
"Wave 'The Final Challenge' (Entry Mode) complete!<br>Duration: <col=ff0000>2:42</col><br>Theatre of Blood wave completion time: <col=ff0000>17:00</col> (new personal best)", null, 0);
|
"Wave 'The Final Challenge' (Entry Mode) complete!<br>" +
|
||||||
|
"Duration: <col=ff0000>2:42</col><br>" +
|
||||||
|
"Theatre of Blood completion time: <col=ff0000>17:00</col> (new personal best)", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood: Entry Mode count is: <col=ff0000>73</col>.", null, 0);
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Theatre of Blood total completion time: <col=ff0000>24:40.20</col>. Personal best: 20:45.00", null, 0);
|
||||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
|
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood: Entry Mode count is: <col=ff0000>73</col>.", null, 0);
|
||||||
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood entry mode", 73);
|
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood entry mode", 73);
|
||||||
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood entry mode", 17 * 60.);
|
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood entry mode", 17 * 60.);
|
||||||
@@ -1074,4 +1089,13 @@ public class ChatCommandsPluginTest
|
|||||||
verify(configManager).setRSProfileConfiguration("personalbest", "tempoross", 234.0);
|
verify(configManager).setRSProfileConfiguration("personalbest", "tempoross", 234.0);
|
||||||
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 1360.0); // the lowest time
|
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 1360.0); // the lowest time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGuardiansOfTheRift()
|
||||||
|
{
|
||||||
|
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Amount of Rifts you have closed: <col=ff0000>7</col>.", null, 0);
|
||||||
|
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||||
|
|
||||||
|
verify(configManager).setRSProfileConfiguration("killcount", "guardians of the rift", 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class FarmingTrackerTest
|
|||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testEmptyNotification()
|
public void testEmptyNotification()
|
||||||
{
|
{
|
||||||
RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null);
|
RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, -1, null);
|
||||||
|
|
||||||
PatchPrediction patchPrediction = new PatchPrediction(Produce.EMPTY_COMPOST_BIN, CropState.EMPTY, 0L, 0, 0);
|
PatchPrediction patchPrediction = new PatchPrediction(Produce.EMPTY_COMPOST_BIN, CropState.EMPTY, 0L, 0, 0);
|
||||||
FarmingRegion region = new FarmingRegion("Ardougne", 10548, false,
|
FarmingRegion region = new FarmingRegion("Ardougne", 10548, false,
|
||||||
@@ -113,7 +113,7 @@ public class FarmingTrackerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testHarvestableNotification()
|
public void testHarvestableNotification()
|
||||||
{
|
{
|
||||||
RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, null);
|
RuneScapeProfile runeScapeProfile = new RuneScapeProfile("Adam", RuneScapeProfileType.STANDARD, null, -1, null);
|
||||||
|
|
||||||
PatchPrediction patchPrediction = new PatchPrediction(Produce.RANARR, CropState.HARVESTABLE, 0L, 0, 0);
|
PatchPrediction patchPrediction = new PatchPrediction(Produce.RANARR, CropState.HARVESTABLE, 0L, 0, 0);
|
||||||
FarmingRegion region = new FarmingRegion("Ardougne", 10548, false,
|
FarmingRegion region = new FarmingRegion("Ardougne", 10548, false,
|
||||||
|
|||||||
Reference in New Issue
Block a user