package it.paspiz85.nanobot.ui; import it.paspiz85.nanobot.exception.BotConfigurationException; import it.paspiz85.nanobot.game.Troop; import it.paspiz85.nanobot.logic.Looper; import it.paspiz85.nanobot.platform.Platform; import it.paspiz85.nanobot.scripting.ScriptManager; import it.paspiz85.nanobot.util.BuildInfo; import it.paspiz85.nanobot.util.Settings; import it.paspiz85.nanobot.util.Utils; import java.util.Locale; import java.util.Set; import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.concurrent.Worker.State; /** * Bot model. * * @author paspiz85 * */ public final class Model { public static Model instance() { return Utils.singleton(Model.class, () -> new Model()); } protected final Logger logger = Logger.getLogger(getClass().getName()); private final Looper looper = Looper.instance(); private String lastRunnedScript; private String runningScript; private Service<Void> runningService; private Service<Void> scriptService; private Model() { } public void checkForUpdate(final Runnable updateUI) { final Thread checkForUpdateThread = new Thread(() -> { while (true) { try { if (BuildInfo.instance().checkForUpdate() != null) { updateUI.run(); } Thread.sleep(6 * 60 * 60000); } catch (final Exception e) { logger.log(Level.FINE, "checkForUpdate failed", e); } } }, "checkForUpdateThread"); checkForUpdateThread.setDaemon(true); checkForUpdateThread.start(); } public Troop[] getAvailableTroops() { return Settings.instance().getAvailableTroops(); } public String getLastRunnedScript() { return lastRunnedScript; } public String getRunningScript() { return runningScript; } public Set<String> getScripts() { return ScriptManager.instance().getScripts(); } public void initialize(final BooleanSupplier autoAdjustResolution, final Runnable updateUI) { if (autoAdjustResolution == null) { throw new NullPointerException("autoAdjustResolution not provided"); } if (updateUI == null) { throw new NullPointerException("updateUI not provided"); } // set system locale to ROOT, Turkish clients will break because // jnativehook dependency has Turkish I bug Locale.setDefault(Locale.ROOT); initRunningService(autoAdjustResolution, updateUI); initScriptService(updateUI); } private void initRunningService(final BooleanSupplier autoAdjustResolution, final Runnable updateUI) { runningService = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { @Override protected Void call() throws Exception { looper.start(autoAdjustResolution, updateUI); return null; } }; } }; runningService.setOnCancelled(event -> { runningService.reset(); logger.warning("Running is cancelled"); }); runningService.setOnFailed(event -> { runningService.reset(); logger.warning("Running is failed"); }); } private void initScriptService(final Runnable updateUI) { scriptService = new Service<Void>() { @Override protected Task<Void> createTask() { return new Task<Void>() { @Override protected Void call() throws Exception { updateUI.run(); try { Platform.instance().init(); } catch (final BotConfigurationException e) { logger.log(Level.WARNING, e.getMessage(), e); } ScriptManager.instance().run(runningScript); return null; } }; } }; scriptService.setOnCancelled(event -> { scriptService.reset(); runningScript = null; updateUI.run(); logger.warning("Script is cancelled"); }); scriptService.setOnFailed(event -> { scriptService.reset(); runningScript = null; updateUI.run(); logger.warning("Script is failed"); }); scriptService.setOnSucceeded(event -> { scriptService.reset(); runningScript = null; updateUI.run(); logger.log(Level.INFO, "Script is succeeded"); }); } public boolean isRunning() { return looper.isRunning(); } public boolean isScriptRunning() { return this.runningScript != null; } public Settings loadSettings() { return Settings.instance(); } public void runScript(final String script) throws IllegalAccessException { if (this.runningScript != null) { throw new IllegalAccessException("Wait the previous script"); } this.runningScript = script; if (scriptService.getState() == State.READY) { scriptService.start(); } this.lastRunnedScript = script; } public void saveSettings(final Consumer<Settings> consumer) { final Settings settings = Settings.instance(); consumer.accept(settings); settings.save(); } public void start() { if (runningService.getState() == State.READY) { runningService.start(); } } public void stop() { looper.stop(); if (runningService.isRunning()) { runningService.cancel(); } runningService.reset(); if (scriptService.isRunning()) { scriptService.cancel(); } scriptService.reset(); } }