Skip to content

Commit fd2e266

Browse files
committed
Ability to Compress Origin games, task them for auto installing etc #63
1 parent 2a3f83a commit fd2e266

File tree

13 files changed

+335
-208
lines changed

13 files changed

+335
-208
lines changed

Binaries/Steam Library Manager.exe

8 KB
Binary file not shown.

Source/Steam Library Manager/Definitions/App.cs

+84-47
Large diffs are not rendered by default.

Source/Steam Library Manager/Definitions/Global.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
namespace Steam_Library_Manager.Definitions
1+
using System.Collections.Generic;
2+
namespace Steam_Library_Manager.Definitions
23
{
34
internal static class Global
45
{
@@ -13,6 +14,7 @@ public static class Steam
1314
public static class Origin
1415
{
1516
public static string ConfigFilePath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "Origin", "local.xml");
17+
public static List<KeyValuePair<string, string>> AppIds = new List<KeyValuePair<string, string>>();
1618
}
1719
}
1820
}

Source/Steam Library Manager/Definitions/List.cs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class TaskInfo : INotifyPropertyChanged
3535
public bool ErrorHappened { get; set; }
3636
public bool Active { get; set; }
3737
public bool Completed { get; set; }
38+
public bool AutoInstall { get; set; }
3839
public bool Compress { get; set; } = Properties.Settings.Default.Global_Compress;
3940
public bool RemoveOldFiles { get; set; } = Properties.Settings.Default.Global_RemoveOldFiles;
4041
public bool ReportFileMovement { get; set; } = Properties.Settings.Default.Global_ReportFileMovement;

Source/Steam Library Manager/Definitions/OriginAppInfo.cs

+22-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class OriginAppInfo : App
1818
public string RepairParameter { get; set; }
1919
public Version AppVersion { get; set; }
2020

21-
public OriginAppInfo(Library library, string appName, int appId, DirectoryInfo installationDirectory, Version appVersion, string[] locales, string installedLocale, string touchupFile, string installationParameter, string updateParameter = null, string repairParameter = null)
21+
public OriginAppInfo(Library library, string appName, int appId, DirectoryInfo installationDirectory, Version appVersion, string[] locales, string installedLocale, bool isCompressed, string touchupFile, string installationParameter, string updateParameter = null, string repairParameter = null)
2222
{
2323
Library = library;
2424
AppName = appName;
@@ -31,8 +31,10 @@ public OriginAppInfo(Library library, string appName, int appId, DirectoryInfo i
3131
UpdateParameter = updateParameter;
3232
RepairParameter = repairParameter;
3333
AppVersion = appVersion;
34-
SizeOnDisk = Functions.FileSystem.GetDirectorySize(InstallationDirectory, true);
3534
LastUpdated = InstallationDirectory.LastWriteTimeUtc;
35+
IsCompressed = isCompressed;
36+
CompressedArchivePath = new FileInfo(Path.Combine(Library.FullPath, AppId + ".zip"));
37+
SizeOnDisk = (!IsCompressed) ? Functions.FileSystem.GetDirectorySize(InstallationDirectory, true) : CompressedArchivePath.Length;
3638
IsCompacted = CompactStatus().Result;
3739
}
3840

@@ -52,6 +54,19 @@ public override async void ParseMenuItemActionAsync(string action)
5254

5355
break;
5456

57+
case "compress":
58+
if (Functions.TaskManager.TaskList.Count(x => x.App == this && x.TargetLibrary == Library && x.TaskType == Enums.TaskType.Compress) == 0)
59+
{
60+
Functions.TaskManager.AddTask(new List.TaskInfo
61+
{
62+
App = this,
63+
TargetLibrary = Library,
64+
TaskType = Enums.TaskType.Compress,
65+
Compress = !IsCompressed
66+
});
67+
}
68+
break;
69+
5570
case "compact":
5671
if (Functions.TaskManager.TaskList.Count(x => x.App == this && x.TargetLibrary == Library && x.TaskType == Enums.TaskType.Compact) == 0)
5772
{
@@ -116,7 +131,7 @@ public async Task InstallAsync(bool repair = false)
116131

117132
await Main.FormAccessor.AppView.AppPanel.Dispatcher.Invoke(async delegate
118133
{
119-
var progressInformationMessage = await Main.FormAccessor.ShowProgressAsync(Functions.SLM.Translate(nameof(Properties.Resources.PleaseWait)), Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation_Start)), new { AppName })).ConfigureAwait(false);
134+
var progressInformationMessage = await Main.FormAccessor.ShowProgressAsync(Functions.SLM.Translate(nameof(Properties.Resources.PleaseWait)), Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation_Start)), new { AppName })).ConfigureAwait(true);
120135
progressInformationMessage.SetIndeterminate();
121136

