Skip to content

Commit

Permalink
Merge #4064 Play game option for ConsoleUI
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Mar 22, 2024
2 parents fc6d481 + 864904e commit ae32e5b
Show file tree
Hide file tree
Showing 23 changed files with 113 additions and 90 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
- [GUI] Proportional, granular progress updates for installing (#4055 by: HebaruSan)
- [GUI] Modpack compatibility prompt, GameComparator clean-up (#4056 by: HebaruSan)
- [ConsoleUI] Add downloads column for ConsoleUI (#4063 by: HebaruSan)
- [ConsoleUI] Play game option for ConsoleUI (#4064 by: HebaruSan)

### Bugfixes

Expand Down
30 changes: 30 additions & 0 deletions ConsoleUI/ModListScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re
AddObject(searchBox);
AddObject(moduleList);

AddBinding(Keys.CtrlP, (object sender, ConsoleTheme theme) => PlayGame());
AddBinding(Keys.CtrlQ, (object sender, ConsoleTheme theme) => false);
AddBinding(Keys.AltX, (object sender, ConsoleTheme theme) => false);
AddBinding(Keys.F1, (object sender, ConsoleTheme theme) => Help(theme));
Expand Down Expand Up @@ -279,6 +280,22 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re
));

List<ConsoleMenuOption> opts = new List<ConsoleMenuOption>() {
new ConsoleMenuOption(Properties.Resources.ModListPlayMenu, "",
Properties.Resources.ModListPlayMenuTip,
true, null, null, null, true,
() => new ConsolePopupMenu(
manager.CurrentInstance
.game
.DefaultCommandLines(manager.SteamLibrary,
new DirectoryInfo(manager.CurrentInstance.GameDir()))
.Select((cmd, i) => new ConsoleMenuOption(
cmd,
i == 0 ? $"{Properties.Resources.Ctrl}+P"
: "",
cmd, true,
th => PlayGame(cmd)))
.ToList())),
null,
new ConsoleMenuOption(Properties.Resources.ModListSortMenu, "",
Properties.Resources.ModListSortMenuTip,
true, null, null, moduleList.SortMenu()),
Expand Down Expand Up @@ -432,6 +449,19 @@ private int daysSinceUpdated(string filename)
return (DateTime.Now - File.GetLastWriteTime(filename)).Days;
}

private bool PlayGame()
=> PlayGame(manager.CurrentInstance
.game
.DefaultCommandLines(manager.SteamLibrary,
new DirectoryInfo(manager.CurrentInstance.GameDir()))
.FirstOrDefault());

private bool PlayGame(string commandLine)
{
manager.CurrentInstance.PlayGame(commandLine);
return true;
}

private bool UpdateRegistry(ConsoleTheme theme, bool showNewModsPrompt = true)
{
ProgressScreen ps = new ProgressScreen(
Expand Down
2 changes: 2 additions & 0 deletions ConsoleUI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ If you uninstall it, CKAN will not be able to re-install it.</value></data>
<data name="ModListApplyChangesTip" xml:space="preserve"><value>Apply changes</value></data>
<data name="ModListUpdatedDayAgo" xml:space="preserve"><value>Updated at least {0} day ago</value></data>
<data name="ModListUpdatedDaysAgo" xml:space="preserve"><value>Updated at least {0} days ago</value></data>
<data name="ModListPlayMenu" xml:space="preserve"><value>Play game</value></data>
<data name="ModListPlayMenuTip" xml:space="preserve"><value>Launch the game</value></data>
<data name="ModListSortMenu" xml:space="preserve"><value>Sort...</value></data>
<data name="ModListSortMenuTip" xml:space="preserve"><value>Change the sorting of the list of mods</value></data>
<data name="ModListRefreshMenu" xml:space="preserve"><value>Refresh mod list</value></data>
Expand Down
15 changes: 11 additions & 4 deletions ConsoleUI/Toolkit/ConsolePopupMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public ConsolePopupMenu(List<ConsoleMenuOption> opts)
int len = opt.Caption.Length + (
string.IsNullOrEmpty(opt.Key) ? 0 : 2 + opt.Key.Length
) + (
opt.SubMenu != null ? 3 :
opt.SubMenu != null || opt.SubMenuFunc != null ? 3 :
opt.RadioActive != null ? 4 :
0
);
Expand Down Expand Up @@ -66,7 +66,8 @@ public bool Run(ConsoleTheme theme, int right, int top)
if (options[selectedOption].OnExec != null) {
val = options[selectedOption].OnExec(theme);
}
options[selectedOption].SubMenu?.Run(
(options[selectedOption].SubMenu ?? (options[selectedOption].SubMenuFunc?.Invoke()))
?.Run(
theme,
right - 2,
top + selectedOption + 2);
Expand Down Expand Up @@ -153,7 +154,7 @@ private void DrawFooter(ConsoleTheme theme)
}

private string AnnotatedCaption(ConsoleMenuOption opt)
=> opt.SubMenu != null
=> opt.SubMenu != null || opt.SubMenuFunc != null
? opt.Caption.PadRight(longestLength - 1) + submenuIndicator
: opt.RadioActive != null
? opt.RadioActive()
Expand Down Expand Up @@ -184,9 +185,10 @@ public class ConsoleMenuOption {
/// <param name="radio">If set, this option is a radio button, and this function returns its value</param>
/// <param name="submenu">Submenu to open for this option</param>
/// <param name="enabled">true if this option should be drawn normally and allowed for selection, false to draw it grayed out and not allow selection</param>
/// <param name="submenuFunc">Function to generate submenu to open for this option</param>
public ConsoleMenuOption(string cap, string key, string tt, bool close,
Func<ConsoleTheme, bool> exec = null, Func<bool> radio = null, ConsolePopupMenu submenu = null,
bool enabled = true)
bool enabled = true, Func<ConsolePopupMenu> submenuFunc = null)
{
Caption = cap;
Key = key;
Expand All @@ -196,6 +198,7 @@ public class ConsoleMenuOption {
SubMenu = submenu;
RadioActive = radio;
Enabled = enabled;
SubMenuFunc = submenuFunc;
}

/// <summary>
Expand Down Expand Up @@ -227,6 +230,10 @@ public class ConsoleMenuOption {
/// </summary>
public readonly ConsolePopupMenu SubMenu;
/// <summary>
/// Function to generate submenu to open for this option
/// </summary>
public readonly Func<ConsolePopupMenu> SubMenuFunc;
/// <summary>
/// Function to call to check whether this option is enabled
/// </summary>
public readonly bool Enabled;
Expand Down
7 changes: 7 additions & 0 deletions ConsoleUI/Toolkit/Keys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ public static class Keys {
(char)12, ConsoleKey.Clear, false, false, false
);

/// <summary>
/// Representation of Ctrl+P for key bindings
/// </summary>
public static readonly ConsoleKeyInfo CtrlP = new ConsoleKeyInfo(
(char)16, ConsoleKey.P, false, false, true
);

/// <summary>
/// Representation of Ctrl+Q for key bindings
/// </summary>
Expand Down
40 changes: 40 additions & 0 deletions Core/GameInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,46 @@ public bool HasManagedFiles(Registry registry, string absPath)
&& Directory.EnumerateFileSystemEntries(absPath, "*", SearchOption.AllDirectories)
.Any(f => registry.FileOwner(ToRelativeGameDir(f)) != null));

public void PlayGame(string command, Action onExit = null)
{
var split = (command ?? "").Split(' ');
if (split.Length == 0)
{
return;
}

split = game.AdjustCommandLine(split, Version());
var binary = split[0];
var args = string.Join(" ", split.Skip(1));

try
{
Directory.SetCurrentDirectory(GameDir());
Process p = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = binary,
Arguments = args
},
EnableRaisingEvents = true
};

p.Exited += (sender, e) =>
{
playTime.Stop(CkanDir());
onExit?.Invoke();
};

p.Start();
playTime.Start();
}
catch (Exception exception)
{
User.RaiseError(Properties.Resources.GameInstancePlayGameFailed, exception.Message);
}
}

public override string ToString()
=> string.Format(Properties.Resources.GameInstanceToString, game.ShortName, gameDir);

Expand Down
5 changes: 4 additions & 1 deletion Core/Properties/Resources.fr-FR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ Installez le paquet `mono-complete` ou un équivalent pour votre système d'expl
<data name="GameInstancePathNotFound" xml:space="preserve">
<value>{0} n'existe pas</value>
</data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>Impossible de lancer le jeu.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve">
<value>Téléchargement de {0} ...</value>
</data>
Expand Down Expand Up @@ -582,7 +585,7 @@ Pensez à ajouter un jeton d'authentification pour augmenter la limite avant bri
<data name="KrakenAlreadyRunning" xml:space="preserve">
<value>Fichier verrou avec un ID de processus actif à {0}

Un autre processus CKAN est probablement déjà en train d'accéder à ce dossier de jeu. Si vous êtes sûr que ce fichier verrou est périmé, vous pouvez supprimer ce fichier pour continuer. Mais si ce n'est pas le cas, les deux CKAN risque de rentrer en conflit et corrompre votre registre de mods et votre dossier de jeu.
Un autre processus CKAN est probablement déjà en train d'accéder à ce dossier de jeu. Si vous êtes sûr que ce fichier verrou est périmé, vous pouvez supprimer ce fichier pour continuer. Mais si ce n'est pas le cas, les deux CKAN risque de rentrer en conflit et corrompre votre registre de mods et votre dossier de jeu.

Voulez-vous supprimez ce fichier verrou pour forcer l'accès ?</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.it-IT.resx
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@ Installa il pacchetto `mono-complete` o un pacchetto equivalente per il tuo sist
<data name="GameInstancePathNotFound" xml:space="preserve">
<value>{0} non esiste</value>
</data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>Impossibile avviare il gioco.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve">
<value>Download di "{0}"</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.pl-PL.resx
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ Zainstaluj pakiet `mono-complete` lub pasujący do twojego systemu operacyjnego.
<data name="GameInstancePathNotFound" xml:space="preserve">
<value>{0} nie istnieje</value>
</data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>Nie można uruchomić gry.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve">
<value>Pobieranie "{0}"</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ Install the `mono-complete` package or equivalent for your operating system.</va
<data name="GameInstanceNoValidName" xml:space="preserve"><value>Could not return a valid name for the new instance</value></data>
<data name="GameInstanceByPathName" xml:space="preserve"><value>custom</value></data>
<data name="GameInstancePathNotFound" xml:space="preserve"><value>{0} does not exist</value></data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>Couldn't start game.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve"><value>Downloading {0} ...</value></data>
<data name="ModuleInstallerNothingToInstall" xml:space="preserve"><value>Nothing to install</value></data>
<data name="ModuleInstallerAboutToInstall" xml:space="preserve"><value>About to install:</value></data>
Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.ru-RU.resx
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@
<data name="GameInstanceNoValidName" xml:space="preserve"><value>Не удалось вернуть корректное имя для новой сборки</value></data>
<data name="GameInstanceByPathName" xml:space="preserve"><value>своя</value></data>
<data name="GameInstancePathNotFound" xml:space="preserve"><value>{0} не существует</value></data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>Не удалось запустить игру.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve"><value>Загружается «{0}»</value></data>
<data name="ModuleInstallerNothingToInstall" xml:space="preserve"><value>Нечего устанавливать</value></data>
<data name="ModuleInstallerAboutToInstall" xml:space="preserve"><value>Будут установлены:</value></data>
Expand Down
3 changes: 3 additions & 0 deletions Core/Properties/Resources.zh-CN.resx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@
<data name="GameInstancePathNotFound" xml:space="preserve">
<value>{0} 不存在</value>
</data>
<data name="GameInstancePlayGameFailed" xml:space="preserve"><value>无法启动游戏.

{0}</value></data>
<data name="ModuleInstallerDownloading" xml:space="preserve">
<value>正在下载 "{0}"</value>
</data>
Expand Down
50 changes: 3 additions & 47 deletions GUI/Main/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -979,25 +979,14 @@ private void openGameToolStripMenuItem_Click(object sender, EventArgs e)

private void LaunchGame(string command = null)
{
if (string.IsNullOrEmpty(command))
{
command = configuration.CommandLines.First();
}
var split = command.Split(' ');
if (split.Length == 0)
{
return;
}

var registry = RegistryManager.Instance(CurrentInstance, repoData).registry;

var suppressedIdentifiers = CurrentInstance.GetSuppressedCompatWarningIdentifiers;
var incomp = registry.IncompatibleInstalled(CurrentInstance.VersionCriteria())
.Where(m => !m.Module.IsDLC && !suppressedIdentifiers.Contains(m.identifier))
.ToList();
if (incomp.Any())
{
// Warn that it might not be safe to run Game with incompatible modules installed
// Warn that it might not be safe to run game with incompatible modules installed
string incompatDescrip = incomp
.Select(m => $"{m.Module} ({m.Module.CompatibleGameVersions(CurrentInstance.game)})")
.Aggregate((a, b) => $"{a}{Environment.NewLine}{b}");
Expand All @@ -1022,41 +1011,8 @@ private void LaunchGame(string command = null)
}
}

split = CurrentInstance.game.AdjustCommandLine(split, CurrentInstance.Version());
var binary = split[0];
var args = string.Join(" ", split.Skip(1));

try
{

Directory.SetCurrentDirectory(CurrentInstance.GameDir());

Process p = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = binary,
Arguments = args
},
EnableRaisingEvents = true
};

GameInstance inst = CurrentInstance;
p.Exited += (sender, e) => GameExit(inst);

p.Start();
CurrentInstance.playTime.Start();
}
catch (Exception exception)
{
currentUser.RaiseError(Properties.Resources.MainLaunchFailed, exception.Message);
}
}

