mirror of
https://github.com/MathiasLui/CSGO-Projects.git
synced 2025-05-06 13:51:18 +00:00
Clean up SteamHelper and SteamGame
* Also makes required adjustments in the DamageCalculator
This commit is contained in:
parent
803dd30c7f
commit
2d8e38d48a
4 changed files with 280 additions and 90 deletions
|
@ -127,7 +127,7 @@ namespace Damage_Calculator
|
|||
InitializeComponent();
|
||||
Globals.LoadSettings();
|
||||
|
||||
SteamShared.Globals.Settings.CsgoHelper.CsgoPath = SteamShared.Globals.Settings.SteamHelper.GetGamePathFromExactName("Counter-Strike: Global Offensive");
|
||||
SteamShared.Globals.Settings.CsgoHelper.CsgoPath = SteamShared.Globals.Settings.SteamHelper.GetGamePathFromExactName("Counter-Strike: Global Offensive", true);
|
||||
if (SteamShared.Globals.Settings.CsgoHelper.CsgoPath == null)
|
||||
{
|
||||
ShowMessage.Error("Make sure you have installed CS:GO and Steam correctly.");
|
||||
|
@ -1843,7 +1843,7 @@ namespace Damage_Calculator
|
|||
// CS:GO is not opened, just ask if the user wants to start it
|
||||
if (MessageBox.Show("Do you want to start CS:GO now?", "Start CS:GO", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||
{
|
||||
SteamShared.Globals.Settings.SteamHelper.StartApp(SteamShared.CsgoHelper.GameID, additionalStartOptions);
|
||||
SteamShared.Globals.Settings.SteamHelper.StartSteamApp(SteamShared.CsgoHelper.GameID, additionalStartOptions);
|
||||
ShowMessage.Info("CS:GO is currently attempting to start. Retry to connect when you're in-game.\n\nRetrying while on a map will load the corresponding map.");
|
||||
return;
|
||||
}
|
||||
|
@ -1866,7 +1866,7 @@ namespace Damage_Calculator
|
|||
|
||||
if (csgo.HasExited)
|
||||
{
|
||||
SteamShared.Globals.Settings.SteamHelper.StartApp(SteamShared.CsgoHelper.GameID, additionalStartOptions);
|
||||
SteamShared.Globals.Settings.SteamHelper.StartSteamApp(SteamShared.CsgoHelper.GameID, additionalStartOptions);
|
||||
|
||||
ShowMessage.Info("CS:GO is currently attempting to restart. Retry to connect when you're in-game.\n\nRetrying while on a map will load the corresponding map.");
|
||||
return;
|
||||
|
|
|
@ -8,10 +8,19 @@ namespace SteamShared.Models
|
|||
{
|
||||
public class MapPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// The actual UI circle element of this point displayed on the map.
|
||||
/// </summary>
|
||||
public System.Windows.Shapes.Ellipse? Circle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The percentage that this point is at on the map's X axis (0% is left, 100% is right).
|
||||
/// </summary>
|
||||
public double PercentageX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The percentage that this point is at on the map's Y axis (0% is top, 100% is bottom).
|
||||
/// </summary>
|
||||
public double PercentageY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -29,8 +38,20 @@ namespace SteamShared.Models
|
|||
/// </summary>
|
||||
public double? Z { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the area that this point was put on.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If there is no area associated, it will be negative.
|
||||
/// </remarks>
|
||||
public int AssociatedAreaID { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The percentage of how wide this circle is relative to the map's width or height.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Width or height doesn't matter as maps are square shaped.
|
||||
/// </remarks>
|
||||
public double PercentageScale { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,123 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamShared.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A game (or app) which contains mainly app manifest data.
|
||||
/// </summary>
|
||||
public class SteamGame
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this game.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the folder this game's files are installed in,
|
||||
/// e.g. for CS:GO it would be "Counter-Strike Global Offensive".
|
||||
/// </summary>
|
||||
public string? InstallFolderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The absolute path of the steam library, which contains this game.
|
||||
/// </summary>
|
||||
public string? LinkedSteamLibraryPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The absolute installation path of this game, including the <see cref="InstallFolderName"/>,
|
||||
/// or <see langword="null"/>, if a puzzle piece of it is not specified.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The path might look like this on Windows: <br/><br/>
|
||||
///
|
||||
/// C:\My\Library\Path\steamapps\common\Super Cool Game <br/>
|
||||
/// [ Library Path ] [ Xtra Folders ] [ Game Name ]
|
||||
/// </remarks>
|
||||
public string? FullInstallPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.LinkedSteamLibraryPath is null || this.InstallFolderName is null)
|
||||
return null;
|
||||
|
||||
return System.IO.Path.Combine(LinkedSteamLibraryPath, "steamapps", "common", InstallFolderName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the game's directory (<see cref="FullInstallPath"/>) exists.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="LinkedSteamLibraryPath"/> and <see cref="InstallFolderName"/> need to be set.
|
||||
/// </remarks>
|
||||
public bool GameFolderExists
|
||||
{
|
||||
get
|
||||
{
|
||||
return Directory.Exists(this.FullInstallPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ID of this Steam App, e.g. for CS:GO this would be 730.
|
||||
/// </summary>
|
||||
public int AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The flags of this game, defined in <see cref="SteamShared.Models.GameState"/>.
|
||||
/// Note, that these are *flags* and thus can have multiple values.
|
||||
/// </summary>
|
||||
public int GameState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time this game was last updated at.
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The SteamID64 of the last owner user of this game.
|
||||
/// </summary>
|
||||
public long LastOwnerSteam64Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bytes that are left to download.
|
||||
/// </summary>
|
||||
public long BytesToDownload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bytes that were already downloaded.
|
||||
/// </summary>
|
||||
public long BytesDownloaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bytes that are left to be staged (Not 100% sure, what staging does).
|
||||
/// </summary>
|
||||
public long BytesToStage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bytes that were alread staged.
|
||||
/// </summary>
|
||||
public long BytesStaged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether Steam should keep this game updated automatically.
|
||||
/// </summary>
|
||||
public bool KeepAutomaticallyUpdated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether Steam is allowed to update other games and apps while this app is running.
|
||||
/// </summary>
|
||||
public bool AllowOtherUpdatesWhileRunning { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GameState flags defined in the app manifests.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
enum GameState
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SteamShared
|
|||
public List<SteamGame>? InstalledGames;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute path to the Steam install directory.
|
||||
/// The absolute path to the Steam install directory.
|
||||
/// If it can't be fetched (i.e. Steam is not installed) null is returned.
|
||||
/// </summary>
|
||||
public string? SteamPath
|
||||
|
@ -58,9 +58,9 @@ namespace SteamShared
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the Steam install directory. (For external use <see cref="SteamPath"/> is preferred.)
|
||||
/// The path to the Steam install directory. (For external use <see cref="SteamPath"/> is preferred.)
|
||||
/// </summary>
|
||||
/// <returns>The absolute path to the Steam install directory, or null if it can't be fetched.</returns>
|
||||
/// <returns>the absolute path to the Steam install directory, or null if it can't be fetched.</returns>
|
||||
public string? GetSteamPath()
|
||||
{
|
||||
var steamKey = Registry.CurrentUser.OpenSubKey("software\\valve\\steam");
|
||||
|
@ -98,7 +98,7 @@ namespace SteamShared
|
|||
|
||||
// Usually the config.vdf had "BaseInstallFolder_" entries,
|
||||
// now it seems that these entries don't exist anymore with reinstalls, and maybe they're not up-to-date anyways?
|
||||
// Now we try reading the "libraryfolders.vdf", which now also contains the default library location
|
||||
// Now we try reading the "libraryfolders.vdf", which now also contains the default library location (In the Steam folder, by default under C:)
|
||||
#if NEWLIBRARYLOCATION
|
||||
string configFilePath = Path.Combine(this.steamPath, "config", "libraryfolders.vdf");
|
||||
if (!File.Exists(configFilePath))
|
||||
|
@ -144,6 +144,10 @@ namespace SteamShared
|
|||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the <see cref="InstalledGames">list of installed steam games</see>.
|
||||
/// </summary>
|
||||
/// <param name="force">Whether to fetch them again, even if they were fetched before.</param>
|
||||
public void UpdateInstalledGames(bool force = false)
|
||||
{
|
||||
if (!force && this.InstalledGames != null)
|
||||
|
@ -152,10 +156,25 @@ namespace SteamShared
|
|||
this.InstalledGames = this.GetInstalledGames();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of fully installed Steam games, as seen by the manifest files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Games are seen as fully installed, when their manifest file exists,
|
||||
/// and the manifest states that the game is fully installed.
|
||||
/// This means, that if the files are deleted manually, it might still be seen as installed,
|
||||
/// because the manifest file might not change.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// a list of installed Steam games, with some manifest data,
|
||||
/// or <see langword="null"/>, if no games could be fetched or found.
|
||||
/// </returns>
|
||||
public List<SteamGame>? GetInstalledGames()
|
||||
{
|
||||
// Get all steam library paths
|
||||
var steamLibraries = this.GetSteamLibraries();
|
||||
|
||||
// If the steam path couldn't be fetched or no libraries exist, we short-circuit
|
||||
if (steamLibraries == null)
|
||||
return null;
|
||||
|
||||
|
@ -163,10 +182,11 @@ namespace SteamShared
|
|||
|
||||
foreach(var library in steamLibraries)
|
||||
{
|
||||
if (!library.DoesExist)
|
||||
if (!library.DoesExist || library.Path is null)
|
||||
continue;
|
||||
|
||||
List<string> manifestFiles = Directory.GetFiles(Path.Combine(library.Path!, "steamapps")).ToList().Where(f => this.isAppManifestFile(f)).ToList();
|
||||
List<string> manifestFiles = Directory.GetFiles(Path.Combine(library.Path, "steamapps"))
|
||||
.Where(f => this.isAppManifestFile(f)).ToList();
|
||||
|
||||
foreach (string manifestFile in manifestFiles)
|
||||
{
|
||||
|
@ -178,9 +198,13 @@ namespace SteamShared
|
|||
|
||||
var root = manifestVDF["AppState"];
|
||||
|
||||
if (root == null)
|
||||
// Parse error of manifest, skip it
|
||||
continue;
|
||||
|
||||
var currGame = new SteamGame();
|
||||
|
||||
this.populateGameInfo(currGame, root!);
|
||||
this.populateGameInfo(currGame, root, library.Path);
|
||||
|
||||
if((currGame.GameState & (int)GameState.StateFullyInstalled) != 0)
|
||||
{
|
||||
|
@ -193,69 +217,83 @@ namespace SteamShared
|
|||
return allGames;
|
||||
}
|
||||
|
||||
public string? GetGamePathFromExactName(string gameName)
|
||||
/// <summary>
|
||||
/// Gets the absolute path of the game name (not folder) provided.
|
||||
/// </summary>
|
||||
/// <param name="gameName">The name of the game. The case, as well as leading and trailing whitespaces don't matter.</param>
|
||||
/// <param name="shouldBeFullyInstalled">Whether to only return it, if it's marked as fully installed.</param>
|
||||
/// <returns>
|
||||
/// the absolute path of the game, or <see langword="null"/> if not found,
|
||||
/// the game's folder doesn't exist, or it wasn't marked as fully installed, when required to be.
|
||||
/// </returns>
|
||||
public string? GetGamePathFromExactName(string gameName, bool shouldBeFullyInstalled = false)
|
||||
{
|
||||
var steamLibraries = this.GetSteamLibraries();
|
||||
// Will not update, if already updated once before
|
||||
this.UpdateInstalledGames();
|
||||
|
||||
if (steamLibraries == null)
|
||||
if (this.InstalledGames is null)
|
||||
// User is broke or something
|
||||
return null;
|
||||
|
||||
var allGames = new List<SteamGame>();
|
||||
gameName = gameName.Trim();
|
||||
|
||||
foreach (var library in steamLibraries)
|
||||
{
|
||||
if (!library.DoesExist)
|
||||
continue;
|
||||
|
||||
List<string> manifestFiles = Directory.GetFiles(Path.Combine(library.Path!, "steamapps")).ToList().Where(f => this.isAppManifestFile(f)).ToList();
|
||||
|
||||
foreach (string manifestFile in manifestFiles)
|
||||
{
|
||||
var manifestVDF = new VDFFile(manifestFile);
|
||||
|
||||
if (manifestVDF.RootElements.Count < 1)
|
||||
// App manifest might be still existent but the game might not be installed (happened during testing)
|
||||
continue;
|
||||
|
||||
var root = manifestVDF["AppState"];
|
||||
|
||||
if(root!["name"].Value!.Trim().ToLower() != gameName.Trim().ToLower())
|
||||
{
|
||||
// Not our wanted game, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
var currGame = new SteamGame();
|
||||
|
||||
this.populateGameInfo(currGame, root);
|
||||
|
||||
if ((currGame.GameState & (int)GameState.StateFullyInstalled) != 0)
|
||||
{
|
||||
// Game was fully installed according to steam
|
||||
return Path.Combine(library.Path!, "steamapps", "common", currGame.InstallFolderName!);
|
||||
}
|
||||
}
|
||||
}
|
||||
var foundGame = this.InstalledGames.Where(game => game.Name is not null && game.Name.Trim().Equals(gameName, StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (foundGame is null)
|
||||
return null;
|
||||
|
||||
if (!foundGame.GameFolderExists)
|
||||
return null;
|
||||
|
||||
if (shouldBeFullyInstalled
|
||||
&& (foundGame.GameState & (int)GameState.StateFullyInstalled) == 0)
|
||||
return null;
|
||||
|
||||
// Match the name while ignoring leading and trailing whitespaces, as well as upper/lower case.
|
||||
return foundGame.FullInstallPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the most recently logged in Steam user, based on the "MostRecent" value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The most recent logged in Steam user, or <see langword="null"/>, if none has been found or an error has occurred.
|
||||
/// the most recent logged in Steam user, or <see langword="null"/>, if none has been found or an error has occurred.
|
||||
/// </returns>
|
||||
public SteamUser? GetMostRecentSteamUser()
|
||||
{
|
||||
string steamPath = this.SteamPath;
|
||||
List<SteamUser>? steamUsers = this.GetSteamUsers();
|
||||
|
||||
if (steamUsers == null)
|
||||
return null;
|
||||
|
||||
// Gets the user that has logged in most recently.
|
||||
// We do this instead of checking, which user has the "MostRecent" VDF property set to 1
|
||||
SteamUser? mostRecentLoggedInSteamUser = steamUsers.OrderByDescending(user => user.LastLogin).FirstOrDefault();
|
||||
|
||||
return mostRecentLoggedInSteamUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all Steam users from the loginusers.vdf file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// a list of users, or <see langword="null"/>, if no users exist or there was an error.
|
||||
/// </returns>
|
||||
public List<SteamUser>? GetSteamUsers()
|
||||
{
|
||||
string? steamPath = this.SteamPath;
|
||||
|
||||
// SteamPath couldn't be fetched.
|
||||
// This would break if Steam was installed to a different directory between fetching and using the steam path.
|
||||
if (steamPath == null)
|
||||
return null;
|
||||
|
||||
// The path that probably contains all users that have logged in since Steam was installed
|
||||
string usersFilePath = Path.Combine(steamPath, "config", "loginusers.vdf");
|
||||
|
||||
if (!File.Exists(usersFilePath))
|
||||
// Where file? 🦧
|
||||
return null;
|
||||
|
||||
VDFFile vdf = new VDFFile(usersFilePath);
|
||||
|
@ -265,44 +303,51 @@ namespace SteamShared
|
|||
if (users == null)
|
||||
return null;
|
||||
|
||||
SteamUser? mostRecentUser = null;
|
||||
List<SteamUser>? steamUsers = null;
|
||||
|
||||
// users may be empty here
|
||||
foreach (var user in users)
|
||||
{
|
||||
if (int.TryParse(user["MostRecent"]?.Value, out int mostRecent) && Convert.ToBoolean(mostRecent))
|
||||
{
|
||||
// We found a "most recent" user
|
||||
mostRecentUser = new SteamUser();
|
||||
// Create the list if we have at least one *potential* user
|
||||
if (steamUsers == null)
|
||||
steamUsers = new List<SteamUser>();
|
||||
|
||||
if(ulong.TryParse(user.Name, out ulong steamID64))
|
||||
var steamUser = new SteamUser();
|
||||
|
||||
// This is not the user name, but the name of the VDF element, which in this case should be the steam ID 64
|
||||
if (ulong.TryParse(user.Name, out ulong steamID64))
|
||||
{
|
||||
mostRecentUser.SteamID64 = steamID64;
|
||||
steamUser.SteamID64 = steamID64;
|
||||
}
|
||||
|
||||
mostRecentUser.AccountName = user["AccountName"].Value;
|
||||
mostRecentUser.PersonaName = user["PersonaName"].Value;
|
||||
steamUser.AccountName = user["AccountName"].Value;
|
||||
steamUser.PersonaName = user["PersonaName"].Value;
|
||||
|
||||
// "MostRecent" can later be found by getting the largest Timestamp
|
||||
if (ulong.TryParse(user["Timestamp"].Value, out ulong lastLoginUnixTime))
|
||||
{
|
||||
mostRecentUser.LastLogin = lastLoginUnixTime;
|
||||
steamUser.LastLogin = lastLoginUnixTime;
|
||||
}
|
||||
|
||||
mostRecentUser.AbsoluteUserdataFolderPath = Path.Combine(steamPath, "userdata", mostRecentUser.AccountID.ToString());
|
||||
}
|
||||
// The needed AccountID (Last part of the SteamId3) is calculated automatically from the SteamId64
|
||||
steamUser.AbsoluteUserdataFolderPath = Path.Combine(steamPath, "userdata", steamUser.AccountID.ToString());
|
||||
|
||||
steamUsers.Add(steamUser);
|
||||
}
|
||||
|
||||
return mostRecentUser;
|
||||
return steamUsers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the given steam game, with the given additional arguments, if possible.
|
||||
/// </summary>
|
||||
/// <param name="gameID">The ID of the game.</param>
|
||||
/// <param name="arguments">
|
||||
/// <param name="gameID">The ID of the game (e.g. 730 for CS:GO/CS2).</param>
|
||||
/// <param name="additionalArgs">
|
||||
/// The arguments passed to that game.
|
||||
/// Note, that the default arguments set by the user in the UI are also passed to the app, these are just additional.
|
||||
/// Note, that the default arguments set by the user in the UI are also passed to the app,
|
||||
/// these are just additional to that.
|
||||
/// </param>
|
||||
public void StartApp(int gameID, string arguments)
|
||||
public void StartSteamApp(int gameID, string additionalArgs)
|
||||
{
|
||||
string? steamPath = this.SteamPath;
|
||||
this.UpdateInstalledGames(); // Won't force update, if already set
|
||||
|
@ -316,28 +361,66 @@ namespace SteamShared
|
|||
startInfo.UseShellExecute = false; // Make double sure
|
||||
startInfo.CreateNoWindow = false;
|
||||
startInfo.FileName = Path.Combine(steamPath, "steam.exe");
|
||||
startInfo.Arguments = $"-applaunch {gameID}" + (String.IsNullOrWhiteSpace(arguments) ? string.Empty : $" {arguments}");
|
||||
|
||||
string extraArgs = String.IsNullOrWhiteSpace(additionalArgs) ? string.Empty : $" {additionalArgs}";
|
||||
|
||||
// The "-applaunch" argument will automatically add the args stored by the user. We add our own ones to that, if required.
|
||||
startInfo.Arguments = $"-applaunch {gameID}" + extraArgs;
|
||||
|
||||
// Fire and forget!
|
||||
Process.Start(startInfo);
|
||||
}
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Checks, if the file at the given absolute path is considered an appmanifest, by the looks of it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// App manifest have the format "appmanifest_GAMEID.acf"
|
||||
/// </remarks>
|
||||
/// <param name="filePath">The absolute path of the app manifest (acf) file.</param>
|
||||
/// <returns>
|
||||
/// whether the file name matches the app manifest description.
|
||||
/// </returns>
|
||||
private bool isAppManifestFile(string filePath)
|
||||
{
|
||||
return System.Text.RegularExpressions.Regex.IsMatch(filePath.Split(new[] { '\\', '/' }).Last(), "appmanifest_\\d+.acf"); ;
|
||||
string[] splitFilePath = filePath.Split(new[] { '\\', '/' });
|
||||
|
||||
if (splitFilePath.Length < 1)
|
||||
// Doesn't seem to be a valid path
|
||||
return false;
|
||||
|
||||
return System.Text.RegularExpressions.Regex.IsMatch(splitFilePath.Last(), "appmanifest_\\d+.acf"); ;
|
||||
}
|
||||
|
||||
private DateTime fromUnixFormat(long unixFormat)
|
||||
/// <summary>
|
||||
/// Converts a unix time in seconds to a <see cref="DateTime"/> using the specified <see cref="DateTimeKind"/>.
|
||||
/// </summary>
|
||||
/// <param name="unixSeconds">The unix seconds.</param>
|
||||
/// <param name="dateTimeKind">The type of time zone, UTC by default.</param>
|
||||
/// <returns>
|
||||
/// the <see cref="DateTime"/> that was created from the given seconds.
|
||||
/// </returns>
|
||||
private DateTime fromUnixFormat(long unixSeconds, DateTimeKind dateTimeKind = DateTimeKind.Utc)
|
||||
{
|
||||
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local);
|
||||
return dateTime.AddSeconds(unixFormat);
|
||||
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, dateTimeKind);
|
||||
return dateTime.AddSeconds(unixSeconds);
|
||||
}
|
||||
|
||||
private void populateGameInfo(SteamGame game, Element appStateVdf)
|
||||
/// <summary>
|
||||
/// Takes a game object and populates it with the info from the app manifest file,
|
||||
/// which is specified by the given VDF element.
|
||||
/// </summary>
|
||||
/// <param name="game">The game to populate with info.</param>
|
||||
/// <param name="appStateVdf">The app state VDF element, which contains the required information.</param>
|
||||
/// <param name="steamLibraryPath">The absolute path to the steam library containing this game.</param>
|
||||
private void populateGameInfo(SteamGame game, Element appStateVdf, string steamLibraryPath)
|
||||
{
|
||||
game.Name = appStateVdf["name"]?.Value;
|
||||
|
||||
// Setting these two properties enables the ability to fetch the FullInstallPath
|
||||
game.InstallFolderName = appStateVdf["installdir"]?.Value;
|
||||
game.LinkedSteamLibraryPath = steamLibraryPath;
|
||||
|
||||
if (int.TryParse(appStateVdf["appid"]?.Value, out int appId))
|
||||
{
|
||||
|
@ -351,7 +434,8 @@ namespace SteamShared
|
|||
|
||||
if (long.TryParse(appStateVdf["LastUpdated"]?.Value, out long lastUpdated))
|
||||
{
|
||||
game.LastUpdated = fromUnixFormat(lastUpdated);
|
||||
// It's unix time, but the time is in the local time zone, and not in UTC.
|
||||
game.LastUpdated = fromUnixFormat(lastUpdated, DateTimeKind.Local);
|
||||
}
|
||||
|
||||
if (long.TryParse(appStateVdf["LastOwner"]?.Value, out long lastOwner))
|
||||
|
|
Loading…
Add table
Reference in a new issue