diff --git a/Barotrauma/BarotraumaShared/Lua/DefaultHook.lua b/Barotrauma/BarotraumaShared/Lua/DefaultHook.lua index 40bfc8b70..7cdac4356 100644 --- a/Barotrauma/BarotraumaShared/Lua/DefaultHook.lua +++ b/Barotrauma/BarotraumaShared/Lua/DefaultHook.lua @@ -1,10 +1,24 @@ -Hook.HookMethod("Barotrauma.Item", "TryInteract", "itemInteract", nil) -- instance, picker, ignoreRequiredItems, forceSelectKey, forceActionKey -Hook.HookMethod("Barotrauma.Item", "Use", "itemUse", function (instance, deltaTime, character, targetLimb) return {instance, character, targetLimb} end) -Hook.HookMethod("Barotrauma.Item", "SecondaryUse", "itemSecondaryUse", function (instance, deltaTime, character) return {instance, character} end) -Hook.HookMethod("Barotrauma.Item", "ApplyTreatment", "itemApplyTreatment", nil) -- instance, user, character, targetLimb -Hook.HookMethod("Barotrauma.Item", "Combine", "itemCombine", nil) -- instance, item, user -Hook.HookMethod("Barotrauma.Item", "Drop", "itemDrop", function (instance, dropper, createNetworkEvent) return {instance, dropper} end) -Hook.HookMethod("Barotrauma.Item", "Equip", "itemEquip", nil) -- instance, character -Hook.HookMethod("Barotrauma.Item", "Unequip", "itemUnequip", nil) -- instance, character +Hook.HookMethod("Barotrauma.Item", "TryInteract", function (instance, p) + Hook.Call("itemInteract", instance, p.picker, p.ignoreRequiredItems, p.forceSelectKey, p.forceActionKey) +end, Hook.HookMethodType.Before) +Hook.HookMethod("Barotrauma.Item", "ApplyTreatment", function (instance, p) + Hook.Call("itemApplyTreatment", instance, p.user, p.character, p.targetLimb) +end, Hook.HookMethodType.Before) + +Hook.HookMethod("Barotrauma.Item", "Combine", function (instance, p) + Hook.Call("itemCombine", instance, p.item, p.user) +end, Hook.HookMethodType.Before) + +Hook.HookMethod("Barotrauma.Item", "Drop", function (instance, p) + Hook.Call("itemDrop", instance, p.dropper) +end, Hook.HookMethodType.Before) + +Hook.HookMethod("Barotrauma.Item", "Equip", function (instance, p) + Hook.Call("itemEquip", instance, p.character) +end, Hook.HookMethodType.Before) + +Hook.HookMethod("Barotrauma.Item", "Unequip", function (instance, p) + Hook.Call("itemUnequip", instance, p.character) +end, Hook.HookMethodType.Before) \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index d1d17d44b..04a2b68b9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -2304,6 +2304,11 @@ namespace Barotrauma if (condition == 0.0f) { return; } + var should = new LuaResult(GameMain.Lua.hook.Call("itemUse", new object[] { this, character, targetLimb })); + + if (should.Bool()) + return; + bool remove = false; foreach (ItemComponent ic in components) @@ -2337,6 +2342,11 @@ namespace Barotrauma { if (condition == 0.0f) { return; } + var should = new LuaResult(GameMain.Lua.hook.Call("itemSecondaryUse", new object[] { this, character})); + + if (should.Bool()) + return; + bool remove = false; foreach (ItemComponent ic in components) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs index e079ae849..698967aec 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaClasses.cs @@ -692,8 +692,7 @@ namespace Barotrauma public LuaHook(LuaSetup e) { env = e; - _methodPathToHookName = new Dictionary(); - _luaPatchParamsMap = new Dictionary(); + _hookMethods = new Dictionary(); } public class HookFunction @@ -712,8 +711,7 @@ namespace Barotrauma private Dictionary> hookFunctions = new Dictionary>(); - private static Dictionary _methodPathToHookName; - private static Dictionary _luaPatchParamsMap; + private static Dictionary _hookMethods; private Queue> queuedFunctionCalls = new Queue>(); @@ -722,48 +720,50 @@ namespace Barotrauma Before, After } - static void _hookLuaPatchPreProcess(MethodBase __originalMethod, object[] __params, object __instance, out string hookName, out object[] parameters) + static void _hookLuaPatch(MethodBase __originalMethod, object[] __params, object __instance, out LuaResult result, HookMethodType hookMethodType) { + // Although it works correctly, the performance is low + result = new LuaResult(null); + try { - var @class = __originalMethod.DeclaringType; - var methodPath = $"{@class.Namespace}.{@class.Name}.{__originalMethod.Name}"; + var classType = __originalMethod.DeclaringType; + var methodPath = $"{hookMethodType}:{classType.Namespace}.{classType.Name}.{__originalMethod.Name}"; - hookName = _methodPathToHookName[methodPath]; + var @params = __originalMethod.GetParameters(); + var ptable = new Dictionary(); + for (int i = 0; i < @params.Length; i++) + { + ptable.Add(@params[i].Name, __params[i]); - // Regardless of whether __instance is null or not, it's necessaray to avoid the inability to distinguish parameters when adding hooks in lua. - parameters = new object[__params.Length + 1]; - __params.CopyTo(parameters, 1); - parameters[0] = __instance; - // Map the parameters for compatibility - if (_luaPatchParamsMap.TryGetValue(methodPath, out object map)) + } + + if (_hookMethods.TryGetValue(methodPath, out object hookMethod)) { - var result = luaSetup.hook.env.lua.Call(map, parameters); - if (!result.IsNil()) parameters = result.ToObject(); + result = new LuaResult(luaSetup.hook.env.lua.Call(hookMethod, __instance, ptable)); + } + else + { + DebugConsole.ThrowError($"No hook method found in _hookMethods[{methodPath}]"); } } catch (Exception ex) { - parameters = null; - hookName = null; - DebugConsole.ThrowError(nameof(_hookLuaPatchPreProcess), ex); + DebugConsole.ThrowError(nameof(_hookLuaPatch), ex); } } static bool HookLuaPatchPrefix(MethodBase __originalMethod, object[] __params, object __instance) { - _hookLuaPatchPreProcess(__originalMethod, __params, __instance, out string hookName, out object[] parameters); - - var result = new LuaResult(luaSetup.hook.Call(hookName, parameters)); + _hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.Before); + return result.IsNull(); } static bool HookLuaPatchRetPrefix(MethodBase __originalMethod, object[] __params, ref object __result, object __instance) { - _hookLuaPatchPreProcess(__originalMethod, __params, __instance, out string hookName, out object[] parameters); - - var result = new LuaResult(luaSetup.hook.Call(hookName, parameters)); + _hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.Before); if (!result.IsNull()) { @@ -776,71 +776,69 @@ namespace Barotrauma static void HookLuaPatchPostfix(MethodBase __originalMethod, object[] __params, object __instance) { - _hookLuaPatchPreProcess(__originalMethod, __params, __instance, out string hookName, out object[] parameters); - luaSetup.hook.Call(hookName, parameters); + _hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.After); } - - static void HookLuaPatchRetPostfix(MethodBase __originalMethod, object[] __params, ref object __result, object __instance) { - _hookLuaPatchPreProcess(__originalMethod, __params, __instance, out string hookName, out object[] parameters); - - var result = new LuaResult(luaSetup.hook.Call(hookName, parameters)); + _hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.After); if (!result.IsNull()) __result = result.Object(); } - public void HookMethod(string className, string methodName, string hookName, object paramsMap, HookMethodType hookMethodType = HookMethodType.Before) + private static MethodInfo _miHookLuaPatchPrefix = typeof(LuaHook).GetMethod("HookLuaPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaPatchRetPrefix = typeof(LuaHook).GetMethod("HookLuaPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaPatchPostfix = typeof(LuaHook).GetMethod("HookLuaPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static); + private static MethodInfo _miHookLuaPatchRetPostfix = typeof(LuaHook).GetMethod("HookLuaPatchRetPostfix", BindingFlags.NonPublic | BindingFlags.Static); + public void HookMethod(string className, string methodName, object hookMethod, HookMethodType hookMethodType = HookMethodType.Before) { - var @class = Type.GetType(className); - var methodInfos = @class.GetMethods(); + var classType = Type.GetType(className); + var methodInfos = classType.GetMethods(); HarmonyMethod harmonyMethod = new HarmonyMethod(); HarmonyMethod harmonyMethodRet = new HarmonyMethod(); if (hookMethodType == HookMethodType.Before) { - harmonyMethod = new HarmonyMethod(GetType().GetMethod("HookLuaPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static)); - - harmonyMethodRet = new HarmonyMethod(GetType().GetMethod("HookLuaPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static)); + harmonyMethod = new HarmonyMethod(_miHookLuaPatchPrefix); + harmonyMethodRet = new HarmonyMethod(_miHookLuaPatchRetPrefix); } else if (hookMethodType == HookMethodType.After) { - harmonyMethod = new HarmonyMethod(GetType().GetMethod("HookLuaPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static)); - - harmonyMethodRet = new HarmonyMethod(GetType().GetMethod("HookLuaPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static)); + harmonyMethod = new HarmonyMethod(_miHookLuaPatchPostfix); + harmonyMethodRet = new HarmonyMethod(_miHookLuaPatchRetPostfix); } - foreach (var methodInfo in methodInfos) { if (methodInfo.Name == methodName) { if (hookMethodType == HookMethodType.Before) + { if (methodInfo.ReturnType == typeof(void)) - env.harmony.Patch(methodInfo, harmonyMethod); + env.harmony.Patch(methodInfo, prefix: harmonyMethod); else - env.harmony.Patch(methodInfo, harmonyMethodRet); - - + env.harmony.Patch(methodInfo, prefix: harmonyMethodRet); + } else if (hookMethodType == HookMethodType.After) + { if (methodInfo.ReturnType == typeof(void)) env.harmony.Patch(methodInfo, postfix: harmonyMethod); else env.harmony.Patch(methodInfo, postfix: harmonyMethodRet); + } - var methodPath = $"{@class.Namespace}.{@class.Name}.{methodInfo.Name}"; - if (_methodPathToHookName.TryAdd(methodPath, hookName)) - DebugConsole.NewMessage($"Sucessfully added key-value in {nameof(_methodPathToHookName)}\n[{methodPath}, {hookName}]", Color.LightSkyBlue); - else DebugConsole.ThrowError($"Failed to add key-value in {nameof(_methodPathToHookName)}\n[{methodPath}, {hookName}]"); - - if (paramsMap != null) + // build an unique method path by patch type, class, method self + var methodPath = $"{hookMethodType}:{classType.Namespace}.{classType.Name}.{methodInfo.Name}"; + + if (hookMethod != null) { - if (_luaPatchParamsMap.TryAdd(methodPath, paramsMap)) - DebugConsole.NewMessage($"Sucessfully added key-value in {nameof(_luaPatchParamsMap)}\n[{methodPath}, {paramsMap.ToString()}]", Color.LightSkyBlue); - else DebugConsole.ThrowError($"Failed to add key-value in {nameof(_luaPatchParamsMap)}\n[{methodPath}, {paramsMap.ToString()}]"); - + if (!_hookMethods.TryAdd(methodPath, hookMethod)) + DebugConsole.ThrowError($"Failed to add key-value in {nameof(_hookMethods)}\n[{methodPath}, {hookMethod.ToString()}]"); +#if DEBUG + else + DebugConsole.NewMessage($"Sucessfully added key-value in {nameof(_hookMethods)}\n[{methodPath}, {hookMethod.ToString()}]", Color.LightSkyBlue); +#endif } break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs index feb05ffea..b10afe263 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Lua/LuaSetup.cs @@ -324,7 +324,6 @@ namespace Barotrauma UserData.RegisterType(); UserData.RegisterType(); UserData.RegisterType(); - UserData.RegisterType(); UserData.RegisterType();