private void GameExit(GameInstance inst)
{
inst.playTime.Stop(inst.CkanDir());
UpdateStatusBar();
CurrentInstance.PlayGame(command ?? configuration.CommandLines.First(),
UpdateStatusBar);
}

// This is used by Reinstall
Expand Down
5 changes: 0 additions & 5 deletions GUI/Properties/Resources.de-DE.resx
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,6 @@ Versuche {2} aus {3} zu verschieben und CKAN neu zu starten.</value></data>
</data>
<data name="MainLaunch" xml:space="preserve"><value>Starten</value></data>
<data name="MainLaunchDontShow" xml:space="preserve"><value>Für diese Mods und {0} {1} nicht mehr anzeigen</value></data>
<data name="MainLaunchFailed" xml:space="preserve">
<value>Das Spiel konnte nicht gestartet werden.

{0}</value>
</data>
<data name="MainModPack" xml:space="preserve"><value>CKAN Modpack (*.ckan)</value></data>
<data name="MainPlainText" xml:space="preserve"><value>Klartext (*.txt)</value></data>
<data name="MainNotFound" xml:space="preserve"><value>Nicht gefunden.</value></data>
Expand Down
5 changes: 0 additions & 5 deletions GUI/Properties/Resources.fr-FR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,6 @@ Quelle version souhaitez-vous utiliser ?
<data name="MainLaunch" xml:space="preserve">
<value>Lancement</value>
</data>
<data name="MainLaunchFailed" xml:space="preserve">
<value>Impossible de lancer le jeu.

