/// <summary> /// Generates a wrapper function for an individual virtual function table entry /// in a virtual function table. /// </summary> /// <typeparam name="TFunction">Delegate type marked with complete ReloadedFunction Attribute/X64 Reloaded Function Attribute that defines the individual function properties.</typeparam> /// <param name="tableEntry">The individual Virtual function table entry to create a wrapper function for.</param> /// <returns>Delegate to assign back to ReloadedFunction marked game function.</returns> public static TFunction CreateWrapperFunction <TFunction>(this VirtualFunctionTable.TableEntry tableEntry) { // Create X86/X64 wrapper conditionally. if (IntPtr.Size == 4) { return(FunctionWrapper.CreateWrapperFunction <TFunction>((long)tableEntry.FunctionPointer)); } if (IntPtr.Size == 8) { return(X64FunctionWrapper.CreateWrapperFunction <TFunction>((long)tableEntry.FunctionPointer)); } // Null case return(default(TFunction)); }
/// <summary> /// Retrieves an instance of the delegate which can be used to call the function behind the function pointer. /// </summary> /// <returns>False if the pointer to call is invalid, else true.</returns> public TDelegate GetDelegate() { // Return false if pointer points to invalid address. if (FunctionAddress == IntPtr.Zero) { return(null); } // Get the pointer to the function. // Our pointer is dereferenced here, see "Pointer" Property. IntPtr functionPointer = FunctionAddress; // [Performance] Fast return if the pointer is the same as the last value. if (functionPointer == _lastFunctionPointer) { return(_delegate); } // Try to get the cached function wrapper. if (_methodCache.TryGetValue(functionPointer, out var cachedDelegate)) { return(cachedDelegate); } // Cached delegate not found. else { // Create wrapper if nonexisting. if (IntPtr.Size == 4) { _delegate = FunctionWrapper.CreateWrapperFunction <TDelegate>((long)functionPointer); } else { _delegate = X64FunctionWrapper.CreateWrapperFunction <TDelegate>((long)functionPointer); } // Cache the function wrapper. _methodCache[functionPointer] = _delegate; // Cache last function pointer. _lastFunctionPointer = functionPointer; // Return new Delegate return(_delegate); } }