122137
var process = Process.Start(TouchupFile.FullName, ((repair) ? RepairParameter : InstallationParameter).Replace("{locale}", InstalledLocale).Replace("{installLocation}", InstallationDirectory.FullName));
@@ -127,19 +142,19 @@ await Main.FormAccessor.AppView.AppPanel.Dispatcher.Invoke(async delegate
127142

128143
while (!process.HasExited)
129144
{
130-
await Task.Delay(100).ConfigureAwait(false);
145+
await Task.Delay(100).ConfigureAwait(true);
131146
}
132147

133-
await progressInformationMessage.CloseAsync().ConfigureAwait(false);
148+
await progressInformationMessage.CloseAsync().ConfigureAwait(true);
134149

135150
var installLog = File.ReadAllLines(Path.Combine(InstallationDirectory.FullName, "__Installer", "InstallLog.txt")).Reverse().ToList();
136151
if (installLog.Any(x => x.IndexOf("Installer finished with exit code:", StringComparison.OrdinalIgnoreCase) != -1))
137152
{
138153
var installerResult = installLog.FirstOrDefault(x => x.IndexOf("Installer finished with exit code:", StringComparison.OrdinalIgnoreCase) != -1);
139154

140-
await Main.FormAccessor.ShowMessageAsync(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation)), Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation_Completed)), new { installerResult })).ConfigureAwait(false);
155+
await Main.FormAccessor.ShowMessageAsync(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation)), Framework.StringFormat.Format(Functions.SLM.Translate(nameof(Properties.Resources.OriginInstallation_Completed)), new { installerResult })).ConfigureAwait(true);
141156
}
142-
}).ConfigureAwait(false);
157+
}).ConfigureAwait(true);
143158
}
144159
}
145160
catch (Exception ex)

Source/Steam Library Manager/Definitions/OriginLibrary.cs

+24-124
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
using Newtonsoft.Json.Linq;
22
using System;
33
using System.Collections.Async;
4-
using System.Collections.Generic;
54
using System.Diagnostics;
65
using System.IO;
6+
using System.IO.Compression;
77
using System.Linq;
88
using System.Net;
99
using System.Windows;
10-
using System.Xml.Linq;
1110

