diff --git a/Plugins/UE5Coro/Source/UE5Coro/Private/Generator.cpp b/Plugins/UE5Coro/Source/UE5Coro/Private/Generator.cpp index 7de780d..f463832 100644 --- a/Plugins/UE5Coro/Source/UE5Coro/Private/Generator.cpp +++ b/Plugins/UE5Coro/Source/UE5Coro/Private/Generator.cpp @@ -36,7 +36,11 @@ using namespace UE5Coro::Private; void FGeneratorPromise::unhandled_exception() { #if PLATFORM_EXCEPTIONS_DISABLED - check(!"Exceptions are not supported"); + // Hitting this can be a result of the generator itself invoking undefined + // behavior, e.g., by using a bad pointer. + // On Windows, SEH exceptions can end up here if C++ exceptions are disabled. + // If this hinders debugging, feel free to remove it! + checkSlow(!"Unhandled exception from generator!"); #else throw; #endif diff --git a/Plugins/UE5Coro/Source/UE5Coro/Private/Promise.cpp b/Plugins/UE5Coro/Source/UE5Coro/Private/Promise.cpp index a4f1429..5bc72f7 100644 --- a/Plugins/UE5Coro/Source/UE5Coro/Private/Promise.cpp +++ b/Plugins/UE5Coro/Source/UE5Coro/Private/Promise.cpp @@ -166,7 +166,11 @@ void FPromise::AddContinuation(std::function Fn) void FPromise::unhandled_exception() { #if PLATFORM_EXCEPTIONS_DISABLED - check(!"Exceptions are not supported"); + // Hitting this can be a result of the coroutine itself invoking undefined + // behavior, e.g., by using a bad pointer. + // On Windows, SEH exceptions can end up here if C++ exceptions are disabled. + // If this hinders debugging, feel free to remove it! + checkSlow(!"Unhandled exception from coroutine!"); #else bUnhandledException = true; throw; diff --git a/Plugins/UE5Coro/UE5Coro.uplugin b/Plugins/UE5Coro/UE5Coro.uplugin index 83e9182..2de23c5 100644 --- a/Plugins/UE5Coro/UE5Coro.uplugin +++ b/Plugins/UE5Coro/UE5Coro.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "1.10.2-ue4", + "VersionName": "1.10.3-ue4", "FriendlyName": "UE5Coro (UE4 edition)", "Description": "C++20 coroutine implementation for Unreal Engine 4", "Category": "Programming", diff --git a/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Private/UE5CoroGameplayAbility.cpp b/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Private/UE5CoroGameplayAbility.cpp index 9b0fb51..d3953fc 100644 --- a/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Private/UE5CoroGameplayAbility.cpp +++ b/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Private/UE5CoroGameplayAbility.cpp @@ -37,6 +37,7 @@ using namespace UE5Coro; using namespace UE5Coro::Private; +using namespace UE5CoroGAS::Private; namespace { @@ -53,10 +54,30 @@ bool IsTemplate(UObject* Object) } } +namespace UE5CoroGAS::Private +{ +struct FStrictPredictionKey : FPredictionKey +{ + FStrictPredictionKey(const FPredictionKey& Key) noexcept + : FPredictionKey(Key) { } + + bool operator==(const FStrictPredictionKey& Other) const noexcept + { + return FPredictionKey::operator==(Other) && Base == Other.Base; + } +}; + +int32 GetTypeHash(const FStrictPredictionKey& Key) noexcept // ADL +{ + return GetTypeHash(static_cast(Key)) ^ + Key.Base << 16; +} +} + UUE5CoroGameplayAbility::UUE5CoroGameplayAbility() { if (::IsTemplate(this)) - Activations = new TMap*>; + Activations = new TMap*>; else Activations = GetDefault(GetClass())->Activations; checkf(Activations, TEXT("Internal error: non-template object before CDO")); diff --git a/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Public/UE5CoroGAS/UE5CoroGameplayAbility.h b/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Public/UE5CoroGAS/UE5CoroGameplayAbility.h index a1aaf46..2b082a9 100644 --- a/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Public/UE5CoroGAS/UE5CoroGameplayAbility.h +++ b/Plugins/UE5CoroGAS/Source/UE5CoroGAS/Public/UE5CoroGAS/UE5CoroGameplayAbility.h @@ -37,6 +37,8 @@ #include "UE5CoroGAS/AbilityPromises.h" #include "UE5CoroGameplayAbility.generated.h" +namespace UE5CoroGAS::Private { struct FStrictPredictionKey; } + /** * Usage summary: * - Override ExecuteAbility instead of ActivateAbility @@ -52,7 +54,8 @@ class UE5COROGAS_API UUE5CoroGameplayAbility : public UGameplayAbility // One shared per class to support every instancing policy including derived // classes changing their minds at runtime. The real one is on the CDO. - TMap*>* Activations; + TMap*>* Activations; public: UUE5CoroGameplayAbility(); diff --git a/Plugins/UE5CoroGAS/UE5CoroGAS.uplugin b/Plugins/UE5CoroGAS/UE5CoroGAS.uplugin index 231d6ad..b2dde3c 100644 --- a/Plugins/UE5CoroGAS/UE5CoroGAS.uplugin +++ b/Plugins/UE5CoroGAS/UE5CoroGAS.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 1, - "VersionName": "1.10.2-ue4", + "VersionName": "1.10.3-ue4", "FriendlyName": "UE5Coro – Gameplay Ability System (UE4 edition)", "Description": "C++20 coroutines for GAS", "Category": "Programming",