runelite-client: add config plugin
This commit is contained in:
@@ -92,6 +92,12 @@
|
|||||||
<version>4.12</version>
|
<version>4.12</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-all</artifactId>
|
||||||
|
<version>1.10.19</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import javax.imageio.ImageIO;
|
|||||||
import joptsimple.OptionParser;
|
import joptsimple.OptionParser;
|
||||||
import joptsimple.OptionSet;
|
import joptsimple.OptionSet;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.account.AccountSession;
|
import net.runelite.client.account.AccountSession;
|
||||||
import net.runelite.client.events.SessionClose;
|
import net.runelite.client.events.SessionClose;
|
||||||
import net.runelite.client.events.SessionOpen;
|
import net.runelite.client.events.SessionOpen;
|
||||||
@@ -57,6 +58,7 @@ public class RuneLite
|
|||||||
private static final Logger logger = LoggerFactory.getLogger(RuneLite.class);
|
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 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 final File SESSION_FILE = new File(RUNELITE_DIR, "session");
|
||||||
|
|
||||||
public static Image ICON;
|
public static Image ICON;
|
||||||
@@ -75,6 +77,7 @@ public class RuneLite
|
|||||||
private WSClient wsclient;
|
private WSClient wsclient;
|
||||||
|
|
||||||
private AccountSession accountSession;
|
private AccountSession accountSession;
|
||||||
|
private ConfigManager configManager = new ConfigManager(eventBus);
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
@@ -99,6 +102,8 @@ public class RuneLite
|
|||||||
parser.accepts("no-rs");
|
parser.accepts("no-rs");
|
||||||
options = parser.parse(args);
|
options = parser.parse(args);
|
||||||
|
|
||||||
|
PROFILES_DIR.mkdirs();
|
||||||
|
|
||||||
runelite = new RuneLite();
|
runelite = new RuneLite();
|
||||||
runelite.start();
|
runelite.start();
|
||||||
}
|
}
|
||||||
@@ -109,6 +114,8 @@ public class RuneLite
|
|||||||
|
|
||||||
setupTrayIcon();
|
setupTrayIcon();
|
||||||
|
|
||||||
|
configManager.load();
|
||||||
|
|
||||||
eventBus.register(menuManager);
|
eventBus.register(menuManager);
|
||||||
|
|
||||||
pluginManager = new PluginManager(this);
|
pluginManager = new PluginManager(this);
|
||||||
@@ -210,6 +217,14 @@ public class RuneLite
|
|||||||
|
|
||||||
accountSession = session;
|
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());
|
eventBus.post(new SessionOpen());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +245,10 @@ public class RuneLite
|
|||||||
|
|
||||||
accountSession = null; // No more account
|
accountSession = null; // No more account
|
||||||
|
|
||||||
|
// Restore config
|
||||||
|
configManager = new ConfigManager(eventBus);
|
||||||
|
configManager.load();
|
||||||
|
|
||||||
eventBus.post(new SessionClose());
|
eventBus.post(new SessionClose());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +312,11 @@ public class RuneLite
|
|||||||
return trayIcon;
|
return trayIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConfigManager getConfigManager()
|
||||||
|
{
|
||||||
|
return configManager;
|
||||||
|
}
|
||||||
|
|
||||||
public AccountSession getAccountSession()
|
public AccountSession getAccountSession()
|
||||||
{
|
{
|
||||||
return accountSession;
|
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;
|
return overlay != null ? Arrays.asList(overlay) : Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object getConfig()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override AbstractIdleService's default executor to instead execute in
|
* Override AbstractIdleService's default executor to instead execute in
|
||||||
* the main thread. Prevents plugins from all being initialized from
|
* the main thread. Prevents plugins from all being initialized from
|
||||||
* different threads, which causes the plugin order on the navbar to be
|
* different threads, which causes the plugin order on the navbar to be
|
||||||
* undefined
|
* undefined
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import net.runelite.client.plugins.account.AccountPlugin;
|
|||||||
import net.runelite.client.plugins.boosts.Boosts;
|
import net.runelite.client.plugins.boosts.Boosts;
|
||||||
import net.runelite.client.plugins.bosstimer.BossTimers;
|
import net.runelite.client.plugins.bosstimer.BossTimers;
|
||||||
import net.runelite.client.plugins.clanchat.ClanChat;
|
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.devtools.DevTools;
|
||||||
import net.runelite.client.plugins.fpsinfo.FPS;
|
import net.runelite.client.plugins.fpsinfo.FPS;
|
||||||
import net.runelite.client.plugins.hiscore.Hiscore;
|
import net.runelite.client.plugins.hiscore.Hiscore;
|
||||||
@@ -77,6 +78,7 @@ public class PluginManager
|
|||||||
plugins.add(new ClanChat());
|
plugins.add(new ClanChat());
|
||||||
plugins.add(new Zulrah());
|
plugins.add(new Zulrah());
|
||||||
plugins.add(new AccountPlugin());
|
plugins.add(new AccountPlugin());
|
||||||
|
plugins.add(new ConfigPlugin());
|
||||||
|
|
||||||
if (RuneLite.getOptions().has("developer-mode"))
|
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.io.InputStreamReader;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import net.runelite.client.RuneLite;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.ui.overlay.Overlay;
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
|
|
||||||
public class OpponentInfo extends Plugin
|
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
|
@Override
|
||||||
public Overlay getOverlay()
|
public Overlay getOverlay()
|
||||||
@@ -53,10 +55,18 @@ public class OpponentInfo extends Plugin
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpponentConfig getConfig()
|
||||||
|
{
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<String, Integer> loadNpcHealth()
|
public static Map<String, Integer> loadNpcHealth()
|
||||||
{
|
{
|
||||||
Gson gson = new Gson();
|
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");
|
InputStream healthFile = OpponentInfo.class.getResourceAsStream("/npc_health.json");
|
||||||
return gson.fromJson(new InputStreamReader(healthFile), type);
|
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
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.runelite.client.plugins.opponentinfo;
|
package net.runelite.client.plugins.opponentinfo;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
@@ -58,6 +57,7 @@ class OpponentInfoOverlay extends Overlay
|
|||||||
|
|
||||||
private static final Duration WAIT = Duration.ofSeconds(3);
|
private static final Duration WAIT = Duration.ofSeconds(3);
|
||||||
|
|
||||||
|
private final OpponentConfig config;
|
||||||
private Integer lastMaxHealth;
|
private Integer lastMaxHealth;
|
||||||
private DecimalFormat df = new DecimalFormat("0.0");
|
private DecimalFormat df = new DecimalFormat("0.0");
|
||||||
private float lastRatio = 0;
|
private float lastRatio = 0;
|
||||||
@@ -65,9 +65,10 @@ class OpponentInfoOverlay extends Overlay
|
|||||||
private String opponentName;
|
private String opponentName;
|
||||||
private Map<String, Integer> oppInfoHealth = OpponentInfo.loadNpcHealth();
|
private Map<String, Integer> oppInfoHealth = OpponentInfo.loadNpcHealth();
|
||||||
|
|
||||||
OpponentInfoOverlay()
|
OpponentInfoOverlay(OpponentInfo plugin)
|
||||||
{
|
{
|
||||||
super(OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
|
super(OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
|
||||||
|
this.config = plugin.getConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Actor getOpponent()
|
private Actor getOpponent()
|
||||||
@@ -76,7 +77,9 @@ class OpponentInfoOverlay extends Overlay
|
|||||||
|
|
||||||
Player player = client.getLocalPlayer();
|
Player player = client.getLocalPlayer();
|
||||||
if (player == null)
|
if (player == null)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return player.getInteracting();
|
return player.getInteracting();
|
||||||
}
|
}
|
||||||
@@ -84,8 +87,10 @@ class OpponentInfoOverlay extends Overlay
|
|||||||
@Override
|
@Override
|
||||||
public Dimension render(Graphics2D graphics)
|
public Dimension render(Graphics2D graphics)
|
||||||
{
|
{
|
||||||
if (RuneLite.getClient().getGameState() != GameState.LOGGED_IN)
|
if (RuneLite.getClient().getGameState() != GameState.LOGGED_IN || config.enabled() == false)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Actor opponent = getOpponent();
|
Actor opponent = getOpponent();
|
||||||
|
|
||||||
@@ -98,8 +103,9 @@ class OpponentInfoOverlay extends Overlay
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Duration.between(Instant.now(), lastTime).abs().compareTo(WAIT) > 0)
|
if (Duration.between(Instant.now(), lastTime).abs().compareTo(WAIT) > 0)
|
||||||
|
{
|
||||||
return null; //don't draw anything.
|
return null; //don't draw anything.
|
||||||
|
}
|
||||||
FontMetrics fm = graphics.getFontMetrics();
|
FontMetrics fm = graphics.getFontMetrics();
|
||||||
|
|
||||||
int height = TOP_BORDER + fm.getHeight(); // opponent name
|
int height = TOP_BORDER + fm.getHeight(); // opponent name
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@@ -99,7 +100,7 @@ public final class ClientUI extends JFrame
|
|||||||
|
|
||||||
public void expand(PluginPanel panel)
|
public void expand(PluginPanel panel)
|
||||||
{
|
{
|
||||||
if (pluginPanel == panel)
|
if (Objects.equals(pluginPanel, panel))
|
||||||
{
|
{
|
||||||
navContainer.remove(1);
|
navContainer.remove(1);
|
||||||
container.validate();
|
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