1211
namespace Steam_Library_Manager.Definitions
1312
{
@@ -23,146 +22,47 @@ public override async void UpdateAppListAsync()
2322
{
2423
try
2524
{
26-
Apps.Clear();
27-
28-
if (!Directory.Exists(FullPath)) return;
25+
if (IsUpdatingAppList)
26+
return;
2927

30-
var appIds = new List<KeyValuePair<string, string>>();
28+
IsUpdatingAppList = true;
3129

32-
if (Directory.Exists(Directories.Origin.LocalContentDirectoy))
33-
{
34-
//foreach (var originApp in Directory.EnumerateFiles(Directories.Origin.LocalContentDirectoy, "*.mfst", SearchOption.AllDirectories))
35-
await Directory.EnumerateFiles(Directories.Origin.LocalContentDirectoy, "*.mfst",
36-
SearchOption.AllDirectories).ParallelForEachAsync(
37-
async originApp =>
38-
{
39-
var appId = Path.GetFileNameWithoutExtension(originApp);
40-
41-
if (!appId.StartsWith("Origin"))
42-
{
43-
// Get game id by fixing file via adding : before integer part of the name
44-
// for example OFB-EAST52017 converts to OFB-EAST:52017
45-
var match = System.Text.RegularExpressions.Regex.Match(appId, @"^(.*?)(\d+)$");
46-
if (!match.Success)
47-
{
48-
return;
49-
}
50-
51-
appId = match.Groups[1].Value + ":" + match.Groups[2].Value;
52-
}
30+
Apps.Clear();
5331

54-
appIds.Add(new KeyValuePair<string, string>(new FileInfo(originApp).Directory.Name, appId));
55-
});
56-
}
32+
if (!Directory.Exists(FullPath)) return;
5733

5834
await Directory.EnumerateFiles(FullPath, "installerdata.xml", SearchOption.AllDirectories)
5935
.ParallelForEachAsync(
6036
async originApp =>
6137
{
62-
if (new FileInfo(originApp).Directory.Parent.Parent.Name !=
63-
new DirectoryInfo(FullPath).Name)
64-
return;
65-
66-
var installerLog = Path.Combine(Directory.GetParent(originApp).FullName, "InstallLog.txt");
67-
var installedLocale = "en_US";
68-
69-
if (File.Exists(installerLog))
70-
{
71-
foreach (var line in File.ReadAllLines(installerLog))
72-
{
73-
if (!line.Contains("Install Locale:")) continue;
74-
75-
installedLocale = line.Split(new string[] { "Install Locale:" },
76-
StringSplitOptions.None)[1];
77-
break;
78-
}
79-
80-
installedLocale = installedLocale.Replace(" ", "");
81-
}
82-
83-
var xml = XDocument.Load(originApp);
84-
var manifestVersion = new Version((xml.Root.Name.LocalName == "game")
85-
? xml.Root.Attribute("manifestVersion").Value
86-
: ((xml.Root.Name.LocalName == "DiPManifest")
87-
? xml.Root.Attribute("version").Value
88-
: "1.0"));
89-
90-
OriginAppInfo originAppInfo = null;
91-
92-
if (manifestVersion == new Version("4.0"))
93-
{
94-
originAppInfo = new OriginAppInfo(this,
95-
xml.Root.Element("gameTitles")?.Elements("gameTitle")
96-
?.First(x => x.Attribute("locale").Value == "en_US")?.Value,
97-
Convert.ToInt32(xml.Root.Element("contentIDs")?.Elements()
98-
.FirstOrDefault(x => int.TryParse(x.Value, out int appId))?.Value),
99-
new FileInfo(originApp).Directory.Parent,
100-
new Version(xml.Root.Element("buildMetaData")?.Element("gameVersion")
101-
?.Attribute("version")?.Value),
102-
xml.Root.Element("installMetaData")?.Element("locales")?.Value.Split(','),
103-
installedLocale,
104-
xml.Root.Element("touchup")?.Element("filePath")?.Value,
105-
xml.Root.Element("touchup")?.Element("parameters")?.Value,
106-
xml.Root.Element("touchup")?.Element("updateParameters")?.Value,
107-
xml.Root.Element("touchup")?.Element("repairParameters")?.Value);
108-
}
109-
else if (manifestVersion >= new Version("1.1") && manifestVersion <= new Version("3.0"))
110-
{
111-
var locales = new List<string>();
112-
foreach (var locale in xml.Root.Element("metadata")?.Elements("localeInfo")
113-
?.Attributes()?.Where(x => x.Name == "locale"))
114-
{
115-
locales.Add(locale.Value);
116-
}
117-
118-
originAppInfo = new OriginAppInfo(this,
119-
xml.Root.Element("metadata")?.Elements("localeInfo")
120-
?.First(x => x.Attribute("locale").Value == "en_US")?.Element("title").Value,
121-
Convert.ToInt32(xml.Root.Element("contentIDs")?.Element("contentID")?.Value
122-
.Replace("EAX", "")),
123-
new FileInfo(originApp).Directory.Parent,
124-
new Version(xml.Root.Attribute("gameVersion").Value),
125-
locales.ToArray(),
126-
installedLocale,
127-
xml.Root.Element("executable")?.Element("filePath")?.Value,
128-
xml.Root.Element("executable")?.Element("parameters")?.Value);
129-
}
130-
else
131-
{
132-
MessageBox.Show(Framework.StringFormat.Format(
133-
Functions.SLM.Translate(nameof(Properties.Resources.OriginUnknownManifestFile)),
134-
new { ManifestVersion = manifestVersion, OriginApp = originApp }));
135-
return;
136-
}
38+
await Functions.Origin.ParseAppDetailsAsync(new StreamReader(originApp).BaseStream, originApp, this);
39+
});
13740

138-
if (appIds.Count(x => x.Key == originAppInfo.InstallationDirectory.Name) > 0)
41+
await Directory.EnumerateFiles(FullPath, "*.zip", SearchOption.TopDirectoryOnly).ParallelForEachAsync(async originCompressedArchive =>
42+
{
43+
using (var archive = ZipFile.OpenRead(originCompressedArchive))
44+
{
45+
if (archive.Entries.Count > 0)
46+
{
47+
foreach (var archiveEntry in archive.Entries.Where(x => x.Name.Contains("installerdata.xml")))
13948
{
140-
var appId = appIds.First(x => x.Key == originAppInfo.InstallationDirectory.Name);
141-
142-
var appLocalData = GetGameLocalData(appId.Value);
143-
144-
if (appLocalData != null)
145-
{
146-
await Framework.CachedImage.FileCache.HitAsync(string.Concat(appLocalData["customAttributes"]["imageServer"],
147-
appLocalData["localizableAttributes"]["packArtLarge"])
148-
, $"{originAppInfo.AppId}_o")
149-
.ConfigureAwait(false);
150-
}
49+
await Functions.Origin.ParseAppDetailsAsync(archiveEntry.Open(), originCompressedArchive, this, true);
15150
}
152-
153-
originAppInfo.GameHeaderImage = $"{Directories.SLM.Cache}\\{originAppInfo.AppId}_o.jpg";
154-
155-
Apps.Add(originAppInfo);
156-
});
51+
}
52+
}
53+
});
15754

15855
if (SLM.CurrentSelectedLibrary != null && SLM.CurrentSelectedLibrary == this)
15956
{
16057
Functions.App.UpdateAppPanel(this);
16158
}
59+
60+
IsUpdatingAppList = false;
16261
}
16362
catch (Exception ex)
16463
{
165-
MessageBox.Show(ex.ToString());
64+
MessageBox.Show($"An error happened while updating game list for Origin library: {FullPath}\n{ex}");
65+
Logger.Fatal(ex);
16666
}
16767
}
16868

@@ -195,7 +95,7 @@ public override void RemoveLibraryAsync(bool withFiles)
19595
}
19696
}
19797

198-
private JObject GetGameLocalData(string gameId)
98+
public JObject GetGameLocalData(string gameId)
19999
{
200100
try
201101
{

Source/Steam Library Manager/Forms/Main.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ private void CreateLibraryButton_Click(object sender, RoutedEventArgs e)
294294
{
295295
if (Directory.GetDirectoryRoot(libraryPath) != libraryPath)
296296
{
297-
Functions.Origin.AddNewAsync(libraryPath);
297+
Functions.Origin.AddNewLibraryAsync(libraryPath);
298298
createLibraryFlyout.IsOpen = false;
299299
}
300300
else

0 commit comments

Comments
 (0)