chore: tidy-up, move files shared between dalamud and injector into separate assembly

This commit is contained in:
goat 2023-09-30 16:11:52 +02:00
parent 6f99cfe48c
commit f44c6794e7
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
29 changed files with 174 additions and 129 deletions

View file

@ -1,5 +1,7 @@
namespace Dalamud;
// TODO(v10): Delete this, and use Dalamud.Common.ClientLanguage instead for everything.
/// <summary>
/// Enum describing the language the game loads in.
/// </summary>

View file

@ -1,4 +1,3 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -7,6 +6,7 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Common;
using Dalamud.Configuration.Internal;
using Dalamud.Game;
using Dalamud.Game.Gui.Internal;
@ -14,6 +14,7 @@ using Dalamud.Interface.Internal;
using Dalamud.Plugin.Internal;
using Dalamud.Storage;
using Dalamud.Utility;
using Dalamud.Utility.Timing;
using PInvoke;
using Serilog;
@ -47,10 +48,28 @@ internal sealed class Dalamud : IServiceType
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
public Dalamud(DalamudStartInfo info, ReliableFileStorage fs, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent)
{
this.StartInfo = info;
this.unloadSignal = new ManualResetEvent(false);
this.unloadSignal.Reset();
// Directory resolved signatures(CS, our own) will be cached in
var cacheDir = new DirectoryInfo(Path.Combine(this.StartInfo.WorkingDirectory!, "cachedSigs"));
if (!cacheDir.Exists)
cacheDir.Create();
// Set up the SigScanner for our target module
TargetSigScanner scanner;
using (Timings.Start("SigScanner Init"))
{
scanner = new TargetSigScanner(
true, new FileInfo(Path.Combine(cacheDir.FullName, $"{this.StartInfo.GameVersion}.json")));
}
ServiceManager.InitializeProvidedServicesAndClientStructs(this, info, fs, configuration);
ServiceManager.InitializeProvidedServices(this, fs, configuration, scanner);
// Set up FFXIVClientStructs
this.SetupClientStructsResolver(cacheDir);
if (!configuration.IsResumeGameAfterPluginLoad)
{
@ -97,11 +116,16 @@ internal sealed class Dalamud : IServiceType
});
}
}
/// <summary>
/// Gets the start information for this Dalamud instance.
/// </summary>
internal DalamudStartInfo StartInfo { get; private set; }
/// <summary>
/// Gets location of stored assets.
/// </summary>
internal DirectoryInfo AssetDirectory => new(Service<DalamudStartInfo>.Get().AssetDirectory!);
internal DirectoryInfo AssetDirectory => new(this.StartInfo.AssetDirectory!);
/// <summary>
/// Signal to the crash handler process that we should restart the game.
@ -176,4 +200,13 @@ internal sealed class Dalamud : IServiceType
var oldFilter = NativeFunctions.SetUnhandledExceptionFilter(releaseFilter);
Log.Debug("Reset ExceptionFilter, old: {0}", oldFilter);
}
private void SetupClientStructsResolver(DirectoryInfo cacheDir)
{
using (Timings.Start("CS Resolver Init"))
{
FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service<TargetSigScanner>.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{this.StartInfo.GameVersion}_cs.json")));
FFXIVClientStructs.Interop.Resolver.GetInstance.Resolve();
}
}
}

View file

@ -89,6 +89,7 @@
<PackageReference Include="System.Resources.Extensions" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dalamud.Common\Dalamud.Common.csproj" />
<ProjectReference Include="..\lib\FFXIVClientStructs\FFXIVClientStructs\FFXIVClientStructs.csproj" />
<ProjectReference Include="..\lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj" />
<ProjectReference Include="..\lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj" />

View file

