- XML GUI Asset service implemented (alpha, requires testing).
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs.Data;
|
||||||
|
|
||||||
|
public interface IStylesResourceInfo : IBaseResourceInfo { }
|
||||||
|
|
||||||
|
public record StylesResourceInfo : BaseResourceInfo, IStylesResourceInfo { }
|
||||||
|
|
||||||
|
public partial interface IModConfigInfo
|
||||||
|
{
|
||||||
|
public ImmutableArray<IStylesResourceInfo> Styles { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial record ModConfigInfo
|
||||||
|
{
|
||||||
|
public ImmutableArray<IStylesResourceInfo> Styles { get; init; }
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Barotrauma.CharacterEditor;
|
using Barotrauma.CharacterEditor;
|
||||||
using Barotrauma.LuaCs;
|
using Barotrauma.LuaCs;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
|
||||||
// ReSharper disable ObjectCreationAsStatement
|
// ReSharper disable ObjectCreationAsStatement
|
||||||
|
|
||||||
@@ -66,6 +67,15 @@ namespace Barotrauma
|
|||||||
return isCsValueChanged;
|
return isCsValueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetupServicesProviderClient(IServicesProvider serviceProvider)
|
||||||
|
{
|
||||||
|
serviceProvider.RegisterServiceType<IUIStylesService, UIStylesService>(ServiceLifetime.Singleton);
|
||||||
|
// supplied via factory
|
||||||
|
//serviceProvider.RegisterServiceType<IUIStylesCollection, UIStylesCollection>(ServiceLifetime.Transient);
|
||||||
|
serviceProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, IStylesResourceInfo>, ModConfigFileParserService>(ServiceLifetime.Transient);
|
||||||
|
serviceProvider.RegisterServiceType<IUIStylesCollection.IFactory, UIStylesCollection.Factory>(ServiceLifetime.Transient);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles changes in game states tracked by screen changes.
|
/// Handles changes in game states tracked by screen changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
using FluentResults;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
public interface IUIStylesCollection : IService
|
||||||
|
{
|
||||||
|
public interface IFactory : IService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a new <see cref="IUIStylesCollection"/> for-each <see cref="ContentPath"/> in the given
|
||||||
|
/// <see cref="IStylesResourceInfo.FilePaths"/> or empty is none.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info"></param>
|
||||||
|
/// <param name="storageService"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IEnumerable<IUIStylesCollection> CreateInstance(IStylesResourceInfo info, IStorageService storageService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The assigned/target <see cref="ContentPath"/> for this collection.
|
||||||
|
/// </summary>
|
||||||
|
public ContentPath Path { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="GUIFont"/> with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<GUIFont> GetFont(string name);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="GUISprite"/> with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<GUISprite> GetSprite(string name);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="GUISpriteSheet"/> with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<GUISpriteSheet> GetSpriteSheet(string name);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="GUICursor"/> with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<GUICursor> GetCursor(string name);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="GUIColor"/> with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<GUIColor> GetColor(string name);
|
||||||
|
|
||||||
|
#region BAROTRAUMA.UISTYLEFILE
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Definition of <see cref="HashlessFile.LoadFile"/>
|
||||||
|
/// </summary>
|
||||||
|
internal void LoadFile();
|
||||||
|
/// <summary>
|
||||||
|
/// Definition of <see cref="HashlessFile.UnloadFile"/>
|
||||||
|
/// </summary>
|
||||||
|
internal void UnloadFile();
|
||||||
|
/// <summary>
|
||||||
|
/// Definition of <see cref="HashlessFile.Sort"/>
|
||||||
|
/// </summary>
|
||||||
|
internal void Sort();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System.Collections.Immutable;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
using FluentResults;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
public interface IUIStylesService : IReusableService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the first loaded <see cref="GUIColor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="package">The target <see cref="ContentPackage"/></param>
|
||||||
|
/// <param name="internalName">The targets <see cref="IDataInfo.InternalName"/> as specified in the ModConfig.xml.</param>
|
||||||
|
/// <param name="assetName">The asset's name as specified in the styles XML file.</param>
|
||||||
|
/// <returns>A <see cref="FluentResults.Result"/> indicating success, and the target if succeeded.</returns>
|
||||||
|
public Result<GUIColor> GetColor(ContentPackage package, string internalName, string assetName);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the loaded <see cref="GUICursor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="package">The target <see cref="ContentPackage"/></param>
|
||||||
|
/// <param name="internalName">The targets <see cref="IDataInfo.InternalName"/> as specified in the ModConfig.xml.</param>
|
||||||
|
/// <param name="assetName">The asset's name as specified in the styles XML file.</param>
|
||||||
|
/// <returns>A <see cref="FluentResults.Result"/> indicating success, and the target if succeeded.</returns>
|
||||||
|
public Result<GUICursor> GetCursor(ContentPackage package, string internalName, string assetName);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the loaded <see cref="GUIFont"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="package">The target <see cref="ContentPackage"/></param>
|
||||||
|
/// <param name="internalName">The targets <see cref="IDataInfo.InternalName"/> as specified in the ModConfig.xml.</param>
|
||||||
|
/// <param name="assetName">The asset's name as specified in the styles XML file.</param>
|
||||||
|
/// <returns>A <see cref="FluentResults.Result"/> indicating success, and the target if succeeded.</returns>
|
||||||
|
public Result<GUIFont> GetFont(ContentPackage package, string internalName, string assetName);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the loaded <see cref="GUISprite"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="package">The target <see cref="ContentPackage"/></param>
|
||||||
|
/// <param name="internalName">The targets <see cref="IDataInfo.InternalName"/> as specified in the ModConfig.xml.</param>
|
||||||
|
/// <param name="assetName">The asset's name as specified in the styles XML file.</param>
|
||||||
|
/// <returns>A <see cref="FluentResults.Result"/> indicating success, and the target if succeeded.</returns>
|
||||||
|
public Result<GUISprite> GetSprite(ContentPackage package, string internalName, string assetName);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the loaded <see cref="GUISpriteSheet"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="package">The target <see cref="ContentPackage"/></param>
|
||||||
|
/// <param name="internalName">The targets <see cref="IDataInfo.InternalName"/> as specified in the ModConfig.xml.</param>
|
||||||
|
/// <param name="assetName">The asset's name as specified in the styles XML file.</param>
|
||||||
|
/// <returns>A <see cref="FluentResults.Result"/> indicating success, and the target if succeeded.</returns>
|
||||||
|
public Result<GUISpriteSheet> GetSpriteSheet(ContentPackage package, string internalName, string assetName);
|
||||||
|
|
||||||
|
public FluentResults.Result LoadAssets(ImmutableArray<IStylesResourceInfo> resources);
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadPackages(ImmutableArray<ContentPackage> packages);
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadPackage(ContentPackage package);
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadAllPackages();
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
using FluentResults;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
public sealed partial class ModConfigFileParserService :
|
||||||
|
IParserServiceAsync<ResourceParserInfo, IStylesResourceInfo>
|
||||||
|
{
|
||||||
|
async Task<Result<IStylesResourceInfo>> IParserServiceAsync<ResourceParserInfo, IStylesResourceInfo>.TryParseResourceAsync(ResourceParserInfo src)
|
||||||
|
{
|
||||||
|
using var lck = await _operationsLock.AcquireReaderLock();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
if (CheckThrowNullRefs(src, "Style") is { IsFailed: true } fail)
|
||||||
|
return fail;
|
||||||
|
|
||||||
|
var runtimeEnv = GetRuntimeEnvironment(src.Element);
|
||||||
|
var fileResults = await UnsafeGetCheckedFiles(src.Element, src.Owner, ".xml");
|
||||||
|
|
||||||
|
if (fileResults.IsFailed)
|
||||||
|
return FluentResults.Result.Fail(fileResults.Errors);
|
||||||
|
|
||||||
|
return new StylesResourceInfo()
|
||||||
|
{
|
||||||
|
SupportedPlatforms = runtimeEnv.Platform,
|
||||||
|
SupportedTargets = Target.Client, // clientside only
|
||||||
|
LoadPriority = src.Element.GetAttributeInt("LoadPriority", 0),
|
||||||
|
FilePaths = fileResults.Value,
|
||||||
|
Optional = src.Element.GetAttributeBool("Optional", false),
|
||||||
|
InternalName = src.Element.GetAttributeString("Name", string.Empty),
|
||||||
|
OwnerPackage = src.Owner,
|
||||||
|
RequiredPackages = src.Required,
|
||||||
|
IncompatiblePackages = src.Incompatible
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ImmutableArray<Result<IStylesResourceInfo>>> TryParseResourcesAsync(IEnumerable<ResourceParserInfo> sources)
|
||||||
|
{
|
||||||
|
return await this.TryParseGenericResourcesAsync<IStylesResourceInfo>(sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
using FluentResults;
|
||||||
|
using Microsoft.Toolkit.Diagnostics;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
public class UIStylesCollection : HashlessFile, IUIStylesCollection
|
||||||
|
{
|
||||||
|
public class Factory : IUIStylesCollection.IFactory
|
||||||
|
{
|
||||||
|
public IEnumerable<IUIStylesCollection> CreateInstance(IStylesResourceInfo info, IStorageService storageService)
|
||||||
|
{
|
||||||
|
Guard.IsNotNull(info, nameof(info));
|
||||||
|
Guard.IsNotNull(info.OwnerPackage, nameof(info.OwnerPackage));
|
||||||
|
if (info.FilePaths.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return ImmutableArray<IUIStylesCollection>.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = ImmutableArray.CreateBuilder<IUIStylesCollection>();
|
||||||
|
foreach (var contentPath in info.FilePaths)
|
||||||
|
{
|
||||||
|
builder.Add(new UIStylesCollection(contentPath, storageService));
|
||||||
|
}
|
||||||
|
return builder.ToImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
//ignore, stateless service
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDisposed => false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<string, GUIFont> _fonts = new();
|
||||||
|
private readonly ConcurrentDictionary<string, GUISprite> _sprites = new();
|
||||||
|
private readonly ConcurrentDictionary<string, GUISpriteSheet> _spriteSheets = new();
|
||||||
|
private readonly ConcurrentDictionary<string, GUICursor> _cursors = new();
|
||||||
|
private readonly ConcurrentDictionary<string, GUIColor> _colors = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only for internal reference.
|
||||||
|
/// </summary>
|
||||||
|
private UIStyleFile _fakeFile;
|
||||||
|
|
||||||
|
private IStorageService _storageService;
|
||||||
|
|
||||||
|
public UIStylesCollection(ContentPath path, IStorageService storageService) : base(path.ContentPackage, path)
|
||||||
|
{
|
||||||
|
Guard.IsNotNull(path, nameof(path));
|
||||||
|
Guard.IsNotNull(path.ContentPackage, nameof(path.ContentPackage));
|
||||||
|
_storageService = storageService;
|
||||||
|
_fakeFile = new UIStyleFile(path.ContentPackage, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new ContentPath Path => base.Path;
|
||||||
|
|
||||||
|
public Result<GUIFont> GetFont(string name)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (_fonts.TryGetValue(name, out var asset))
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FluentResults.Result.Fail($"{nameof(GetFont)}: Failed to find the font with the name '{name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUISprite> GetSprite(string name)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (_sprites.TryGetValue(name, out var asset))
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FluentResults.Result.Fail($"{nameof(GetSprite)}: Failed to find the sprite with the name '{name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUISpriteSheet> GetSpriteSheet(string name)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (_spriteSheets.TryGetValue(name, out var asset))
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FluentResults.Result.Fail($"{nameof(GetSpriteSheet)}: Failed to find the spritesheet with the name '{name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUICursor> GetCursor(string name)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (_cursors.TryGetValue(name, out var asset))
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FluentResults.Result.Fail($"{nameof(GetCursor)}: Failed to find the cursor with the name '{name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUIColor> GetColor(string name)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (_colors.TryGetValue(name, out var asset))
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FluentResults.Result.Fail($"{nameof(GetColor)}: Failed to find the color with the name '{name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadFile()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
if (_storageService.LoadPackageXml(Path) is not { IsSuccess: true } result)
|
||||||
|
{
|
||||||
|
DebugConsole.LogError($"Failed to load xml from {Path.FullPath}.");
|
||||||
|
ThrowHelper.ThrowArgumentException($"Failed to load xml from {Path.FullPath}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var root = result.Value.Root?.FromPackage(Path.ContentPackage);
|
||||||
|
if (root is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var styleElement = root.Name.LocalName.ToLowerInvariant() == "style" ? root : root.GetChildElement("style");
|
||||||
|
if (styleElement is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var childElements = styleElement.GetChildElements("Font");
|
||||||
|
if (childElements is not null)
|
||||||
|
AddToList<GUIFont, GUIFontPrefab>(_fonts, childElements, _fakeFile);
|
||||||
|
|
||||||
|
childElements = styleElement.GetChildElements("Sprite");
|
||||||
|
if (childElements is not null)
|
||||||
|
AddToList<GUISprite, GUISpritePrefab>(_sprites, childElements, _fakeFile);
|
||||||
|
|
||||||
|
childElements = styleElement.GetChildElements("Spritesheet");
|
||||||
|
if (childElements is not null)
|
||||||
|
AddToList<GUISpriteSheet, GUISpriteSheetPrefab>(_spriteSheets, childElements, _fakeFile);
|
||||||
|
|
||||||
|
childElements = styleElement.GetChildElements("Cursor");
|
||||||
|
if (childElements is not null)
|
||||||
|
AddToList<GUICursor, GUICursorPrefab>(_cursors, childElements, _fakeFile);
|
||||||
|
|
||||||
|
childElements = styleElement.GetChildElements("Color");
|
||||||
|
if (childElements is not null)
|
||||||
|
AddToList<GUIColor, GUIColorPrefab>(_colors, childElements, _fakeFile);
|
||||||
|
|
||||||
|
void AddToList<T1, T2>(ConcurrentDictionary<string, T1> dict, IEnumerable<ContentXElement> elem, UIStyleFile file) where T1 : GUISelector<T2> where T2 : GUIPrefab
|
||||||
|
{
|
||||||
|
foreach (ContentXElement prefabElement in elem)
|
||||||
|
{
|
||||||
|
string name = prefabElement.GetAttributeString("name", string.Empty);
|
||||||
|
if (name != string.Empty)
|
||||||
|
{
|
||||||
|
var prefab = (T2)Activator.CreateInstance(typeof(T2), new object[]{ prefabElement, file })!;
|
||||||
|
if (!dict.ContainsKey(name))
|
||||||
|
dict[name] = (T1)Activator.CreateInstance(typeof(T1), new object[] { name })!;
|
||||||
|
dict[name].Prefabs.Add(prefab, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UnloadFile()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
_fonts.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_sprites.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_spriteSheets.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_cursors.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_colors.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Sort()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
_fonts.Values.ForEach(p => p.Prefabs.Sort());
|
||||||
|
_sprites.Values.ForEach(p => p.Prefabs.Sort());
|
||||||
|
_spriteSheets.Values.ForEach(p => p.Prefabs.Sort());
|
||||||
|
_cursors.Values.ForEach(p => p.Prefabs.Sort());
|
||||||
|
_colors.Values.ForEach(p => p.Prefabs.Sort());
|
||||||
|
}
|
||||||
|
|
||||||
|
#region INTERNAL_DISPOSE
|
||||||
|
|
||||||
|
private readonly AsyncReaderWriterLock _lock = new();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fonts.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_sprites.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_spriteSheets.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_cursors.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
_colors.Values.ForEach(p => p.Prefabs.RemoveByFile(_fakeFile));
|
||||||
|
|
||||||
|
_fonts.Clear();
|
||||||
|
_sprites.Clear();
|
||||||
|
_spriteSheets.Clear();
|
||||||
|
_cursors.Clear();
|
||||||
|
_colors.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _isDisposed;
|
||||||
|
public bool IsDisposed
|
||||||
|
{
|
||||||
|
get => ModUtils.Threading.GetBool(ref _isDisposed);
|
||||||
|
private set => ModUtils.Threading.SetBool(ref _isDisposed, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,350 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using Barotrauma.LuaCs.Data;
|
||||||
|
using FluentResults;
|
||||||
|
using Microsoft.Toolkit.Diagnostics;
|
||||||
|
|
||||||
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
|
public class UIStylesService : IUIStylesService
|
||||||
|
{
|
||||||
|
#region DISPOSAL
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var collection in _stylesCollections.Values.SelectMany(c => c))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
collection.Dispose();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_stylesCollections.Clear();
|
||||||
|
_storageService.Dispose();
|
||||||
|
_stylesCollectionFactory.Dispose();
|
||||||
|
|
||||||
|
_storageService = null;
|
||||||
|
_stylesCollectionFactory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _isDisposed = 0;
|
||||||
|
public bool IsDisposed
|
||||||
|
{
|
||||||
|
get => ModUtils.Threading.GetBool(ref _isDisposed);
|
||||||
|
private set => ModUtils.Threading.SetBool(ref _isDisposed, value);
|
||||||
|
}
|
||||||
|
public FluentResults.Result Reset()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
var result = FluentResults.Result.Ok();
|
||||||
|
|
||||||
|
foreach (var collection in _stylesCollections.Values.SelectMany(c => c))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
collection.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
result.WithError(new ExceptionalError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_stylesCollections.Clear();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly AsyncReaderWriterLock _lock = new();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private IStorageService _storageService;
|
||||||
|
private IUIStylesCollection.IFactory _stylesCollectionFactory;
|
||||||
|
|
||||||
|
private ConcurrentDictionary<(ContentPackage Package, string InternalName), ImmutableArray<IUIStylesCollection>>
|
||||||
|
_stylesCollections = new();
|
||||||
|
|
||||||
|
public UIStylesService(IUIStylesCollection.IFactory stylesCollectionFactory, IStorageService storageService)
|
||||||
|
{
|
||||||
|
_stylesCollectionFactory = stylesCollectionFactory;
|
||||||
|
_storageService = storageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUIColor> GetColor(ContentPackage package, string internalName, string assetName)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
Guard.IsNotNull(package, nameof(package));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(assetName, nameof(assetName));
|
||||||
|
|
||||||
|
if (!_stylesCollections.TryGetValue((package, internalName), out var collection)
|
||||||
|
|| collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return FluentResults.Result.Fail(
|
||||||
|
$"{nameof(UIStylesService)}: No styles loaded for [ContentPackage].[InternalName] of: [{package.Name}].[{internalName}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedResult = new FluentResults.Result();
|
||||||
|
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
var res = stylesCollection.GetColor(assetName);
|
||||||
|
if (res.IsSuccess)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedResult.WithErrors(res.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUICursor> GetCursor(ContentPackage package, string internalName, string assetName)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
Guard.IsNotNull(package, nameof(package));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(assetName, nameof(assetName));
|
||||||
|
|
||||||
|
if (!_stylesCollections.TryGetValue((package, internalName), out var collection)
|
||||||
|
|| collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return FluentResults.Result.Fail(
|
||||||
|
$"{nameof(UIStylesService)}: No styles loaded for [ContentPackage].[InternalName] of: [{package.Name}].[{internalName}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedResult = new FluentResults.Result();
|
||||||
|
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
var res = stylesCollection.GetCursor(assetName);
|
||||||
|
if (res.IsSuccess)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedResult.WithErrors(res.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUIFont> GetFont(ContentPackage package, string internalName, string assetName)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
Guard.IsNotNull(package, nameof(package));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(assetName, nameof(assetName));
|
||||||
|
|
||||||
|
if (!_stylesCollections.TryGetValue((package, internalName), out var collection)
|
||||||
|
|| collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return FluentResults.Result.Fail(
|
||||||
|
$"{nameof(UIStylesService)}: No styles loaded for [ContentPackage].[InternalName] of: [{package.Name}].[{internalName}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedResult = new FluentResults.Result();
|
||||||
|
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
var res = stylesCollection.GetFont(assetName);
|
||||||
|
if (res.IsSuccess)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedResult.WithErrors(res.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUISprite> GetSprite(ContentPackage package, string internalName, string assetName)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
Guard.IsNotNull(package, nameof(package));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(assetName, nameof(assetName));
|
||||||
|
|
||||||
|
if (!_stylesCollections.TryGetValue((package, internalName), out var collection)
|
||||||
|
|| collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return FluentResults.Result.Fail(
|
||||||
|
$"{nameof(UIStylesService)}: No styles loaded for [ContentPackage].[InternalName] of: [{package.Name}].[{internalName}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedResult = new FluentResults.Result();
|
||||||
|
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
var res = stylesCollection.GetSprite(assetName);
|
||||||
|
if (res.IsSuccess)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedResult.WithErrors(res.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<GUISpriteSheet> GetSpriteSheet(ContentPackage package, string internalName, string assetName)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
Guard.IsNotNull(package, nameof(package));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||||
|
Guard.IsNotNullOrWhiteSpace(assetName, nameof(assetName));
|
||||||
|
|
||||||
|
if (!_stylesCollections.TryGetValue((package, internalName), out var collection)
|
||||||
|
|| collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
return FluentResults.Result.Fail(
|
||||||
|
$"{nameof(UIStylesService)}: No styles loaded for [ContentPackage].[InternalName] of: [{package.Name}].[{internalName}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var failedResult = new FluentResults.Result();
|
||||||
|
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
var res = stylesCollection.GetSpriteSheet(assetName);
|
||||||
|
if (res.IsSuccess)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
failedResult.WithErrors(res.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentResults.Result LoadAssets(ImmutableArray<IStylesResourceInfo> resources)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
if (resources.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
ThrowHelper.ThrowArgumentNullException(nameof(resources));
|
||||||
|
}
|
||||||
|
|
||||||
|
var operationSuccess = FluentResults.Result.Ok();
|
||||||
|
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
var builder = ImmutableArray.CreateBuilder<IUIStylesCollection>();
|
||||||
|
if (_stylesCollections.TryGetValue((resource.OwnerPackage, resource.InternalName), out var collection))
|
||||||
|
{
|
||||||
|
builder.AddRange(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var newCollections = _stylesCollectionFactory.CreateInstance(resource, _storageService).ToImmutableArray();
|
||||||
|
foreach (var stylesCollection in newCollections)
|
||||||
|
{
|
||||||
|
stylesCollection.LoadFile();
|
||||||
|
}
|
||||||
|
builder.AddRange(newCollections);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
operationSuccess.WithError(new ExceptionalError(e));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stylesCollections[(resource.OwnerPackage, resource.InternalName)] = builder.ToImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return operationSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadPackages(ImmutableArray<ContentPackage> packages)
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
var toRemove = _stylesCollections
|
||||||
|
.Select(c => c.Key)
|
||||||
|
.Where(c => packages.Contains(c.Package))
|
||||||
|
.ToImmutableArray();
|
||||||
|
|
||||||
|
var result = FluentResults.Result.Ok();
|
||||||
|
|
||||||
|
foreach (var key in toRemove)
|
||||||
|
{
|
||||||
|
if (_stylesCollections.TryRemove(key, out var collection) && !collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stylesCollection.UnloadFile();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
result.WithError(new ExceptionalError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadPackage(ContentPackage package)
|
||||||
|
{
|
||||||
|
// Yes, this is very cursed/inefficient. We don't care.
|
||||||
|
return UnloadPackages(new [] { package }.ToImmutableArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FluentResults.Result UnloadAllPackages()
|
||||||
|
{
|
||||||
|
using var lck = _lock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
|
var result = FluentResults.Result.Ok();
|
||||||
|
|
||||||
|
foreach (var key in _stylesCollections.Keys.ToImmutableArray())
|
||||||
|
{
|
||||||
|
if (_stylesCollections.TryRemove(key, out var collection) && !collection.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
foreach (var stylesCollection in collection)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stylesCollection.UnloadFile();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
result.WithError(new ExceptionalError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=clientsource/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
@@ -15,7 +15,7 @@ namespace Barotrauma.LuaCs.Data;
|
|||||||
|
|
||||||
#region ModConfigurationInfo
|
#region ModConfigurationInfo
|
||||||
|
|
||||||
public record ModConfigInfo : IModConfigInfo
|
public partial record ModConfigInfo : IModConfigInfo
|
||||||
{
|
{
|
||||||
public ContentPackage Package { get; init; }
|
public ContentPackage Package { get; init; }
|
||||||
public ImmutableArray<IAssemblyResourceInfo> Assemblies { get; init; }
|
public ImmutableArray<IAssemblyResourceInfo> Assemblies { get; init; }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma.LuaCs.Data;
|
namespace Barotrauma.LuaCs.Data;
|
||||||
|
|
||||||
public interface IModConfigInfo : IAssembliesResourcesInfo,
|
public partial interface IModConfigInfo : IAssembliesResourcesInfo,
|
||||||
ILuaScriptsResourcesInfo, IConfigsResourcesInfo
|
ILuaScriptsResourcesInfo, IConfigsResourcesInfo
|
||||||
{
|
{
|
||||||
// package info
|
// package info
|
||||||
|
|||||||
@@ -209,6 +209,10 @@ namespace Barotrauma
|
|||||||
servicesProvider.RegisterServiceType<IConfigServiceConfig, ConfigServiceConfig>(ServiceLifetime.Singleton);
|
servicesProvider.RegisterServiceType<IConfigServiceConfig, ConfigServiceConfig>(ServiceLifetime.Singleton);
|
||||||
servicesProvider.RegisterServiceType<IPackageManagementServiceConfig, PackageManagementServiceConfig>(ServiceLifetime.Singleton);
|
servicesProvider.RegisterServiceType<IPackageManagementServiceConfig, PackageManagementServiceConfig>(ServiceLifetime.Singleton);
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
SetupServicesProviderClient(servicesProvider);
|
||||||
|
#endif
|
||||||
|
|
||||||
// gen IL
|
// gen IL
|
||||||
servicesProvider.CompileAndRun();
|
servicesProvider.CompileAndRun();
|
||||||
return servicesProvider;
|
return servicesProvider;
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ using Microsoft.Toolkit.Diagnostics;
|
|||||||
|
|
||||||
namespace Barotrauma.LuaCs;
|
namespace Barotrauma.LuaCs;
|
||||||
|
|
||||||
public sealed class ModConfigFileParserService :
|
public sealed partial class ModConfigFileParserService :
|
||||||
IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo>,
|
IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo>,
|
||||||
IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo>,
|
IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo>,
|
||||||
IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo>
|
IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo>
|
||||||
|
|||||||
@@ -23,12 +23,18 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
private IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo> _assemblyParserService;
|
private IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo> _assemblyParserService;
|
||||||
private IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo> _luaScriptParserService;
|
private IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo> _luaScriptParserService;
|
||||||
private IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo> _configParserService;
|
private IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo> _configParserService;
|
||||||
|
#if CLIENT
|
||||||
|
private IParserServiceAsync<ResourceParserInfo, IStylesResourceInfo> _stylesParserService;
|
||||||
|
#endif
|
||||||
private readonly AsyncReaderWriterLock _operationsLock = new();
|
private readonly AsyncReaderWriterLock _operationsLock = new();
|
||||||
|
|
||||||
public ModConfigService(IStorageService storageService,
|
public ModConfigService(IStorageService storageService,
|
||||||
IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo> assemblyParserService,
|
IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo> assemblyParserService,
|
||||||
IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo> luaScriptParserService,
|
IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo> luaScriptParserService,
|
||||||
IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo> configParserService,
|
IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo> configParserService,
|
||||||
|
#if CLIENT
|
||||||
|
IParserServiceAsync<ResourceParserInfo, IStylesResourceInfo> stylesParserService,
|
||||||
|
#endif
|
||||||
ILoggerService logger)
|
ILoggerService logger)
|
||||||
{
|
{
|
||||||
_storageService = storageService;
|
_storageService = storageService;
|
||||||
@@ -36,6 +42,9 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
_luaScriptParserService = luaScriptParserService;
|
_luaScriptParserService = luaScriptParserService;
|
||||||
_configParserService = configParserService;
|
_configParserService = configParserService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
#if CLIENT
|
||||||
|
_stylesParserService = stylesParserService;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Dispose
|
#region Dispose
|
||||||
@@ -59,6 +68,11 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
_assemblyParserService = null;
|
_assemblyParserService = null;
|
||||||
_luaScriptParserService = null;
|
_luaScriptParserService = null;
|
||||||
_configParserService = null;
|
_configParserService = null;
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
_stylesParserService.Dispose();
|
||||||
|
_stylesParserService = null;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -130,14 +144,26 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
var asmTask = Task.Factory.StartNew(async () => await GetAssembliesFromXml(owner, src));
|
var asmTask = Task.Factory.StartNew(async () => await GetAssembliesFromXml(owner, src));
|
||||||
var cfgTask = Task.Factory.StartNew(async () => await GetConfigsFromXml(owner, src));
|
var cfgTask = Task.Factory.StartNew(async () => await GetConfigsFromXml(owner, src));
|
||||||
var luaTask = Task.Factory.StartNew(async () => await GetLuaScriptsFromXml(owner, src));
|
var luaTask = Task.Factory.StartNew(async () => await GetLuaScriptsFromXml(owner, src));
|
||||||
|
#if CLIENT
|
||||||
|
var styleTask = Task.Factory.StartNew(async () => await GetStylesFromXml(owner, src));
|
||||||
|
#endif
|
||||||
|
|
||||||
await Task.WhenAll(asmTask, cfgTask, luaTask);
|
await Task.WhenAll(
|
||||||
|
asmTask,
|
||||||
|
cfgTask,
|
||||||
|
#if CLIENT
|
||||||
|
styleTask,
|
||||||
|
#endif
|
||||||
|
luaTask);
|
||||||
|
|
||||||
return FluentResults.Result.Ok<IModConfigInfo>(new ModConfigInfo()
|
return FluentResults.Result.Ok<IModConfigInfo>(new ModConfigInfo()
|
||||||
{
|
{
|
||||||
Package = owner,
|
Package = owner,
|
||||||
Assemblies = await await asmTask,
|
Assemblies = await await asmTask,
|
||||||
Configs = await await cfgTask,
|
Configs = await await cfgTask,
|
||||||
|
#if CLIENT
|
||||||
|
Styles = await await styleTask,
|
||||||
|
#endif
|
||||||
LuaScripts = await await luaTask
|
LuaScripts = await await luaTask
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -151,7 +177,6 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
XElement cfgElement)
|
XElement cfgElement)
|
||||||
{
|
{
|
||||||
return await GetResourceFromXml<IConfigResourceInfo>(contentPackage, cfgElement, "Config", "FileGroup", _configParserService);
|
return await GetResourceFromXml<IConfigResourceInfo>(contentPackage, cfgElement, "Config", "FileGroup", _configParserService);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<ImmutableArray<IAssemblyResourceInfo>> GetAssembliesFromXml(ContentPackage contentPackage,
|
async Task<ImmutableArray<IAssemblyResourceInfo>> GetAssembliesFromXml(ContentPackage contentPackage,
|
||||||
@@ -160,6 +185,14 @@ public sealed class ModConfigService : IModConfigService
|
|||||||
return await GetResourceFromXml<IAssemblyResourceInfo>(contentPackage, cfgElement, "Assembly", "FileGroup", _assemblyParserService);
|
return await GetResourceFromXml<IAssemblyResourceInfo>(contentPackage, cfgElement, "Assembly", "FileGroup", _assemblyParserService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
async Task<ImmutableArray<IStylesResourceInfo>> GetStylesFromXml(ContentPackage contentPackage,
|
||||||
|
XElement cfgElement)
|
||||||
|
{
|
||||||
|
return await GetResourceFromXml<IStylesResourceInfo>(contentPackage, cfgElement, "Style", "FileGroup", _stylesParserService);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
async Task<ImmutableArray<T>> GetResourceFromXml<T>(ContentPackage contentPackage, XElement cfgElement, string elemName, string fileGroupName, IParserServiceAsync<ResourceParserInfo, T> resourceService)
|
async Task<ImmutableArray<T>> GetResourceFromXml<T>(ContentPackage contentPackage, XElement cfgElement, string elemName, string fileGroupName, IParserServiceAsync<ResourceParserInfo, T> resourceService)
|
||||||
{
|
{
|
||||||
var elems = GetResourceElementsWithName(owner, cfgElement, elemName, fileGroupName);
|
var elems = GetResourceElementsWithName(owner, cfgElement, elemName, fileGroupName);
|
||||||
|
|||||||
+41
-2
@@ -20,6 +20,9 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
private IConfigService _configService;
|
private IConfigService _configService;
|
||||||
private ILuaScriptManagementService _luaScriptManagementService;
|
private ILuaScriptManagementService _luaScriptManagementService;
|
||||||
private IPluginManagementService _pluginManagementService;
|
private IPluginManagementService _pluginManagementService;
|
||||||
|
#if CLIENT
|
||||||
|
private IUIStylesService _uiStylesService;
|
||||||
|
#endif
|
||||||
private IPackageManagementServiceConfig _runConfig;
|
private IPackageManagementServiceConfig _runConfig;
|
||||||
// state
|
// state
|
||||||
private readonly ConcurrentDictionary<ContentPackage, IModConfigInfo> _loadedPackages = new();
|
private readonly ConcurrentDictionary<ContentPackage, IModConfigInfo> _loadedPackages = new();
|
||||||
@@ -40,7 +43,11 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
IModConfigService modConfigService,
|
IModConfigService modConfigService,
|
||||||
ILuaScriptManagementService luaScriptManagementService,
|
ILuaScriptManagementService luaScriptManagementService,
|
||||||
IPluginManagementService pluginManagementService,
|
IPluginManagementService pluginManagementService,
|
||||||
IConfigService configService, IPackageManagementServiceConfig runConfig)
|
IConfigService configService,
|
||||||
|
#if CLIENT
|
||||||
|
IUIStylesService uiStylesService,
|
||||||
|
#endif
|
||||||
|
IPackageManagementServiceConfig runConfig)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_modConfigService = modConfigService;
|
_modConfigService = modConfigService;
|
||||||
@@ -48,6 +55,9 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_runConfig = runConfig;
|
_runConfig = runConfig;
|
||||||
|
#if CLIENT
|
||||||
|
_uiStylesService = uiStylesService;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -61,11 +71,19 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
_pluginManagementService.Dispose();
|
_pluginManagementService.Dispose();
|
||||||
_modConfigService.Dispose();
|
_modConfigService.Dispose();
|
||||||
_logger.Dispose();
|
_logger.Dispose();
|
||||||
|
#if CLIENT
|
||||||
|
_uiStylesService.Dispose();
|
||||||
|
#endif
|
||||||
|
|
||||||
_logger = null;
|
_logger = null;
|
||||||
_luaScriptManagementService = null;
|
_luaScriptManagementService = null;
|
||||||
_pluginManagementService = null;
|
_pluginManagementService = null;
|
||||||
_modConfigService = null;
|
_modConfigService = null;
|
||||||
|
#if CLIENT
|
||||||
|
_uiStylesService = null;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
_loadedPackages.Clear();
|
_loadedPackages.Clear();
|
||||||
_runningPackages.Clear();
|
_runningPackages.Clear();
|
||||||
}
|
}
|
||||||
@@ -86,9 +104,13 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var operationResult = new FluentResults.Result();
|
var operationResult = new FluentResults.Result();
|
||||||
operationResult.WithReasons(_configService.Reset().Reasons);
|
|
||||||
operationResult.WithReasons(_luaScriptManagementService.Reset().Reasons);
|
operationResult.WithReasons(_luaScriptManagementService.Reset().Reasons);
|
||||||
operationResult.WithReasons(_pluginManagementService.Reset().Reasons);
|
operationResult.WithReasons(_pluginManagementService.Reset().Reasons);
|
||||||
|
operationResult.WithReasons(_configService.Reset().Reasons);
|
||||||
|
#if CLIENT
|
||||||
|
operationResult.WithReasons(_uiStylesService.Reset().Reasons);
|
||||||
|
#endif
|
||||||
_runningPackages.Clear();
|
_runningPackages.Clear();
|
||||||
_loadedPackages.Clear();
|
_loadedPackages.Clear();
|
||||||
return operationResult;
|
return operationResult;
|
||||||
@@ -206,10 +228,18 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
return FluentResults.Result.Ok();
|
return FluentResults.Result.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CLIENT
|
||||||
|
if (!config.Styles.IsDefaultOrEmpty)
|
||||||
|
{
|
||||||
|
res.WithReasons(_uiStylesService.LoadAssets(config.Styles).Reasons);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
var r = Task.WhenAll(tasks.ToArray()).ConfigureAwait(false).GetAwaiter().GetResult();
|
var r = Task.WhenAll(tasks.ToArray()).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
|
||||||
foreach (var task in r)
|
foreach (var task in r)
|
||||||
|
{
|
||||||
res.WithReasons(task.ConfigureAwait(false).GetAwaiter().GetResult().Reasons);
|
res.WithReasons(task.ConfigureAwait(false).GetAwaiter().GetResult().Reasons);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -363,12 +393,19 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
IService.CheckDisposed(this);
|
IService.CheckDisposed(this);
|
||||||
|
|
||||||
if (!_loadedPackages.ContainsKey(package))
|
if (!_loadedPackages.ContainsKey(package))
|
||||||
|
{
|
||||||
return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: The package is not loaded.");
|
return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: The package is not loaded.");
|
||||||
|
}
|
||||||
if (!_runningPackages.IsEmpty)
|
if (!_runningPackages.IsEmpty)
|
||||||
|
{
|
||||||
return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: Packages are currently executing.");
|
return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: Packages are currently executing.");
|
||||||
|
}
|
||||||
var result = new FluentResults.Result();
|
var result = new FluentResults.Result();
|
||||||
result.WithReasons(_luaScriptManagementService.DisposePackageResources(package).Reasons);
|
result.WithReasons(_luaScriptManagementService.DisposePackageResources(package).Reasons);
|
||||||
result.WithReasons(_configService.DisposePackageData(package).Reasons);
|
result.WithReasons(_configService.DisposePackageData(package).Reasons);
|
||||||
|
#if CLIENT
|
||||||
|
result.WithReasons(_uiStylesService.UnloadPackage(package).Reasons);
|
||||||
|
#endif
|
||||||
_loadedPackages.TryRemove(package, out _);
|
_loadedPackages.TryRemove(package, out _);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -384,7 +421,9 @@ public sealed class PackageManagementService : IPackageManagementService
|
|||||||
|
|
||||||
var result = new FluentResults.Result();
|
var result = new FluentResults.Result();
|
||||||
foreach (var package in packages)
|
foreach (var package in packages)
|
||||||
|
{
|
||||||
result.WithReasons(UnloadPackage(package).Reasons);
|
result.WithReasons(UnloadPackage(package).Reasons);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user