Fix mixed spaces and tabs

This commit is contained in:
EvilFactory
2022-10-28 12:29:35 -03:00
parent 43810a3509
commit 5e29d1d8ba
11 changed files with 1864 additions and 1864 deletions

View File

@@ -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<string, object> Revision = new Dictionary<string, object>()
{
{ 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<string, object> Revision = new Dictionary<string, object>()
{
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() { }
}
}
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() { }
}
}

View File

@@ -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<MetadataReference> defaultReferences;
class CsScriptLoader : CsScriptBase
{
private List<MetadataReference> defaultReferences;
private Dictionary<string, List<string>> sources;
public Assembly Assembly { get; private set; }
private Dictionary<string, List<string>> 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<string, List<string>>();
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<string, string>();
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<string> { s });
}
}
}
sources = new Dictionary<string, List<string>>();
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<SyntaxTree> ParseSources() {
var syntaxTrees = new List<SyntaxTree>();
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<Type> Compile()
{
IEnumerable<SyntaxTree> 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<Diagnostic> 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;
}
}
}
}
public void SearchFolders()
{
var paths = new Dictionary<string, string>();
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<string> { s });
}
}
}
private void RunFolder(string folder)
{
AddSources(folder + "/CSharp/Shared");
#if SERVER
AddSources(folder + "/CSharp/Server");
#else
AddSources(folder + "/CSharp/Client");
#endif
}
private IEnumerable<SyntaxTree> ParseSources() {
var syntaxTrees = new List<SyntaxTree>();
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<Type> Compile()
{
IEnumerable<SyntaxTree> 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<Diagnostic> 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;
}
}
}

View File

@@ -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<MetadataReference> defaultReferences;
private CSharpCompilationOptions compileOptions;
private static readonly string[] usings = {
"System",
"Barotrauma",
"System.Collections.Generic",
"System.Linq"
};
class CsScriptRunner : CsScriptBase
{
public LuaCsSetup setup;
private List<MetadataReference> 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<Diagnostic> 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<int, (string, string)>();
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<Diagnostic> failures = result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error);
string errStr = "Script compilation errors:";
var lineErr = new SortedDictionary<int, (string, string)>();
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;
}
}
}
}
}

View File

@@ -7,19 +7,19 @@ using Barotrauma.Networking;
namespace Barotrauma.Networking
{
partial class Client
{
public static IReadOnlyList<Client> ClientList
{
get
{
partial class Client
{
public static IReadOnlyList<Client> 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
{
}
}

View File

@@ -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<Item> updatePriorityItems = new HashSet<Item>();
public HashSet<Character> updatePriorityCharacters = new HashSet<Character>();
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<Item> updatePriorityItems = new HashSet<Item>();
public HashSet<Character> updatePriorityCharacters = new HashSet<Character>();
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<Items.Components.Steering>();
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<WifiComponent>();
}
public World World
{
get
{
return GameMain.World;
}
}
public static LightComponent GetLightComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<LightComponent>();
}
#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<CustomInterface>();
}
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<Fabricator>();
}
public void OverrideTraitors(bool o)
{
overrideTraitors = o;
}
public static Holdable GetHoldableComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<Holdable>();
}
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<DebugConsole.Command> luaAddedCommand = new List<DebugConsole.Command>();
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<Items.Components.Steering>();
if (steering != null)
{
return steering;
}
}
return null;
}
public static WifiComponent GetWifiComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<WifiComponent>();
}
public static LightComponent GetLightComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<LightComponent>();
}
public static CustomInterface GetCustomInterface(Item item)
{
if (item == null) return null;
return item.GetComponent<CustomInterface>();
}
public static Fabricator GetFabricatorComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<Fabricator>();
}
public static Holdable GetHoldableComponent(Item item)
{
if (item == null) return null;
return item.GetComponent<Holdable>();
}
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<DebugConsole.Command> luaAddedCommand = new List<DebugConsole.Command>();
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<DebugConsole.Command> 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<DebugConsole.Command> 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);
}
}
}
}

View File

