new hook call method + function to delegate conversion

This commit is contained in:
Oiltanker
2022-04-15 17:15:45 +03:00
parent 891efb4c4f
commit 3eba20ecb7
39 changed files with 470 additions and 676 deletions
@@ -1,482 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using MoonSharp.Interpreter;
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Barotrauma.Items.Components;
using System.IO;
using System.Net;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics.Dynamics;
using System.Reflection;
using HarmonyLib;
using MoonSharp.Interpreter.Interop;
using System.Diagnostics;
namespace Barotrauma
{
public partial class LuaTimer
{
public static long LastUpdateTime = 0;
public static double Time
{
get
{
return GetTime();
}
}
public void Wait(object function, int millisecondDelay)
{
GameMain.LuaCs.HookBase.EnqueueTimedLuaFunction((float)Timing.TotalTime + (millisecondDelay / 1000f), function);
}
public static double GetTime()
{
return Timing.TotalTime;
}
public static float GetUsageMemory()
{
Process proc = Process.GetCurrentProcess();
float memory = MathF.Round(proc.PrivateMemorySize64 / (1024 * 1024), 2);
proc.Dispose();
return memory;
}
}
partial class LuaFile
{
public static bool CanReadFromPath(string path)
{
string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath();
path = getFullPath(path);
bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
string localModsDir = getFullPath(ContentPackage.LocalModsDir);
string workshopModsDir = getFullPath(ContentPackage.WorkshopModsDir);
#if CLIENT
string tempDownloadDir = getFullPath(ModReceiver.DownloadFolder);
#endif
if (pathStartsWith(localModsDir))
return true;
if (pathStartsWith(workshopModsDir))
return true;
#if CLIENT
if (pathStartsWith(tempDownloadDir))
return true;
#endif
if (pathStartsWith(getFullPath(".")))
return true;
return false;
}
public static bool CanWriteToPath(string path)
{
string getFullPath(string p) => System.IO.Path.GetFullPath(p).CleanUpPath();
path = getFullPath(path);
bool pathStartsWith(string prefix) => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
if (pathStartsWith(getFullPath(ContentPackage.LocalModsDir + "LuaForBarotraumaUnstable")))
return false;
if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir + "LuaForBarotraumaUnstable")))
return false;
#if CLIENT
if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder + "LuaForBarotraumaUnstable")))
return false;
#endif
if (pathStartsWith(getFullPath(ContentPackage.LocalModsDir)))
return true;
if (pathStartsWith(getFullPath(ContentPackage.WorkshopModsDir)))
return true;
#if CLIENT
if (pathStartsWith(getFullPath(ModReceiver.DownloadFolder)))
return true;
#endif
return false;
}
public static bool IsPathAllowedLuaException(string path, bool write = true)
{
if (write)
{
if (CanWriteToPath(path))
return true;
else
GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed."));
}
else
{
if (CanReadFromPath(path))
return true;
else
GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed."));
}
return false;
}
public static string Read(string path)
{
if (!IsPathAllowedLuaException(path, false))
return "";
return File.ReadAllText(path);
}
public static void Write(string path, string text)
{
if (!IsPathAllowedLuaException(path))
return;
File.WriteAllText(path, text);
}
public static bool Exists(string path)
{
if (!IsPathAllowedLuaException(path, false))
return false;
return File.Exists(path);
}
public static bool CreateDirectory(string path)
{
if (!IsPathAllowedLuaException(path))
return false;
Directory.CreateDirectory(path);
return true;
}
public static bool DirectoryExists(string path)
{
if (!IsPathAllowedLuaException(path, false))
return false;
return Directory.Exists(path);
}
public static string[] GetFiles(string path)
{
if (!IsPathAllowedLuaException(path, false))
return null;
return Directory.GetFiles(path);
}
public static string[] GetDirectories(string path)
{
if (!IsPathAllowedLuaException(path, false))
return new string[] { };
return Directory.GetDirectories(path);
}
public static string[] DirSearch(string sDir)
{
if (!IsPathAllowedLuaException(sDir, false))
return new string[] { };
List<string> files = new List<string>();
try
{
foreach (string f in Directory.GetFiles(sDir))
{
files.Add(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
files.Add(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
return files.ToArray();
}
}
partial class LuaNetworking
{
public bool restrictMessageSize = true;
public Dictionary<string, object> LuaNetReceives = new Dictionary<string, object>();
#if SERVER
[MoonSharpHidden]
public void NetMessageReceived(IReadMessage netMessage, ClientPacketHeader header, Client client = null)
{
if (header == ClientPacketHeader.LUA_NET_MESSAGE)
{
string netMessageName = netMessage.ReadString();
if (LuaNetReceives[netMessageName] is Closure)
GameMain.LuaCs.CallLuaFunction(LuaNetReceives[netMessageName], new object[] { netMessage, client });
}
else
{
GameMain.LuaCs.HookBase.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 (LuaNetReceives[netMessageName] is Closure)
GameMain.LuaCs.lua.Call(LuaNetReceives[netMessageName], new object[] { netMessage, client });
}
else
{
GameMain.LuaCs.HookBase.Call("netMessageReceived", netMessage, header, client);
}
}
#endif
public void Receive(string netMessageName, object callback)
{
LuaNetReceives[netMessageName] = callback;
}
public IWriteMessage Start(string netMessageName)
{
var message = new WriteOnlyMessage();
#if SERVER
message.Write((byte)ServerPacketHeader.LUA_NET_MESSAGE);
#else
message.Write((byte)ClientPacketHeader.LUA_NET_MESSAGE);
#endif
message.Write(netMessageName);
return ((IWriteMessage)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 RequestPostHTTP(string url, object callback, string data, string contentType = "application/json")
{
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = contentType;
httpWebRequest.Method = "POST";
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()))
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, streamReader.ReadToEnd());
}
catch (Exception e)
{
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, e.ToString());
}
}), null);
}
catch (Exception e)
{
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, e.ToString());
}
}
public void RequestGetHTTP(string url, object callback)
{
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult result) =>
{
try
{
var httpResponse = httpWebRequest.EndGetResponse(result);
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, streamReader.ReadToEnd());
}
catch (Exception e)
{
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, e.ToString());
}
}), null);
}
catch (Exception e)
{
GameMain.LuaCs.HookBase.EnqueueLuaFunction(callback, e.ToString());
}
}
public void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData)
{
GameMain.NetworkMember.CreateEntityEvent(entity, extraData);
}
#if SERVER
public void UpdateClientPermissions(Client client)
{
GameMain.Server.UpdateClientPermissions(client);
}
public void RemovePendingClient(ServerPeer.PendingClient pendingClient, DisconnectReason reason, string msg)
{
GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, reason, msg);
}
#endif
public ushort LastClientListUpdateID
{
get { return GameMain.NetworkMember.LastClientListUpdateID; }
set { GameMain.NetworkMember.LastClientListUpdateID = value; }
}
}
}
public class LuaResult
{
object result;
public LuaResult(object arg)
{
result = arg;
}
public bool IsNull()
{
if (result == null)
return true;
if (result is DynValue dynValue)
return dynValue.IsNil();
return false;
}
public bool Bool()
{
if (result is DynValue dynValue)
{
return dynValue.CastToBool();
}
return false;
}
public float Float()
{
if (result is DynValue dynValue)
{
var num = dynValue.CastToNumber();
if (num == null) { return 0f; }
return (float)num.Value;
}
return 0f;
}
public double Double()
{
if (result is DynValue dynValue)
{
var num = dynValue.CastToNumber();
if (num == null) { return 0f; }
return num.Value;
}
return 0f;
}
public string String()
{
if (result is DynValue dynValue)
{
var str = dynValue.CastToString();
if (str == null) { return ""; }
return str;
}
return "";
}
public object Object()
{
if (result is DynValue dynValue)
{
return dynValue.ToObject();
}
return null;
}
public DynValue DynValue()
{
if (result is DynValue dynValue)
{
return dynValue;
}
return null;
}
}
@@ -324,14 +324,14 @@ namespace Barotrauma
}
}
public void AddCommand(string name, string help, object onExecute, object getValidArgs = null, bool isCheat = false)
public void AddCommand(string name, string help, CsAction onExecute, CsFunc getValidArgs = null, bool isCheat = false)
{
var cmd = new DebugConsole.Command(name, help, (string[] arg1) => { GameMain.LuaCs.CallLuaFunction(onExecute, new object[] { arg1 }); },
var cmd = new DebugConsole.Command(name, help, (string[] arg1) => { onExecute(arg1); },
() =>
{
if (getValidArgs == null) return null;
var result = new LuaResult(GameMain.LuaCs.CallLuaFunction(getValidArgs, new object[] { }));
var obj = result.Object();
var obj = getValidArgs();
if (obj is LuaResult res) obj = res.Object();
if (obj is string[][]) return (string[][])obj;
return null;
}, isCheat);
@@ -1,44 +0,0 @@
using System;
namespace Barotrauma
{
partial class LuaCsSetup
{
// CSharp wrapper for LuaCsHook
public class LuaHook : LuaCsHookWrapper
{
public LuaHook(LuaCsHook hook) : base(hook) { }
public class HookMethodTypeProxy
{
public HookMethodTypeProxy() { }
public const HookMethodType Before = Barotrauma.HookMethodType.Before;
public const HookMethodType After = Barotrauma.HookMethodType.After;
}
public static readonly HookMethodTypeProxy HookMethodType = new HookMethodTypeProxy();
public void HookMethod(string identifier, string className, string methodName, string[] parameterNames, object hookMethod, HookMethodType hookMethodType = Barotrauma.HookMethodType.Before) =>
_hook.HookLuaMethod(identifier, className, methodName, parameterNames, hookMethod, hookMethodType);
public void HookMethod(string identifier, string className, string methodName, object hookMethod, HookMethodType hookMethodType = Barotrauma.HookMethodType.Before) =>
_hook.HookLuaMethod(identifier, className, methodName, null, hookMethod, hookMethodType);
public void HookMethod(string className, string methodName, object hookMethod, HookMethodType hookMethodType = Barotrauma.HookMethodType.Before) =>
_hook.HookLuaMethod("", className, methodName, null, hookMethod, hookMethodType);
public void HookMethod(string className, string methodName, string[] parameterNames, object hookMethod, HookMethodType hookMethodType = Barotrauma.HookMethodType.Before) =>
_hook.HookLuaMethod("", className, methodName, parameterNames, hookMethod, hookMethodType);
public void Add(string name, string hookName, object function) =>
_hook.AddLuaHook(name, hookName, function);
public void EnqueueFunction(object function, params object[] args) =>
_hook.EnqueueLuaFunction(function, args);
public void EnqueueTimedFunction(float time, object function, params object[] args) =>
_hook.EnqueueTimedLuaFunction(time, function, args);
}
}
}
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Text;
using MoonSharp.Interpreter;
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Barotrauma.Items.Components;
using System.IO;
using System.Net;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics.Dynamics;
using System.Reflection;
using HarmonyLib;
using MoonSharp.Interpreter.Interop;
using System.Diagnostics;
namespace Barotrauma
{
public class LuaResult
{
object result;
public LuaResult(object arg)
{
result = arg;
}
public bool IsNull()
{
if (result == null)
return true;
if (result is DynValue dynValue)
return dynValue.IsNil();
return false;
}
public bool Bool()
{
if (result is DynValue dynValue)
{
return dynValue.CastToBool();
}
return false;
}
public float Float()
{
if (result is DynValue dynValue)
{
var num = dynValue.CastToNumber();
if (num == null) { return 0f; }
return (float)num.Value;
}
return 0f;
}
public double Double()
{
if (result is DynValue dynValue)
{
var num = dynValue.CastToNumber();
if (num == null) { return 0f; }
return num.Value;
}
return 0f;
}
public string String()
{
if (result is DynValue dynValue)
{
var str = dynValue.CastToString();
if (str == null) { return ""; }
return str;
}
return "";
}
public object Object()
{
if (result is DynValue dynValue)
{
return dynValue.ToObject();
}
return null;
}
public DynValue DynValue()
{
if (result is DynValue dynValue)
{
return dynValue;
}
return null;
}
public static implicit operator bool(LuaResult res) => res.Bool();
public static implicit operator float(LuaResult res) => res.Float();
public static implicit operator string(LuaResult res) => res.String();
public static implicit operator double(LuaResult res) => res.Double();
public static implicit operator DynValue(LuaResult res) => res.DynValue();
}
}
@@ -23,6 +23,10 @@ namespace Barotrauma
var function = v.Function;
return (Func<Fixture, Vector2, Vector2, float, float>)((Fixture a, Vector2 b, Vector2 c, float d) => new LuaResult(function.Call(a, b, c, d)).Float());
});
Script.GlobalOptions.CustomConverters.SetScriptToClrCustomConversion(DataType.Function, typeof(Closure), v => v.Function);
Script.GlobalOptions.CustomConverters.SetScriptToClrCustomConversion(DataType.Function, typeof(CsAction), v => (CsAction)( args => GameMain.LuaCs.CallLuaFunction(v.Function, args) ));
Script.GlobalOptions.CustomConverters.SetScriptToClrCustomConversion(DataType.Function, typeof(CsFunc), v => (CsFunc)( args => new LuaResult(GameMain.LuaCs.CallLuaFunction(v.Function, args)).Object() ));
Script.GlobalOptions.CustomConverters.SetScriptToClrCustomConversion(DataType.Function, typeof(CsPatch), v => (CsPatch)( (self, args) => new LuaResult(GameMain.LuaCs.CallLuaFunction(v.Function, self, args)).Object() ));
#if CLIENT
RegisterAction<float>();
@@ -13,14 +13,14 @@ namespace Barotrauma
public override object LoadFile(string file, Table globalContext)
{
if (!LuaFile.IsPathAllowedLuaException(file, false)) return null;
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null;
return File.ReadAllText(file);
}
public override bool ScriptFileExists(string file)
{
if (!LuaFile.IsPathAllowedLuaException(file, false)) return false;
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return false;
return File.Exists(file);
}