[Milestone] PackageManagementService completed.

- ContentPackageInfoLookup Service completed.
- Implemented ModConfigService.cs
- Implemented some of the resource processors.
This commit is contained in:
MapleWheels
2025-02-26 12:48:34 -05:00
committed by Maplewheels
parent cb88d215fa
commit 52d920d969
78 changed files with 2331 additions and 422 deletions
@@ -5,6 +5,7 @@ using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Barotrauma.Steam;
namespace Barotrauma.LuaCs.Data;
@@ -14,9 +15,6 @@ public partial record ModConfigInfo : IModConfigInfo
{
public ContentPackage Package { get; init; }
public string PackageName { get; init; }
public TargetRunMode RunModes { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IAssemblyResourceInfo> Assemblies { get; init; }
public ImmutableArray<ILocalizationResourceInfo> Localizations { get; init; }
public ImmutableArray<ILuaScriptResourceInfo> LuaScripts { get; init; }
@@ -28,10 +26,15 @@ public partial record ModConfigInfo : IModConfigInfo
#region DataContracts
public record AssemblyResourceInfo : IAssemblyResourceInfo
public record AssemblyResourcesInfo(ImmutableArray<IAssemblyResourceInfo> Assemblies) : IAssembliesResourcesInfo;
public record LocalizationResourcesInfo(ImmutableArray<ILocalizationResourceInfo> Localizations) : ILocalizationsResourcesInfo;
public record LuaScriptsResourcesInfo(ImmutableArray<ILuaScriptResourceInfo> LuaScripts) : ILuaScriptsResourcesInfo;
public record ConfigResourcesInfo(ImmutableArray<IConfigResourceInfo> Configs) : IConfigsResourcesInfo;
public record ConfigProfilesResourcesInfo(ImmutableArray<IConfigProfileResourceInfo> ConfigProfiles) : IConfigProfilesResourcesInfo;
public record AssemblyResourceInfo : IAssemblyResourceInfo
{
public ContentPackage OwnerPackage { get; init; }
public string FallbackPackageName { get; init; }
public string FriendlyName { get; init; }
public bool IsScript { get; init; }
public string InternalName { get; init; }
@@ -41,138 +44,148 @@ public record AssemblyResourceInfo : IAssemblyResourceInfo
public int LoadPriority { get; init; }
public ImmutableArray<string> FilePaths { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IPackageDependencyInfo> Dependencies { get; init; }
public ImmutableArray<IPackageDependency> Dependencies { get; init; }
public bool Optional { get; init; }
}
public record DependencyInfo : IPackageDependencyInfo
public record PackageDependency : IPackageDependency
{
public PackageDependency(ContentPackage package, IPackageInfo dependencyInfo, string internalName)
{
Dependency = dependencyInfo ?? throw new ArgumentNullException(nameof(dependencyInfo));
OwnerPackage = package ?? throw new ArgumentNullException(nameof(package));
InternalName = internalName ?? throw new ArgumentNullException(nameof(internalName));
}
public string InternalName { get; init; }
public ContentPackage OwnerPackage { get; init; }
public string FolderPath { get; init; }
public string FallbackPackageName { get; init; }
public ulong SteamWorkshopId { get; init; }
public ContentPackage DependencyPackage { get; init; }
public bool IsMissing { get; init; }
public bool IsWorkshopInstallation { get; init; }
public virtual bool Equals(DependencyInfo other) => Equals(this, other);
public override int GetHashCode()
{
if (DependencyPackage is not null)
return DependencyPackage.GetHashCode();
if (SteamWorkshopId != 0)
return SteamWorkshopId.GetHashCode();
if (!FallbackPackageName.IsNullOrWhiteSpace() && !FolderPath.IsNullOrWhiteSpace())
return string.Concat(FallbackPackageName, FolderPath).GetHashCode();
if (!InternalName.IsNullOrWhiteSpace() && !FolderPath.IsNullOrWhiteSpace())
return string.Concat(InternalName, FolderPath).GetHashCode();
return base.GetHashCode();
}
bool IEqualityComparer<IPackageDependencyInfo>.Equals(IPackageDependencyInfo x, IPackageDependencyInfo y) => DependencyInfo.Equals(x, y);
public IPackageInfo Dependency { get; init; }
public override int GetHashCode() => Dependency.GetHashCode();
public static bool operator ==(IPackageDependencyInfo x, DependencyInfo y) => y?.Equals(x) ?? false;
public static bool operator !=(IPackageDependencyInfo x, DependencyInfo y) => y?.Equals(x) ?? false;
public static bool Equals(IPackageDependencyInfo x, IPackageDependencyInfo y)
{
if (x is null)
return false;
if (y is null)
return false;
if (x == y)
return true;
if (x.DependencyPackage is not null && y.DependencyPackage is not null)
return y.DependencyPackage == x.DependencyPackage;
if (!x.FolderPath.IsNullOrWhiteSpace()
&& !y.FolderPath.IsNullOrWhiteSpace()
&& y.FolderPath == x.FolderPath)
return true;
if (!x.FolderPath.IsNullOrWhiteSpace() != !y.FolderPath.IsNullOrWhiteSpace())
return false;
if (!x.FallbackPackageName.IsNullOrWhiteSpace()
&& !y.FallbackPackageName.IsNullOrWhiteSpace()
&& y.FallbackPackageName == x.FallbackPackageName)
return true;
if (x.SteamWorkshopId != 0 && y.SteamWorkshopId == x.SteamWorkshopId)
return true;
}
return false;
}
public record PackageInfo : IPackageInfo
{
public string Name { get; private set; }
public ulong SteamWorkshopId { get; private set; }
public uint Id { get; private set; }
/// <summary>
/// Returns the hash code unique for the package reference.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
/// <remarks>The hash should only be collision-free when referring to different packages.</remarks>
public int GetHashCode(IPackageDependencyInfo obj)
{
int hashCode = Seed;
hashCode = ApplyHashString(hashCode, obj.FallbackPackageName);
hashCode = ApplyHashString(hashCode, obj.InternalName);
if (obj.SteamWorkshopId > 0)
hashCode ^= (int)obj.SteamWorkshopId;
private readonly Func<IPackageInfo, ContentPackage> _getPackage;
int ApplyHashString(int currentValue, string str)
public ContentPackage GetPackage() => _getPackage?.Invoke(this) ?? null;
public void UpdateInfo(string name, ulong steamId, uint packageId)
{
if (name.IsNullOrWhiteSpace() || steamId == 0 || packageId == 0)
{
try
{
if (str is null || str.Length < 1)
return currentValue;
byte[] b = Encoding.UTF8.GetBytes(str);
for (int i = 0; i < Math.Min(24, b.Length-1); i++)
currentValue ^= b[i];
return currentValue;
}
catch
{
return currentValue;
}
throw new ArgumentException(
$"{nameof(PackageInfo)}: You cannot update a package with an invalid name or steam id with a valid id, or vice-versa.");
}
return hashCode;
Name = name;
SteamWorkshopId = steamId;
Id = packageId;
}
public PackageInfo(ContentPackage package, uint id, Func<IPackageInfo, ContentPackage> getPackage)
{
if (package is null)
throw new ArgumentNullException($"{nameof(PackageInfo)}: package is null");
if (id == 0)
throw new ArgumentNullException($"{nameof(PackageInfo)}: id is zero.");
this.Name = package.Name;
this.SteamWorkshopId = package.TryExtractSteamWorkshopId(out var sId) ? sId.Value : 0;
this.Id = id;
this._getPackage = getPackage;
}
private static readonly int Seed = new Random().Next(436457, int.MaxValue-900);
public PackageInfo(string name, ulong steamWorkshopId, uint id, Func<IPackageInfo, ContentPackage> getPackage)
{
Name = !name.IsNullOrWhiteSpace() ? name : throw new ArgumentNullException($"{nameof(PackageInfo)}: name cannot be null or empty.");
SteamWorkshopId = steamWorkshopId != 0 ? steamWorkshopId : throw new ArgumentNullException($"{nameof(PackageInfo)}: steam id cannot be 0.");
this.Id = id;
this._getPackage = getPackage;
}
public PackageInfo(string name, uint id, Func<IPackageInfo, ContentPackage> getPackage)
{
Name = name ?? throw new ArgumentNullException($"{nameof(PackageInfo)}: name cannot be null or empty.");
this.SteamWorkshopId = 0;
this.Id = id;
this._getPackage = getPackage;
}
public PackageInfo(ulong steamWorkshopId, uint id, Func<IPackageInfo, ContentPackage> getPackage)
{
SteamWorkshopId = steamWorkshopId != 0 ? steamWorkshopId : throw new ArgumentNullException($"{nameof(PackageInfo)}: steamid cannot be 0.");
this.Id = id;
this._getPackage = getPackage;
}
public override int GetHashCode()
{
return (int)Id;
}
public virtual bool Equals(PackageInfo other)
{
return ((IEquatable<IPackageInfo>)this).Equals(other);
}
}
public record ConfigResourceInfo : IConfigResourceInfo
{
public Platform SupportedPlatforms { get; init; }
public Target SupportedTargets { get; init; }
public int LoadPriority { get; init; }
public ImmutableArray<string> FilePaths { get; init; }
public bool Optional { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IPackageDependency> Dependencies { get; init; }
public string InternalName { get; init; }
public ContentPackage OwnerPackage { get; init; }
}
public record ConfigProfileResourceInfo : IConfigProfileResourceInfo
{
public Platform SupportedPlatforms { get; init; }
public Target SupportedTargets { get; init; }
public int LoadPriority { get; init; }
public ImmutableArray<string> FilePaths { get; init; }
public bool Optional { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IPackageDependency> Dependencies { get; init; }
public string InternalName { get; init; }
public ContentPackage OwnerPackage { get; init; }
}
public record LocalizationResourceInfo : ILocalizationResourceInfo
{
public string InternalName { get; init; }
public ContentPackage OwnerPackage { get; init; }
public string FallbackPackageName { get; init; }
public CultureInfo TargetCulture { get; init; }
public Platform SupportedPlatforms { get; init; }
public Target SupportedTargets { get; init; }
public int LoadPriority { get; init; }
public ImmutableArray<string> FilePaths { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IPackageDependencyInfo> Dependencies { get; init; }
public ImmutableArray<IPackageDependency> Dependencies { get; init; }
public bool Optional { get; init; }
}
public readonly struct LuaScriptScriptResourceInfo : ILuaScriptResourceInfo
{
public ContentPackage OwnerPackage { get; init; }
public string FallbackPackageName { get; init; }
public Platform SupportedPlatforms { get; init; }
public Target SupportedTargets { get; init; }
public int LoadPriority { get; init; }
public ImmutableArray<string> FilePaths { get; init; }
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
public ImmutableArray<IPackageDependencyInfo> Dependencies { get; init; }
public ImmutableArray<IPackageDependency> Dependencies { get; init; }
public bool Optional { get; init; }
public string InternalName { get; init; }
public bool LazyLoad { get; init; }
public bool IsAutorun { get; init; }
}
#endregion