Merge pull request #12834 from abextm/rsprofile-external

Per RuneScape-Profile configuration
This commit is contained in:
Adam
2020-11-27 00:00:54 -05:00
committed by GitHub
21 changed files with 998 additions and 256 deletions

View File

@@ -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<>();

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
{
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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.
*/

View File

@@ -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
{
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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)
{

View File

@@ -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());
}
}
}

View File

@@ -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]);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}