diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 694d355b9..250c00cfb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -40,7 +40,10 @@ import org.jackhuang.hmcl.ui.LogWindow; import org.jackhuang.hmcl.ui.construct.DialogCloseEvent; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.Log4jLevel; +import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.Pair; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.function.ExceptionalSupplier; import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter; import org.jackhuang.hmcl.util.platform.CommandBuilder; @@ -62,39 +65,58 @@ import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class LauncherHelper { - public static final LauncherHelper INSTANCE = new LauncherHelper(); - private LauncherHelper(){} - public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); + private final Profile profile; + private final Account account; + private final String selectedVersion; + private File scriptFile; + private final VersionSetting setting; + private LauncherVisibility launcherVisibility; + private boolean showLogs; + + public LauncherHelper(Profile profile, Account account, String selectedVersion) { + this.profile = Objects.requireNonNull(profile); + this.account = Objects.requireNonNull(account); + this.selectedVersion = Objects.requireNonNull(selectedVersion); + this.setting = profile.getVersionSetting(selectedVersion); + this.launcherVisibility = setting.getLauncherVisibility(); + this.showLogs = setting.isShowLogs(); + } + private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(it -> {}); - public void launch(Profile profile, Account account, String selectedVersion, File scriptFile) { - if (account == null) - throw new IllegalArgumentException("No account"); + public void setTestMode() { + launcherVisibility = LauncherVisibility.KEEP; + showLogs = true; + } + public void launch() { Logging.LOG.info("Launching game version: " + selectedVersion); GameRepository repository = profile.getRepository(); - Version version = repository.getResolvedVersion(selectedVersion); - VersionSetting setting = profile.getVersionSetting(selectedVersion); Platform.runLater(() -> { try { checkGameState(profile, setting, version, () -> { Controllers.dialog(launchingStepsPane); - Schedulers.newThread().schedule(() -> launch0(profile, account, selectedVersion, scriptFile)); + Schedulers.newThread().schedule(this::launch0); }); } catch (InterruptedException ignore) { } }); } - private void launch0(Profile profile, Account account, String selectedVersion, File scriptFile) { + public void makeLaunchScript(File scriptFile) { + this.scriptFile = Objects.requireNonNull(scriptFile); + + launch(); + } + + private void launch0() { HMCLGameRepository repository = profile.getRepository(); DefaultDependencyManager dependencyManager = profile.getDependency(); Version version = MaintainTask.maintain(repository.getResolvedVersion(selectedVersion)); - VersionSetting setting = profile.getVersionSetting(selectedVersion); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) @@ -134,7 +156,7 @@ public final class LauncherHelper { selectedVersion, variables.get("account"), setting.toLaunchOptions(profile.getGameDir()), - setting.getLauncherVisibility() == LauncherVisibility.CLOSE + launcherVisibility == LauncherVisibility.CLOSE ? null // Unnecessary to start listening to game process output when close launcher immediately after game launched. : new HMCLProcessListener(variables.get("account"), setting, gameVersion.isPresent()) )); @@ -154,7 +176,7 @@ public final class LauncherHelper { if (scriptFile == null) { ManagedProcess process = variables.get(LaunchTask.LAUNCH_ID); PROCESSES.add(process); - if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) + if (launcherVisibility == LauncherVisibility.CLOSE) Launcher.stopApplication(); else launchingStepsPane.setCancel(it -> { @@ -337,11 +359,6 @@ public final class LauncherHelper { onAccept.run(); } - public static void stopManagedProcesses() { - while (!PROCESSES.isEmpty()) - Optional.ofNullable(PROCESSES.poll()).ifPresent(ManagedProcess::stop); - } - public void emitStatus(LoadingState state) { if (state == LoadingState.DONE) { launchingStepsPane.fireEvent(new DialogCloseEvent()); @@ -351,8 +368,8 @@ public final class LauncherHelper { launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length); } - private void checkExit(LauncherVisibility v) { - switch (v) { + private void checkExit() { + switch (launcherVisibility) { case HIDE_AND_REOPEN: Platform.runLater(Controllers.getStage()::show); break; @@ -401,7 +418,6 @@ public final class LauncherHelper { private final VersionSetting setting; private final Map forbiddenTokens; - private final LauncherVisibility visibility; private ManagedProcess process; private boolean lwjgl; private LogWindow logWindow; @@ -422,7 +438,6 @@ public final class LauncherHelper { pair(authInfo.getUsername(), "") ); - visibility = setting.getLauncherVisibility(); logs = new LinkedList<>(); } @@ -430,7 +445,7 @@ public final class LauncherHelper { public void setProcess(ManagedProcess process) { this.process = process; - if (setting.isShowLogs()) + if (showLogs) Platform.runLater(() -> { logWindow = new LogWindow(); logWindow.show(); @@ -453,7 +468,7 @@ public final class LauncherHelper { if (logs.size() > config().getLogLines()) logs.removeFirst(); - if (setting.isShowLogs()) { + if (showLogs) { try { latch.await(); logWindow.waitForLoaded(); @@ -467,7 +482,7 @@ public final class LauncherHelper { if (!lwjgl && (log.contains("LWJGL Version: ") || !detectWindow)) { lwjgl = true; - switch (visibility) { + switch (launcherVisibility) { case HIDE_AND_REOPEN: Platform.runLater(() -> { Controllers.getStage().hide(); @@ -518,8 +533,14 @@ public final class LauncherHelper { }); }); - checkExit(visibility); + checkExit(); } } + + public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); + public static void stopManagedProcesses() { + while (!PROCESSES.isEmpty()) + Optional.ofNullable(PROCESSES.poll()).ifPresent(ManagedProcess::stop); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItem.java index 56be39904..62a07fd40 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItem.java @@ -17,13 +17,12 @@ */ package org.jackhuang.hmcl.ui.versions; -import javafx.beans.property.*; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.scene.control.Control; import javafx.scene.control.Skin; import javafx.scene.control.ToggleGroup; - import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.ui.Controllers; public class GameListItem extends Control { private final Profile profile; @@ -83,7 +82,7 @@ public class GameListItem extends Control { } public void launch() { - Versions.launch(profile, version); + Versions.testGame(profile, version); } public void modifyGameSettings() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index cafe976b9..5e7c9037b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -63,7 +63,7 @@ public class GameListItemSkin extends SkinBase { new MenuSeparator(), new IconedMenuItem(FXUtils.limitingSize(SVG.folderOpen(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("folder.game"), FXUtils.withJFXPopupClosing(skinnable::browse, popup)), new MenuSeparator(), - new IconedMenuItem(FXUtils.limitingSize(SVG.launch(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.launch"), FXUtils.withJFXPopupClosing(skinnable::launch, popup)), + new IconedMenuItem(FXUtils.limitingSize(SVG.launch(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.launch.test"), FXUtils.withJFXPopupClosing(skinnable::launch, popup)), new IconedMenuItem(FXUtils.limitingSize(SVG.script(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.launch_script"), FXUtils.withJFXPopupClosing(skinnable::generateLaunchScript, popup))); HBox right = new HBox(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index 53c135101..b37dbb536 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -101,11 +101,8 @@ public class Versions { } public static void generateLaunchScript(Profile profile, String id) { - GameRepository repository = profile.getRepository(); - - if (Accounts.getSelectedAccount() == null) - Controllers.dialog(i18n("login.empty_username")); - else { + if (checkForLaunching(profile, id)) { + GameRepository repository = profile.getRepository(); FileChooser chooser = new FileChooser(); if (repository.getRunDirectory(id).isDirectory()) chooser.setInitialDirectory(repository.getRunDirectory(id)); @@ -115,17 +112,31 @@ public class Versions { : new FileChooser.ExtensionFilter(i18n("extension.sh"), "*.sh")); File file = chooser.showSaveDialog(Controllers.getStage()); if (file != null) - LauncherHelper.INSTANCE.launch(profile, Accounts.getSelectedAccount(), id, file); + new LauncherHelper(profile, Accounts.getSelectedAccount(), id).makeLaunchScript(file); } } public static void launch(Profile profile, String id) { + if (checkForLaunching(profile, id)) + new LauncherHelper(profile, Accounts.getSelectedAccount(), id).launch(); + } + + public static void testGame(Profile profile, String id) { + if (checkForLaunching(profile, id)) { + LauncherHelper helper = new LauncherHelper(profile, Accounts.getSelectedAccount(), id); + helper.setTestMode(); + helper.launch(); + } + } + + private static boolean checkForLaunching(Profile profile, String id) { if (Accounts.getSelectedAccount() == null) Controllers.getLeftPaneController().checkAccount(); - else if (id == null) + else if (id == null || !profile.getRepository().isLoaded() || !profile.getRepository().hasVersion(id)) Controllers.dialog(i18n("version.empty.launch")); else - LauncherHelper.INSTANCE.launch(profile, Accounts.getSelectedAccount(), id, null); + return true; + return false; } public static void modifyGlobalSettings(Profile profile) { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index f813584ef..ced51b096 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -368,6 +368,7 @@ version.game.old=Old version.game.release=Release version.game.snapshot=Snapshot version.launch=Play +version.launch.test=Test Game version.launch_script=Make Launching Script version.launch_script.failed=Unable to make launch script. version.launch_script.save=Save the launch script diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index efaa87d5d..af9740203 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -368,6 +368,7 @@ version.game.old=老舊版本 version.game.release=穩定版本 version.game.snapshot=測試版本 version.launch=啟動遊戲 +version.launch.test=測試遊戲 version.launch_script=生成啟動腳本 version.launch_script.failed=生成啟動腳本失敗 version.launch_script.save=儲存啟動腳本 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 36e19eeaa..24dc5a3e6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -368,6 +368,7 @@ version.game.old=远古版 version.game.release=稳定版 version.game.snapshot=测试版 version.launch=启动游戏 +version.launch.test=测试游戏 version.launch_script=生成启动脚本 version.launch_script.failed=生成启动脚本失败 version.launch_script.save=保存启动脚本 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/SelectedItemProperties.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/SelectedItemProperties.java index 7abd3689c..3cc1392ff 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/SelectedItemProperties.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/javafx/SelectedItemProperties.java @@ -54,7 +54,7 @@ public final class SelectedItemProperties { return new ReadWriteComposedProperty<>(bean, "extra.selectedItem", MultiStepBinding.of(modelProperty) .flatMap(SelectionModel::selectedItemProperty), - modelProperty.getValue()::select); + obj -> modelProperty.getValue().select(obj)); } // ====