Advertisement
Guest User

Untitled

a guest
Jan 2nd, 2014
681
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 33.78 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Reflection;
  5. using System.Runtime.InteropServices;
  6.  
  7. namespace Addon
  8. {
  9.     // ***** Uncomment if using .NET Framework 2.0 .NET Framework 3.0, or .NET Framework 3.5 *****
  10.     // ***** Yes, all of it, seriously. *****
  11.     /*
  12.     public delegate TResult Func<TResult>();
  13.     public delegate void Action();
  14.     public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
  15.     public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
  16.     public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
  17.     public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
  18.     public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
  19.     public delegate void Action<T1, T2, T3, T4, T5, T6, T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
  20.     public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
  21.     public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
  22.     */
  23.  
  24.     enum ParameterType
  25.     {
  26.         Entity = 1,
  27.         String = 2,
  28.         Vector = 4,
  29.         Float = 5,
  30.         Integer = 6
  31.     }
  32.  
  33.     class Parameter
  34.     {
  35.         private static readonly IntPtr EntityAddress = (IntPtr)0x01918900;
  36.         private static readonly IntPtr ClientAddress = (IntPtr)0x4A0FE90;
  37.  
  38.         private readonly object _value;
  39.         private readonly ParameterType _type;
  40.  
  41.         internal Parameter(object value, ParameterType type)
  42.         {
  43.             _value = value;
  44.             _type = type;
  45.         }
  46.  
  47.         public ParameterType Type
  48.         {
  49.             get { return _type; }
  50.         }
  51.  
  52.         public object Value
  53.         {
  54.             get { return _value; }
  55.         }
  56.  
  57.         public bool IsPlayer
  58.         {
  59.             get { return _type == ParameterType.Entity && (int)_value < 18; }
  60.         }
  61.  
  62.         public bool IsEntity
  63.         {
  64.             get { return _type == ParameterType.Entity && (int)_value >= 18; }
  65.         }
  66.  
  67.         public T As<T>()
  68.         {
  69.             if (typeof(T) == typeof(Entity))
  70.                 return (T)(object)GetEntity();
  71.  
  72.             if (typeof(T) == typeof(ServerClient))
  73.                 return (T)(object)GetClient();
  74.  
  75.             if (typeof(T) == typeof(bool) && _type == ParameterType.Integer)
  76.                 return (T)(object)((int)_value != 0);
  77.  
  78.             return (T)Convert.ChangeType(_value, typeof(T));
  79.         }
  80.  
  81.         public static implicit operator Parameter(string value)
  82.         {
  83.             return new Parameter(value, ParameterType.String);
  84.         }
  85.  
  86.         public static implicit operator Parameter(int value)
  87.         {
  88.             return new Parameter(value, ParameterType.Integer);
  89.         }
  90.  
  91.         public static implicit operator Parameter(float value)
  92.         {
  93.             return new Parameter(value, ParameterType.Float);
  94.         }
  95.  
  96.         public static implicit operator Parameter(Vector value)
  97.         {
  98.             return new Parameter(value, ParameterType.Vector);
  99.         }
  100.  
  101.         public static implicit operator Parameter(ServerClient client)
  102.         {
  103.             return new Parameter(client.ClientNum, ParameterType.Entity);
  104.         }
  105.  
  106.         public static implicit operator Parameter(Entity entity)
  107.         {
  108.             return new Parameter(entity.EntityNum, ParameterType.Entity);
  109.         }
  110.  
  111.         private Entity GetEntity()
  112.         {
  113.             // Get the constructor for the Entity class.
  114.             var entityConstructors = typeof(Entity).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
  115.  
  116.             // Invoke the constructor with no arguments.
  117.             var entity = (Entity)entityConstructors[0].Invoke(null);
  118.  
  119.             // Call the internal SetInformation method with a pointer to the Entity.
  120.             typeof(Entity).GetMethod("SetInformation", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(entity, new object[] { GetEntityFromNum((int)_value) });
  121.  
  122.             return entity;
  123.         }
  124.  
  125.         private ServerClient GetClient()
  126.         {
  127.             // Get the constructor for the Client class.
  128.             var clientConstructors = typeof(ServerClient).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
  129.  
  130.             // Invoke the constructor with no arguments.
  131.             var client = (ServerClient)clientConstructors[0].Invoke(null);
  132.  
  133.             // Call the internal SetInformation method with a pointer to the Entity.
  134.             typeof(ServerClient).GetMethod("SetInformation", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(client, new object[] { GetClientFromNum((int)_value) });
  135.  
  136.             return client;
  137.         }
  138.  
  139.         private static IntPtr GetEntityFromNum(int entityNum)
  140.         {
  141.             return (IntPtr)(EntityAddress.ToInt32() + entityNum * 0x274);
  142.         }
  143.  
  144.         private static IntPtr GetClientFromNum(int clientNum)
  145.         {
  146.             return (IntPtr)(ClientAddress.ToInt32() + clientNum * 0x78690);
  147.         }
  148.     }
  149.  
  150.     static class Timing
  151.     {
  152.         class ServerTimer
  153.         {
  154.             public int Interval { get; set; }
  155.             public long Time { get; set; }
  156.             public ServerClient Target { get; set; }
  157.             public Delegate Function { get; set; }
  158.         }
  159.  
  160.         class ServerNotify
  161.         {
  162.             public int TargetNum { get; set; }
  163.             public bool HasTarget { get; set; }
  164.             public Delegate Function { get; set; }
  165.         }
  166.  
  167.         [StructLayout(LayoutKind.Sequential)]
  168.         struct Vec3
  169.         {
  170.             public float X;
  171.             public float Y;
  172.             public float Z;
  173.  
  174.             public static implicit operator Vec3(Vector vector)
  175.             {
  176.                 return new Vec3 { X = vector.X, Y = vector.Y, Z = vector.Z };
  177.             }
  178.  
  179.             public static implicit operator Vector(Vec3 vector)
  180.             {
  181.                 return new Vector(vector.X, vector.Y, vector.Z);
  182.             }
  183.         }
  184.  
  185.         private static readonly byte[] ScrAddStringStub = new byte[]
  186.         {
  187.             0x55, // push ebp
  188.             0x8B, 0xEC, // mov ebp, esp
  189.             0x51, // push ecx
  190.             0x57, // push edi
  191.             0xC7, 0x45, 0xFC, 0xD0, 0x11, 0x4F, 0x00, // mov dword ptr [ebp-4], 4F11D0
  192.             0x8B, 0x7D, 0x08, // mov edi, [ebp+8]
  193.             0xFF, 0x55, 0xFC, // call [ebp-4]
  194.             0x5F, // pop edi
  195.             0x8B, 0xE5, // mov esp, ebp
  196.             0x5D, // pop ebp
  197.             0xC3 // retn
  198.         };
  199.  
  200.         private static readonly byte[] ScrAddObjectStub = new byte[]
  201.         {
  202.             0x55, // push ebp
  203.             0x8B, 0xEC, // mov ebp, esp
  204.             0x51, // push ecx
  205.             0x56, // push esi
  206.             0xC7, 0x45, 0xFC, 0x50, 0x11, 0x4F, 0x00, // mov dword ptr [ebp-4], 4F1150
  207.             0x8B, 0x75, 0x08, // mov esi, [ebp+8]
  208.             0xFF, 0x55, 0xFC, // call [ebp-4]
  209.             0x5E, // pop esi
  210.             0x8B, 0xE5, // mov esp, ebp
  211.             0x5D, // pop ebp
  212.             0xC3 // retn
  213.         };
  214.  
  215.         private static readonly byte[] ScrAddVectorStub = new byte[]
  216.         {
  217.             0x55, // push ebp
  218.             0x8B, 0xEC, // mov ebp, esp
  219.             0x51, // push ecx
  220.             0x57, // push edi
  221.             0xC7, 0x45, 0xFC, 0xF0, 0x12, 0x4F, 0x00, // mov dword ptr [ebp-4], 4F12F0
  222.             0x8B, 0x7D, 0x08, // mov edi, [ebp+8]
  223.             0xFF, 0x55, 0xFC, // call [ebp-4]
  224.             0x5F, // pop edi
  225.             0x8B, 0xE5, // mov esp, ebp
  226.             0x5D, // pop ebp
  227.             0xC3 // retn
  228.         };
  229.  
  230.         private static readonly byte[] ScrNotifyNumStub = new byte[]
  231.         {
  232.             0x55, // push ebp
  233.             0x8B, 0xEC, // mov ebp, esp
  234.             0x51, // push ecx
  235.             0xC7, 0x45, 0xFC, 0x00, 0xFD, 0x4E, 0x00, // mov dword ptr [ebp-4], 4EFD00
  236.             0x8B, 0x45, 0x0C, // mov eax, [ebp+C]
  237.             0xFF, 0x75, 0x14, // push [ebp+14]
  238.             0xFF, 0x75, 0x10, // push [ebp+10]
  239.             0xFF, 0x75, 0x08, // push [ebp+8]
  240.             0xFF, 0x55, 0xFC, // call [ebp-4]
  241.             0x83, 0xC4, 0x0C, // add esp, C
  242.             0x8B, 0xE5, // mov esp, ebp
  243.             0x5D, // pop ebp
  244.             0xC3 // retn    
  245.         };
  246.  
  247.         private static byte[] VmExecuteHookStub = new byte[]
  248.         {
  249.             0x8B, 0x44, 0x24, 0x0C, // mov eax, [esp+0Ch]
  250.             0x50, // push eax
  251.             0x8B, 0x44, 0x24, 0x0C, // mov eax, [esp+0Ch]
  252.             0x50, // push eax
  253.             0x8B, 0x44, 0x24, 0x0C, // mov eax, [esp+0Ch]
  254.             0x50, // push eax
  255.             0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <handler>
  256.             0xFF, 0xD0, // call eax
  257.             0x83, 0xC4, 0x0C, // add esp, 0Ch
  258.             0x55, // push ebp
  259.             0x8B, 0xEC, // mov ebp, esp
  260.             0x83, 0xE4, 0xF8, // and esp, 0FFFFFFF8h
  261.             0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <dest>
  262.             0xFF, 0xE0, // jmp eax
  263.         };
  264.  
  265.         [DllImport("kernel32.dll", SetLastError = true)]
  266.         static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
  267.  
  268.         [DllImport("kernel32.dll", SetLastError = true)]
  269.         static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
  270.  
  271.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  272.         static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
  273.  
  274.         private const uint MEM_COMMIT = 0x1000;
  275.         private const uint MEM_RESERVE = 0x2000;
  276.         private const uint PAGE_EXECUTE_READWRITE = 0x40;
  277.         private const uint MB_ICONERROR = 0x10;
  278.  
  279.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  280.         private delegate void GameScriptNotifyHandlerDelegate(int entity, uint type, IntPtr variableStack);
  281.  
  282.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  283.         private delegate int ScrAddFloatDelegate(float value);
  284.  
  285.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  286.         private delegate int ScrAddIntegerDelegate(int value);
  287.  
  288.         [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  289.         private delegate void ScrAddStringDelegate(string value);
  290.  
  291.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  292.         private delegate int ScrGetEntityIdDelegate(int entityNum, int entityShift);
  293.  
  294.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  295.         private delegate void ScrAddObjectDelegate(int num);
  296.  
  297.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  298.         private delegate void ScrAddVectorDelegate(ref Vec3 vector);
  299.  
  300.         [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  301.         private delegate int ScrPrepareNotifyDelegate(string message, int zero, int messageLength);
  302.  
  303.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  304.         private delegate void ScrNotifyNumDelegate(int entNum, int entShift, int prepareResult, int paramCount);
  305.  
  306.         private static readonly IntPtr VirtualMachineExecuteAddress = (IntPtr)0x4EF610;
  307.         private static readonly IntPtr GameScriptStringTablePointer = (IntPtr)0x1C122A4;
  308.         private static readonly IntPtr GameScriptObjectTypeArray = (IntPtr)0x1D39804;
  309.         private static readonly IntPtr GameScriptObjectToEntityLo = (IntPtr)0x1D39802;
  310.  
  311.         private static readonly IntPtr ScrAddFloatAddress = (IntPtr)0x4F1070;
  312.         private static readonly IntPtr ScrAddIntegerAddress = (IntPtr)0x4F1020;
  313.         private static readonly IntPtr ScrGetEntityIdAddress = (IntPtr)0x4EA450;
  314.         private static readonly IntPtr ScrPrepareNotifyAddress = (IntPtr)0x4E7650;
  315.  
  316.         private static readonly List<ServerTimer> Timers = new List<ServerTimer>();
  317.         private static readonly Stopwatch Stopwatch = new Stopwatch();
  318.         private static readonly Dictionary<string, List<ServerNotify>> NotifyHandlers = new Dictionary<string, List<ServerNotify>>();
  319.  
  320.         private static ScrAddFloatDelegate _scrAddFloatFunc;
  321.         private static ScrAddIntegerDelegate _scrAddIntegerFunc;
  322.         private static ScrAddStringDelegate _scrAddStringFunc;
  323.         private static ScrGetEntityIdDelegate _scrGetEntityIdFunc;
  324.         private static ScrAddObjectDelegate _scrAddObjectFunc;
  325.         private static ScrAddVectorDelegate _scrAddVectorFunc;
  326.         private static ScrPrepareNotifyDelegate _scrPrepareNotifyFunc;
  327.         private static ScrNotifyNumDelegate _scrNotifyNumFunc;
  328.         private static GCHandle _gch;
  329.  
  330.         private static IntPtr _scrNotifyStack = IntPtr.Zero;
  331.         private static IntPtr _scrAddStringFuncAddress = IntPtr.Zero;
  332.         private static IntPtr _scrAddObjectFuncAddress = IntPtr.Zero;
  333.         private static IntPtr _scrAddVectorFuncAddress = IntPtr.Zero;
  334.         private static IntPtr _scrNotifyNumFuncAddress = IntPtr.Zero;
  335.  
  336.         static Timing()
  337.         {
  338.             HookGameScriptNotifyHandler();
  339.             Stopwatch.Start();
  340.         }
  341.  
  342.         private static void PushFloat(float value)
  343.         {
  344.             if (_scrAddFloatFunc == null)
  345.                 _scrAddFloatFunc = (ScrAddFloatDelegate)Marshal.GetDelegateForFunctionPointer(ScrAddFloatAddress, typeof(ScrAddFloatDelegate));
  346.  
  347.             _scrAddFloatFunc(value);
  348.         }
  349.  
  350.         private static void PushInteger(int value)
  351.         {
  352.             if (_scrAddIntegerFunc == null)
  353.                 _scrAddIntegerFunc = (ScrAddIntegerDelegate)Marshal.GetDelegateForFunctionPointer(ScrAddIntegerAddress, typeof(ScrAddIntegerDelegate));
  354.  
  355.             _scrAddIntegerFunc(value);
  356.         }
  357.  
  358.         private static void PushString(string value)
  359.         {
  360.             if (_scrAddStringFuncAddress == IntPtr.Zero)
  361.             {
  362.                 _scrAddStringFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)ScrAddStringStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  363.                 if (_scrAddStringFuncAddress == IntPtr.Zero)
  364.                     return;
  365.                 Marshal.Copy(ScrAddStringStub, 0, _scrAddStringFuncAddress, ScrAddStringStub.Length);
  366.                 _scrAddStringFunc = (ScrAddStringDelegate)Marshal.GetDelegateForFunctionPointer(_scrAddStringFuncAddress, typeof(ScrAddStringDelegate));
  367.             }
  368.  
  369.             _scrAddStringFunc(value);
  370.         }
  371.  
  372.         private static void PushEntity(int entityNum)
  373.         {
  374.             if (_scrGetEntityIdFunc == null)
  375.                 _scrGetEntityIdFunc = (ScrGetEntityIdDelegate)Marshal.GetDelegateForFunctionPointer(ScrGetEntityIdAddress, typeof(ScrGetEntityIdDelegate));
  376.  
  377.             if (_scrAddObjectFuncAddress == IntPtr.Zero)
  378.             {
  379.                 _scrAddObjectFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)ScrAddObjectStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  380.                 if (_scrAddObjectFuncAddress == IntPtr.Zero)
  381.                     return;
  382.                 Marshal.Copy(ScrAddObjectStub, 0, _scrAddObjectFuncAddress, ScrAddObjectStub.Length);
  383.                 _scrAddObjectFunc = (ScrAddObjectDelegate)Marshal.GetDelegateForFunctionPointer(_scrAddObjectFuncAddress, typeof(ScrAddObjectDelegate));
  384.             }
  385.  
  386.             int result = _scrGetEntityIdFunc(entityNum, entityNum >> 16);
  387.             _scrAddObjectFunc(result);
  388.         }
  389.  
  390.         private static void PushVector(Vector vector)
  391.         {
  392.             if (_scrAddVectorFuncAddress == IntPtr.Zero)
  393.             {
  394.                 _scrAddVectorFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)ScrAddVectorStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  395.                 if (_scrAddVectorFuncAddress == IntPtr.Zero)
  396.                     return;
  397.                 Marshal.Copy(ScrAddVectorStub, 0, _scrAddVectorFuncAddress, ScrAddVectorStub.Length);
  398.                 _scrAddVectorFunc = (ScrAddVectorDelegate)Marshal.GetDelegateForFunctionPointer(_scrAddVectorFuncAddress, typeof(ScrAddVectorDelegate));
  399.             }
  400.  
  401.             Vec3 vec = vector;
  402.             _scrAddVectorFunc(ref vec);
  403.         }
  404.  
  405.         public static void Notify(Entity entity, string message, params Parameter[] parameters)
  406.         {
  407.             Notify(entity.EntityNum, message, parameters);
  408.         }
  409.  
  410.         public static void Notify(ServerClient client, string message, params Parameter[] parameters)
  411.         {
  412.             Notify(client.ClientNum, message, parameters);
  413.         }
  414.  
  415.         private static void Notify(int entNum, string message, params Parameter[] parameters)
  416.         {
  417.             if (_scrPrepareNotifyFunc == null)
  418.                 _scrPrepareNotifyFunc = (ScrPrepareNotifyDelegate)Marshal.GetDelegateForFunctionPointer(ScrPrepareNotifyAddress, typeof(ScrPrepareNotifyDelegate));
  419.  
  420.             if (_scrNotifyNumFuncAddress == IntPtr.Zero)
  421.             {
  422.                 _scrNotifyNumFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)ScrNotifyNumStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  423.                 if (_scrNotifyNumFuncAddress == IntPtr.Zero)
  424.                     return;
  425.                 Marshal.Copy(ScrNotifyNumStub, 0, _scrNotifyNumFuncAddress, ScrNotifyNumStub.Length);
  426.                 _scrNotifyNumFunc = (ScrNotifyNumDelegate)Marshal.GetDelegateForFunctionPointer(_scrNotifyNumFuncAddress, typeof(ScrNotifyNumDelegate));
  427.             }
  428.  
  429.             Array.Reverse(parameters);
  430.  
  431.             foreach (var param in parameters)
  432.             {
  433.                 switch (param.Type)
  434.                 {
  435.                     case ParameterType.Float:
  436.                         PushFloat(Convert.ToSingle(param.Value));
  437.                         break;
  438.                     case ParameterType.Integer:
  439.                         PushInteger(Convert.ToInt32(param.Value));
  440.                         break;
  441.                     case ParameterType.String:
  442.                         PushString(Convert.ToString(param.Value));
  443.                         break;
  444.                     case ParameterType.Entity:
  445.                         PushEntity(Convert.ToInt32(param.Value));
  446.                         break;
  447.                     case ParameterType.Vector:
  448.                         PushVector((Vector)param.Value);
  449.                         break;
  450.                 }
  451.             }
  452.  
  453.             int result = _scrPrepareNotifyFunc(message, 0, message.Length + 1);
  454.             _scrNotifyNumFunc(entNum, entNum >> 16, result, parameters.Length);
  455.         }
  456.  
  457.         private static void HookGameScriptNotifyHandler()
  458.         {
  459.             var handler = new GameScriptNotifyHandlerDelegate(GameScriptNotifyHandlerHook);
  460.             _gch = GCHandle.Alloc(handler); // Prevent GC from relocating/freeing function.
  461.             var handlerAddress = Marshal.GetFunctionPointerForDelegate(handler);
  462.             var hookStub = VirtualAlloc(IntPtr.Zero, (UIntPtr)VmExecuteHookStub.Length, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  463.             BitConverter.GetBytes(handlerAddress.ToInt32()).CopyTo(VmExecuteHookStub, 16);
  464.             BitConverter.GetBytes(VirtualMachineExecuteAddress.ToInt32() + 6).CopyTo(VmExecuteHookStub, 32);
  465.             Marshal.Copy(VmExecuteHookStub, 0, hookStub, VmExecuteHookStub.Length);
  466.             SetJmpHook(VirtualMachineExecuteAddress, hookStub);
  467.         }
  468.  
  469.         private static void SetJmpHook(IntPtr original, IntPtr destination)
  470.         {
  471.             uint oldProtect;
  472.             VirtualProtect(original, (UIntPtr)5, PAGE_EXECUTE_READWRITE, out oldProtect);
  473.             var hook = new byte[5];
  474.             hook[0] = 0xE9;
  475.             BitConverter.GetBytes((destination.ToInt32() - original.ToInt32()) - 5).CopyTo(hook, 1);
  476.             Marshal.Copy(hook, 0, original, hook.Length);
  477.             VirtualProtect(original, (UIntPtr)5, oldProtect, out oldProtect);
  478.         }
  479.  
  480.         private static int GetObjectType(int @object)
  481.         {
  482.             return Marshal.ReadInt32(GameScriptObjectTypeArray, 8 * @object);
  483.         }
  484.  
  485.         private static IntPtr GetVariableStackValueFromIndex(int index)
  486.         {
  487.             return (IntPtr)(_scrNotifyStack.ToInt32() + -8 * index);
  488.         }
  489.  
  490.         private static object[] GetParameters(int argumentCount)
  491.         {
  492.             var param = new object[argumentCount];
  493.  
  494.             for (int i = 0; i < argumentCount; i++)
  495.             {
  496.                 var paramType = (ParameterType)Marshal.ReadInt32(GetVariableStackValueFromIndex(i), 4);
  497.                 object value = null;
  498.  
  499.                 switch (paramType)
  500.                 {
  501.                     case ParameterType.Integer:
  502.                         value = Marshal.ReadInt32(GetVariableStackValueFromIndex(i));
  503.                         break;
  504.                     case ParameterType.String:
  505.                         int stringIndex = Marshal.ReadInt16(GetVariableStackValueFromIndex(i));
  506.                         value = Marshal.PtrToStringAnsi((IntPtr)(Marshal.ReadInt32(GameScriptStringTablePointer) + 12 * stringIndex + 4));
  507.                         break;
  508.                     case ParameterType.Float:
  509.                         value = Marshal.PtrToStructure(GetVariableStackValueFromIndex(i), typeof(float));
  510.                         break;
  511.                     case ParameterType.Entity:
  512.                         int entityObjectId = Marshal.ReadInt32(GetVariableStackValueFromIndex(i));
  513.                         value = ScriptObjectIDToEntityNum(entityObjectId);
  514.                         break;
  515.                     case ParameterType.Vector:
  516.                         value = (Vector)(Vec3)Marshal.PtrToStructure(Marshal.ReadIntPtr(GetVariableStackValueFromIndex(i)), typeof(Vec3));
  517.                         break;
  518.                 }
  519.  
  520.                 param[i] = new Parameter(value, paramType);
  521.             }
  522.  
  523.             return param;
  524.         }
  525.  
  526.         private static int ScriptObjectIDToEntityNum(int scriptObjectId)
  527.         {
  528.             var loword = (uint)(Marshal.ReadInt16(GameScriptObjectToEntityLo, 8 * scriptObjectId));
  529.             var hiword = (uint)(Marshal.ReadInt32(GameScriptObjectTypeArray, 8 * scriptObjectId) >> 8);
  530.             return (int)((hiword << 16) | (loword & 0xFFFF));
  531.         }
  532.  
  533.         private static int GetNotifyArgumentCount()
  534.         {
  535.             int argumentCount = 0;
  536.  
  537.             if (Marshal.ReadInt32(_scrNotifyStack, 4) != 8)
  538.             {
  539.                 for (int i = _scrNotifyStack.ToInt32(); Marshal.ReadInt32((IntPtr)i, 4) != 8; i -= 8)
  540.                     argumentCount++;
  541.             }
  542.  
  543.             return argumentCount;
  544.         }
  545.  
  546.         private static void DispatchMessage(int targetEntityNum, string message)
  547.         {
  548.             foreach (var handler in NotifyHandlers[message])
  549.             {
  550.                 // Check if the handler specified a client or entity, if so, check the client num.
  551.                 if (handler.HasTarget && handler.TargetNum != targetEntityNum)
  552.                     continue;
  553.  
  554.                 var handlerParams = handler.Function.Method.GetParameters();
  555.  
  556.                 // Check if the handler function has parameters.
  557.                 if (handlerParams.Length > 0)
  558.                 {
  559.                     // Calculate the number of arguments.
  560.                     int argumentCount = GetNotifyArgumentCount();
  561.  
  562.                     // Get the parameters.
  563.                     object[] parameters = GetParameters(argumentCount);
  564.  
  565.                     // Fix the parameters if the user omitted some of them.
  566.                     var fixedParameters = new object[handlerParams.Length];
  567.                     Array.Copy(parameters, fixedParameters, fixedParameters.Length);
  568.  
  569.                     // Dynamically invoke the function.
  570.                     handler.Function.DynamicInvoke(fixedParameters);
  571.                 }
  572.                 else
  573.                 {
  574.                     // Perform a dynamic invoke with no arguments.
  575.                     handler.Function.DynamicInvoke();
  576.                 }
  577.             }
  578.         }
  579.  
  580.         private static void HandleNotifyEvent(int entity, uint type)
  581.         {
  582.             if (type == 0)
  583.                 return;
  584.  
  585.             // Get the current message address.
  586.             var messageAddress = (IntPtr)(Marshal.ReadInt32(GameScriptStringTablePointer) + 12 * type + 4);
  587.  
  588.             if (messageAddress == IntPtr.Zero)
  589.                 return;
  590.  
  591.             int targetEntityNum = -1;
  592.  
  593.             // Check if the script object type is an entity/client.
  594.             if (GetObjectType(entity) == 21)
  595.             {
  596.                 // Convert the script object ID to an entity/client num.
  597.                 targetEntityNum = ScriptObjectIDToEntityNum(entity);
  598.             }
  599.  
  600.             // Get the current message.
  601.             string message = Marshal.PtrToStringAnsi(messageAddress);
  602.  
  603.             // Check the message is valid and notify the handlers.
  604.             if (string.IsNullOrEmpty(message) || !NotifyHandlers.ContainsKey(message))
  605.                 return;
  606.  
  607.             try
  608.             {
  609.                 DispatchMessage(targetEntityNum, message);
  610.             }
  611.             catch (Exception ex)
  612.             {
  613.                 // Catch any errors and display it as a message box since there's no way to
  614.                 // log it without a plugin instance.
  615.                 MessageBox(IntPtr.Zero, ex.ToString(), "HandleNotifyEvent failed.", MB_ICONERROR);
  616.             }
  617.         }
  618.  
  619.         private static void GameScriptNotifyHandlerHook(int entity, uint type, IntPtr variableStack)
  620.         {
  621.             _scrNotifyStack = variableStack;
  622.             HandleNotifyEvent(entity, type);
  623.         }
  624.  
  625.         public static void OnInterval(int interval, ServerClient target, Func<bool> function)
  626.         {
  627.             Timers.Add(new ServerTimer { Interval = interval, Function = function, Target = target });
  628.         }
  629.  
  630.         public static void OnInterval(int interval, Func<bool> function)
  631.         {
  632.             Timers.Add(new ServerTimer { Interval = interval, Function = function });
  633.         }
  634.  
  635.         public static void AfterDelay(int delay, ServerClient target, Action action)
  636.         {
  637.             Timers.Add(new ServerTimer { Interval = -1, Time = Stopwatch.ElapsedMilliseconds + delay, Function = action, Target = target });
  638.         }
  639.  
  640.         public static void AfterDelay(int delay, Action action)
  641.         {
  642.             Timers.Add(new ServerTimer { Interval = -1, Time = Stopwatch.ElapsedMilliseconds + delay, Function = action });
  643.         }
  644.  
  645.         public static void ProcessFrame(List<ServerClient> clients)
  646.         {
  647.             var currentTime = Stopwatch.ElapsedMilliseconds;
  648.  
  649.             foreach (var timer in Timers.ToArray())
  650.             {
  651.                 if (currentTime < timer.Time)
  652.                     continue;
  653.  
  654.                 if (timer.Target != null && clients.FindIndex(sc => sc.XUID == timer.Target.XUID) == -1)
  655.                 {
  656.                     Timers.Remove(timer);
  657.                     continue;
  658.                 }
  659.  
  660.                 object returnValue = timer.Function.DynamicInvoke();
  661.  
  662.                 if (timer.Interval == -1 || timer.Function.Method.ReturnType == typeof(bool) && !(bool)returnValue)
  663.                 {
  664.                     Timers.Remove(timer);
  665.                 }
  666.                 else
  667.                 {
  668.                     timer.Time = currentTime + timer.Interval;
  669.                 }
  670.             }
  671.         }
  672.  
  673.         private static void OnNotify(string type, Delegate action, bool hasTarget, int targetNum)
  674.         {
  675.             var serverNotify = new ServerNotify { Function = action, HasTarget = hasTarget, TargetNum = targetNum };
  676.  
  677.             if (NotifyHandlers.ContainsKey(type))
  678.                 NotifyHandlers[type].Add(serverNotify);
  679.             else
  680.                 NotifyHandlers.Add(type, new List<ServerNotify>(new[] { serverNotify }));
  681.         }
  682.  
  683.         public static void OnNotify(string type, Action action)
  684.         {
  685.             OnNotify(type, action, false, -1);
  686.         }
  687.  
  688.         public static void OnNotify(string type, Action<Parameter> action)
  689.         {
  690.             OnNotify(type, action, false, -1);
  691.         }
  692.  
  693.         public static void OnNotify(string type, Action<Parameter, Parameter> action)
  694.         {
  695.             OnNotify(type, action, false, -1);
  696.         }
  697.  
  698.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter> action)
  699.         {
  700.             OnNotify(type, action, false, -1);
  701.         }
  702.  
  703.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter> action)
  704.         {
  705.             OnNotify(type, action, false, -1);
  706.         }
  707.  
  708.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter, Parameter> action)
  709.         {
  710.             OnNotify(type, action, false, -1);
  711.         }
  712.  
  713.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  714.         {
  715.             OnNotify(type, action, false, -1);
  716.         }
  717.  
  718.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  719.         {
  720.             OnNotify(type, action, false, -1);
  721.         }
  722.  
  723.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  724.         {
  725.             OnNotify(type, action, false, -1);
  726.         }
  727.  
  728.         public static void OnNotify(string type, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  729.         {
  730.             OnNotify(type, action, false, -1);
  731.         }
  732.  
  733.         public static void OnNotify(string type, ServerClient client, Action action)
  734.         {
  735.             OnNotify(type, action, true, client.ClientNum);
  736.         }
  737.  
  738.         public static void OnNotify(string type, ServerClient client, Action<Parameter> action)
  739.         {
  740.             OnNotify(type, action, true, client.ClientNum);
  741.         }
  742.  
  743.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter> action)
  744.         {
  745.             OnNotify(type, action, true, client.ClientNum);
  746.         }
  747.  
  748.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter> action)
  749.         {
  750.             OnNotify(type, action, true, client.ClientNum);
  751.         }
  752.  
  753.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter> action)
  754.         {
  755.             OnNotify(type, action, true, client.ClientNum);
  756.         }
  757.  
  758.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter, Parameter> action)
  759.         {
  760.             OnNotify(type, action, true, client.ClientNum);
  761.         }
  762.  
  763.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  764.         {
  765.             OnNotify(type, action, true, client.ClientNum);
  766.         }
  767.  
  768.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  769.         {
  770.             OnNotify(type, action, true, client.ClientNum);
  771.         }
  772.  
  773.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  774.         {
  775.             OnNotify(type, action, true, client.ClientNum);
  776.         }
  777.  
  778.         public static void OnNotify(string type, ServerClient client, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  779.         {
  780.             OnNotify(type, action, true, client.ClientNum);
  781.         }
  782.  
  783.         public static void OnNotify(string type, Entity entity, Action action)
  784.         {
  785.             OnNotify(type, action, true, entity.EntityNum);
  786.         }
  787.  
  788.         public static void OnNotify(string type, Entity entity, Action<Parameter> action)
  789.         {
  790.             OnNotify(type, action, true, entity.EntityNum);
  791.         }
  792.  
  793.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter> action)
  794.         {
  795.             OnNotify(type, action, true, entity.EntityNum);
  796.         }
  797.  
  798.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter> action)
  799.         {
  800.             OnNotify(type, action, true, entity.EntityNum);
  801.         }
  802.  
  803.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter> action)
  804.         {
  805.             OnNotify(type, action, true, entity.EntityNum);
  806.         }
  807.  
  808.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter, Parameter> action)
  809.         {
  810.             OnNotify(type, action, true, entity.EntityNum);
  811.         }
  812.  
  813.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  814.         {
  815.             OnNotify(type, action, true, entity.EntityNum);
  816.         }
  817.  
  818.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  819.         {
  820.             OnNotify(type, action, true, entity.EntityNum);
  821.         }
  822.  
  823.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  824.         {
  825.             OnNotify(type, action, true, entity.EntityNum);
  826.         }
  827.  
  828.         public static void OnNotify(string type, Entity entity, Action<Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter, Parameter> action)
  829.         {
  830.             OnNotify(type, action, true, entity.EntityNum);
  831.         }
  832.     }
  833. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement