Merge pull request #12834 from abextm/rsprofile-external
Per RuneScape-Profile configuration
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package net.runelite.http.api.config;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonParseException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -48,6 +49,7 @@ import okhttp3.Response;
|
||||
public class ConfigClient
|
||||
{
|
||||
private static final MediaType TEXT_PLAIN = MediaType.parse("text/plain");
|
||||
private static final Gson GSON = RuneLiteAPI.GSON;
|
||||
|
||||
private final OkHttpClient client;
|
||||
private final UUID uuid;
|
||||
@@ -114,6 +116,59 @@ public class ConfigClient
|
||||
return future;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> patch(Configuration configuration)
|
||||
{
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
|
||||
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
|
||||
.addPathSegment("config")
|
||||
.build();
|
||||
|
||||
log.debug("Built URI: {}", url);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.patch(RequestBody.create(RuneLiteAPI.JSON, GSON.toJson(configuration)))
|
||||
.header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString())
|
||||
.url(url)
|
||||
.build();
|
||||
|
||||
client.newCall(request).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
{
|
||||
log.warn("Unable to synchronize configuration item", e);
|
||||
future.completeExceptionally(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response)
|
||||
{
|
||||
if (response.code() != 200)
|
||||
{
|
||||
String body = "bad response";
|
||||
try
|
||||
{
|
||||
body = response.body().string();
|
||||
}
|
||||
catch (IOException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
log.warn("failed to synchronize some of {} configuration values: {}", configuration.getConfig().size(), body);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("Synchronized {} configuration values", configuration.getConfig().size());
|
||||
}
|
||||
response.close();
|
||||
future.complete(null);
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> unset(String key)
|
||||
{
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
|
||||
@@ -24,28 +24,15 @@
|
||||
*/
|
||||
package net.runelite.http.api.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ConfigEntry
|
||||
{
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
public String getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,18 +26,12 @@ package net.runelite.http.api.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Configuration
|
||||
{
|
||||
private List<ConfigEntry> config = new ArrayList<>();
|
||||
|
||||
public Configuration(List<ConfigEntry> config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public List<ConfigEntry> getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.http.service.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
@@ -32,6 +33,7 @@ import net.runelite.http.service.account.AuthFilter;
|
||||
import net.runelite.http.service.account.beans.SessionEntry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -66,6 +68,29 @@ public class ConfigController
|
||||
return configService.get(session.getUser());
|
||||
}
|
||||
|
||||
@PatchMapping
|
||||
public List<String> patch(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestBody Configuration changes
|
||||
) throws IOException
|
||||
{
|
||||
SessionEntry session = authFilter.handle(request, response);
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> failures = configService.patch(session.getUser(), changes);
|
||||
if (failures.size() != 0)
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return failures;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/{key:.+}", method = PUT)
|
||||
public void setKey(
|
||||
HttpServletRequest request,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.http.service.config;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -38,6 +39,7 @@ import static com.mongodb.client.model.Filters.eq;
|
||||
import com.mongodb.client.model.IndexOptions;
|
||||
import com.mongodb.client.model.Indexes;
|
||||
import com.mongodb.client.model.UpdateOptions;
|
||||
import static com.mongodb.client.model.Updates.combine;
|
||||
import static com.mongodb.client.model.Updates.set;
|
||||
import static com.mongodb.client.model.Updates.unset;
|
||||
import java.util.ArrayList;
|
||||
@@ -50,6 +52,7 @@ import net.runelite.http.api.RuneLiteAPI;
|
||||
import net.runelite.http.api.config.ConfigEntry;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -131,31 +134,79 @@ public class ConfigService
|
||||
return new Configuration(config);
|
||||
}
|
||||
|
||||
public List<String> patch(int userID, Configuration config)
|
||||
{
|
||||
List<String> failures = new ArrayList<>();
|
||||
List<Bson> sets = new ArrayList<>(config.getConfig().size());
|
||||
for (ConfigEntry entry : config.getConfig())
|
||||
{
|
||||
Bson s = setForKV(entry.getKey(), entry.getValue());
|
||||
if (s == null)
|
||||
{
|
||||
failures.add(entry.getKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
sets.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (sets.size() > 0)
|
||||
{
|
||||
mongoCollection.updateOne(
|
||||
eq("_userId", userID),
|
||||
combine(sets),
|
||||
upsertUpdateOptions
|
||||
);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Bson setForKV(String key, @Nullable String value)
|
||||
{
|
||||
if (key.startsWith("$") || key.startsWith("_"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] split = key.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String dbKey = split[0] + "." + split[1].replace('.', ':');
|
||||
|
||||
if (Strings.isNullOrEmpty(value))
|
||||
{
|
||||
return unset(dbKey);
|
||||
}
|
||||
|
||||
if (!validateJson(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Object jsonValue = parseJsonString(value);
|
||||
return set(dbKey, jsonValue);
|
||||
}
|
||||
|
||||
public boolean setKey(
|
||||
int userId,
|
||||
String key,
|
||||
@Nullable String value
|
||||
)
|
||||
{
|
||||
if (key.startsWith("$") || key.startsWith("_"))
|
||||
Bson set = setForKV(key, value);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] split = key.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validateJson(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Object jsonValue = parseJsonString(value);
|
||||
mongoCollection.updateOne(eq("_userId", userId),
|
||||
set(split[0] + "." + split[1].replace('.', ':'), jsonValue),
|
||||
set,
|
||||
upsertUpdateOptions);
|
||||
return true;
|
||||
}
|
||||
@@ -165,19 +216,13 @@ public class ConfigService
|
||||
String key
|
||||
)
|
||||
{
|
||||
if (key.startsWith("$") || key.startsWith("_"))
|
||||
Bson set = setForKV(key, null);
|
||||
if (set == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] split = key.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mongoCollection.updateOne(eq("_userId", userId),
|
||||
unset(split[0] + "." + split[1].replace('.', ':')));
|
||||
mongoCollection.updateOne(eq("_userId", userId), set);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.Player;
|
||||
|
||||
@Value
|
||||
public class PlayerChanged
|
||||
{
|
||||
private final Player player;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
|
||||
/**
|
||||
* Posted when the game world the client wants to connect to has changed
|
||||
* This is posted after the world ID and type have updated, but before a new
|
||||
* connection is established
|
||||
*
|
||||
* @see Client#getWorld()
|
||||
* @see Client#getWorldType()
|
||||
*/
|
||||
public class WorldChanged
|
||||
{
|
||||
}
|
||||
@@ -24,9 +24,13 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.hash.Hasher;
|
||||
import com.google.common.hash.Hashing;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
@@ -45,34 +49,50 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.AtomicMoveNotSupportedException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.PlayerChanged;
|
||||
import net.runelite.api.events.UsernameChanged;
|
||||
import net.runelite.api.events.WorldChanged;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ClientShutdown;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.RuneScapeProfileChanged;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.http.api.config.ConfigClient;
|
||||
import net.runelite.http.api.config.ConfigEntry;
|
||||
@@ -83,30 +103,52 @@ import okhttp3.OkHttpClient;
|
||||
@Slf4j
|
||||
public class ConfigManager
|
||||
{
|
||||
public static final String RSPROFILE_GROUP = "rsprofile";
|
||||
|
||||
private static final String RSPROFILE_DISPLAY_NAME = "displayName";
|
||||
private static final String RSPROFILE_TYPE = "type";
|
||||
private static final String RSPROFILE_LOGIN_HASH = "loginHash";
|
||||
private static final String RSPROFILE_LOGIN_SALT = "loginSalt";
|
||||
|
||||
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
|
||||
@VisibleForTesting
|
||||
static final Pattern KEY_SPLITTER = Pattern.compile("([^.]+)\\.(?:(" + RSPROFILE_GROUP + "\\.[^.]+)\\.)?(.*)");
|
||||
private static final int KEY_SPLITTER_GROUP = 1;
|
||||
private static final int KEY_SPLITTER_PROFILE = 2;
|
||||
private static final int KEY_SPLITTER_KEY = 3;
|
||||
|
||||
private final File settingsFileInput;
|
||||
private final EventBus eventBus;
|
||||
private final OkHttpClient okHttpClient;
|
||||
|
||||
private AccountSession session;
|
||||
private ConfigClient client;
|
||||
private ConfigClient configClient;
|
||||
private File propertiesFile;
|
||||
|
||||
@Nullable
|
||||
private final Client client;
|
||||
|
||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||
private final Properties properties = new Properties();
|
||||
private final Map<String, String> pendingChanges = new HashMap<>();
|
||||
|
||||
// null => we need to make a new profile
|
||||
@Nullable
|
||||
private String rsProfileKey;
|
||||
|
||||
@Inject
|
||||
public ConfigManager(
|
||||
@Named("config") File config,
|
||||
ScheduledExecutorService scheduledExecutorService,
|
||||
EventBus eventBus,
|
||||
OkHttpClient okHttpClient)
|
||||
OkHttpClient okHttpClient,
|
||||
@Nullable Client client)
|
||||
{
|
||||
this.settingsFileInput = config;
|
||||
this.eventBus = eventBus;
|
||||
this.okHttpClient = okHttpClient;
|
||||
this.client = client;
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
|
||||
scheduledExecutorService.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS);
|
||||
@@ -120,12 +162,12 @@ public class ConfigManager
|
||||
if (session == null)
|
||||
{
|
||||
this.session = null;
|
||||
this.client = null;
|
||||
this.configClient = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.session = session;
|
||||
this.client = new ConfigClient(okHttpClient, session.getUuid());
|
||||
this.configClient = new ConfigClient(okHttpClient, session.getUuid());
|
||||
}
|
||||
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
@@ -154,7 +196,7 @@ public class ConfigManager
|
||||
|
||||
public void load()
|
||||
{
|
||||
if (client == null)
|
||||
if (configClient == null)
|
||||
{
|
||||
loadFromFile();
|
||||
return;
|
||||
@@ -164,7 +206,7 @@ public class ConfigManager
|
||||
|
||||
try
|
||||
{
|
||||
configuration = client.get();
|
||||
configuration = configClient.get();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
@@ -186,26 +228,30 @@ public class ConfigManager
|
||||
for (ConfigEntry entry : configuration.getConfig())
|
||||
{
|
||||
log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue());
|
||||
final String[] split = entry.getKey().split("\\.", 2);
|
||||
|
||||
if (split.length != 2)
|
||||
Matcher matcher = KEY_SPLITTER.matcher(entry.getKey());
|
||||
if (!matcher.find())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String groupName = split[0];
|
||||
final String key = split[1];
|
||||
final String groupName = matcher.group(KEY_SPLITTER_GROUP);
|
||||
final String profile = matcher.group(KEY_SPLITTER_PROFILE);
|
||||
final String key = matcher.group(KEY_SPLITTER_KEY);
|
||||
final String value = entry.getValue();
|
||||
final String oldValue = (String) properties.setProperty(entry.getKey(), value);
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setProfile(profile);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
migrateConfig();
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile(propertiesFile);
|
||||
@@ -232,44 +278,47 @@ public class ConfigManager
|
||||
}
|
||||
|
||||
final Map<String, String> copy = (Map) ImmutableMap.copyOf(this.properties);
|
||||
copy.forEach((groupAndKey, value) ->
|
||||
copy.forEach((wholeKey, value) ->
|
||||
{
|
||||
if (!properties.containsKey(groupAndKey))
|
||||
if (!properties.containsKey(wholeKey))
|
||||
{
|
||||
final String[] split = groupAndKey.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
Matcher matcher = KEY_SPLITTER.matcher(wholeKey);
|
||||
if (!matcher.find())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final String groupName = split[0];
|
||||
final String key = split[1];
|
||||
unsetConfiguration(groupName, key);
|
||||
String groupName = matcher.group(KEY_SPLITTER_GROUP);
|
||||
String profile = matcher.group(KEY_SPLITTER_PROFILE);
|
||||
String key = matcher.group(KEY_SPLITTER_KEY);
|
||||
unsetConfiguration(groupName, profile, key);
|
||||
}
|
||||
});
|
||||
|
||||
properties.forEach((objGroupAndKey, objValue) ->
|
||||
properties.forEach((wholeKey, objValue) ->
|
||||
{
|
||||
final String groupAndKey = String.valueOf(objGroupAndKey);
|
||||
final String[] split = groupAndKey.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
Matcher matcher = KEY_SPLITTER.matcher((String) wholeKey);
|
||||
if (!matcher.find())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final String groupName = split[0];
|
||||
final String key = split[1];
|
||||
final String value = String.valueOf(objValue);
|
||||
setConfiguration(groupName, key, value);
|
||||
String groupName = matcher.group(KEY_SPLITTER_GROUP);
|
||||
String profile = matcher.group(KEY_SPLITTER_PROFILE);
|
||||
String key = matcher.group(KEY_SPLITTER_KEY);
|
||||
String value = String.valueOf(objValue);
|
||||
setConfiguration(groupName, profile, key, value);
|
||||
});
|
||||
|
||||
migrateConfig();
|
||||
}
|
||||
|
||||
public void importLocal()
|
||||
public Future<Void> importLocal()
|
||||
{
|
||||
if (session == null)
|
||||
{
|
||||
// No session, no import
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
final File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date()));
|
||||
@@ -281,10 +330,12 @@ public class ConfigManager
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("Backup failed, skipping import", e);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
syncPropertiesFromFile(getLocalPropertiesFile());
|
||||
|
||||
return sendConfig();
|
||||
}
|
||||
|
||||
private synchronized void loadFromFile()
|
||||
@@ -308,21 +359,23 @@ public class ConfigManager
|
||||
try
|
||||
{
|
||||
Map<String, String> copy = (Map) ImmutableMap.copyOf(properties);
|
||||
copy.forEach((groupAndKey, value) ->
|
||||
copy.forEach((wholeKey, value) ->
|
||||
{
|
||||
final String[] split = groupAndKey.split("\\.", 2);
|
||||
if (split.length != 2)
|
||||
Matcher matcher = KEY_SPLITTER.matcher(wholeKey);
|
||||
if (!matcher.find())
|
||||
{
|
||||
log.debug("Properties key malformed!: {}", groupAndKey);
|
||||
properties.remove(groupAndKey);
|
||||
log.debug("Properties key malformed!: {}", wholeKey);
|
||||
properties.remove(wholeKey);
|
||||
return;
|
||||
}
|
||||
|
||||
final String groupName = split[0];
|
||||
final String key = split[1];
|
||||
String groupName = matcher.group(KEY_SPLITTER_GROUP);
|
||||
String profile = matcher.group(KEY_SPLITTER_PROFILE);
|
||||
String key = matcher.group(KEY_SPLITTER_KEY);
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setProfile(profile);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(null);
|
||||
configChanged.setNewValue(value);
|
||||
@@ -333,6 +386,8 @@ public class ConfigManager
|
||||
{
|
||||
log.warn("Error posting config events", ex);
|
||||
}
|
||||
|
||||
migrateConfig();
|
||||
}
|
||||
|
||||
private void saveToFile(final File propertiesFile) throws IOException
|
||||
@@ -381,14 +436,58 @@ public class ConfigManager
|
||||
return properties.keySet().stream().filter(v -> ((String) v).startsWith(prefix)).map(String.class::cast).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static String getWholeKey(String groupName, String profile, String key)
|
||||
{
|
||||
if (profile == null)
|
||||
{
|
||||
return groupName + "." + key;
|
||||
}
|
||||
else
|
||||
{
|
||||
return groupName + "." + profile + "." + key;
|
||||
}
|
||||
}
|
||||
|
||||
public String getConfiguration(String groupName, String key)
|
||||
{
|
||||
return properties.getProperty(groupName + "." + key);
|
||||
return getConfiguration(groupName, null, key);
|
||||
}
|
||||
|
||||
public String getRSProfileConfiguration(String groupName, String key)
|
||||
{
|
||||
String rsProfileKey = this.rsProfileKey;
|
||||
if (rsProfileKey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getConfiguration(groupName, rsProfileKey, key);
|
||||
}
|
||||
|
||||
public String getConfiguration(String groupName, String profile, String key)
|
||||
{
|
||||
return properties.getProperty(getWholeKey(groupName, profile, key));
|
||||
}
|
||||
|
||||
public <T> T getConfiguration(String groupName, String key, Class<T> clazz)
|
||||
{
|
||||
String value = getConfiguration(groupName, key);
|
||||
return getConfiguration(groupName, null, key, clazz);
|
||||
}
|
||||
|
||||
public <T> T getRSProfileConfiguration(String groupName, String key, Class<T> clazz)
|
||||
{
|
||||
String rsProfileKey = this.rsProfileKey;
|
||||
if (rsProfileKey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getConfiguration(groupName, rsProfileKey, key, clazz);
|
||||
}
|
||||
|
||||
public <T> T getConfiguration(String groupName, String profile, String key, Class<T> clazz)
|
||||
{
|
||||
String value = getConfiguration(groupName, profile, key);
|
||||
if (!Strings.isNullOrEmpty(value))
|
||||
{
|
||||
try
|
||||
@@ -397,7 +496,7 @@ public class ConfigManager
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unable to unmarshal {}.{} ", groupName, key, e);
|
||||
log.warn("Unable to unmarshal {} ", getWholeKey(groupName, profile, key), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -405,23 +504,31 @@ public class ConfigManager
|
||||
|
||||
public void setConfiguration(String groupName, String key, String value)
|
||||
{
|
||||
String oldValue = (String) properties.setProperty(groupName + "." + key, value);
|
||||
setConfiguration(groupName, null, key, value);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String profile, String key, String value)
|
||||
{
|
||||
assert !key.startsWith(RSPROFILE_GROUP + ".");
|
||||
String wholeKey = getWholeKey(groupName, profile, key);
|
||||
String oldValue = (String) properties.setProperty(wholeKey, value);
|
||||
|
||||
if (Objects.equals(oldValue, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
||||
log.debug("Setting configuration value for {} to {}", wholeKey, value);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
pendingChanges.put(groupName + "." + key, value);
|
||||
pendingChanges.put(wholeKey, value);
|
||||
}
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setProfile(profile);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
@@ -429,26 +536,74 @@ public class ConfigManager
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String profile, String key, Object value)
|
||||
{
|
||||
setConfiguration(groupName, profile, key, objectToString(value));
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String key, Object value)
|
||||
{
|
||||
setConfiguration(groupName, key, objectToString(value));
|
||||
setConfiguration(groupName, null, key, value);
|
||||
}
|
||||
|
||||
public void setRSProfileConfiguration(String groupName, String key, Object value)
|
||||
{
|
||||
String rsProfileKey = this.rsProfileKey;
|
||||
if (rsProfileKey == null)
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
log.warn("trying to use profile without injected client");
|
||||
return;
|
||||
}
|
||||
|
||||
String displayName = null;
|
||||
Player p = client.getLocalPlayer();
|
||||
if (p == null)
|
||||
{
|
||||
log.warn("trying to create profile without display name");
|
||||
}
|
||||
else
|
||||
{
|
||||
displayName = p.getName();
|
||||
}
|
||||
|
||||
String username = client.getUsername();
|
||||
if (Strings.isNullOrEmpty(username))
|
||||
{
|
||||
log.warn("trying to create profile without a set username");
|
||||
return;
|
||||
}
|
||||
|
||||
RuneScapeProfile prof = findRSProfile(getRSProfiles(), username, RuneScapeProfileType.getCurrent(client), displayName, true);
|
||||
rsProfileKey = prof.getKey();
|
||||
this.rsProfileKey = rsProfileKey;
|
||||
}
|
||||
setConfiguration(groupName, rsProfileKey, key, value);
|
||||
}
|
||||
|
||||
public void unsetConfiguration(String groupName, String key)
|
||||
{
|
||||
String oldValue = (String) properties.remove(groupName + "." + key);
|
||||
unsetConfiguration(groupName, null, key);
|
||||
}
|
||||
|
||||
public void unsetConfiguration(String groupName, String profile, String key)
|
||||
{
|
||||
assert !key.startsWith(RSPROFILE_GROUP + ".");
|
||||
String wholeKey = getWholeKey(groupName, profile, key);
|
||||
String oldValue = (String) properties.remove(wholeKey);
|
||||
|
||||
if (oldValue == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Unsetting configuration value for {}.{}", groupName, key);
|
||||
log.debug("Unsetting configuration value for {}", wholeKey);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
pendingChanges.put(groupName + "." + key, null);
|
||||
pendingChanges.put(wholeKey, null);
|
||||
}
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
@@ -459,6 +614,17 @@ public class ConfigManager
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
public void unsetRSProfileConfiguration(String groupName, String key)
|
||||
{
|
||||
String rsProfileKey = this.rsProfileKey;
|
||||
if (rsProfileKey == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsetConfiguration(groupName, rsProfileKey, key);
|
||||
}
|
||||
|
||||
public ConfigDescriptor getConfigDescriptor(Config configurationProxy)
|
||||
{
|
||||
Class<?> inter = configurationProxy.getClass().getInterfaces()[0];
|
||||
@@ -656,6 +822,10 @@ public class ConfigManager
|
||||
{
|
||||
return Duration.ofMillis(Long.parseLong(str));
|
||||
}
|
||||
if (type == byte[].class)
|
||||
{
|
||||
return Base64.getUrlDecoder().decode(str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -703,6 +873,10 @@ public class ConfigManager
|
||||
{
|
||||
return Long.toString(((Duration) object).toMillis());
|
||||
}
|
||||
if (object instanceof byte[])
|
||||
{
|
||||
return Base64.getUrlEncoder().encodeToString((byte[]) object);
|
||||
}
|
||||
return object == null ? null : object.toString();
|
||||
}
|
||||
|
||||
@@ -720,42 +894,280 @@ public class ConfigManager
|
||||
private CompletableFuture<Void> sendConfig()
|
||||
{
|
||||
CompletableFuture<Void> future = null;
|
||||
boolean changed;
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
if (client != null)
|
||||
if (pendingChanges.isEmpty())
|
||||
{
|
||||
future = CompletableFuture.allOf(pendingChanges.entrySet().stream().map(entry ->
|
||||
{
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
||||
if (Strings.isNullOrEmpty(value))
|
||||
{
|
||||
return client.unset(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
return client.set(key, value);
|
||||
}
|
||||
}).toArray(CompletableFuture[]::new));
|
||||
return null;
|
||||
}
|
||||
changed = !pendingChanges.isEmpty();
|
||||
|
||||
if (configClient != null)
|
||||
{
|
||||
Configuration patch = new Configuration(pendingChanges.entrySet().stream()
|
||||
.map(e -> new ConfigEntry(e.getKey(), e.getValue()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
future = configClient.patch(patch);
|
||||
}
|
||||
|
||||
pendingChanges.clear();
|
||||
}
|
||||
|
||||
if (changed)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
saveToFile(propertiesFile);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("unable to save configuration file", ex);
|
||||
}
|
||||
saveToFile(propertiesFile);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("unable to save configuration file", ex);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
public List<RuneScapeProfile> getRSProfiles()
|
||||
{
|
||||
String prefix = RSPROFILE_GROUP + "." + RSPROFILE_GROUP + ".";
|
||||
Set<String> profileKeys = new HashSet<>();
|
||||
for (Object oKey : properties.keySet())
|
||||
{
|
||||
String key = (String) oKey;
|
||||
if (!key.startsWith(prefix))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher m = KEY_SPLITTER.matcher(key);
|
||||
if (!m.find())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profileKeys.add(m.group(KEY_SPLITTER_PROFILE));
|
||||
}
|
||||
|
||||
return profileKeys.stream()
|
||||
.map(key ->
|
||||
{
|
||||
RuneScapeProfile prof = new RuneScapeProfile(
|
||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_DISPLAY_NAME),
|
||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_TYPE, RuneScapeProfileType.class),
|
||||
getConfiguration(RSPROFILE_GROUP, key, RSPROFILE_LOGIN_HASH, byte[].class),
|
||||
key
|
||||
);
|
||||
|
||||
return prof;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private synchronized RuneScapeProfile findRSProfile(List<RuneScapeProfile> profiles, String username, RuneScapeProfileType type, String displayName, boolean create)
|
||||
{
|
||||
byte[] salt = getConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, byte[].class);
|
||||
if (salt == null)
|
||||
{
|
||||
salt = new byte[15];
|
||||
new SecureRandom()
|
||||
.nextBytes(salt);
|
||||
setConfiguration(RSPROFILE_GROUP, RSPROFILE_LOGIN_SALT, salt);
|
||||
}
|
||||
|
||||
Hasher h = Hashing.sha512().newHasher();
|
||||
h.putBytes(salt);
|
||||
h.putString(username.toLowerCase(Locale.US), StandardCharsets.UTF_8);
|
||||
byte[] loginHash = h.hash().asBytes();
|
||||
|
||||
Set<RuneScapeProfile> matches = profiles.stream()
|
||||
.filter(p -> Arrays.equals(p.getLoginHash(), loginHash) && p.getType() == type)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (matches.size() > 1)
|
||||
{
|
||||
log.warn("multiple matching profiles");
|
||||
}
|
||||
|
||||
if (matches.size() >= 1)
|
||||
{
|
||||
return matches.iterator().next();
|
||||
}
|
||||
|
||||
if (!create)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 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());
|
||||
byte[] key = Arrays.copyOf(loginHash, 6);
|
||||
key[0] += type.ordinal();
|
||||
for (int i = 0; i < 0xFF; i++, key[1]++)
|
||||
{
|
||||
String keyStr = RSPROFILE_GROUP + "." + Base64.getUrlEncoder().encodeToString(key);
|
||||
if (!keys.contains(keyStr))
|
||||
{
|
||||
log.info("creating new profile {} for user {}", key, username);
|
||||
|
||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_LOGIN_HASH, loginHash);
|
||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_TYPE, type);
|
||||
if (displayName != null)
|
||||
{
|
||||
setConfiguration(RSPROFILE_GROUP, keyStr, RSPROFILE_DISPLAY_NAME, displayName);
|
||||
}
|
||||
return new RuneScapeProfile(displayName, type, loginHash, keyStr);
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("too many rs profiles");
|
||||
}
|
||||
|
||||
private void updateRSProfile()
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<RuneScapeProfile> profiles = getRSProfiles();
|
||||
RuneScapeProfile prof = findRSProfile(profiles, client.getUsername(), RuneScapeProfileType.getCurrent(client), null, false);
|
||||
|
||||
String key = prof == null ? null : prof.getKey();
|
||||
if (Objects.equals(key, rsProfileKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
rsProfileKey = key;
|
||||
|
||||
eventBus.post(new RuneScapeProfileChanged());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onUsernameChanged(UsernameChanged ev)
|
||||
{
|
||||
updateRSProfile();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onWorldChanged(WorldChanged ev)
|
||||
{
|
||||
updateRSProfile();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onPlayerChanged(PlayerChanged ev)
|
||||
{
|
||||
if (ev.getPlayer() == client.getLocalPlayer())
|
||||
{
|
||||
String name = ev.getPlayer().getName();
|
||||
setRSProfileConfiguration(RSPROFILE_GROUP, RSPROFILE_DISPLAY_NAME, name);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void migrateConfig()
|
||||
{
|
||||
String migrationKey = "profileMigrationDone";
|
||||
if (getConfiguration("runelite", migrationKey) != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> profiles = new HashMap<>();
|
||||
|
||||
AtomicInteger changes = new AtomicInteger();
|
||||
List<Predicate<String>> migrators = new ArrayList<>();
|
||||
for (String[] tpl : new String[][]
|
||||
{
|
||||
{"(grandexchange)\\.buylimit_(%)\\.(#)", "$1.buylimit.$3"},
|
||||
{"(timetracking)\\.(%)\\.(autoweed|contract)", "$1.$3"},
|
||||
{"(timetracking)\\.(%)\\.(#\\.#)", "$1.$3"},
|
||||
{"(timetracking)\\.(%)\\.(birdhouse)\\.(#)", "$1.$3.$4"},
|
||||
{"(killcount|personalbest)\\.(%)\\.([^.]+)", "$1.$3"},
|
||||
{"(geoffer)\\.(%)\\.(#)", "$1.$3"},
|
||||
})
|
||||
{
|
||||
String replace = tpl[1];
|
||||
String pat = ("^" + tpl[0] + "$")
|
||||
.replace("#", "-?[0-9]+")
|
||||
.replace("(%)", "(?<login>.*)");
|
||||
Pattern p = Pattern.compile(pat);
|
||||
|
||||
migrators.add(oldkey ->
|
||||
{
|
||||
Matcher m = p.matcher(oldkey);
|
||||
if (!m.find())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String newKey = m.replaceFirst(replace);
|
||||
String username = m.group("login").toLowerCase(Locale.US);
|
||||
|
||||
if (username.startsWith(RSPROFILE_GROUP + "."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String profKey = profiles.computeIfAbsent(username, u ->
|
||||
findRSProfile(getRSProfiles(), u, RuneScapeProfileType.STANDARD, u, true).getKey());
|
||||
|
||||
Matcher oldKeyM = KEY_SPLITTER.matcher(oldkey);
|
||||
if (!oldKeyM.find())
|
||||
{
|
||||
log.warn("skipping migration of invalid key \"{}\"", oldkey);
|
||||
return false;
|
||||
}
|
||||
if (oldKeyM.group(KEY_SPLITTER_PROFILE) != null)
|
||||
{
|
||||
log.debug("skipping migrated key \"{}\"", oldkey);
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher newKeyM = KEY_SPLITTER.matcher(newKey);
|
||||
if (!newKeyM.find() || newKeyM.group(KEY_SPLITTER_PROFILE) != null)
|
||||
{
|
||||
log.warn("migration produced a bad key: \"{}\" -> \"{}\"", oldkey, newKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (changes.getAndAdd(1) <= 0)
|
||||
{
|
||||
File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date()));
|
||||
log.info("backing up pre-migration config to {}", file);
|
||||
try
|
||||
{
|
||||
saveToFile(file);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.error("Backup failed", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String oldGroup = oldKeyM.group(KEY_SPLITTER_GROUP);
|
||||
String oldKeyPart = oldKeyM.group(KEY_SPLITTER_KEY);
|
||||
String value = getConfiguration(oldGroup, oldKeyPart);
|
||||
setConfiguration(newKeyM.group(KEY_SPLITTER_GROUP), profKey, newKeyM.group(KEY_SPLITTER_KEY), value);
|
||||
unsetConfiguration(oldGroup, oldKeyPart);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Set<String> keys = (Set<String>) ImmutableSet.copyOf((Set<?>) properties.keySet());
|
||||
keys:
|
||||
for (String key : keys)
|
||||
{
|
||||
for (Predicate<String> mig : migrators)
|
||||
{
|
||||
if (mig.test(key))
|
||||
{
|
||||
continue keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changes.get() > 0)
|
||||
{
|
||||
log.info("migrated {} config keys", changes);
|
||||
}
|
||||
setConfiguration("runelite", migrationKey, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.client.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* A profile/save of a OSRS account. Each account can 1 profile per {@link RuneScapeProfileType}
|
||||
* (ie Standard/League/DMM}.
|
||||
*/
|
||||
@Data
|
||||
public class RuneScapeProfile
|
||||
{
|
||||
private final String displayName;
|
||||
private final RuneScapeProfileType type;
|
||||
private final byte[] loginHash;
|
||||
|
||||
/**
|
||||
* Profile key used to save configs for this profile to the config store. This will
|
||||
* always start with {@link ConfigManager#RSPROFILE_GROUP}
|
||||
*/
|
||||
private final String key;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.client.config;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.WorldType;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum RuneScapeProfileType
|
||||
{
|
||||
STANDARD(client -> true),
|
||||
BETA(client -> client.getWorldType().contains(WorldType.TOURNAMENT)),
|
||||
DEADMAN(client -> client.getWorldType().contains(WorldType.DEADMAN)),
|
||||
TRAILBLAZER_LEAGUE(client -> client.getWorldType().contains(WorldType.LEAGUE)),
|
||||
;
|
||||
|
||||
private final Predicate<Client> test;
|
||||
|
||||
public static RuneScapeProfileType getCurrent(Client client)
|
||||
{
|
||||
RuneScapeProfileType[] types = values();
|
||||
for (int i = types.length - 1; i >= 0; i--)
|
||||
{
|
||||
RuneScapeProfileType type = types[i];
|
||||
if (types[i].test.test(client))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return STANDARD;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Data;
|
||||
import net.runelite.client.config.RuneScapeProfile;
|
||||
|
||||
/**
|
||||
* An event where a configuration entry has been modified.
|
||||
@@ -39,6 +41,14 @@ public class ConfigChanged
|
||||
* between other key values that may have the same name.
|
||||
*/
|
||||
private String group;
|
||||
|
||||
/**
|
||||
* The profile that has changed, if any
|
||||
*
|
||||
* @see RuneScapeProfile#getKey()
|
||||
*/
|
||||
@Nullable
|
||||
private String profile;
|
||||
/**
|
||||
* The configuration key that has been modified.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.client.events;
|
||||
|
||||
/**
|
||||
* Posted when the user switches to a different RuneScape save profile
|
||||
* This might be because they logged into a different account, or hopped
|
||||
* to/from a Beta/Tournament/DMM/Leagues world
|
||||
*/
|
||||
public class RuneScapeProfileChanged
|
||||
{
|
||||
}
|
||||
@@ -230,27 +230,23 @@ public class ChatCommandsPlugin extends Plugin
|
||||
|
||||
private void setKc(String boss, int killcount)
|
||||
{
|
||||
configManager.setConfiguration("killcount." + client.getUsername().toLowerCase(),
|
||||
boss.toLowerCase(), killcount);
|
||||
configManager.setRSProfileConfiguration("killcount", boss.toLowerCase(), killcount);
|
||||
}
|
||||
|
||||
private int getKc(String boss)
|
||||
{
|
||||
Integer killCount = configManager.getConfiguration("killcount." + client.getUsername().toLowerCase(),
|
||||
boss.toLowerCase(), int.class);
|
||||
Integer killCount = configManager.getRSProfileConfiguration("killcount", boss.toLowerCase(), int.class);
|
||||
return killCount == null ? 0 : killCount;
|
||||
}
|
||||
|
||||
private void setPb(String boss, int seconds)
|
||||
{
|
||||
configManager.setConfiguration("personalbest." + client.getUsername().toLowerCase(),
|
||||
boss.toLowerCase(), seconds);
|
||||
configManager.setRSProfileConfiguration("personalbest", boss.toLowerCase(), seconds);
|
||||
}
|
||||
|
||||
private int getPb(String boss)
|
||||
{
|
||||
Integer personalBest = configManager.getConfiguration("personalbest." + client.getUsername().toLowerCase(),
|
||||
boss.toLowerCase(), int.class);
|
||||
Integer personalBest = configManager.getRSProfileConfiguration("personalbest", boss.toLowerCase(), int.class);
|
||||
return personalBest == null ? 0 : personalBest;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
private static final String OSB_GE_TEXT = "<br>OSBuddy Actively traded price: ";
|
||||
|
||||
private static final String BUY_LIMIT_GE_TEXT = "<br>Buy limit: ";
|
||||
private static final String BUY_LIMIT_KEY = "buylimit_";
|
||||
private static final String BUY_LIMIT_KEY = "buylimit";
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final Duration BUY_LIMIT_RESET = Duration.ofHours(4);
|
||||
|
||||
@@ -244,7 +244,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
private SavedOffer getOffer(int slot)
|
||||
{
|
||||
String offer = configManager.getConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot));
|
||||
String offer = configManager.getRSProfileConfiguration("geoffer", Integer.toString(slot));
|
||||
if (offer == null)
|
||||
{
|
||||
return null;
|
||||
@@ -254,12 +254,12 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
private void setOffer(int slot, SavedOffer offer)
|
||||
{
|
||||
configManager.setConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot), GSON.toJson(offer));
|
||||
configManager.setRSProfileConfiguration("geoffer", Integer.toString(slot), GSON.toJson(offer));
|
||||
}
|
||||
|
||||
private void deleteOffer(int slot)
|
||||
{
|
||||
configManager.unsetConfiguration("geoffer." + client.getUsername().toLowerCase(), Integer.toString(slot));
|
||||
configManager.unsetRSProfileConfiguration("geoffer", Integer.toString(slot));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -782,20 +782,19 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
private void setLimitResetTime(int itemId)
|
||||
{
|
||||
Instant lastDateTime = configManager.getConfiguration(GrandExchangeConfig.CONFIG_GROUP,
|
||||
BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId, Instant.class);
|
||||
Instant lastDateTime = configManager.getRSProfileConfiguration(GrandExchangeConfig.CONFIG_GROUP,
|
||||
BUY_LIMIT_KEY + "." + itemId, Instant.class);
|
||||
if (lastDateTime == null || lastDateTime.isBefore(Instant.now()))
|
||||
{
|
||||
configManager.setConfiguration(GrandExchangeConfig.CONFIG_GROUP,
|
||||
BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId,
|
||||
configManager.setRSProfileConfiguration(GrandExchangeConfig.CONFIG_GROUP, BUY_LIMIT_KEY + "." + itemId,
|
||||
Instant.now().plus(BUY_LIMIT_RESET));
|
||||
}
|
||||
}
|
||||
|
||||
private Instant getLimitResetTime(int itemId)
|
||||
{
|
||||
Instant lastDateTime = configManager.getConfiguration(GrandExchangeConfig.CONFIG_GROUP,
|
||||
BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId, Instant.class);
|
||||
Instant lastDateTime = configManager.getRSProfileConfiguration(GrandExchangeConfig.CONFIG_GROUP,
|
||||
BUY_LIMIT_KEY + "." + itemId, Instant.class);
|
||||
if (lastDateTime == null)
|
||||
{
|
||||
return null;
|
||||
@@ -803,7 +802,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
if (lastDateTime.isBefore(Instant.now()))
|
||||
{
|
||||
configManager.unsetConfiguration(GrandExchangeConfig.CONFIG_GROUP, BUY_LIMIT_KEY + client.getUsername().toLowerCase() + "." + itemId);
|
||||
configManager.unsetRSProfileConfiguration(GrandExchangeConfig.CONFIG_GROUP, BUY_LIMIT_KEY + "." + itemId);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,11 +40,11 @@ import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.UsernameChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.RuneScapeProfileChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
@@ -216,7 +216,7 @@ public class TimeTrackingPlugin extends Plugin
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onUsernameChanged(UsernameChanged e)
|
||||
public void onRuneScapeProfileChanged(RuneScapeProfileChanged e)
|
||||
{
|
||||
farmingTracker.loadCompletionTimes();
|
||||
birdHouseTracker.loadFromConfig();
|
||||
|
||||
@@ -331,7 +331,7 @@ public class FarmingContractManager
|
||||
{
|
||||
try
|
||||
{
|
||||
return Produce.getByItemID(Integer.parseInt(configManager.getConfiguration(getConfigGroup(), CONFIG_KEY_CONTRACT)));
|
||||
return Produce.getByItemID(Integer.parseInt(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, CONFIG_KEY_CONTRACT)));
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
@@ -343,17 +343,11 @@ public class FarmingContractManager
|
||||
{
|
||||
if (contract != null)
|
||||
{
|
||||
configManager.setConfiguration(getConfigGroup(), CONFIG_KEY_CONTRACT, String.valueOf(contract.getItemID()));
|
||||
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, CONFIG_KEY_CONTRACT, String.valueOf(contract.getItemID()));
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager.unsetConfiguration(getConfigGroup(), CONFIG_KEY_CONTRACT);
|
||||
configManager.unsetRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, CONFIG_KEY_CONTRACT);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private String getConfigGroup()
|
||||
{
|
||||
return TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,11 +83,10 @@ public class FarmingTracker
|
||||
boolean changed = false;
|
||||
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
||||
if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)))
|
||||
if (!autoweed.equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED)))
|
||||
{
|
||||
configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed);
|
||||
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED, autoweed);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -100,16 +99,15 @@ public class FarmingTracker
|
||||
}
|
||||
|
||||
// Write config with new varbits
|
||||
// timetracking.<login-username>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + region.getRegionID();
|
||||
// timetracking.<rsprofile>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
for (FarmingPatch patch : region.getPatches())
|
||||
{
|
||||
// Write the config value if it doesn't match what is current, or it is more than 5 minutes old
|
||||
Varbits varbit = patch.getVarbit();
|
||||
String key = Integer.toString(varbit.getId());
|
||||
String key = region.getRegionID() + "." + varbit.getId();
|
||||
String strVarbit = Integer.toString(client.getVar(varbit));
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key);
|
||||
|
||||
if (storedValue != null)
|
||||
{
|
||||
@@ -133,7 +131,7 @@ public class FarmingTracker
|
||||
}
|
||||
|
||||
String value = strVarbit + ":" + unixNow;
|
||||
configManager.setConfiguration(group, key, value);
|
||||
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key, value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -151,16 +149,11 @@ public class FarmingTracker
|
||||
{
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
|
||||
boolean autoweed;
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
autoweed = Integer.toString(Autoweed.ON.ordinal())
|
||||
.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED));
|
||||
}
|
||||
boolean autoweed = Integer.toString(Autoweed.ON.ordinal())
|
||||
.equals(configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, TimeTrackingConfig.AUTOWEED));
|
||||
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + patch.getRegion().getRegionID();
|
||||
String key = Integer.toString(patch.getVarbit().getId());
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
String key = patch.getRegion().getRegionID() + "." + patch.getVarbit().getId();
|
||||
String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key);
|
||||
|
||||
if (storedValue == null)
|
||||
{
|
||||
|
||||
@@ -91,12 +91,10 @@ public class BirdHouseTracker
|
||||
{
|
||||
birdHouseData.clear();
|
||||
|
||||
final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE;
|
||||
|
||||
for (BirdHouseSpace space : BirdHouseSpace.values())
|
||||
{
|
||||
String key = Integer.toString(space.getVarp().getId());
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
String key = TimeTrackingConfig.BIRD_HOUSE + "." + space.getVarp().getId();
|
||||
String storedValue = configManager.getRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key);
|
||||
|
||||
if (storedValue != null)
|
||||
{
|
||||
@@ -242,12 +240,10 @@ public class BirdHouseTracker
|
||||
|
||||
private void saveToConfig(Map<BirdHouseSpace, BirdHouseData> updatedData)
|
||||
{
|
||||
final String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + TimeTrackingConfig.BIRD_HOUSE;
|
||||
|
||||
for (BirdHouseData data : updatedData.values())
|
||||
{
|
||||
String key = Integer.toString(data.getSpace().getVarp().getId());
|
||||
configManager.setConfiguration(group, key, data.getVarp() + ":" + data.getTimestamp());
|
||||
String key = TimeTrackingConfig.BIRD_HOUSE + "." + data.getSpace().getVarp().getId();
|
||||
configManager.setRSProfileConfiguration(TimeTrackingConfig.CONFIG_GROUP, key, data.getVarp() + ":" + data.getTimestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,10 @@ import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.regex.Matcher;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
@@ -67,6 +69,10 @@ public class ConfigManagerTest
|
||||
@Named("config")
|
||||
File config = RuneLite.DEFAULT_CONFIG_FILE;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
Client client;
|
||||
|
||||
@Inject
|
||||
ConfigManager manager;
|
||||
|
||||
@@ -132,4 +138,26 @@ public class ConfigManagerTest
|
||||
manager.setDefaultConfiguration(conf, false);
|
||||
Assert.assertNull(conf.nullDefaultKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeySplitter()
|
||||
{
|
||||
for (String[] test : new String[][]
|
||||
{
|
||||
{"rsprofile", "rsprofile.123", "rsprofileThing"},
|
||||
{"rsprofile", null, "rsprofileThing"},
|
||||
{"foo", "rsprofile.123", "big.bad"},
|
||||
{"foo", null, "big.bad"},
|
||||
{"foo", "rsprofile.123", "456"},
|
||||
{"foo", null, "file.256"},
|
||||
})
|
||||
{
|
||||
String whole = ConfigManager.getWholeKey(test[0], test[1], test[2]);
|
||||
Matcher m = ConfigManager.KEY_SPLITTER.matcher(whole);
|
||||
Assert.assertTrue(m.find());
|
||||
Assert.assertEquals(m.group(1), test[0]);
|
||||
Assert.assertEquals(m.group(2), test[1]);
|
||||
Assert.assertEquals(m.group(3), test[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +124,6 @@ public class ChatCommandsPluginTest
|
||||
Player player = mock(Player.class);
|
||||
when(player.getName()).thenReturn(PLAYER_NAME);
|
||||
when(client.getLocalPlayer()).thenReturn(player);
|
||||
|
||||
when(client.getUsername()).thenReturn(PLAYER_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -151,7 +149,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Corporeal Beast kill count is: <col=ff0000>4</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "corporeal beast", 4);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "corporeal beast", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,8 +161,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "theatre of blood", 73);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "theatre of blood", 37 * 60 + 4);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -176,14 +174,14 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "theatre of blood", 73);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "theatre of blood", 37 * 60 + 4);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 37 * 60 + 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTheatreOfBloodNoPB()
|
||||
{
|
||||
when(configManager.getConfiguration("personalbest.adam", "theatre of blood", int.class)).thenReturn(37 * 60 + 4); // 37:04
|
||||
when(configManager.getRSProfileConfiguration("personalbest", "theatre of blood", int.class)).thenReturn(37 * 60 + 4); // 37:04
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Wave 'The Final Challenge' complete! Duration: <col=ff0000>5:04</col><br>Theatre of Blood wave completion time: <col=ff0000>38:17</col><br></col>Personal best: 37:10", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
@@ -191,8 +189,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Theatre of Blood count is: <col=ff0000>73</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "theatre of blood", 73);
|
||||
verify(configManager, never()).setConfiguration(eq("personalbest.adam"), eq("theatre of blood"), anyInt());
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
|
||||
verify(configManager, never()).setRSProfileConfiguration(eq("personalbest"), eq("theatre of blood"), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -201,7 +199,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your subdued Wintertodt count is: <col=ff0000>4</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "wintertodt", 4);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "wintertodt", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -210,7 +208,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Kree'arra kill count is: <col=ff0000>4</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "kree'arra", 4);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "kree'arra", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -219,7 +217,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your Barrows chest count is: <col=ff0000>277</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "barrows chests", 277);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "barrows chests", 277);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,7 +226,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "", "Your herbiboar harvest count is: <col=ff0000>4091</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "herbiboar", 4091);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "herbiboar", 4091);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,7 +235,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage gauntletMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>123</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(gauntletMessage);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "gauntlet", 123);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "gauntlet", 123);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -246,7 +244,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage corruptedGauntletMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Corrupted Gauntlet completion count is: <col=ff0000>4729</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(corruptedGauntletMessage);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "corrupted gauntlet", 4729);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "corrupted gauntlet", 4729);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -261,7 +259,7 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("kree'arra"), eq(79));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("kree'arra"), eq(79));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,7 +274,7 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", FIGHT_DURATION, null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("zulrah"), eq(55));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("zulrah"), eq(55));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -291,7 +289,7 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("kree'arra"), eq(181));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("kree'arra"), eq(181));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -300,8 +298,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You won! You have now won 27 duels.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "duel arena wins", 27);
|
||||
verify(configManager).setConfiguration("killcount.adam", "duel arena win streak", 1);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "duel arena wins", 27);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "duel arena win streak", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -310,7 +308,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You were defeated! You have won 22 duels.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "duel arena wins", 22);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "duel arena wins", 22);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -319,7 +317,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessageEvent = new ChatMessage(null, TRADE, "", "You have now lost 999 duels.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessageEvent);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "duel arena losses", 999);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "duel arena losses", 999);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -334,8 +332,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", NEW_PB, null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("prifddinas agility course"), eq(61));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("prifddinas agility course"), eq(2));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("prifddinas agility course"), eq(61));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("prifddinas agility course"), eq(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -347,8 +345,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>104:31</col> (new personal best)", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tzkal-zuk"), eq(104 * 60 + 31));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("tzkal-zuk"), eq(2));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("tzkal-zuk"), eq(104 * 60 + 31));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("tzkal-zuk"), eq(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -360,8 +358,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Duration: <col=ff0000>172:18</col>. Personal best: 134:52", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tzkal-zuk"), eq(134 * 60 + 52));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("tzkal-zuk"), eq(3));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("tzkal-zuk"), eq(134 * 60 + 52));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("tzkal-zuk"), eq(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -373,8 +371,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>179</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("grotesque guardians"), eq(96));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("grotesque guardians"), eq(179));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("grotesque guardians"), eq(96));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("grotesque guardians"), eq(179));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -386,8 +384,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Grotesque Guardians kill count is: <col=ff0000>32</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("grotesque guardians"), eq(2 * 60 + 14));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("grotesque guardians"), eq(32));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("grotesque guardians"), eq(2 * 60 + 14));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("grotesque guardians"), eq(32));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -399,8 +397,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>124</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("gauntlet"), eq(124));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("gauntlet"), eq(7 * 60 + 59));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("gauntlet"), eq(124));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("gauntlet"), eq(7 * 60 + 59));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -412,8 +410,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Gauntlet completion count is: <col=ff0000>124</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("gauntlet"), eq(10 * 60 + 24));
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("gauntlet"), eq(124));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("gauntlet"), eq(10 * 60 + 24));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("gauntlet"), eq(124));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -425,14 +423,14 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: <col=ff0000>51</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("chambers of xeric"), eq(51));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), eq(37 * 60 + 4));
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("chambers of xeric"), eq(51));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric"), eq(37 * 60 + 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCoXKillUnknownPb()
|
||||
{
|
||||
when(configManager.getConfiguration("personalbest.adam", "chambers of xeric", int.class)).thenReturn(25 * 60 + 14);
|
||||
when(configManager.getRSProfileConfiguration("personalbest", "chambers of xeric", int.class)).thenReturn(25 * 60 + 14);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>11-15 players</col> Duration:</col> <col=ff0000>23:25</col> Personal best: </col><col=ff0000>20:19</col>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
@@ -440,14 +438,14 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: <col=ff0000>52</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "chambers of xeric", 52);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "chambers of xeric", 20 * 60 + 19);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 52);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCoXKillNoPb()
|
||||
{
|
||||
when(configManager.getConfiguration(anyString(), anyString(), any())).thenReturn(2224);
|
||||
when(configManager.getRSProfileConfiguration(anyString(), anyString(), any(Class.class))).thenReturn(2224);
|
||||
|
||||
ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", "<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>3 players</col> Duration:</col> <col=ff0000>37:10</col> (new personal best)</col>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
@@ -455,8 +453,8 @@ public class ChatCommandsPluginTest
|
||||
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: <col=ff0000>52</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration(eq("killcount.adam"), eq("chambers of xeric"), eq(52));
|
||||
verify(configManager, never()).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), anyInt());
|
||||
verify(configManager).setRSProfileConfiguration(eq("killcount"), eq("chambers of xeric"), eq(52));
|
||||
verify(configManager, never()).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric"), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -467,7 +465,7 @@ public class ChatCommandsPluginTest
|
||||
when(advLogWidget.getChild(ChatCommandsPlugin.ADV_LOG_EXPLOITS_TEXT_INDEX)).thenReturn(advLogExploitsTextWidget);
|
||||
when(advLogExploitsTextWidget.getText()).thenReturn("The Exploits of " + PLAYER_NAME);
|
||||
when(client.getWidget(WidgetInfo.ADVENTURE_LOG)).thenReturn(advLogWidget);
|
||||
when(configManager.getConfiguration(anyString(), anyString(), any())).thenReturn(2224);
|
||||
when(configManager.getRSProfileConfiguration(anyString(), anyString(), any(Class.class))).thenReturn(2224);
|
||||
|
||||
WidgetLoaded advLogEvent = new WidgetLoaded();
|
||||
advLogEvent.setGroupId(ADVENTURE_LOG_ID);
|
||||
@@ -502,14 +500,14 @@ public class ChatCommandsPluginTest
|
||||
chatCommandsPlugin.onWidgetLoaded(countersLogEvent);
|
||||
chatCommandsPlugin.onGameTick(new GameTick());
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tztok-jad"), eq(38 * 60 + 10));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("zulrah"), eq(5 * 60 + 48));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("vorkath"), eq(1 * 60 + 21));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("grotesque guardians"), eq(2 * 60 + 49));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("hespori"), eq(57));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("nightmare"), eq(3 * 60 + 30));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), eq(24 * 60 + 17));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric challenge mode"), eq(22 * 60 + 15));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("tztok-jad"), eq(38 * 60 + 10));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("zulrah"), eq(5 * 60 + 48));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("vorkath"), eq(1 * 60 + 21));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("grotesque guardians"), eq(2 * 60 + 49));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("hespori"), eq(57));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("nightmare"), eq(3 * 60 + 30));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric"), eq(24 * 60 + 17));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric challenge mode"), eq(22 * 60 + 15));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -554,12 +552,12 @@ public class ChatCommandsPluginTest
|
||||
chatCommandsPlugin.onWidgetLoaded(countersLogEvent);
|
||||
chatCommandsPlugin.onGameTick(new GameTick());
|
||||
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("tztok-jad"), eq(65 * 60 + 12));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("zulrah"), eq(2 * 60 + 55));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("vorkath"), eq(1 * 60 + 37));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("hespori"), eq(1 * 60 + 42));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), eq(21 * 60 + 23));
|
||||
verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric challenge mode"), eq(21 * 60 + 26));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("tztok-jad"), eq(65 * 60 + 12));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("zulrah"), eq(2 * 60 + 55));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("vorkath"), eq(1 * 60 + 37));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("hespori"), eq(1 * 60 + 42));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric"), eq(21 * 60 + 23));
|
||||
verify(configManager).setRSProfileConfiguration(eq("personalbest"), eq("chambers of xeric challenge mode"), eq(21 * 60 + 26));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -612,7 +610,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 1 time: <col=ff0000>1:19</col>. Personal best: 0:28", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 1", 28);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 1", 28);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -621,7 +619,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 2 time: <col=ff0000>0:47</col> (new personal best)", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 2", 47);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 2", 47);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -630,8 +628,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>4:46</col> (new personal best)<br>Overall time: <col=ff0000>9:53</col> (new personal best)<br>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 5", 4 * 60 + 46);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre", 9 * 60 + 53);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 4 * 60 + 46);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 53);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -640,8 +638,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:26</col> (new personal best)<br>Overall time: <col=ff0000>9:17</col>. Personal best: 9:15<br>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 5", 3 * 60 + 26);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre", 9 * 60 + 15);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 26);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 9 * 60 + 15);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -650,8 +648,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:56</col>. Personal best: 3:05<br>Overall time: <col=ff0000>9:14</col>. Personal best: 7:49<br>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 5", 3 * 60 + 5);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre", 7 * 60 + 49);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 5);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 49);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -660,8 +658,8 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Floor 5 time: <col=ff0000>3:10</col>. Personal best: 3:04<br>Overall time: <col=ff0000>7:47</col> (new personal best)<br>", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre floor 5", 3 * 60 + 4);
|
||||
verify(configManager).setConfiguration("personalbest.adam", "hallowed sepulchre", 7 * 60 + 47);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre floor 5", 3 * 60 + 4);
|
||||
verify(configManager).setRSProfileConfiguration("personalbest", "hallowed sepulchre", 7 * 60 + 47);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -670,7 +668,7 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have completed Floor 5 of the Hallowed Sepulchre! Total completions: <col=ff0000>81</col>.", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "hallowed sepulchre floor 5", 81);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre floor 5", 81);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -679,6 +677,6 @@ public class ChatCommandsPluginTest
|
||||
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "You have opened the Grand Hallowed Coffin <col=ff0000>36</col> times!", null, 0);
|
||||
chatCommandsPlugin.onChatMessage(chatMessage);
|
||||
|
||||
verify(configManager).setConfiguration("killcount.adam", "hallowed sepulchre", 36);
|
||||
verify(configManager).setRSProfileConfiguration("killcount", "hallowed sepulchre", 36);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,6 @@ public class GrandExchangePluginTest
|
||||
public void setUp()
|
||||
{
|
||||
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
||||
when(client.getUsername()).thenReturn("adam");
|
||||
when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class));
|
||||
}
|
||||
|
||||
@@ -148,7 +147,7 @@ public class GrandExchangePluginTest
|
||||
savedOffer.setPrice(1000);
|
||||
savedOffer.setSpent(25);
|
||||
savedOffer.setState(GrandExchangeOfferState.BUYING);
|
||||
when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
|
||||
// buy 2 @ 10/ea
|
||||
GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class);
|
||||
@@ -182,7 +181,7 @@ public class GrandExchangePluginTest
|
||||
savedOffer.setPrice(1000);
|
||||
savedOffer.setSpent(25);
|
||||
savedOffer.setState(GrandExchangeOfferState.BUYING);
|
||||
when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
|
||||
GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class);
|
||||
when(grandExchangeOffer.getQuantitySold()).thenReturn(1);
|
||||
@@ -206,7 +205,7 @@ public class GrandExchangePluginTest
|
||||
savedOffer.setPrice(1000);
|
||||
savedOffer.setSpent(25);
|
||||
savedOffer.setState(GrandExchangeOfferState.BUYING);
|
||||
when(configManager.getConfiguration("geoffer.adam", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
when(configManager.getRSProfileConfiguration("geoffer", "0")).thenReturn(GSON.toJson(savedOffer));
|
||||
|
||||
GrandExchangeOffer grandExchangeOffer = mock(GrandExchangeOffer.class);
|
||||
when(grandExchangeOffer.getQuantitySold()).thenReturn(1);
|
||||
@@ -242,6 +241,6 @@ public class GrandExchangePluginTest
|
||||
|
||||
grandExchangePlugin.onGrandExchangeOfferChanged(grandExchangeOfferChanged);
|
||||
|
||||
verify(configManager, never()).unsetConfiguration(anyString(), anyString());
|
||||
verify(configManager, never()).unsetRSProfileConfiguration(anyString(), anyString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user