{0}</value>
</data>
<data name="MainModPack" xml:space="preserve">
<value>Modpack CKAN (*.ckan)</value>
</data>
Expand Down
5 changes: 0 additions & 5 deletions GUI/Properties/Resources.it-IT.resx
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,6 @@ Prova a spostare {2} da {3} e a riavviare CKAN.</value>
<data name="MainLaunch" xml:space="preserve">
<value>Avvia</value>
</data>
<data name="MainLaunchFailed" xml:space="preserve">
<value>Impossibile avviare il gioco.

{0}</value>
</data>
<data name="MainModPack" xml:space="preserve">
<value>Modpack CKAN (*.ckan)</value>
</data>
Expand Down
3 changes: 0 additions & 3 deletions GUI/Properties/Resources.ja-JP.resx
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,6 @@ Try to move {2} out of {3} and restart CKAN.</value></data>

{0}</value></data>
<data name="MainLaunch" xml:space="preserve"><value>起動</value></data>
<data name="MainLaunchFailed" xml:space="preserve"><value>起動に失敗しました。

{0}</value></data>
<data name="MainModPack" xml:space="preserve"><value>CKAN Modパック (*.ckan)</value></data>
<data name="MainPlainText" xml:space="preserve"><value>平文 (*.txt)</value></data>
<data name="MainMarkdown" xml:space="preserve"><value>Markdown (*.md)</value></data>
Expand Down
3 changes: 0 additions & 3 deletions GUI/Properties/Resources.ko-KR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,6 @@
{0}</value></data>
<data name="MainLaunchDontShow" xml:space="preserve"><value>이 모드들에 관해서는 다시 보여주지 않기 {0} {1}</value></data>
<data name="MainLaunch" xml:space="preserve"><value>실행</value></data>
<data name="MainLaunchFailed" xml:space="preserve"><value>게임을 실행할 수 없었어요.

{0}</value></data>
<data name="MainModPack" xml:space="preserve"><value>CKAN 모드팩 (*.ckan)</value></data>
<data name="MainPlainText" xml:space="preserve"><value>일반 텍스트(*.txt)</value></data>
<data name="MainMarkdown" xml:space="preserve"><value>마크다운 (*.md)</value></data>
Expand Down
5 changes: 0 additions & 5 deletions GUI/Properties/Resources.pl-PL.resx
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,6 @@ Spróbuj przenieść {2} z {3} i uruchomić ponownie CKAN.</value>
<data name="MainLaunch" xml:space="preserve">
<value>Uruchom</value>
</data>
<data name="MainLaunchFailed" xml:space="preserve">
<value>Nie można uruchomić gry.

{0}</value>
</data>
<data name="MainModPack" xml:space="preserve">
<value>CKAN modpack (*.ckan)</value>
</data>
Expand Down
Loading

0 comments on commit ae32e5b

Please sign in to comment.