diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index cb1ffd5ee2..5ea49d8640 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -33,6 +33,7 @@ import com.google.inject.Injector; import java.io.File; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; +import java.nio.file.Paths; import java.util.Locale; import javax.annotation.Nullable; import javax.inject.Provider; @@ -41,6 +42,8 @@ import javax.swing.SwingUtilities; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; import joptsimple.util.EnumConverter; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -52,12 +55,12 @@ import net.runelite.client.chat.CommandManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; import net.runelite.client.eventbus.EventBus; +import net.runelite.client.externalplugins.ExternalPluginManager; import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.menus.MenuManager; -import net.runelite.client.externalplugins.ExternalPluginManager; import net.runelite.client.plugins.PluginManager; import net.runelite.client.rs.ClientLoader; import net.runelite.client.rs.ClientUpdateCheckMode; @@ -85,6 +88,8 @@ public class RuneLite public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles"); public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots"); public static final File LOGS_DIR = new File(RUNELITE_DIR, "logs"); + public static final String DEFAULT_SESSION_FILE = "session"; + public static final String DEFAULT_CONFIG_FILE = "settings.properties"; @Getter private static Injector injector; @@ -173,6 +178,14 @@ public class RuneLite parser.accepts("developer-mode", "Enable developer tools"); parser.accepts("debug", "Show extra debugging output"); + final ArgumentAcceptingOptionSpec sessionfile = parser.accepts("sessionfile", "Use a specified session file") + .withRequiredArg().defaultsTo(DEFAULT_SESSION_FILE) + .withValuesConvertedBy(new ConfigFileConverter()); + + final ArgumentAcceptingOptionSpec configfile = parser.accepts("config", "Use a specified config file") + .withRequiredArg().defaultsTo(DEFAULT_CONFIG_FILE) + .withValuesConvertedBy(new ConfigFileConverter()); + final ArgumentAcceptingOptionSpec updateMode = parser .accepts("rs", "Select client type") .withRequiredArg() @@ -246,7 +259,9 @@ public class RuneLite injector = Guice.createInjector(new RuneLiteModule( clientLoader, - developerMode)); + developerMode, + options.valueOf(sessionfile), + options.valueOf(configfile))); injector.getInstance(RuneLite.class).start(); @@ -363,4 +378,43 @@ public class RuneLite { RuneLite.injector = injector; } + + private static class ConfigFileConverter implements ValueConverter + { + @Override + public File convert(String fileName) + { + final File file; + + if (Paths.get(fileName).isAbsolute() + || fileName.startsWith("./") + || fileName.startsWith(".\\")) + { + file = new File(fileName); + } + else + { + file = new File(RuneLite.RUNELITE_DIR, fileName); + } + + if (file.exists() && (!file.isFile() || !file.canWrite())) + { + throw new ValueConversionException(String.format("File %s is not accessible", file.getAbsolutePath())); + } + + return file; + } + + @Override + public Class valueType() + { + return File.class; + } + + @Override + public String valuePattern() + { + return null; + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java index 56076b3368..0434f54abf 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteModule.java @@ -61,17 +61,23 @@ public class RuneLiteModule extends AbstractModule private final Supplier clientLoader; private final boolean developerMode; + private final File sessionfile; + private final File config; - public RuneLiteModule(Supplier clientLoader, boolean developerMode) + public RuneLiteModule(Supplier clientLoader, boolean developerMode, File sessionfile, File config) { this.clientLoader = clientLoader; this.developerMode = developerMode; + this.sessionfile = sessionfile; + this.config = config; } @Override protected void configure() { bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode); + bind(File.class).annotatedWith(Names.named("sessionfile")).toInstance(sessionfile); + bind(File.class).annotatedWith(Names.named("config")).toInstance(config); bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor())); bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT.newBuilder() .cache(new Cache(new File(RuneLite.CACHE_DIR, "okhttp"), MAX_OKHTTP_CACHE_SIZE)) diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index acac9a3b32..a5c45f2591 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -33,15 +33,15 @@ import java.io.InputStreamReader; import java.time.Instant; import java.util.UUID; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import net.runelite.client.events.SessionClose; -import net.runelite.client.events.SessionOpen; -import net.runelite.client.RuneLite; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.SessionClose; +import net.runelite.client.events.SessionOpen; import net.runelite.client.util.LinkBrowser; import net.runelite.client.ws.WSClient; import net.runelite.http.api.account.AccountClient; @@ -52,27 +52,32 @@ import net.runelite.http.api.ws.messages.LoginResponse; @Slf4j public class SessionManager { - private static final File SESSION_FILE = new File(RuneLite.RUNELITE_DIR, "session"); - @Getter private AccountSession accountSession; private final EventBus eventBus; private final ConfigManager configManager; private final WSClient wsClient; + private final File sessionFile; @Inject - private SessionManager(ConfigManager configManager, EventBus eventBus, WSClient wsClient) + private SessionManager( + @Named("sessionfile") File sessionfile, + ConfigManager configManager, + EventBus eventBus, + WSClient wsClient) { this.configManager = configManager; this.eventBus = eventBus; this.wsClient = wsClient; + this.sessionFile = sessionfile; + eventBus.register(this); } public void loadSession() { - if (!SESSION_FILE.exists()) + if (!sessionFile.exists()) { log.info("No session file exists"); return; @@ -80,7 +85,7 @@ public class SessionManager AccountSession session; - try (FileInputStream in = new FileInputStream(SESSION_FILE)) + try (FileInputStream in = new FileInputStream(sessionFile)) { session = new Gson().fromJson(new InputStreamReader(in), AccountSession.class); @@ -110,11 +115,11 @@ public class SessionManager return; } - try (FileWriter fw = new FileWriter(SESSION_FILE)) + try (FileWriter fw = new FileWriter(sessionFile)) { new Gson().toJson(accountSession, fw); - log.debug("Saved session to {}", SESSION_FILE); + log.debug("Saved session to {}", sessionFile); } catch (IOException ex) { @@ -124,7 +129,7 @@ public class SessionManager private void deleteSession() { - SESSION_FILE.delete(); + sessionFile.delete(); } /** diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index 88c4a2e18a..6e7102920f 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -61,6 +61,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.coords.WorldPoint; @@ -77,7 +78,6 @@ import net.runelite.http.api.config.Configuration; @Slf4j public class ConfigManager { - private static final String SETTINGS_FILE_NAME = "settings.properties"; private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); @Inject @@ -92,11 +92,15 @@ public class ConfigManager private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this); private final Properties properties = new Properties(); private final Map pendingChanges = new HashMap<>(); + private final File settingsFileInput; @Inject - public ConfigManager(ScheduledExecutorService scheduledExecutorService) + public ConfigManager( + @Named("config") File config, + ScheduledExecutorService scheduledExecutorService) { this.executor = scheduledExecutorService; + this.settingsFileInput = config; this.propertiesFile = getPropertiesFile(); executor.scheduleWithFixedDelay(this::sendConfig, 30, 30, TimeUnit.SECONDS); @@ -125,7 +129,7 @@ public class ConfigManager private File getLocalPropertiesFile() { - return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME); + return settingsFileInput; } private File getPropertiesFile() @@ -138,7 +142,7 @@ public class ConfigManager else { File profileDir = new File(RuneLite.PROFILES_DIR, session.getUsername().toLowerCase()); - return new File(profileDir, SETTINGS_FILE_NAME); + return new File(profileDir, RuneLite.DEFAULT_CONFIG_FILE); } } @@ -331,7 +335,7 @@ public class ConfigManager parent.mkdirs(); - File tempFile = new File(parent, SETTINGS_FILE_NAME + ".tmp"); + File tempFile = new File(parent, RuneLite.DEFAULT_CONFIG_FILE + ".tmp"); try (FileOutputStream out = new FileOutputStream(tempFile)) { diff --git a/runelite-client/src/test/java/net/runelite/client/config/ConfigManagerTest.java b/runelite-client/src/test/java/net/runelite/client/config/ConfigManagerTest.java index 14e4b80f06..d98fee4097 100644 --- a/runelite-client/src/test/java/net/runelite/client/config/ConfigManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/config/ConfigManagerTest.java @@ -27,11 +27,14 @@ package net.runelite.client.config; import com.google.inject.Guice; import com.google.inject.testing.fieldbinder.Bind; import com.google.inject.testing.fieldbinder.BoundFieldModule; +import java.io.File; import java.io.IOException; import java.time.Instant; import java.util.UUID; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; +import javax.inject.Named; +import net.runelite.client.RuneLite; import net.runelite.client.account.AccountSession; import net.runelite.client.eventbus.EventBus; import org.junit.Assert; @@ -56,6 +59,14 @@ public class ConfigManagerTest @Bind RuneLiteConfig runeliteConfig; + @Bind + @Named("sessionfile") + File sessionfile = new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_SESSION_FILE); + + @Bind + @Named("config") + File config = new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_CONFIG_FILE); + @Inject ConfigManager manager; diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java index 99c85db67d..8aaaa9ea86 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/PluginManagerTest.java @@ -48,9 +48,9 @@ import java.util.Set; import net.runelite.api.Client; import net.runelite.client.RuneLite; import net.runelite.client.RuneLiteModule; -import net.runelite.client.eventbus.EventBus; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigItem; +import net.runelite.client.eventbus.EventBus; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Rule; @@ -83,7 +83,9 @@ public class PluginManagerTest public void before() throws IOException { Injector injector = Guice.createInjector(Modules - .override(new RuneLiteModule(() -> null, true)) + .override(new RuneLiteModule(() -> null, true, + new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_SESSION_FILE), + new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_CONFIG_FILE))) .with(BoundFieldModule.of(this))); RuneLite.setInjector(injector); @@ -144,7 +146,9 @@ public class PluginManagerTest { List modules = new ArrayList<>(); modules.add(new GraphvizModule()); - modules.add(new RuneLiteModule(() -> null, true)); + modules.add(new RuneLiteModule(() -> null, true, + new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_SESSION_FILE), + new File(RuneLite.RUNELITE_DIR, RuneLite.DEFAULT_CONFIG_FILE))); PluginManager pluginManager = new PluginManager(true, null, null, null, null, null); pluginManager.loadCorePlugins(); diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java index e28f122305..4cb4e18a8f 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/loottracker/LootTrackerPluginTest.java @@ -34,6 +34,7 @@ import net.runelite.api.Client; import net.runelite.api.Player; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; +import net.runelite.client.account.SessionManager; import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.http.api.loottracker.LootRecordType; @@ -72,6 +73,10 @@ public class LootTrackerPluginTest @Bind private LootTrackerConfig lootTrackerConfig; + @Mock + @Bind + private SessionManager sessionManager; + @Before public void setUp() { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/motherlode/MotherlodePluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/motherlode/MotherlodePluginTest.java index 6646ca5aad..3141025604 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/motherlode/MotherlodePluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/motherlode/MotherlodePluginTest.java @@ -39,6 +39,7 @@ import net.runelite.api.Varbits; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.VarbitChanged; +import net.runelite.client.ui.overlay.OverlayManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -87,6 +88,10 @@ public class MotherlodePluginTest @Bind private ScheduledExecutorService scheduledExecutorService; + @Mock + @Bind + private OverlayManager overlayManager; + @Before public void before() { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java index 6b20c0fc3a..58df1cf936 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.client.ui.overlay.OverlayManager; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; @@ -58,6 +59,10 @@ public class NpcIndicatorsPluginTest @Inject private NpcIndicatorsPlugin npcIndicatorsPlugin; + @Mock + @Bind + private OverlayManager overlayManager; + @Before public void setUp() { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java index 01af2080f5..dc03a3e556 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/raids/RaidsPluginTest.java @@ -36,16 +36,18 @@ import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.widgets.WidgetID; +import net.runelite.client.Notifier; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.game.ItemManager; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.ImageCapture; +import net.runelite.client.ws.PartyService; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import net.runelite.client.Notifier; -import net.runelite.client.util.ImageCapture; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -98,6 +100,14 @@ public class RaidsPluginTest @Inject RaidsPlugin raidsPlugin; + @Mock + @Bind + private PartyService partyService; + + @Mock + @Bind + private OverlayManager overlayManager; + @Before public void before() { diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java index 631e94dcde..b7058d4092 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -44,6 +44,7 @@ import net.runelite.client.Notifier; import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.DrawManager; +import net.runelite.client.ui.overlay.OverlayManager; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; @@ -97,6 +98,10 @@ public class ScreenshotPluginTest @Bind ScheduledExecutorService service; + @Mock + @Bind + private OverlayManager overlayManager; + @Before public void before() {