runelite-client: add config plugin
This commit is contained in:
@@ -92,6 +92,12 @@
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -42,6 +42,7 @@ import javax.imageio.ImageIO;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.events.SessionClose;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
@@ -57,6 +58,7 @@ public class RuneLite
|
||||
private static final Logger logger = LoggerFactory.getLogger(RuneLite.class);
|
||||
|
||||
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite");
|
||||
public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles");
|
||||
public static final File SESSION_FILE = new File(RUNELITE_DIR, "session");
|
||||
|
||||
public static Image ICON;
|
||||
@@ -75,6 +77,7 @@ public class RuneLite
|
||||
private WSClient wsclient;
|
||||
|
||||
private AccountSession accountSession;
|
||||
private ConfigManager configManager = new ConfigManager(eventBus);
|
||||
|
||||
static
|
||||
{
|
||||
@@ -99,6 +102,8 @@ public class RuneLite
|
||||
parser.accepts("no-rs");
|
||||
options = parser.parse(args);
|
||||
|
||||
PROFILES_DIR.mkdirs();
|
||||
|
||||
runelite = new RuneLite();
|
||||
runelite.start();
|
||||
}
|
||||
@@ -109,6 +114,8 @@ public class RuneLite
|
||||
|
||||
setupTrayIcon();
|
||||
|
||||
configManager.load();
|
||||
|
||||
eventBus.register(menuManager);
|
||||
|
||||
pluginManager = new PluginManager(this);
|
||||
@@ -210,6 +217,14 @@ public class RuneLite
|
||||
|
||||
accountSession = session;
|
||||
|
||||
if (session.getUsername() != null)
|
||||
{
|
||||
// Initialize config for new session
|
||||
// If the session isn't logged in yet, don't switch to the new config
|
||||
configManager = new ConfigManager(eventBus, session);
|
||||
configManager.load();
|
||||
}
|
||||
|
||||
eventBus.post(new SessionOpen());
|
||||
}
|
||||
|
||||
@@ -230,6 +245,10 @@ public class RuneLite
|
||||
|
||||
accountSession = null; // No more account
|
||||
|
||||
// Restore config
|
||||
configManager = new ConfigManager(eventBus);
|
||||
configManager.load();
|
||||
|
||||
eventBus.post(new SessionClose());
|
||||
}
|
||||
|
||||
@@ -293,6 +312,11 @@ public class RuneLite
|
||||
return trayIcon;
|
||||
}
|
||||
|
||||
public ConfigManager getConfigManager()
|
||||
{
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public AccountSession getAccountSession()
|
||||
{
|
||||
return accountSession;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ConfigDescriptor
|
||||
{
|
||||
private final ConfigGroup group;
|
||||
private final Collection<ConfigItemDescriptor> items;
|
||||
|
||||
public ConfigDescriptor(ConfigGroup group, Collection<ConfigItemDescriptor> items)
|
||||
{
|
||||
this.group = group;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public ConfigGroup getGroup()
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
public Collection<ConfigItemDescriptor> getItems()
|
||||
{
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ConfigGroup
|
||||
{
|
||||
String keyName();
|
||||
|
||||
String name();
|
||||
|
||||
String description();
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class ConfigInvocationHandler implements InvocationHandler
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigInvocationHandler.class);
|
||||
|
||||
private final ConfigManager manager;
|
||||
|
||||
public ConfigInvocationHandler(ConfigManager manager)
|
||||
{
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
|
||||
{
|
||||
Class<?> iface = proxy.getClass().getInterfaces()[0];
|
||||
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
logger.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
logger.warn("Configuration method {} has no @ConfigItem!", method);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (args == null)
|
||||
{
|
||||
// Getting configuration item
|
||||
String value = manager.getConfiguration(group.keyName(), item.keyName());
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
if (method.isDefault())
|
||||
{
|
||||
return callDefaultMethod(proxy, method, args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert value to return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (returnType == value.getClass())
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (returnType == Boolean.class)
|
||||
{
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
|
||||
logger.warn("Unknown return type for configuration item {}.{}: {}", group.keyName(), item.keyName(), returnType);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setting a configuration value
|
||||
|
||||
if (args.length != 1)
|
||||
{
|
||||
throw new RuntimeException("Invalid number of arguents to configuration method");
|
||||
}
|
||||
|
||||
Object newValue = args[0];
|
||||
|
||||
if (method.isDefault())
|
||||
{
|
||||
Object defaultValue = callDefaultMethod(proxy, method, args);
|
||||
|
||||
if (Objects.equal(newValue, defaultValue))
|
||||
{
|
||||
// Just unset if it goes back to the default
|
||||
manager.unsetConfiguration(group.keyName(), item.keyName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
manager.setConfiguration(group.keyName(), item.keyName(), args[0].toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object callDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable
|
||||
{
|
||||
// Call the default method implementation - https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/
|
||||
Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
|
||||
constructor.setAccessible(true);
|
||||
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
return constructor.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
|
||||
.unreflectSpecial(method, declaringClass)
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ConfigItem
|
||||
{
|
||||
String keyName();
|
||||
|
||||
String name();
|
||||
|
||||
String description();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
public class ConfigItemDescriptor
|
||||
{
|
||||
private final ConfigItem item;
|
||||
private final Class<?> type;
|
||||
|
||||
public ConfigItemDescriptor(ConfigItem item, Class<?> type)
|
||||
{
|
||||
this.item = item;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ConfigItem getItem()
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
public Class<?> getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.http.api.config.ConfigClient;
|
||||
import net.runelite.http.api.config.ConfigEntry;
|
||||
import net.runelite.http.api.config.Configuration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConfigManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
|
||||
|
||||
private static final String SETTINGS_FILE_NAME = "settings.properties";
|
||||
|
||||
private final EventBus eventBus;
|
||||
private AccountSession session;
|
||||
private ConfigClient client;
|
||||
|
||||
private final File propertiesFile;
|
||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
public ConfigManager(EventBus eventBus)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
}
|
||||
|
||||
public ConfigManager(EventBus eventBus, AccountSession session)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.session = session;
|
||||
// if session username is null then dont..
|
||||
this.client = new ConfigClient(session.getUuid());
|
||||
this.propertiesFile = getPropertiesFile();
|
||||
}
|
||||
|
||||
private File getPropertiesFile()
|
||||
{
|
||||
// Sessions that aren't logged in have no username
|
||||
if (session == null || session.getUsername() == null)
|
||||
{
|
||||
return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
File profileDir = new File(RuneLite.PROFILES_DIR, session.getUsername().toLowerCase());
|
||||
return new File(profileDir, SETTINGS_FILE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
public void load()
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration configuration;
|
||||
|
||||
try
|
||||
{
|
||||
configuration = client.get();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug("Unable to load configuration from client, using saved configuration from disk", ex);
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
if (configuration.getConfig().isEmpty())
|
||||
{
|
||||
logger.debug("No configuration from client, using saved configuration on disk");
|
||||
loadFromFile();
|
||||
return;
|
||||
}
|
||||
|
||||
properties.clear();
|
||||
|
||||
for (ConfigEntry entry : configuration.getConfig())
|
||||
{
|
||||
properties.setProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile();
|
||||
|
||||
logger.debug("Updated configuration on disk with the latest version");
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("Unable to update configuration on disk", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromFile()
|
||||
{
|
||||
try (FileInputStream in = new FileInputStream(propertiesFile))
|
||||
{
|
||||
properties.load(in);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
logger.debug("Unable to load settings - no such file");
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("Unable to load settings", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToFile() throws IOException
|
||||
{
|
||||
propertiesFile.getParentFile().mkdirs();
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream(propertiesFile))
|
||||
{
|
||||
properties.store(out, "Runelite configuration");
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T getConfig(Class<T> clazz)
|
||||
{
|
||||
if (!Modifier.isPublic(clazz.getModifiers()))
|
||||
{
|
||||
throw new RuntimeException("Non-public configuration classes can't have default methods invoked");
|
||||
}
|
||||
|
||||
return (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]
|
||||
{
|
||||
clazz
|
||||
}, handler);
|
||||
}
|
||||
|
||||
public String getConfiguration(String groupName, String key)
|
||||
{
|
||||
return properties.getProperty(groupName + "." + key);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String key, String value)
|
||||
{
|
||||
logger.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
||||
|
||||
String oldValue = (String) properties.setProperty(groupName + "." + key, value);
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
client.set(groupName + "." + key, value);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("unable to set configuration item", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("unable to save configuration file", ex);
|
||||
}
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
public void unsetConfiguration(String groupName, String key)
|
||||
{
|
||||
logger.debug("Unsetting configuration value for {}.{}", groupName, key);
|
||||
|
||||
String oldValue = (String) properties.remove(groupName + "." + key);
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
client.unset(groupName + "." + key);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("unable to set configuration item", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveToFile();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.warn("unable to save configuration file", ex);
|
||||
}
|
||||
|
||||
ConfigChanged configChanged = new ConfigChanged();
|
||||
configChanged.setGroup(groupName);
|
||||
configChanged.setKey(key);
|
||||
configChanged.setOldValue(oldValue);
|
||||
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
public ConfigDescriptor getConfigDescriptor(Object configurationProxy)
|
||||
{
|
||||
Class<?> inter = configurationProxy.getClass().getInterfaces()[0];
|
||||
ConfigGroup group = inter.getAnnotation(ConfigGroup.class);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Not a config group");
|
||||
}
|
||||
|
||||
List<ConfigItemDescriptor> items = Arrays.stream(inter.getMethods())
|
||||
.filter(m -> m.getParameterCount() == 0)
|
||||
.map(m -> new ConfigItemDescriptor(
|
||||
m.getDeclaredAnnotation(ConfigItem.class),
|
||||
m.getReturnType()
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
return new ConfigDescriptor(group, items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
public class ConfigChanged
|
||||
{
|
||||
private String group;
|
||||
private String key;
|
||||
private String oldValue;
|
||||
private String newValue;
|
||||
|
||||
public String getGroup()
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group)
|
||||
{
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getOldValue()
|
||||
{
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public void setOldValue(String oldValue)
|
||||
{
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
public String getNewValue()
|
||||
{
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public void setNewValue(String newValue)
|
||||
{
|
||||
this.newValue = newValue;
|
||||
}
|
||||
}
|
||||
@@ -44,11 +44,17 @@ public abstract class Plugin extends AbstractIdleService
|
||||
return overlay != null ? Arrays.asList(overlay) : Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
public Object getConfig()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override AbstractIdleService's default executor to instead execute in
|
||||
* the main thread. Prevents plugins from all being initialized from
|
||||
* different threads, which causes the plugin order on the navbar to be
|
||||
* undefined
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -36,6 +36,7 @@ import net.runelite.client.plugins.account.AccountPlugin;
|
||||
import net.runelite.client.plugins.boosts.Boosts;
|
||||
import net.runelite.client.plugins.bosstimer.BossTimers;
|
||||
import net.runelite.client.plugins.clanchat.ClanChat;
|
||||
import net.runelite.client.plugins.config.ConfigPlugin;
|
||||
import net.runelite.client.plugins.devtools.DevTools;
|
||||
import net.runelite.client.plugins.fpsinfo.FPS;
|
||||
import net.runelite.client.plugins.hiscore.Hiscore;
|
||||
@@ -77,6 +78,7 @@ public class PluginManager
|
||||
plugins.add(new ClanChat());
|
||||
plugins.add(new Zulrah());
|
||||
plugins.add(new AccountPlugin());
|
||||
plugins.add(new ConfigPlugin());
|
||||
|
||||
if (RuneLite.getOptions().has("developer-mode"))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.config;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.swing.BoxLayout;
|
||||
import static javax.swing.BoxLayout.Y_AXIS;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigDescriptor;
|
||||
import net.runelite.client.config.ConfigItemDescriptor;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import static net.runelite.client.ui.PluginPanel.PANEL_HEIGHT;
|
||||
import static net.runelite.client.ui.PluginPanel.PANEL_WIDTH;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConfigPanel extends PluginPanel
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigPanel.class);
|
||||
|
||||
private final RuneLite runelite = RuneLite.getRunelite();
|
||||
|
||||
public ConfigPanel()
|
||||
{
|
||||
setMinimumSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
setSize(PANEL_WIDTH, PANEL_HEIGHT);
|
||||
setLayout(new BorderLayout());
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return other.getClass() == this.getClass();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
add(createConfigPanel());
|
||||
}
|
||||
|
||||
private Collection<ConfigDescriptor> getConfig()
|
||||
{
|
||||
List<ConfigDescriptor> list = new ArrayList<>();
|
||||
PluginManager pm = runelite.getPluginManager();
|
||||
for (Plugin plugin : pm.getPlugins())
|
||||
{
|
||||
Object config = plugin.getConfig();
|
||||
if (config != null)
|
||||
{
|
||||
ConfigManager configManager = runelite.getConfigManager();
|
||||
ConfigDescriptor configDescriptor = configManager.getConfigDescriptor(config);
|
||||
list.add(configDescriptor);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private JPanel createConfigPanel()
|
||||
{
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, Y_AXIS));
|
||||
|
||||
ConfigManager configManager = runelite.getConfigManager();
|
||||
Collection<ConfigDescriptor> config = getConfig();
|
||||
for (ConfigDescriptor cd : config)
|
||||
{
|
||||
JPanel groupPanel = new JPanel();
|
||||
groupPanel.setLayout(new BorderLayout());
|
||||
|
||||
groupPanel.add(new JLabel(cd.getGroup().name()), BorderLayout.NORTH);
|
||||
|
||||
JPanel itemPanel = new JPanel();
|
||||
|
||||
for (ConfigItemDescriptor cid : cd.getItems())
|
||||
{
|
||||
itemPanel.add(new JLabel(cid.getItem().name()));
|
||||
|
||||
if (cid.getType() == boolean.class)
|
||||
{
|
||||
JCheckBox checkbox = new JCheckBox();
|
||||
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName())));
|
||||
checkbox.addActionListener(ae -> changeConfiguration(ae, checkbox, cd, cid));
|
||||
|
||||
itemPanel.add(checkbox);
|
||||
}
|
||||
}
|
||||
|
||||
groupPanel.add(itemPanel, BorderLayout.CENTER);
|
||||
panel.add(groupPanel);
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void changeConfiguration(ActionEvent ae, JCheckBox checkbox, ConfigDescriptor cd, ConfigItemDescriptor cid)
|
||||
{
|
||||
ConfigManager configManager = runelite.getConfigManager();
|
||||
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), "" + checkbox.isSelected());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.config;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ConfigPlugin extends Plugin
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigPlugin.class);
|
||||
|
||||
private final NavigationButton navButton = new NavigationButton("Configuration");
|
||||
private final RuneLite runelite = RuneLite.getRunelite();
|
||||
private final ClientUI ui = runelite.getGui();
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
navButton.getButton().addActionListener(this::setPluginPanel);
|
||||
|
||||
ImageIcon icon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("config_icon.png")));
|
||||
navButton.getButton().setIcon(icon);
|
||||
|
||||
ui.getNavigationPanel().addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
private void setPluginPanel(ActionEvent ae)
|
||||
{
|
||||
ConfigPanel panel = new ConfigPanel();
|
||||
panel.init();
|
||||
|
||||
ui.expand(panel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.opponentinfo;
|
||||
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(
|
||||
keyName = "oppinfo",
|
||||
name = "Opponent Info",
|
||||
description = "Configuration for the opponent info plugin"
|
||||
)
|
||||
public interface OpponentConfig
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "enabled",
|
||||
name = "Enabled",
|
||||
description = "Configures whether or not opponent info is displayed"
|
||||
)
|
||||
default boolean enabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -30,12 +30,14 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
|
||||
public class OpponentInfo extends Plugin
|
||||
{
|
||||
private final Overlay overlay = new OpponentInfoOverlay();
|
||||
private final OpponentConfig config = RuneLite.getRunelite().getConfigManager().getConfig(OpponentConfig.class);
|
||||
private final Overlay overlay = new OpponentInfoOverlay(this);
|
||||
|
||||
@Override
|
||||
public Overlay getOverlay()
|
||||
@@ -53,10 +55,18 @@ public class OpponentInfo extends Plugin
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpponentConfig getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
public static Map<String, Integer> loadNpcHealth()
|
||||
{
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<Map<String, Integer>>(){}.getType();
|
||||
Type type = new TypeToken<Map<String, Integer>>()
|
||||
{
|
||||
}.getType();
|
||||
|
||||
InputStream healthFile = OpponentInfo.class.getResourceAsStream("/npc_health.json");
|
||||
return gson.fromJson(new InputStreamReader(healthFile), type);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.opponentinfo;
|
||||
|
||||
import java.awt.Color;
|
||||
@@ -58,6 +57,7 @@ class OpponentInfoOverlay extends Overlay
|
||||
|
||||
private static final Duration WAIT = Duration.ofSeconds(3);
|
||||
|
||||
private final OpponentConfig config;
|
||||
private Integer lastMaxHealth;
|
||||
private DecimalFormat df = new DecimalFormat("0.0");
|
||||
private float lastRatio = 0;
|
||||
@@ -65,9 +65,10 @@ class OpponentInfoOverlay extends Overlay
|
||||
private String opponentName;
|
||||
private Map<String, Integer> oppInfoHealth = OpponentInfo.loadNpcHealth();
|
||||
|
||||
OpponentInfoOverlay()
|
||||
OpponentInfoOverlay(OpponentInfo plugin)
|
||||
{
|
||||
super(OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
|
||||
this.config = plugin.getConfig();
|
||||
}
|
||||
|
||||
private Actor getOpponent()
|
||||
@@ -76,7 +77,9 @@ class OpponentInfoOverlay extends Overlay
|
||||
|
||||
Player player = client.getLocalPlayer();
|
||||
if (player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return player.getInteracting();
|
||||
}
|
||||
@@ -84,8 +87,10 @@ class OpponentInfoOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (RuneLite.getClient().getGameState() != GameState.LOGGED_IN)
|
||||
if (RuneLite.getClient().getGameState() != GameState.LOGGED_IN || config.enabled() == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Actor opponent = getOpponent();
|
||||
|
||||
@@ -98,8 +103,9 @@ class OpponentInfoOverlay extends Overlay
|
||||
}
|
||||
|
||||
if (Duration.between(Instant.now(), lastTime).abs().compareTo(WAIT) > 0)
|
||||
{
|
||||
return null; //don't draw anything.
|
||||
|
||||
}
|
||||
FontMetrics fm = graphics.getFontMetrics();
|
||||
|
||||
int height = TOP_BORDER + fm.getHeight(); // opponent name
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
@@ -99,7 +100,7 @@ public final class ClientUI extends JFrame
|
||||
|
||||
public void expand(PluginPanel panel)
|
||||
{
|
||||
if (pluginPanel == panel)
|
||||
if (Objects.equals(pluginPanel, panel))
|
||||
{
|
||||
navContainer.remove(1);
|
||||
container.validate();
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class ConfigManagerTest
|
||||
{
|
||||
@Test
|
||||
public void testGetConfig() throws IOException
|
||||
{
|
||||
AccountSession accountSession = new AccountSession();
|
||||
accountSession.setUuid(UUID.randomUUID());
|
||||
accountSession.setUsername("test");
|
||||
accountSession.setCreated(Instant.now());
|
||||
|
||||
ConfigManager manager = new ConfigManager(mock(EventBus.class));
|
||||
manager.setConfiguration("test", "key", "moo");
|
||||
|
||||
TestConfig conf = manager.getConfig(TestConfig.class);
|
||||
Assert.assertEquals("moo", conf.key());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigDefault() throws IOException
|
||||
{
|
||||
AccountSession accountSession = new AccountSession();
|
||||
accountSession.setUuid(UUID.randomUUID());
|
||||
accountSession.setUsername("test");
|
||||
accountSession.setCreated(Instant.now());
|
||||
|
||||
ConfigManager manager = new ConfigManager(mock(EventBus.class));
|
||||
|
||||
TestConfig conf = manager.getConfig(TestConfig.class);
|
||||
Assert.assertEquals("default", conf.key());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetConfig() throws IOException
|
||||
{
|
||||
AccountSession accountSession = new AccountSession();
|
||||
accountSession.setUuid(UUID.randomUUID());
|
||||
accountSession.setUsername("test");
|
||||
accountSession.setCreated(Instant.now());
|
||||
|
||||
ConfigManager manager = new ConfigManager(mock(EventBus.class));
|
||||
|
||||
TestConfig conf = manager.getConfig(TestConfig.class);
|
||||
conf.key("new value");
|
||||
|
||||
Assert.assertEquals("new value", conf.key());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigDescriptor() throws IOException
|
||||
{
|
||||
AccountSession accountSession = new AccountSession();
|
||||
accountSession.setUuid(UUID.randomUUID());
|
||||
accountSession.setUsername("test");
|
||||
accountSession.setCreated(Instant.now());
|
||||
|
||||
ConfigManager manager = new ConfigManager(mock(EventBus.class));
|
||||
|
||||
TestConfig conf = manager.getConfig(TestConfig.class);
|
||||
ConfigDescriptor descriptor = manager.getConfigDescriptor(conf);
|
||||
Assert.assertEquals(1, descriptor.getItems().size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
@ConfigGroup(
|
||||
keyName = "test",
|
||||
name = "test",
|
||||
description = "test"
|
||||
)
|
||||
public interface TestConfig
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "key",
|
||||
name = "Key Name",
|
||||
description = "value"
|
||||
)
|
||||
default String key()
|
||||
{
|
||||
return "default";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "key",
|
||||
name = "Key Name",
|
||||
description = "value"
|
||||
)
|
||||
void key(String key);
|
||||
}
|
||||
Reference in New Issue
Block a user