diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptBase.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptBase.cs index 285d41a82..1ed59da50 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptBase.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptBase.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis.Scripting; @@ -14,40 +14,40 @@ using System.Runtime.CompilerServices; namespace Barotrauma { - class CsScriptBase : AssemblyLoadContext - { + class CsScriptBase : AssemblyLoadContext + { - public const string CsOneTimeScriptAssembly = "NetOneTimeScriptAssembly"; - public const string CsScriptAssembly = "NetScriptAssembly"; + public const string CsOneTimeScriptAssembly = "NetOneTimeScriptAssembly"; + public const string CsScriptAssembly = "NetScriptAssembly"; - public static readonly string[] LoadedAssemblyName = { - CsScriptBase.CsScriptAssembly, - CsScriptBase.CsOneTimeScriptAssembly - }; - - public static Dictionary Revision = new Dictionary() - { - { CsScriptAssembly, 0}, - { CsOneTimeScriptAssembly, 0} + public static readonly string[] LoadedAssemblyName = { + CsScriptBase.CsScriptAssembly, + CsScriptBase.CsOneTimeScriptAssembly }; - public CSharpParseOptions ParseOptions { get; protected set; } - - public CsScriptBase() : base(isCollectible: true) { - ParseOptions = CSharpParseOptions.Default - .WithPreprocessorSymbols(new[] { LuaCsSetup.IsServer ? "SERVER" : (LuaCsSetup.IsClient ? "CLIENT" : "UNDEFINED") }); - } - - public static SyntaxTree AssemblyInfoSyntaxTree(string asmName = null) + public static Dictionary Revision = new Dictionary() { - Revision[asmName] = (int)Revision[asmName] + 1; - var asmInfo = new StringBuilder(); - asmInfo.AppendLine("using System.Reflection;"); - asmInfo.AppendLine($"[assembly: AssemblyMetadata(\"Revision\", \"{Revision[asmName]}\")]"); - asmInfo.AppendLine($"[assembly: AssemblyVersion(\"0.0.0.{Revision[asmName]}\")]"); - return CSharpSyntaxTree.ParseText(asmInfo.ToString(), CSharpParseOptions.Default); - } + { CsScriptAssembly, 0}, + { CsOneTimeScriptAssembly, 0} + }; - ~CsScriptBase() { } - } -} \ No newline at end of file + public CSharpParseOptions ParseOptions { get; protected set; } + + public CsScriptBase() : base(isCollectible: true) { + ParseOptions = CSharpParseOptions.Default + .WithPreprocessorSymbols(new[] { LuaCsSetup.IsServer ? "SERVER" : (LuaCsSetup.IsClient ? "CLIENT" : "UNDEFINED") }); + } + + public static SyntaxTree AssemblyInfoSyntaxTree(string asmName = null) + { + Revision[asmName] = (int)Revision[asmName] + 1; + var asmInfo = new StringBuilder(); + asmInfo.AppendLine("using System.Reflection;"); + asmInfo.AppendLine($"[assembly: AssemblyMetadata(\"Revision\", \"{Revision[asmName]}\")]"); + asmInfo.AppendLine($"[assembly: AssemblyVersion(\"0.0.0.{Revision[asmName]}\")]"); + return CSharpSyntaxTree.ParseText(asmInfo.ToString(), CSharpParseOptions.Default); + } + + ~CsScriptBase() { } + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptLoader.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptLoader.cs index 5584c6b0d..f4ce73ffe 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptLoader.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptLoader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis.Scripting; @@ -14,208 +14,208 @@ using System.Xml.Linq; namespace Barotrauma { - class CsScriptLoader : CsScriptBase - { - private List defaultReferences; + class CsScriptLoader : CsScriptBase + { + private List defaultReferences; - private Dictionary> sources; - public Assembly Assembly { get; private set; } + private Dictionary> sources; + public Assembly Assembly { get; private set; } - public CsScriptLoader() - { - defaultReferences = AppDomain.CurrentDomain.GetAssemblies() - .Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit"))) - .Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference) - .ToList(); - - sources = new Dictionary>(); - Assembly = null; - } - - private enum RunType { Standard, Forced, None }; - private bool ShouldRun(ContentPackage cp, string path) - { - if (!Directory.Exists(path + "CSharp")) - { - return false; - } - - var isEnabled = ContentPackageManager.EnabledPackages.All.Contains(cp); - if (File.Exists(path + "CSharp/RunConfig.xml")) - { - Stream stream = File.Open(path + "CSharp/RunConfig.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - var doc = XDocument.Load(stream); - var elems = doc.Root.Elements().ToArray(); - var elem = elems.FirstOrDefault(e => e.Name.LocalName.Equals(LuaCsSetup.IsServer ? "Server" : (LuaCsSetup.IsClient ? "Client" : "None"), StringComparison.OrdinalIgnoreCase)); - - if (elem != null && Enum.TryParse(elem.Value, true, out RunType rtValue)) - { - if (rtValue == RunType.Standard && isEnabled) - { - LuaCsSetup.PrintCsMessage($"Standard run C# of {cp.Name}"); - return true; - } - else if (rtValue == RunType.Forced) - { - LuaCsSetup.PrintCsMessage($"Forced run C# of {cp.Name}"); - return true; - } - else if (rtValue == RunType.None) - { - return false; - } - } - - stream.Close(); - } - - if (isEnabled) - { - LuaCsSetup.PrintCsMessage($"Assumed run C# of {cp.Name}"); - return true; - } - else - { - return false; - } - } - - public void SearchFolders() - { - var paths = new Dictionary(); - foreach (var cp in ContentPackageManager.AllPackages.Concat(ContentPackageManager.EnabledPackages.All)) - { - var path = $"{Path.GetFullPath(Path.GetDirectoryName(cp.Path)).Replace('\\', '/')}/"; - if (ShouldRun(cp, path)) - { - if (paths.ContainsKey(cp.Name)) - { - if (ContentPackageManager.EnabledPackages.All.Contains(cp)) - { - paths[cp.Name] = path; - } - } - else - { - paths.Add(cp.Name, path); - } - } - } - - foreach ((var _, var path) in paths) - { - RunFolder(path); - } - } - - public bool HasSources { get => sources.Count > 0; } - - private void AddSources(string folder) + public CsScriptLoader() { - foreach (var str in DirSearch(folder)) - { - string s = str.Replace("\\", "/"); + defaultReferences = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit"))) + .Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference) + .ToList(); - if (sources.ContainsKey(folder)) - { - sources[folder].Add(s); - } - else - { - sources.Add(folder, new List { s }); - } - } - } + sources = new Dictionary>(); + Assembly = null; + } - private void RunFolder(string folder) - { - - AddSources(folder + "/CSharp/Shared"); - -#if SERVER - AddSources(folder + "/CSharp/Server"); -#else - AddSources(folder + "/CSharp/Client"); -#endif - } - - private IEnumerable ParseSources() { - var syntaxTrees = new List(); - - if (sources.Count <= 0) throw new Exception("No Cs sources detected"); - syntaxTrees.Add(AssemblyInfoSyntaxTree(CsScriptAssembly)); - foreach ((var folder, var src) in sources) + private enum RunType { Standard, Forced, None }; + private bool ShouldRun(ContentPackage cp, string path) + { + if (!Directory.Exists(path + "CSharp")) { - try - { - foreach (var file in src) - { - var tree = SyntaxFactory.ParseSyntaxTree(File.ReadAllText(file), ParseOptions, file); - - syntaxTrees.Add(tree); - } - } - catch (Exception ex) - { - LuaCsSetup.PrintCsError("Error loading '" + folder + "':\n" + ex.Message + "\n" + ex.StackTrace); - } - } - - return syntaxTrees; - } - - public List Compile() - { - IEnumerable syntaxTrees = ParseSources(); - - var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - .WithMetadataImportOptions(MetadataImportOptions.All) - .WithOptimizationLevel(OptimizationLevel.Release) - .WithAllowUnsafe(false); - var compilation = CSharpCompilation.Create(CsScriptAssembly, syntaxTrees, defaultReferences, options); - - using (var mem = new MemoryStream()) - { - var result = compilation.Emit(mem); - if (!result.Success) - { - IEnumerable failures = result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error); - - string errStr = "CS MODS NOT LOADED | Compilation errors:"; - foreach (Diagnostic diagnostic in failures) - errStr += $"\n{diagnostic}"; - LuaCsSetup.PrintCsError(errStr); - } - else - { - mem.Seek(0, SeekOrigin.Begin); - Assembly = LoadFromStream(mem); - } - } - - if (Assembly != null) - { - return Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(ACsMod))).ToList(); - } - else - { - throw new Exception("Unable to create cs mods assembly."); - } - } - - private static string[] DirSearch(string sDir) - { - if (!Directory.Exists(sDir)) - { - return new string[] {}; + return false; } - return Directory.GetFiles(sDir, "*.cs", SearchOption.AllDirectories); - } + var isEnabled = ContentPackageManager.EnabledPackages.All.Contains(cp); + if (File.Exists(path + "CSharp/RunConfig.xml")) + { + Stream stream = File.Open(path + "CSharp/RunConfig.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + var doc = XDocument.Load(stream); + var elems = doc.Root.Elements().ToArray(); + var elem = elems.FirstOrDefault(e => e.Name.LocalName.Equals(LuaCsSetup.IsServer ? "Server" : (LuaCsSetup.IsClient ? "Client" : "None"), StringComparison.OrdinalIgnoreCase)); - public void Clear() - { - Assembly = null; + if (elem != null && Enum.TryParse(elem.Value, true, out RunType rtValue)) + { + if (rtValue == RunType.Standard && isEnabled) + { + LuaCsSetup.PrintCsMessage($"Standard run C# of {cp.Name}"); + return true; + } + else if (rtValue == RunType.Forced) + { + LuaCsSetup.PrintCsMessage($"Forced run C# of {cp.Name}"); + return true; + } + else if (rtValue == RunType.None) + { + return false; + } + } + + stream.Close(); + } + + if (isEnabled) + { + LuaCsSetup.PrintCsMessage($"Assumed run C# of {cp.Name}"); + return true; + } + else + { + return false; + } } - } -} \ No newline at end of file + + public void SearchFolders() + { + var paths = new Dictionary(); + foreach (var cp in ContentPackageManager.AllPackages.Concat(ContentPackageManager.EnabledPackages.All)) + { + var path = $"{Path.GetFullPath(Path.GetDirectoryName(cp.Path)).Replace('\\', '/')}/"; + if (ShouldRun(cp, path)) + { + if (paths.ContainsKey(cp.Name)) + { + if (ContentPackageManager.EnabledPackages.All.Contains(cp)) + { + paths[cp.Name] = path; + } + } + else + { + paths.Add(cp.Name, path); + } + } + } + + foreach ((var _, var path) in paths) + { + RunFolder(path); + } + } + + public bool HasSources { get => sources.Count > 0; } + + private void AddSources(string folder) + { + foreach (var str in DirSearch(folder)) + { + string s = str.Replace("\\", "/"); + + if (sources.ContainsKey(folder)) + { + sources[folder].Add(s); + } + else + { + sources.Add(folder, new List { s }); + } + } + } + + private void RunFolder(string folder) + { + + AddSources(folder + "/CSharp/Shared"); + +#if SERVER + AddSources(folder + "/CSharp/Server"); +#else + AddSources(folder + "/CSharp/Client"); +#endif + } + + private IEnumerable ParseSources() { + var syntaxTrees = new List(); + + if (sources.Count <= 0) throw new Exception("No Cs sources detected"); + syntaxTrees.Add(AssemblyInfoSyntaxTree(CsScriptAssembly)); + foreach ((var folder, var src) in sources) + { + try + { + foreach (var file in src) + { + var tree = SyntaxFactory.ParseSyntaxTree(File.ReadAllText(file), ParseOptions, file); + + syntaxTrees.Add(tree); + } + } + catch (Exception ex) + { + LuaCsSetup.PrintCsError("Error loading '" + folder + "':\n" + ex.Message + "\n" + ex.StackTrace); + } + } + + return syntaxTrees; + } + + public List Compile() + { + IEnumerable syntaxTrees = ParseSources(); + + var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + .WithMetadataImportOptions(MetadataImportOptions.All) + .WithOptimizationLevel(OptimizationLevel.Release) + .WithAllowUnsafe(false); + var compilation = CSharpCompilation.Create(CsScriptAssembly, syntaxTrees, defaultReferences, options); + + using (var mem = new MemoryStream()) + { + var result = compilation.Emit(mem); + if (!result.Success) + { + IEnumerable failures = result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error); + + string errStr = "CS MODS NOT LOADED | Compilation errors:"; + foreach (Diagnostic diagnostic in failures) + errStr += $"\n{diagnostic}"; + LuaCsSetup.PrintCsError(errStr); + } + else + { + mem.Seek(0, SeekOrigin.Begin); + Assembly = LoadFromStream(mem); + } + } + + if (Assembly != null) + { + return Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(ACsMod))).ToList(); + } + else + { + throw new Exception("Unable to create cs mods assembly."); + } + } + + private static string[] DirSearch(string sDir) + { + if (!Directory.Exists(sDir)) + { + return new string[] {}; + } + + return Directory.GetFiles(sDir, "*.cs", SearchOption.AllDirectories); + } + + public void Clear() + { + Assembly = null; + } + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptRunner.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptRunner.cs index b8d6a8e02..36869a536 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptRunner.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Cs/CsScriptRunner.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis.Scripting; @@ -13,109 +13,109 @@ using MoonSharp.Interpreter; namespace Barotrauma { - class CsScriptRunner : CsScriptBase - { - public LuaCsSetup setup; - private List defaultReferences; - private CSharpCompilationOptions compileOptions; - private static readonly string[] usings = { - "System", - "Barotrauma", - "System.Collections.Generic", - "System.Linq" - }; + class CsScriptRunner : CsScriptBase + { + public LuaCsSetup setup; + private List defaultReferences; + private CSharpCompilationOptions compileOptions; + private static readonly string[] usings = { + "System", + "Barotrauma", + "System.Collections.Generic", + "System.Linq" + }; - public CsScriptRunner(LuaCsSetup setup) - { - this.setup = setup; - - defaultReferences = AppDomain.CurrentDomain.GetAssemblies() - .Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit"))) - .Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference) - .ToList(); - compileOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - .WithMetadataImportOptions(MetadataImportOptions.All) - .WithOptimizationLevel(OptimizationLevel.Release) - .WithAllowUnsafe(false); - } - - private static string ToOneTimeScript(string code) + public CsScriptRunner(LuaCsSetup setup) { - var prefix = ""; - foreach (var u in usings) prefix += $"using {u}; "; - prefix += "namespace NetOneTimeScript { public class NetOneTimeScriptRunner { public NetOneTimeScriptRunner() { } public object Run() {\n"; - var postfix = "\nreturn null; } } }"; - return prefix + code + postfix; - } + this.setup = setup; - public object Run(string code) - { - object scriptResilt = null; + defaultReferences = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit"))) + .Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference) + .ToList(); + compileOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + .WithMetadataImportOptions(MetadataImportOptions.All) + .WithOptimizationLevel(OptimizationLevel.Release) + .WithAllowUnsafe(false); + } - try - { - code = ToOneTimeScript(code); - var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, ParseOptions); - var compilation = CSharpCompilation.Create(CsOneTimeScriptAssembly, new[] { AssemblyInfoSyntaxTree(CsOneTimeScriptAssembly), syntaxTree }, defaultReferences, compileOptions); + private static string ToOneTimeScript(string code) + { + var prefix = ""; + foreach (var u in usings) prefix += $"using {u}; "; + prefix += "namespace NetOneTimeScript { public class NetOneTimeScriptRunner { public NetOneTimeScriptRunner() { } public object Run() {\n"; + var postfix = "\nreturn null; } } }"; + return prefix + code + postfix; + } - Assembly assembly = null; - using (var mem = new MemoryStream()) - { - var result = compilation.Emit(mem); - if (!result.Success) - { - IEnumerable failures = result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error); + public object Run(string code) + { + object scriptResilt = null; - string errStr = "Script compilation errors:"; - var lineErr = new SortedDictionary(); - foreach (Diagnostic diagnostic in failures) + try + { + code = ToOneTimeScript(code); + var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, ParseOptions); + var compilation = CSharpCompilation.Create(CsOneTimeScriptAssembly, new[] { AssemblyInfoSyntaxTree(CsOneTimeScriptAssembly), syntaxTree }, defaultReferences, compileOptions); + + Assembly assembly = null; + using (var mem = new MemoryStream()) + { + var result = compilation.Emit(mem); + if (!result.Success) + { + IEnumerable failures = result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error); + + string errStr = "Script compilation errors:"; + var lineErr = new SortedDictionary(); + foreach (Diagnostic diagnostic in failures) { - var line = syntaxTree.GetLineSpan(diagnostic.Location.SourceSpan).StartLinePosition.Line; - lineErr[line] = (diagnostic.Id, diagnostic.ToString()); - } - var lines = code.Split('\n'); - for (var i = 1; i < lines.Length - 1; i++) + var line = syntaxTree.GetLineSpan(diagnostic.Location.SourceSpan).StartLinePosition.Line; + lineErr[line] = (diagnostic.Id, diagnostic.ToString()); + } + var lines = code.Split('\n'); + for (var i = 1; i < lines.Length - 1; i++) { - errStr += $"\n{i} >> {lines[i]}"; - if (lineErr.ContainsKey(i)) errStr += $" <=== {lineErr[i].Item1}"; - } - errStr += "\n"; - foreach ((var idx, (var id, var err)) in lineErr) + errStr += $"\n{i} >> {lines[i]}"; + if (lineErr.ContainsKey(i)) errStr += $" <=== {lineErr[i].Item1}"; + } + errStr += "\n"; + foreach ((var idx, (var id, var err)) in lineErr) { - errStr += $"\n{idx}: {err}"; - } - LuaCsSetup.PrintCsError(errStr); - } - else - { - mem.Seek(0, SeekOrigin.Begin); - assembly = LoadFromStream(mem); - var runner = assembly.CreateInstance("NetOneTimeScript.NetOneTimeScriptRunner"); - if (runner != null) - { - var method = runner.GetType().GetMethod("Run", BindingFlags.Public | BindingFlags.Instance); - if (method != null) - { - scriptResilt = method.Invoke(runner, null); - foreach (var type in assembly.GetTypes()) - { - UserData.UnregisterType(type, true); - } - } - else { LuaCsSetup.PrintCsError("Script Error - no run method detected"); } - } - else { LuaCsSetup.PrintCsError("Script Error - no runner class detected"); } - } - } - Unload(); - } - catch (Exception ex) - { - LuaCsSetup.PrintCsError("Error running script:\n" + ex.Message + "\n" + ex.StackTrace); - } + errStr += $"\n{idx}: {err}"; + } + LuaCsSetup.PrintCsError(errStr); + } + else + { + mem.Seek(0, SeekOrigin.Begin); + assembly = LoadFromStream(mem); + var runner = assembly.CreateInstance("NetOneTimeScript.NetOneTimeScriptRunner"); + if (runner != null) + { + var method = runner.GetType().GetMethod("Run", BindingFlags.Public | BindingFlags.Instance); + if (method != null) + { + scriptResilt = method.Invoke(runner, null); + foreach (var type in assembly.GetTypes()) + { + UserData.UnregisterType(type, true); + } + } + else { LuaCsSetup.PrintCsError("Script Error - no run method detected"); } + } + else { LuaCsSetup.PrintCsError("Script Error - no runner class detected"); } + } + } + Unload(); + } + catch (Exception ex) + { + LuaCsSetup.PrintCsError("Error running script:\n" + ex.Message + "\n" + ex.StackTrace); + } - return scriptResilt; - } + return scriptResilt; + } - } -} \ No newline at end of file + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaBarotraumaAdditions.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaBarotraumaAdditions.cs index da9fd5097..b4a2371b8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaBarotraumaAdditions.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaBarotraumaAdditions.cs @@ -7,19 +7,19 @@ using Barotrauma.Networking; namespace Barotrauma.Networking { - partial class Client - { - public static IReadOnlyList ClientList - { - get - { + partial class Client + { + public static IReadOnlyList ClientList + { + get + { #if SERVER - return GameMain.Server.ConnectedClients; + return GameMain.Server.ConnectedClients; #else - return GameMain.Client.ConnectedClients; + return GameMain.Client.ConnectedClients; #endif - } - } + } + } public ulong SteamID { @@ -36,71 +36,71 @@ namespace Barotrauma.Networking } } - } + } } namespace Barotrauma { - using Barotrauma.Networking; - using System.Linq; - using System.Reflection; + using Barotrauma.Networking; + using System.Linq; + using System.Reflection; - partial class Character - { - - } + partial class Character + { + + } - partial class Item - { - public object GetComponentString(string component) - { - Type type = Type.GetType("Barotrauma.Items.Components." + component); + partial class Item + { + public object GetComponentString(string component) + { + Type type = Type.GetType("Barotrauma.Items.Components." + component); - if (type == null) - return null; + if (type == null) + return null; - MethodInfo method = typeof(Item).GetMethod(nameof(Item.GetComponent)); - MethodInfo generic = method.MakeGenericMethod(type); - return generic.Invoke(this, null); - } + MethodInfo method = typeof(Item).GetMethod(nameof(Item.GetComponent)); + MethodInfo generic = method.MakeGenericMethod(type); + return generic.Invoke(this, null); + } - } + } - partial class ItemPrefab - { + partial class ItemPrefab + { - public static ItemPrefab GetItemPrefab(string itemNameOrId) - { - ItemPrefab itemPrefab = - (MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ?? - MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab; + public static ItemPrefab GetItemPrefab(string itemNameOrId) + { + ItemPrefab itemPrefab = + (MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ?? + MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab; - return itemPrefab; - } - } + return itemPrefab; + } + } - abstract partial class MapEntity - { - public void AddLinked(MapEntity entity) - { - linkedTo.Add(entity); - } - } + abstract partial class MapEntity + { + public void AddLinked(MapEntity entity) + { + linkedTo.Add(entity); + } + } } namespace Barotrauma.Items.Components { - using Barotrauma.Networking; + using Barotrauma.Networking; - partial class CustomInterface - { - } + partial class CustomInterface + { + } - partial struct Signal - { - } + partial struct Signal + { + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaGame.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaGame.cs index 2f8a78feb..40f915a58 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaGame.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaGame.cs @@ -10,86 +10,86 @@ using MoonSharp.Interpreter; namespace Barotrauma { - partial class LuaGame - { - public bool IsSingleplayer => GameMain.IsSingleplayer; - public bool IsMultiplayer => GameMain.IsMultiplayer; - public string SaveFolder => SaveUtil.SaveFolder; + partial class LuaGame + { + public bool IsSingleplayer => GameMain.IsSingleplayer; + public bool IsMultiplayer => GameMain.IsMultiplayer; + public string SaveFolder => SaveUtil.SaveFolder; #if CLIENT - public GameClient Client - { - get - { - return GameMain.Client; - } - } - - public bool Paused => GameMain.Instance?.Paused == true; - public byte SessionId => GameMain.Client.SessionId; - public byte MyID => SessionId; // compatibility - - public ChatMode ActiveChatMode => GameMain.ActiveChatMode; - - public ChatBox ChatBox - { - get - { - if (GameMain.IsSingleplayer) - return GameMain.GameSession.CrewManager.ChatBox; - else - return GameMain.Client.ChatBox; - } - } - - public Sounds.SoundManager SoundManager + public GameClient Client { get { - return GameMain.SoundManager; + return GameMain.Client; } } - public Lights.LightManager LightManager - { - get - { - return GameMain.LightManager; - } - } + public bool Paused => GameMain.Instance?.Paused == true; + public byte SessionId => GameMain.Client.SessionId; + public byte MyID => SessionId; // compatibility - public SubEditorScreen SubEditorScreen - { - get - { - return GameMain.SubEditorScreen; - } - } + public ChatMode ActiveChatMode => GameMain.ActiveChatMode; - public bool IsSubEditor + public ChatBox ChatBox { get { - return Screen.Selected is SubEditorScreen; + if (GameMain.IsSingleplayer) + return GameMain.GameSession.CrewManager.ChatBox; + else + return GameMain.Client.ChatBox; + } + } + + public Sounds.SoundManager SoundManager + { + get + { + return GameMain.SoundManager; + } + } + + public Lights.LightManager LightManager + { + get + { + return GameMain.LightManager; + } + } + + public SubEditorScreen SubEditorScreen + { + get + { + return GameMain.SubEditorScreen; + } + } + + public bool IsSubEditor + { + get + { + return Screen.Selected is SubEditorScreen; } } #else public GameServer Server - { - get - { - return GameMain.Server; - } - } + { + get + { + return GameMain.Server; + } + } - public bool IsDedicated - { - get - { - return GameMain.Server.ServerPeer is LidgrenServerPeer; - } - } + public bool IsDedicated + { + get + { + return GameMain.Server.ServerPeer is LidgrenServerPeer; + } + } #endif public ServerSettings ServerSettings @@ -121,296 +121,296 @@ namespace Barotrauma public DynValue Settings; - public bool allowWifiChat = false; - public bool overrideTraitors = false; - public bool overrideRespawnSub = false; - public bool overrideSignalRadio = false; - public bool disableSpamFilter = false; - public bool disableDisconnectCharacter = false; - public bool enableControlHusk = false; + public bool allowWifiChat = false; + public bool overrideTraitors = false; + public bool overrideRespawnSub = false; + public bool overrideSignalRadio = false; + public bool disableSpamFilter = false; + public bool disableDisconnectCharacter = false; + public bool enableControlHusk = false; - public int mapEntityUpdateInterval - { - get { return MapEntity.MapEntityUpdateInterval; } - set { MapEntity.MapEntityUpdateInterval = value; } - } - - public int gapUpdateInterval - { - get { return MapEntity.GapUpdateInterval; } - set { MapEntity.GapUpdateInterval = value; } - } - - public int poweredUpdateInterval - { - get { return MapEntity.PoweredUpdateInterval; } - set { MapEntity.PoweredUpdateInterval = value; } - } - - public int characterUpdateInterval - { - get { return Character.CharacterUpdateInterval; } - set { Character.CharacterUpdateInterval = value; } - } - - - public HashSet updatePriorityItems = new HashSet(); - public HashSet updatePriorityCharacters = new HashSet(); - - public void AddPriorityItem(Item item) - { - updatePriorityItems.Add(item); - } - - public void RemovePriorityItem(Item item) - { - updatePriorityItems.Remove(item); - } - - public void ClearPriorityItem() - { - updatePriorityItems.Clear(); - } - - public void AddPriorityCharacter(Character character) - { - updatePriorityCharacters.Add(character); - } - - public void RemovePriorityCharacter(Character character) - { - updatePriorityCharacters.Remove(character); - } - - public void ClearPriorityCharacter() - { - updatePriorityCharacters.Clear(); - } - - public bool RoundStarted - { - - get - { -#if SERVER - return GameMain.Server?.GameStarted == true; -#else - return GameMain.Client?.GameStarted == true; -#endif - } - } - - public GameSession GameSession - { - get - { - return GameMain.GameSession; - } - } - - public NetLobbyScreen NetLobbyScreen - { - get - { - return GameMain.NetLobbyScreen; - } - } - - public GameScreen GameScreen - { - get - { - return GameMain.GameScreen; - } - } - - public World World - { - get - { - return GameMain.World; - } - } - -#if SERVER - public ServerPeer Peer - { - get - { - return GameMain.Server.ServerPeer; - } - } -#else - public ClientPeer Peer - { - get - { - return GameMain.Client.ClientPeer; - } - } -#endif - - public LuaGame() + public int mapEntityUpdateInterval { - LuaUserData.MakeFieldAccessible(UserData.RegisterType(typeof(GameSettings)), "currentConfig"); - Settings = UserData.CreateStatic(typeof(GameSettings)); + get { return MapEntity.MapEntityUpdateInterval; } + set { MapEntity.MapEntityUpdateInterval = value; } } - public void OverrideTraitors(bool o) - { - overrideTraitors = o; - } - - public void OverrideRespawnSub(bool o) - { - overrideRespawnSub = o; - } - - public void AllowWifiChat(bool o) - { - allowWifiChat = o; - } - - public void OverrideSignalRadio(bool o) - { - overrideSignalRadio = o; - } - - public void DisableSpamFilter(bool o) - { - disableSpamFilter = o; - } - - public void DisableDisconnectCharacter(bool o) - { - disableDisconnectCharacter = o; - } - - - public void EnableControlHusk(bool o) - { - enableControlHusk = o; - } - - public static void Explode(Vector2 pos, float range = 100, float force = 30, float damage = 30, float structureDamage = 30, float itemDamage = 30, float empStrength = 0, float ballastFloraStrength = 0) - { - new Explosion(range, force, damage, structureDamage, itemDamage, empStrength, ballastFloraStrength).Explode(pos, null); - } - - public static string SpawnItem(string name, Vector2 pos, bool inventory = false, Character character = null) - { - string error; - DebugConsole.SpawnItem(new string[] { name, inventory ? "inventory" : "cursor" }, pos, character, out error); - return error; - } - - public static ContentPackage[] GetEnabledContentPackages() + public int gapUpdateInterval { - return ContentPackageManager.EnabledPackages.All.ToArray(); + get { return MapEntity.GapUpdateInterval; } + set { MapEntity.GapUpdateInterval = value; } } - public static ItemPrefab GetItemPrefab(string itemNameOrId) - { - ItemPrefab itemPrefab = - (MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ?? - MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab; + public int poweredUpdateInterval + { + get { return MapEntity.PoweredUpdateInterval; } + set { MapEntity.PoweredUpdateInterval = value; } + } - return itemPrefab; - } + public int characterUpdateInterval + { + get { return Character.CharacterUpdateInterval; } + set { Character.CharacterUpdateInterval = value; } + } - public static Submarine GetRespawnSub() - { + + public HashSet updatePriorityItems = new HashSet(); + public HashSet updatePriorityCharacters = new HashSet(); + + public void AddPriorityItem(Item item) + { + updatePriorityItems.Add(item); + } + + public void RemovePriorityItem(Item item) + { + updatePriorityItems.Remove(item); + } + + public void ClearPriorityItem() + { + updatePriorityItems.Clear(); + } + + public void AddPriorityCharacter(Character character) + { + updatePriorityCharacters.Add(character); + } + + public void RemovePriorityCharacter(Character character) + { + updatePriorityCharacters.Remove(character); + } + + public void ClearPriorityCharacter() + { + updatePriorityCharacters.Clear(); + } + + public bool RoundStarted + { + + get + { #if SERVER - if (GameMain.Server.RespawnManager == null) - return null; - return GameMain.Server.RespawnManager.RespawnShuttle; + return GameMain.Server?.GameStarted == true; #else - if (GameMain.Client.RespawnManager == null) - return null; - return GameMain.Client.RespawnManager.RespawnShuttle; + return GameMain.Client?.GameStarted == true; #endif - } + } + } - public static Items.Components.Steering GetSubmarineSteering(Submarine sub) - { - foreach (Item item in Item.ItemList) - { - if (item.Submarine != sub) continue; + public GameSession GameSession + { + get + { + return GameMain.GameSession; + } + } - var steering = item.GetComponent(); - if (steering != null) - { - return steering; - } - } + public NetLobbyScreen NetLobbyScreen + { + get + { + return GameMain.NetLobbyScreen; + } + } - return null; - } + public GameScreen GameScreen + { + get + { + return GameMain.GameScreen; + } + } - public static WifiComponent GetWifiComponent(Item item) - { - if (item == null) return null; - return item.GetComponent(); - } + public World World + { + get + { + return GameMain.World; + } + } - public static LightComponent GetLightComponent(Item item) - { - if (item == null) return null; - return item.GetComponent(); - } +#if SERVER + public ServerPeer Peer + { + get + { + return GameMain.Server.ServerPeer; + } + } +#else + public ClientPeer Peer + { + get + { + return GameMain.Client.ClientPeer; + } + } +#endif - public static CustomInterface GetCustomInterface(Item item) - { - if (item == null) return null; - return item.GetComponent(); - } + public LuaGame() + { + LuaUserData.MakeFieldAccessible(UserData.RegisterType(typeof(GameSettings)), "currentConfig"); + Settings = UserData.CreateStatic(typeof(GameSettings)); + } - public static Fabricator GetFabricatorComponent(Item item) - { - if (item == null) return null; - return item.GetComponent(); - } + public void OverrideTraitors(bool o) + { + overrideTraitors = o; + } - public static Holdable GetHoldableComponent(Item item) - { - if (item == null) return null; - return item.GetComponent(); - } + public void OverrideRespawnSub(bool o) + { + overrideRespawnSub = o; + } - public static void ExecuteCommand(string command) - { - DebugConsole.ExecuteCommand(command); - } + public void AllowWifiChat(bool o) + { + allowWifiChat = o; + } - public static Signal CreateSignal(string value, int stepsTaken = 1, Character sender = null, Item source = null, float power = 0, float strength = 1) - { - return new Signal(value, stepsTaken, sender, source, power, strength); - } + public void OverrideSignalRadio(bool o) + { + overrideSignalRadio = o; + } - private List luaAddedCommand = new List(); + public void DisableSpamFilter(bool o) + { + disableSpamFilter = o; + } - public void RemoveCommand(string name) - { - for (var i = 0; i < DebugConsole.Commands.Count; i++) - { - foreach (var cmdname in DebugConsole.Commands[i].names) - { - if (cmdname == name) - { - luaAddedCommand.Remove(DebugConsole.Commands[i]); - DebugConsole.Commands.RemoveAt(i); - continue; - } - } - } - } + public void DisableDisconnectCharacter(bool o) + { + disableDisconnectCharacter = o; + } - public void AddCommand(string name, string help, LuaCsAction onExecute, LuaCsFunc getValidArgs = null, bool isCheat = false) - { - var cmd = new DebugConsole.Command(name, help, (string[] arg1) => onExecute(new object[] { arg1 }), - () => - { - if (getValidArgs == null) return null; + + public void EnableControlHusk(bool o) + { + enableControlHusk = o; + } + + public static void Explode(Vector2 pos, float range = 100, float force = 30, float damage = 30, float structureDamage = 30, float itemDamage = 30, float empStrength = 0, float ballastFloraStrength = 0) + { + new Explosion(range, force, damage, structureDamage, itemDamage, empStrength, ballastFloraStrength).Explode(pos, null); + } + + public static string SpawnItem(string name, Vector2 pos, bool inventory = false, Character character = null) + { + string error; + DebugConsole.SpawnItem(new string[] { name, inventory ? "inventory" : "cursor" }, pos, character, out error); + return error; + } + + public static ContentPackage[] GetEnabledContentPackages() + { + return ContentPackageManager.EnabledPackages.All.ToArray(); + } + + public static ItemPrefab GetItemPrefab(string itemNameOrId) + { + ItemPrefab itemPrefab = + (MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ?? + MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab; + + return itemPrefab; + } + + public static Submarine GetRespawnSub() + { +#if SERVER + if (GameMain.Server.RespawnManager == null) + return null; + return GameMain.Server.RespawnManager.RespawnShuttle; +#else + if (GameMain.Client.RespawnManager == null) + return null; + return GameMain.Client.RespawnManager.RespawnShuttle; +#endif + } + + public static Items.Components.Steering GetSubmarineSteering(Submarine sub) + { + foreach (Item item in Item.ItemList) + { + if (item.Submarine != sub) continue; + + var steering = item.GetComponent(); + if (steering != null) + { + return steering; + } + } + + return null; + } + + public static WifiComponent GetWifiComponent(Item item) + { + if (item == null) return null; + return item.GetComponent(); + } + + public static LightComponent GetLightComponent(Item item) + { + if (item == null) return null; + return item.GetComponent(); + } + + public static CustomInterface GetCustomInterface(Item item) + { + if (item == null) return null; + return item.GetComponent(); + } + + public static Fabricator GetFabricatorComponent(Item item) + { + if (item == null) return null; + return item.GetComponent(); + } + + public static Holdable GetHoldableComponent(Item item) + { + if (item == null) return null; + return item.GetComponent(); + } + + public static void ExecuteCommand(string command) + { + DebugConsole.ExecuteCommand(command); + } + + public static Signal CreateSignal(string value, int stepsTaken = 1, Character sender = null, Item source = null, float power = 0, float strength = 1) + { + return new Signal(value, stepsTaken, sender, source, power, strength); + } + + private List luaAddedCommand = new List(); + + public void RemoveCommand(string name) + { + for (var i = 0; i < DebugConsole.Commands.Count; i++) + { + foreach (var cmdname in DebugConsole.Commands[i].names) + { + if (cmdname == name) + { + luaAddedCommand.Remove(DebugConsole.Commands[i]); + DebugConsole.Commands.RemoveAt(i); + continue; + } + } + } + } + + public void AddCommand(string name, string help, LuaCsAction onExecute, LuaCsFunc getValidArgs = null, bool isCheat = false) + { + var cmd = new DebugConsole.Command(name, help, (string[] arg1) => onExecute(new object[] { arg1 }), + () => + { + if (getValidArgs == null) return null; var validArgs = getValidArgs(); if (validArgs is DynValue luaValue) { @@ -419,96 +419,96 @@ namespace Barotrauma return (string[][])validArgs; }, isCheat); - luaAddedCommand.Add(cmd); - DebugConsole.Commands.Add(cmd); - } - - public List Commands => DebugConsole.Commands; - - public void AssignOnExecute(string names, object onExecute) => DebugConsole.AssignOnExecute(names, (string[] a) => { GameMain.LuaCs.CallLuaFunction(onExecute, new object[] { a }); }); - - public void SaveGame(string path) - { - if (!LuaCsFile.CanWriteToPath(path)) { throw new ScriptRuntimeException($"Saving files to {path} is disallowed."); } - SaveUtil.SaveGame(path); + luaAddedCommand.Add(cmd); + DebugConsole.Commands.Add(cmd); } - public void LoadGame(string path) - { - SaveUtil.LoadGame(path); - } + public List Commands => DebugConsole.Commands; + + public void AssignOnExecute(string names, object onExecute) => DebugConsole.AssignOnExecute(names, (string[] a) => { GameMain.LuaCs.CallLuaFunction(onExecute, new object[] { a }); }); + + public void SaveGame(string path) + { + if (!LuaCsFile.CanWriteToPath(path)) { throw new ScriptRuntimeException($"Saving files to {path} is disallowed."); } + SaveUtil.SaveGame(path); + } + + public void LoadGame(string path) + { + SaveUtil.LoadGame(path); + } #if SERVER - public void LoadCampaign(string path) - { - MultiPlayerCampaign.LoadCampaign(path); - } + public void LoadCampaign(string path) + { + MultiPlayerCampaign.LoadCampaign(path); + } - public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null) - { - GameMain.Server.SendChatMessage(msg, messageType, sender, character); - } + public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null) + { + GameMain.Server.SendChatMessage(msg, messageType, sender, character); + } - public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null) - { - GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character); - } + public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null) + { + GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character); + } - public static void SendTraitorMessage(Client client, string msg, Identifier missionid, TraitorMessageType type) - { - GameMain.Server.SendTraitorMessage(client, msg, missionid, type); - } + public static void SendTraitorMessage(Client client, string msg, Identifier missionid, TraitorMessageType type) + { + GameMain.Server.SendTraitorMessage(client, msg, missionid, type); + } - public static void SendDirectChatMessage(string sendername, string text, Character sender, ChatMessageType messageType = ChatMessageType.Private, Client client = null, string iconStyle = "") - { + public static void SendDirectChatMessage(string sendername, string text, Character sender, ChatMessageType messageType = ChatMessageType.Private, Client client = null, string iconStyle = "") + { - ChatMessage cm = ChatMessage.Create(sendername, text, messageType, sender, client); - cm.IconStyle = iconStyle; + ChatMessage cm = ChatMessage.Create(sendername, text, messageType, sender, client); + cm.IconStyle = iconStyle; - GameMain.Server.SendDirectChatMessage(cm, client); + GameMain.Server.SendDirectChatMessage(cm, client); - } + } - public static void SendDirectChatMessage(ChatMessage chatMessage, Client client) - { - GameMain.Server.SendDirectChatMessage(chatMessage, client); - } + public static void SendDirectChatMessage(ChatMessage chatMessage, Client client) + { + GameMain.Server.SendDirectChatMessage(chatMessage, client); + } - public static void Log(string message, ServerLog.MessageType type) - { - GameServer.Log(message, type); - } + public static void Log(string message, ServerLog.MessageType type) + { + GameServer.Log(message, type); + } - public static void DispatchRespawnSub() - { - GameMain.Server.RespawnManager.DispatchShuttle(); - } + public static void DispatchRespawnSub() + { + GameMain.Server.RespawnManager.DispatchShuttle(); + } - public static void StartGame() - { - GameMain.Server.StartGame(); - } + public static void StartGame() + { + GameMain.Server.StartGame(); + } - public static void EndGame() - { - GameMain.Server.EndGame(); - } + public static void EndGame() + { + GameMain.Server.EndGame(); + } - public void AssignOnClientRequestExecute(string names, object onExecute) => DebugConsole.AssignOnClientRequestExecute(names, (Client a, Vector2 b, string[] c) => { GameMain.LuaCs.CallLuaFunction(onExecute, new object[] { a, b, c }); }); + public void AssignOnClientRequestExecute(string names, object onExecute) => DebugConsole.AssignOnClientRequestExecute(names, (Client a, Vector2 b, string[] c) => { GameMain.LuaCs.CallLuaFunction(onExecute, new object[] { a, b, c }); }); #endif - public void Stop() - { - mapEntityUpdateInterval = 1; - gapUpdateInterval = 4; - characterUpdateInterval = 1; + public void Stop() + { + mapEntityUpdateInterval = 1; + gapUpdateInterval = 4; + characterUpdateInterval = 1; - foreach (var cmd in luaAddedCommand) - { - DebugConsole.Commands.Remove(cmd); - } - } - } + foreach (var cmd in luaAddedCommand) + { + DebugConsole.Commands.Remove(cmd); + } + } + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaUserData.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaUserData.cs index 914caefa9..4460aa313 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaUserData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaUserData.cs @@ -7,265 +7,265 @@ using MoonSharp.Interpreter.Interop; namespace Barotrauma { - partial class LuaUserData - { - public static Type GetType(string typeName) - { + partial class LuaUserData + { + public static Type GetType(string typeName) + { if (typeName == null || typeName.Length == 0) return null; - var byRef = false; + var byRef = false; if (typeName.StartsWith("out ") || typeName.StartsWith("ref ")) - { - typeName = typeName.Remove(0, 4); - byRef = true; - } + { + typeName = typeName.Remove(0, 4); + byRef = true; + } - var type = Type.GetType(typeName); - if (type != null) return byRef ? type.MakeByRefType() : type; - foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) - { - if (CsScriptBase.LoadedAssemblyName.Contains(a.GetName().Name)) - { - var attrs = a.GetCustomAttributes(); - var revision = attrs.FirstOrDefault(attr => attr.Key == "Revision")?.Value; - if (revision != null && int.Parse(revision) != (int)CsScriptBase.Revision[a.GetName().Name]) { continue; } - } - type = a.GetType(typeName); - if (type != null) - { - return byRef ? type.MakeByRefType() : type; - } - } - return null; - } + var type = Type.GetType(typeName); + if (type != null) return byRef ? type.MakeByRefType() : type; + foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) + { + if (CsScriptBase.LoadedAssemblyName.Contains(a.GetName().Name)) + { + var attrs = a.GetCustomAttributes(); + var revision = attrs.FirstOrDefault(attr => attr.Key == "Revision")?.Value; + if (revision != null && int.Parse(revision) != (int)CsScriptBase.Revision[a.GetName().Name]) { continue; } + } + type = a.GetType(typeName); + if (type != null) + { + return byRef ? type.MakeByRefType() : type; + } + } + return null; + } - public static IUserDataDescriptor RegisterType(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"Tried to register a type that doesn't exist: {typeName}."); - } - - return UserData.RegisterType(type); - } - - public static void UnregisterType(string typeName, bool deleteHistory = false) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"Tried to unregister a type that doesn't exist: {typeName}."); - } - - UserData.UnregisterType(type, deleteHistory); - } - public static IUserDataDescriptor RegisterGenericType(string typeName, params string[] typeNameArguements) - { - Type type = GetType(typeName); - Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); - Type genericType = type.MakeGenericType(typeArguements); - return UserData.RegisterType(genericType); - } - - public static void UnregisterGenericType(string typeName, params string[] typeNameArguements) - { - Type type = GetType(typeName); - Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); - Type genericType = type.MakeGenericType(typeArguements); - UserData.UnregisterType(genericType); - } - - private static bool IsType(object obj) { return obj is T; } - - public static bool IsTargetType(object obj, string typeName) - { - var type = GetType(typeName); - MethodInfo method = typeof(LuaUserData).GetMethod(nameof(IsType), BindingFlags.NonPublic | BindingFlags.Static); - MethodInfo generic = method.MakeGenericMethod(type); - return (bool)generic.Invoke(null, new object[] { obj }); - } - - public static object CreateStatic(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"Tried to create a static userdata of a type that doesn't exist: {typeName}."); - } - - MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]); - MethodInfo generic = method.MakeGenericMethod(type); - return generic.Invoke(null, null); - } - - public static object CreateEnumTable(string typeName) + public static IUserDataDescriptor RegisterType(string typeName) { - Type type = GetType(typeName); + Type type = GetType(typeName); - if (type == null) - { - throw new ScriptRuntimeException($"Tried to create an enum table with a type that doesn't exist:: {typeName}."); - } - - Dictionary result = new Dictionary(); - - foreach (var value in Enum.GetValues(type)) + if (type == null) { - string name = Enum.GetName(type, value); - - result[name] = value; + throw new ScriptRuntimeException($"Tried to register a type that doesn't exist: {typeName}."); } - return result; - } + return UserData.RegisterType(type); + } - private static FieldInfo FindFieldRecursively(Type type, string fieldName) + public static void UnregisterType(string typeName, bool deleteHistory = false) { - var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + Type type = GetType(typeName); - if (field == null && type.BaseType != null) + if (type == null) { - return FindFieldRecursively(type.BaseType, fieldName); + throw new ScriptRuntimeException($"Tried to unregister a type that doesn't exist: {typeName}."); } - return field; - } + UserData.UnregisterType(type, deleteHistory); + } + public static IUserDataDescriptor RegisterGenericType(string typeName, params string[] typeNameArguements) + { + Type type = GetType(typeName); + Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); + Type genericType = type.MakeGenericType(typeArguements); + return UserData.RegisterType(genericType); + } - public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {fieldName} accessible."); - } + public static void UnregisterGenericType(string typeName, params string[] typeNameArguements) + { + Type type = GetType(typeName); + Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); + Type genericType = type.MakeGenericType(typeArguements); + UserData.UnregisterType(genericType); + } - var descriptor = (StandardUserDataDescriptor)IUUD; - var field = IUUD.Type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + private static bool IsType(object obj) { return obj is T; } - if (field == null) + public static bool IsTargetType(object obj, string typeName) + { + var type = GetType(typeName); + MethodInfo method = typeof(LuaUserData).GetMethod(nameof(IsType), BindingFlags.NonPublic | BindingFlags.Static); + MethodInfo generic = method.MakeGenericMethod(type); + return (bool)generic.Invoke(null, new object[] { obj }); + } + + public static object CreateStatic(string typeName) + { + Type type = GetType(typeName); + + if (type == null) { - field = FindFieldRecursively(IUUD.Type, fieldName); + throw new ScriptRuntimeException($"Tried to create a static userdata of a type that doesn't exist: {typeName}."); } - if (field == null) - { - throw new ScriptRuntimeException($"Tried to make field '{fieldName}' accessible, but the field doesn't exist."); - } + MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]); + MethodInfo generic = method.MakeGenericMethod(type); + return generic.Invoke(null, null); + } - descriptor.RemoveMember(fieldName); - descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default)); - } + public static object CreateEnumTable(string typeName) + { + Type type = GetType(typeName); - private static MethodInfo FindMethodRecursively(Type type, string methodName) - { - var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + if (type == null) + { + throw new ScriptRuntimeException($"Tried to create an enum table with a type that doesn't exist:: {typeName}."); + } - if (method == null && type.BaseType != null) - { - return FindMethodRecursively(type.BaseType, methodName); - } + Dictionary result = new Dictionary(); - return method; - } + foreach (var value in Enum.GetValues(type)) + { + string name = Enum.GetName(type, value); - public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {methodName} accessible."); - } + result[name] = value; + } - var descriptor = (StandardUserDataDescriptor)IUUD; - var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + return result; + } - if (method == null) - { - method = FindMethodRecursively(IUUD.Type, methodName); - } + private static FieldInfo FindFieldRecursively(Type type, string fieldName) + { + var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - if (method == null) - { - throw new ScriptRuntimeException($"Tried to make method '{methodName}' accessible, but the method doesn't exist."); - } + if (field == null && type.BaseType != null) + { + return FindFieldRecursively(type.BaseType, fieldName); + } - descriptor.RemoveMember(methodName); - descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default)); - } + return field; + } - public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add method {methodName}."); - } + public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {fieldName} accessible."); + } - var descriptor = (StandardUserDataDescriptor)IUUD; + var descriptor = (StandardUserDataDescriptor)IUUD; + var field = IUUD.Type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - descriptor.RemoveMember(methodName); - descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) => - { - if (GameMain.LuaCs != null) - return GameMain.LuaCs.CallLuaFunction(function, arg3.GetArray()); - return null; - })); - } + if (field == null) + { + field = FindFieldRecursively(IUUD.Type, fieldName); + } - public static void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add field {fieldName}."); - } + if (field == null) + { + throw new ScriptRuntimeException($"Tried to make field '{fieldName}' accessible, but the field doesn't exist."); + } - var descriptor = (StandardUserDataDescriptor)IUUD; - descriptor.RemoveMember(fieldName); - descriptor.AddMember(fieldName, new DynValueMemberDescriptor(fieldName, value)); - } + descriptor.RemoveMember(fieldName); + descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default)); + } - public static void RemoveMember(IUserDataDescriptor IUUD, string memberName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to remove the member {memberName}."); - } + private static MethodInfo FindMethodRecursively(Type type, string methodName) + { + var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - var descriptor = (StandardUserDataDescriptor)IUUD; - descriptor.RemoveMember(memberName); - } + if (method == null && type.BaseType != null) + { + return FindMethodRecursively(type.BaseType, methodName); + } - /// - /// See . - /// - /// Lua value to convert and wrap in a userdata. - /// Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters. - /// A userdata that wraps the Lua value converted to an object of the desired type as described by . - public static DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor) - { - return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor); - } + return method; + } - /// - /// Converts a Lua value to a CLR object of a desired type and wraps it in a userdata. - /// If the type is not registered, then a new will be created and used. - /// The goal of this method is to allow Lua scripts to create userdata to wrap certain data without having to register types. - /// Wrapping the value in a userdata preserves the original type during script-to-CLR conversions. - /// A Lua script needs to pass a List`1 to a CLR method expecting System.Object, MoonSharp gets - /// in the way by converting the List`1 to a MoonSharp.Interpreter.Table and breaking everything. - /// Registering the List`1 type can break other scripts relying on default converters, so instead - /// it is better to manually wrap the List`1 object into a userdata. - /// - /// - /// Lua value to convert and wrap in a userdata. - /// Type describing the CLR type of the object to convert the Lua value to. - /// A userdata that wraps the Lua value converted to an object of the desired type. - public static DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType) - { - IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true); - descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default); - return CreateUserDataFromDescriptor(scriptObject, descriptor); - } - } + public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {methodName} accessible."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + + if (method == null) + { + method = FindMethodRecursively(IUUD.Type, methodName); + } + + if (method == null) + { + throw new ScriptRuntimeException($"Tried to make method '{methodName}' accessible, but the method doesn't exist."); + } + + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default)); + } + + public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add method {methodName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) => + { + if (GameMain.LuaCs != null) + return GameMain.LuaCs.CallLuaFunction(function, arg3.GetArray()); + return null; + })); + } + + public static void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add field {fieldName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(fieldName); + descriptor.AddMember(fieldName, new DynValueMemberDescriptor(fieldName, value)); + } + + public static void RemoveMember(IUserDataDescriptor IUUD, string memberName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to remove the member {memberName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(memberName); + } + + /// + /// See . + /// + /// Lua value to convert and wrap in a userdata. + /// Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters. + /// A userdata that wraps the Lua value converted to an object of the desired type as described by . + public static DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor) + { + return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor); + } + + /// + /// Converts a Lua value to a CLR object of a desired type and wraps it in a userdata. + /// If the type is not registered, then a new will be created and used. + /// The goal of this method is to allow Lua scripts to create userdata to wrap certain data without having to register types. + /// Wrapping the value in a userdata preserves the original type during script-to-CLR conversions. + /// A Lua script needs to pass a List`1 to a CLR method expecting System.Object, MoonSharp gets + /// in the way by converting the List`1 to a MoonSharp.Interpreter.Table and breaking everything. + /// Registering the List`1 type can break other scripts relying on default converters, so instead + /// it is better to manually wrap the List`1 object into a userdata. + /// + /// + /// Lua value to convert and wrap in a userdata. + /// Type describing the CLR type of the object to convert the Lua value to. + /// A userdata that wraps the Lua value converted to an object of the desired type. + public static DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType) + { + IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true); + descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default); + return CreateUserDataFromDescriptor(scriptObject, descriptor); + } + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaScriptLoader.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaScriptLoader.cs index 64ebceb3d..212c70ae5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaScriptLoader.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaScriptLoader.cs @@ -8,21 +8,21 @@ using System.Linq; namespace Barotrauma { - class LuaScriptLoader : ScriptLoaderBase - { + class LuaScriptLoader : ScriptLoaderBase + { - public override object LoadFile(string file, Table globalContext) - { - if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null; - - return File.ReadAllText(file); - } + public override object LoadFile(string file, Table globalContext) + { + if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null; + + return File.ReadAllText(file); + } - public override bool ScriptFileExists(string file) - { - if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return false; + public override bool ScriptFileExists(string file) + { + if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return false; - return File.Exists(file); - } + return File.Exists(file); + } } -} \ No newline at end of file +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsHookCompat.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsHookCompat.cs index dd8f39261..e48902f8e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsHookCompat.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsHookCompat.cs @@ -8,229 +8,229 @@ using LuaCsCompatPatchFunc = Barotrauma.LuaCsPatch; namespace Barotrauma { - // XXX: this can't be renamed because of backward compatibility with C# mods - public delegate object LuaCsPatch(object self, Dictionary args); + // XXX: this can't be renamed because of backward compatibility with C# mods + public delegate object LuaCsPatch(object self, Dictionary args); - partial class LuaCsHook + partial class LuaCsHook { - private Dictionary> compatHookPrefixMethods = new Dictionary>(); - private Dictionary> compatHookPostfixMethods = new Dictionary>(); + private Dictionary> compatHookPrefixMethods = new Dictionary>(); + private Dictionary> compatHookPostfixMethods = new Dictionary>(); - private static void _hookLuaCsPatch(MethodBase __originalMethod, object[] __args, object __instance, out object result, HookMethodType hookType) - { - result = null; + private static void _hookLuaCsPatch(MethodBase __originalMethod, object[] __args, object __instance, out object result, HookMethodType hookType) + { + result = null; - try - { - var funcAddr = ((long)__originalMethod.MethodHandle.GetFunctionPointer()); - HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet = null; - switch (hookType) - { - case HookMethodType.Before: - instance.compatHookPrefixMethods.TryGetValue(funcAddr, out methodSet); - break; - case HookMethodType.After: - instance.compatHookPostfixMethods.TryGetValue(funcAddr, out methodSet); - break; - default: - throw new ArgumentException($"Invalid {nameof(HookMethodType)} enum value.", nameof(hookType)); - } + try + { + var funcAddr = ((long)__originalMethod.MethodHandle.GetFunctionPointer()); + HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet = null; + switch (hookType) + { + case HookMethodType.Before: + instance.compatHookPrefixMethods.TryGetValue(funcAddr, out methodSet); + break; + case HookMethodType.After: + instance.compatHookPostfixMethods.TryGetValue(funcAddr, out methodSet); + break; + default: + throw new ArgumentException($"Invalid {nameof(HookMethodType)} enum value.", nameof(hookType)); + } - if (methodSet != null) - { - var @params = __originalMethod.GetParameters(); - var args = new Dictionary(); - for (int i = 0; i < @params.Length; i++) - { - args.Add(@params[i].Name, __args[i]); - } + if (methodSet != null) + { + var @params = __originalMethod.GetParameters(); + var args = new Dictionary(); + for (int i = 0; i < @params.Length; i++) + { + args.Add(@params[i].Name, __args[i]); + } - var outOfSocpe = new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>(); - foreach (var tuple in methodSet) - { - if (tuple.Item3 != null && tuple.Item3.IsDisposed) - { - outOfSocpe.Add(tuple); - } - else - { - var _result = tuple.Item2(__instance, args); - if (_result != null) - { - if (_result is DynValue res) - { - if (!res.IsNil()) - { - if (__originalMethod is MethodInfo mi && mi.ReturnType != typeof(void)) - { - result = res.ToObject(mi.ReturnType); - } - else - { - result = res.ToObject(); - } - } - } - else - { - result = _result; - } - } - } - } - foreach (var tuple in outOfSocpe) { methodSet.Remove(tuple); } - } - } - catch (Exception ex) - { - GameMain.LuaCs.PrintError($"Error in {__originalMethod.Name}:", LuaCsMessageOrigin.Unknown); - GameMain.LuaCs.HandleException(ex, LuaCsMessageOrigin.Unknown); - } - } + var outOfSocpe = new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>(); + foreach (var tuple in methodSet) + { + if (tuple.Item3 != null && tuple.Item3.IsDisposed) + { + outOfSocpe.Add(tuple); + } + else + { + var _result = tuple.Item2(__instance, args); + if (_result != null) + { + if (_result is DynValue res) + { + if (!res.IsNil()) + { + if (__originalMethod is MethodInfo mi && mi.ReturnType != typeof(void)) + { + result = res.ToObject(mi.ReturnType); + } + else + { + result = res.ToObject(); + } + } + } + else + { + result = _result; + } + } + } + } + foreach (var tuple in outOfSocpe) { methodSet.Remove(tuple); } + } + } + catch (Exception ex) + { + GameMain.LuaCs.PrintError($"Error in {__originalMethod.Name}:", LuaCsMessageOrigin.Unknown); + GameMain.LuaCs.HandleException(ex, LuaCsMessageOrigin.Unknown); + } + } - private static bool HookLuaCsPatchPrefix(MethodBase __originalMethod, object[] __args, object __instance) - { - _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before); - return result == null; - } + private static bool HookLuaCsPatchPrefix(MethodBase __originalMethod, object[] __args, object __instance) + { + _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before); + return result == null; + } - private static void HookLuaCsPatchPostfix(MethodBase __originalMethod, object[] __args, object __instance) => - _hookLuaCsPatch(__originalMethod, __args, __instance, out object _, HookMethodType.After); + private static void HookLuaCsPatchPostfix(MethodBase __originalMethod, object[] __args, object __instance) => + _hookLuaCsPatch(__originalMethod, __args, __instance, out object _, HookMethodType.After); - private static bool HookLuaCsPatchRetPrefix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance) - { - _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before); - if (result != null) - { - __result = result; - return false; - } - else return true; - } + private static bool HookLuaCsPatchRetPrefix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance) + { + _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before); + if (result != null) + { + __result = result; + return false; + } + else return true; + } - private static void HookLuaCsPatchRetPostfix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance) - { - _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.After); - if (result != null) __result = result; - } + private static void HookLuaCsPatchRetPostfix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance) + { + _hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.After); + if (result != null) __result = result; + } - private static MethodInfo _miHookLuaCsPatchPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static); - private static MethodInfo _miHookLuaCsPatchPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static); - private static MethodInfo _miHookLuaCsPatchRetPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static); - private static MethodInfo _miHookLuaCsPatchRetPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPostfix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaCsPatchPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaCsPatchPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaCsPatchRetPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaCsPatchRetPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPostfix", BindingFlags.NonPublic | BindingFlags.Static); // TODO: deprecate this - public void HookMethod(string identifier, MethodBase method, LuaCsCompatPatchFunc patch, HookMethodType hookType = HookMethodType.Before, ACsMod owner = null) - { - if (identifier == null || method == null || patch == null) - { - luaCs.HandleException(new ArgumentNullException("Identifier, Method and Patch arguments must not be null."), LuaCsMessageOrigin.Unknown); - return; - } - ValidatePatchTarget(method); - - var funcAddr = ((long)method.MethodHandle.GetFunctionPointer()); - var patches = Harmony.GetPatchInfo(method); - - if (hookType == HookMethodType.Before) - { - if (method is MethodInfo mi && mi.ReturnType != typeof(void)) - { - if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchRetPrefix) == null) - { - harmony.Patch(method, prefix: new HarmonyMethod(_miHookLuaCsPatchRetPrefix)); - } - } - else - { - if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchPrefix) == null) - { - harmony.Patch(method, prefix: new HarmonyMethod(_miHookLuaCsPatchPrefix)); - } - } - - if (compatHookPrefixMethods.TryGetValue(funcAddr, out HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet)) - { - if (identifier != "") - { - methodSet.RemoveWhere(tuple => tuple.Item1 == identifier); - } - - methodSet.Add((identifier, patch, owner)); - } - else if (patch != null) - { - compatHookPrefixMethods.Add(funcAddr, new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>() { (identifier, patch, owner) }); - } - - } - else if (hookType == HookMethodType.After) - { - if (method is MethodInfo mi && mi.ReturnType != typeof(void)) - { - if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchRetPostfix) == null) - { - harmony.Patch(method, postfix: new HarmonyMethod(_miHookLuaCsPatchRetPostfix)); - } - } - else - { - if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchPostfix) == null) - { - harmony.Patch(method, postfix: new HarmonyMethod(_miHookLuaCsPatchPostfix)); - } - } - - if (compatHookPostfixMethods.TryGetValue(funcAddr, out HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet)) - { - if (identifier != "") - { - methodSet.RemoveWhere(tuple => tuple.Item1 == identifier); - } - - methodSet.Add((identifier, patch, owner)); - } - else if (patch != null) - { - compatHookPostfixMethods.Add(funcAddr, new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>() { (identifier, patch, owner) }); - } - } - } - protected void HookMethod(string identifier, string className, string methodName, string[] parameterNames, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) - { - var method = ResolveMethod(className, methodName, parameterNames); - if (method == null) return; - if (method.GetParameters().Any(x => x.ParameterType.IsByRef)) + public void HookMethod(string identifier, MethodBase method, LuaCsCompatPatchFunc patch, HookMethodType hookType = HookMethodType.Before, ACsMod owner = null) + { + if (identifier == null || method == null || patch == null) { - throw new InvalidOperationException($"{nameof(HookMethod)} doesn't support ByRef parameters; use {nameof(Patch)} instead."); + luaCs.HandleException(new ArgumentNullException("Identifier, Method and Patch arguments must not be null."), LuaCsMessageOrigin.Unknown); + return; } - HookMethod(identifier, method, patch, hookMethodType); - } - protected void HookMethod(string identifier, string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => - HookMethod(identifier, className, methodName, null, patch, hookMethodType); - protected void HookMethod(string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => - HookMethod("", className, methodName, null, patch, hookMethodType); - protected void HookMethod(string className, string methodName, string[] parameterNames, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => - HookMethod("", className, methodName, parameterNames, patch, hookMethodType); + ValidatePatchTarget(method); + + var funcAddr = ((long)method.MethodHandle.GetFunctionPointer()); + var patches = Harmony.GetPatchInfo(method); + + if (hookType == HookMethodType.Before) + { + if (method is MethodInfo mi && mi.ReturnType != typeof(void)) + { + if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchRetPrefix) == null) + { + harmony.Patch(method, prefix: new HarmonyMethod(_miHookLuaCsPatchRetPrefix)); + } + } + else + { + if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchPrefix) == null) + { + harmony.Patch(method, prefix: new HarmonyMethod(_miHookLuaCsPatchPrefix)); + } + } + + if (compatHookPrefixMethods.TryGetValue(funcAddr, out HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet)) + { + if (identifier != "") + { + methodSet.RemoveWhere(tuple => tuple.Item1 == identifier); + } + + methodSet.Add((identifier, patch, owner)); + } + else if (patch != null) + { + compatHookPrefixMethods.Add(funcAddr, new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>() { (identifier, patch, owner) }); + } + + } + else if (hookType == HookMethodType.After) + { + if (method is MethodInfo mi && mi.ReturnType != typeof(void)) + { + if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchRetPostfix) == null) + { + harmony.Patch(method, postfix: new HarmonyMethod(_miHookLuaCsPatchRetPostfix)); + } + } + else + { + if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaCsPatchPostfix) == null) + { + harmony.Patch(method, postfix: new HarmonyMethod(_miHookLuaCsPatchPostfix)); + } + } + + if (compatHookPostfixMethods.TryGetValue(funcAddr, out HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet)) + { + if (identifier != "") + { + methodSet.RemoveWhere(tuple => tuple.Item1 == identifier); + } + + methodSet.Add((identifier, patch, owner)); + } + else if (patch != null) + { + compatHookPostfixMethods.Add(funcAddr, new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>() { (identifier, patch, owner) }); + } + } + } + protected void HookMethod(string identifier, string className, string methodName, string[] parameterNames, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) + { + var method = ResolveMethod(className, methodName, parameterNames); + if (method == null) return; + if (method.GetParameters().Any(x => x.ParameterType.IsByRef)) + { + throw new InvalidOperationException($"{nameof(HookMethod)} doesn't support ByRef parameters; use {nameof(Patch)} instead."); + } + HookMethod(identifier, method, patch, hookMethodType); + } + protected void HookMethod(string identifier, string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => + HookMethod(identifier, className, methodName, null, patch, hookMethodType); + protected void HookMethod(string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => + HookMethod("", className, methodName, null, patch, hookMethodType); + protected void HookMethod(string className, string methodName, string[] parameterNames, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) => + HookMethod("", className, methodName, parameterNames, patch, hookMethodType); - public void UnhookMethod(string identifier, MethodBase method, HookMethodType hookType = HookMethodType.Before) - { - var funcAddr = (long)method.MethodHandle.GetFunctionPointer(); + public void UnhookMethod(string identifier, MethodBase method, HookMethodType hookType = HookMethodType.Before) + { + var funcAddr = (long)method.MethodHandle.GetFunctionPointer(); - Dictionary> methods; - if (hookType == HookMethodType.Before) methods = compatHookPrefixMethods; - else if (hookType == HookMethodType.After) methods = compatHookPostfixMethods; - else throw null; + Dictionary> methods; + if (hookType == HookMethodType.Before) methods = compatHookPrefixMethods; + else if (hookType == HookMethodType.After) methods = compatHookPostfixMethods; + else throw null; - if (methods.ContainsKey(funcAddr)) methods[funcAddr]?.RemoveWhere(t => t.Item1 == identifier); - } - protected void UnhookMethod(string identifier, string className, string methodName, string[] parameterNames, HookMethodType hookType = HookMethodType.Before) - { - var method = ResolveMethod(className, methodName, parameterNames); - if (method == null) return; - UnhookMethod(identifier, method, hookType); - } - } + if (methods.ContainsKey(funcAddr)) methods[funcAddr]?.RemoveWhere(t => t.Item1 == identifier); + } + protected void UnhookMethod(string identifier, string className, string methodName, string[] parameterNames, HookMethodType hookType = HookMethodType.Before) + { + var method = ResolveMethod(className, methodName, parameterNames); + if (method == null) return; + UnhookMethod(identifier, method, hookType); + } + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsNetworking.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsNetworking.cs index c720b3505..781cab4b9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsNetworking.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsNetworking.cs @@ -11,286 +11,286 @@ using MoonSharp.Interpreter; namespace Barotrauma { - partial class LuaCsNetworking - { - public class HttpListener + partial class LuaCsNetworking + { + public class HttpListener { - private System.Net.HttpListener listener; + private System.Net.HttpListener listener; - public HttpListener(System.Net.HttpListener list) - { - listener = list; - } - - public void Close() - { - listener.Close(); - } - } - - public class IncomingHttpRequest - { - private HttpListenerRequest request; - - public IncomingHttpRequest(HttpListenerRequest req) + public HttpListener(System.Net.HttpListener list) { - request = req; - } + listener = list; + } - public string ContentType => request.ContentType; - public string LocalEndPoint => request.LocalEndPoint.ToString(); - public string RemoteEndPoint => request.RemoteEndPoint.ToString(); - public string RawUrl => request.RawUrl; - public Uri Url => request.Url; - public string UserAgent => request.UserAgent; - public string UserHostName => request.UserHostName; - public string UserHostAddress => request.UserHostAddress; - public NameValueCollection Headers => request.Headers; - public string HttpMethod => request.HttpMethod; - } + public void Close() + { + listener.Close(); + } + } - public class IncomingHttpResponse - { - private HttpListenerResponse response; + public class IncomingHttpRequest + { + private HttpListenerRequest request; - public IncomingHttpResponse(HttpListenerResponse resp) - { - response = resp; + public IncomingHttpRequest(HttpListenerRequest req) + { + request = req; + } - response.ContentType = "text/html"; - } + public string ContentType => request.ContentType; + public string LocalEndPoint => request.LocalEndPoint.ToString(); + public string RemoteEndPoint => request.RemoteEndPoint.ToString(); + public string RawUrl => request.RawUrl; + public Uri Url => request.Url; + public string UserAgent => request.UserAgent; + public string UserHostName => request.UserHostName; + public string UserHostAddress => request.UserHostAddress; + public NameValueCollection Headers => request.Headers; + public string HttpMethod => request.HttpMethod; + } - public string ContentType + public class IncomingHttpResponse + { + private HttpListenerResponse response; + + public IncomingHttpResponse(HttpListenerResponse resp) + { + response = resp; + + response.ContentType = "text/html"; + } + + public string ContentType { get { return response.ContentType; } - set { response.ContentType = value; } + set { response.ContentType = value; } } - public void Write(string text) - { - byte[] data = Encoding.UTF8.GetBytes(text); - response.ContentEncoding = Encoding.UTF8; - response.ContentLength64 = data.LongLength; + public void Write(string text) + { + byte[] data = Encoding.UTF8.GetBytes(text); + response.ContentEncoding = Encoding.UTF8; + response.ContentLength64 = data.LongLength; - response.OutputStream.Write(data, 0, data.Length); - } - } + response.OutputStream.Write(data, 0, data.Length); + } + } - public bool RestrictMessageSize = true; - public Dictionary LuaCsNetReceives = new Dictionary(); + public bool RestrictMessageSize = true; + public Dictionary LuaCsNetReceives = new Dictionary(); #if SERVER - [MoonSharpHidden] - public void NetMessageReceived(IReadMessage netMessage, ClientPacketHeader header, Client client = null) - { - if (header == ClientPacketHeader.LUA_NET_MESSAGE) - { - string netMessageName = netMessage.ReadString(); - if (LuaCsNetReceives.ContainsKey(netMessageName)) - { - try - { - LuaCsNetReceives[netMessageName](netMessage, client); - } - catch (Exception e) - { - // TODO: make LuaCsNetworking hold a reference to LuaCsSetup instead of using this global - GameMain.LuaCs.PrintError($"Exception thrown inside NetMessageReceive({netMessageName})", LuaCsMessageOrigin.Unknown); - GameMain.LuaCs.HandleException(e, LuaCsMessageOrigin.Unknown); - } - } - } - else - { - GameMain.LuaCs.Hook.Call("netMessageReceived", netMessage, header, client); - } - } - -#else - [MoonSharpHidden] - public void NetMessageReceived(IReadMessage netMessage, ServerPacketHeader header, Client client = null) - { - if (header == ServerPacketHeader.LUA_NET_MESSAGE) - { - string netMessageName = netMessage.ReadString(); - if (LuaCsNetReceives.ContainsKey(netMessageName)) - { - try - { - LuaCsNetReceives[netMessageName](netMessage, client); - } - catch (Exception e) - { - GameMain.LuaCs.PrintError($"Exception thrown inside NetMessageReceive({netMessageName})", LuaCsMessageOrigin.Unknown); - GameMain.LuaCs.HandleException(e, LuaCsMessageOrigin.Unknown); - } - } - } - else - { - GameMain.LuaCs.Hook.Call("netMessageReceived", netMessage, header, client); - } - } -#endif - public void Receive(string netMessageName, LuaCsAction callback) - { - LuaCsNetReceives[netMessageName] = callback; - } - - public IWriteMessage Start(string netMessageName) - { - var message = new WriteOnlyMessage(); -#if SERVER - message.WriteByte((byte)ServerPacketHeader.LUA_NET_MESSAGE); -#else - message.WriteByte((byte)ClientPacketHeader.LUA_NET_MESSAGE); -#endif - message.WriteString(netMessageName); - return message; - } - - public IWriteMessage Start() - { - return new WriteOnlyMessage(); - } - -#if SERVER - public void ClientWriteLobby(Client client) => GameMain.Server.ClientWriteLobby(client); - - public void Send(IWriteMessage netMessage, NetworkConnection connection = null, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable) - { - if (connection == null) - { - foreach (NetworkConnection conn in Client.ClientList.Select(c => c.Connection)) - { - GameMain.Server.ServerPeer.Send(netMessage, conn, deliveryMethod); - } - } - else - { - GameMain.Server.ServerPeer.Send(netMessage, connection, deliveryMethod); - } - } -#else - public void Send(IWriteMessage netMessage, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable) - { - GameMain.Client.ClientPeer.Send(netMessage, deliveryMethod); - } -#endif - - public void HttpRequest(string url, LuaCsAction callback, string data = null, string method = "POST", string contentType = "application/json") - { - try - { - var httpWebRequest = (HttpWebRequest)WebRequest.Create(url); - httpWebRequest.ContentType = contentType; - httpWebRequest.Method = method; - - if (data != null) - { - using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) - streamWriter.Write(data); - } - - httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult result) => - { - try - { - var httpResponse = httpWebRequest.EndGetResponse(result); - using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) - { - string responseResult = streamReader.ReadToEnd(); - GameMain.LuaCs.Timer.Wait((object[] par) => { callback(responseResult); }, 0); - } - } - catch (Exception e) - { - GameMain.LuaCs.Timer.Wait((object[] par) => { callback(e.Message); }, 0); - } - }), null); - - } - catch (Exception e) - { - GameMain.LuaCs.Timer.Wait((object[] par) => { callback(e.Message); }, 0); - } - } - - public void HttpPost(string url, LuaCsAction callback, string data, string contentType = "application/json") + [MoonSharpHidden] + public void NetMessageReceived(IReadMessage netMessage, ClientPacketHeader header, Client client = null) { - HttpRequest(url, callback, data, "POST", contentType); - } + if (header == ClientPacketHeader.LUA_NET_MESSAGE) + { + string netMessageName = netMessage.ReadString(); + if (LuaCsNetReceives.ContainsKey(netMessageName)) + { + try + { + LuaCsNetReceives[netMessageName](netMessage, client); + } + catch (Exception e) + { + // TODO: make LuaCsNetworking hold a reference to LuaCsSetup instead of using this global + GameMain.LuaCs.PrintError($"Exception thrown inside NetMessageReceive({netMessageName})", LuaCsMessageOrigin.Unknown); + GameMain.LuaCs.HandleException(e, LuaCsMessageOrigin.Unknown); + } + } + } + else + { + GameMain.LuaCs.Hook.Call("netMessageReceived", netMessage, header, client); + } + } + +#else + [MoonSharpHidden] + public void NetMessageReceived(IReadMessage netMessage, ServerPacketHeader header, Client client = null) + { + if (header == ServerPacketHeader.LUA_NET_MESSAGE) + { + string netMessageName = netMessage.ReadString(); + if (LuaCsNetReceives.ContainsKey(netMessageName)) + { + try + { + LuaCsNetReceives[netMessageName](netMessage, client); + } + catch (Exception e) + { + GameMain.LuaCs.PrintError($"Exception thrown inside NetMessageReceive({netMessageName})", LuaCsMessageOrigin.Unknown); + GameMain.LuaCs.HandleException(e, LuaCsMessageOrigin.Unknown); + } + } + } + else + { + GameMain.LuaCs.Hook.Call("netMessageReceived", netMessage, header, client); + } + } +#endif + public void Receive(string netMessageName, LuaCsAction callback) + { + LuaCsNetReceives[netMessageName] = callback; + } + + public IWriteMessage Start(string netMessageName) + { + var message = new WriteOnlyMessage(); +#if SERVER + message.WriteByte((byte)ServerPacketHeader.LUA_NET_MESSAGE); +#else + message.WriteByte((byte)ClientPacketHeader.LUA_NET_MESSAGE); +#endif + message.WriteString(netMessageName); + return message; + } + + public IWriteMessage Start() + { + return new WriteOnlyMessage(); + } + +#if SERVER + public void ClientWriteLobby(Client client) => GameMain.Server.ClientWriteLobby(client); + + public void Send(IWriteMessage netMessage, NetworkConnection connection = null, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable) + { + if (connection == null) + { + foreach (NetworkConnection conn in Client.ClientList.Select(c => c.Connection)) + { + GameMain.Server.ServerPeer.Send(netMessage, conn, deliveryMethod); + } + } + else + { + GameMain.Server.ServerPeer.Send(netMessage, connection, deliveryMethod); + } + } +#else + public void Send(IWriteMessage netMessage, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable) + { + GameMain.Client.ClientPeer.Send(netMessage, deliveryMethod); + } +#endif + + public void HttpRequest(string url, LuaCsAction callback, string data = null, string method = "POST", string contentType = "application/json") + { + try + { + var httpWebRequest = (HttpWebRequest)WebRequest.Create(url); + httpWebRequest.ContentType = contentType; + httpWebRequest.Method = method; + + if (data != null) + { + using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) + streamWriter.Write(data); + } + + httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult result) => + { + try + { + var httpResponse = httpWebRequest.EndGetResponse(result); + using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) + { + string responseResult = streamReader.ReadToEnd(); + GameMain.LuaCs.Timer.Wait((object[] par) => { callback(responseResult); }, 0); + } + } + catch (Exception e) + { + GameMain.LuaCs.Timer.Wait((object[] par) => { callback(e.Message); }, 0); + } + }), null); + + } + catch (Exception e) + { + GameMain.LuaCs.Timer.Wait((object[] par) => { callback(e.Message); }, 0); + } + } + + public void HttpPost(string url, LuaCsAction callback, string data, string contentType = "application/json") + { + HttpRequest(url, callback, data, "POST", contentType); + } - public void HttpGet(string url, LuaCsAction callback) - { - HttpRequest(url, callback, null, "GET"); - } + public void HttpGet(string url, LuaCsAction callback) + { + HttpRequest(url, callback, null, "GET"); + } - public static async void HandleIncomingConnections(System.Net.HttpListener listener, LuaCsAction onRequestReceived) - { - try - { - while (listener.IsListening) - { - HttpListenerContext ctx = await listener.GetContextAsync(); + public static async void HandleIncomingConnections(System.Net.HttpListener listener, LuaCsAction onRequestReceived) + { + try + { + while (listener.IsListening) + { + HttpListenerContext ctx = await listener.GetContextAsync(); - IncomingHttpRequest req = new IncomingHttpRequest(ctx.Request); - IncomingHttpResponse resp = new IncomingHttpResponse(ctx.Response); + IncomingHttpRequest req = new IncomingHttpRequest(ctx.Request); + IncomingHttpResponse resp = new IncomingHttpResponse(ctx.Response); - onRequestReceived(req, resp); + onRequestReceived(req, resp); - ctx.Response.Close(); - } + ctx.Response.Close(); + } - } - catch (Exception) + } + catch (Exception) { } - } + } public LuaCsNetworking.HttpListener StartHttpServer(string address, LuaCsAction onRequestReceived) { - var listener = new System.Net.HttpListener(); - listener.Prefixes.Add(address); - listener.Start(); + var listener = new System.Net.HttpListener(); + listener.Prefixes.Add(address); + listener.Start(); - HandleIncomingConnections(listener, onRequestReceived); + HandleIncomingConnections(listener, onRequestReceived); - return new LuaCsNetworking.HttpListener(listener); - } + return new LuaCsNetworking.HttpListener(listener); + } - public void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData) - { - GameMain.NetworkMember.CreateEntityEvent(entity, extraData); - } + public void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData) + { + GameMain.NetworkMember.CreateEntityEvent(entity, extraData); + } #if SERVER - public void UpdateClientPermissions(Client client) - { - GameMain.Server.UpdateClientPermissions(client); - } + public void UpdateClientPermissions(Client client) + { + GameMain.Server.UpdateClientPermissions(client); + } - public void RemovePendingClient(ServerPeer.PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket) - { - GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, peerDisconnectPacket); - } + public void RemovePendingClient(ServerPeer.PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket) + { + GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, peerDisconnectPacket); + } - public int FileSenderMaxPacketsPerUpdate - { - get { return FileSender.FileTransferOut.MaxPacketsPerUpdate; } - set { FileSender.FileTransferOut.MaxPacketsPerUpdate = value; } - } + public int FileSenderMaxPacketsPerUpdate + { + get { return FileSender.FileTransferOut.MaxPacketsPerUpdate; } + set { FileSender.FileTransferOut.MaxPacketsPerUpdate = value; } + } #endif - public ushort LastClientListUpdateID - { - get { return GameMain.NetworkMember.LastClientListUpdateID; } - set { GameMain.NetworkMember.LastClientListUpdateID = value; } - } - } + public ushort LastClientListUpdateID + { + get { return GameMain.NetworkMember.LastClientListUpdateID; } + set { GameMain.NetworkMember.LastClientListUpdateID = value; } + } + } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSteam.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSteam.cs index d4f891664..861d17e89 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSteam.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSteam.cs @@ -1,4 +1,4 @@ -using Steamworks; +using Steamworks; using Steamworks.Data; using Barotrauma.Steam; using System.Threading; @@ -10,8 +10,8 @@ using System; namespace Barotrauma { - partial class LuaCsSteam - { + partial class LuaCsSteam + { private struct WorkshopItemDownload { public ulong ID; @@ -54,7 +54,7 @@ namespace Barotrauma { itemsBeingDownloaded.Add(download); } - } + } public void DownloadWorkshopItem(ulong id, string destination, LuaCsAction callback) @@ -93,4 +93,4 @@ namespace Barotrauma } } } -} \ No newline at end of file +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsUtility.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsUtility.cs index d9087591b..ffa2ba388 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsUtility.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsUtility.cs @@ -13,47 +13,47 @@ using System.Xml.Linq; namespace Barotrauma { - partial class LuaCsFile - { - public static bool CanReadFromPath(string path) - { - string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath(); + partial class LuaCsFile + { + public static bool CanReadFromPath(string path) + { + string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath(); - path = getFullPath(path); + path = getFullPath(path); - bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); + bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); - string localModsDir = getFullPath(ContentPackage.LocalModsDir); - string workshopModsDir = getFullPath(ContentPackage.WorkshopModsDir); + string localModsDir = getFullPath(ContentPackage.LocalModsDir); + string workshopModsDir = getFullPath(ContentPackage.WorkshopModsDir); #if CLIENT string tempDownloadDir = getFullPath(ModReceiver.DownloadFolder); #endif - if (pathStartsWith(localModsDir)) - return true; + if (pathStartsWith(localModsDir)) + return true; - if (pathStartsWith(workshopModsDir)) - return true; + if (pathStartsWith(workshopModsDir)) + return true; #if CLIENT - if (pathStartsWith(tempDownloadDir)) - return true; + if (pathStartsWith(tempDownloadDir)) + return true; #endif - if (pathStartsWith(getFullPath("."))) - return true; + if (pathStartsWith(getFullPath("."))) + return true; - return false; - } + return false; + } - public static bool CanWriteToPath(string path) - { - string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath(); + public static bool CanWriteToPath(string path) + { + string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath(); - path = getFullPath(path); + path = getFullPath(path); - bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); + bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); foreach (var package in ContentPackageManager.AllPackages) { @@ -67,451 +67,451 @@ namespace Barotrauma return true; if (pathStartsWith(getFullPath(ContentPackage.LocalModsDir))) - return true; + return true; - if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir))) - return true; + if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir))) + return true; #if CLIENT - if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder))) - return true; + if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder))) + return true; #endif - return false; - } + return false; + } - public static bool IsPathAllowedException(string path, bool write = true, LuaCsMessageOrigin origin = LuaCsMessageOrigin.Unknown) - { - if (write) - { - if (CanWriteToPath(path)) - { - return true; - } - else - { - throw new Exception("File access to \"" + path + "\" not allowed."); - } - } - else - { - if (CanReadFromPath(path)) - { - return true; - } - else - { - throw new Exception("File access to \"" + path + "\" not allowed."); - } - } - } + public static bool IsPathAllowedException(string path, bool write = true, LuaCsMessageOrigin origin = LuaCsMessageOrigin.Unknown) + { + if (write) + { + if (CanWriteToPath(path)) + { + return true; + } + else + { + throw new Exception("File access to \"" + path + "\" not allowed."); + } + } + else + { + if (CanReadFromPath(path)) + { + return true; + } + else + { + throw new Exception("File access to \"" + path + "\" not allowed."); + } + } + } - public static bool IsPathAllowedLuaException(string path, bool write = true) => - IsPathAllowedException(path, write, LuaCsMessageOrigin.LuaMod); - public static bool IsPathAllowedCsException(string path, bool write = true) => - IsPathAllowedException(path, write, LuaCsMessageOrigin.CSharpMod); + public static bool IsPathAllowedLuaException(string path, bool write = true) => + IsPathAllowedException(path, write, LuaCsMessageOrigin.LuaMod); + public static bool IsPathAllowedCsException(string path, bool write = true) => + IsPathAllowedException(path, write, LuaCsMessageOrigin.CSharpMod); - public static string Read(string path) - { - if (!IsPathAllowedException(path, false)) - return ""; + public static string Read(string path) + { + if (!IsPathAllowedException(path, false)) + return ""; - return File.ReadAllText(path); - } + return File.ReadAllText(path); + } - public static void Write(string path, string text) - { - if (!IsPathAllowedException(path)) - return; + public static void Write(string path, string text) + { + if (!IsPathAllowedException(path)) + return; - File.WriteAllText(path, text); - } + File.WriteAllText(path, text); + } - public static void Delete(string path) - { - if (!IsPathAllowedException(path)) - return; + public static void Delete(string path) + { + if (!IsPathAllowedException(path)) + return; - File.Delete(path); - } + File.Delete(path); + } - public static void DeleteDirectory(string path) - { - if (!IsPathAllowedException(path)) - return; + public static void DeleteDirectory(string path) + { + if (!IsPathAllowedException(path)) + return; - Directory.Delete(path, true); - } + Directory.Delete(path, true); + } - public static FileStream OpenRead(string path) - { - if (!IsPathAllowedException(path)) - return null; + public static FileStream OpenRead(string path) + { + if (!IsPathAllowedException(path)) + return null; - return File.Open(path, FileMode.Open, FileAccess.Read); - } - public static FileStream OpenWrite(string path) - { - if (!IsPathAllowedException(path)) - return null; + return File.Open(path, FileMode.Open, FileAccess.Read); + } + public static FileStream OpenWrite(string path) + { + if (!IsPathAllowedException(path)) + return null; - if (File.Exists(path)) return File.Open(path, FileMode.Truncate, FileAccess.Write); - else return File.Open(path, FileMode.Create, FileAccess.Write); - } + if (File.Exists(path)) return File.Open(path, FileMode.Truncate, FileAccess.Write); + else return File.Open(path, FileMode.Create, FileAccess.Write); + } - public static bool Exists(string path) - { - if (!IsPathAllowedException(path, false)) - return false; + public static bool Exists(string path) + { + if (!IsPathAllowedException(path, false)) + return false; - return File.Exists(path); - } + return File.Exists(path); + } - public static bool CreateDirectory(string path) - { - if (!IsPathAllowedException(path)) - return false; + public static bool CreateDirectory(string path) + { + if (!IsPathAllowedException(path)) + return false; - Directory.CreateDirectory(path); + Directory.CreateDirectory(path); - return true; - } + return true; + } - public static bool DirectoryExists(string path) - { - if (!IsPathAllowedException(path, false)) - return false; + public static bool DirectoryExists(string path) + { + if (!IsPathAllowedException(path, false)) + return false; - return Directory.Exists(path); - } + return Directory.Exists(path); + } - public static string[] GetFiles(string path) - { - if (!IsPathAllowedException(path, false)) - return null; + public static string[] GetFiles(string path) + { + if (!IsPathAllowedException(path, false)) + return null; - return Directory.GetFiles(path); - } + return Directory.GetFiles(path); + } - public static string[] GetDirectories(string path) - { - if (!IsPathAllowedException(path, false)) - return new string[] { }; + public static string[] GetDirectories(string path) + { + if (!IsPathAllowedException(path, false)) + return new string[] { }; - return Directory.GetDirectories(path); - } + return Directory.GetDirectories(path); + } - public static string[] DirSearch(string sDir) - { - if (!IsPathAllowedException(sDir, false)) - return new string[] { }; + public static string[] DirSearch(string sDir) + { + if (!IsPathAllowedException(sDir, false)) + return new string[] { }; - List files = new List(); + List files = new List(); - try - { - foreach (string f in Directory.GetFiles(sDir)) - { - files.Add(f); - } + try + { + foreach (string f in Directory.GetFiles(sDir)) + { + files.Add(f); + } - foreach (string d in Directory.GetDirectories(sDir)) - { - foreach (string f in Directory.GetFiles(d)) - { - files.Add(f); - } - DirSearch(d); - } - } - catch (System.Exception excpt) - { - Console.WriteLine(excpt.Message); - } + foreach (string d in Directory.GetDirectories(sDir)) + { + foreach (string f in Directory.GetFiles(d)) + { + files.Add(f); + } + DirSearch(d); + } + } + catch (System.Exception excpt) + { + Console.WriteLine(excpt.Message); + } - return files.ToArray(); - } - } + return files.ToArray(); + } + } - class LuaCsConfig + class LuaCsConfig { - private enum ValueType + private enum ValueType { - None, - Text, - Integer, - Decimal, - Boolean, - Collection, - Object, - Enum + None, + Text, + Integer, + Decimal, + Boolean, + Collection, + Object, + Enum } - private static Type[] LoadDocTypes(XElement typesElem) + private static Type[] LoadDocTypes(XElement typesElem) { - var result = new List(); - foreach (var elem in typesElem.Elements()) + var result = new List(); + foreach (var elem in typesElem.Elements()) { - var type = Type.GetType(elem.Value); - if (type == null && GameMain.LuaCs?.CsScriptLoader?.Assembly != null) type = GameMain.LuaCs.CsScriptLoader.Assembly.GetType(elem.Value); - if (type == null) throw new Exception($"Type {elem.Value} not found."); - result.Add(type); + var type = Type.GetType(elem.Value); + if (type == null && GameMain.LuaCs?.CsScriptLoader?.Assembly != null) type = GameMain.LuaCs.CsScriptLoader.Assembly.GetType(elem.Value); + if (type == null) throw new Exception($"Type {elem.Value} not found."); + result.Add(type); - } - return result.ToArray(); + } + return result.ToArray(); } - private static IEnumerable SaveDocTypes(IEnumerable types) - { - return types.Select(t => new XElement("Type", t.ToString())); - } - - private static Type GetTypeAttr(Type[] types, XElement elem) + private static IEnumerable SaveDocTypes(IEnumerable types) { - var idx = elem.GetAttributeInt("Type", -1); - if (idx < 0 || idx >= types.Length) throw new Exception($"Type index '{idx}' is outside of saved types bounds"); - return types[idx]; - } - private static ValueType GetValueType(XElement elem) + return types.Select(t => new XElement("Type", t.ToString())); + } + + private static Type GetTypeAttr(Type[] types, XElement elem) { - Enum.TryParse(typeof(ValueType), elem.Attribute("Value")?.Value, out object result); - if (result != null) return (ValueType)result; - else return ValueType.None; - } - private static object ParseValue(Type[] types, XElement elem) + var idx = elem.GetAttributeInt("Type", -1); + if (idx < 0 || idx >= types.Length) throw new Exception($"Type index '{idx}' is outside of saved types bounds"); + return types[idx]; + } + private static ValueType GetValueType(XElement elem) { - var type = GetValueType(elem); + Enum.TryParse(typeof(ValueType), elem.Attribute("Value")?.Value, out object result); + if (result != null) return (ValueType)result; + else return ValueType.None; + } + private static object ParseValue(Type[] types, XElement elem) + { + var type = GetValueType(elem); - if (elem.IsEmpty) return null; - if (type == ValueType.Enum) + if (elem.IsEmpty) return null; + if (type == ValueType.Enum) { - var tType = GetTypeAttr(types, elem); - if (tType == null || !tType.IsSubclassOf(typeof(Enum))) return null; - if (Enum.TryParse(tType, elem.Value, out object result)) return result; - else return null; - } - if (type == ValueType.Collection) - { - var tType = GetTypeAttr(types, elem); - var tInt = tType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); - var gArg = tInt.GetGenericArguments()[0]; - if (tType == null || !tType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) return null; - - object result = null; - - if (result == null) { - var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => - { - var param = c.GetParameters(); - return param.Count() == 1 && param.Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)); - }); - if (ctor != null) - { - var elements = elem.Elements().Select(x => ParseValue(types, x)); - var castElems = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(gArg).Invoke(elements, new object[] { elements }); - result = ctor.Invoke(new object[] { castElems }); - } - } - - if (result == null) - { - var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0); - var addMethod = tType.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(m => - { - if (m.Name != "Add") return false; - var param = m.GetParameters(); - return param.Count() == 1 && param[0].ParameterType == gArg; - }); - if (ctor != null && addMethod != null) - { - var elements = elem.Elements().Select(x => ParseValue(types, x)); - result = ctor.Invoke(null); - foreach (var el in elements) addMethod.Invoke(result, new object[] { el }); - } - } - - if (result == null) - { - var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(); - var setMethod = tType.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(m => - { - if (m.Name != "Set") return false; - var param = m.GetParameters(); - return param.Count() == 2 && param[0].ParameterType == typeof(int) && param[1].ParameterType == gArg; - }); - if (ctor != null || setMethod != null) - { - var elements = elem.Elements().Select(x => ParseValue(types, x)); - result = ctor.Invoke(new object[] { elements.Count() }); - int i = 0; - foreach (var el in elements) - { - setMethod.Invoke(result, new object[] { i, el }); - i++; - } - } - } - - return result; - } - else if (type == ValueType.Text) return elem.Value; - else if (type == ValueType.Integer) - { - int.TryParse(elem.Value, out var num); - return num; - } - else if (type == ValueType.Decimal) + var tType = GetTypeAttr(types, elem); + if (tType == null || !tType.IsSubclassOf(typeof(Enum))) return null; + if (Enum.TryParse(tType, elem.Value, out object result)) return result; + else return null; + } + if (type == ValueType.Collection) { - float.TryParse(elem.Value, out var num); - return num; - } - else if (type == ValueType.Boolean) - { - bool.TryParse(elem.Value, out var boolean); - return boolean; - } - else if (type == ValueType.Object) - { - var tType = GetTypeAttr(types, elem); - if (tType == null) return null; + var tType = GetTypeAttr(types, elem); + var tInt = tType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); + var gArg = tInt.GetGenericArguments()[0]; + if (tType == null || !tType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) return null; - IEnumerable fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public) - .Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)); - IEnumerable properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null) - .Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null)); + object result = null; - object result = null; - var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0); - if (ctor == null) - { - if (!tType.IsValueType) return null; - result = Activator.CreateInstance(tType); - } - else result = ctor.Invoke(null); - - foreach(var el in elem.Elements()) - { - var value = ParseValue(types, el); - - var field = fields.FirstOrDefault(f => f.Name == el.Name.LocalName); - if (field != null) field.SetValue(result, value); - var property = properties.FirstOrDefault(p => p.Name == el.Name.LocalName); - if (property != null) property.SetValue(result, value); + if (result == null) { + var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => + { + var param = c.GetParameters(); + return param.Count() == 1 && param.Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)); + }); + if (ctor != null) + { + var elements = elem.Elements().Select(x => ParseValue(types, x)); + var castElems = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(gArg).Invoke(elements, new object[] { elements }); + result = ctor.Invoke(new object[] { castElems }); + } } - return result; - } - else return elem.Value; - } - - private static void AddTypeAttr(List types, Type type, XElement elem) - { - if (!types.Contains(type)) types.Add(type); - elem.SetAttributeValue("Type", types.IndexOf(type)); - } - - private static XElement ParseObject(List types, string name, object value) - { - XElement result = new XElement(name); - - if (value != null) - { - var tType = value.GetType(); - - if (tType.IsEnum) + if (result == null) { - result.SetAttributeValue("Value", ValueType.Enum); - AddTypeAttr(types, tType, result); - - result.Value = Enum.GetName(tType, value) ?? ""; + var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0); + var addMethod = tType.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(m => + { + if (m.Name != "Add") return false; + var param = m.GetParameters(); + return param.Count() == 1 && param[0].ParameterType == gArg; + }); + if (ctor != null && addMethod != null) + { + var elements = elem.Elements().Select(x => ParseValue(types, x)); + result = ctor.Invoke(null); + foreach (var el in elements) addMethod.Invoke(result, new object[] { el }); + } } - else if (value is string str) - { - result.SetAttributeValue("Value", ValueType.Text); - result.Value = str; - } - else if (value is int integer) - { - result.SetAttributeValue("Value", ValueType.Integer); - result.Value = integer.ToString(); - } - else if (value is float || value is double) - { - result.SetAttributeValue("Value", ValueType.Decimal); - result.Value = value.ToString(); - } - else if (value is bool boolean) - { - result.SetAttributeValue("Value", ValueType.Boolean); - result.Value = boolean.ToString(); - } - else if (tType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) - { - result.SetAttributeValue("Value", ValueType.Collection); - AddTypeAttr(types, tType, result); - var enumerator = (IEnumerator)tType.GetMethod("GetEnumerator").Invoke(value, null); - while (enumerator.MoveNext()) - { - var elVal = ParseObject(types, "Item", enumerator.Current); - result.Add(elVal); - } - } - else if (tType.IsClass || tType.IsValueType) + if (result == null) { - result.SetAttributeValue("Value", ValueType.Object); - AddTypeAttr(types, tType, result); + var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(); + var setMethod = tType.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(m => + { + if (m.Name != "Set") return false; + var param = m.GetParameters(); + return param.Count() == 2 && param[0].ParameterType == typeof(int) && param[1].ParameterType == gArg; + }); + if (ctor != null || setMethod != null) + { + var elements = elem.Elements().Select(x => ParseValue(types, x)); + result = ctor.Invoke(new object[] { elements.Count() }); + int i = 0; + foreach (var el in elements) + { + setMethod.Invoke(result, new object[] { i, el }); + i++; + } + } + } - IEnumerable fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public) - .Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)); - IEnumerable properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null) - .Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null)); + return result; + } + else if (type == ValueType.Text) return elem.Value; + else if (type == ValueType.Integer) + { + int.TryParse(elem.Value, out var num); + return num; + } + else if (type == ValueType.Decimal) + { + float.TryParse(elem.Value, out var num); + return num; + } + else if (type == ValueType.Boolean) + { + bool.TryParse(elem.Value, out var boolean); + return boolean; + } + else if (type == ValueType.Object) + { + var tType = GetTypeAttr(types, elem); + if (tType == null) return null; - foreach(var field in fields) result.Add(ParseObject(types, field.Name, field.GetValue(value))); - foreach (var property in properties) result.Add(ParseObject(types, property.Name, property.GetValue(value))); - } - else - { - result.SetAttributeValue("Value", ValueType.None); - result.Value = value.ToString(); - } - } + IEnumerable fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public) + .Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)); + IEnumerable properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null) + .Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null)); - return result; + object result = null; + var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0); + if (ctor == null) + { + if (!tType.IsValueType) return null; + result = Activator.CreateInstance(tType); + } + else result = ctor.Invoke(null); + + foreach(var el in elem.Elements()) + { + var value = ParseValue(types, el); + + var field = fields.FirstOrDefault(f => f.Name == el.Name.LocalName); + if (field != null) field.SetValue(result, value); + var property = properties.FirstOrDefault(p => p.Name == el.Name.LocalName); + if (property != null) property.SetValue(result, value); + } + return result; + } + else return elem.Value; + + } + + private static void AddTypeAttr(List types, Type type, XElement elem) + { + if (!types.Contains(type)) types.Add(type); + elem.SetAttributeValue("Type", types.IndexOf(type)); + } + + private static XElement ParseObject(List types, string name, object value) + { + XElement result = new XElement(name); + + if (value != null) + { + var tType = value.GetType(); + + if (tType.IsEnum) + { + result.SetAttributeValue("Value", ValueType.Enum); + AddTypeAttr(types, tType, result); + + result.Value = Enum.GetName(tType, value) ?? ""; + } + else if (value is string str) + { + result.SetAttributeValue("Value", ValueType.Text); + result.Value = str; + } + else if (value is int integer) + { + result.SetAttributeValue("Value", ValueType.Integer); + result.Value = integer.ToString(); + } + else if (value is float || value is double) + { + result.SetAttributeValue("Value", ValueType.Decimal); + result.Value = value.ToString(); + } + else if (value is bool boolean) + { + result.SetAttributeValue("Value", ValueType.Boolean); + result.Value = boolean.ToString(); + } + else if (tType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) + { + result.SetAttributeValue("Value", ValueType.Collection); + AddTypeAttr(types, tType, result); + + var enumerator = (IEnumerator)tType.GetMethod("GetEnumerator").Invoke(value, null); + while (enumerator.MoveNext()) + { + var elVal = ParseObject(types, "Item", enumerator.Current); + result.Add(elVal); + } + } + else if (tType.IsClass || tType.IsValueType) + { + result.SetAttributeValue("Value", ValueType.Object); + AddTypeAttr(types, tType, result); + + IEnumerable fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public) + .Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)); + IEnumerable properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null) + .Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null)); + + foreach(var field in fields) result.Add(ParseObject(types, field.Name, field.GetValue(value))); + foreach (var property in properties) result.Add(ParseObject(types, property.Name, property.GetValue(value))); + } + else + { + result.SetAttributeValue("Value", ValueType.None); + result.Value = value.ToString(); + } + } + + return result; } - public static T Load(FileStream file) - { - var doc = XDocument.Load(file); - - var rootElems = doc.Root.Elements().ToArray(); - var types = rootElems[0]; - var elem = rootElems[1]; - - var dict = ParseValue(LoadDocTypes(types), elem); - if (dict.GetType() == typeof(T)) return (T)dict; - else throw new Exception($"Loaded configuration is not of the type '{typeof(T).Name}'"); - } - - public static void Save(FileStream file, object obj) - { - var types = new List(); - var elem = ParseObject(types, "Root", obj); - var root = new XElement("Configuration", new XElement("Types", SaveDocTypes(types)), elem); - - var doc = new XDocument(root); - doc.Save(file); - } - - public static T Load(string path) - { - using (var file = LuaCsFile.OpenRead(path)) return Load(file); - } - - public static void Save(string path, object obj) + public static T Load(FileStream file) { - using (var file = LuaCsFile.OpenWrite(path)) Save(file, obj); - } + var doc = XDocument.Load(file); + + var rootElems = doc.Root.Elements().ToArray(); + var types = rootElems[0]; + var elem = rootElems[1]; + + var dict = ParseValue(LoadDocTypes(types), elem); + if (dict.GetType() == typeof(T)) return (T)dict; + else throw new Exception($"Loaded configuration is not of the type '{typeof(T).Name}'"); + } + + public static void Save(FileStream file, object obj) + { + var types = new List(); + var elem = ParseObject(types, "Root", obj); + var root = new XElement("Configuration", new XElement("Types", SaveDocTypes(types)), elem); + + var doc = new XDocument(root); + doc.Save(file); + } + + public static T Load(string path) + { + using (var file = LuaCsFile.OpenRead(path)) return Load(file); + } + + public static void Save(string path, object obj) + { + using (var file = LuaCsFile.OpenWrite(path)) Save(file, obj); + } } }