@ -1,176 +0,0 @@
using System;
using System.Collections.Generic;
using Dalamud.Game;
using Newtonsoft.Json;
namespace Dalamud;
/// <summary>
/// Struct containing information needed to initialize Dalamud.
/// </summary>
[Serializable]
[ServiceManager.Service]
public record DalamudStartInfo : IServiceType
{
/// <summary>
/// Initializes a new instance of the <see cref="DalamudStartInfo"/> class.
/// </summary>
public DalamudStartInfo()
{
// ignored
}
/// <summary>
/// Initializes a new instance of the <see cref="DalamudStartInfo"/> class.
/// </summary>
/// <param name="other">Object to copy values from.</param>
public DalamudStartInfo(DalamudStartInfo other)
{
this.WorkingDirectory = other.WorkingDirectory;
this.ConfigurationPath = other.ConfigurationPath;
this.LogPath = other.LogPath;
this.LogName = other.LogName;
this.PluginDirectory = other.PluginDirectory;
this.AssetDirectory = other.AssetDirectory;
this.Language = other.Language;
this.GameVersion = other.GameVersion;
this.DelayInitializeMs = other.DelayInitializeMs;
this.TroubleshootingPackData = other.TroubleshootingPackData;
this.NoLoadPlugins = other.NoLoadPlugins;
this.NoLoadThirdPartyPlugins = other.NoLoadThirdPartyPlugins;
this.BootLogPath = other.BootLogPath;
this.BootShowConsole = other.BootShowConsole;
this.BootDisableFallbackConsole = other.BootDisableFallbackConsole;
this.BootWaitMessageBox = other.BootWaitMessageBox;
this.BootWaitDebugger = other.BootWaitDebugger;
this.BootVehEnabled = other.BootVehEnabled;
this.BootVehFull = other.BootVehFull;
this.BootEnableEtw = other.BootEnableEtw;
this.BootDotnetOpenProcessHookMode = other.BootDotnetOpenProcessHookMode;
this.BootEnabledGameFixes = other.BootEnabledGameFixes;
this.BootUnhookDlls = other.BootUnhookDlls;
this.CrashHandlerShow = other.CrashHandlerShow;
}
/// <summary>
/// Gets or sets the working directory of the XIVLauncher installations.
/// </summary>
public string? WorkingDirectory { get; set; }
/// <summary>
/// Gets or sets the path to the configuration file.
/// </summary>
public string? ConfigurationPath { get; set; }
/// <summary>
/// Gets or sets the path of the log files.
/// </summary>
public string? LogPath { get; set; }
/// <summary>
/// Gets or sets the name of the log file.
/// </summary>
public string? LogName { get; set; }
/// <summary>
/// Gets or sets the path to the directory for installed plugins.
/// </summary>
public string? PluginDirectory { get; set; }
/// <summary>
/// Gets or sets the path to core Dalamud assets.
/// </summary>
public string? AssetDirectory { get; set; }
/// <summary>
/// Gets or sets the language of the game client.
/// </summary>
public ClientLanguage Language { get; set; } = ClientLanguage.English;
/// <summary>
/// Gets or sets the current game version code.
/// </summary>
[JsonConverter(typeof(GameVersionConverter))]
public GameVersion? GameVersion { get; set; }
/// <summary>
/// Gets or sets troubleshooting information to attach when generating a tspack file.
/// </summary>
public string TroubleshootingPackData { get; set; }
/// <summary>
/// Gets or sets a value that specifies how much to wait before a new Dalamud session.
/// </summary>
public int DelayInitializeMs { get; set; }
/// <summary>
/// Gets or sets a value indicating whether no plugins should be loaded.
/// </summary>
public bool NoLoadPlugins { get; set; }
/// <summary>
/// Gets or sets a value indicating whether no third-party plugins should be loaded.
/// </summary>
public bool NoLoadThirdPartyPlugins { get; set; }
/// <summary>
/// Gets or sets the path the boot log file is supposed to be written to.
/// </summary>
public string? BootLogPath { get; set; }
/// <summary>
/// Gets or sets a value indicating whether a Boot console should be shown.
/// </summary>
public bool BootShowConsole { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the fallback console should be shown, if needed.
/// </summary>
public bool BootDisableFallbackConsole { get; set; }
/// <summary>
/// Gets or sets a flag indicating where Dalamud should wait with a message box.
/// </summary>
public int BootWaitMessageBox { get; set; }
/// <summary>
/// Gets or sets a value indicating whether Dalamud should wait for a debugger to be attached before initializing.
/// </summary>
public bool BootWaitDebugger { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the VEH should be enabled.
/// </summary>
public bool BootVehEnabled { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the VEH should be doing full crash dumps.
/// </summary>
public bool BootVehFull { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not ETW should be enabled.
/// </summary>
public bool BootEnableEtw { get; set; }
/// <summary>
/// Gets or sets a value choosing the OpenProcess hookmode.
/// </summary>
public int BootDotnetOpenProcessHookMode { get; set; }
/// <summary>
/// Gets or sets a list of enabled game fixes.
/// </summary>
public List<string>? BootEnabledGameFixes { get; set; }
/// <summary>
/// Gets or sets a list of DLLs that should be unhooked.
/// </summary>
public List<string>? BootUnhookDlls { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to show crash handler console window.
/// </summary>
public bool CrashHandlerShow { get; set; }
}

View file

@ -7,6 +7,7 @@ using System.Threading;
using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using Dalamud.Utility.Timing;
using JetBrains.Annotations;
using Lumina;
@ -32,9 +33,9 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager
private readonly CancellationTokenSource luminaCancellationTokenSource;
[ServiceManager.ServiceConstructor]
private DataManager(DalamudStartInfo dalamudStartInfo, Dalamud dalamud)
private DataManager(Dalamud dalamud)
{
this.Language = dalamudStartInfo.Language;
this.Language = (ClientLanguage)dalamud.StartInfo.Language;
// Set up default values so plugins do not null-reference when data is being loaded.
this.ClientOpCodes = this.ServerOpCodes = new ReadOnlyDictionary<string, ushort>(new Dictionary<string, ushort>());
@ -82,17 +83,20 @@ internal sealed class DataManager : IDisposable, IServiceType, IDataManager
Log.Information("Lumina is ready: {0}", this.GameData.DataPath);
try
if (!dalamud.StartInfo.TroubleshootingPackData.IsNullOrEmpty())
{
var tsInfo =
JsonConvert.DeserializeObject<LauncherTroubleshootingInfo>(
dalamudStartInfo.TroubleshootingPackData);
this.HasModifiedGameDataFiles =
tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception;
}
catch
{
// ignored
try
{
var tsInfo =
JsonConvert.DeserializeObject<LauncherTroubleshootingInfo>(
dalamud.StartInfo.TroubleshootingPackData);
this.HasModifiedGameDataFiles =
tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed or LauncherTroubleshootingInfo.IndexIntegrityResult.Exception;
}
catch
{
// ignored
}
}
}

View file

@ -1,4 +1,3 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
@ -6,6 +5,7 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Common;
using Dalamud.Configuration.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Logging.Retention;
@ -163,6 +163,9 @@ public sealed class EntryPoint
Log.Information(new string('-', 80));
Log.Information("Initializing a session..");
if (string.IsNullOrEmpty(info.WorkingDirectory))
throw new Exception("Working directory was invalid");
Reloaded.Hooks.Tools.Utilities.FasmBasePath = new DirectoryInfo(info.WorkingDirectory);
// This is due to GitHub not supporting TLS 1.0, so we enable all TLS versions globally

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -14,8 +13,6 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Interface.Internal;
using Dalamud.Interface.Internal.Notifications;
using Dalamud.Interface.Internal.Windows;
using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using Serilog;
@ -104,6 +101,9 @@ internal class ChatHandlers : IServiceType
private readonly DalamudLinkPayload openInstallerWindowLink;
[ServiceManager.ServiceDependency]
private readonly Dalamud dalamud = Service<Dalamud>.Get();
[ServiceManager.ServiceDependency]
private readonly DalamudConfiguration configuration = Service<DalamudConfiguration>.Get();
@ -160,7 +160,6 @@ internal class ChatHandlers : IServiceType
private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
{
var startInfo = Service<DalamudStartInfo>.Get();
var clientState = Service<ClientState.ClientState>.GetNullable();
if (clientState == null)
return;
@ -182,7 +181,7 @@ internal class ChatHandlers : IServiceType
if (type == XivChatType.RetainerSale)
{
foreach (var regex in this.retainerSaleRegexes[startInfo.Language])
foreach (var regex in this.retainerSaleRegexes[(ClientLanguage)this.dalamud.StartInfo.Language])
{
var matchInfo = regex.Match(message.TextValue);

View file

@ -41,7 +41,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState
private bool lastFramePvP;
[ServiceManager.ServiceConstructor]
private ClientState(TargetSigScanner sigScanner, DalamudStartInfo startInfo, GameLifecycle lifecycle)
private ClientState(TargetSigScanner sigScanner, Dalamud dalamud, GameLifecycle lifecycle)
{
this.lifecycle = lifecycle;
this.address = new ClientStateAddressResolver();
@ -49,7 +49,7 @@ internal sealed class ClientState : IDisposable, IServiceType, IClientState
Log.Verbose("===== C L I E N T S T A T E =====");
this.ClientLanguage = startInfo.Language;
this.ClientLanguage = (ClientLanguage)dalamud.StartInfo.Language;
Log.Verbose($"SetupTerritoryType address 0x{this.address.SetupTerritoryType.ToInt64():X}");

View file

@ -35,15 +35,15 @@ internal sealed class CommandManager : IServiceType, IDisposable, ICommandManage
private readonly ChatGui chatGui = Service<ChatGui>.Get();
[ServiceManager.ServiceConstructor]
private CommandManager(DalamudStartInfo startInfo)
private CommandManager(Dalamud dalamud)
{
this.currentLangCommandRegex = startInfo.Language switch
this.currentLangCommandRegex = (ClientLanguage)dalamud.StartInfo.Language switch
{
ClientLanguage.Japanese => this.commandRegexJp,
ClientLanguage.English => this.commandRegexEn,
ClientLanguage.German => this.commandRegexDe,
ClientLanguage.French => this.commandRegexFr,
_ => this.currentLangCommandRegex,
_ => this.commandRegexEn,
};
this.chatGui.CheckMessageHandled += this.OnCheckMessageHandled;

View file

@ -1,408 +0,0 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace Dalamud.Game;
/// <summary>
/// A GameVersion object contains give hierarchical numeric components: year, month,
/// day, major and minor. All components may be unspecified, which is represented
/// internally as a -1. By definition, an unspecified component matches anything
/// (both unspecified and specified), and an unspecified component is "less than" any
/// specified component. It will also equal the string "any" if all components are
/// unspecified. The value can be retrieved from the ffxivgame.ver file in your game
/// installation directory.
/// </summary>
[Serializable]
public sealed class GameVersion : ICloneable, IComparable, IComparable<GameVersion>, IEquatable<GameVersion>
{
private static readonly GameVersion AnyVersion = new();
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="version">Version string to parse.</param>
[JsonConstructor]
public GameVersion(string version)
{
var ver = Parse(version);
this.Year = ver.Year;
this.Month = ver.Month;
this.Day = ver.Day;
this.Major = ver.Major;
this.Minor = ver.Minor;
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <param name="day">The day.</param>
/// <param name="major">The major version.</param>
/// <param name="minor">The minor version.</param>
public GameVersion(int year, int month, int day, int major, int minor)
{
if ((this.Year = year) < 0)
throw new ArgumentOutOfRangeException(nameof(year));
if ((this.Month = month) < 0)
throw new ArgumentOutOfRangeException(nameof(month));
if ((this.Day = day) < 0)
throw new ArgumentOutOfRangeException(nameof(day));
if ((this.Major = major) < 0)
throw new ArgumentOutOfRangeException(nameof(major));
if ((this.Minor = minor) < 0)
throw new ArgumentOutOfRangeException(nameof(minor));
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <param name="day">The day.</param>
/// <param name="major">The major version.</param>
public GameVersion(int year, int month, int day, int major)
{
if ((this.Year = year) < 0)
throw new ArgumentOutOfRangeException(nameof(year));
if ((this.Month = month) < 0)
throw new ArgumentOutOfRangeException(nameof(month));
if ((this.Day = day) < 0)
throw new ArgumentOutOfRangeException(nameof(day));
if ((this.Major = major) < 0)
throw new ArgumentOutOfRangeException(nameof(major));
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <param name="day">The day.</param>
public GameVersion(int year, int month, int day)
{
if ((this.Year = year) < 0)
throw new ArgumentOutOfRangeException(nameof(year));
if ((this.Month = month) < 0)
throw new ArgumentOutOfRangeException(nameof(month));
if ((this.Day = day) < 0)
throw new ArgumentOutOfRangeException(nameof(day));
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
public GameVersion(int year, int month)
{
if ((this.Year = year) < 0)
throw new ArgumentOutOfRangeException(nameof(year));
if ((this.Month = month) < 0)
throw new ArgumentOutOfRangeException(nameof(month));
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
/// <param name="year">The year.</param>
public GameVersion(int year)
{
if ((this.Year = year) < 0)
throw new ArgumentOutOfRangeException(nameof(year));
}
/// <summary>
/// Initializes a new instance of the <see cref="GameVersion"/> class.
/// </summary>
public GameVersion()
{
}
/// <summary>
/// Gets the default "any" game version.
/// </summary>
public static GameVersion Any => AnyVersion;
/// <summary>
/// Gets the year component.
/// </summary>
public int Year { get; } = -1;
/// <summary>
/// Gets the month component.
/// </summary>
public int Month { get; } = -1;
/// <summary>
/// Gets the day component.
/// </summary>
public int Day { get; } = -1;
/// <summary>
/// Gets the major version component.
/// </summary>
public int Major { get; } = -1;
/// <summary>
/// Gets the minor version component.
/// </summary>
public int Minor { get; } = -1;
public static implicit operator GameVersion(string ver)
{
return Parse(ver);
}
public static bool operator ==(GameVersion v1, GameVersion v2)
{
if (v1 is null)
{
return v2 is null;
}
return v1.Equals(v2);
}
public static bool operator !=(GameVersion v1, GameVersion v2)
{
return !(v1 == v2);
}
public static bool operator <(GameVersion v1, GameVersion v2)
{
if (v1 is null)
throw new ArgumentNullException(nameof(v1));
return v1.CompareTo(v2) < 0;
}
public static bool operator <=(GameVersion v1, GameVersion v2)
{
if (v1 is null)
throw new ArgumentNullException(nameof(v1));
return v1.CompareTo(v2) <= 0;
}
public static bool operator >(GameVersion v1, GameVersion v2)
{
return v2 < v1;
}
public static bool operator >=(GameVersion v1, GameVersion v2)
{
return v2 <= v1;
}
public static GameVersion operator +(GameVersion v1, TimeSpan v2)
{
if (v1 == null)
throw new ArgumentNullException(nameof(v1));
if (v1.Year == -1 || v1.Month == -1 || v1.Day == -1)
return v1;
var date = new DateTime(v1.Year, v1.Month, v1.Day) + v2;
return new GameVersion(date.Year, date.Month, date.Day, v1.Major, v1.Minor);
}
public static GameVersion operator -(GameVersion v1, TimeSpan v2)
{
if (v1 == null)
throw new ArgumentNullException(nameof(v1));
if (v1.Year == -1 || v1.Month == -1 || v1.Day == -1)
return v1;
var date = new DateTime(v1.Year, v1.Month, v1.Day) - v2;
return new GameVersion(date.Year, date.Month, date.Day, v1.Major, v1.Minor);
}
/// <summary>
/// Parse a version string. YYYY.MM.DD.majr.minr or "any".
/// </summary>
/// <param name="input">Input to parse.</param>
/// <returns>GameVersion object.</returns>
public static GameVersion Parse(string input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
if (input.ToLower(CultureInfo.InvariantCulture) == "any")
return new GameVersion();
var parts = input.Split('.');
var tplParts = parts.Select(p =>
{
var result = int.TryParse(p, out var value);
return (result, value);
}).ToArray();
if (tplParts.Any(t => !t.result))
throw new FormatException("Bad formatting");
var intParts = tplParts.Select(t => t.value).ToArray();
var len = intParts.Length;
if (len == 1)
return new GameVersion(intParts[0]);
else if (len == 2)
return new GameVersion(intParts[0], intParts[1]);
else if (len == 3)
return new GameVersion(intParts[0], intParts[1], intParts[2]);
else if (len == 4)
return new GameVersion(intParts[0], intParts[1], intParts[2], intParts[3]);
else if (len == 5)
return new GameVersion(intParts[0], intParts[1], intParts[2], intParts[3], intParts[4]);
else
throw new ArgumentException("Too many parts");
}
/// <summary>
/// Try to parse a version string. YYYY.MM.DD.majr.minr or "any".
/// </summary>
/// <param name="input">Input to parse.</param>
/// <param name="result">GameVersion object.</param>
/// <returns>Success or failure.</returns>
public static bool TryParse(string input, out GameVersion result)
{
try
{
result = Parse(input);
return true;
}
catch
{
result = null;
return false;
}
}
/// <inheritdoc/>
public object Clone() => new GameVersion(this.Year, this.Month, this.Day, this.Major, this.Minor);
/// <inheritdoc/>
public int CompareTo(object obj)
{
if (obj == null)
return 1;
if (obj is GameVersion value)
{
return this.CompareTo(value);
}
else
{
throw new ArgumentException("Argument must be a GameVersion");
}
}
/// <inheritdoc/>
public int CompareTo(GameVersion value)
{
if (value == null)
return 1;
if (this == value)
return 0;
if (this == AnyVersion)
return 1;
if (value == AnyVersion)
return -1;
if (this.Year != value.Year)
return this.Year > value.Year ? 1 : -1;
if (this.Month != value.Month)
return this.Month > value.Month ? 1 : -1;
if (this.Day != value.Day)
return this.Day > value.Day ? 1 : -1;
if (this.Major != value.Major)
return this.Major > value.Major ? 1 : -1;
if (this.Minor != value.Minor)
return this.Minor > value.Minor ? 1 : -1;
return 0;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is not GameVersion value)
return false;
return this.Equals(value);
}
/// <inheritdoc/>
public bool Equals(GameVersion value)
{
if (value == null)
{
return false;
}
return
(this.Year == value.Year) &&
(this.Month == value.Month) &&
(this.Day == value.Day) &&
(this.Major == value.Major) &&
(this.Minor == value.Minor);
}
/// <inheritdoc/>
public override int GetHashCode()
{
var accumulator = 0;
// This might be horribly wrong, but it isn't used heavily.
accumulator |= this.Year.GetHashCode();
accumulator |= this.Month.GetHashCode();
accumulator |= this.Day.GetHashCode();
accumulator |= this.Major.GetHashCode();
accumulator |= this.Minor.GetHashCode();
return accumulator;
}
/// <inheritdoc/>
public override string ToString()
{
if (this.Year == -1 &&
this.Month == -1 &&
this.Day == -1 &&
this.Major == -1 &&
this.Minor == -1)
return "any";
return new StringBuilder()
.Append(string.Format("{0:D4}.", this.Year == -1 ? 0 : this.Year))
.Append(string.Format("{0:D2}.", this.Month == -1 ? 0 : this.Month))
.Append(string.Format("{0:D2}.", this.Day == -1 ? 0 : this.Day))
.Append(string.Format("{0:D4}.", this.Major == -1 ? 0 : this.Major))
.Append(string.Format("{0:D4}", this.Minor == -1 ? 0 : this.Minor))
.ToString();
}
}

View file

@ -1,79 +0,0 @@
using System;
using Newtonsoft.Json;
namespace Dalamud.Game;
/// <summary>
/// Converts a <see cref="GameVersion"/> to and from a string (e.g. <c>"2010.01.01.1234.5678"</c>).
/// </summary>
public sealed class GameVersionConverter : JsonConverter
{
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
}
else if (value is GameVersion)
{
writer.WriteValue(value.ToString());
}
else
{
throw new JsonSerializationException("Expected GameVersion object value");
}
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else
{
if (reader.TokenType == JsonToken.String)
{
try
{
return new GameVersion((string)reader.Value!);
}
catch (Exception ex)
{
throw new JsonSerializationException($"Error parsing GameVersion string: {reader.Value}", ex);
}
}
else
{
throw new JsonSerializationException($"Unexpected token or value when parsing GameVersion. Token: {reader.TokenType}, Value: {reader.Value}");
}
}
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(GameVersion);
}
}

View file

@ -635,9 +635,7 @@ internal class DalamudInterface : IDisposable, IServiceType
ImGui.EndMenu();
}
var startInfo = Service<DalamudStartInfo>.Get();
var logSynchronously = configuration.LogSynchronously;
if (ImGui.MenuItem("Log Synchronously", null, ref logSynchronously))
{
@ -645,10 +643,10 @@ internal class DalamudInterface : IDisposable, IServiceType
configuration.QueueSave();
EntryPoint.InitLogging(
startInfo.LogPath!,
startInfo.BootShowConsole,
dalamud.StartInfo.LogPath!,
dalamud.StartInfo.BootShowConsole,
configuration.LogSynchronously,
startInfo.LogName);
dalamud.StartInfo.LogName);
}
var antiDebug = Service<AntiDebug>.Get();
@ -767,7 +765,7 @@ internal class DalamudInterface : IDisposable, IServiceType
}
ImGui.MenuItem(Util.AssemblyVersion, false);
ImGui.MenuItem(startInfo.GameVersion?.ToString() ?? "Unknown version", false);
ImGui.MenuItem(dalamud.StartInfo.GameVersion?.ToString() ?? "Unknown version", false);
ImGui.MenuItem($"D: {Util.GetGitHash()}[{Util.GetGitCommitCount()}] CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.Interop.Resolver.Version}]", false);
ImGui.MenuItem($"CLR: {Environment.Version}", false);

View file

@ -563,10 +563,10 @@ internal class InterfaceManager : IDisposable, IServiceType
return;
}
var startInfo = Service<DalamudStartInfo>.Get();
var startInfo = Service<Dalamud>.Get().StartInfo;
var configuration = Service<DalamudConfiguration>.Get();
var iniFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath), "dalamudUI.ini"));
var iniFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(startInfo.ConfigurationPath)!, "dalamudUI.ini"));
try
{

View file

@ -39,7 +39,8 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe
private readonly Framework framework;
private readonly DataManager dataManager;
private readonly InterfaceManager im;
private readonly DalamudStartInfo startInfo;
private readonly ClientLanguage language;
private readonly Dictionary<string, TextureInfo> activeTextures = new();
@ -48,17 +49,18 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe
/// <summary>
/// Initializes a new instance of the <see cref="TextureManager"/> class.
/// </summary>
/// <param name="dalamud">Dalamud instance.</param>
/// <param name="framework">Framework instance.</param>
/// <param name="dataManager">DataManager instance.</param>
/// <param name="im">InterfaceManager instance.</param>
/// <param name="startInfo">DalamudStartInfo instance.</param>
[ServiceManager.ServiceConstructor]
public TextureManager(Framework framework, DataManager dataManager, InterfaceManager im, DalamudStartInfo startInfo)
public TextureManager(Dalamud dalamud, Framework framework, DataManager dataManager, InterfaceManager im)
{
this.framework = framework;
this.dataManager = dataManager;
this.im = im;
this.startInfo = startInfo;
this.language = (ClientLanguage)dalamud.StartInfo.Language;
this.framework.Update += this.FrameworkOnUpdate;
@ -115,7 +117,7 @@ internal class TextureManager : IDisposable, IServiceType, ITextureProvider, ITe
if (this.dataManager.FileExists(path))
return path;
language ??= this.startInfo.Language;
language ??= this.language;
var languageFolder = language switch
{
ClientLanguage.Japanese => "ja/",

View file

@ -66,7 +66,7 @@ public class BranchSwitcherWindow : Window
return;
}
var si = Service<DalamudStartInfo>.Get();
var si = Service<Dalamud>.Get().StartInfo;
var itemsArray = this.branches.Select(x => x.Key).ToArray();
ImGui.ListBox("Branch", ref this.selectedBranchIndex, itemsArray, itemsArray.Length);

View file

@ -26,7 +26,7 @@ internal class StartInfoWidget : IDataWindowWidget
/// <inheritdoc/>
public void Draw()
{
var startInfo = Service<DalamudStartInfo>.Get();
var startInfo = Service<Dalamud>.Get().StartInfo;
ImGui.Text(JsonConvert.SerializeObject(startInfo, Formatting.Indented));
}

View file

@ -1994,7 +1994,6 @@ internal class PluginInstallerWindow : Window, IDisposable
{
var configuration = Service<DalamudConfiguration>.Get();
var pluginManager = Service<PluginManager>.Get();
var startInfo = Service<DalamudStartInfo>.Get();
if (ImGui.BeginPopupContextItem("ItemContextMenu"))
{
@ -2022,10 +2021,10 @@ internal class PluginInstallerWindow : Window, IDisposable
Task.Run(() =>
{
pluginManager.PluginConfigs.Delete(manifest.InternalName);
var dir = pluginManager.PluginConfigs.GetDirectory(manifest.InternalName);
var path = Path.Combine(startInfo.PluginDirectory, manifest.InternalName);
if (Directory.Exists(path))
Directory.Delete(path, true);
if (Directory.Exists(dir))
Directory.Delete(dir, true);
})
.ContinueWith(task =>
{

View file

@ -74,7 +74,7 @@ internal partial class PluginManager : IDisposable, IServiceType
private readonly DalamudConfiguration configuration = Service<DalamudConfiguration>.Get();
[ServiceManager.ServiceDependency]
private readonly DalamudStartInfo startInfo = Service<DalamudStartInfo>.Get();
private readonly Dalamud dalamud = Service<Dalamud>.Get();
[ServiceManager.ServiceDependency]
private readonly ProfileManager profileManager = Service<ProfileManager>.Get();
@ -90,12 +90,12 @@ internal partial class PluginManager : IDisposable, IServiceType
[ServiceManager.ServiceConstructor]
private PluginManager()
{
this.pluginDirectory = new DirectoryInfo(this.startInfo.PluginDirectory!);
this.pluginDirectory = new DirectoryInfo(this.dalamud.StartInfo.PluginDirectory!);
if (!this.pluginDirectory.Exists)
this.pluginDirectory.Create();
this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || this.configuration.PluginSafeMode || this.startInfo.NoLoadPlugins;
this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || this.configuration.PluginSafeMode || this.dalamud.StartInfo.NoLoadPlugins;
try
{
@ -119,9 +119,9 @@ internal partial class PluginManager : IDisposable, IServiceType
this.configuration.QueueSave();
}
this.PluginConfigs = new PluginConfigurations(Path.Combine(Path.GetDirectoryName(this.startInfo.ConfigurationPath) ?? string.Empty, "pluginConfigs"));
this.PluginConfigs = new PluginConfigurations(Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath) ?? string.Empty, "pluginConfigs"));
var bannedPluginsJson = File.ReadAllText(Path.Combine(this.startInfo.AssetDirectory!, "UIRes", "bannedplugin.json"));
var bannedPluginsJson = File.ReadAllText(Path.Combine(this.dalamud.StartInfo.AssetDirectory!, "UIRes", "bannedplugin.json"));
this.bannedPlugins = JsonConvert.DeserializeObject<BannedPlugin[]>(bannedPluginsJson);
if (this.bannedPlugins == null)
{
@ -1168,7 +1168,7 @@ internal partial class PluginManager : IDisposable, IServiceType
}
// Applicable version
if (manifest.ApplicableVersion < this.startInfo.GameVersion)
if (manifest.ApplicableVersion < this.dalamud.StartInfo.GameVersion)
{
Log.Verbose($"Game version: {manifest.InternalName} - {manifest.AssemblyVersion} - {manifest.TestingAssemblyVersion}");
return false;

View file

@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Common.Game;
using Dalamud.Configuration.Internal;
using Dalamud.Game;
using Dalamud.Game.Gui.Dtr;
@ -336,7 +336,7 @@ internal class LocalPlugin : IDisposable
var framework = await Service<Framework>.GetAsync();
var ioc = await Service<ServiceContainer>.GetAsync();
var pluginManager = await Service<PluginManager>.GetAsync();
var startInfo = await Service<DalamudStartInfo>.GetAsync();
var dalamud = await Service<Dalamud>.GetAsync();
// UiBuilder constructor requires the following two.
await Service<InterfaceManager>.GetAsync();
@ -392,7 +392,7 @@ internal class LocalPlugin : IDisposable
if (pluginManager.IsManifestBanned(this.manifest) && !this.IsDev)
throw new BannedPluginException($"Unable to load {this.Name}, banned");
if (this.manifest.ApplicableVersion < startInfo.GameVersion)
if (this.manifest.ApplicableVersion < dalamud.StartInfo.GameVersion)
throw new InvalidPluginOperationException($"Unable to load {this.Name}, no applicable version");
if (this.manifest.DalamudApiLevel < PluginManager.DalamudApiLevel && !pluginManager.LoadAllApiLevels)
@ -624,7 +624,7 @@ internal class LocalPlugin : IDisposable
/// <returns>Whether or not this plugin shouldn't load.</returns>
public bool CheckPolicy()
{
var startInfo = Service<DalamudStartInfo>.Get();
var startInfo = Service<Dalamud>.Get().StartInfo;
var manager = Service<PluginManager>.Get();
if (startInfo.NoLoadPlugins)

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using Dalamud.Game;
using Dalamud.Common.Game;
using Dalamud.Plugin.Internal.Types.Manifest;
using Newtonsoft.Json;

View file

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
@ -83,16 +81,11 @@ internal static class ServiceManager
/// Initializes Provided Services and FFXIVClientStructs.
/// </summary>
/// <param name="dalamud">Instance of <see cref="Dalamud"/>.</param>
/// <param name="startInfo">Instance of <see cref="DalamudStartInfo"/>.</param>
/// <param name="fs">Instance of <see cref="ReliableFileStorage"/>.</param>
/// <param name="configuration">Instance of <see cref="DalamudConfiguration"/>.</param>
public static void InitializeProvidedServicesAndClientStructs(Dalamud dalamud, DalamudStartInfo startInfo, ReliableFileStorage fs, DalamudConfiguration configuration)
/// <param name="scanner">Instance of <see cref="TargetSigScanner"/>.</param>
public static void InitializeProvidedServices(Dalamud dalamud, ReliableFileStorage fs, DalamudConfiguration configuration, TargetSigScanner scanner)
{
// Initialize the process information.
var cacheDir = new DirectoryInfo(Path.Combine(startInfo.WorkingDirectory!, "cachedSigs"));
if (!cacheDir.Exists)
cacheDir.Create();
lock (LoadedServices)
{
void ProvideService<T>(T service) where T : IServiceType
@ -103,19 +96,10 @@ internal static class ServiceManager
}
ProvideService(dalamud);
ProvideService(startInfo);
ProvideService(fs);
ProvideService(configuration);
ProvideService(new ServiceContainer());
ProvideService(
new TargetSigScanner(
true, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}.json"))));
}
using (Timings.Start("CS Resolver Init"))
{
FFXIVClientStructs.Interop.Resolver.GetInstance.SetupSearchSpace(Service<TargetSigScanner>.Get().SearchBase, new FileInfo(Path.Combine(cacheDir.FullName, $"{startInfo.GameVersion}_cs.json")));
FFXIVClientStructs.Interop.Resolver.GetInstance.Resolve();
ProvideService(scanner);
}
}

View file

@ -58,7 +58,7 @@ public static class Troubleshooting
/// </summary>
internal static void LogTroubleshooting()
{
var startInfo = Service<DalamudStartInfo>.Get();
var startInfo = Service<Dalamud>.Get().StartInfo;
var configuration = Service<DalamudConfiguration>.Get();
var interfaceManager = Service<InterfaceManager>.GetNullable();
var pluginManager = Service<PluginManager>.GetNullable();
@ -72,7 +72,7 @@ public static class Troubleshooting
EverStartedLoadingPlugins = pluginManager?.InstalledPlugins.Where(x => x.HasEverStartedLoad).Select(x => x.InternalName).ToList(),
DalamudVersion = Util.AssemblyVersion,
DalamudGitHash = Util.GetGitHash(),
GameVersion = startInfo.GameVersion.ToString(),
GameVersion = startInfo.GameVersion?.ToString() ?? "Unknown",
Language = startInfo.Language.ToString(),
BetaKey = configuration.DalamudBetaKey,
DoPluginTest = configuration.DoPluginTest,