v1.0.13 — Section « Arguments de lancement » indépendante du mode auto

Feature request : jusqu'à v1.0.12, les CLI args passés à PROSERVE_UE_*.exe
n'étaient utilisés QUE dans _config.AutoMode.Args, et seulement pour la
version désignée AUTO. Un opérateur qui voulait des flags globaux appliqués
à TOUS les lancements manuels (ex : -nosplash, -log, -fps=90) devait soit
activer le mode auto sur chaque version manuellement, soit modifier le
raccourci Windows (perdu au prochain install).

Fix : nouvelle section « Arguments de lancement » dans Settings → Avancés,
au-dessus du bloc « Mode auto ». Ces args sont concaténés en PREMIER dans
la ligne de commande passée à Unreal ; les args du mode auto s'ajoutent
DERRIÈRE quand la version courante est celle marquée AUTO.

Sémantique de merge :
  • Non-auto (comportement neuf) : cliArgs = DefaultLaunchArgs
  • Auto (comportement étendu)    : cliArgs = DefaultLaunchArgs + AutoMode.Args
  • Doublons de clé : Unreal FParse prend la dernière occurrence — les
    auto args écrasent silencieusement un default homonyme. Voulu (ex :
    -fps=90 en default, -fps=120 en auto).

Impl :
  • Model : LocalConfig.DefaultLaunchArgs (List<AutoModeArg>, reuse du type
    existant). Empty par défaut → rétro-compat total.
  • MainViewModel.LaunchVersion : composition de argList (default puis auto).
  • SettingsViewModel : nouvelle ObservableCollection DefaultLaunchArgs +
    AddDefaultLaunchArgCommand + Save/Load persistence.
  • SettingsDialog.xaml : nouvelle carte au-dessus d'AutoMode, patron
    identique (Key + Value + Remove par ligne + bouton Ajouter).
  • Strings.cs : SettingsLaunchArgs + SettingsLaunchArgsHelp (FR/EN/CN/TH/
    AR/ES/DE).

