From e7467cd6d017c5c073ee4aee02433ad050099fc5 Mon Sep 17 00:00:00 2001 From: Iain Mckay Date: Fri, 2 Aug 2019 16:25:01 +0200 Subject: [PATCH] Adds UGameInstance::Init --- .../CoreUObject/UObject.cs | 5 +++ .../Engine/GameInstance_Injected.cs | 26 ++++++++++++ .../Internal/VTableHacks.cs | 19 +++++++++ .../Internal/Export_VTableHacks.h | 2 + Source/USharp/Private/VTableHacks.h | 40 +++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/InjectedClasses/Engine/GameInstance_Injected.cs diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/UObject.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/UObject.cs index 5606e22..f99b208 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/UObject.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/UObject.cs @@ -697,6 +697,11 @@ internal virtual void GetActorEyesViewPointInternal(out FVector OutLocation, out OutRotation = default(FRotator); } + internal virtual void InitInternal() + { + // This is eventually implemented in injected classes + } + /// /// Looks for a given function name /// diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/InjectedClasses/Engine/GameInstance_Injected.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/InjectedClasses/Engine/GameInstance_Injected.cs new file mode 100644 index 0000000..2a2fc68 --- /dev/null +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/InjectedClasses/Engine/GameInstance_Injected.cs @@ -0,0 +1,26 @@ +using System; +using UnrealEngine.Engine; +using UnrealEngine.Runtime; +using UnrealEngine.Runtime.Native; + +namespace UnrealEngine.Engine +{ + public partial class UGameInstance : UObject + { + private VTableHacks.CachedFunctionRedirect initializeRedirect; + internal override void InitInternal() + { + Init(); + } + + /// + /// Allow custom GameInstances an opportunity to set up what it needs. + /// + public virtual void Init() + { + initializeRedirect + .Resolve(VTableHacks.GameInstanceInit, this) + .Invoke(Address); + } + } +} diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/VTableHacks.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/VTableHacks.cs index 9417fe3..246b8e0 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/VTableHacks.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/VTableHacks.cs @@ -19,6 +19,7 @@ private static void AddVTableRedirects() IntPtr actorClass = Runtime.Classes.AActor; IntPtr actorComponentClass = Runtime.Classes.UActorComponent; IntPtr playerControllerClass = Runtime.Classes.APlayerController; + IntPtr gameInstanceClass = Runtime.Classes.UGameInstance; GetLifetimeReplicatedProps = AddVTableRedirect(objectClass, "DummyRepProps", new GetLifetimeReplicatedPropsDel(OnGetLifetimeReplicatedProps)); PawnSetupPlayerInputComponent = AddVTableRedirect(pawnClass, "DummySetupPlayerInput", new PawnSetupPlayerInputComponentDel(OnPawnSetupPlayerInputComponent)); @@ -29,6 +30,7 @@ private static void AddVTableRedirects() ActorComponentEndPlay = AddVTableRedirect(actorComponentClass, "DummyActorComponentEndPlay", new EndPlayDel(OnActorComponentEndPlay)); PlayerControllerSetupInputComponent = AddVTableRedirect(playerControllerClass, "DummyPlayerControllerSetupInputComponent", new PlayerControllerSetupInputComponentDel(OnPlayerControllerSetupInputComponent)); PlayerControllerUpdateRotation = AddVTableRedirect(playerControllerClass, "DummyPlayerControllerUpdateRotation", new PlayerControllerUpdateRotationDel(OnPlayerControllerUpdateRotation)); + GameInstanceInit = AddVTableRedirect(gameInstanceClass, "DummyGameInstanceInit", new GameInstanceInitDel(OnGameInstanceInit)); } private static void LogCallbackException(string functionName, Exception e) @@ -186,6 +188,23 @@ private static void OnPlayerControllerUpdateRotation(IntPtr address, float delta } } + public static FunctionRedirect GameInstanceInit { get; private set; } + delegate void GameInstanceInitDel(IntPtr address); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate void GameInstanceInitDel_ThisCall(IntPtr address); + private static void OnGameInstanceInit(IntPtr address) + { + try + { + UObject obj = GCHelper.Find(address); + obj.InitInternal(); + } + catch (Exception e) + { + LogCallbackException(nameof(OnGameInstanceInit), e); + } + } + //////////////////////////////////////////////////////////////////////////////////////// // Add vtable redirects above this line //////////////////////////////////////////////////////////////////////////////////////// diff --git a/Source/USharp/Private/ExportedFunctions/Internal/Export_VTableHacks.h b/Source/USharp/Private/ExportedFunctions/Internal/Export_VTableHacks.h index b23db70..8a3d736 100644 --- a/Source/USharp/Private/ExportedFunctions/Internal/Export_VTableHacks.h +++ b/Source/USharp/Private/ExportedFunctions/Internal/Export_VTableHacks.h @@ -9,6 +9,7 @@ ActorComponentBeginPlayCallbackSig ActorComponentBeginPlayCallback = nullptr; ActorComponentEndPlayCallbackSig ActorComponentEndPlayCallback = nullptr; PlayerControllerSetupInputComponentCallbackSig PlayerControllerSetupInputComponentCallback = nullptr; PlayerControllerUpdateRotationCallbackSig PlayerControllerUpdateRotationCallback = nullptr; +GameInstanceInitCallbackSig GameInstanceInitCallback = nullptr; TMap DummyNames; CSEXPORT void CSCONV Export_VTableHacks_Set_VTableCallback(const FString& DummyName, void* Callback) @@ -25,6 +26,7 @@ CSEXPORT void CSCONV Export_VTableHacks_Set_VTableCallback(const FString& DummyN DummyNames.Add(TEXT("DummyActorComponentEndPlay"), (void**)&ActorComponentEndPlayCallback); DummyNames.Add(TEXT("DummyPlayerControllerSetupInputComponent"), (void**)&PlayerControllerSetupInputComponentCallback); DummyNames.Add(TEXT("DummyPlayerControllerUpdateRotation"), (void**)&PlayerControllerUpdateRotationCallback); + DummyNames.Add(TEXT("DummyGameInstanceInit"), (void**)&GameInstanceInitCallback); } void*** Element = DummyNames.Find(DummyName); diff --git a/Source/USharp/Private/VTableHacks.h b/Source/USharp/Private/VTableHacks.h index 2b3af28..61272f7 100644 --- a/Source/USharp/Private/VTableHacks.h +++ b/Source/USharp/Private/VTableHacks.h @@ -428,4 +428,44 @@ class USHARP_API ADummyPlayerControllerUpdateRotation3 : public ADummyPlayerCont { FMsg::Logf("", 0, FName(TEXT("USharp")), ELogVerbosity::Log, TEXT("ADummyPlayerControllerUpdateRotation3-UpdateRotation")); } +}; + +///////////////////////////////////////////////////////////////////////////// +// UGameInstance::Init +///////////////////////////////////////////////////////////////////////////// + +typedef void(CSCONV *GameInstanceInitCallbackSig)(UGameInstance* Obj); +extern GameInstanceInitCallbackSig GameInstanceInitCallback; + +UCLASS(NotBlueprintable, NotBlueprintType) +class USHARP_API UDummyGameInstanceInit1 : public UGameInstance +{ + GENERATED_BODY() + +public: + virtual void Init() override + { + if (GameInstanceInitCallback != nullptr) + { + GameInstanceInitCallback(this); + } + } +}; + +UCLASS(NotBlueprintable, NotBlueprintType) +class USHARP_API UDummyGameInstanceInit2 : public UDummyGameInstanceInit1 +{ + GENERATED_BODY() +}; + +UCLASS(NotBlueprintable, NotBlueprintType) +class USHARP_API UDummyGameInstanceInit3 : public UDummyGameInstanceInit2 +{ + GENERATED_BODY() + +public: + virtual void Init() override + { + FMsg::Logf("", 0, FName(TEXT("USharp")), ELogVerbosity::Log, TEXT("UDummyGameInstanceInit3-Init")); + } }; \ No newline at end of file