Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Fronter.NET.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Outputtable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Patreon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=playset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=playsets/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Playsets/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
119 changes: 38 additions & 81 deletions Fronter.NET/Models/Configuration/Config.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using Avalonia.Controls.ApplicationLifetimes;
using commonItems;
using Fronter.Models.Configuration.Options;
using Fronter.Models.Database;
using Fronter.Services;
using Fronter.ViewModels;
using log4net;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;

Expand All @@ -19,8 +22,9 @@
public string SourceGame { get; private set; } = string.Empty;
public string TargetGame { get; private set; } = string.Empty;
public string? SentryDsn { get; private set; }
public string? ModAutoGenerationSource { get; private set; } = null;
public ObservableCollection<Mod> AutoLocatedMods { get; } = [];
public bool TargetPlaysetSelectionEnabled { get; private set; } = false;
public ObservableCollection<Playset> AutoLocatedPlaysets { get; } = [];
public Playset? SelectedPlayset { get; set; }
public bool CopyToTargetGameModDirectory { get; set; } = true;
public ushort ProgressOnCopyingComplete { get; set; } = 109;
public bool UpdateCheckerEnabled { get; private set; } = false;
Expand Down Expand Up @@ -87,7 +91,9 @@
parser.RegisterKeyword("displayName", reader => DisplayName = reader.GetString());
parser.RegisterKeyword("sourceGame", reader => SourceGame = reader.GetString());
parser.RegisterKeyword("targetGame", reader => TargetGame = reader.GetString());
parser.RegisterKeyword("autoGenerateModsFrom", reader => ModAutoGenerationSource = reader.GetString());
parser.RegisterKeyword("targetPlaysetSelectionEnabled", reader => {
TargetPlaysetSelectionEnabled = reader.GetBool();
});
parser.RegisterKeyword("copyToTargetGameModDirectory", reader => {
CopyToTargetGameModDirectory = reader.GetString().Equals("true");
});
Expand All @@ -112,8 +118,8 @@

private void RegisterPreloadKeys(Parser parser) {
parser.RegisterRegex(CommonRegexes.String, (reader, incomingKey) => {
var valueStringOfItem = reader.GetStringOfItem();
var valueStr = valueStringOfItem.ToString().RemQuotes();
StringOfItem valueStringOfItem = reader.GetStringOfItem();
string valueStr = valueStringOfItem.ToString().RemQuotes();
var valueReader = new BufferedReader(valueStr);

foreach (var folder in RequiredFolders) {
Expand All @@ -137,13 +143,6 @@
option.SetCheckBoxSelectorPreloaded();
}
}
if (incomingKey.Equals("selectedMods")) {
var theList = valueReader.GetStrings();
var matchingMods = AutoLocatedMods.Where(m => theList.Contains(m.FileName, StringComparer.Ordinal));
foreach (var mod in matchingMods) {
mod.Enabled = true;
}
}
});
parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreAndLogItem);
}
Expand Down Expand Up @@ -173,7 +172,7 @@
if (uint.TryParse(folder.SteamGameId, out uint steamId)) {
possiblePath = CommonFunctions.GetSteamInstallPath(steamId);
}
if (possiblePath is null && long.TryParse(folder.GOGGameId, out long gogId)) {
if (possiblePath is null && long.TryParse(folder.GOGGameId, CultureInfo.InvariantCulture, out long gogId)) {
possiblePath = CommonFunctions.GetGOGInstallPath(gogId);
}

Expand All @@ -192,10 +191,6 @@
if (Directory.Exists(initialValue)) {
folder.Value = initialValue;
}

if (folder.Name.Equals(ModAutoGenerationSource)) {
AutoLocateMods();
}
}
}

Expand Down Expand Up @@ -258,11 +253,11 @@
var outConfPath = Path.Combine(ConverterFolder, "configuration.txt");
try {
using var writer = new StreamWriter(outConfPath);

WriteRequiredFolders(writer);
WriteRequiredFiles(writer);

if (ModAutoGenerationSource is not null) {
WriteSelectedMods(writer);
if (SelectedPlayset is not null) {
writer.WriteLine($"selectedPlayset = {SelectedPlayset.Id}");
}

WriteOptions(writer);
Expand All @@ -276,17 +271,6 @@
}
}

private void WriteSelectedMods(StreamWriter writer) {
writer.WriteLine("selectedMods = {");
foreach (var mod in AutoLocatedMods) {
if (mod.Enabled) {
writer.WriteLine($"\t\"{mod.FileName}\"");
}
}

writer.WriteLine("}");
}