Rétro-compat : configs existantes qui n'ont pas le field DefaultLaunchArgs
en JSON → deserialize en List vide → cliArgs = null sur launch manuel (=
comportement d'avant, identique).

Bump : 1.0.12 → 1.0.13 (nouvelle feature UI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 12:30:06 +02:00
parent f8af338faf
commit e673b1954c
7 changed files with 139 additions and 8 deletions

View File

@@ -11,7 +11,7 @@
#define MyAppName "PROSERVE Launcher"
#define MyAppShortName "PS_Launcher"
#define MyAppVersion "1.0.12"
#define MyAppVersion "1.0.13"
#define MyAppPublisher "ASTERION VR"
#define MyAppURL "https://asterionvr.com"
#define MyAppExeName "PS_Launcher.exe"

View File

@@ -18,9 +18,9 @@
<Product>PROSERVE Launcher</Product>
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
<RootNamespace>PSLauncher.App</RootNamespace>
<Version>1.0.12</Version>
<AssemblyVersion>1.0.12.0</AssemblyVersion>
<FileVersion>1.0.12.0</FileVersion>
<Version>1.0.13</Version>
<AssemblyVersion>1.0.13.0</AssemblyVersion>
<FileVersion>1.0.13.0</FileVersion>
<!-- Single-file self-contained publish profile (used by `dotnet publish`) -->
<PublishSingleFile>true</PublishSingleFile>

View File

@@ -1186,13 +1186,22 @@ public sealed partial class MainViewModel : ObservableObject
try
{
// Si on lance la version désignée comme "auto", on passe les CLI args
// configurés (ex: -autoconnect -login=Jerome2 -password=… -ipserver=10.0.4.100).
// Pour les lancements manuels d'autres versions, args = null (comportement standard).
// Composition des CLI args passés à PROSERVE_UE_*.exe :
// 1. _config.DefaultLaunchArgs — appliqués à CHAQUE lancement (auto ou manuel).
// Contenu type : -nosplash, -log, -fps=90.
// 2. _config.AutoMode.Args — appliqués UNIQUEMENT si la version lancée est la
// version auto désignée. Contenu type : -autoconnect, -login=Jerome,
// -password=…, -ipserver=10.0.4.100.
// Concaténation dans cet ordre → Unreal FParse lit dans l'ordre, la dernière
// occurrence d'une clé gagne : les auto args écrasent les default args sur un
// même key (comportement intentionnel : un opérateur peut avoir -fps=90 en
// default et -fps=120 en auto sans conflit).
var isAutoVersion = _config.AutoMode.FeatureEnabled
&& !string.IsNullOrEmpty(_config.AutoMode.SelectedVersion)
&& string.Equals(_config.AutoMode.SelectedVersion, row.Version, StringComparison.Ordinal);
string[]? cliArgs = isAutoVersion ? BuildAutoModeCliArgs(_config.AutoMode.Args) : null;
var argList = new List<AutoModeArg>(_config.DefaultLaunchArgs);
if (isAutoVersion) argList.AddRange(_config.AutoMode.Args);
string[]? cliArgs = argList.Count > 0 ? BuildAutoModeCliArgs(argList) : null;
var proc = _processLauncher.Launch(row.Installed, cliArgs);
_runningProserve = proc;

View File

@@ -129,6 +129,10 @@ public sealed partial class SettingsViewModel : ObservableObject
public System.Collections.ObjectModel.ObservableCollection<string> LanDiscoveredPeers { get; } = new();
public bool HasLanDiscoveredPeers => LanDiscoveredPeers.Count > 0;
// ----- Args par défaut (chaque lancement) -----
/// <summary>Args édités dans la UI. Persiste vers <c>_config.DefaultLaunchArgs</c> au Save.</summary>
public System.Collections.ObjectModel.ObservableCollection<AutoModeArgRowViewModel> DefaultLaunchArgs { get; } = new();
// ----- Mode auto -----
[ObservableProperty] private bool _autoModeFeatureEnabled;
[ObservableProperty] private int _autoModeGraceSeconds;
@@ -276,6 +280,9 @@ public sealed partial class SettingsViewModel : ObservableObject
Environment.NewLine,
config.SteamVr.ProcessesToKill ?? new List<string>());
foreach (var a in config.DefaultLaunchArgs ?? new List<AutoModeArg>())
DefaultLaunchArgs.Add(new AutoModeArgRowViewModel(a.Key, a.Value, RemoveDefaultLaunchArg));
_autoModeFeatureEnabled = config.AutoMode.FeatureEnabled;
_autoModeGraceSeconds = config.AutoMode.GracePeriodSeconds;
_autoModeSelectedVersion = config.AutoMode.SelectedVersion ?? string.Empty;
@@ -465,6 +472,15 @@ public sealed partial class SettingsViewModel : ObservableObject
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
_config.DefaultLaunchArgs = DefaultLaunchArgs
.Select(r => new AutoModeArg
{
Key = (r.Key ?? string.Empty).Trim(),
Value = string.IsNullOrEmpty(r.Value) ? null : r.Value.Trim(),
})
.Where(a => !string.IsNullOrWhiteSpace(a.Key))
.ToList();
_config.AutoMode.FeatureEnabled = AutoModeFeatureEnabled;
_config.AutoMode.GracePeriodSeconds = Math.Clamp(AutoModeGraceSeconds, 1, 60);
_config.AutoMode.SelectedVersion = string.IsNullOrWhiteSpace(AutoModeSelectedVersion)
@@ -1057,6 +1073,19 @@ public sealed partial class SettingsViewModel : ObservableObject
}
}
// ===================== DEFAULT LAUNCH ARGS =====================
[RelayCommand]
private void AddDefaultLaunchArg()
{
DefaultLaunchArgs.Add(new AutoModeArgRowViewModel(string.Empty, null, RemoveDefaultLaunchArg));
}
private void RemoveDefaultLaunchArg(AutoModeArgRowViewModel row)
{
DefaultLaunchArgs.Remove(row);
}
// ===================== AUTO MODE ARGS =====================
[RelayCommand]

View File

@@ -696,6 +696,68 @@
</StackPanel>
</Border>
<!-- Args par défaut : appliqués à CHAQUE lancement de PROSERVE, mode
auto ou pas. Utile pour des flags globaux (ex : -nosplash, -log,
-fps=90) qui doivent s'appliquer quelle que soit la version lancée
manuellement. Les args du mode auto (bloc suivant) s'ajoutent en
plus, uniquement quand la version courante est celle désignée AUTO. -->
<Border Background="{StaticResource Brush.Bg.Card}"
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"
CornerRadius="6" Padding="20" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="{x:Static loc:Strings.SettingsLaunchArgs}"
FontSize="11" FontWeight="Bold"
Foreground="{StaticResource Brush.Text.Secondary}"
Margin="0,0,0,8" />
<TextBlock Text="{x:Static loc:Strings.SettingsLaunchArgsHelp}"
FontSize="12"
Foreground="{StaticResource Brush.Text.Secondary}"
TextWrapping="Wrap"
Margin="0,0,0,10" />
<!-- Liste éditable identique à celle du mode auto : Key + Value + Remove. -->
<ItemsControl ItemsSource="{Binding DefaultLaunchArgs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Text="{Binding Key, UpdateSourceTrigger=PropertyChanged}"
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
FontFamily="Consolas"
Tag="{x:Static loc:Strings.SettingsAutoModeArgKey}"
ToolTip="{x:Static loc:Strings.SettingsAutoModeArgKey}" />
<TextBox Grid.Column="1"
Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
FontFamily="Consolas"
Margin="6,0,6,0"
Tag="{x:Static loc:Strings.SettingsAutoModeArgValue}"
ToolTip="{x:Static loc:Strings.SettingsAutoModeArgValue}" />
<Button Grid.Column="2"
Style="{StaticResource SecondaryButton}"
Content="{x:Static loc:Strings.SettingsAutoModeArgRemove}"
Command="{Binding RemoveCommand}"
Padding="10,6" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Style="{StaticResource SecondaryButton}"
Content="{x:Static loc:Strings.SettingsAutoModeArgAdd}"
Command="{Binding AddDefaultLaunchArgCommand}"
HorizontalAlignment="Left"
Margin="0,4,0,0" Padding="12,6" />
</StackPanel>
</Border>
<!-- Mode auto : auto-launch + auto-relaunch d'une version désignée -->
<Border Background="{StaticResource Brush.Bg.Card}"
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1"

