package com.narrowtux.fmm; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.narrowtux.fmm.gui.GuiFiles; import com.narrowtux.fmm.gui.ModsTabController; import com.narrowtux.fmm.gui.SavesTabController; import com.narrowtux.fmm.io.URISchemeHandler; import com.narrowtux.fmm.io.dirwatch.SimpleDirectoryWatchService; import com.narrowtux.fmm.gui.MainWindowController; import com.narrowtux.fmm.gui.SettingsWindowController; import com.narrowtux.fmm.io.tasks.TaskService; import com.narrowtux.fmm.model.Datastore; import com.narrowtux.fmm.util.OS; import com.narrowtux.fmm.util.OSXAppleEventHelper; import com.narrowtux.fmm.util.Util; import javafx.application.Application; import javafx.application.Platform; import javafx.application.Preloader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.stage.Stage; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Base64; public class FactorioModManagerApplication extends Application { private SettingsWindowController settingsWindowController; private Stage settingsStage; @Override public void start(Stage primaryStage) throws Exception { try { Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> { System.out.println("Exception in main thread: " + throwable.getMessage()); }); Datastore store = new Datastore(); // preload all GUIs settingsWindowController = new SettingsWindowController(); Util.preloadFXML(GuiFiles.SETTINGS_WINDOW, settingsWindowController); Util.preloadFXML(GuiFiles.MAIN_WINDOW); Util.preloadFXML(GuiFiles.SAVES_TAB, new SavesTabController()); Util.preloadFXML(GuiFiles.MODS_TAB, new ModsTabController()); Util.preloadFXML(GuiFiles.MODPACKS_TAB); URISchemeHandler schemeHandler = new URISchemeHandler(); schemeHandler.start(getParameters().getRaw().toArray(new String[0])); if (OS.isMac()) { Path applicationSupport = Paths.get(System.getenv("HOME"), "Library/Application Support/"); store.setDataDir(applicationSupport.resolve("factorio/")); store.setFactorioApplication(Paths.get("/Applications/factorio.app")); store.setStorageDir(applicationSupport.resolve("FactorioModManager/")); } else if (OS.isWindows()) { Path appData = Paths.get(System.getenv("AppData")); store.setDataDir(appData.resolve("factorio")); store.setStorageDir(appData.resolve("FactorioModManager")); } else { String xdgConf = System.getenv("XDG_CONFIG_DIR"); String xdgData = System.getenv("XDG_DATA_HOME"); if (xdgConf == null) xdgConf = Paths.get(System.getenv("HOME"), ".config").toString(); if (xdgData == null) xdgData = Paths.get(System.getenv("HOME"), ".local/share").toString(); store.setStorageDir(Paths.get(xdgConf, "FactorioModManager")); store.setDataDir(Paths.get(System.getenv("HOME"), ".factorio")); Path[] possibleExe = { Paths.get("/usr/bin/factorio"), Paths.get(xdgData, "steam/SteamApps/common/Factorio/bin/x64/factorio"), Paths.get(xdgData, "steam/SteamApps/common/Factorio/bin/i386/factorio"), Paths.get(System.getenv("HOME"), "factorio/bin/x64/factorio"), Paths.get(System.getenv("HOME"), "factorio/bin/i386/factorio"), }; for (Path exePath : possibleExe) { if (Files.exists(exePath)) { store.setFactorioApplication(exePath); break; } } } Path settingsPath = store.getStorageDir().resolve("settings.json"); if (Files.exists(settingsPath)) { JsonObject settings = new Gson().fromJson(new FileReader(settingsPath.toFile()), JsonObject.class); if (settings.has("data")) { store.setDataDir(Paths.get(settings.get("data").getAsString())); } if (settings.has("executable")) { store.setFactorioApplication(Paths.get(settings.get("executable").getAsString())); } } else if (!Files.exists(store.getStorageDir())) { Files.createDirectories(store.getStorageDir()); } if (store.getFactorioApplication() == null || store.getDataDir() == null) { loadSettingsWindow(); settingsStage.show(); settingsWindowController.setOnClose(() -> { try { continueStartup(primaryStage, store); } catch (IOException e) { e.printStackTrace(); } }); } else { continueStartup(primaryStage, store); } } catch (Exception e) { e.printStackTrace(); throw e; } } private void loadSettingsWindow() throws IOException { if (settingsStage == null) { Parent settingsRoot = (Parent) Util.loadFXML(GuiFiles.SETTINGS_WINDOW, () -> settingsWindowController).getNode(); settingsStage = new Stage(); settingsStage.setScene(new Scene(settingsRoot)); settingsWindowController.setWindow(settingsStage); } } private void continueStartup(Stage primaryStage, Datastore store) throws IOException { //move mod dir to fmm so it can be managed. if (!Files.exists(store.getFMMDir())) { Files.createDirectory(store.getFMMDir()); Files.move(store.getModDir(), store.getFMMDir().resolve("default")); } if (!Files.exists(store.getFMMDir().resolve("mods"))) { Files.createDirectory(store.getFMMDir().resolve("mods")); } store.scanDirectory(); loadSettingsWindow(); Parent root = (Parent) Util.loadFXML(GuiFiles.MAIN_WINDOW, () -> new MainWindowController(settingsStage)).getNode(); primaryStage.setTitle("Smart Mod Inserter"); primaryStage.setScene(new Scene(root, 450, 320)); primaryStage.show(); Util.clearPreloadThreads(); } @Override public void stop() throws Exception { SimpleDirectoryWatchService.getInstance().stop(); TaskService.getInstance().shutdown(); super.stop(); System.exit(1); } public static void main(String[] args) { launch(args); } }