Merge pull request #26 from zhu-rengong/master
modified way to patch, can realize params map for compatibility, and try to hook Item in lua.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
|
||||
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)
|
||||
@@ -49,7 +49,7 @@ if SERVER then
|
||||
|
||||
elseif CLIENT then
|
||||
defaultLib["Sprite"] = CreateStatic("Sprite")
|
||||
defaultLib["Keys"] = LuaUserData.RegisterType("Microsoft.Xna.Framework.Input.Keys")
|
||||
defaultLib["Keys"] = LuaUserData.CreateStatic("Microsoft.Xna.Framework.Input.Keys")
|
||||
defaultLib["PlayerInput"] = CreateStatic("PlayerInput")
|
||||
end
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ for key, value in pairs(defaultLib) do
|
||||
_G[key] = value
|
||||
end
|
||||
|
||||
require("DefaultHook")
|
||||
|
||||
-- Execute Mods
|
||||
|
||||
if SERVER and Game.IsDedicated then
|
||||
|
||||
@@ -2166,11 +2166,6 @@ namespace Barotrauma
|
||||
|
||||
public bool TryInteract(Character picker, bool ignoreRequiredItems = false, bool forceSelectKey = false, bool forceActionKey = false)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemInteract", new object[] { this, picker, ignoreRequiredItems, forceSelectKey, forceActionKey }));
|
||||
|
||||
if (!should.IsNull())
|
||||
return should.Bool();
|
||||
|
||||
if (CampaignInteractionType != CampaignMode.InteractionType.None) { return false; }
|
||||
|
||||
bool picked = false, selected = false;
|
||||
@@ -2352,7 +2347,6 @@ namespace Barotrauma
|
||||
if (should.Bool())
|
||||
return;
|
||||
|
||||
|
||||
bool remove = false;
|
||||
|
||||
foreach (ItemComponent ic in components)
|
||||
@@ -2384,11 +2378,6 @@ namespace Barotrauma
|
||||
|
||||
public void ApplyTreatment(Character user, Character character, Limb targetLimb)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemApplyTreatment", new object[] { this, user, character, targetLimb }));
|
||||
|
||||
if (should.Bool())
|
||||
return;
|
||||
|
||||
//can't apply treatment to dead characters
|
||||
if (character.IsDead) { return; }
|
||||
if (!UseInHealthInterface) { return; }
|
||||
@@ -2454,11 +2443,6 @@ namespace Barotrauma
|
||||
|
||||
public bool Combine(Item item, Character user)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemCombine", new object[] { this, item, user }));
|
||||
|
||||
if (!should.IsNull())
|
||||
return should.Bool();
|
||||
|
||||
if (item == this) { return false; }
|
||||
bool isCombined = false;
|
||||
foreach (ItemComponent ic in components)
|
||||
@@ -2473,11 +2457,6 @@ namespace Barotrauma
|
||||
|
||||
public void Drop(Character dropper, bool createNetworkEvent = true)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemDrop", new object[] { this, dropper}));
|
||||
|
||||
if (should.Bool())
|
||||
return;
|
||||
|
||||
if (createNetworkEvent)
|
||||
{
|
||||
if (parentInventory != null && !parentInventory.Owner.Removed && !Removed &&
|
||||
@@ -2530,11 +2509,6 @@ namespace Barotrauma
|
||||
|
||||
public void Equip(Character character)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemEquip", new object[] { this, character}));
|
||||
|
||||
if (should.Bool())
|
||||
return;
|
||||
|
||||
if (Removed)
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to equip a removed item ({Name}).\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
@@ -2546,11 +2520,6 @@ namespace Barotrauma
|
||||
|
||||
public void Unequip(Character character)
|
||||
{
|
||||
var should = new LuaResult(GameMain.Lua.hook.Call("itemUnequip", new object[] { this, character }));
|
||||
|
||||
if (should.Bool())
|
||||
return;
|
||||
|
||||
foreach (ItemComponent ic in components) { ic.Unequip(character); }
|
||||
}
|
||||
|
||||
|
||||
@@ -62,12 +62,12 @@ namespace Barotrauma
|
||||
descriptor.AddMetaMember("__call", new ObjectCallbackMemberDescriptor("__call", LuaSetup.luaSetup.HandleCall));
|
||||
}
|
||||
|
||||
public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string methodName)
|
||||
public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName)
|
||||
{
|
||||
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));
|
||||
var field = IUUD.Type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
descriptor.RemoveMember(fieldName);
|
||||
descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default));
|
||||
}
|
||||
|
||||
public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName)
|
||||
@@ -692,7 +692,7 @@ namespace Barotrauma
|
||||
public LuaHook(LuaSetup e)
|
||||
{
|
||||
env = e;
|
||||
methodNameToHookName = new Dictionary<string, string>();
|
||||
_hookMethods = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public class HookFunction
|
||||
@@ -711,7 +711,7 @@ namespace Barotrauma
|
||||
|
||||
private Dictionary<string, Dictionary<string, HookFunction>> hookFunctions = new Dictionary<string, Dictionary<string, HookFunction>>();
|
||||
|
||||
private static Dictionary<string, string> methodNameToHookName;
|
||||
private static Dictionary<string, object> _hookMethods;
|
||||
|
||||
private Queue<Tuple<object, object[]>> queuedFunctionCalls = new Queue<Tuple<object, object[]>>();
|
||||
|
||||
@@ -720,47 +720,50 @@ namespace Barotrauma
|
||||
Before, After
|
||||
}
|
||||
|
||||
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 classType = __originalMethod.DeclaringType;
|
||||
var methodPath = $"{hookMethodType}:{classType.Namespace}.{classType.Name}.{__originalMethod.Name}";
|
||||
|
||||
var @params = __originalMethod.GetParameters();
|
||||
var ptable = new Dictionary<string, object>();
|
||||
for (int i = 0; i < @params.Length; i++)
|
||||
{
|
||||
ptable.Add(@params[i].Name, __params[i]);
|
||||
|
||||
}
|
||||
|
||||
if (_hookMethods.TryGetValue(methodPath, out object hookMethod))
|
||||
{
|
||||
result = new LuaResult(luaSetup.hook.env.lua.Call(hookMethod, __instance, ptable));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"No hook method found in _hookMethods[{methodPath}]");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DebugConsole.ThrowError(nameof(_hookLuaPatch), ex);
|
||||
}
|
||||
}
|
||||
|
||||
static bool HookLuaPatchPrefix(MethodBase __originalMethod, object[] __params, object __instance)
|
||||
{
|
||||
object[] parameters;
|
||||
|
||||
if (__instance == null)
|
||||
{
|
||||
parameters = __params;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = new object[__params.Length + 1];
|
||||
__params.CopyTo(parameters, 1);
|
||||
parameters[0] = __instance;
|
||||
}
|
||||
|
||||
var result = new LuaResult(luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name], parameters));
|
||||
|
||||
if (!result.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
_hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.Before);
|
||||
|
||||
return result.IsNull();
|
||||
}
|
||||
|
||||
static bool HookLuaPatchRetPrefix(MethodBase __originalMethod, object[] __params, ref object __result, object __instance)
|
||||
{
|
||||
object[] parameters;
|
||||
|
||||
if (__instance == null)
|
||||
{
|
||||
parameters = __params;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = new object[__params.Length + 1];
|
||||
__params.CopyTo(parameters, 1);
|
||||
parameters[0] = __instance;
|
||||
}
|
||||
|
||||
var result = new LuaResult(luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name], parameters));
|
||||
_hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.Before);
|
||||
|
||||
if (!result.IsNull())
|
||||
{
|
||||
@@ -773,34 +776,22 @@ namespace Barotrauma
|
||||
|
||||
static void HookLuaPatchPostfix(MethodBase __originalMethod, object[] __params, object __instance)
|
||||
{
|
||||
if (__instance == null)
|
||||
luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name], __params);
|
||||
else
|
||||
luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name], __instance, __params);
|
||||
_hookLuaPatch(__originalMethod, __params, __instance, out LuaResult result, HookMethodType.After);
|
||||
}
|
||||
|
||||
static void HookLuaPatchRetPostfix(MethodBase __originalMethod, object[] __params, ref object __result, object __instance)
|
||||
{
|
||||
object[] parameters;
|
||||
|
||||
if (__instance == null)
|
||||
{
|
||||
parameters = __params;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters = new object[__params.Length + 1];
|
||||
__params.CopyTo(parameters, 1);
|
||||
parameters[0] = __instance;
|
||||
}
|
||||
|
||||
var result = new LuaResult(luaSetup.hook.Call(methodNameToHookName[__originalMethod.Name], 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, 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 classType = Type.GetType(className);
|
||||
var methodInfos = classType.GetMethods();
|
||||
@@ -809,42 +800,50 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
var foundAny = false;
|
||||
|
||||
foreach (var methodInfo in methodInfos)
|
||||
{
|
||||
if(methodInfo.Name == methodName)
|
||||
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);
|
||||
}
|
||||
|
||||
foundAny = true;
|
||||
// build an unique method path by patch type, class, method self
|
||||
var methodPath = $"{hookMethodType}:{classType.Namespace}.{classType.Name}.{methodInfo.Name}";
|
||||
|
||||
if (hookMethod != null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundAny)
|
||||
methodNameToHookName.Add(methodName, hookName);
|
||||
}
|
||||
|
||||
public void EnqueueFunction(object function, params object[] args)
|
||||
|
||||
@@ -324,7 +324,6 @@ namespace Barotrauma
|
||||
UserData.RegisterType<LuaFile>();
|
||||
UserData.RegisterType<LuaNetworking>();
|
||||
UserData.RegisterType<LuaUserData>();
|
||||
UserData.RegisterType<LuaHook.HookMethodType>();
|
||||
UserData.RegisterType<IUserDataDescriptor>();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user