View File

@@ -990,6 +990,26 @@ public static class Strings
"هناك نسخة من PROSERVE قيد التشغيل بالفعل. يرفض المشغل بدء نسخة ثانية لتجنب التعارضات (الجلسات، المنافذ، الملفات المقفلة).\n\nأغلق النسخة الحالية قبل بدء أخرى."
);
// ---- Section Settings → Avancés → Arguments de lancement (défauts appliqués partout) ----
public static string SettingsLaunchArgs => T(
"ARGUMENTS DE LANCEMENT",
"LAUNCH ARGUMENTS",
"启动参数",
"อาร์กิวเมนต์การเปิด",
"وسائط التشغيل",
"ARGUMENTOS DE INICIO",
"STARTARGUMENTE"
);
public static string SettingsLaunchArgsHelp => T(
"Arguments CLI appliqués à CHAQUE lancement de PROSERVE (mode auto ou manuel). Les arguments du mode auto ci-dessous s'ajoutent en plus, uniquement pour la version désignée AUTO.",
"CLI arguments applied to EVERY PROSERVE launch (auto or manual). Auto mode arguments below are added on top, only for the version marked AUTO.",
"应用于每次 PROSERVE 启动的 CLI 参数(自动或手动)。下方的自动模式参数仅对标记为 AUTO 的版本额外附加。",
"อาร์กิวเมนต์ CLI ที่ใช้กับการเปิด PROSERVE ทุกครั้ง (อัตโนมัติหรือด้วยตนเอง) อาร์กิวเมนต์โหมดอัตโนมัติด้านล่างจะเพิ่มเฉพาะสำหรับเวอร์ชันที่ตั้งเป็น AUTO",
"وسائط CLI مطبقة على كل تشغيل لـ PROSERVE (تلقائي أو يدوي). وسائط الوضع التلقائي أدناه تُضاف فقط للنسخة المحددة AUTO.",
"Argumentos CLI aplicados a CADA inicio de PROSERVE (auto o manual). Los argumentos del modo auto de abajo se añaden encima solo para la versión marcada AUTO.",
"CLI-Argumente, die bei JEDEM Start von PROSERVE angewendet werden (Auto oder manuell). Die Auto-Modus-Argumente unten werden nur für die als AUTO markierte Version zusätzlich angehängt."
);
// ---- Section Settings → Avancés → Mode auto ----
public static string SettingsAutoMode => T("MODE AUTO", "AUTO MODE", "自动模式", "โหมดอัตโนมัติ", "الوضع التلقائي");
public static string SettingsAutoModeFeatureEnabled => T(

View File

@@ -7,6 +7,17 @@ public sealed class LocalConfig
public string InstallRoot { get; set; } = string.Empty;
public string? LastLaunchedVersion { get; set; }
/// <summary>
/// Arguments CLI appliqués à CHAQUE lancement de PROSERVE (mode auto ou manuel).
/// Format identique à <see cref="AutoModeConfig.Args"/> : flag <c>-{Key}</c> si
/// <c>Value</c> null/vide, sinon <c>-{Key}={Value}</c>. Concaténés en premier ;
/// si la version lancée est aussi la version auto, les <see cref="AutoModeConfig.Args"/>
/// s'ajoutent DERRIÈRE (Unreal <c>FParse</c> lit dans l'ordre — la dernière occurrence
/// gagne sur un même key). Éditable dans Settings → « Arguments de lancement ».
/// Exemples typiques : <c>-nosplash</c>, <c>-log</c>, <c>-fps=90</c>.
/// </summary>
public List<AutoModeArg> DefaultLaunchArgs { get; set; } = new();
/// <summary>
/// Code de langue de l'UI : "auto" (suit la langue Windows), "fr", "en",
/// "zh", "th" ou "ar". Tout changement nécessite un redémarrage du launcher.