private void WriteOptions(StreamWriter writer) {
foreach (var option in Options) {
if (option.CheckBoxSelector is not null) {
Expand Down Expand Up @@ -332,60 +316,33 @@
}
}

public void AutoLocateMods() {
logger.Debug("Clearing previously located mods...");
AutoLocatedMods.Clear();
logger.Debug("Autolocating mods...");

// Do we have a mod path?
string? modPath = null;
foreach (var folder in RequiredFolders) {
if (folder.Name.Equals(ModAutoGenerationSource)) {
modPath = folder.Value;
}
}
if (modPath is null) {
logger.Warn("No folder found as source for mods autolocation.");
return;
}

// Does it exist?
if (!Directory.Exists(modPath)) {
logger.Warn($"Mod path \"{modPath}\" does not exist or can not be accessed!");
return;
}

// Are we looking at documents directory?
var combinedPath = Path.Combine(modPath, "mod");
if (Directory.Exists(combinedPath)) {
modPath = combinedPath;
}
logger.Debug($"Mods autolocation path set to: \"{modPath}\"");

// Are there mods inside?
List<string> validModFiles = GetValidModFiles(modPath);

if (validModFiles.Count == 0) {
logger.Debug($"No mod files could be found in \"{modPath}\"");
return;
public string? TargetGameModsPath {
get {
var targetGameModPath = RequiredFolders
.FirstOrDefault(f => f?.Name == "targetGameModPath", defaultValue: null);

Check warning on line 322 in Fronter.NET/Models/Configuration/Config.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

Check warning on line 322 in Fronter.NET/Models/Configuration/Config.cs

View workflow job for this annotation

GitHub Actions / build (macos-15)

Check warning on line 322 in Fronter.NET/Models/Configuration/Config.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

Check warning on line 322 in Fronter.NET/Models/Configuration/Config.cs

View workflow job for this annotation

GitHub Actions / test (macos-15)

return targetGameModPath?.Value;
}
}

foreach (var modFile in validModFiles) {
var path = Path.Combine(modPath, modFile);
Mod theMod;
try {
theMod = new Mod(path);
} catch (IOException ex) {
logger.Warn($"Failed to parse mod file {modFile}: {ex.Message}");
continue;
}
if (string.IsNullOrEmpty(theMod.Name)) {
logger.Warn($"Mod at \"{path}\" has no defined name, skipping.");
continue;
public void AutoLocatePlaysets() {
logger.Debug("Clearing previously located playsets...");
AutoLocatedPlaysets.Clear();
logger.Debug("Autolocating playsets...");

var destModsFolder = TargetGameModsPath;
var locatedPlaysetsCount = 0;
if (destModsFolder is not null) {
var dbContext = TargetDbManager.GetLauncherDbContext(this);
if (dbContext is not null) {
foreach (var playset in dbContext.Playsets.Where(p => p.IsRemoved == null || p.IsRemoved == false )) {
AutoLocatedPlaysets.Add(playset);
}
}
AutoLocatedMods.Add(theMod);

locatedPlaysetsCount = AutoLocatedPlaysets.Count;
}
logger.Debug($"Autolocated {AutoLocatedMods.Count} mods");

logger.Debug($"Autolocated {locatedPlaysetsCount} playsets.");
}

private static List<string> GetValidModFiles(string modPath) {
Expand Down
18 changes: 0 additions & 18 deletions Fronter.NET/Models/Configuration/Mod.cs

This file was deleted.

6 changes: 3 additions & 3 deletions Fronter.NET/Models/Configuration/RequiredFolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public override string Value {

base.Value = value;
logger.Info($"{TranslationSource.Instance[DisplayName]} set to: {value}");

if (Name.Equals(config.ModAutoGenerationSource)) {
config.AutoLocateMods();
if (config.TargetPlaysetSelectionEnabled) {
config.AutoLocatePlaysets();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ l_english:
OPTIONSTAB: "Options"
CONVERTTAB: "Convert"
MODSTAB: "Mods"
TARGET_PLAYSET_TAB: "Target Playset"
MODSDISABLED: "Mod autodetection disabled by configuration/not required."
MODSNOTFOUND: "Mods not found in mod directory."
MODSFOUND: "Mods autodetected:"
Expand Down
19 changes: 3 additions & 16 deletions Fronter.NET/Services/ModCopier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Fronter.Models.Database;
using log4net;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
Expand All @@ -18,7 +17,7 @@
this.config = config;
}

public bool CopyMod() {

Check warning on line 20 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

Method is too long (116 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 20 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / build (macos-15)

Method is too long (116 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 20 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

Method is too long (116 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 20 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / test (macos-15)

Method is too long (116 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)
logger.Notice("Mod Copying Started.");
var converterFolder = config.ConverterFolder;
if (!Directory.Exists(converterFolder)) {
Expand All @@ -32,13 +31,11 @@
return false;
}

var requiredFolders = config.RequiredFolders;
var targetGameModPath = requiredFolders.FirstOrDefault(f => string.Equals(f?.Name, "targetGameModPath", StringComparison.Ordinal), defaultValue: null);
if (targetGameModPath is null) {
string? destModsFolder = config.TargetGameModsPath;
if (destModsFolder is null) {
logger.Error("Copy failed - Target Folder isn't loaded!");
return false;
}
var destModsFolder = targetGameModPath.Value;
if (!Directory.Exists(destModsFolder)) {
logger.Error("Copy failed - Target Folder does not exist!");
return false;
Expand Down Expand Up @@ -138,13 +135,13 @@
return true;
}

private void CreatePlayset(string targetModsDirectory, string modName, string destModFolder) {

Check warning on line 138 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

Method is too long (94 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 138 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / build (macos-15)

Method is too long (94 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 138 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

Method is too long (94 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 138 in Fronter.NET/Services/ModCopier.cs

View workflow job for this annotation

GitHub Actions / test (macos-15)

Method is too long (94 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)
var gameDocsDirectory = Directory.GetParent(targetModsDirectory)?.FullName;
if (gameDocsDirectory is null) {
logger.Warn($"Couldn't get parent directory of \"{targetModsDirectory}\".");
return;
}
var latestDbFilePath = GetLastUpdatedLauncherDbPath(gameDocsDirectory);
var latestDbFilePath = TargetDbManager.GetLastUpdatedLauncherDbPath(gameDocsDirectory);
if (latestDbFilePath is null) {
logger.Debug("Launcher's database not found.");
return;
Expand Down Expand Up @@ -234,16 +231,6 @@
}
}

private static string? GetLastUpdatedLauncherDbPath(string gameDocsDirectory) {
var possibleDbFileNames = new List<string> { "launcher-v2.sqlite", "launcher-v2_openbeta.sqlite" };
var latestDbFilePath = possibleDbFileNames
.Select(name => Path.Join(gameDocsDirectory, name))
.Where(File.Exists)
.OrderByDescending(File.GetLastWriteTimeUtc)
.FirstOrDefault(defaultValue: null);
return latestDbFilePath;
}

// Returns saved mod.
private Mod AddModToDb(LauncherDbContext dbContext, string modName, string gameRegistryId, string dirPath) {
logger.Debug($"Saving mod \"{modName}\" to DB...");
Expand Down
37 changes: 37 additions & 0 deletions Fronter.NET/Services/TargetDbManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Fronter.Models.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Fronter.Services;

internal class TargetDbManager {

Check warning on line 8 in Fronter.NET/Services/TargetDbManager.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

Make class static (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1102)

Check warning on line 8 in Fronter.NET/Services/TargetDbManager.cs

View workflow job for this annotation

GitHub Actions / build (macos-15)

Make class static (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1102)

Check warning on line 8 in Fronter.NET/Services/TargetDbManager.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

Make class static (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1102)

Check warning on line 8 in Fronter.NET/Services/TargetDbManager.cs

View workflow job for this annotation

GitHub Actions / test (macos-15)

Make class static (https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1102)
public static string? GetLastUpdatedLauncherDbPath(string gameDocsDirectory) {
var possibleDbFileNames = new List<string> { "launcher-v2.sqlite", "launcher-v2_openbeta.sqlite" };
var latestDbFilePath = possibleDbFileNames
.Select(name => Path.Join(gameDocsDirectory, name))
.Where(File.Exists)
.OrderByDescending(File.GetLastWriteTimeUtc)
.FirstOrDefault(defaultValue: null);
return latestDbFilePath;
}

public static LauncherDbContext? GetLauncherDbContext(Config config) {
var targetGameModsPath = config.TargetGameModsPath;
if (string.IsNullOrWhiteSpace(targetGameModsPath)) {
return null;
}
var gameDocsDirectory = Directory.GetParent(targetGameModsPath)?.FullName;
if (gameDocsDirectory is null) {
return null;
}

var dbPath = GetLastUpdatedLauncherDbPath(gameDocsDirectory);
if (dbPath is null) {
return null;
}

string connectionString = $"Data Source={dbPath};";
return new LauncherDbContext(connectionString);
}
}
6 changes: 3 additions & 3 deletions Fronter.NET/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
internal Config Config { get; }

internal PathPickerViewModel PathPicker { get; }
internal ModsPickerViewModel ModsPicker { get; }
public bool ModsPickerTabVisible => Config.ModAutoGenerationSource is not null;
internal TargetPlaysetPickerViewModel TargetPlaysetPicker { get; }
public bool TargetPlaysetPickerTabVisible => Config.TargetPlaysetSelectionEnabled;
public OptionsViewModel Options { get; }
public bool OptionsTabVisible => Options.Items.Any();

Expand Down Expand Up @@ -99,7 +99,7 @@
LogGridAppender.LogGrid = logGrid;

PathPicker = new PathPickerViewModel(Config);
ModsPicker = new ModsPickerViewModel(Config);
TargetPlaysetPicker = new TargetPlaysetPickerViewModel(Config);
Options = new OptionsViewModel(Config.Options);

// Create reactive commands.
Expand Down Expand Up @@ -178,7 +178,7 @@
});
copyThread.Start();
}
public async Task LaunchConverter() {

Check warning on line 181 in Fronter.NET/ViewModels/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (self-hosted, linux)

Method is too long (65 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 181 in Fronter.NET/ViewModels/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (macos-15)

Method is too long (65 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 181 in Fronter.NET/ViewModels/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / test_and_check_coverage

Method is too long (65 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 181 in Fronter.NET/ViewModels/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / test (macos-15)

Method is too long (65 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)
ConvertButtonEnabled = false;
ClearLogGrid();

Expand Down
27 changes: 0 additions & 27 deletions Fronter.NET/ViewModels/ModsPickerViewModel.cs

This file was deleted.

Loading
Loading