- ConfigService.cs alpha testing.
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigControl : IConfigBase
|
||||
public interface ISettingControl : ISettingBase
|
||||
{
|
||||
event Action<IConfigControl> OnDown;
|
||||
event Action<ISettingControl> OnDown;
|
||||
KeyOrMouse Value { get; }
|
||||
bool IsAssignable(KeyOrMouse value);
|
||||
bool TrySetValue(KeyOrMouse value);
|
||||
@@ -7,11 +7,11 @@ public partial interface IConfigInfo : IConfigDisplayInfo { }
|
||||
public interface IConfigDisplayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// User-friendly name or Localization Token.
|
||||
/// Localization Token for display name.
|
||||
/// </summary>
|
||||
string DisplayName { get; }
|
||||
/// <summary>
|
||||
/// User-friendly description or Localization Token.
|
||||
/// Localization Token for description.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
/// <summary>
|
||||
@@ -29,5 +29,5 @@ public interface IConfigDisplayInfo
|
||||
/// <summary>
|
||||
/// Icon for display in menus, if available.
|
||||
/// </summary>
|
||||
string ImageIconPath { get; }
|
||||
ContentPath ImageIconPath { get; }
|
||||
}
|
||||
|
||||
@@ -21,8 +21,20 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckCsEnabled()
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns>Returns whether the IsCsEnabled has been changed to true/enabled. Returns false if already enabled.</returns>
|
||||
public bool CheckCsEnabled()
|
||||
{
|
||||
// fast exit if enabled or unavailable.
|
||||
if (this.IsCsEnabled?.Value ?? true )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isCsValueChanged = false;
|
||||
|
||||
var csharpMods = PackageManagementService.GetLoadedAssemblyPackages();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -38,7 +50,7 @@ namespace Barotrauma
|
||||
if (GameMain.Client == null || GameMain.Client.IsServerOwner)
|
||||
{
|
||||
new GUIMessageBox("", $"You have CSharp mods enabled but don't have the CSharp Scripting enabled, those mods might not work, go to the Main Menu, click on LuaCs Settings and check Enable CSharp Scripting.\n\n{sb}");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
GUIMessageBox msg = new GUIMessageBox(
|
||||
@@ -49,6 +61,7 @@ namespace Barotrauma
|
||||
msg.Buttons[0].OnClicked = (GUIButton button, object obj) =>
|
||||
{
|
||||
this.IsCsEnabled.TrySetValue(true);
|
||||
isCsValueChanged = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -57,6 +70,8 @@ namespace Barotrauma
|
||||
this.IsCsEnabled.TrySetValue(false);
|
||||
return true;
|
||||
};
|
||||
|
||||
return isCsValueChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,7 +100,10 @@ namespace Barotrauma
|
||||
case SpriteEditorScreen:
|
||||
case SubEditorScreen:
|
||||
case TestScreen: // notes: TestScreen is a Linux edge case editor screen and is deprecated.
|
||||
CheckCsEnabled();
|
||||
if (CheckCsEnabled() && this.CurrentRunState >= RunState.Running)
|
||||
{
|
||||
SetRunState(RunState.LoadedNoExec);
|
||||
}
|
||||
SetRunState(RunState.Running);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -19,7 +19,7 @@ public partial class ConfigService
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result<IConfigControl> AddConfigControl(IConfigInfo configInfo)
|
||||
public Result<ISettingControl> AddConfigControl(IConfigInfo configInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ public partial interface IConfigService
|
||||
ImmutableArray<IDisplayableConfigBase> GetDisplayableConfigs();
|
||||
ImmutableArray<IDisplayableConfigBase> GetDisplayableConfigsForPackage(ContentPackage package);
|
||||
|
||||
FluentResults.Result<IConfigControl> AddConfigControl(IConfigInfo configInfo);
|
||||
FluentResults.Result<ISettingControl> AddConfigControl(IConfigInfo configInfo);
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Services;
|
||||
using Barotrauma.Networking;
|
||||
using OneOf;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public class ConfigEntry<T> : IConfigEntry<T> where T : IEquatable<T>
|
||||
{
|
||||
|
||||
private readonly Action<ConfigEntry<T>, INetReadMessage> _readMessageHandler;
|
||||
private readonly Action<ConfigEntry<T>, INetWriteMessage> _writeMessageHandler;
|
||||
|
||||
public ConfigEntry(IConfigInfo configInfo, Action<ConfigEntry<T>, INetReadMessage> readMessageHandler,
|
||||
Action<ConfigEntry<T>, INetWriteMessage> writeMessageHandler)
|
||||
{
|
||||
_readMessageHandler = readMessageHandler;
|
||||
_writeMessageHandler = writeMessageHandler;
|
||||
}
|
||||
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
|
||||
public bool Equals(IConfigBase other)
|
||||
{
|
||||
if (ReferenceEquals(this, other))
|
||||
return true;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Type GetValueType()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TrySetValue(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private event Action<IConfigEntry<T>> _onValueChanged;
|
||||
public event Action<IConfigEntry<T>> OnValueChanged
|
||||
{
|
||||
add => _onValueChanged += value;
|
||||
remove => _onValueChanged -= value;
|
||||
}
|
||||
|
||||
event Action<IConfigBase> IConfigBase.OnValueChanged
|
||||
{
|
||||
add => _onValueChanged += value;
|
||||
remove => _onValueChanged -= value;
|
||||
}
|
||||
|
||||
public OneOf<string, XElement> GetSerializableValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Guid InstanceId => throw new NotImplementedException();
|
||||
|
||||
public NetSync SyncType => throw new NotImplementedException();
|
||||
|
||||
public ClientPermissions WritePermissions => throw new NotImplementedException();
|
||||
|
||||
public void ReadNetMessage(INetReadMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void WriteNetMessage(INetWriteMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T Value => throw new NotImplementedException();
|
||||
|
||||
public bool TrySetValue(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Services;
|
||||
using Barotrauma.Networking;
|
||||
using OneOf;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public class ConfigList<T> : IConfigList<T> where T : IEquatable<T>
|
||||
{
|
||||
private readonly Action<ConfigList<T>, INetReadMessage> _readMessageHandler;
|
||||
private readonly Action<ConfigList<T>, INetWriteMessage> _writeMessageHandler;
|
||||
|
||||
public ConfigList(IConfigInfo configInfo, Action<ConfigList<T>, INetReadMessage> readMessageHandler,
|
||||
Action<ConfigList<T>, INetWriteMessage> writeMessageHandler)
|
||||
{
|
||||
_readMessageHandler = readMessageHandler;
|
||||
_writeMessageHandler = writeMessageHandler;
|
||||
}
|
||||
|
||||
public string InternalName => throw new NotImplementedException();
|
||||
|
||||
public ContentPackage OwnerPackage => throw new NotImplementedException();
|
||||
|
||||
public bool Equals(IConfigBase other)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Type GetValueType()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TrySetValue(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private event Action<IConfigList<T>> _onValueChanged;
|
||||
|
||||
public event Action<IConfigList<T>> OnValueChanged
|
||||
{
|
||||
add => _onValueChanged += value;
|
||||
remove => _onValueChanged -= value;
|
||||
}
|
||||
|
||||
event Action<IConfigEntry<T>> IConfigEntry<T>.OnValueChanged
|
||||
{
|
||||
add => _onValueChanged += value;
|
||||
remove => _onValueChanged -= value;
|
||||
}
|
||||
|
||||
event Action<IConfigBase> IConfigBase.OnValueChanged
|
||||
{
|
||||
add => _onValueChanged += value;
|
||||
remove => _onValueChanged -= value;
|
||||
}
|
||||
|
||||
public T Value => throw new NotImplementedException();
|
||||
|
||||
public bool TrySetValue(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OneOf<string, XElement> GetSerializableValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Guid InstanceId => throw new NotImplementedException();
|
||||
|
||||
public NetSync SyncType => throw new NotImplementedException();
|
||||
|
||||
public ClientPermissions WritePermissions => throw new NotImplementedException();
|
||||
|
||||
public void ReadNetMessage(INetReadMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void WriteNetMessage(INetWriteMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IReadOnlyList<T> Options => throw new NotImplementedException();
|
||||
}
|
||||
@@ -6,12 +6,13 @@ using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public partial interface IConfigBase : IDataInfo, IEquatable<IConfigBase>, IDisposable
|
||||
public partial interface ISettingBase : IDataInfo, IEquatable<ISettingBase>, IDisposable
|
||||
{
|
||||
Type GetValueType();
|
||||
string GetValue();
|
||||
string GetStringValue();
|
||||
bool TrySetValue(OneOf.OneOf<string, XElement> value);
|
||||
bool IsAssignable(OneOf.OneOf<string, XElement> value);
|
||||
event Action<IConfigBase> OnValueChanged;
|
||||
event Func<OneOf.OneOf<string, XElement>, bool> IsNewValueValid;
|
||||
event Action<ISettingBase> OnValueChanged;
|
||||
OneOf.OneOf<string, XElement> GetSerializableValue();
|
||||
}
|
||||
@@ -3,10 +3,10 @@ using Barotrauma.LuaCs.Services;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigEntry<T> : IConfigBase, INetworkSyncEntity where T : IEquatable<T>
|
||||
public interface ISettingEntry<T> : ISettingBase, INetworkSyncEntity where T : IEquatable<T>
|
||||
{
|
||||
T Value { get; }
|
||||
bool TrySetValue(T value);
|
||||
bool IsAssignable(T value);
|
||||
new event Action<IConfigEntry<T>> OnValueChanged;
|
||||
new event Action<ISettingEntry<T>> OnValueChanged;
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using Barotrauma.LuaCs.Services;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigEnum : IConfigBase, INetworkSyncEntity
|
||||
public interface ISettingEnum : ISettingBase, INetworkSyncEntity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -4,8 +4,8 @@ using Barotrauma.LuaCs.Services;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigList<T> : IConfigEntry<T>, INetworkSyncEntity where T : IEquatable<T>
|
||||
public interface ISettingList<T> : ISettingEntry<T>, INetworkSyncEntity where T : IEquatable<T>
|
||||
{
|
||||
IReadOnlyList<T> Options { get; }
|
||||
new event Action<IConfigList<T>> OnValueChanged;
|
||||
new event Action<ISettingList<T>> OnValueChanged;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigRangeEntry<T> : IConfigEntry<T> where T : IConvertible, IEquatable<T>
|
||||
public interface ISettingRangeEntry<T> : ISettingEntry<T> where T : IConvertible, IEquatable<T>
|
||||
{
|
||||
T MinValue { get; }
|
||||
T MaxValue { get; }
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Services;
|
||||
using Barotrauma.Networking;
|
||||
using OneOf;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public class SettingEntry<T> : ISettingEntry<T> where T : IEquatable<T>
|
||||
{
|
||||
public string InternalName { get; }
|
||||
public ContentPackage OwnerPackage { get; }
|
||||
public bool Equals(ISettingBase other)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Type GetValueType()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetStringValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TrySetValue(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public event Func<OneOf<string, XElement>, bool> IsNewValueValid;
|
||||
public T Value { get; }
|
||||
public bool TrySetValue(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
event Action<ISettingEntry<T>> ISettingEntry<T>.OnValueChanged
|
||||
{
|
||||
add => throw new NotImplementedException();
|
||||
remove => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
event Action<ISettingBase> ISettingBase.OnValueChanged
|
||||
{
|
||||
add => throw new NotImplementedException();
|
||||
remove => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OneOf<string, XElement> GetSerializableValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Guid InstanceId { get; }
|
||||
public NetSync SyncType { get; }
|
||||
public ClientPermissions WritePermissions { get; }
|
||||
public void ReadNetMessage(INetReadMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void WriteNetMessage(INetWriteMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Services;
|
||||
using Barotrauma.Networking;
|
||||
using OneOf;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public class SettingList<T> : ISettingList<T> where T : IEquatable<T>
|
||||
{
|
||||
public string InternalName { get; }
|
||||
public ContentPackage OwnerPackage { get; }
|
||||
public bool Equals(ISettingBase other)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Type GetValueType()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetStringValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TrySetValue(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(OneOf<string, XElement> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public event Func<OneOf<string, XElement>, bool> IsNewValueValid;
|
||||
public T Value { get; }
|
||||
public bool TrySetValue(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsAssignable(T value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
event Action<ISettingList<T>> ISettingList<T>.OnValueChanged
|
||||
{
|
||||
add => throw new NotImplementedException();
|
||||
remove => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IReadOnlyList<T> Options { get; }
|
||||
|
||||
event Action<ISettingEntry<T>> ISettingEntry<T>.OnValueChanged
|
||||
{
|
||||
add => throw new NotImplementedException();
|
||||
remove => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
event Action<ISettingBase> ISettingBase.OnValueChanged
|
||||
{
|
||||
add => throw new NotImplementedException();
|
||||
remove => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OneOf<string, XElement> GetSerializableValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Guid InstanceId { get; }
|
||||
public NetSync SyncType { get; }
|
||||
public ClientPermissions WritePermissions { get; }
|
||||
public void ReadNetMessage(INetReadMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void WriteNetMessage(INetWriteMessage message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -67,9 +67,8 @@ public record ConfigInfo : IConfigInfo
|
||||
{
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
public Type DataType { get; init; }
|
||||
public OneOf<string, XElement> DefaultValue { get; init; }
|
||||
public OneOf<string, XElement> Value { get; init; }
|
||||
public string DataType { get; init; }
|
||||
public XElement Element { get; init; }
|
||||
public RunState EditableStates { get; init; }
|
||||
public NetSync NetSync { get; init; }
|
||||
|
||||
@@ -79,7 +78,7 @@ public record ConfigInfo : IConfigInfo
|
||||
public string DisplayCategory { get; init; }
|
||||
public bool ShowInMenus { get; init; }
|
||||
public string Tooltip { get; init; }
|
||||
public string ImageIconPath { get; init; }
|
||||
public ContentPath ImageIconPath { get; init; }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ public record ConfigProfileInfo : IConfigProfileInfo
|
||||
{
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
public IReadOnlyList<(string ConfigName, OneOf<string, XElement> Value)> ProfileValues { get; init; }
|
||||
public IReadOnlyList<(string ConfigName, XElement Element)> ProfileValues { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -13,26 +13,18 @@ public partial interface IConfigInfo : IDataInfo
|
||||
/// <summary>
|
||||
/// Specifies the type initializer that will be used to instantiate the config var.
|
||||
/// </summary>
|
||||
Type DataType { get; }
|
||||
string DataType { get; }
|
||||
/// <summary>
|
||||
/// The default value.
|
||||
/// The 'Setting' XML element.
|
||||
/// </summary>
|
||||
OneOf.OneOf<string, XElement> DefaultValue { get; }
|
||||
/// <summary>
|
||||
/// The value the last time this config was saved. If not found, returns the default value.
|
||||
/// <br/><b>[If(Type='<see cref="string"/>')]</b><br/>
|
||||
/// The value is from the 'Value' Attribute. Typically used for types with single/simple values, such as primitives.
|
||||
/// <br/><b>[If(Type='<see cref="XElement"/>')]</b><br/>
|
||||
/// The value is from the first 'Value' child element. Typically used with complex config types, such as range and list.
|
||||
/// </summary>
|
||||
OneOf.OneOf<string, XElement> Value { get; }
|
||||
XElement Element { get; }
|
||||
/// <summary>
|
||||
/// In what <see cref="RunState"/>(s) is this config editable. Will be editable in the selected state, and lower value states.
|
||||
/// <br/><br/>
|
||||
/// <b>[Important]</b><br/> Setting this to value lower than 'Configuration` will render this config read-only.
|
||||
/// <br/><br/><b>Expected Behaviour</b>:
|
||||
/// <br/><b>[<see cref="RunState.Unloaded"/>|<see cref="RunState.Parsed"/>]</b>: Read-Only.
|
||||
/// <br/><b>[<see cref="RunState.Configuration"/>]</b>: Can only be changed at the Main Menu (not in a lobby).
|
||||
/// <br/><b>[<see cref="RunState.Unloaded"/>|<see cref="RunState.Unloaded"/>]</b>: Read-Only.
|
||||
/// <br/><b>[<see cref="RunState.LoadedNoExec"/>]</b>: Can only be changed at the Main Menu (not in a lobby).
|
||||
/// <br/><b>[<see cref="RunState.Running"/>]</b>: Can be changed at the Main Menu and while a lobby is active.
|
||||
/// </summary>
|
||||
RunState EditableStates { get; }
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
public interface IConfigProfileInfo : IDataInfo
|
||||
{
|
||||
IReadOnlyList<(string ConfigName, OneOf.OneOf<string, XElement> Value)> ProfileValues { get; }
|
||||
IReadOnlyList<(string ConfigName, XElement Element)> ProfileValues { get; }
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface IEvent<out T> : IEvent where T : IEvent<T>
|
||||
}
|
||||
}
|
||||
|
||||
#region RuntimeEvents
|
||||
#region RuntimeServiceEvents
|
||||
|
||||
/// <summary>
|
||||
/// Called when the current <see cref="Screen"/> (game state) changes. Upstream Type 'Screen' is internal.
|
||||
@@ -61,6 +61,12 @@ internal interface IEventReloadAllPackages : IEvent<IEventReloadAllPackages>
|
||||
void OnReloadAllPackages();
|
||||
}
|
||||
|
||||
internal interface IEventSettingInstanceLifetime : IEvent<IEventSettingInstanceLifetime>
|
||||
{
|
||||
void OnSettingInstanceCreated<T>(T configInstance) where T : ISettingBase;
|
||||
void OnSettingInstanceDisposed<T>(T configInstance) where T : ISettingBase;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GameEvents
|
||||
|
||||
@@ -99,56 +99,56 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Whether C# plugin code is enabled.
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> IsCsEnabled { get; private set; }
|
||||
internal ISettingEntry<bool> IsCsEnabled { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether mods marked as 'forced' or 'always load' should only be loaded if they're in the enabled mods list.
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> TreatForcedModsAsNormal { get; private set; }
|
||||
internal ISettingEntry<bool> TreatForcedModsAsNormal { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the lua script runner from Workshop package should be used over the in-built version.
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> PreferToUseWorkshopLuaSetup { get; private set; }
|
||||
internal ISettingEntry<bool> PreferToUseWorkshopLuaSetup { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the popup error GUI should be hidden/suppressed.
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> DisableErrorGUIOverlay { get; private set; }
|
||||
internal ISettingEntry<bool> DisableErrorGUIOverlay { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether usernames are anonymized or show in logs.
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> HideUserNamesInLogs { get; private set; }
|
||||
internal ISettingEntry<bool> HideUserNamesInLogs { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The SteamId of the Workshop LuaCs CPackage in use, if available.
|
||||
/// </summary>
|
||||
internal IConfigEntry<ulong> LuaForBarotraumaSteamId { get; private set; }
|
||||
internal ISettingEntry<ulong> LuaForBarotraumaSteamId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: @evilfactory@users.noreply.github.com
|
||||
/// </summary>
|
||||
internal IConfigEntry<bool> RestrictMessageSize { get; private set; }
|
||||
internal ISettingEntry<bool> RestrictMessageSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The local save path for all local data storage for mods.
|
||||
/// </summary>
|
||||
internal IConfigEntry<string> LocalDataSavePath { get; private set; }
|
||||
internal ISettingEntry<string> LocalDataSavePath { get; private set; }
|
||||
|
||||
void LoadLuaCsConfig()
|
||||
{
|
||||
IsCsEnabled = ConfigService.TryGetConfig<IConfigEntry<bool>>(ContentPackageManager.VanillaCorePackage, "IsCsEnabled", out var val1) ? val1
|
||||
IsCsEnabled = ConfigService.TryGetConfig<ISettingEntry<bool>>(ContentPackageManager.VanillaCorePackage, "IsCsEnabled", out var val1) ? val1
|
||||
: throw new NullReferenceException($"{nameof(IsCsEnabled)} cannot be loaded.");
|
||||
TreatForcedModsAsNormal = ConfigService.TryGetConfig<IConfigEntry<bool>>(ContentPackageManager.VanillaCorePackage, "TreatForcedModsAsNormal", out var val2) ? val2
|
||||
TreatForcedModsAsNormal = ConfigService.TryGetConfig<ISettingEntry<bool>>(ContentPackageManager.VanillaCorePackage, "TreatForcedModsAsNormal", out var val2) ? val2
|
||||
: throw new NullReferenceException($"{nameof(TreatForcedModsAsNormal)} cannot be loaded.");
|
||||
DisableErrorGUIOverlay = ConfigService.TryGetConfig<IConfigEntry<bool>>(ContentPackageManager.VanillaCorePackage, "DisableErrorGUIOverlay", out var val3) ? val3
|
||||
DisableErrorGUIOverlay = ConfigService.TryGetConfig<ISettingEntry<bool>>(ContentPackageManager.VanillaCorePackage, "DisableErrorGUIOverlay", out var val3) ? val3
|
||||
: throw new NullReferenceException($"{nameof(DisableErrorGUIOverlay)} cannot be loaded.");
|
||||
HideUserNamesInLogs = ConfigService.TryGetConfig<IConfigEntry<bool>>(ContentPackageManager.VanillaCorePackage, "HideUserNamesInLogs", out var val4) ? val4
|
||||
HideUserNamesInLogs = ConfigService.TryGetConfig<ISettingEntry<bool>>(ContentPackageManager.VanillaCorePackage, "HideUserNamesInLogs", out var val4) ? val4
|
||||
: throw new NullReferenceException($"{nameof(HideUserNamesInLogs)} cannot be loaded.");
|
||||
LuaForBarotraumaSteamId = ConfigService.TryGetConfig<IConfigEntry<ulong>>(ContentPackageManager.VanillaCorePackage, "LuaForBarotraumaSteamId", out var val5) ? val5
|
||||
LuaForBarotraumaSteamId = ConfigService.TryGetConfig<ISettingEntry<ulong>>(ContentPackageManager.VanillaCorePackage, "LuaForBarotraumaSteamId", out var val5) ? val5
|
||||
: throw new NullReferenceException($"{nameof(LuaForBarotraumaSteamId)} cannot be loaded.");
|
||||
RestrictMessageSize = ConfigService.TryGetConfig<IConfigEntry<bool>>(ContentPackageManager.VanillaCorePackage, "RestrictMessageSize", out var val7) ? val7
|
||||
RestrictMessageSize = ConfigService.TryGetConfig<ISettingEntry<bool>>(ContentPackageManager.VanillaCorePackage, "RestrictMessageSize", out var val7) ? val7
|
||||
: throw new NullReferenceException($"{nameof(RestrictMessageSize)} cannot be loaded.");
|
||||
}
|
||||
|
||||
@@ -170,9 +170,11 @@ namespace Barotrauma
|
||||
// TODO: INetworkingService
|
||||
servicesProvider.RegisterServiceType<IConfigService, ConfigService>(ServiceLifetime.Singleton);
|
||||
servicesProvider.RegisterServiceType<IModConfigService, ModConfigService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo>, ConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo>, ConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo>, ConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo>, ModConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo>, ModConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo>, ModConfigFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo>, SettingsFileParserService>(ServiceLifetime.Transient);
|
||||
servicesProvider.RegisterServiceType<IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo>, SettingsFileParserService>(ServiceLifetime.Transient);
|
||||
// service config data
|
||||
servicesProvider.RegisterServiceType<IStorageServiceConfig, StorageServiceConfig>(ServiceLifetime.Singleton);
|
||||
servicesProvider.RegisterServiceType<ILuaScriptServicesConfig, LuaScriptServicesConfig>(ServiceLifetime.Singleton);
|
||||
|
||||
@@ -26,37 +26,19 @@ public class ConfigInitializers : IService
|
||||
// stateless service
|
||||
public bool IsDisposed => false;
|
||||
|
||||
private Result<IConfigEntry<T>> CreateConfigEntry<T>(IConfigInfo configInfo,
|
||||
Action<ConfigEntry<T>, INetReadMessage> readHandler,
|
||||
Action<ConfigEntry<T>, INetWriteMessage> writeHandler)
|
||||
private Result<ISettingEntry<T>> CreateConfigEntry<T>(IConfigInfo configInfo,
|
||||
Action<SettingEntry<T>, INetReadMessage> readHandler,
|
||||
Action<SettingEntry<T>, INetWriteMessage> writeHandler)
|
||||
where T : IEquatable<T>
|
||||
{
|
||||
try
|
||||
{
|
||||
var ice = new ConfigEntry<T>(configInfo, readHandler, writeHandler);
|
||||
return FluentResults.Result.Ok<IConfigEntry<T>>(ice);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return FluentResults.Result.Fail($"Error while initializing config var: {configInfo?.OwnerPackage} - {configInfo?.InternalName}")
|
||||
.WithError(new ExceptionalError(e));
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Result<IConfigList<T>> CreateConfigList<T>(IConfigInfo configInfo,
|
||||
Action<IConfigList<T>, INetReadMessage> readHandler, Action<IConfigList<T>, INetWriteMessage> writeHandler)
|
||||
private Result<ISettingList<T>> CreateConfigList<T>(IConfigInfo configInfo,
|
||||
Action<ISettingList<T>, INetReadMessage> readHandler, Action<ISettingList<T>, INetWriteMessage> writeHandler)
|
||||
where T : IEquatable<T>
|
||||
{
|
||||
try
|
||||
{
|
||||
var icl = new ConfigList<T>(configInfo, readHandler, writeHandler);
|
||||
return FluentResults.Result.Ok<IConfigList<T>>(icl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return FluentResults.Result.Fail($"Error while initializing config var: {configInfo?.OwnerPackage} - {configInfo?.InternalName}")
|
||||
.WithError(new ExceptionalError(e));
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterTypeInitializers(IConfigService configService)
|
||||
@@ -64,30 +46,30 @@ public class ConfigInitializers : IService
|
||||
if (configService == null)
|
||||
throw new ArgumentNullException($"{nameof(RegisterTypeInitializers)}: {nameof(IConfigService)} is null.");
|
||||
|
||||
configService.RegisterTypeInitializer<bool, IConfigEntry<bool>>(this.CreateConfigBool);
|
||||
configService.RegisterTypeInitializer<sbyte, IConfigEntry<sbyte>>(this.CreateConfigSbyte);
|
||||
configService.RegisterTypeInitializer<byte, IConfigEntry<byte>>(this.CreateConfigByte);
|
||||
configService.RegisterTypeInitializer<short, IConfigEntry<short>>(this.CreateConfigShort);
|
||||
configService.RegisterTypeInitializer<ushort, IConfigEntry<ushort>>(this.CreateConfigUShort);
|
||||
configService.RegisterTypeInitializer<int, IConfigEntry<int>>(this.CreateConfigInt32);
|
||||
configService.RegisterTypeInitializer<uint, IConfigEntry<uint>>(this.CreateConfigUInt32);
|
||||
configService.RegisterTypeInitializer<long, IConfigEntry<long>>(this.CreateConfigInt64);
|
||||
configService.RegisterTypeInitializer<ulong, IConfigEntry<ulong>>(this.CreateConfigUInt64);
|
||||
configService.RegisterTypeInitializer<float, IConfigEntry<float>>(this.CreateConfigFloat32);
|
||||
configService.RegisterTypeInitializer<double, IConfigEntry<double>>(this.CreateConfigFloat64);
|
||||
configService.RegisterTypeInitializer<decimal, IConfigEntry<decimal>>(this.CreateConfigFloat128);
|
||||
configService.RegisterTypeInitializer<char, IConfigEntry<char>>(this.CreateConfigChar);
|
||||
configService.RegisterTypeInitializer<string, IConfigEntry<string>>(this.CreateConfigString);
|
||||
configService.RegisterTypeInitializer<Color, IConfigEntry<Color>>(this.CreateConfigColor);
|
||||
configService.RegisterTypeInitializer<Vector2, IConfigEntry<Vector2>>(this.CreateConfigVector2);
|
||||
configService.RegisterTypeInitializer<Vector3, IConfigEntry<Vector3>>(this.CreateConfigVector3);
|
||||
configService.RegisterTypeInitializer<Vector4, IConfigEntry<Vector4>>(this.CreateConfigVector4);
|
||||
/*configService.RegisterTypeInitializer<bool, ISettingEntry<bool>>(this.CreateConfigBool);
|
||||
configService.RegisterTypeInitializer<sbyte, ISettingEntry<sbyte>>(this.CreateConfigSbyte);
|
||||
configService.RegisterTypeInitializer<byte, ISettingEntry<byte>>(this.CreateConfigByte);
|
||||
configService.RegisterTypeInitializer<short, ISettingEntry<short>>(this.CreateConfigShort);
|
||||
configService.RegisterTypeInitializer<ushort, ISettingEntry<ushort>>(this.CreateConfigUShort);
|
||||
configService.RegisterTypeInitializer<int, ISettingEntry<int>>(this.CreateConfigInt32);
|
||||
configService.RegisterTypeInitializer<uint, ISettingEntry<uint>>(this.CreateConfigUInt32);
|
||||
configService.RegisterTypeInitializer<long, ISettingEntry<long>>(this.CreateConfigInt64);
|
||||
configService.RegisterTypeInitializer<ulong, ISettingEntry<ulong>>(this.CreateConfigUInt64);
|
||||
configService.RegisterTypeInitializer<float, ISettingEntry<float>>(this.CreateConfigFloat32);
|
||||
configService.RegisterTypeInitializer<double, ISettingEntry<double>>(this.CreateConfigFloat64);
|
||||
configService.RegisterTypeInitializer<decimal, ISettingEntry<decimal>>(this.CreateConfigFloat128);
|
||||
configService.RegisterTypeInitializer<char, ISettingEntry<char>>(this.CreateConfigChar);
|
||||
configService.RegisterTypeInitializer<string, ISettingEntry<string>>(this.CreateConfigString);
|
||||
configService.RegisterTypeInitializer<Color, ISettingEntry<Color>>(this.CreateConfigColor);
|
||||
configService.RegisterTypeInitializer<Vector2, ISettingEntry<Vector2>>(this.CreateConfigVector2);
|
||||
configService.RegisterTypeInitializer<Vector3, ISettingEntry<Vector3>>(this.CreateConfigVector3);
|
||||
configService.RegisterTypeInitializer<Vector4, ISettingEntry<Vector4>>(this.CreateConfigVector4);*/
|
||||
}
|
||||
|
||||
|
||||
#region InitializerWrappers_NetworkInjected
|
||||
|
||||
private void AssignValueConditional<T>(T val, IConfigEntry<T> inst) where T : IEquatable<T>
|
||||
private void AssignValueConditional<T>(T val, ISettingEntry<T> inst) where T : IEquatable<T>
|
||||
{
|
||||
#if SERVER
|
||||
if (inst.SyncType is NetSync.None or NetSync.ServerAuthority)
|
||||
@@ -100,7 +82,7 @@ public class ConfigInitializers : IService
|
||||
#endif
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<bool>> CreateConfigBool(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<bool>> CreateConfigBool(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<bool>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -112,7 +94,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<sbyte>> CreateConfigSbyte(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<sbyte>> CreateConfigSbyte(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<sbyte>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -124,7 +106,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<byte>> CreateConfigByte(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<byte>> CreateConfigByte(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<byte>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -136,7 +118,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<short>> CreateConfigShort(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<short>> CreateConfigShort(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<short>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -148,7 +130,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<ushort>> CreateConfigUShort(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<ushort>> CreateConfigUShort(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<ushort>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -160,7 +142,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<int>> CreateConfigInt32(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<int>> CreateConfigInt32(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<int>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -172,7 +154,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<uint>> CreateConfigUInt32(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<uint>> CreateConfigUInt32(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<uint>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -184,7 +166,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<long>> CreateConfigInt64(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<long>> CreateConfigInt64(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<long>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -196,7 +178,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<ulong>> CreateConfigUInt64(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<ulong>> CreateConfigUInt64(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<ulong>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -208,7 +190,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<float>> CreateConfigFloat32(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<float>> CreateConfigFloat32(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<float>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -220,7 +202,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<double>> CreateConfigFloat64(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<double>> CreateConfigFloat64(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<double>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -232,7 +214,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<decimal>> CreateConfigFloat128(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<decimal>> CreateConfigFloat128(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<decimal>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -253,7 +235,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<char>> CreateConfigChar(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<char>> CreateConfigChar(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<char>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -265,7 +247,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<string>> CreateConfigString(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<string>> CreateConfigString(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<string>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -277,7 +259,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<Color>> CreateConfigColor(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<Color>> CreateConfigColor(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<Color>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -289,7 +271,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<Vector2>> CreateConfigVector2(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<Vector2>> CreateConfigVector2(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<Vector2>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -302,7 +284,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<Vector3>> CreateConfigVector3(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<Vector3>> CreateConfigVector3(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<Vector3>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
@@ -316,7 +298,7 @@ public class ConfigInitializers : IService
|
||||
});
|
||||
}
|
||||
|
||||
private Result<IConfigEntry<Vector4>> CreateConfigVector4(IConfigInfo configInfo)
|
||||
private Result<ISettingEntry<Vector4>> CreateConfigVector4(IConfigInfo configInfo)
|
||||
{
|
||||
return CreateConfigEntry<Vector4>(configInfo, (inst, readMsg) =>
|
||||
{
|
||||
|
||||
@@ -6,217 +6,318 @@ using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Configuration;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Events;
|
||||
using Barotrauma.LuaCs.Services.Processing;
|
||||
using Barotrauma.Networking;
|
||||
using Dynamitey.DynamicObjects;
|
||||
using FluentResults;
|
||||
using Microsoft.Xna.Framework;
|
||||
using OneOf;
|
||||
using Path = Barotrauma.IO.Path;
|
||||
using Microsoft.Toolkit.Diagnostics;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services;
|
||||
|
||||
public partial class ConfigService : IConfigService
|
||||
public sealed partial class ConfigService : IConfigService
|
||||
{
|
||||
#region Disposal_Locks_Reset
|
||||
|
||||
private readonly AsyncReaderWriterLock _operationLock = new ();
|
||||
private readonly AsyncReaderWriterLock _settingsByPackageLock = new ();
|
||||
private int _isDisposed = 0;
|
||||
public bool IsDisposed
|
||||
{
|
||||
get => ModUtils.Threading.GetBool(ref _isDisposed);
|
||||
private set => ModUtils.Threading.SetBool(ref _isDisposed, value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
using var lck = _operationLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
using var settingsLck = _settingsByPackageLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogDebug($"{nameof(ConfigService)}: Disposing.");
|
||||
|
||||
_configInfoParserService.Dispose();
|
||||
_configProfileInfoParserService.Dispose();
|
||||
|
||||
public bool IsDisposed { get; }
|
||||
if (!_settingsInstances.IsEmpty)
|
||||
{
|
||||
foreach (var instance in _settingsInstances)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (instance.Value is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_eventService.PublishEvent<IEventSettingInstanceLifetime>(sub =>
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
sub.OnSettingInstanceDisposed(instance.Value));
|
||||
instance.Value.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_settingsInstances.Clear();
|
||||
_instanceFactory.Clear();
|
||||
_settingsInstancesByPackage.Clear();
|
||||
|
||||
_storageService = null;
|
||||
_logger = null;
|
||||
_eventService = null;
|
||||
_configInfoParserService = null;
|
||||
_configProfileInfoParserService = null;
|
||||
}
|
||||
|
||||
public FluentResults.Result Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
using var lck = _operationLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
var result = new FluentResults.Result();
|
||||
|
||||
if (!_settingsInstances.IsEmpty)
|
||||
{
|
||||
foreach (var instance in _settingsInstances)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (instance.Value is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#region LuaInterface
|
||||
_eventService.PublishEvent<IEventSettingInstanceLifetime>(sub =>
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
sub.OnSettingInstanceDisposed(instance.Value));
|
||||
instance.Value.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.WithError(new ExceptionalError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_settingsInstances.Clear();
|
||||
_instanceFactory.Clear();
|
||||
_settingsInstancesByPackage.Clear();
|
||||
|
||||
public bool TryGetConfigBool(string packageName, string configName, out bool value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TryGetConfigInt(string packageName, string configName, out int value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigFloat(string packageName, string configName, out float value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigNumber(string packageName, string configName, out double value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigString(string packageName, string configName, out string value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigVector2(string packageName, string configName, out Vector2 value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigVector3(string packageName, string configName, out Vector3 value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigColor(string packageName, string configName, out Color value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfigList(string packageName, string configName, out IReadOnlyList<string> value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigBool(string packageName, string configName, bool value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigInt(string packageName, string configName, int value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigFloat(string packageName, string configName, float value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigNumber(string packageName, string configName, double value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigString(string packageName, string configName, string value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigVector2(string packageName, string configName, Vector2 value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigVector3(string packageName, string configName, Vector3 value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigColor(string packageName, string configName, Color value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetConfigList(string packageName, string configName, string value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryApplyProfileSettings(string packageName, string profileName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void RegisterTypeInitializer<TData, TConfig>(Func<IConfigInfo, Result<TConfig>> initializer, bool replaceIfExists = false) where TData : IEquatable<TData> where TConfig : IConfigBase
|
||||
private readonly ConcurrentDictionary<(ContentPackage OwnerPackage, string InternalName), ISettingBase>
|
||||
_settingsInstances = new();
|
||||
private readonly ConcurrentDictionary<string, Func<IConfigInfo, ISettingBase>>
|
||||
_instanceFactory = new();
|
||||
private readonly ConcurrentDictionary<ContentPackage, ConcurrentBag<ISettingBase>>
|
||||
_settingsInstancesByPackage = new();
|
||||
|
||||
private IStorageService _storageService;
|
||||
private ILoggerService _logger;
|
||||
private IEventService _eventService;
|
||||
private IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo> _configInfoParserService;
|
||||
private IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo> _configProfileInfoParserService;
|
||||
|
||||
public ConfigService(ILoggerService logger,
|
||||
IStorageService storageService,
|
||||
IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo> configInfoParserService,
|
||||
IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo> configProfileInfoParserService, IEventService eventService)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_logger = logger;
|
||||
_storageService = storageService;
|
||||
_configInfoParserService = configInfoParserService;
|
||||
_configProfileInfoParserService = configProfileInfoParserService;
|
||||
_eventService = eventService;
|
||||
}
|
||||
|
||||
|
||||
public void RegisterSettingTypeInitializer<T>(string typeIdentifier, Func<IConfigInfo, T> settingFactory) where T : class, ISettingBase
|
||||
{
|
||||
Guard.IsNotNullOrWhiteSpace(typeIdentifier, nameof(typeIdentifier));
|
||||
Guard.IsNotNull(settingFactory, nameof(settingFactory));
|
||||
using var lck = _operationLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
if (_instanceFactory.ContainsKey(typeIdentifier))
|
||||
{
|
||||
ThrowHelper.ThrowArgumentException($"{nameof(RegisterSettingTypeInitializer)}: The type identifier {typeIdentifier} is already registered.");
|
||||
}
|
||||
|
||||
_instanceFactory[typeIdentifier] = settingFactory;
|
||||
}
|
||||
|
||||
public async Task<FluentResults.Result> LoadConfigsAsync(ImmutableArray<IConfigResourceInfo> configResources)
|
||||
{
|
||||
#if DEBUG
|
||||
return FluentResults.Result.Ok(); // just for startup testing
|
||||
#endif
|
||||
throw new NotImplementedException();
|
||||
using var lck = _operationLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
IService.CheckDisposed(this);
|
||||
if (configResources.IsDefaultOrEmpty)
|
||||
{
|
||||
return FluentResults.Result.Ok();
|
||||
}
|
||||
|
||||
var taskBuilder = ImmutableArray.CreateBuilder<Task<ImmutableArray<IConfigInfo>>>();
|
||||
var toProcessErrors = new ConcurrentStack<IError>();
|
||||
|
||||
var taskCtx = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
|
||||
foreach (var resource in configResources)
|
||||
{
|
||||
taskBuilder.Add(await Task.Factory.StartNew<Task<ImmutableArray<IConfigInfo>>>(async Task<ImmutableArray<IConfigInfo>> () =>
|
||||
{
|
||||
var r = await _configInfoParserService.TryParseResourcesAsync(resource);
|
||||
if (r.IsFailed)
|
||||
{
|
||||
toProcessErrors.PushRange(r.Errors.ToArray());
|
||||
return ImmutableArray<IConfigInfo>.Empty;
|
||||
}
|
||||
return r.Value;
|
||||
}));
|
||||
}
|
||||
|
||||
var taskResults = await Task.WhenAll(taskBuilder.MoveToImmutable());
|
||||
|
||||
if (toProcessErrors.Count > 0)
|
||||
{
|
||||
return FluentResults.Result.Fail($"{nameof(LoadConfigsAsync)}: Errors while loading configuration info: ").WithErrors(toProcessErrors.ToArray());
|
||||
}
|
||||
|
||||
var toProcessDocs = taskResults
|
||||
.Where(tr => !tr.IsDefaultOrEmpty)
|
||||
.SelectMany(tr => tr)
|
||||
.ToImmutableArray();
|
||||
|
||||
var instanceQueue = new Queue<(IConfigInfo configInfo, Func<IConfigInfo, ISettingBase> factory)>();
|
||||
|
||||
foreach (var info in toProcessDocs)
|
||||
{
|
||||
if (!_instanceFactory.TryGetValue(info.DataType, out var factory))
|
||||
{
|
||||
return FluentResults.Result.Fail($"{nameof(LoadConfigsAsync)}: Could not retrieve the instance factory for the data type of '{info.DataType}'!");
|
||||
}
|
||||
if (_settingsInstances.ContainsKey((info.OwnerPackage, info.InternalName)))
|
||||
{
|
||||
// duplicate for some reason (ie. double loading). This should never happen.
|
||||
ThrowHelper.ThrowInvalidOperationException($"{nameof(LoadConfigsAsync)}: A setting for the [ContentPackage].[InternalName] of '[{info.OwnerPackage.Name}].[{info.InternalName}]' already exists!");
|
||||
}
|
||||
|
||||
instanceQueue.Enqueue((info, factory));
|
||||
}
|
||||
|
||||
var toProcessInstanceQueue = new Queue<(IConfigInfo info, ISettingBase instance)>();
|
||||
|
||||
while (instanceQueue.TryDequeue(out var instanceFactoryInfo))
|
||||
{
|
||||
try
|
||||
{
|
||||
toProcessInstanceQueue.Enqueue((instanceFactoryInfo.configInfo, instanceFactoryInfo.factory(instanceFactoryInfo.configInfo)));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FluentResults.Result.Fail(
|
||||
$"{nameof(LoadConfigsAsync)}: Error while instancing setting for '{instanceFactoryInfo.configInfo.OwnerPackage}.{instanceFactoryInfo.configInfo.InternalName}': {e.Message}!");
|
||||
}
|
||||
}
|
||||
|
||||
using var settingsLck = await _settingsByPackageLock.AcquireWriterLock(); // block to protect new bag instance creation
|
||||
var result = new FluentResults.Result();
|
||||
|
||||
while (toProcessInstanceQueue.TryDequeue(out var newInstanceData))
|
||||
{
|
||||
_settingsInstances[(newInstanceData.info.OwnerPackage, newInstanceData.info.InternalName)] = newInstanceData.instance;
|
||||
if (!_settingsInstancesByPackage.TryGetValue(newInstanceData.info.OwnerPackage, out _))
|
||||
{
|
||||
_settingsInstancesByPackage[newInstanceData.info.OwnerPackage] = new ConcurrentBag<ISettingBase>();
|
||||
}
|
||||
_settingsInstancesByPackage[newInstanceData.info.OwnerPackage].Add(newInstanceData.instance);
|
||||
result.WithReasons(_eventService.PublishEvent<IEventSettingInstanceLifetime>(sub =>
|
||||
sub.OnSettingInstanceCreated(newInstanceData.instance)).Reasons);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<FluentResults.Result> LoadConfigsProfilesAsync(ImmutableArray<IConfigResourceInfo> configProfileResources)
|
||||
{
|
||||
#if DEBUG
|
||||
return FluentResults.Result.Ok(); // just for startup testing
|
||||
// TODO: Implement profiles.
|
||||
return FluentResults.Result.Ok();
|
||||
#endif
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result<TConfig> AddConfig<TConfig>(IConfigInfo configInfo) where TConfig : IConfigBase
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public FluentResults.Result ApplyProfileSettings(ContentPackage package, string profileName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public FluentResults.Result DisposePackageData(ContentPackage package)
|
||||
{
|
||||
#if DEBUG
|
||||
return FluentResults.Result.Ok(); // just for startup testing
|
||||
#endif
|
||||
throw new NotImplementedException();
|
||||
Guard.IsNotNull(package, nameof(package));
|
||||
using var lck = _operationLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
ConcurrentBag<ISettingBase> toDispose;
|
||||
using (var settingsLck = _settingsByPackageLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult())
|
||||
{
|
||||
if (!_settingsInstancesByPackage.TryRemove(package, out toDispose) || toDispose is null)
|
||||
{
|
||||
return FluentResults.Result.Ok();
|
||||
}
|
||||
}
|
||||
|
||||
var result = new FluentResults.Result();
|
||||
|
||||
foreach (var setting in toDispose)
|
||||
{
|
||||
result.WithReasons(_eventService.PublishEvent<IEventSettingInstanceLifetime>(sub => sub.OnSettingInstanceDisposed(setting)).Reasons);
|
||||
try
|
||||
{
|
||||
setting.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.WithError(new ExceptionalError(e));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public FluentResults.Result DisposeAllPackageData()
|
||||
{
|
||||
#if DEBUG
|
||||
return FluentResults.Result.Ok(); // just for startup testing
|
||||
#endif
|
||||
throw new NotImplementedException();
|
||||
return this.Reset();
|
||||
}
|
||||
|
||||
public Result<IReadOnlyDictionary<(ContentPackage Package, string ConfigName), IConfigBase>> GetConfigsForPackage(ContentPackage package)
|
||||
public bool TryGetConfig<T>(ContentPackage package, string internalName, out T instance) where T : ISettingBase
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
Guard.IsNotNull(package, nameof(package));
|
||||
Guard.IsNotNullOrWhiteSpace(internalName, nameof(internalName));
|
||||
using var lck = _operationLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
using var settingsLck =
|
||||
_settingsByPackageLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
instance = default;
|
||||
|
||||
if(!_settingsInstances.TryGetValue((package, internalName), out var inst))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Result<IReadOnlyDictionary<(ContentPackage Package, string ConfigName), ImmutableArray<(string ConfigName, OneOf<string, XElement> Value)>>> GetProfilesForPackage(ContentPackage package)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<(ContentPackage Package, string Name), IConfigBase> GetAllConfigs()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetConfig<T>(ContentPackage package, string name, out T config) where T : IConfigBase
|
||||
{
|
||||
#if DEBUG
|
||||
config = default(T);
|
||||
return true; // just for startup testing
|
||||
#endif
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<FluentResults.Result> SaveAllConfigs()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<FluentResults.Result> SaveConfigsForPackage(ContentPackage package)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<FluentResults.Result> SaveConfig((ContentPackage Package, string ConfigName) config)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (inst is not T instanceT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
instance = instanceT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,6 +325,9 @@ public class EventService : IEventService, IEventAssemblyContextUnloading
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
throw; //make errors apparent
|
||||
#endif
|
||||
errors.Enqueue(new Error($"Error while executing runner for {eventType.Name} on type {eventSub.GetType().Name}.")
|
||||
.WithMetadata(MetadataType.ExceptionObject, this)
|
||||
.WithMetadata(MetadataType.RootObject, eventSub)
|
||||
|
||||
@@ -18,3 +18,8 @@ public interface IParserServiceAsync<in TSrc, TOut> : IService
|
||||
Task<Result<TOut>> TryParseResourceAsync(TSrc src);
|
||||
Task<ImmutableArray<Result<TOut>>> TryParseResourcesAsync(IEnumerable<TSrc> sources);
|
||||
}
|
||||
|
||||
public interface IParserServiceOneToManyAsync<in TSrc, TOut> : IService
|
||||
{
|
||||
Task<Result<ImmutableArray<TOut>>> TryParseResourcesAsync(TSrc src);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ using Microsoft.Toolkit.Diagnostics;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Processing;
|
||||
|
||||
public sealed class ConfigFileParserService :
|
||||
public sealed class ModConfigFileParserService :
|
||||
IParserServiceAsync<ResourceParserInfo, IAssemblyResourceInfo>,
|
||||
IParserServiceAsync<ResourceParserInfo, ILuaScriptResourceInfo>,
|
||||
IParserServiceAsync<ResourceParserInfo, IConfigResourceInfo>
|
||||
@@ -18,7 +18,7 @@ public sealed class ConfigFileParserService :
|
||||
private IStorageService _storageService;
|
||||
private readonly AsyncReaderWriterLock _operationsLock = new();
|
||||
|
||||
public ConfigFileParserService(IStorageService storageService)
|
||||
public ModConfigFileParserService(IStorageService storageService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using FluentResults;
|
||||
using Microsoft.Toolkit.Diagnostics;
|
||||
using OneOf;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Processing;
|
||||
|
||||
public sealed class SettingsFileParserService :
|
||||
IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo>,
|
||||
IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo>
|
||||
{
|
||||
#region DisposalControl
|
||||
|
||||
private AsyncReaderWriterLock _operationLock = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
using var lck = _operationLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_storageService.Dispose();
|
||||
_storageService = null;
|
||||
}
|
||||
|
||||
private int _isDisposed = 0;
|
||||
public bool IsDisposed
|
||||
{
|
||||
get => ModUtils.Threading.GetBool(ref _isDisposed);
|
||||
private set => ModUtils.Threading.SetBool(ref _isDisposed, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private IStorageService _storageService;
|
||||
|
||||
public SettingsFileParserService(IStorageService storageService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
}
|
||||
|
||||
async Task<Result<ImmutableArray<IConfigInfo>>> IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo>
|
||||
.TryParseResourcesAsync(IConfigResourceInfo src)
|
||||
{
|
||||
Guard.IsNotNull(src, nameof(src));
|
||||
Guard.IsNotNull(src.OwnerPackage, nameof(src.OwnerPackage));
|
||||
using var lck = await _operationLock.AcquireReaderLock();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
if (src.FilePaths.IsDefaultOrEmpty)
|
||||
{
|
||||
return ReturnFail($"The config file list is empty.");
|
||||
}
|
||||
|
||||
var parsedInfo = ImmutableArray.CreateBuilder<IConfigInfo>();
|
||||
|
||||
foreach ((ContentPath path, Result<XDocument> docLoadResult) res in await _storageService.LoadPackageXmlFilesAsync(src.FilePaths))
|
||||
{
|
||||
if (res.docLoadResult.IsFailed)
|
||||
{
|
||||
return ReturnFail($"Failed to load document for {src.OwnerPackage.Name}").WithErrors(res.docLoadResult.Errors);
|
||||
}
|
||||
|
||||
var settingElements = res.docLoadResult.Value.GetChildElement("Configuration")
|
||||
.GetChildElements("Settings").SelectMany(e => e.GetChildElements("Setting")).ToImmutableArray();
|
||||
if (settingElements.IsDefaultOrEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var packageIdent = res.path.ContentPackage.ToIdentifier().ToString();
|
||||
|
||||
foreach (var element in settingElements)
|
||||
{
|
||||
var name = element.GetAttributeString("Name", string.Empty);
|
||||
if (name.IsNullOrWhiteSpace())
|
||||
{
|
||||
return ReturnFail(
|
||||
$"The internal name for a setting in the config file '{res.path.FullPath}' is empty!");
|
||||
}
|
||||
|
||||
var newSetting = new ConfigInfo()
|
||||
{
|
||||
InternalName = name,
|
||||
OwnerPackage = res.path.ContentPackage,
|
||||
DataType = element.GetAttributeString("Type", string.Empty),
|
||||
Element = element,
|
||||
EditableStates = element.GetAttributeBool("AllowChangesWhileExecuting", true) ? RunState.Running :
|
||||
element.GetAttributeBool("ReadOnly", false) ? RunState.LoadedNoExec :
|
||||
RunState.Unloaded,
|
||||
NetSync = element.GetAttributeEnum("NetSync", NetSync.None),
|
||||
#if CLIENT
|
||||
DisplayName = $"{packageIdent}.{name}.DisplayName",
|
||||
Description = $"{packageIdent}.{name}.Description",
|
||||
DisplayCategory = $"{packageIdent}.{name}.DisplayCategory",
|
||||
ShowInMenus = element.GetAttributeBool("ShowInMenus", true),
|
||||
Tooltip = $"{packageIdent}.{name}.Tooltip",
|
||||
ImageIconPath = element.GetAttributeString("ImageIcon", string.Empty) is {} val && !val.IsNullOrWhiteSpace() ?
|
||||
ContentPath.FromRaw(res.path.ContentPackage, val) : ContentPath.Empty
|
||||
#endif
|
||||
};
|
||||
if (!IsInfoValid(newSetting))
|
||||
{
|
||||
return ReturnFail($"A setting was invalid. ContentPackage: {res.path.ContentPackage}");
|
||||
}
|
||||
parsedInfo.Add(newSetting);
|
||||
}
|
||||
}
|
||||
|
||||
return FluentResults.Result.Ok(parsedInfo.MoveToImmutable());
|
||||
|
||||
// Helpers
|
||||
|
||||
FluentResults.Result ReturnFail(string msg)
|
||||
{
|
||||
return FluentResults.Result.Fail($"{nameof(IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigInfo>.TryParseResourcesAsync)}: {msg}");
|
||||
}
|
||||
|
||||
bool IsInfoValid(ConfigInfo info)
|
||||
{
|
||||
return info.OwnerPackage != null
|
||||
&& !info.InternalName.IsNullOrWhiteSpace()
|
||||
&& !info.DataType.IsNullOrWhiteSpace()
|
||||
&& !info.DataType.IsNullOrWhiteSpace()
|
||||
&& info.Element != null
|
||||
#if CLIENT
|
||||
&& !info.DisplayName.IsNullOrWhiteSpace()
|
||||
&& !info.Description.IsNullOrWhiteSpace()
|
||||
&& !info.DisplayCategory.IsNullOrWhiteSpace()
|
||||
&& !info.Tooltip.IsNullOrWhiteSpace()
|
||||
#endif
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<Result<ImmutableArray<IConfigProfileInfo>>>
|
||||
IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo>
|
||||
.TryParseResourcesAsync(IConfigResourceInfo src)
|
||||
{
|
||||
Guard.IsNotNull(src, nameof(src));
|
||||
Guard.IsNotNull(src.OwnerPackage, nameof(src.OwnerPackage));
|
||||
using var lck = await _operationLock.AcquireReaderLock();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
if (src.FilePaths.IsDefaultOrEmpty)
|
||||
{
|
||||
return ReturnFail($"The config file list is empty.");
|
||||
}
|
||||
|
||||
var parsedInfo = ImmutableArray.CreateBuilder<IConfigProfileInfo>();
|
||||
|
||||
foreach ((ContentPath path, Result<XDocument> docLoadResult) res in await _storageService
|
||||
.LoadPackageXmlFilesAsync(src.FilePaths))
|
||||
{
|
||||
if (res.docLoadResult.IsFailed)
|
||||
{
|
||||
return ReturnFail($"Failed to load document for {src.OwnerPackage.Name}")
|
||||
.WithErrors(res.docLoadResult.Errors);
|
||||
}
|
||||
|
||||
var profileCollection = res.docLoadResult.Value.GetChildElement("Configuration")
|
||||
.GetChildElement("Profiles");
|
||||
if (profileCollection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var profile in profileCollection.GetChildElements("Profile"))
|
||||
{
|
||||
var profileName = profile.GetAttributeString("Name", string.Empty);
|
||||
Guard.IsNotNullOrWhiteSpace(profileName, nameof(profileName));
|
||||
|
||||
var settingValues = profile.GetChildElements("SettingValue").ToImmutableArray();
|
||||
if (settingValues.IsDefaultOrEmpty)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentNullException(nameof(settingValues));
|
||||
}
|
||||
|
||||
var profileValuesBuilder = ImmutableArray.CreateBuilder<(string ConfigName, XElement Value)>();
|
||||
|
||||
foreach (var settingValue in settingValues)
|
||||
{
|
||||
var cfgName = settingValue.GetAttributeString("Name", string.Empty);
|
||||
Guard.IsNotNullOrWhiteSpace(cfgName, nameof(cfgName));
|
||||
profileValuesBuilder.Add((cfgName, settingValue));
|
||||
}
|
||||
|
||||
parsedInfo.Add(new ConfigProfileInfo()
|
||||
{
|
||||
InternalName = profileName,
|
||||
OwnerPackage = res.path.ContentPackage,
|
||||
ProfileValues = profileValuesBuilder.MoveToImmutable()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return parsedInfo.MoveToImmutable();
|
||||
|
||||
FluentResults.Result ReturnFail(string msg)
|
||||
{
|
||||
return FluentResults.Result.Fail($"{nameof(IParserServiceOneToManyAsync<IConfigResourceInfo, IConfigProfileInfo>.TryParseResourcesAsync)}: {msg}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,27 +6,5 @@ namespace Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
public interface ILuaConfigService : ILuaService
|
||||
{
|
||||
// get values
|
||||
bool TryGetConfigBool(string packageName, string configName, out bool value);
|
||||
bool TryGetConfigInt(string packageName, string configName, out int value);
|
||||
bool TryGetConfigFloat(string packageName, string configName, out float value);
|
||||
bool TryGetConfigNumber(string packageName, string configName, out double value);
|
||||
bool TryGetConfigString(string packageName, string configName, out string value);
|
||||
bool TryGetConfigVector2(string packageName, string configName, out Vector2 value);
|
||||
bool TryGetConfigVector3(string packageName, string configName, out Vector3 value);
|
||||
bool TryGetConfigColor(string packageName, string configName, out Color value);
|
||||
bool TryGetConfigList(string packageName, string configName, out IReadOnlyList<string> value);
|
||||
// set values
|
||||
void SetConfigBool(string packageName, string configName, bool value);
|
||||
void SetConfigInt(string packageName, string configName, int value);
|
||||
void SetConfigFloat(string packageName, string configName, float value);
|
||||
void SetConfigNumber(string packageName, string configName, double value);
|
||||
void SetConfigString(string packageName, string configName, string value);
|
||||
void SetConfigVector2(string packageName, string configName, Vector2 value);
|
||||
void SetConfigVector3(string packageName, string configName, Vector3 value);
|
||||
void SetConfigColor(string packageName, string configName, Color value);
|
||||
void SetConfigList(string packageName, string configName, string value);
|
||||
// profiles
|
||||
bool TryApplyProfileSettings(string packageName, string profileName);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,33 +15,18 @@ namespace Barotrauma.LuaCs.Services;
|
||||
|
||||
public partial interface IConfigService : IReusableService, ILuaConfigService
|
||||
{
|
||||
void RegisterSettingTypeInitializer<T>(string typeIdentifier, Func<IConfigInfo, T> settingFactory)
|
||||
where T : class, ISettingBase;
|
||||
/// <summary>
|
||||
/// Registers a type initializer from instancing config types by indicated type from config.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="initializer"></param>
|
||||
/// <param name="replaceIfExists"></param>
|
||||
/// <typeparam name="TData">The <see cref="Type"/> as parsed from the configuration info.</typeparam>
|
||||
/// <typeparam name="TConfig">The resulting configuration instance.</typeparam>
|
||||
void RegisterTypeInitializer<TData, TConfig>(Func<IConfigInfo, FluentResults.Result<TConfig>> initializer, bool replaceIfExists = false)
|
||||
where TData : IEquatable<TData> where TConfig : IConfigBase;
|
||||
|
||||
// Config Files/Resources
|
||||
/// <param name="configResources"></param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
/// <exception cref="NullReferenceException"></exception>
|
||||
/// <returns></returns>
|
||||
Task<FluentResults.Result> LoadConfigsAsync(ImmutableArray<IConfigResourceInfo> configResources);
|
||||
Task<FluentResults.Result> LoadConfigsProfilesAsync(ImmutableArray<IConfigResourceInfo> configProfileResources);
|
||||
|
||||
// Immediate Mode
|
||||
FluentResults.Result<TConfig> AddConfig<TConfig>(IConfigInfo configInfo) where TConfig : IConfigBase;
|
||||
|
||||
// Utility
|
||||
FluentResults.Result ApplyProfileSettings(ContentPackage package, string profileName);
|
||||
FluentResults.Result DisposePackageData(ContentPackage package);
|
||||
FluentResults.Result DisposeAllPackageData();
|
||||
FluentResults.Result<IReadOnlyDictionary<(ContentPackage Package, string ConfigName), IConfigBase>> GetConfigsForPackage(ContentPackage package);
|
||||
FluentResults.Result<IReadOnlyDictionary<(ContentPackage Package, string ConfigName), ImmutableArray<(string ConfigName, OneOf.OneOf<string, XElement> Value)>>>
|
||||
GetProfilesForPackage(ContentPackage package);
|
||||
IReadOnlyDictionary<(ContentPackage Package, string Name), IConfigBase> GetAllConfigs();
|
||||
bool TryGetConfig<T>(ContentPackage package, string name, out T config) where T : IConfigBase;
|
||||
Task<FluentResults.Result> SaveAllConfigs();
|
||||
Task<FluentResults.Result> SaveConfigsForPackage(ContentPackage package);
|
||||
Task<FluentResults.Result> SaveConfig((ContentPackage Package, string ConfigName) config);
|
||||
bool TryGetConfig<T>(ContentPackage package, string internalName, out T instance) where T : ISettingBase;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user