@@ -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<AssemblyMetadataAttribute>();
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<AssemblyMetadataAttribute>();
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<T>(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<string, object> result = new Dictionary<string, object>();
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<T>(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<string, object> result = new Dictionary<string, object>();
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);
}
/// <summary>
/// See <see cref="CreateUserDataFromType"/>.
/// </summary>
/// <param name="scriptObject">Lua value to convert and wrap in a userdata.</param>
/// <param name="desiredTypeDescriptor">Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters.</param>
/// <returns>A userdata that wraps the Lua value converted to an object of the desired type as described by <paramref name="desiredTypeDescriptor"/>.</returns>
public static DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor)
{
return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor);
}
return method;
}
/// <summary>
/// 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 <see cref="MoonSharp.Interpreter.Interop.StandardUserDataDescriptor"/> 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.
/// <remarks>Wrapping the value in a userdata preserves the original type during script-to-CLR conversions.</remarks>
/// <example>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.
/// </example>
/// </summary>
/// <param name="scriptObject">Lua value to convert and wrap in a userdata.</param>
/// <param name="desiredType">Type describing the CLR type of the object to convert the Lua value to.</param>
/// <returns>A userdata that wraps the Lua value converted to an object of the desired type.</returns>
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);
}
/// <summary>
/// See <see cref="CreateUserDataFromType"/>.
/// </summary>
/// <param name="scriptObject">Lua value to convert and wrap in a userdata.</param>
/// <param name="desiredTypeDescriptor">Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters.</param>
/// <returns>A userdata that wraps the Lua value converted to an object of the desired type as described by <paramref name="desiredTypeDescriptor"/>.</returns>
public static DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor)
{
return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor);
}
/// <summary>
/// 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 <see cref="MoonSharp.Interpreter.Interop.StandardUserDataDescriptor"/> 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.
/// <remarks>Wrapping the value in a userdata preserves the original type during script-to-CLR conversions.</remarks>
/// <example>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.
/// </example>
/// </summary>
/// <param name="scriptObject">Lua value to convert and wrap in a userdata.</param>
/// <param name="desiredType">Type describing the CLR type of the object to convert the Lua value to.</param>
/// <returns>A userdata that wraps the Lua value converted to an object of the desired type.</returns>
public static DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType)
{
IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true);
descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default);
return CreateUserDataFromDescriptor(scriptObject, descriptor);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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<string, object> args);
// XXX: this can't be renamed because of backward compatibility with C# mods
public delegate object LuaCsPatch(object self, Dictionary<string, object> args);
partial class LuaCsHook
partial class LuaCsHook
{
private Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> compatHookPrefixMethods = new Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>>();
private Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> compatHookPostfixMethods = new Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>>();
private Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> compatHookPrefixMethods = new Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>>();
private Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> compatHookPostfixMethods = new Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>>();
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<string, object>();
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<string, object>();
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<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> methods;
if (hookType == HookMethodType.Before) methods = compatHookPrefixMethods;
else if (hookType == HookMethodType.After) methods = compatHookPostfixMethods;
else throw null;
Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> 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);
}
}
}

View File

@@ -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<string, LuaCsAction> LuaCsNetReceives = new Dictionary<string, LuaCsAction>();
public bool RestrictMessageSize = true;
public Dictionary<string, LuaCsAction> LuaCsNetReceives = new Dictionary<string, LuaCsAction>();
#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; }
}
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -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<string> files = new List<string>();
List<string> files = new List<string>();
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<Type>();
foreach (var elem in typesElem.Elements())
var result = new List<Type>();
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<XElement> SaveDocTypes(IEnumerable<Type> types)
{
return types.Select(t => new XElement("Type", t.ToString()));
}
private static Type GetTypeAttr(Type[] types, XElement elem)
private static IEnumerable<XElement> SaveDocTypes(IEnumerable<Type> 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<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
IEnumerable<PropertyInfo> 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<Type> types, Type type, XElement elem)
{
if (!types.Contains(type)) types.Add(type);
elem.SetAttributeValue("Type", types.IndexOf(type));
}
private static XElement ParseObject(List<Type> 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<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
IEnumerable<PropertyInfo> 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<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
IEnumerable<PropertyInfo> 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<Type> types, Type type, XElement elem)
{
if (!types.Contains(type)) types.Add(type);
elem.SetAttributeValue("Type", types.IndexOf(type));
}
private static XElement ParseObject(List<Type> 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<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
IEnumerable<PropertyInfo> 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<T>(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<Type>();
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<T>(string path)
{
using (var file = LuaCsFile.OpenRead(path)) return Load<T>(file);
}
public static void Save(string path, object obj)
public static T Load<T>(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<Type>();
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<T>(string path)
{
using (var file = LuaCsFile.OpenRead(path)) return Load<T>(file);
}
public static void Save(string path, object obj)
{
using (var file = LuaCsFile.OpenWrite(path)) Save(file, obj);
}
}
}