[Milestone] AssemblyLoader completed.
Details: - Assembly Mgmt Service for loading now a separate interface, not intended for normal use. - Assembly Loader work; implemented custom dictionary key and table. - Assembly loading work. - EventService completed. - Moved assembly extensions to ModUtils.cs - Work to event service. NetworkService work - Added ImpromptuInterfaces package. - Networking Service work to support NetVars - Event Service - Added assemblies references package for script compilation. Updated Roslyn version for compatibility. - Package Loading work. Swap Harmony to HarmonyX - More refactor conversion to FluentResults. - Updated StylesService to return Results. - Refactor of PackageService partially complete. - Made IService.Reset() required to return a Result. - Moved plugin/assembly related code to their own folder (same namespace). - Updated interfaces to reflect the use of Result<T>. - Partial refactor, incomplete. - Added 'FluentResults' so we can stop using cursed Exception-based flow control in loading code. - Added 'OneOf' nuget package: https://github.com/mcintyre321/OneOf for the implementation of the Optional<T> pattern and complex discrete return types instead of cursed enums (see current AssemblyManager.cs). - Reapplied old branch changes.
This commit is contained in:
@@ -2,15 +2,17 @@ using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public class DisplayableData : IDisplayableData
|
||||
public record DisplayableData : IDisplayableData
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public string ModName { get; private set; }
|
||||
public string DisplayName { get; private set; }
|
||||
public string DisplayModName { get; private set; }
|
||||
public string DisplayCategory { get; private set; }
|
||||
public string Tooltip { get; private set; }
|
||||
public string ImageIcon { get; private set; }
|
||||
public Point IconResolution { get; private set; }
|
||||
public bool ShowWhenNotLoaded { get; private set; }
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
public string FallbackPackageName { get; init; }
|
||||
public string DisplayName { get; init; }
|
||||
public string DisplayModName { get; init; }
|
||||
public string DisplayCategory { get; init; }
|
||||
public string Tooltip { get; init; }
|
||||
public string ImageIcon { get; init; }
|
||||
public Point IconResolution { get; init; }
|
||||
public bool ShowWhenNotLoaded { get; init; }
|
||||
public string Description { get; init; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
|
||||
public interface IConfigControl : IConfigBase
|
||||
{
|
||||
event Action<IConfigControl> OnDown;
|
||||
KeyOrMouse Value { get; }
|
||||
bool IsAssignable(KeyOrMouse value);
|
||||
bool TrySetValue(KeyOrMouse value);
|
||||
bool IsDown();
|
||||
}
|
||||
+8
-11
@@ -1,4 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.LuaCs.Configuration;
|
||||
@@ -6,16 +7,8 @@ namespace Barotrauma.LuaCs.Configuration;
|
||||
/// <summary>
|
||||
/// Contains the Display Data for use with Menus.
|
||||
/// </summary>
|
||||
public interface IDisplayableData
|
||||
public interface IDisplayableData : IDataInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal name of the instance.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
/// <summary>
|
||||
/// Internal mod name of the instance. ContentPackage name will be used by default.
|
||||
/// </summary>
|
||||
string ModName { get; }
|
||||
/// <summary>
|
||||
/// The name to display in GUIs and Menus.
|
||||
/// </summary>
|
||||
@@ -44,6 +37,10 @@ public interface IDisplayableData
|
||||
/// Whether to show the entry in the menu when not loaded.
|
||||
/// </summary>
|
||||
bool ShowWhenNotLoaded { get; }
|
||||
/// <summary>
|
||||
/// What does this setting do?
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
}
|
||||
|
||||
public interface IDisplayableInitialize
|
||||
@@ -53,8 +50,8 @@ public interface IDisplayableInitialize
|
||||
// copy this as needed
|
||||
/*public void Initialize(IDisplayableData values)
|
||||
{
|
||||
this.Name = values.Name;
|
||||
this.ModName = values.ModName;
|
||||
this.InternalName = values.InternalName;
|
||||
this.OwnerPackage = values.OwnerPackage;
|
||||
this.DisplayName = values.DisplayName;
|
||||
this.DisplayModName = values.DisplayModName;
|
||||
this.DisplayCategory = values.DisplayCategory;
|
||||
@@ -17,5 +17,6 @@ public record StylesResourceInfo : IStylesResourceInfo
|
||||
public bool Optional { get; init; }
|
||||
public ImmutableArray<CultureInfo> SupportedCultures { get; init; }
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
public ImmutableArray<IPackageDependencyInfo> Dependencies { get; init; }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
public partial interface IModConfigInfo : IStylesResourcesInfo { }
|
||||
|
||||
public interface IStylesResourceInfo : IResourceInfo, IResourceCultureInfo, ILoadableResourceInfo, IPackageDependenciesInfo { }
|
||||
public interface IStylesResourceInfo : IResourceInfo, IResourceCultureInfo, IDataInfo, IPackageDependenciesInfo { }
|
||||
|
||||
public interface IStylesResourcesInfo
|
||||
{
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Compatibility;
|
||||
|
||||
internal partial interface ILuaCsNetworking : ILuaCsShim
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Barotrauma.LuaCs.Services;
|
||||
|
||||
public interface IClientLoggerService : IService
|
||||
public interface IClientLoggerService : IReusableService
|
||||
{
|
||||
void AddToGUIUpdateList();
|
||||
void ShowErrorOverlay(string message, float time = 5f, float duration = 1.5f);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.LuaCs.Configuration;
|
||||
using Barotrauma.LuaCs.Networking;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services;
|
||||
|
||||
public partial interface IConfigService
|
||||
{
|
||||
/*
|
||||
* Immediate mode
|
||||
*/
|
||||
FluentResults.Result<IConfigEntry<T>> AddConfigEntry<T>(IDisplayableData data,
|
||||
T defaultValue,
|
||||
NetSync syncMode = NetSync.None,
|
||||
ClientPermissions permissions = ClientPermissions.None,
|
||||
Func<T, bool> valueChangePredicate = null,
|
||||
Action<IConfigEntry<T>> onValueChanged = null) where T : IConvertible, IEquatable<T>;
|
||||
|
||||
FluentResults.Result<IConfigList> AddConfigList(IDisplayableData data,
|
||||
int defaultIndex, IReadOnlyList<string> values,
|
||||
NetSync syncMode = NetSync.None,
|
||||
ClientPermissions permissions = ClientPermissions.None,
|
||||
Func<IConfigList, int, bool> valueChangePredicate = null,
|
||||
Action<IConfigList, int> onValueChanged = null);
|
||||
|
||||
FluentResults.Result<IConfigRangeEntry<T>> AddConfigRangeEntry<T>(IDisplayableData data,
|
||||
T defaultValue, T minValue, T maxValue,
|
||||
Func<IConfigRangeEntry<T>, int> getStepCount,
|
||||
NetSync syncMode = NetSync.None,
|
||||
ClientPermissions permissions = ClientPermissions.None,
|
||||
Func<T, bool> valueChangePredicate = null,
|
||||
Action<IConfigEntry<T>> onValueChanged = null) where T : IConvertible, IEquatable<T>;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
/// <summary>
|
||||
/// Loads XML Style assets from the given content package.
|
||||
/// </summary>
|
||||
public interface IStylesService : IService
|
||||
public interface IStylesService : IReusableService
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to load the styles file for the given contentpackage and path into a new UIStylesProcessor instance.
|
||||
@@ -12,11 +12,11 @@ public interface IStylesService : IService
|
||||
/// <param name="package"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
bool TryLoadStylesFile(ContentPackage package, ContentPath path);
|
||||
FluentResults.Result LoadStylesFile(ContentPackage package, ContentPath path);
|
||||
/// <summary>
|
||||
/// Unloads all styles assets and UIStyleProcessor instances.
|
||||
/// </summary>
|
||||
void UnloadAllStyles();
|
||||
FluentResults.Result UnloadAllStyles();
|
||||
|
||||
/// <summary>
|
||||
/// Tries to the get the font asset by xml asset name, returns null on failure.
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
using Barotrauma.LuaCs.Services;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.LuaCs.Networking;
|
||||
|
||||
partial class NetworkingService
|
||||
{
|
||||
private Dictionary<ushort, Queue<IReadMessage>> receiveQueue = new Dictionary<ushort, Queue<IReadMessage>>();
|
||||
|
||||
public void SendSyncMessage()
|
||||
{
|
||||
if (GameMain.Client == null) { return; }
|
||||
|
||||
WriteOnlyMessage message = new WriteOnlyMessage();
|
||||
message.WriteByte((byte)ClientPacketHeader.LUA_NET_MESSAGE);
|
||||
message.WriteByte((byte)LuaCsClientToServer.RequestAllIds);
|
||||
GameMain.Client.ClientPeer.Send(message, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void NetMessageReceived(IReadMessage netMessage, ServerPacketHeader header, Client client = null)
|
||||
{
|
||||
if (header != ServerPacketHeader.LUA_NET_MESSAGE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LuaCsServerToClient luaCsHeader = (LuaCsServerToClient)netMessage.ReadByte();
|
||||
|
||||
switch (luaCsHeader)
|
||||
{
|
||||
case LuaCsServerToClient.NetMessageString:
|
||||
HandleNetMessageString(netMessage);
|
||||
break;
|
||||
|
||||
case LuaCsServerToClient.NetMessageId:
|
||||
HandleNetMessageId(netMessage);
|
||||
break;
|
||||
|
||||
case LuaCsServerToClient.ReceiveIds:
|
||||
ReadIds(netMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public INetWriteMessage Start(Guid netId)
|
||||
{
|
||||
var message = new WriteOnlyMessage();
|
||||
|
||||
message.WriteByte((byte)ClientPacketHeader.LUA_NET_MESSAGE);
|
||||
|
||||
if (idToPacket.ContainsKey(netId))
|
||||
{
|
||||
message.WriteByte((byte)LuaCsClientToServer.NetMessageId);
|
||||
message.WriteUInt16(idToPacket[netId]);
|
||||
}
|
||||
else
|
||||
{
|
||||
message.WriteByte((byte)LuaCsClientToServer.NetMessageString);
|
||||
message.WriteBytes(netId.ToByteArray(), 0, 16);
|
||||
}
|
||||
|
||||
return message.ToNetWriteMessage();
|
||||
}
|
||||
|
||||
public void RequestId(Guid netId)
|
||||
{
|
||||
if (idToPacket.ContainsKey(netId)) { return; }
|
||||
|
||||
if (GameMain.Client == null) { return; }
|
||||
|
||||
WriteOnlyMessage message = new WriteOnlyMessage();
|
||||
message.WriteByte((byte)ClientPacketHeader.LUA_NET_MESSAGE);
|
||||
message.WriteByte((byte)LuaCsClientToServer.RequestSingleId);
|
||||
|
||||
message.WriteBytes(netId.ToByteArray(), 0, 16);
|
||||
|
||||
Send(message, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void Send(IWriteMessage netMessage, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable)
|
||||
{
|
||||
GameMain.Client.ClientPeer.Send(netMessage, deliveryMethod);
|
||||
}
|
||||
|
||||
private void HandleNetMessageId(IReadMessage netMessage, Client client = null)
|
||||
{
|
||||
ushort id = netMessage.ReadUInt16();
|
||||
|
||||
if (packetToId.ContainsKey(id))
|
||||
{
|
||||
HandleNetMessage(netMessage, packetToId[id], client);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!receiveQueue.ContainsKey(id)) { receiveQueue[id] = new Queue<IReadMessage>(); }
|
||||
receiveQueue[id].Enqueue(netMessage);
|
||||
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
LuaCsLogger.LogMessage($"Received NetMessage with unknown id {id} from server, storing in queue in case we receive the id later.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadIds(IReadMessage netMessage)
|
||||
{
|
||||
ushort size = netMessage.ReadUInt16();
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
ushort packetId = netMessage.ReadUInt16();
|
||||
Guid netId = new Guid(netMessage.ReadBytes(16));
|
||||
|
||||
packetToId[packetId] = netId;
|
||||
idToPacket[netId] = packetId;
|
||||
|
||||
if (!receiveQueue.ContainsKey(packetId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We could have received messages before receiving the sync message, so we need to process them now
|
||||
|
||||
while (receiveQueue[packetId].TryDequeue(out var queueMessage))
|
||||
{
|
||||
if (netReceives.ContainsKey(netId))
|
||||
{
|
||||
netReceives[netId](queueMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,10 @@ namespace Barotrauma.LuaCs.Services;
|
||||
public partial class PackageService : IStylesResourcesInfo
|
||||
{
|
||||
private readonly Lazy<IStylesService> _stylesService;
|
||||
public IStylesService Styles => _stylesService.Value;
|
||||
|
||||
public PackageService(
|
||||
Lazy<IXmlModConfigConverterService> converterService,
|
||||
Lazy<ILegacyConfigService> legacyConfigService,
|
||||
Lazy<IModConfigParserService> configParserService,
|
||||
Lazy<ILuaScriptService> luaScriptService,
|
||||
Lazy<ILocalizationService> localizationService,
|
||||
Lazy<IPluginService> pluginService,
|
||||
@@ -22,8 +22,7 @@ public partial class PackageService : IStylesResourcesInfo
|
||||
IStorageService storageService,
|
||||
ILoggerService loggerService)
|
||||
{
|
||||
_modConfigConverterService = converterService;
|
||||
_legacyConfigService = legacyConfigService;
|
||||
_configParserService = configParserService;
|
||||
_luaScriptService = luaScriptService;
|
||||
_localizationService = localizationService;
|
||||
_pluginService = pluginService;
|
||||
@@ -36,7 +35,7 @@ public partial class PackageService : IStylesResourcesInfo
|
||||
|
||||
public ImmutableArray<IStylesResourceInfo> StylesResourceInfos => ModConfigInfo?.StylesResourceInfos ?? ImmutableArray<IStylesResourceInfo>.Empty;
|
||||
|
||||
public void LoadStyles([NotNull]IStylesResourcesInfo stylesInfo)
|
||||
public FluentResults.Result LoadStyles([NotNull]IStylesResourcesInfo stylesInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using FluentResults;
|
||||
using FluentResults.LuaCs;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services;
|
||||
|
||||
@@ -18,44 +20,53 @@ public class StylesService : IStylesService
|
||||
_loggerService = loggerService;
|
||||
}
|
||||
|
||||
public bool TryLoadStylesFile(ContentPackage package, ContentPath path)
|
||||
public FluentResults.Result LoadStylesFile(ContentPackage package, ContentPath path)
|
||||
{
|
||||
//check if file already in dict
|
||||
if (_loadedProcessors.ContainsKey(path.FullPath))
|
||||
{
|
||||
return true;
|
||||
return FluentResults.Result.Ok();
|
||||
}
|
||||
//check if file exists
|
||||
if (_storageService.FileExists(path.FullPath))
|
||||
if (_storageService.FileExists(path.FullPath) is {} result
|
||||
&& result.IsFailed | (result.IsSuccess & result.Value == false))
|
||||
{
|
||||
try
|
||||
{
|
||||
var styleProcessor = new UIStyleProcessor(package, path);
|
||||
styleProcessor.LoadFile();
|
||||
_loadedProcessors.Add(path.FullPath, styleProcessor);
|
||||
}
|
||||
catch (InvalidDataException exception)
|
||||
{
|
||||
_loggerService.LogError($"XmlAssetService.TryLoadStylesFile failed for ContentPackage {package.Name}: Exception: {exception.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return FluentResults.Result.Fail(result.Errors)
|
||||
.WithError(new Error($"{nameof(StylesService)}.{nameof(LoadStylesFile)} file does not exist!")
|
||||
.WithMetadata(MetadataType.ExceptionObject, this)
|
||||
.WithMetadata(MetadataType.RootObject, package));
|
||||
}
|
||||
|
||||
return false;
|
||||
try
|
||||
{
|
||||
var styleProcessor = new UIStyleProcessor(package, path);
|
||||
styleProcessor.LoadFile();
|
||||
_loadedProcessors.Add(path.FullPath, styleProcessor);
|
||||
}
|
||||
catch (InvalidDataException exception)
|
||||
{
|
||||
return FluentResults.Result.Fail(new Error($"{nameof(StylesService)}.{nameof(LoadStylesFile)} failed for ContentPackage {package.Name}: Exception: {exception.Message}")
|
||||
.WithMetadata(MetadataType.ExceptionDetails, exception.Message)
|
||||
.WithMetadata(MetadataType.ExceptionObject, this)
|
||||
.WithMetadata(MetadataType.RootObject, package)
|
||||
.WithMetadata(MetadataType.StackTrace, exception.StackTrace));
|
||||
}
|
||||
|
||||
return FluentResults.Result.Ok();
|
||||
}
|
||||
|
||||
public void UnloadAllStyles()
|
||||
public FluentResults.Result UnloadAllStyles()
|
||||
{
|
||||
if (NoProcessorsLoaded)
|
||||
return;
|
||||
return FluentResults.Result.Fail(new Error($"{nameof(StylesService)}.{nameof(UnloadAllStyles)}: No processors have been loaded.")
|
||||
.WithMetadata(MetadataType.ExceptionObject, this));
|
||||
|
||||
foreach (var processor in _loadedProcessors)
|
||||
{
|
||||
processor.Value.UnloadFile();
|
||||
}
|
||||
_loadedProcessors.Clear();
|
||||
return FluentResults.Result.Ok();
|
||||
}
|
||||
|
||||
public GUIFont GetFont(string fontName)
|
||||
@@ -131,8 +142,8 @@ public class StylesService : IStylesService
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
public FluentResults.Result Reset()
|
||||
{
|
||||
UnloadAllStyles();
|
||||
return UnloadAllStyles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,7 +603,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
ServerPacketHeader header = (ServerPacketHeader)inc.ReadByte();
|
||||
|
||||
GameMain.LuaCs.Networking.NetMessageReceived(inc, header);
|
||||
GameMain.LuaCs.NetworkingService.NetMessageReceived(inc, header);
|
||||
|
||||
if (roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize
|
||||
&& header is not (
|
||||
|
||||
Reference in New Issue
Block a user