From a8a0c96d571cd7dd7630eb8ed5157b2abf140c5a Mon Sep 17 00:00:00 2001 From: Evil Factory <36804725+evilfactory@users.noreply.github.com> Date: Thu, 4 Nov 2021 11:30:36 -0300 Subject: [PATCH] move most of the registration code to Lua, include harmony, add useful perf methods to Time and a more useful(but still useless) error handling in the hook call --- .../BarotraumaClient/LinuxClient.csproj | 1 + Barotrauma/BarotraumaClient/MacClient.csproj | 1 + .../BarotraumaClient/WindowsClient.csproj | 1 + .../BarotraumaServer/LinuxServer.csproj | 1 + Barotrauma/BarotraumaServer/MacServer.csproj | 1 + .../BarotraumaServer/ServerSource/GameMain.cs | 7 +- .../BarotraumaServer/WindowsServer.csproj | 1 + .../BarotraumaShared/Lua/.vscode/launch.json | 11 + .../Lua/.vscode/settings.json | 39 +++ .../BarotraumaShared/Lua/DefaultLib.lua | 56 ++++ .../BarotraumaShared/Lua/DefaultRegister.lua | 157 +++++++++++ .../Lua/{MoonsharpSetup.lua => LuaSetup.lua} | 12 +- Barotrauma/BarotraumaShared/Lua/NluaSetup.lua | 0 .../SharedSource/Lua/LuaClasses.cs | 168 +++++++++++- .../SharedSource/Lua/LuaSetup.cs | 254 +++--------------- 15 files changed, 481 insertions(+), 229 deletions(-) create mode 100644 Barotrauma/BarotraumaShared/Lua/.vscode/launch.json create mode 100644 Barotrauma/BarotraumaShared/Lua/.vscode/settings.json create mode 100644 Barotrauma/BarotraumaShared/Lua/DefaultLib.lua create mode 100644 Barotrauma/BarotraumaShared/Lua/DefaultRegister.lua rename Barotrauma/BarotraumaShared/Lua/{MoonsharpSetup.lua => LuaSetup.lua} (89%) delete mode 100644 Barotrauma/BarotraumaShared/Lua/NluaSetup.lua diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index d7446d96c..6c3780e94 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -121,6 +121,7 @@ + diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 9e8888dc5..6640759d6 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -122,6 +122,7 @@ + diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index f768ce3e1..0a16bfdca 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -125,6 +125,7 @@ + diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 7c5ab18b1..c25ba6e32 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -74,6 +74,7 @@ + diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 246a1e1b6..248219178 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -89,6 +89,7 @@ + diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs index d8ca89639..d4ce0ca29 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/GameMain.cs @@ -364,7 +364,7 @@ namespace Barotrauma { DebugConsole.NewMessage("WARNING: Stopwatch frequency under 1500 ticks per second. Expect significant syncing accuracy issues.", Color.Yellow); } - + Stopwatch performanceMeasurement = new Stopwatch(); stopwatch = Stopwatch.StartNew(); long prevTicks = stopwatch.ElapsedTicks; while (ShouldRun) @@ -380,6 +380,8 @@ namespace Barotrauma prevTicks = currTicks; while (Timing.Accumulator >= Timing.Step) { + performanceMeasurement.Start(); + Timing.TotalTime += Timing.Step; DebugConsole.Update(); if (GameSession?.GameMode == null || !GameSession.GameMode.Paused) @@ -393,6 +395,9 @@ namespace Barotrauma CoroutineManager.Update((float)Timing.Step, (float)Timing.Step); GameMain.Lua.hook.Call("think", new object[] { }); + performanceMeasurement.Stop(); + LuaSetup.LuaTimer.LastUpdateTime = performanceMeasurement.ElapsedMilliseconds; + performanceMeasurement.Reset(); Timing.Accumulator -= Timing.Step; } diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 5793a4254..5a0f09221 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -83,6 +83,7 @@ + diff --git a/Barotrauma/BarotraumaShared/Lua/.vscode/launch.json b/Barotrauma/BarotraumaShared/Lua/.vscode/launch.json new file mode 100644 index 000000000..bd4a5a056 --- /dev/null +++ b/Barotrauma/BarotraumaShared/Lua/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "MoonSharp Attach", + "type": "moonsharp-debug", + "debugServer": 41912, + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Lua/.vscode/settings.json b/Barotrauma/BarotraumaShared/Lua/.vscode/settings.json new file mode 100644 index 000000000..6bff2e0b1 --- /dev/null +++ b/Barotrauma/BarotraumaShared/Lua/.vscode/settings.json @@ -0,0 +1,39 @@ +{ + "Lua.diagnostics.globals": [ + "Game", + "Player", + "Random", + "Hook", + "Timer", + "bit32", + "TotalTime", + "DoFile", + "WayPoint", + "SpawnType", + "Level", + "Submarine", + "Vector2", + "PositionType", + "ServerLog_MessageType", + "Character", + "TraitorMessageType", + "ChatMessageType", + "CauseOfDeathType", + "CreateVector2", + "Item", + "ChatMessage", + "AfflictionPrefab", + "Gap", + "File", + "Networking", + "printNoLog", + "Client", + "SERVER", + "setmodulepaths", + "Type", + "BindingFlags", + "UserData", + "LuaUserData", + "CLIENT" + ] +} \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Lua/DefaultLib.lua b/Barotrauma/BarotraumaShared/Lua/DefaultLib.lua new file mode 100644 index 000000000..acd20433e --- /dev/null +++ b/Barotrauma/BarotraumaShared/Lua/DefaultLib.lua @@ -0,0 +1,56 @@ +local defaultLib = {} + +require("DefaultRegister") + +local CreateStatic = function (typeName) + return LuaUserData.CreateStatic("Barotrauma." .. typeName) +end + +defaultLib["WayPoint"] = CreateStatic("WayPoint") +defaultLib["SpawnType"] = CreateStatic("SpawnType") +defaultLib["ChatMessageType"] = CreateStatic("Networking.ChatMessageType") +defaultLib["ServerLog_MessageType"] = CreateStatic("Networking.ServerLog+MessageType") +defaultLib["ServerLogMessageType"] = CreateStatic("Networking.ServerLog+MessageType") +defaultLib["Submarine"] = CreateStatic("Submarine") +defaultLib["Client"] = CreateStatic("Networking.Client") +defaultLib["Character"] = CreateStatic("Character") +defaultLib["CharacterInfo"] = CreateStatic("CharacterInfo") +defaultLib["Item"] = CreateStatic("Item") +defaultLib["ItemPrefab"] = CreateStatic("ItemPrefab") +defaultLib["Level"] = CreateStatic("Level") +defaultLib["PositionType"] = CreateStatic("Level+PositionType") +defaultLib["JobPrefab"] = CreateStatic("JobPrefab") +defaultLib["TraitorMessageType"] = CreateStatic("Networking.TraitorMessageType") +defaultLib["CauseOfDeathType"] = CreateStatic("CauseOfDeathType") +defaultLib["AfflictionPrefab"] = CreateStatic("AfflictionPrefab") +defaultLib["CharacterTeamType"] = CreateStatic("CharacterTeamType") +defaultLib["Vector2"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector2") +defaultLib["Vector3"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector3") +defaultLib["Vector4"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector4") +defaultLib["Color"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Color") +defaultLib["Point"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Point") +defaultLib["ChatMessage"] = CreateStatic("Networking.ChatMessage") +defaultLib["Hull"] = CreateStatic("Hull") +defaultLib["InvSlotType"] = CreateStatic("InvSlotType") +defaultLib["Gap"] = CreateStatic("Gap") +defaultLib["ContentPackage"] = CreateStatic("ContentPackage") +defaultLib["ClientPermissions"] = CreateStatic("Networking.ClientPermissions") +defaultLib["Signal"] = CreateStatic("Items.Components.Signal") +defaultLib["DeliveryMethod"] = CreateStatic("Networking.DeliveryMethod") +defaultLib["ClientPacketHeader"] = CreateStatic("Networking.ClientPacketHeader") +defaultLib["ServerPacketHeader"] = CreateStatic("Networking.ServerPacketHeader") +defaultLib["RandSync"] = CreateStatic("Rand+RandSync") +defaultLib["SubmarineInfo"] = CreateStatic("SubmarineInfo") +defaultLib["Rectangle"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Rectangle") +defaultLib["Entity"] = CreateStatic("Entity") +defaultLib["Physics"] = CreateStatic("Physics") + +if SERVER then + +elseif CLIENT then + defaultLib["Sprite"] = CreateStatic("Sprite") + defaultLib["Keys"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Input.Keys") + defaultLib["PlayerInput"] = CreateStatic("PlayerInput") +end + +return defaultLib \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Lua/DefaultRegister.lua b/Barotrauma/BarotraumaShared/Lua/DefaultRegister.lua new file mode 100644 index 000000000..887a1ba01 --- /dev/null +++ b/Barotrauma/BarotraumaShared/Lua/DefaultRegister.lua @@ -0,0 +1,157 @@ +local function RegisterBarotrauma(typeName) + return LuaUserData.RegisterType("Barotrauma." .. typeName) +end + +local AddCallMetaMember = LuaUserData.AddCallMetaMember + +RegisterBarotrauma("CauseOfDeathType") +RegisterBarotrauma("Level+InterestingPosition") +RegisterBarotrauma("Level+PositionType") +RegisterBarotrauma("Networking.TraitorMessageType") +RegisterBarotrauma("SpawnType") +RegisterBarotrauma("Networking.ChatMessageType") +RegisterBarotrauma("InputType") + +RegisterBarotrauma("Job") +RegisterBarotrauma("JobPrefab") +RegisterBarotrauma("Level") +RegisterBarotrauma("Items.Components.Steering") +RegisterBarotrauma("Networking.ServerLog+MessageType") +RegisterBarotrauma("WayPoint") +RegisterBarotrauma("Character") +RegisterBarotrauma("Item") +RegisterBarotrauma("Submarine") +RegisterBarotrauma("Networking.Client") +RegisterBarotrauma("AfflictionPrefab") +RegisterBarotrauma("Affliction") +RegisterBarotrauma("CharacterHealth") +RegisterBarotrauma("AnimController") +RegisterBarotrauma("Limb") +RegisterBarotrauma("Ragdoll") +RegisterBarotrauma("Networking.ChatMessage") +RegisterBarotrauma("CharacterHealth+LimbHealth") +RegisterBarotrauma("AttackResult") +RegisterBarotrauma("Entity") +RegisterBarotrauma("EntitySpawner") +RegisterBarotrauma("MapEntity") +RegisterBarotrauma("MapEntityPrefab") +RegisterBarotrauma("CauseOfDeath") +RegisterBarotrauma("CharacterTeamType") +RegisterBarotrauma("Items.Components.Connection") +RegisterBarotrauma("CharacterInventory") +RegisterBarotrauma("Hull") +RegisterBarotrauma("Gap") +RegisterBarotrauma("PhysicsBody") +RegisterBarotrauma("InvSlotType") +RegisterBarotrauma("ItemPrefab") +RegisterBarotrauma("SerializableProperty") +RegisterBarotrauma("StatusEffect") +RegisterBarotrauma("FireSource") +RegisterBarotrauma("ContentPackage") +RegisterBarotrauma("SubmarineBody") +RegisterBarotrauma("Explosion") +RegisterBarotrauma("Networking.ServerSettings") +RegisterBarotrauma("Inventory") +RegisterBarotrauma("ItemInventory") + +RegisterBarotrauma("Items.Components.Fabricator") +RegisterBarotrauma("Items.Components.ItemComponent") +RegisterBarotrauma("Items.Components.WifiComponent") +RegisterBarotrauma("Items.Components.LightComponent") +RegisterBarotrauma("Items.Components.Holdable") +RegisterBarotrauma("Items.Components.CustomInterface") +RegisterBarotrauma("Items.Components.CustomInterface+CustomInterfaceElement") +RegisterBarotrauma("Items.Components.ItemContainer") +RegisterBarotrauma("Items.Components.PowerContainer") +RegisterBarotrauma("Items.Components.Pickable") +RegisterBarotrauma("Items.Components.Reactor") +RegisterBarotrauma("Items.Components.RelayComponent") +RegisterBarotrauma("Items.Components.MemoryComponent") +RegisterBarotrauma("Items.Components.Engine") + +RegisterBarotrauma("AIController") +RegisterBarotrauma("EnemyAIController") +RegisterBarotrauma("HumanAIController") +RegisterBarotrauma("AICharacter") +RegisterBarotrauma("AITarget") +RegisterBarotrauma("AITargetMemory") + +RegisterBarotrauma("TalentPrefab") +RegisterBarotrauma("TalentOption") +RegisterBarotrauma("TalentSubTree") +RegisterBarotrauma("TalentTree") +RegisterBarotrauma("CharacterTalent") + +RegisterBarotrauma("Screen") +RegisterBarotrauma("GameScreen") +RegisterBarotrauma("GameSession") +RegisterBarotrauma("CampaignMode") + +local descriptor = RegisterBarotrauma("NetLobbyScreen") +LuaUserData.MakeFieldAccessible(descriptor, "subs") + +RegisterBarotrauma("Networking.IWriteMessage") +RegisterBarotrauma("Networking.IReadMessage") +RegisterBarotrauma("Networking.ServerPacketHeader") +RegisterBarotrauma("Networking.ClientPacketHeader") +RegisterBarotrauma("Networking.DeliveryMethod") +RegisterBarotrauma("Rand+RandSync") +RegisterBarotrauma("Skill") +RegisterBarotrauma("SkillPrefab") +RegisterBarotrauma("TraitorMissionPrefab") +RegisterBarotrauma("TraitorMissionResult") + +LuaUserData.RegisterType("FarseerPhysics.Dynamics.World") +LuaUserData.RegisterType("FarseerPhysics.Dynamics.Fixture") +RegisterBarotrauma("Physics") + +RegisterBarotrauma("Camera") +RegisterBarotrauma("InputType") +RegisterBarotrauma("Key") + +AddCallMetaMember(RegisterBarotrauma("CharacterInfo")) +AddCallMetaMember(RegisterBarotrauma("Items.Components.Signal")) +AddCallMetaMember(RegisterBarotrauma("SubmarineInfo")) + +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector2")) +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector3")) +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Vector4")) +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Color")) +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Point")) +AddCallMetaMember(LuaUserData.RegisterType("Microsoft.Xna.Framework.Rectangle")) + +if SERVER then + +RegisterBarotrauma("Traitor") +RegisterBarotrauma("Traitor+TraitorMission") + +elseif CLIENT then + +RegisterBarotrauma("LuaSetup+LuaGUI") +RegisterBarotrauma("ChatBox") +RegisterBarotrauma("GUICanvas") +RegisterBarotrauma("Anchor") +RegisterBarotrauma("Alignment") +RegisterBarotrauma("Pivot") +RegisterBarotrauma("Key") +RegisterBarotrauma("PlayerInput") + +LuaUserData.RegisterType("Microsoft.Xna.Framework.Graphics.Texture2D") +LuaUserData.RegisterType("EventInput.KeyEventArgs") +LuaUserData.RegisterType("Microsoft.Xna.Framework.Input.Keys") + +AddCallMetaMember(RegisterBarotrauma("Sprite")) +AddCallMetaMember(RegisterBarotrauma("GUILayoutGroup")) +AddCallMetaMember(RegisterBarotrauma("GUITextBox")) +AddCallMetaMember(RegisterBarotrauma("GUITextBlock")) +AddCallMetaMember(RegisterBarotrauma("GUIButton")) +AddCallMetaMember(RegisterBarotrauma("RectTransform")) +AddCallMetaMember(RegisterBarotrauma("GUIFrame")) +AddCallMetaMember(RegisterBarotrauma("GUITickBox")) +AddCallMetaMember(RegisterBarotrauma("GUICustomComponent")) +AddCallMetaMember(RegisterBarotrauma("GUIImage")) +AddCallMetaMember(RegisterBarotrauma("GUIListBox")) +AddCallMetaMember(RegisterBarotrauma("GUIScrollBar")) +AddCallMetaMember(RegisterBarotrauma("GUIDropDown")) + +end \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/Lua/MoonsharpSetup.lua b/Barotrauma/BarotraumaShared/Lua/LuaSetup.lua similarity index 89% rename from Barotrauma/BarotraumaShared/Lua/MoonsharpSetup.lua rename to Barotrauma/BarotraumaShared/Lua/LuaSetup.lua index 327974002..cd83b391e 100644 --- a/Barotrauma/BarotraumaShared/Lua/MoonsharpSetup.lua +++ b/Barotrauma/BarotraumaShared/Lua/LuaSetup.lua @@ -1,4 +1,14 @@ +-- Config + local runDisabledMods = false +local modulePaths = {"Lua/?.lua"} +setmodulepaths(modulePaths) + +local defaultLib = require("DefaultLib") + +for key, value in pairs(defaultLib) do + _G[key] = value +end if SERVER and Game.IsDedicated then runDisabledMods = true @@ -30,8 +40,6 @@ local function runFolder(folder) end end -local modulePaths = {} - if not runDisabledMods then for _, package in pairs(enabledPackages) do diff --git a/Barotrauma/BarotraumaShared/Lua/NluaSetup.lua b/Barotrauma/BarotraumaShared/Lua/NluaSetup.lua deleted file mode 100644 index e69de29bb..000000000 diff --git a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs index 6e88b11d6..3ea2b743e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs @@ -11,6 +11,10 @@ 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 { @@ -32,7 +36,82 @@ namespace Barotrauma return new Vector4(x, y, z, w); } - private partial class LuaPlayer + partial class LuaUserData + { + public static Type GetType(string typeName) + { + var type = Type.GetType(typeName); + if (type != null) return type; + foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) + { + type = a.GetType(typeName); + if (type != null) + return type; + } + return null; + } + + public static IUserDataDescriptor RegisterType(string typeName) + { + Type type = GetType(typeName); + + MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.RegisterType), new Type[2] { typeof(InteropAccessMode), typeof(string) }); + MethodInfo generic = method.MakeGenericMethod(type); + return (IUserDataDescriptor)generic.Invoke(null, new object[] { null, null }); + } + + public static object CreateStatic(string typeName) + { + Type type = GetType(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 void AddCallMetaMember(IUserDataDescriptor IUDD) + { + var descriptor = (StandardUserDataDescriptor)IUDD; + descriptor.RemoveMetaMember("__call"); + descriptor.AddMetaMember("__call", new ObjectCallbackMemberDescriptor("__call", LuaSetup.luaSetup.HandleCall)); + } + + public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string methodName) + { + var descriptor = (StandardUserDataDescriptor)IUUD; + var field = IUUD.Type.GetField(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new FieldMemberDescriptor(field, InteropAccessMode.Default)); + } + + public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName) + { + var descriptor = (StandardUserDataDescriptor)IUUD; + var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default)); + } + + public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) + { + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) => + { + if (luaSetup != null) + return luaSetup.CallFunction(function, arg3.GetArray()); + return null; + })); + } + + public static void RemoveMember(IUserDataDescriptor IUUD, string memberName) + { + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(memberName); + } + } + + public partial class LuaPlayer { } @@ -322,8 +401,10 @@ namespace Barotrauma } - private partial class LuaTimer + public partial class LuaTimer { + public static long LastUpdateTime = 0; + public LuaSetup env; public LuaTimer(LuaSetup e) @@ -331,12 +412,27 @@ namespace Barotrauma env = e; } + public static double Time + { + get + { + return GetTime(); + } + } + 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; + } } private partial class LuaRandom @@ -592,6 +688,7 @@ namespace Barotrauma public LuaHook(LuaSetup e) { env = e; + methodNameToHookName = new Dictionary(); } public class HookFunction @@ -608,7 +705,60 @@ namespace Barotrauma } } - public Dictionary> hookFunctions = new Dictionary>(); + private Dictionary> hookFunctions = new Dictionary>(); + + private static Dictionary methodNameToHookName; + + public enum HookMethodType + { + Before, After + } + + static void HookLuaPatchPrefix(MethodBase __originalMethod) + { + luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name]); + } + + static void HookLuaPatchPostfix(MethodBase __originalMethod) + { + luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name]); + } + + // not very useful until i find a way to use the transpiler to inject arguments into the call + + public void HookMethod(string className, string methodName, string hookName, HookMethodType hookMethodType = HookMethodType.Before) + { + var classType = Type.GetType(className); + var methodInfos = classType.GetMethods(); + HarmonyMethod harmonyMethod = new HarmonyMethod(); + + if (hookMethodType == HookMethodType.Before) + { + harmonyMethod = new HarmonyMethod(GetType().GetMethod("HookLuaPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static)); + } + else if (hookMethodType == HookMethodType.After) + { + harmonyMethod = new HarmonyMethod(GetType().GetMethod("HookLuaPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static)); + } + + var foundAny = false; + + foreach (var methodInfo in methodInfos) + { + if(methodInfo.Name == methodName) + { + if (hookMethodType == HookMethodType.Before) + env.harmony.Patch(methodInfo, harmonyMethod); + else if (hookMethodType == HookMethodType.After) + env.harmony.Patch(methodInfo, postfix: harmonyMethod); + + foundAny = true; + } + } + + if(foundAny) + methodNameToHookName.Add(methodName, hookName); + } public void Add(string name, string hookName, object function) { @@ -632,7 +782,7 @@ namespace Barotrauma hookFunctions[name].Remove(hookName); } - public object Call(string name, object[] args) + public object Call(string name, params object[] args) { if (env == null) return null; if (name == null) return null; @@ -653,12 +803,16 @@ namespace Barotrauma if (!result.IsNil()) lastResult = result; } - //else if (hf.function is NLua.LuaFunction luaFunction) - // lastResult = luaFunction.Call(args); } catch (Exception e) { - env.HandleLuaException(e); + StringBuilder argsSb = new StringBuilder(); + foreach(var arg in args) + { + argsSb.Append(arg + " "); + } + + env.HandleLuaException(e, $"Error in Hook '{name}'->'{hf.hookName}', with args '{argsSb}'"); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs index 6d12d62a6..35afb201b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs @@ -13,6 +13,7 @@ using MoonSharp.Interpreter.Interop; using System.Reflection; using FarseerPhysics.Dynamics; using System.IO.Compression; +using HarmonyLib; #if CLIENT using Microsoft.Xna.Framework.Graphics; @@ -31,11 +32,15 @@ namespace Barotrauma public LuaHook hook; public LuaGame game; public LuaNetworking networking; + public Harmony harmony; public LuaScriptLoader luaScriptLoader; - public void HandleLuaException(Exception ex) + public void HandleLuaException(Exception ex, string extra = "") { + if (!string.IsNullOrWhiteSpace(extra)) + PrintMessage(extra); + if (ex is InterpreterException) { if (((InterpreterException)ex).DecoratedMessage == null) @@ -197,8 +202,9 @@ namespace Barotrauma } // messy solution - private object HandleCall(object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) + public object HandleCall(object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) { + var what = arg3.RawGet(0, true); var code = "return " + what.UserData.Descriptor.Type.Name + ".__new("; @@ -230,12 +236,6 @@ namespace Barotrauma return null; } - private void AddCallMetaMember(IUserDataDescriptor IUDD) - { - var descriptor = (StandardUserDataDescriptor)IUDD; - descriptor.RemoveMetaMember("__call"); - descriptor.AddMetaMember("__call", new ObjectCallbackMemberDescriptor("__call", HandleCall)); - } #if SERVER public static void InstallClientSideLua() @@ -301,6 +301,17 @@ namespace Barotrauma LuaCustomConverters.RegisterAll(); + lua = new Script(CoreModules.Preset_SoftSandbox); + lua.Options.DebugPrint = PrintMessage; + lua.Options.ScriptLoader = luaScriptLoader; + + harmony = new Harmony("com.LuaForBarotrauma"); + harmony.UnpatchAll(); + + hook = new LuaHook(this); + game = new LuaGame(this); + networking = new LuaNetworking(this); + UserData.RegisterType(); UserData.RegisterType(); UserData.RegisterType(); @@ -308,83 +319,8 @@ namespace Barotrauma UserData.RegisterType(); UserData.RegisterType(); UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType>(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); + UserData.RegisterType(); + UserData.RegisterType(); UserData.RegisterType>(); UserData.RegisterType>(); @@ -392,90 +328,10 @@ namespace Barotrauma UserData.RegisterType>(); UserData.RegisterType>(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); + UserData.RegisterType>(); - { - var descriptor = (StandardUserDataDescriptor)UserData.RegisterType(); - var type = typeof(NetLobbyScreen); - var field = type.GetField("subs", BindingFlags.NonPublic | BindingFlags.Instance); - descriptor.RemoveMember("subs"); - descriptor.AddMember("subs", new FieldMemberDescriptor(field, InteropAccessMode.Default)); - } - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(typeof(Physics)); - - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - -#if SERVER - UserData.RegisterType(); - UserData.RegisterType(); -#elif CLIENT - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - UserData.RegisterType(); - - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); - AddCallMetaMember(UserData.RegisterType()); -#endif - lua = new Script(CoreModules.Preset_SoftSandbox); - - lua.Options.DebugPrint = PrintMessage; - - lua.Options.ScriptLoader = luaScriptLoader; - - hook = new LuaHook(this); - game = new LuaGame(this); - networking = new LuaNetworking(this); + lua.Globals["setmodulepaths"] = (Action)SetModulePaths; lua.Globals["TestFunction"] = (Func)TestFunction; @@ -487,9 +343,8 @@ namespace Barotrauma lua.Globals["dostring"] = (Func)DoString; lua.Globals["load"] = (Func)LoadString; - - lua.Globals["setmodulepaths"] = (Action)SetModulePaths; - + + lua.Globals["LuaUserData"] = UserData.CreateStatic(); lua.Globals["Player"] = new LuaPlayer(); lua.Globals["Game"] = game; lua.Globals["Hook"] = hook; @@ -497,56 +352,17 @@ namespace Barotrauma lua.Globals["Timer"] = new LuaTimer(this); lua.Globals["File"] = UserData.CreateStatic(); lua.Globals["Networking"] = networking; - lua.Globals["WayPoint"] = UserData.CreateStatic(); - lua.Globals["SpawnType"] = UserData.CreateStatic(); - lua.Globals["ChatMessageType"] = UserData.CreateStatic(); - lua.Globals["ServerLog_MessageType"] = UserData.CreateStatic(); - lua.Globals["Submarine"] = UserData.CreateStatic(); - lua.Globals["Client"] = UserData.CreateStatic(); - lua.Globals["Character"] = UserData.CreateStatic(); - lua.Globals["CharacterInfo"] = UserData.CreateStatic(); - lua.Globals["Item"] = UserData.CreateStatic(); - lua.Globals["ItemPrefab"] = UserData.CreateStatic(); - lua.Globals["Level"] = UserData.CreateStatic(); - lua.Globals["PositionType"] = UserData.CreateStatic(); - lua.Globals["JobPrefab"] = UserData.CreateStatic(); - lua.Globals["TraitorMessageType"] = UserData.CreateStatic(); - lua.Globals["CauseOfDeathType"] = UserData.CreateStatic(); - lua.Globals["AfflictionPrefab"] = UserData.CreateStatic(); - lua.Globals["CharacterTeamType"] = UserData.CreateStatic(); - lua.Globals["Vector2"] = UserData.CreateStatic(); - lua.Globals["Vector3"] = UserData.CreateStatic(); - lua.Globals["Vector4"] = UserData.CreateStatic(); - lua.Globals["Color"] = UserData.CreateStatic(); - lua.Globals["Point"] = UserData.CreateStatic(); - lua.Globals["ChatMessage"] = UserData.CreateStatic(); - lua.Globals["Hull"] = UserData.CreateStatic(); - lua.Globals["InvSlotType"] = UserData.CreateStatic(); - lua.Globals["Gap"] = UserData.CreateStatic(); - lua.Globals["ContentPackage"] = UserData.CreateStatic(); - lua.Globals["ClientPermissions"] = UserData.CreateStatic(); - lua.Globals["Signal"] = UserData.CreateStatic(); - lua.Globals["DeliveryMethod"] = UserData.CreateStatic(); - lua.Globals["ClientPacketHeader"] = UserData.CreateStatic(); - lua.Globals["ServerPacketHeader"] = UserData.CreateStatic(); - lua.Globals["RandSync"] = UserData.CreateStatic(); - lua.Globals["SubmarineInfo"] = UserData.CreateStatic(); - lua.Globals["Rectangle"] = UserData.CreateStatic(); - lua.Globals["Entity"] = UserData.CreateStatic(); - lua.Globals["Physics"] = UserData.CreateStatic(typeof(Physics)); + + // obsolete + lua.Globals["CreateVector2"] = (Func)CreateVector2; + lua.Globals["CreateVector3"] = (Func)CreateVector3; + lua.Globals["CreateVector4"] = (Func)CreateVector4; #if SERVER #elif CLIENT lua.Globals["GUI"] = new LuaGUI(this); - lua.Globals["Sprite"] = UserData.CreateStatic(); - lua.Globals["Keys"] = UserData.CreateStatic(); - lua.Globals["PlayerInput"] = UserData.CreateStatic(); #endif - // obsolete - lua.Globals["CreateVector2"] = (Func)CreateVector2; - lua.Globals["CreateVector3"] = (Func)CreateVector3; - lua.Globals["CreateVector4"] = (Func)CreateVector4; bool isServer = true; @@ -561,13 +377,13 @@ namespace Barotrauma // LuaDocs.GenerateDocs(typeof(EntitySpawner)); - if (File.Exists("Lua/MoonsharpSetup.lua")) // try the default loader - DoFile("Lua/MoonsharpSetup.lua"); - else if (File.Exists("Mods/LuaForBarotrauma/Lua/MoonsharpSetup.lua")) // in case its the workshop version - DoFile("Mods/LuaForBarotrauma/Lua/MoonsharpSetup.lua"); + if (File.Exists("Lua/LuaSetup.lua")) // try the default loader + DoFile("Lua/LuaSetup.lua"); + else if (File.Exists("Mods/LuaForBarotrauma/Lua/LuaSetup.lua")) // in case its the workshop version + DoFile("Mods/LuaForBarotrauma/Lua/LuaSetup.lua"); else // fallback to c# script loading { - PrintMessage("Lua/MoonSharp.lua not found, loading Mods directly, things can break!"); + PrintMessage("Lua/LuaSetup.lua not found, loading Mods directly, things can break!"); List modulePaths = new List();