Fix mixed spaces and tabs
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.CodeAnalysis.Scripting;
|
using Microsoft.CodeAnalysis.Scripting;
|
||||||
@@ -14,40 +14,40 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class CsScriptBase : AssemblyLoadContext
|
class CsScriptBase : AssemblyLoadContext
|
||||||
{
|
{
|
||||||
|
|
||||||
public const string CsOneTimeScriptAssembly = "NetOneTimeScriptAssembly";
|
public const string CsOneTimeScriptAssembly = "NetOneTimeScriptAssembly";
|
||||||
public const string CsScriptAssembly = "NetScriptAssembly";
|
public const string CsScriptAssembly = "NetScriptAssembly";
|
||||||
|
|
||||||
public static readonly string[] LoadedAssemblyName = {
|
public static readonly string[] LoadedAssemblyName = {
|
||||||
CsScriptBase.CsScriptAssembly,
|
CsScriptBase.CsScriptAssembly,
|
||||||
CsScriptBase.CsOneTimeScriptAssembly
|
CsScriptBase.CsOneTimeScriptAssembly
|
||||||
};
|
|
||||||
|
|
||||||
public static Dictionary<string, object> Revision = new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ CsScriptAssembly, 0},
|
|
||||||
{ CsOneTimeScriptAssembly, 0}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public CSharpParseOptions ParseOptions { get; protected set; }
|
public static Dictionary<string, object> Revision = new Dictionary<string, object>()
|
||||||
|
|
||||||
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;
|
{ CsScriptAssembly, 0},
|
||||||
var asmInfo = new StringBuilder();
|
{ CsOneTimeScriptAssembly, 0}
|
||||||
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() { }
|
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() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.CodeAnalysis.Scripting;
|
using Microsoft.CodeAnalysis.Scripting;
|
||||||
@@ -14,208 +14,208 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class CsScriptLoader : CsScriptBase
|
class CsScriptLoader : CsScriptBase
|
||||||
{
|
{
|
||||||
private List<MetadataReference> defaultReferences;
|
private List<MetadataReference> defaultReferences;
|
||||||
|
|
||||||
private Dictionary<string, List<string>> sources;
|
private Dictionary<string, List<string>> sources;
|
||||||
public Assembly Assembly { get; private set; }
|
public Assembly Assembly { get; private set; }
|
||||||
|
|
||||||
public CsScriptLoader()
|
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)
|
|
||||||
{
|
{
|
||||||
foreach (var str in DirSearch(folder))
|
defaultReferences = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
{
|
.Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit")))
|
||||||
string s = str.Replace("\\", "/");
|
.Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (sources.ContainsKey(folder))
|
sources = new Dictionary<string, List<string>>();
|
||||||
{
|
Assembly = null;
|
||||||
sources[folder].Add(s);
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sources.Add(folder, new List<string> { s });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RunFolder(string folder)
|
private enum RunType { Standard, Forced, None };
|
||||||
{
|
private bool ShouldRun(ContentPackage cp, string path)
|
||||||
|
{
|
||||||
AddSources(folder + "/CSharp/Shared");
|
if (!Directory.Exists(path + "CSharp"))
|
||||||
|
|
||||||
#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
|
return false;
|
||||||
{
|
|
||||||
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);
|
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()
|
if (elem != null && Enum.TryParse(elem.Value, true, out RunType rtValue))
|
||||||
{
|
{
|
||||||
Assembly = null;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.CodeAnalysis.Scripting;
|
using Microsoft.CodeAnalysis.Scripting;
|
||||||
@@ -13,109 +13,109 @@ using MoonSharp.Interpreter;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class CsScriptRunner : CsScriptBase
|
class CsScriptRunner : CsScriptBase
|
||||||
{
|
{
|
||||||
public LuaCsSetup setup;
|
public LuaCsSetup setup;
|
||||||
private List<MetadataReference> defaultReferences;
|
private List<MetadataReference> defaultReferences;
|
||||||
private CSharpCompilationOptions compileOptions;
|
private CSharpCompilationOptions compileOptions;
|
||||||
private static readonly string[] usings = {
|
private static readonly string[] usings = {
|
||||||
"System",
|
"System",
|
||||||
"Barotrauma",
|
"Barotrauma",
|
||||||
"System.Collections.Generic",
|
"System.Collections.Generic",
|
||||||
"System.Linq"
|
"System.Linq"
|
||||||
};
|
};
|
||||||
|
|
||||||
public CsScriptRunner(LuaCsSetup setup)
|
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)
|
|
||||||
{
|
{
|
||||||
var prefix = "";
|
this.setup = setup;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Run(string code)
|
defaultReferences = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
{
|
.Where(a => !(a.IsDynamic || string.IsNullOrEmpty(a.Location) || a.Location.Contains("xunit")))
|
||||||
object scriptResilt = null;
|
.Select(a => MetadataReference.CreateFromFile(a.Location) as MetadataReference)
|
||||||
|
.ToList();
|
||||||
|
compileOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
|
||||||
|
.WithMetadataImportOptions(MetadataImportOptions.All)
|
||||||
|
.WithOptimizationLevel(OptimizationLevel.Release)
|
||||||
|
.WithAllowUnsafe(false);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
private static string ToOneTimeScript(string code)
|
||||||
{
|
{
|
||||||
code = ToOneTimeScript(code);
|
var prefix = "";
|
||||||
var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, ParseOptions);
|
foreach (var u in usings) prefix += $"using {u}; ";
|
||||||
var compilation = CSharpCompilation.Create(CsOneTimeScriptAssembly, new[] { AssemblyInfoSyntaxTree(CsOneTimeScriptAssembly), syntaxTree }, defaultReferences, compileOptions);
|
prefix += "namespace NetOneTimeScript { public class NetOneTimeScriptRunner { public NetOneTimeScriptRunner() { } public object Run() {\n";
|
||||||
|
var postfix = "\nreturn null; } } }";
|
||||||
|
return prefix + code + postfix;
|
||||||
|
}
|
||||||
|
|
||||||
Assembly assembly = null;
|
public object Run(string code)
|
||||||
using (var mem = new MemoryStream())
|
{
|
||||||
{
|
object scriptResilt = null;
|
||||||
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:";
|
try
|
||||||
var lineErr = new SortedDictionary<int, (string, string)>();
|
{
|
||||||
foreach (Diagnostic diagnostic in failures)
|
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;
|
var line = syntaxTree.GetLineSpan(diagnostic.Location.SourceSpan).StartLinePosition.Line;
|
||||||
lineErr[line] = (diagnostic.Id, diagnostic.ToString());
|
lineErr[line] = (diagnostic.Id, diagnostic.ToString());
|
||||||
}
|
}
|
||||||
var lines = code.Split('\n');
|
var lines = code.Split('\n');
|
||||||
for (var i = 1; i < lines.Length - 1; i++)
|
for (var i = 1; i < lines.Length - 1; i++)
|
||||||
{
|
{
|
||||||
errStr += $"\n{i} >> {lines[i]}";
|
errStr += $"\n{i} >> {lines[i]}";
|
||||||
if (lineErr.ContainsKey(i)) errStr += $" <=== {lineErr[i].Item1}";
|
if (lineErr.ContainsKey(i)) errStr += $" <=== {lineErr[i].Item1}";
|
||||||
}
|
}
|
||||||
errStr += "\n";
|
errStr += "\n";
|
||||||
foreach ((var idx, (var id, var err)) in lineErr)
|
foreach ((var idx, (var id, var err)) in lineErr)
|
||||||
{
|
{
|
||||||
errStr += $"\n{idx}: {err}";
|
errStr += $"\n{idx}: {err}";
|
||||||
}
|
}
|
||||||
LuaCsSetup.PrintCsError(errStr);
|
LuaCsSetup.PrintCsError(errStr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem.Seek(0, SeekOrigin.Begin);
|
mem.Seek(0, SeekOrigin.Begin);
|
||||||
assembly = LoadFromStream(mem);
|
assembly = LoadFromStream(mem);
|
||||||
var runner = assembly.CreateInstance("NetOneTimeScript.NetOneTimeScriptRunner");
|
var runner = assembly.CreateInstance("NetOneTimeScript.NetOneTimeScriptRunner");
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
{
|
{
|
||||||
var method = runner.GetType().GetMethod("Run", BindingFlags.Public | BindingFlags.Instance);
|
var method = runner.GetType().GetMethod("Run", BindingFlags.Public | BindingFlags.Instance);
|
||||||
if (method != null)
|
if (method != null)
|
||||||
{
|
{
|
||||||
scriptResilt = method.Invoke(runner, null);
|
scriptResilt = method.Invoke(runner, null);
|
||||||
foreach (var type in assembly.GetTypes())
|
foreach (var type in assembly.GetTypes())
|
||||||
{
|
{
|
||||||
UserData.UnregisterType(type, true);
|
UserData.UnregisterType(type, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { LuaCsSetup.PrintCsError("Script Error - no run method detected"); }
|
else { LuaCsSetup.PrintCsError("Script Error - no run method detected"); }
|
||||||
}
|
}
|
||||||
else { LuaCsSetup.PrintCsError("Script Error - no runner class detected"); }
|
else { LuaCsSetup.PrintCsError("Script Error - no runner class detected"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unload();
|
Unload();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LuaCsSetup.PrintCsError("Error running script:\n" + ex.Message + "\n" + ex.StackTrace);
|
LuaCsSetup.PrintCsError("Error running script:\n" + ex.Message + "\n" + ex.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scriptResilt;
|
return scriptResilt;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ using Barotrauma.Networking;
|
|||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
partial class Client
|
partial class Client
|
||||||
{
|
{
|
||||||
public static IReadOnlyList<Client> ClientList
|
public static IReadOnlyList<Client> ClientList
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if SERVER
|
#if SERVER
|
||||||
return GameMain.Server.ConnectedClients;
|
return GameMain.Server.ConnectedClients;
|
||||||
#else
|
#else
|
||||||
return GameMain.Client.ConnectedClients;
|
return GameMain.Client.ConnectedClients;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong SteamID
|
public ulong SteamID
|
||||||
{
|
{
|
||||||
@@ -36,71 +36,71 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
partial class Character
|
partial class Character
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial class Item
|
partial class Item
|
||||||
{
|
{
|
||||||
public object GetComponentString(string component)
|
public object GetComponentString(string component)
|
||||||
{
|
{
|
||||||
Type type = Type.GetType("Barotrauma.Items.Components." + component);
|
Type type = Type.GetType("Barotrauma.Items.Components." + component);
|
||||||
|
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
MethodInfo method = typeof(Item).GetMethod(nameof(Item.GetComponent));
|
MethodInfo method = typeof(Item).GetMethod(nameof(Item.GetComponent));
|
||||||
MethodInfo generic = method.MakeGenericMethod(type);
|
MethodInfo generic = method.MakeGenericMethod(type);
|
||||||
return generic.Invoke(this, null);
|
return generic.Invoke(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial class ItemPrefab
|
partial class ItemPrefab
|
||||||
{
|
{
|
||||||
|
|
||||||
public static ItemPrefab GetItemPrefab(string itemNameOrId)
|
public static ItemPrefab GetItemPrefab(string itemNameOrId)
|
||||||
{
|
{
|
||||||
ItemPrefab itemPrefab =
|
ItemPrefab itemPrefab =
|
||||||
(MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ??
|
(MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ??
|
||||||
MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab;
|
MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab;
|
||||||
|
|
||||||
return itemPrefab;
|
return itemPrefab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract partial class MapEntity
|
abstract partial class MapEntity
|
||||||
{
|
{
|
||||||
public void AddLinked(MapEntity entity)
|
public void AddLinked(MapEntity entity)
|
||||||
{
|
{
|
||||||
linkedTo.Add(entity);
|
linkedTo.Add(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
using Barotrauma.Networking;
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
partial class CustomInterface
|
partial class CustomInterface
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
partial struct Signal
|
partial struct Signal
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,86 +10,86 @@ using MoonSharp.Interpreter;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LuaGame
|
partial class LuaGame
|
||||||
{
|
{
|
||||||
public bool IsSingleplayer => GameMain.IsSingleplayer;
|
public bool IsSingleplayer => GameMain.IsSingleplayer;
|
||||||
public bool IsMultiplayer => GameMain.IsMultiplayer;
|
public bool IsMultiplayer => GameMain.IsMultiplayer;
|
||||||
public string SaveFolder => SaveUtil.SaveFolder;
|
public string SaveFolder => SaveUtil.SaveFolder;
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
public GameClient 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
|
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GameMain.SoundManager;
|
return GameMain.Client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Lights.LightManager LightManager
|
public bool Paused => GameMain.Instance?.Paused == true;
|
||||||
{
|
public byte SessionId => GameMain.Client.SessionId;
|
||||||
get
|
public byte MyID => SessionId; // compatibility
|
||||||
{
|
|
||||||
return GameMain.LightManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubEditorScreen SubEditorScreen
|
public ChatMode ActiveChatMode => GameMain.ActiveChatMode;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GameMain.SubEditorScreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSubEditor
|
public ChatBox ChatBox
|
||||||
{
|
{
|
||||||
get
|
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
|
#else
|
||||||
public GameServer Server
|
public GameServer Server
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GameMain.Server;
|
return GameMain.Server;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDedicated
|
public bool IsDedicated
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GameMain.Server.ServerPeer is LidgrenServerPeer;
|
return GameMain.Server.ServerPeer is LidgrenServerPeer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public ServerSettings ServerSettings
|
public ServerSettings ServerSettings
|
||||||
@@ -121,296 +121,296 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public DynValue Settings;
|
public DynValue Settings;
|
||||||
|
|
||||||
public bool allowWifiChat = false;
|
public bool allowWifiChat = false;
|
||||||
public bool overrideTraitors = false;
|
public bool overrideTraitors = false;
|
||||||
public bool overrideRespawnSub = false;
|
public bool overrideRespawnSub = false;
|
||||||
public bool overrideSignalRadio = false;
|
public bool overrideSignalRadio = false;
|
||||||
public bool disableSpamFilter = false;
|
public bool disableSpamFilter = false;
|
||||||
public bool disableDisconnectCharacter = false;
|
public bool disableDisconnectCharacter = false;
|
||||||
public bool enableControlHusk = false;
|
public bool enableControlHusk = false;
|
||||||
|
|
||||||
public int mapEntityUpdateInterval
|
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()
|
|
||||||
{
|
{
|
||||||
LuaUserData.MakeFieldAccessible(UserData.RegisterType(typeof(GameSettings)), "currentConfig");
|
get { return MapEntity.MapEntityUpdateInterval; }
|
||||||
Settings = UserData.CreateStatic(typeof(GameSettings));
|
set { MapEntity.MapEntityUpdateInterval = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OverrideTraitors(bool o)
|
public int gapUpdateInterval
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
return ContentPackageManager.EnabledPackages.All.ToArray();
|
get { return MapEntity.GapUpdateInterval; }
|
||||||
|
set { MapEntity.GapUpdateInterval = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemPrefab GetItemPrefab(string itemNameOrId)
|
public int poweredUpdateInterval
|
||||||
{
|
{
|
||||||
ItemPrefab itemPrefab =
|
get { return MapEntity.PoweredUpdateInterval; }
|
||||||
(MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ??
|
set { MapEntity.PoweredUpdateInterval = value; }
|
||||||
MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab;
|
}
|
||||||
|
|
||||||
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 SERVER
|
||||||
if (GameMain.Server.RespawnManager == null)
|
return GameMain.Server?.GameStarted == true;
|
||||||
return null;
|
|
||||||
return GameMain.Server.RespawnManager.RespawnShuttle;
|
|
||||||
#else
|
#else
|
||||||
if (GameMain.Client.RespawnManager == null)
|
return GameMain.Client?.GameStarted == true;
|
||||||
return null;
|
|
||||||
return GameMain.Client.RespawnManager.RespawnShuttle;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Items.Components.Steering GetSubmarineSteering(Submarine sub)
|
public GameSession GameSession
|
||||||
{
|
{
|
||||||
foreach (Item item in Item.ItemList)
|
get
|
||||||
{
|
{
|
||||||
if (item.Submarine != sub) continue;
|
return GameMain.GameSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var steering = item.GetComponent<Items.Components.Steering>();
|
public NetLobbyScreen NetLobbyScreen
|
||||||
if (steering != null)
|
{
|
||||||
{
|
get
|
||||||
return steering;
|
{
|
||||||
}
|
return GameMain.NetLobbyScreen;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
public GameScreen GameScreen
|
||||||
}
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GameMain.GameScreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static WifiComponent GetWifiComponent(Item item)
|
public World World
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
get
|
||||||
return item.GetComponent<WifiComponent>();
|
{
|
||||||
}
|
return GameMain.World;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static LightComponent GetLightComponent(Item item)
|
#if SERVER
|
||||||
{
|
public ServerPeer Peer
|
||||||
if (item == null) return null;
|
{
|
||||||
return item.GetComponent<LightComponent>();
|
get
|
||||||
}
|
{
|
||||||
|
return GameMain.Server.ServerPeer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
public ClientPeer Peer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GameMain.Client.ClientPeer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static CustomInterface GetCustomInterface(Item item)
|
public LuaGame()
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
LuaUserData.MakeFieldAccessible(UserData.RegisterType(typeof(GameSettings)), "currentConfig");
|
||||||
return item.GetComponent<CustomInterface>();
|
Settings = UserData.CreateStatic(typeof(GameSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Fabricator GetFabricatorComponent(Item item)
|
public void OverrideTraitors(bool o)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
overrideTraitors = o;
|
||||||
return item.GetComponent<Fabricator>();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static Holdable GetHoldableComponent(Item item)
|
public void OverrideRespawnSub(bool o)
|
||||||
{
|
{
|
||||||
if (item == null) return null;
|
overrideRespawnSub = o;
|
||||||
return item.GetComponent<Holdable>();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void ExecuteCommand(string command)
|
public void AllowWifiChat(bool o)
|
||||||
{
|
{
|
||||||
DebugConsole.ExecuteCommand(command);
|
allowWifiChat = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Signal CreateSignal(string value, int stepsTaken = 1, Character sender = null, Item source = null, float power = 0, float strength = 1)
|
public void OverrideSignalRadio(bool o)
|
||||||
{
|
{
|
||||||
return new Signal(value, stepsTaken, sender, source, power, strength);
|
overrideSignalRadio = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DebugConsole.Command> luaAddedCommand = new List<DebugConsole.Command>();
|
public void DisableSpamFilter(bool o)
|
||||||
|
{
|
||||||
|
disableSpamFilter = o;
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveCommand(string name)
|
public void DisableDisconnectCharacter(bool o)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < DebugConsole.Commands.Count; i++)
|
disableDisconnectCharacter = o;
|
||||||
{
|
}
|
||||||
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)
|
|
||||||
{
|
public void EnableControlHusk(bool o)
|
||||||
var cmd = new DebugConsole.Command(name, help, (string[] arg1) => onExecute(new object[] { arg1 }),
|
{
|
||||||
() =>
|
enableControlHusk = o;
|
||||||
{
|
}
|
||||||
if (getValidArgs == null) return null;
|
|
||||||
|
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();
|
var validArgs = getValidArgs();
|
||||||
if (validArgs is DynValue luaValue)
|
if (validArgs is DynValue luaValue)
|
||||||
{
|
{
|
||||||
@@ -419,96 +419,96 @@ namespace Barotrauma
|
|||||||
return (string[][])validArgs;
|
return (string[][])validArgs;
|
||||||
}, isCheat);
|
}, isCheat);
|
||||||
|
|
||||||
luaAddedCommand.Add(cmd);
|
luaAddedCommand.Add(cmd);
|
||||||
DebugConsole.Commands.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadGame(string path)
|
public List<DebugConsole.Command> Commands => DebugConsole.Commands;
|
||||||
{
|
|
||||||
SaveUtil.LoadGame(path);
|
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
|
#if SERVER
|
||||||
public void LoadCampaign(string path)
|
public void LoadCampaign(string path)
|
||||||
{
|
{
|
||||||
MultiPlayerCampaign.LoadCampaign(path);
|
MultiPlayerCampaign.LoadCampaign(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null)
|
public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null)
|
||||||
{
|
{
|
||||||
GameMain.Server.SendChatMessage(msg, messageType, sender, character);
|
GameMain.Server.SendChatMessage(msg, messageType, sender, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null)
|
public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null)
|
||||||
{
|
{
|
||||||
GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character);
|
GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendTraitorMessage(Client client, string msg, Identifier missionid, TraitorMessageType type)
|
public static void SendTraitorMessage(Client client, string msg, Identifier missionid, TraitorMessageType type)
|
||||||
{
|
{
|
||||||
GameMain.Server.SendTraitorMessage(client, msg, missionid, 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);
|
ChatMessage cm = ChatMessage.Create(sendername, text, messageType, sender, client);
|
||||||
cm.IconStyle = iconStyle;
|
cm.IconStyle = iconStyle;
|
||||||
|
|
||||||
GameMain.Server.SendDirectChatMessage(cm, client);
|
GameMain.Server.SendDirectChatMessage(cm, client);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendDirectChatMessage(ChatMessage chatMessage, Client client)
|
public static void SendDirectChatMessage(ChatMessage chatMessage, Client client)
|
||||||
{
|
{
|
||||||
GameMain.Server.SendDirectChatMessage(chatMessage, client);
|
GameMain.Server.SendDirectChatMessage(chatMessage, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(string message, ServerLog.MessageType type)
|
public static void Log(string message, ServerLog.MessageType type)
|
||||||
{
|
{
|
||||||
GameServer.Log(message, type);
|
GameServer.Log(message, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DispatchRespawnSub()
|
public static void DispatchRespawnSub()
|
||||||
{
|
{
|
||||||
GameMain.Server.RespawnManager.DispatchShuttle();
|
GameMain.Server.RespawnManager.DispatchShuttle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void StartGame()
|
public static void StartGame()
|
||||||
{
|
{
|
||||||
GameMain.Server.StartGame();
|
GameMain.Server.StartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EndGame()
|
public static void EndGame()
|
||||||
{
|
{
|
||||||
GameMain.Server.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
|
#endif
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
mapEntityUpdateInterval = 1;
|
mapEntityUpdateInterval = 1;
|
||||||
gapUpdateInterval = 4;
|
gapUpdateInterval = 4;
|
||||||
characterUpdateInterval = 1;
|
characterUpdateInterval = 1;
|
||||||
|
|
||||||
foreach (var cmd in luaAddedCommand)
|
foreach (var cmd in luaAddedCommand)
|
||||||
{
|
{
|
||||||
DebugConsole.Commands.Remove(cmd);
|
DebugConsole.Commands.Remove(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,265 +7,265 @@ using MoonSharp.Interpreter.Interop;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LuaUserData
|
partial class LuaUserData
|
||||||
{
|
{
|
||||||
public static Type GetType(string typeName)
|
public static Type GetType(string typeName)
|
||||||
{
|
{
|
||||||
if (typeName == null || typeName.Length == 0) return null;
|
if (typeName == null || typeName.Length == 0) return null;
|
||||||
|
|
||||||
var byRef = false;
|
var byRef = false;
|
||||||
if (typeName.StartsWith("out ") || typeName.StartsWith("ref "))
|
if (typeName.StartsWith("out ") || typeName.StartsWith("ref "))
|
||||||
{
|
{
|
||||||
typeName = typeName.Remove(0, 4);
|
typeName = typeName.Remove(0, 4);
|
||||||
byRef = true;
|
byRef = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = Type.GetType(typeName);
|
var type = Type.GetType(typeName);
|
||||||
if (type != null) return byRef ? type.MakeByRefType() : type;
|
if (type != null) return byRef ? type.MakeByRefType() : type;
|
||||||
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
if (CsScriptBase.LoadedAssemblyName.Contains(a.GetName().Name))
|
if (CsScriptBase.LoadedAssemblyName.Contains(a.GetName().Name))
|
||||||
{
|
{
|
||||||
var attrs = a.GetCustomAttributes<AssemblyMetadataAttribute>();
|
var attrs = a.GetCustomAttributes<AssemblyMetadataAttribute>();
|
||||||
var revision = attrs.FirstOrDefault(attr => attr.Key == "Revision")?.Value;
|
var revision = attrs.FirstOrDefault(attr => attr.Key == "Revision")?.Value;
|
||||||
if (revision != null && int.Parse(revision) != (int)CsScriptBase.Revision[a.GetName().Name]) { continue; }
|
if (revision != null && int.Parse(revision) != (int)CsScriptBase.Revision[a.GetName().Name]) { continue; }
|
||||||
}
|
}
|
||||||
type = a.GetType(typeName);
|
type = a.GetType(typeName);
|
||||||
if (type != null)
|
if (type != null)
|
||||||
{
|
{
|
||||||
return byRef ? type.MakeByRefType() : type;
|
return byRef ? type.MakeByRefType() : type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUserDataDescriptor RegisterType(string typeName)
|
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)
|
|
||||||
{
|
{
|
||||||
Type type = GetType(typeName);
|
Type type = GetType(typeName);
|
||||||
|
|
||||||
if (type == null)
|
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))
|
|
||||||
{
|
{
|
||||||
string name = Enum.GetName(type, value);
|
throw new ScriptRuntimeException($"Tried to register a type that doesn't exist: {typeName}.");
|
||||||
|
|
||||||
result[name] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
public static void UnregisterGenericType(string typeName, params string[] typeNameArguements)
|
||||||
{
|
{
|
||||||
if (IUUD == null)
|
Type type = GetType(typeName);
|
||||||
{
|
Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray();
|
||||||
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {fieldName} accessible.");
|
Type genericType = type.MakeGenericType(typeArguements);
|
||||||
}
|
UserData.UnregisterType(genericType);
|
||||||
|
}
|
||||||
|
|
||||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
private static bool IsType<T>(object obj) { return obj is T; }
|
||||||
var field = IUUD.Type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
|
||||||
|
|
||||||
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)
|
MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]);
|
||||||
{
|
MethodInfo generic = method.MakeGenericMethod(type);
|
||||||
throw new ScriptRuntimeException($"Tried to make field '{fieldName}' accessible, but the field doesn't exist.");
|
return generic.Invoke(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.RemoveMember(fieldName);
|
public static object CreateEnumTable(string typeName)
|
||||||
descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default));
|
{
|
||||||
}
|
Type type = GetType(typeName);
|
||||||
|
|
||||||
private static MethodInfo FindMethodRecursively(Type type, string methodName)
|
if (type == null)
|
||||||
{
|
{
|
||||||
var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
throw new ScriptRuntimeException($"Tried to create an enum table with a type that doesn't exist:: {typeName}.");
|
||||||
|
}
|
||||||
|
|
||||||
if (method == null && type.BaseType != null)
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
{
|
|
||||||
return FindMethodRecursively(type.BaseType, methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return method;
|
foreach (var value in Enum.GetValues(type))
|
||||||
}
|
{
|
||||||
|
string name = Enum.GetName(type, value);
|
||||||
|
|
||||||
public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName)
|
result[name] = value;
|
||||||
{
|
}
|
||||||
if (IUUD == null)
|
|
||||||
{
|
|
||||||
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {methodName} accessible.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
return result;
|
||||||
var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
}
|
||||||
|
|
||||||
if (method == null)
|
private static FieldInfo FindFieldRecursively(Type type, string fieldName)
|
||||||
{
|
{
|
||||||
method = FindMethodRecursively(IUUD.Type, methodName);
|
var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||||
}
|
|
||||||
|
|
||||||
if (method == null)
|
if (field == null && type.BaseType != null)
|
||||||
{
|
{
|
||||||
throw new ScriptRuntimeException($"Tried to make method '{methodName}' accessible, but the method doesn't exist.");
|
return FindFieldRecursively(type.BaseType, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.RemoveMember(methodName);
|
return field;
|
||||||
descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function)
|
public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName)
|
||||||
{
|
{
|
||||||
if (IUUD == null)
|
if (IUUD == null)
|
||||||
{
|
{
|
||||||
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add method {methodName}.");
|
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);
|
if (field == null)
|
||||||
descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) =>
|
{
|
||||||
{
|
field = FindFieldRecursively(IUUD.Type, fieldName);
|
||||||
if (GameMain.LuaCs != null)
|
}
|
||||||
return GameMain.LuaCs.CallLuaFunction(function, arg3.GetArray());
|
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value)
|
if (field == null)
|
||||||
{
|
{
|
||||||
if (IUUD == null)
|
throw new ScriptRuntimeException($"Tried to make field '{fieldName}' accessible, but the field doesn't exist.");
|
||||||
{
|
}
|
||||||
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to add field {fieldName}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
descriptor.RemoveMember(fieldName);
|
||||||
descriptor.RemoveMember(fieldName);
|
descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default));
|
||||||
descriptor.AddMember(fieldName, new DynValueMemberDescriptor(fieldName, value));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveMember(IUserDataDescriptor IUUD, string memberName)
|
private static MethodInfo FindMethodRecursively(Type type, string methodName)
|
||||||
{
|
{
|
||||||
if (IUUD == null)
|
var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||||
{
|
|
||||||
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to remove the member {memberName}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
if (method == null && type.BaseType != null)
|
||||||
descriptor.RemoveMember(memberName);
|
{
|
||||||
}
|
return FindMethodRecursively(type.BaseType, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
return method;
|
||||||
/// 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>
|
public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName)
|
||||||
/// 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.
|
if (IUUD == null)
|
||||||
/// 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>
|
throw new ScriptRuntimeException($"Tried to use a UserDataDescriptor that is null to make {methodName} accessible.");
|
||||||
/// <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
|
var descriptor = (StandardUserDataDescriptor)IUUD;
|
||||||
/// it is better to manually wrap the List`1 object into a userdata.
|
var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||||
/// </example>
|
|
||||||
/// </summary>
|
if (method == null)
|
||||||
/// <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>
|
method = FindMethodRecursively(IUUD.Type, methodName);
|
||||||
/// <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)
|
|
||||||
{
|
if (method == null)
|
||||||
IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true);
|
{
|
||||||
descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default);
|
throw new ScriptRuntimeException($"Tried to make method '{methodName}' accessible, but the method doesn't exist.");
|
||||||
return CreateUserDataFromDescriptor(scriptObject, descriptor);
|
}
|
||||||
}
|
|
||||||
}
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,21 +8,21 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
class LuaScriptLoader : ScriptLoaderBase
|
class LuaScriptLoader : ScriptLoaderBase
|
||||||
{
|
{
|
||||||
|
|
||||||
public override object LoadFile(string file, Table globalContext)
|
public override object LoadFile(string file, Table globalContext)
|
||||||
{
|
{
|
||||||
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null;
|
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null;
|
||||||
|
|
||||||
return File.ReadAllText(file);
|
return File.ReadAllText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool ScriptFileExists(string file)
|
public override bool ScriptFileExists(string file)
|
||||||
{
|
{
|
||||||
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return false;
|
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return false;
|
||||||
|
|
||||||
return File.Exists(file);
|
return File.Exists(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,229 +8,229 @@ using LuaCsCompatPatchFunc = Barotrauma.LuaCsPatch;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
// XXX: this can't be renamed because of backward compatibility with C# mods
|
// XXX: this can't be renamed because of backward compatibility with C# mods
|
||||||
public delegate object LuaCsPatch(object self, Dictionary<string, object> args);
|
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)>> 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)>> compatHookPostfixMethods = new Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>>();
|
||||||
|
|
||||||
private static void _hookLuaCsPatch(MethodBase __originalMethod, object[] __args, object __instance, out object result, HookMethodType hookType)
|
private static void _hookLuaCsPatch(MethodBase __originalMethod, object[] __args, object __instance, out object result, HookMethodType hookType)
|
||||||
{
|
{
|
||||||
result = null;
|
result = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var funcAddr = ((long)__originalMethod.MethodHandle.GetFunctionPointer());
|
var funcAddr = ((long)__originalMethod.MethodHandle.GetFunctionPointer());
|
||||||
HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet = null;
|
HashSet<(string, LuaCsCompatPatchFunc, ACsMod)> methodSet = null;
|
||||||
switch (hookType)
|
switch (hookType)
|
||||||
{
|
{
|
||||||
case HookMethodType.Before:
|
case HookMethodType.Before:
|
||||||
instance.compatHookPrefixMethods.TryGetValue(funcAddr, out methodSet);
|
instance.compatHookPrefixMethods.TryGetValue(funcAddr, out methodSet);
|
||||||
break;
|
break;
|
||||||
case HookMethodType.After:
|
case HookMethodType.After:
|
||||||
instance.compatHookPostfixMethods.TryGetValue(funcAddr, out methodSet);
|
instance.compatHookPostfixMethods.TryGetValue(funcAddr, out methodSet);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException($"Invalid {nameof(HookMethodType)} enum value.", nameof(hookType));
|
throw new ArgumentException($"Invalid {nameof(HookMethodType)} enum value.", nameof(hookType));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodSet != null)
|
if (methodSet != null)
|
||||||
{
|
{
|
||||||
var @params = __originalMethod.GetParameters();
|
var @params = __originalMethod.GetParameters();
|
||||||
var args = new Dictionary<string, object>();
|
var args = new Dictionary<string, object>();
|
||||||
for (int i = 0; i < @params.Length; i++)
|
for (int i = 0; i < @params.Length; i++)
|
||||||
{
|
{
|
||||||
args.Add(@params[i].Name, __args[i]);
|
args.Add(@params[i].Name, __args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var outOfSocpe = new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>();
|
var outOfSocpe = new HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>();
|
||||||
foreach (var tuple in methodSet)
|
foreach (var tuple in methodSet)
|
||||||
{
|
{
|
||||||
if (tuple.Item3 != null && tuple.Item3.IsDisposed)
|
if (tuple.Item3 != null && tuple.Item3.IsDisposed)
|
||||||
{
|
{
|
||||||
outOfSocpe.Add(tuple);
|
outOfSocpe.Add(tuple);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var _result = tuple.Item2(__instance, args);
|
var _result = tuple.Item2(__instance, args);
|
||||||
if (_result != null)
|
if (_result != null)
|
||||||
{
|
{
|
||||||
if (_result is DynValue res)
|
if (_result is DynValue res)
|
||||||
{
|
{
|
||||||
if (!res.IsNil())
|
if (!res.IsNil())
|
||||||
{
|
{
|
||||||
if (__originalMethod is MethodInfo mi && mi.ReturnType != typeof(void))
|
if (__originalMethod is MethodInfo mi && mi.ReturnType != typeof(void))
|
||||||
{
|
{
|
||||||
result = res.ToObject(mi.ReturnType);
|
result = res.ToObject(mi.ReturnType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = res.ToObject();
|
result = res.ToObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = _result;
|
result = _result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var tuple in outOfSocpe) { methodSet.Remove(tuple); }
|
foreach (var tuple in outOfSocpe) { methodSet.Remove(tuple); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
GameMain.LuaCs.PrintError($"Error in {__originalMethod.Name}:", LuaCsMessageOrigin.Unknown);
|
GameMain.LuaCs.PrintError($"Error in {__originalMethod.Name}:", LuaCsMessageOrigin.Unknown);
|
||||||
GameMain.LuaCs.HandleException(ex, LuaCsMessageOrigin.Unknown);
|
GameMain.LuaCs.HandleException(ex, LuaCsMessageOrigin.Unknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static bool HookLuaCsPatchPrefix(MethodBase __originalMethod, object[] __args, object __instance)
|
private static bool HookLuaCsPatchPrefix(MethodBase __originalMethod, object[] __args, object __instance)
|
||||||
{
|
{
|
||||||
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before);
|
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before);
|
||||||
return result == null;
|
return result == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HookLuaCsPatchPostfix(MethodBase __originalMethod, object[] __args, object __instance) =>
|
private static void HookLuaCsPatchPostfix(MethodBase __originalMethod, object[] __args, object __instance) =>
|
||||||
_hookLuaCsPatch(__originalMethod, __args, __instance, out object _, HookMethodType.After);
|
_hookLuaCsPatch(__originalMethod, __args, __instance, out object _, HookMethodType.After);
|
||||||
|
|
||||||
private static bool HookLuaCsPatchRetPrefix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
private static bool HookLuaCsPatchRetPrefix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
||||||
{
|
{
|
||||||
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before);
|
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.Before);
|
||||||
if (result != null)
|
if (result != null)
|
||||||
{
|
{
|
||||||
__result = result;
|
__result = result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HookLuaCsPatchRetPostfix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
private static void HookLuaCsPatchRetPostfix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
||||||
{
|
{
|
||||||
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.After);
|
_hookLuaCsPatch(__originalMethod, __args, __instance, out object result, HookMethodType.After);
|
||||||
if (result != null) __result = result;
|
if (result != null) __result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodInfo _miHookLuaCsPatchPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPrefix", 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 _miHookLuaCsPatchPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
private static MethodInfo _miHookLuaCsPatchRetPrefix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPrefix", 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 _miHookLuaCsPatchRetPostfix = typeof(LuaCsHook).GetMethod("HookLuaCsPatchRetPostfix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
|
|
||||||
// TODO: deprecate this
|
// TODO: deprecate this
|
||||||
public void HookMethod(string identifier, MethodBase method, LuaCsCompatPatchFunc patch, HookMethodType hookType = HookMethodType.Before, ACsMod owner = null)
|
public void HookMethod(string identifier, MethodBase method, LuaCsCompatPatchFunc patch, HookMethodType hookType = HookMethodType.Before, ACsMod owner = null)
|
||||||
{
|
{
|
||||||
if (identifier == null || method == null || patch == 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))
|
|
||||||
{
|
{
|
||||||
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);
|
ValidatePatchTarget(method);
|
||||||
}
|
|
||||||
protected void HookMethod(string identifier, string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) =>
|
var funcAddr = ((long)method.MethodHandle.GetFunctionPointer());
|
||||||
HookMethod(identifier, className, methodName, null, patch, hookMethodType);
|
var patches = Harmony.GetPatchInfo(method);
|
||||||
protected void HookMethod(string className, string methodName, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) =>
|
|
||||||
HookMethod("", className, methodName, null, patch, hookMethodType);
|
if (hookType == HookMethodType.Before)
|
||||||
protected void HookMethod(string className, string methodName, string[] parameterNames, LuaCsCompatPatchFunc patch, HookMethodType hookMethodType = HookMethodType.Before) =>
|
{
|
||||||
HookMethod("", className, methodName, parameterNames, patch, hookMethodType);
|
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)
|
public void UnhookMethod(string identifier, MethodBase method, HookMethodType hookType = HookMethodType.Before)
|
||||||
{
|
{
|
||||||
var funcAddr = (long)method.MethodHandle.GetFunctionPointer();
|
var funcAddr = (long)method.MethodHandle.GetFunctionPointer();
|
||||||
|
|
||||||
Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> methods;
|
Dictionary<long, HashSet<(string, LuaCsCompatPatchFunc, ACsMod)>> methods;
|
||||||
if (hookType == HookMethodType.Before) methods = compatHookPrefixMethods;
|
if (hookType == HookMethodType.Before) methods = compatHookPrefixMethods;
|
||||||
else if (hookType == HookMethodType.After) methods = compatHookPostfixMethods;
|
else if (hookType == HookMethodType.After) methods = compatHookPostfixMethods;
|
||||||
else throw null;
|
else throw null;
|
||||||
|
|
||||||
if (methods.ContainsKey(funcAddr)) methods[funcAddr]?.RemoveWhere(t => t.Item1 == identifier);
|
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)
|
protected void UnhookMethod(string identifier, string className, string methodName, string[] parameterNames, HookMethodType hookType = HookMethodType.Before)
|
||||||
{
|
{
|
||||||
var method = ResolveMethod(className, methodName, parameterNames);
|
var method = ResolveMethod(className, methodName, parameterNames);
|
||||||
if (method == null) return;
|
if (method == null) return;
|
||||||
UnhookMethod(identifier, method, hookType);
|
UnhookMethod(identifier, method, hookType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,286 +11,286 @@ using MoonSharp.Interpreter;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LuaCsNetworking
|
partial class LuaCsNetworking
|
||||||
{
|
{
|
||||||
public class HttpListener
|
public class HttpListener
|
||||||
{
|
{
|
||||||
private System.Net.HttpListener listener;
|
private System.Net.HttpListener listener;
|
||||||
|
|
||||||
public HttpListener(System.Net.HttpListener list)
|
public HttpListener(System.Net.HttpListener list)
|
||||||
{
|
|
||||||
listener = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
listener.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IncomingHttpRequest
|
|
||||||
{
|
|
||||||
private HttpListenerRequest request;
|
|
||||||
|
|
||||||
public IncomingHttpRequest(HttpListenerRequest req)
|
|
||||||
{
|
{
|
||||||
request = req;
|
listener = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ContentType => request.ContentType;
|
public void Close()
|
||||||
public string LocalEndPoint => request.LocalEndPoint.ToString();
|
{
|
||||||
public string RemoteEndPoint => request.RemoteEndPoint.ToString();
|
listener.Close();
|
||||||
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 class IncomingHttpResponse
|
public class IncomingHttpRequest
|
||||||
{
|
{
|
||||||
private HttpListenerResponse response;
|
private HttpListenerRequest request;
|
||||||
|
|
||||||
public IncomingHttpResponse(HttpListenerResponse resp)
|
public IncomingHttpRequest(HttpListenerRequest req)
|
||||||
{
|
{
|
||||||
response = resp;
|
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; }
|
get { return response.ContentType; }
|
||||||
set { response.ContentType = value; }
|
set { response.ContentType = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(string text)
|
public void Write(string text)
|
||||||
{
|
{
|
||||||
byte[] data = Encoding.UTF8.GetBytes(text);
|
byte[] data = Encoding.UTF8.GetBytes(text);
|
||||||
response.ContentEncoding = Encoding.UTF8;
|
response.ContentEncoding = Encoding.UTF8;
|
||||||
response.ContentLength64 = data.LongLength;
|
response.ContentLength64 = data.LongLength;
|
||||||
|
|
||||||
response.OutputStream.Write(data, 0, data.Length);
|
response.OutputStream.Write(data, 0, data.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool RestrictMessageSize = true;
|
public bool RestrictMessageSize = true;
|
||||||
public Dictionary<string, LuaCsAction> LuaCsNetReceives = new Dictionary<string, LuaCsAction>();
|
public Dictionary<string, LuaCsAction> LuaCsNetReceives = new Dictionary<string, LuaCsAction>();
|
||||||
|
|
||||||
#if SERVER
|
#if SERVER
|
||||||
[MoonSharpHidden]
|
[MoonSharpHidden]
|
||||||
public void NetMessageReceived(IReadMessage netMessage, ClientPacketHeader header, Client client = null)
|
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")
|
|
||||||
{
|
{
|
||||||
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)
|
public void HttpGet(string url, LuaCsAction callback)
|
||||||
{
|
{
|
||||||
HttpRequest(url, callback, null, "GET");
|
HttpRequest(url, callback, null, "GET");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async void HandleIncomingConnections(System.Net.HttpListener listener, LuaCsAction onRequestReceived)
|
public static async void HandleIncomingConnections(System.Net.HttpListener listener, LuaCsAction onRequestReceived)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (listener.IsListening)
|
while (listener.IsListening)
|
||||||
{
|
{
|
||||||
HttpListenerContext ctx = await listener.GetContextAsync();
|
HttpListenerContext ctx = await listener.GetContextAsync();
|
||||||
|
|
||||||
IncomingHttpRequest req = new IncomingHttpRequest(ctx.Request);
|
IncomingHttpRequest req = new IncomingHttpRequest(ctx.Request);
|
||||||
IncomingHttpResponse resp = new IncomingHttpResponse(ctx.Response);
|
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)
|
public LuaCsNetworking.HttpListener StartHttpServer(string address, LuaCsAction onRequestReceived)
|
||||||
{
|
{
|
||||||
var listener = new System.Net.HttpListener();
|
var listener = new System.Net.HttpListener();
|
||||||
listener.Prefixes.Add(address);
|
listener.Prefixes.Add(address);
|
||||||
listener.Start();
|
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)
|
public void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember.CreateEntityEvent(entity, extraData);
|
GameMain.NetworkMember.CreateEntityEvent(entity, extraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SERVER
|
#if SERVER
|
||||||
public void UpdateClientPermissions(Client client)
|
public void UpdateClientPermissions(Client client)
|
||||||
{
|
{
|
||||||
GameMain.Server.UpdateClientPermissions(client);
|
GameMain.Server.UpdateClientPermissions(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovePendingClient(ServerPeer.PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket)
|
public void RemovePendingClient(ServerPeer.PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket)
|
||||||
{
|
{
|
||||||
GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, peerDisconnectPacket);
|
GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, peerDisconnectPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int FileSenderMaxPacketsPerUpdate
|
public int FileSenderMaxPacketsPerUpdate
|
||||||
{
|
{
|
||||||
get { return FileSender.FileTransferOut.MaxPacketsPerUpdate; }
|
get { return FileSender.FileTransferOut.MaxPacketsPerUpdate; }
|
||||||
set { FileSender.FileTransferOut.MaxPacketsPerUpdate = value; }
|
set { FileSender.FileTransferOut.MaxPacketsPerUpdate = value; }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public ushort LastClientListUpdateID
|
public ushort LastClientListUpdateID
|
||||||
{
|
{
|
||||||
get { return GameMain.NetworkMember.LastClientListUpdateID; }
|
get { return GameMain.NetworkMember.LastClientListUpdateID; }
|
||||||
set { GameMain.NetworkMember.LastClientListUpdateID = value; }
|
set { GameMain.NetworkMember.LastClientListUpdateID = value; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Steamworks;
|
using Steamworks;
|
||||||
using Steamworks.Data;
|
using Steamworks.Data;
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -10,8 +10,8 @@ using System;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LuaCsSteam
|
partial class LuaCsSteam
|
||||||
{
|
{
|
||||||
private struct WorkshopItemDownload
|
private struct WorkshopItemDownload
|
||||||
{
|
{
|
||||||
public ulong ID;
|
public ulong ID;
|
||||||
@@ -54,7 +54,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
itemsBeingDownloaded.Add(download);
|
itemsBeingDownloaded.Add(download);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void DownloadWorkshopItem(ulong id, string destination, LuaCsAction callback)
|
public void DownloadWorkshopItem(ulong id, string destination, LuaCsAction callback)
|
||||||
@@ -93,4 +93,4 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,47 +13,47 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class LuaCsFile
|
partial class LuaCsFile
|
||||||
{
|
{
|
||||||
public static bool CanReadFromPath(string path)
|
public static bool CanReadFromPath(string path)
|
||||||
{
|
{
|
||||||
string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath();
|
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 localModsDir = getFullPath(ContentPackage.LocalModsDir);
|
||||||
string workshopModsDir = getFullPath(ContentPackage.WorkshopModsDir);
|
string workshopModsDir = getFullPath(ContentPackage.WorkshopModsDir);
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
string tempDownloadDir = getFullPath(ModReceiver.DownloadFolder);
|
string tempDownloadDir = getFullPath(ModReceiver.DownloadFolder);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (pathStartsWith(localModsDir))
|
if (pathStartsWith(localModsDir))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (pathStartsWith(workshopModsDir))
|
if (pathStartsWith(workshopModsDir))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (pathStartsWith(tempDownloadDir))
|
if (pathStartsWith(tempDownloadDir))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pathStartsWith(getFullPath(".")))
|
if (pathStartsWith(getFullPath(".")))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CanWriteToPath(string path)
|
public static bool CanWriteToPath(string path)
|
||||||
{
|
{
|
||||||
string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath();
|
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)
|
foreach (var package in ContentPackageManager.AllPackages)
|
||||||
{
|
{
|
||||||
@@ -67,451 +67,451 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (pathStartsWith(getFullPath(ContentPackage.LocalModsDir)))
|
if (pathStartsWith(getFullPath(ContentPackage.LocalModsDir)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir)))
|
if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir)))
|
||||||
return true;
|
return true;
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder)))
|
if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder)))
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsPathAllowedException(string path, bool write = true, LuaCsMessageOrigin origin = LuaCsMessageOrigin.Unknown)
|
public static bool IsPathAllowedException(string path, bool write = true, LuaCsMessageOrigin origin = LuaCsMessageOrigin.Unknown)
|
||||||
{
|
{
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
if (CanWriteToPath(path))
|
if (CanWriteToPath(path))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("File access to \"" + path + "\" not allowed.");
|
throw new Exception("File access to \"" + path + "\" not allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (CanReadFromPath(path))
|
if (CanReadFromPath(path))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("File access to \"" + path + "\" not allowed.");
|
throw new Exception("File access to \"" + path + "\" not allowed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsPathAllowedLuaException(string path, bool write = true) =>
|
public static bool IsPathAllowedLuaException(string path, bool write = true) =>
|
||||||
IsPathAllowedException(path, write, LuaCsMessageOrigin.LuaMod);
|
IsPathAllowedException(path, write, LuaCsMessageOrigin.LuaMod);
|
||||||
public static bool IsPathAllowedCsException(string path, bool write = true) =>
|
public static bool IsPathAllowedCsException(string path, bool write = true) =>
|
||||||
IsPathAllowedException(path, write, LuaCsMessageOrigin.CSharpMod);
|
IsPathAllowedException(path, write, LuaCsMessageOrigin.CSharpMod);
|
||||||
|
|
||||||
public static string Read(string path)
|
public static string Read(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path, false))
|
if (!IsPathAllowedException(path, false))
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return File.ReadAllText(path);
|
return File.ReadAllText(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Write(string path, string text)
|
public static void Write(string path, string text)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
File.WriteAllText(path, text);
|
File.WriteAllText(path, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Delete(string path)
|
public static void Delete(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DeleteDirectory(string path)
|
public static void DeleteDirectory(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Directory.Delete(path, true);
|
Directory.Delete(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileStream OpenRead(string path)
|
public static FileStream OpenRead(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return File.Open(path, FileMode.Open, FileAccess.Read);
|
return File.Open(path, FileMode.Open, FileAccess.Read);
|
||||||
}
|
}
|
||||||
public static FileStream OpenWrite(string path)
|
public static FileStream OpenWrite(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (File.Exists(path)) return File.Open(path, FileMode.Truncate, FileAccess.Write);
|
if (File.Exists(path)) return File.Open(path, FileMode.Truncate, FileAccess.Write);
|
||||||
else return File.Open(path, FileMode.Create, FileAccess.Write);
|
else return File.Open(path, FileMode.Create, FileAccess.Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Exists(string path)
|
public static bool Exists(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path, false))
|
if (!IsPathAllowedException(path, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return File.Exists(path);
|
return File.Exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CreateDirectory(string path)
|
public static bool CreateDirectory(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path))
|
if (!IsPathAllowedException(path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool DirectoryExists(string path)
|
public static bool DirectoryExists(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path, false))
|
if (!IsPathAllowedException(path, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Directory.Exists(path);
|
return Directory.Exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetFiles(string path)
|
public static string[] GetFiles(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path, false))
|
if (!IsPathAllowedException(path, false))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return Directory.GetFiles(path);
|
return Directory.GetFiles(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] GetDirectories(string path)
|
public static string[] GetDirectories(string path)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(path, false))
|
if (!IsPathAllowedException(path, false))
|
||||||
return new string[] { };
|
return new string[] { };
|
||||||
|
|
||||||
return Directory.GetDirectories(path);
|
return Directory.GetDirectories(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] DirSearch(string sDir)
|
public static string[] DirSearch(string sDir)
|
||||||
{
|
{
|
||||||
if (!IsPathAllowedException(sDir, false))
|
if (!IsPathAllowedException(sDir, false))
|
||||||
return new string[] { };
|
return new string[] { };
|
||||||
|
|
||||||
List<string> files = new List<string>();
|
List<string> files = new List<string>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (string f in Directory.GetFiles(sDir))
|
foreach (string f in Directory.GetFiles(sDir))
|
||||||
{
|
{
|
||||||
files.Add(f);
|
files.Add(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string d in Directory.GetDirectories(sDir))
|
foreach (string d in Directory.GetDirectories(sDir))
|
||||||
{
|
{
|
||||||
foreach (string f in Directory.GetFiles(d))
|
foreach (string f in Directory.GetFiles(d))
|
||||||
{
|
{
|
||||||
files.Add(f);
|
files.Add(f);
|
||||||
}
|
}
|
||||||
DirSearch(d);
|
DirSearch(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (System.Exception excpt)
|
catch (System.Exception excpt)
|
||||||
{
|
{
|
||||||
Console.WriteLine(excpt.Message);
|
Console.WriteLine(excpt.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return files.ToArray();
|
return files.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LuaCsConfig
|
class LuaCsConfig
|
||||||
{
|
{
|
||||||
private enum ValueType
|
private enum ValueType
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Text,
|
Text,
|
||||||
Integer,
|
Integer,
|
||||||
Decimal,
|
Decimal,
|
||||||
Boolean,
|
Boolean,
|
||||||
Collection,
|
Collection,
|
||||||
Object,
|
Object,
|
||||||
Enum
|
Enum
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type[] LoadDocTypes(XElement typesElem)
|
private static Type[] LoadDocTypes(XElement typesElem)
|
||||||
{
|
{
|
||||||
var result = new List<Type>();
|
var result = new List<Type>();
|
||||||
foreach (var elem in typesElem.Elements())
|
foreach (var elem in typesElem.Elements())
|
||||||
{
|
{
|
||||||
var type = Type.GetType(elem.Value);
|
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 && GameMain.LuaCs?.CsScriptLoader?.Assembly != null) type = GameMain.LuaCs.CsScriptLoader.Assembly.GetType(elem.Value);
|
||||||
if (type == null) throw new Exception($"Type {elem.Value} not found.");
|
if (type == null) throw new Exception($"Type {elem.Value} not found.");
|
||||||
result.Add(type);
|
result.Add(type);
|
||||||
|
|
||||||
}
|
}
|
||||||
return result.ToArray();
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<XElement> SaveDocTypes(IEnumerable<Type> types)
|
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)
|
|
||||||
{
|
{
|
||||||
var idx = elem.GetAttributeInt("Type", -1);
|
return types.Select(t => new XElement("Type", t.ToString()));
|
||||||
if (idx < 0 || idx >= types.Length) throw new Exception($"Type index '{idx}' is outside of saved types bounds");
|
}
|
||||||
return types[idx];
|
|
||||||
}
|
private static Type GetTypeAttr(Type[] types, XElement elem)
|
||||||
private static ValueType GetValueType(XElement elem)
|
|
||||||
{
|
{
|
||||||
Enum.TryParse(typeof(ValueType), elem.Attribute("Value")?.Value, out object result);
|
var idx = elem.GetAttributeInt("Type", -1);
|
||||||
if (result != null) return (ValueType)result;
|
if (idx < 0 || idx >= types.Length) throw new Exception($"Type index '{idx}' is outside of saved types bounds");
|
||||||
else return ValueType.None;
|
return types[idx];
|
||||||
}
|
}
|
||||||
private static object ParseValue(Type[] types, XElement elem)
|
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 (elem.IsEmpty) return null;
|
||||||
if (type == ValueType.Enum)
|
if (type == ValueType.Enum)
|
||||||
{
|
{
|
||||||
var tType = GetTypeAttr(types, elem);
|
var tType = GetTypeAttr(types, elem);
|
||||||
if (tType == null || !tType.IsSubclassOf(typeof(Enum))) return null;
|
if (tType == null || !tType.IsSubclassOf(typeof(Enum))) return null;
|
||||||
if (Enum.TryParse(tType, elem.Value, out object result)) return result;
|
if (Enum.TryParse(tType, elem.Value, out object result)) return result;
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
if (type == ValueType.Collection)
|
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)
|
|
||||||
{
|
{
|
||||||
float.TryParse(elem.Value, out var num);
|
var tType = GetTypeAttr(types, elem);
|
||||||
return num;
|
var tInt = tType.GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
||||||
}
|
var gArg = tInt.GetGenericArguments()[0];
|
||||||
else if (type == ValueType.Boolean)
|
if (tType == null || !tType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) return null;
|
||||||
{
|
|
||||||
bool.TryParse(elem.Value, out var boolean);
|
|
||||||
return boolean;
|
|
||||||
}
|
|
||||||
else if (type == ValueType.Object)
|
|
||||||
{
|
|
||||||
var tType = GetTypeAttr(types, elem);
|
|
||||||
if (tType == null) return null;
|
|
||||||
|
|
||||||
IEnumerable<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
|
object result = null;
|
||||||
.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;
|
if (result == null) {
|
||||||
var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0);
|
var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c =>
|
||||||
if (ctor == null)
|
{
|
||||||
{
|
var param = c.GetParameters();
|
||||||
if (!tType.IsValueType) return null;
|
return param.Count() == 1 && param.Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
||||||
result = Activator.CreateInstance(tType);
|
});
|
||||||
}
|
if (ctor != null)
|
||||||
else result = ctor.Invoke(null);
|
{
|
||||||
|
var elements = elem.Elements().Select(x => ParseValue(types, x));
|
||||||
foreach(var el in elem.Elements())
|
var castElems = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(gArg).Invoke(elements, new object[] { elements });
|
||||||
{
|
result = ctor.Invoke(new object[] { castElems });
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
if (result == null)
|
||||||
|
|
||||||
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);
|
var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => c.GetParameters().Count() == 0);
|
||||||
AddTypeAttr(types, tType, result);
|
var addMethod = tType.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(m =>
|
||||||
|
{
|
||||||
result.Value = Enum.GetName(tType, value) ?? "";
|
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);
|
if (result == 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);
|
var ctor = tType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault();
|
||||||
AddTypeAttr(types, tType, result);
|
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)
|
return result;
|
||||||
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
|
}
|
||||||
IEnumerable<PropertyInfo> properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null)
|
else if (type == ValueType.Text) return elem.Value;
|
||||||
.Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null));
|
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)));
|
IEnumerable<FieldInfo> fields = tType.GetFields(BindingFlags.Instance | BindingFlags.Public)
|
||||||
foreach (var property in properties) result.Add(ParseObject(types, property.Name, property.GetValue(value)));
|
.Concat(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic));
|
||||||
}
|
IEnumerable<PropertyInfo> properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetSetMethod() != null)
|
||||||
else
|
.Concat(tType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic).Where(p => p.GetSetMethod() != null));
|
||||||
{
|
|
||||||
result.SetAttributeValue("Value", ValueType.None);
|
|
||||||
result.Value = value.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user