Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/ClientSource/ContentManagement/ContentPackage/ModProject.cs
Juan Pablo Arce 3f2c843247 Unstable v0.19.3.0
2022-09-02 15:10:56 -03:00

177 lines
6.2 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.IO;
namespace Barotrauma
{
public class ModProject
{
public class File
{
private File(string path, Type type)
{
Path = path.CleanUpPathCrossPlatform(correctFilenameCase: false);
Type = type switch
{
_ when !type.IsSubclassOf(typeof(ContentFile)) => throw new ArgumentException($"{type.Name} does not derive from {nameof(ContentFile)}"),
{ IsAbstract: true } => throw new ArgumentException($"{type.Name} is abstract"),
_ => type
};
}
private File(ContentFile f)
{
Path = f.Path.RawValue ?? "";
Type = f.GetType();
}
public static File FromContentFile(ContentFile file)
=> new File(file);
public static File FromPath<T>(string path) where T : ContentFile
=> new File(path, typeof(T));
/// <summary>
/// Prefer FromPath&lt;T&gt; when possible, this just exists
/// for cases where the type can only be decided at runtime
/// </summary>
public static File FromPath(string path, Type type)
=> new File(path, type);
public readonly string Path;
public readonly Type Type;
public XElement ToXElement()
{
if (Type is null) { throw new InvalidOperationException("Type must be set before calling ToXElement"); }
if (Path.IsNullOrEmpty()) { throw new InvalidOperationException("Path must be set before calling ToXElement"); }
return new XElement(Type.Name.RemoveFromEnd("File"), new XAttribute("file", Path));
}
}
public ModProject() { }
public ModProject(ContentPackage? contentPackage)
{
if (contentPackage is null) { return; }
Name = contentPackage.Name;
AltNames = contentPackage.AltNames.ToList();
files = contentPackage.Files.Select(File.FromContentFile).ToList();
ModVersion = IncrementModVersion(contentPackage.ModVersion);
IsCore = contentPackage is CorePackage;
SteamWorkshopId = contentPackage.SteamWorkshopId;
ExpectedHash = contentPackage.Hash;
InstallTime = contentPackage.InstallTime;
}
private string name = "";
public string Name
{
get => name;
set
{
var charsToRemove = Path.GetInvalidFileNameCharsCrossPlatform();
name = string.Concat(value.Where(c => !charsToRemove.Contains(c)));
}
}
public readonly List<string> AltNames = new List<string>();
private readonly List<File> files = new List<File>();
public IReadOnlyList<File> Files => files;
public string ModVersion = ContentPackage.DefaultModVersion;
public Md5Hash? ExpectedHash { get; private set; }
public bool IsCore = false;
public UInt64 SteamWorkshopId = 0;
public DateTime? InstallTime = null;
public bool HasFile(File file)
=> Files.Any(f =>
string.Equals(f.Path, file.Path, StringComparison.OrdinalIgnoreCase)
&& f.Type == file.Type);
public void AddFile(File file)
{
if (!HasFile(file))
{
files.Add(file);
DiscardHashAndInstallTime();
}
}
public void RemoveFile(File file)
{
if (HasFile(file))
{
files.Remove(file);
DiscardHashAndInstallTime();
}
}
public void DiscardHashAndInstallTime()
{
ExpectedHash = null;
InstallTime = null;
}
public static string IncrementModVersion(string modVersion)
{
//look for an integer at the end of the string and increment it
int startIndex = modVersion.Length - 1;
while (char.IsDigit(modVersion[startIndex])) { startIndex--; }
startIndex++;
if (startIndex >= modVersion.Length
|| !char.IsDigit(modVersion[startIndex])
|| !int.TryParse(
modVersion[startIndex..],
NumberStyles.Any,
CultureInfo.InvariantCulture,
out int theFinalInteger))
{
return modVersion;
}
return $"{modVersion[..startIndex]}{(theFinalInteger + 1).ToString(CultureInfo.InvariantCulture)}";
}
public XDocument ToXDocument()
{
XDocument doc = new XDocument();
XElement rootElement = new XElement("contentpackage");
void addRootAttribute<T>(string name, T value) where T : notnull
=> rootElement.Add(new XAttribute(name, value.ToString() ?? ""));
addRootAttribute("name", Name);
if (!ModVersion.IsNullOrEmpty()) { addRootAttribute("modversion", ModVersion); }
addRootAttribute("corepackage", IsCore);
if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); }
addRootAttribute("gameversion", GameMain.Version);
if (AltNames.Any()) { addRootAttribute("altnames", string.Join(",", AltNames)); }
if (ExpectedHash != null) { addRootAttribute("expectedhash", ExpectedHash.StringRepresentation); }
if (InstallTime != null) { addRootAttribute("installtime", ToolBox.Epoch.FromDateTime(InstallTime.Value)); }
files.ForEach(f => rootElement.Add(f.ToXElement()));
doc.Add(rootElement);
return doc;
}
public void Save(string path)
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
ToXDocument().SaveSafe(path);
}
}
}