private static T FindOrLoadObject <T>(string pathName) where T : UObject { if (typeof(T) == typeof(UPackage)) { return(FindOrLoadPackage(pathName) as T); } // If there is no dot, add a dot and repeat the object name. int packageDelimPos = pathName.IndexOf('.'); if (packageDelimPos == -1) { int objectNameStart = pathName.LastIndexOf('/'); if (objectNameStart != -1) { pathName += "." + pathName.Substring(objectNameStart + 1); } } UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { unrealClass.GetDefaultObject();// force the CDO to be created if it hasn't already T obj = UObject.LoadObject <T>(null, pathName); if (obj != null) { obj.AddToRoot(); } return(obj); } return(null); }
public static unsafe void HackVTable(UObject obj) { // This will swap out the vtable entry and store the old one in our managed UClass if (!Native_UObjectBaseUtility.IsA(obj.Address, Runtime.Classes.UClass)) { UClass unrealClass = obj.GetClass(); if (unrealClass.VTableOriginalFunctions == null) { IntPtr *vtable = *(IntPtr **)obj.Address; unrealClass.VTableOriginalFunctions = new Dictionary <int, UClass.VTableOriginalFunc>(); foreach (FunctionRedirect redirect in vtableRedirects) { if (!Native_UObjectBaseUtility.IsA(obj.Address, redirect.Class)) { continue; } IntPtr originalFunctionAddress = vtable[redirect.VTableIndex]; if (originalFunctionAddress != redirect.NativeCallback) { IntPtr originalOwnerClassAddress = FindOriginalVTableOwner( redirect.Class, unrealClass.Address, originalFunctionAddress, redirect.VTableIndex); if (originalOwnerClassAddress != unrealClass.Address) { UClass originalOwnerClass = GCHelper.Find <UClass>(originalOwnerClassAddress); if (originalOwnerClass.VTableOriginalFunctions == null) { HackVTable(originalOwnerClass.GetDefaultObject()); } } IntPtr pageAlignedPtr = FMemory.PageAlignPointer((IntPtr)(&vtable[redirect.VTableIndex])); FMemory.PageProtect(pageAlignedPtr, (IntPtr)IntPtr.Size, true, true); *(&vtable[redirect.VTableIndex]) = redirect.NativeCallback; } else { // The VTable has already been swapped out. Find the original function address. UClass superClass = unrealClass; while ((superClass = superClass.GetSuperClass()) != null && superClass.VTableOriginalFunctions == null) { } Debug.Assert(superClass != null && superClass.VTableOriginalFunctions != null && superClass.VTableOriginalFunctions.ContainsKey(redirect.VTableIndex)); originalFunctionAddress = superClass.VTableOriginalFunctions[redirect.VTableIndex].FuncAddress; } unrealClass.VTableOriginalFunctions.Add(redirect.VTableIndex, new UClass.VTableOriginalFunc(originalFunctionAddress)); } } } }
/// <summary> /// Get default object of a class. /// </summary> public static T GetDefault <T>() where T : UObject { UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { return(unrealClass.GetDefaultObject() as T); } return(null); }
/// <summary> /// Get the CDO if we are referencing a valid class /// </summary> /// <returns>the CDO, or NULL</returns> public T GetDefaultObject() { UClass unrealClass = Value; if (unrealClass != null) { return(unrealClass.GetDefaultObject() as T); } return(null); }
/// <summary> /// Gets the default object of a class. /// </summary> /// <typeparam name="T">The object type</typeparam> /// <param name="unrealClass">The class to get the CDO for.</param> /// <returns>Class default object (CDO).</returns> public static T GetDefault <T>(UClass unrealClass) where T : UObject { if (unrealClass != null && unrealClass.IsA <T>()) { UObject defaultObject = unrealClass.GetDefaultObject(); if (defaultObject.IsA <T>()) { return(defaultObject as T); } } return(null); }