From f9a40014f0772e2ceace211757d4ba3edf12fd4e Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 16 Oct 2025 12:27:00 +0100 Subject: [PATCH 01/10] [OF-1736] feat: Expose AsyncCall to DuplicateSpace --- Library/include/CSP/Common/NetworkEventData.h | 15 +++ .../include/CSP/Multiplayer/NetworkEventBus.h | 7 +- .../include/CSP/Systems/Spaces/SpaceSystem.h | 43 ++++++- Library/src/Multiplayer/NetworkEventBus.cpp | 2 + .../Multiplayer/NetworkEventSerialisation.cpp | 13 ++ .../Multiplayer/NetworkEventSerialisation.h | 5 + Library/src/Systems/Spaces/SpaceSystem.cpp | 116 ++++++++++++++---- Library/src/Systems/SystemsManager.cpp | 2 +- Tests/src/PublicAPITests/SpaceSystemTests.cpp | 105 ++++++++++++++++ 9 files changed, 279 insertions(+), 29 deletions(-) diff --git a/Library/include/CSP/Common/NetworkEventData.h b/Library/include/CSP/Common/NetworkEventData.h index ce8fa9bd6..ef227b88a 100644 --- a/Library/include/CSP/Common/NetworkEventData.h +++ b/Library/include/CSP/Common/NetworkEventData.h @@ -152,6 +152,21 @@ class CSP_API SequenceChangedNetworkEventData : public NetworkEventData csp::common::Optional HotspotData = nullptr; }; +class CSP_API AsyncCallCompletedEventData : public NetworkEventData +{ +public: + /// @brief The name of the async operation that has been completed. + csp::common::String OperationName; + + /// @brief An Id related to the async operation that has been completed. + /// This could for example be a groud Id, if this were an async duplicate group operation. + csp::common::String ReferenceId; + + /// @brief The type that the Id represents. + /// In the previous example this would be "GroupId". + csp::common::String ReferenceType; +}; + // TODO, this should not be here. It's not an event data, it's just a type for a callback used in the AssetSystem. // The annoyance is that ChangeType is defined for these EventDatas, gotta break that at some point. // I don't really know where this should go at the moment. diff --git a/Library/include/CSP/Multiplayer/NetworkEventBus.h b/Library/include/CSP/Multiplayer/NetworkEventBus.h index 359bc01e7..feeb5ed71 100644 --- a/Library/include/CSP/Multiplayer/NetworkEventBus.h +++ b/Library/include/CSP/Multiplayer/NetworkEventBus.h @@ -199,8 +199,9 @@ class CSP_API NetworkEventBus SequenceChanged, // Unpacks to SequenceChangedNetworkEventData or SequenceHotspotChangedEventData (Better if there was a seperate event for // each.) AccessControlChanged, // Unpacks to AccessControlChangedNetworkEventData - GeneralPurposeEvent // Unpacks to NetworkEventData (Base type). An external event unknown to us that may have been registered with any string - // value. + GeneralPurposeEvent, // Unpacks to NetworkEventData (Base type). An external event unknown to us that may have been registered with any string + // value. + AsyncCallCompleted // Unpacks to AsyncCallCompletedEventData }; static NetworkEvent NetworkEventFromString(const csp::common::String& EventString); @@ -223,7 +224,7 @@ class CSP_API NetworkEventBus static inline const std::unordered_map CustomDeserializationEventMap { { NetworkEvent::AssetDetailBlobChanged, "AssetDetailBlobChanged" }, { NetworkEvent::Conversation, "Conversation" }, { NetworkEvent::SequenceChanged, "SequenceChanged" }, - { NetworkEvent::AccessControlChanged, "AccessControlChanged" } }; + { NetworkEvent::AccessControlChanged, "AccessControlChanged" }, { NetworkEvent::AsyncCallCompleted, "AsyncCallCompleted" } }; CSP_END_IGNORE diff --git a/Library/include/CSP/Systems/Spaces/SpaceSystem.h b/Library/include/CSP/Systems/Spaces/SpaceSystem.h index edc886f49..8c8f98baa 100644 --- a/Library/include/CSP/Systems/Spaces/SpaceSystem.h +++ b/Library/include/CSP/Systems/Spaces/SpaceSystem.h @@ -343,22 +343,55 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase /// @param Callback NullResultCallback : callback when asynchronous task finishes CSP_ASYNC_RESULT void DeleteSpaceGeoLocation(const csp::common::String& SpaceId, NullResultCallback Callback); - /// @brief Duplicate an existing space and assign it to the current user + /// @brief Duplicate an existing space and assign it to the current user. + /// This is a synchronous operation and can have a high execution time for complex spaces. + /// \deprecated Use DuplicateSpaceAsync() instead. This method performs a synchronous duplication of a Space which can timeout and fail for + /// complex Spaces or if the backend services are under excessive load. /// @param SpaceId csp::common::String : Id of the space to duplicate. /// @param NewName csp::common::String : A unique name for the duplicated space. /// @param NewAttributes csp::systems::SpaceAttributes : Attributes to apply to the duplicated space. - /// @param MemberGroupIds csp::common::Array : An optional array of group (space) IDs to copy users from. + /// @param MemberGroupIds csp::common::Array : An optional array of group (space) IDs. Members of these groups will be added + /// to the duplicated space with the same roles. /// @param ShallowCopy bool : If true, the duplicated space will reference the assets of the original space. Otherwise, all assets will be /// duplicated. - /// @param Callback NullResultCallback : callback when asynchronous task finishes + /// @param Callback SpaceResultCallback : callback when asynchronous task finishes. CSP_ASYNC_RESULT void DuplicateSpace(const csp::common::String& SpaceId, const csp::common::String& NewName, SpaceAttributes NewAttributes, const csp::common::Optional>& MemberGroupIds, bool ShallowCopy, SpaceResultCallback Callback); + /// @brief Duplicate an existing space and assign it to the current user. + /// This is an asynchronous operation. Please subcribe to the AsyncCallCompletedCallback via @ref SpaceSystem::SetAsyncCallCompletedCallback() to + /// be notified when the duplication operation is complete. + /// @param SpaceId csp::common::String : Id of the space to duplicate. + /// @param NewName csp::common::String : A unique name for the duplicated space. + /// @param NewAttributes csp::systems::SpaceAttributes : Attributes to apply to the duplicated space. + /// @param MemberGroupIds csp::common::Array : An optional array of group (space) IDs. Members of these groups will be added + /// to the duplicated space with the same roles. + /// @param ShallowCopy bool : If true, the duplicated space will reference the assets of the original space. Otherwise, all assets will be + /// duplicated. + /// @param Callback NullResultCallback : callback when asynchronous task is successfully received by the backend services. + CSP_ASYNC_RESULT void DuplicateSpaceAsync(const csp::common::String& SpaceId, const csp::common::String& NewName, SpaceAttributes NewAttributes, + const csp::common::Optional>& MemberGroupIds, bool ShallowCopy, NullResultCallback Callback); + ///@} + /// @brief The callback for receiving an alert when an async operation is completed. + /// Currently this callback is only being used for the DuplicateSpaceAsync operation. + /// A callback can be set via @ref SpaceSystem::SetAsyncCallCompletedCallback(). + typedef std::function AsyncCallCompletedCallbackHandler; + + /// @brief Sets a callback for the async call completed event. Triggered when an async call to DuplicateSpace is completed. + /// @param Callback AsyncCallCompletedCallbackHandler: Callback to receive data concerning the Space duplication. + CSP_EVENT void SetAsyncCallCompletedCallback(AsyncCallCompletedCallbackHandler Callback); + + /// @brief Deserialises the AsyncCallCompleted event values. + /// The AsyncCallCompletedEventData will contain the name of the operation ("DuplicateSpaceAsync"), the reference Id of the newly created Space as + /// well as the reference type ("GroupId"). + /// @param EventValues std::vector : event values to deserialise + CSP_NO_EXPORT void OnAsyncCallCompletedEvent(const csp::common::NetworkEventData& NetworkEventData); + private: SpaceSystem(); // This constructor is only provided to appease the wrapper generator and should not be used - SpaceSystem(csp::web::WebClient* InWebClient, csp::common::LogSystem& LogSystem); + SpaceSystem(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem); ~SpaceSystem(); // Space Metadata @@ -376,6 +409,8 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase void GetSpaceGeoLocationInternal(const csp::common::String& SpaceId, SpaceGeoLocationResultCallback Callback); + AsyncCallCompletedCallbackHandler AsyncCallCompletedCallback; + // CreateSpace Continuations async::task CreateSpaceGroupInfo(const csp::common::String& Name, const csp::common::String& Description, SpaceAttributes Attributes, const csp::common::Optional>& Tags); diff --git a/Library/src/Multiplayer/NetworkEventBus.cpp b/Library/src/Multiplayer/NetworkEventBus.cpp index 53dc339df..da68a33da 100644 --- a/Library/src/Multiplayer/NetworkEventBus.cpp +++ b/Library/src/Multiplayer/NetworkEventBus.cpp @@ -262,6 +262,8 @@ std::unique_ptr NetworkEventBus::DeserialiseForEv return std::make_unique(csp::multiplayer::DeserializeAccessControlChangedEvent(EventValues, LogSystem)); case NetworkEvent::GeneralPurposeEvent: return std::make_unique(csp::multiplayer::DeserializeGeneralPurposeEvent(EventValues, LogSystem)); + case NetworkEvent::AsyncCallCompleted: + return std::make_unique(csp::multiplayer::DeserializeAsyncCallCompletedEvent(EventValues, LogSystem)); default: throw std::invalid_argument( fmt::format("DeserialiseForEventType: unknown enum value {}", static_cast>(EventType))); diff --git a/Library/src/Multiplayer/NetworkEventSerialisation.cpp b/Library/src/Multiplayer/NetworkEventSerialisation.cpp index b5044edbd..07df91c8c 100644 --- a/Library/src/Multiplayer/NetworkEventSerialisation.cpp +++ b/Library/src/Multiplayer/NetworkEventSerialisation.cpp @@ -418,4 +418,17 @@ csp::common::SequenceChangedNetworkEventData DeserializeSequenceHotspotChangedEv return ParsedEvent; } + +csp::common::AsyncCallCompletedEventData DeserializeAsyncCallCompletedEvent( + const std::vector& EventValues, csp::common::LogSystem& LogSystem) +{ + csp::common::AsyncCallCompletedEventData ParsedEvent {}; + PopulateCommonEventData(EventValues, ParsedEvent, LogSystem); + + ParsedEvent.OperationName = ParsedEvent.EventValues[0].GetString(); + ParsedEvent.ReferenceId = ParsedEvent.EventValues[1].GetString(); + ParsedEvent.ReferenceType = ParsedEvent.EventValues[2].GetString(); + + return ParsedEvent; +} } diff --git a/Library/src/Multiplayer/NetworkEventSerialisation.h b/Library/src/Multiplayer/NetworkEventSerialisation.h index 4686d3a91..80a3bf031 100644 --- a/Library/src/Multiplayer/NetworkEventSerialisation.h +++ b/Library/src/Multiplayer/NetworkEventSerialisation.h @@ -60,4 +60,9 @@ csp::common::SequenceChangedNetworkEventData DeserializeSequenceChangedEvent( csp::common::SequenceChangedNetworkEventData DeserializeSequenceHotspotChangedEvent( const std::vector& EventValues, csp::common::LogSystem& LogSystem); +// Specialized deserializataion for events triggered when an async call completes. +// Some methods take an AsyncCall boolean argument that allows the operation to be completed asyncronously rather than syncronously. +csp::common::AsyncCallCompletedEventData DeserializeAsyncCallCompletedEvent( + const std::vector& EventValues, csp::common::LogSystem& LogSystem); + } // namespace csp::multiplayer diff --git a/Library/src/Systems/Spaces/SpaceSystem.cpp b/Library/src/Systems/Spaces/SpaceSystem.cpp index 4dbc0ad42..80d43a378 100644 --- a/Library/src/Systems/Spaces/SpaceSystem.cpp +++ b/Library/src/Systems/Spaces/SpaceSystem.cpp @@ -58,6 +58,36 @@ namespace constexpr const int MAX_SPACES_RESULTS = 100; +// Construct a new DuplicateSpaceOptions dto request object. This function is called by both DuplicateSpace and DuplicateSpaceAsync methods. +// The only difference is in the value they pass for the AsyncCall parameter. +std::shared_ptr ConstructDuplicateSpaceOptions(const String& SpaceId, const String& NewName, + csp::systems::SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, bool AsyncCall) +{ + auto Request = std::make_shared(); + Request->SetSpaceId(SpaceId); + Request->SetNewGroupOwnerId(csp::systems::SystemsManager::Get().GetUserSystem()->GetLoginState().UserId); + Request->SetNewUniqueName(NewName); + Request->SetDiscoverable(HasFlag(NewAttributes, csp::systems::SpaceAttributes::IsDiscoverable)); + Request->SetRequiresInvite(HasFlag(NewAttributes, csp::systems::SpaceAttributes::RequiresInvite)); + Request->SetShallowCopy(ShallowCopy); + Request->SetAsyncCall(AsyncCall); + + if (MemberGroupIds.HasValue()) + { + std::vector GroupIds; + GroupIds.reserve(MemberGroupIds->Size()); + + for (size_t i = 0; i < MemberGroupIds->Size(); ++i) + { + GroupIds.push_back(MemberGroupIds->operator[](i)); + } + + Request->SetMemberGroupIds(GroupIds); + } + + return Request; +} + } // namespace namespace csp::systems @@ -70,15 +100,24 @@ SpaceSystem::SpaceSystem() { } -SpaceSystem::SpaceSystem(csp::web::WebClient* InWebClient, csp::common::LogSystem& LogSystem) - : SystemBase(InWebClient, nullptr, &LogSystem) +SpaceSystem::SpaceSystem(csp::web::WebClient* InWebClient, multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem) + : SystemBase(InWebClient, InEventBus, &LogSystem) , CurrentSpace() { GroupAPI = new chs::GroupApi(InWebClient); SpaceAPI = new chsaggregation::SpaceApi(InWebClient); } -SpaceSystem::~SpaceSystem() { delete (GroupAPI); } +SpaceSystem::~SpaceSystem() +{ + delete (GroupAPI); + + if (EventBusPtr) + { + EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::SpaceSystem", + csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AsyncCallCompleted))); + } +} /* CreateSpace Continuations */ async::task SpaceSystem::CreateSpaceGroupInfo( @@ -1925,37 +1964,72 @@ void SpaceSystem::DeleteSpaceGeoLocation(const csp::common::String& SpaceId, Nul void SpaceSystem::DuplicateSpace(const String& SpaceId, const String& NewName, SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, SpaceResultCallback Callback) { - auto Request = std::make_shared(); - Request->SetSpaceId(SpaceId); - Request->SetNewGroupOwnerId(SystemsManager::Get().GetUserSystem()->GetLoginState().UserId); - Request->SetNewUniqueName(NewName); - Request->SetDiscoverable(HasFlag(NewAttributes, csp::systems::SpaceAttributes::IsDiscoverable)); - Request->SetRequiresInvite(HasFlag(NewAttributes, csp::systems::SpaceAttributes::RequiresInvite)); - Request->SetShallowCopy(ShallowCopy); + auto Request = ConstructDuplicateSpaceOptions(SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, false); - if (MemberGroupIds.HasValue()) - { - std::vector GroupIds; - GroupIds.reserve(MemberGroupIds->Size()); + csp::services::ResponseHandlerPtr ResponseHandler + = SpaceAPI->CreateHandler(Callback, nullptr); - for (size_t i = 0; i < MemberGroupIds->Size(); ++i) + static_cast(SpaceAPI)->spacesSpaceIdDuplicatePost( { - GroupIds.push_back(MemberGroupIds->operator[](i)); - } + SpaceId, // spaceId + false, // asyncCall + Request // RequestBody + }, + ResponseHandler // ResponseHandler + ); +} - Request->SetMemberGroupIds(GroupIds); - } +void SpaceSystem::DuplicateSpaceAsync(const String& SpaceId, const String& NewName, SpaceAttributes NewAttributes, + const Optional>& MemberGroupIds, bool ShallowCopy, NullResultCallback Callback) +{ + auto Request = ConstructDuplicateSpaceOptions(SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, true); csp::services::ResponseHandlerPtr ResponseHandler - = SpaceAPI->CreateHandler(Callback, nullptr); + = SpaceAPI->CreateHandler(Callback, nullptr); static_cast(SpaceAPI)->spacesSpaceIdDuplicatePost( { SpaceId, // spaceId - false, // asyncCall + true, // asyncCall Request // RequestBody }, ResponseHandler // ResponseHandler ); } + +void SpaceSystem::SetAsyncCallCompletedCallback(AsyncCallCompletedCallbackHandler Callback) +{ + AsyncCallCompletedCallback = std::move(Callback); + + if (!EventBusPtr) + { + CSP_LOG_ERROR_MSG("Error: Failed to register SpaceSystem. NetworkEventBus must be instantiated in the MultiplayerConnection first."); + return; + } + + if (!AsyncCallCompletedCallback) + { + CSP_LOG_ERROR_MSG("Error: AsyncCallCompletedCallback not set. SpaceSystem has not been registered with the AsyncCallCompleted event."); + return; + } + + EventBusPtr->ListenNetworkEvent( + csp::multiplayer::NetworkEventRegistration("CSPInternal::SpaceSystem", + csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AsyncCallCompleted)), + [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnAsyncCallCompletedEvent(NetworkEventData); }); +} + +void SpaceSystem::OnAsyncCallCompletedEvent(const csp::common::NetworkEventData& NetworkEventData) +{ + if (!AsyncCallCompletedCallback) + { + return; + } + + const csp::common::AsyncCallCompletedEventData& AsyncCallCompletedEventData + = static_cast(NetworkEventData); + + AsyncCallCompletedCallback(AsyncCallCompletedEventData); +} + } // namespace csp::systems diff --git a/Library/src/Systems/SystemsManager.cpp b/Library/src/Systems/SystemsManager.cpp index 00c869d93..05b4e50ff 100644 --- a/Library/src/Systems/SystemsManager.cpp +++ b/Library/src/Systems/SystemsManager.cpp @@ -193,7 +193,7 @@ void SystemsManager::CreateSystems(csp::multiplayer::ISignalRConnection* SignalR // SystemBase inheritors - SpaceSystem = new csp::systems::SpaceSystem(WebClient, *LogSystem); + SpaceSystem = new csp::systems::SpaceSystem(WebClient, NetworkEventBus, *LogSystem); AssetSystem = new csp::systems::AssetSystem(WebClient, NetworkEventBus, *LogSystem); AnchorSystem = new csp::systems::AnchorSystem(WebClient, *LogSystem); PointOfInterestSystem = new csp::systems::PointOfInterestInternalSystem(WebClient, *LogSystem); diff --git a/Tests/src/PublicAPITests/SpaceSystemTests.cpp b/Tests/src/PublicAPITests/SpaceSystemTests.cpp index f10aed788..6019a69d7 100644 --- a/Tests/src/PublicAPITests/SpaceSystemTests.cpp +++ b/Tests/src/PublicAPITests/SpaceSystemTests.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -3233,6 +3234,16 @@ CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceTest) EXPECT_EQ(NewSpace.OwnerId, UserId); EXPECT_NE(Space.OwnerId, UserId); + // Ensure we can enter the newly duplicated Space + std::unique_ptr RealtimeEngine { SystemsManager.MakeOnlineRealtimeEngine() }; + RealtimeEngine->SetEntityFetchCompleteCallback([](uint32_t) {}); + + auto [EnterResult] = AWAIT_PRE(SpaceSystem, EnterSpace, RequestPredicate, NewSpace.Id, RealtimeEngine.get()); + ASSERT_EQ(EnterResult.GetResultCode(), csp::systems::EResultCode::Success); + + auto [ExitSpaceResult] = AWAIT_PRE(SpaceSystem, ExitSpace, RequestPredicate); + ASSERT_EQ(ExitSpaceResult.GetResultCode(), csp::systems::EResultCode::Success); + // Delete duplicated space DeleteSpace(SpaceSystem, NewSpace.Id); } @@ -3247,6 +3258,100 @@ CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceTest) // Log out LogOut(UserSystem); } + +CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceAsyncTest) +{ + SetRandSeed(); + + auto& SystemsManager = ::SystemsManager::Get(); + auto* UserSystem = SystemsManager.GetUserSystem(); + auto* SpaceSystem = SystemsManager.GetSpaceSystem(); + + const char* TestSpaceName = "CSP-TEST-SPACE"; + const char* TestSpaceDescription = "CSP-TEST-SPACEDESC"; + + char UniqueSpaceName[256]; + SPRINTF(UniqueSpaceName, "%s-%s", TestSpaceName, GetUniqueString().c_str()); + + String UserId; + + // Create default and alt users + csp::systems::Profile DefaultUser = CreateTestUser(); + csp::systems::Profile AlternativeUser = CreateTestUser(); + + // Log in + LogIn(UserSystem, UserId, DefaultUser.Email, GeneratedTestAccountPassword); + + // Create space + Array UserRoles(1); + UserRoles[0].UserEmail = AlternativeUser.Email; + UserRoles[0].UserRole = SpaceUserRole::User; + InviteUserRoleInfoCollection InviteInfo; + InviteInfo.InviteUserRoleInfos = UserRoles; + + ::Space Space; + CreateSpace(SpaceSystem, UniqueSpaceName, TestSpaceDescription, SpaceAttributes::Private, nullptr, InviteInfo, nullptr, nullptr, Space); + + // Log out and log in as alt user + LogOut(UserSystem); + LogIn(UserSystem, UserId, AlternativeUser.Email, GeneratedTestAccountPassword); + + csp::common::String NewSpaceId; + + // Attempt to duplicate space asynchrously + { + std::promise AsyncCallCompletedPromise; + std::future AsyncCallCompletedFuture = AsyncCallCompletedPromise.get_future(); + + auto AsyncCallCompletedCallback = [&](const csp::common::AsyncCallCompletedEventData& NetworkEventData) + { + EXPECT_EQ(NetworkEventData.OperationName, "DuplicateSpaceAsync"); + EXPECT_EQ(NetworkEventData.ReferenceType, "GroupId"); + + NewSpaceId = NetworkEventData.ReferenceId; + + AsyncCallCompletedPromise.set_value(true); + }; + + SpaceSystem->SetAsyncCallCompletedCallback(AsyncCallCompletedCallback); + + SPRINTF(UniqueSpaceName, "%s-%s", TestSpaceName, GetUniqueString().c_str()); + + auto [Result] + = AWAIT_PRE(SpaceSystem, DuplicateSpaceAsync, RequestPredicate, Space.Id, UniqueSpaceName, SpaceAttributes::Private, nullptr, true); + + EXPECT_EQ(Result.GetResultCode(), EResultCode::Success); + + // Wait for the callback to be received + AsyncCallCompletedFuture.wait(); + EXPECT_TRUE(AsyncCallCompletedFuture.get() == true); + } + + // Ensure we can enter the newly duplicated Space + { + std::unique_ptr RealtimeEngine { SystemsManager.MakeOnlineRealtimeEngine() }; + RealtimeEngine->SetEntityFetchCompleteCallback([](uint32_t) {}); + + auto [EnterResult] = AWAIT_PRE(SpaceSystem, EnterSpace, RequestPredicate, NewSpaceId, RealtimeEngine.get()); + ASSERT_EQ(EnterResult.GetResultCode(), csp::systems::EResultCode::Success); + + auto [ExitSpaceResult] = AWAIT_PRE(SpaceSystem, ExitSpace, RequestPredicate); + ASSERT_EQ(ExitSpaceResult.GetResultCode(), csp::systems::EResultCode::Success); + } + + // Delete duplicated space + DeleteSpace(SpaceSystem, NewSpaceId); + + // Log out and log in as default user to clean up original space + LogOut(UserSystem); + LogIn(UserSystem, UserId, DefaultUser.Email, GeneratedTestAccountPassword); + + // Delete space + DeleteSpace(SpaceSystem, Space.Id); + + // Log out + LogOut(UserSystem); +} namespace CSPEngine { From 64f863f7d3c1bc27efc763dddd6252076f843118 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Wed, 29 Oct 2025 14:05:56 +0000 Subject: [PATCH 02/10] [OF-1736] docs: Update comments - Update the error message logged when the 'AsyncCallCompletedCallback' is not set successfully. - Correct a typo comment in the 'AsyncCallCompletedEventData' class. --- Library/include/CSP/Common/NetworkEventData.h | 2 +- Library/src/Systems/Spaces/SpaceSystem.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Library/include/CSP/Common/NetworkEventData.h b/Library/include/CSP/Common/NetworkEventData.h index ef227b88a..d5635dd4f 100644 --- a/Library/include/CSP/Common/NetworkEventData.h +++ b/Library/include/CSP/Common/NetworkEventData.h @@ -159,7 +159,7 @@ class CSP_API AsyncCallCompletedEventData : public NetworkEventData csp::common::String OperationName; /// @brief An Id related to the async operation that has been completed. - /// This could for example be a groud Id, if this were an async duplicate group operation. + /// This could for example be a group Id, if this were an async duplicate group operation. csp::common::String ReferenceId; /// @brief The type that the Id represents. diff --git a/Library/src/Systems/Spaces/SpaceSystem.cpp b/Library/src/Systems/Spaces/SpaceSystem.cpp index 80d43a378..0ac0af2b5 100644 --- a/Library/src/Systems/Spaces/SpaceSystem.cpp +++ b/Library/src/Systems/Spaces/SpaceSystem.cpp @@ -2009,7 +2009,8 @@ void SpaceSystem::SetAsyncCallCompletedCallback(AsyncCallCompletedCallbackHandle if (!AsyncCallCompletedCallback) { - CSP_LOG_ERROR_MSG("Error: AsyncCallCompletedCallback not set. SpaceSystem has not been registered with the AsyncCallCompleted event."); + CSP_LOG_ERROR_MSG("Error: The AsyncCallCompletedCallback handler has not been set and the SpaceSystem has not been registered with the " + "AsyncCallCompleted event. Please call 'SetAsyncCallCompletedCallback()' with a valid AsyncCallCompletedCallbackHandler."); return; } From a69b4031c30f3fe7da37a2d0d9b0804f3e36fb8a Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Wed, 29 Oct 2025 17:51:50 +0000 Subject: [PATCH 03/10] [OF-1736] refac: Pass NetworkEventBus by ref The SpaceSystem was being passed to the NetworkEventBus ctor by ptr and then we had a nullptr check to ensure it was valid before attempting to add an event listener. However, the NetworkEventBus cannot be null and should therefore be passed by ref. The MultiplayerConnection::GetEventBus() method has been updated to return a reference to the EventBus. This ref is then passed to the systems, which dereference it before passing it to the SystemBase class. This is similar to what is done with the LogSystem. I also took the opportunity to remove any 'In' prefixes from related method arguments. [OF-1736] fix: Update --- .../CSP/Multiplayer/MultiPlayerConnection.h | 9 +- .../include/CSP/Systems/Assets/AssetSystem.h | 2 +- .../HotspotSequence/HotspotSequenceSystem.h | 2 +- .../CSP/Systems/Sequence/SequenceSystem.h | 2 +- .../include/CSP/Systems/Spaces/SpaceSystem.h | 2 +- Library/include/CSP/Systems/SystemBase.h | 8 +- Library/include/CSP/Systems/SystemsManager.h | 3 +- .../include/CSP/Systems/Users/UserSystem.h | 2 +- .../Election/ClientElectionManager.cpp | 12 +-- .../src/Multiplayer/MultiplayerConnection.cpp | 8 +- Library/src/Systems/Assets/AssetSystem.cpp | 10 +- .../ConversationSystemInternal.cpp | 25 +++-- .../Conversation/ConversationSystemInternal.h | 4 +- .../HotspotSequence/HotspotSequenceSystem.cpp | 4 +- .../src/Systems/Sequence/SequenceSystem.cpp | 6 +- Library/src/Systems/Spaces/SpaceSystem.cpp | 21 ++--- Library/src/Systems/SystemBase.cpp | 8 +- Library/src/Systems/SystemsManager.cpp | 20 ++-- Library/src/Systems/Users/UserSystem.cpp | 4 +- .../src/RunnableTests/EventBusPing.cpp | 4 +- Tests/src/PublicAPITests/AssetSystemTests.cpp | 6 +- .../ConversationSystemTests.cpp | 10 +- Tests/src/PublicAPITests/EventBusTests.cpp | 91 +++++++++---------- 23 files changed, 121 insertions(+), 142 deletions(-) diff --git a/Library/include/CSP/Multiplayer/MultiPlayerConnection.h b/Library/include/CSP/Multiplayer/MultiPlayerConnection.h index 18bddcf17..3db864f79 100644 --- a/Library/include/CSP/Multiplayer/MultiPlayerConnection.h +++ b/Library/include/CSP/Multiplayer/MultiPlayerConnection.h @@ -138,7 +138,8 @@ class CSP_API MultiplayerConnection /// @brief Start the connection and register to start receiving updates from the server. /// Connect should be called after LogIn and before EnterSpace. /// @param Callback ErrorCodeCallbackHandler : a callback with failure state. - CSP_NO_EXPORT void Connect(ErrorCodeCallbackHandler Callback, [[maybe_unused]] const csp::common::String& MultiplayerUri, const csp::common::String& AccessToken, const csp::common::String& DeviceId); + CSP_NO_EXPORT void Connect(ErrorCodeCallbackHandler Callback, [[maybe_unused]] const csp::common::String& MultiplayerUri, + const csp::common::String& AccessToken, const csp::common::String& DeviceId); /// @brief Indicates whether the multiplayer connection is established /// @return bool : true if connected, false otherwise @@ -153,8 +154,8 @@ class CSP_API MultiplayerConnection CSP_NO_EXPORT csp::multiplayer::NetworkEventManagerImpl* GetNetworkEventManager() { return NetworkEventManager; } /// @brief Getter for the NetworkEventBus - /// @return NetworkEventBus* : pointer to the NetworkEventBus - CSP_NO_EXPORT NetworkEventBus* GetEventBusPtr() { return EventBusPtr; } + /// @return NetworkEventBus& : reference to the NetworkEventBus + CSP_NO_EXPORT NetworkEventBus& GetEventBus() { return *EventBus; } /// @brief Disconnect the multiplayer and provide a reason /// @param Reason csp::common::String& : the reason to disconnect @@ -243,7 +244,7 @@ class CSP_API MultiplayerConnection class csp::multiplayer::IWebSocketClient* WebSocketClient; class NetworkEventManagerImpl* NetworkEventManager; - class NetworkEventBus* EventBusPtr; + class NetworkEventBus* EventBus; csp::common::LogSystem& LogSystem; diff --git a/Library/include/CSP/Systems/Assets/AssetSystem.h b/Library/include/CSP/Systems/Assets/AssetSystem.h index 5b1a71283..e342da8ef 100644 --- a/Library/include/CSP/Systems/Assets/AssetSystem.h +++ b/Library/include/CSP/Systems/Assets/AssetSystem.h @@ -362,7 +362,7 @@ class CSP_API AssetSystem : public SystemBase private: AssetSystem(); // This constructor is only provided to appease the wrapper generator and should not be used - CSP_NO_EXPORT AssetSystem(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, common::LogSystem& LogSystem); + CSP_NO_EXPORT AssetSystem(csp::web::WebClient* WebClient, csp::multiplayer::NetworkEventBus& EventBus, common::LogSystem& LogSystem); ~AssetSystem(); CSP_ASYNC_RESULT void DeleteAssetCollectionById(const csp::common::String& AssetCollectionId, NullResultCallback Callback); diff --git a/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h b/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h index 3e89767d9..304a2fe31 100644 --- a/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h +++ b/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h @@ -46,7 +46,7 @@ class CSP_API HotspotSequenceSystem : public SystemBase CSP_END_IGNORE HotspotSequenceSystem(csp::systems::SequenceSystem* SequenceSystem, csp::systems::SpaceSystem* SpaceSystem, - csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem); + csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem); /// @brief Create a Hotspot group /// @param GroupName csp::common::String : The unique grouping name /// @param HotspotIds csp::common::Array : set of Hotspot ids to add to the group diff --git a/Library/include/CSP/Systems/Sequence/SequenceSystem.h b/Library/include/CSP/Systems/Sequence/SequenceSystem.h index 944099c7f..b1e5699d7 100644 --- a/Library/include/CSP/Systems/Sequence/SequenceSystem.h +++ b/Library/include/CSP/Systems/Sequence/SequenceSystem.h @@ -127,7 +127,7 @@ class CSP_API SequenceSystem : public SystemBase private: SequenceSystem(); // This constructor is only provided to appease the wrapper generator and should not be used - SequenceSystem(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem); + SequenceSystem(csp::web::WebClient* WebClient, csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem); ~SequenceSystem(); csp::services::ApiBase* SequenceAPI; diff --git a/Library/include/CSP/Systems/Spaces/SpaceSystem.h b/Library/include/CSP/Systems/Spaces/SpaceSystem.h index 8c8f98baa..2636d13e8 100644 --- a/Library/include/CSP/Systems/Spaces/SpaceSystem.h +++ b/Library/include/CSP/Systems/Spaces/SpaceSystem.h @@ -391,7 +391,7 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase private: SpaceSystem(); // This constructor is only provided to appease the wrapper generator and should not be used - SpaceSystem(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem); + SpaceSystem(csp::web::WebClient* WebClient, csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem); ~SpaceSystem(); // Space Metadata diff --git a/Library/include/CSP/Systems/SystemBase.h b/Library/include/CSP/Systems/SystemBase.h index 3ee1897f2..cf6ef3a09 100644 --- a/Library/include/CSP/Systems/SystemBase.h +++ b/Library/include/CSP/Systems/SystemBase.h @@ -49,13 +49,17 @@ namespace csp::systems { /// @brief Base class for all Connected Spaces Platform Systems, which enforces passing of a WebClient or NetworkEventBus instance in the constructor /// of each System. +/// @invariant EventBusPtr can never be null. The NetworkEventBus is owned by the MultiplayerConnection and persists for it's lifetime. It is passed +/// to each system (which derive from SystemBase) by reference to their ctor. This ref is dereferenced before being passed to the SystemBase ctor. +/// @invariant LogSystem can never be null. The LogSystem is owned by the SystemsManager and persists for it's lifetime. It is passed to +/// each system (which derive from SystemBase) by reference to their ctor. This ref is dereferenced before being passed to the SystemBase ctor. class CSP_API CSP_NO_DISPOSE SystemBase { friend class csp::multiplayer::MultiplayerConnection; protected: - CSP_NO_EXPORT SystemBase(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem* LogSystem); - CSP_NO_EXPORT SystemBase(csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem* LogSystem); + CSP_NO_EXPORT SystemBase(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* EventBus, csp::common::LogSystem* LogSystem); + CSP_NO_EXPORT SystemBase(csp::multiplayer::NetworkEventBus* EventBus, csp::common::LogSystem* LogSystem); csp::web::WebClient* WebClient; csp::multiplayer::NetworkEventBus* EventBusPtr; diff --git a/Library/include/CSP/Systems/SystemsManager.h b/Library/include/CSP/Systems/SystemsManager.h index 6091127f8..a3f9e27ae 100644 --- a/Library/include/CSP/Systems/SystemsManager.h +++ b/Library/include/CSP/Systems/SystemsManager.h @@ -171,7 +171,7 @@ class CSP_API SystemsManager csp::multiplayer::MultiplayerConnection* GetMultiplayerConnection(); - csp::multiplayer::NetworkEventBus* GetEventBus(); + csp::multiplayer::NetworkEventBus& GetEventBus(); // Convenience methods for the moment. This will need to be broken at formal modularization, but the standard pattern it creates throughout // integrations/tests will no doubt be helpful in doing that anyhow, rather than having big constructors everywhere. @@ -198,7 +198,6 @@ class CSP_API SystemsManager csp::web::WebClient* WebClient; csp::multiplayer::MultiplayerConnection* MultiplayerConnection; - csp::multiplayer::NetworkEventBus* NetworkEventBus; std::shared_ptr RealtimeEngine; UserSystem* UserSystem; SpaceSystem* SpaceSystem; diff --git a/Library/include/CSP/Systems/Users/UserSystem.h b/Library/include/CSP/Systems/Users/UserSystem.h index 3cb690482..d92fa2950 100644 --- a/Library/include/CSP/Systems/Users/UserSystem.h +++ b/Library/include/CSP/Systems/Users/UserSystem.h @@ -308,7 +308,7 @@ class CSP_API UserSystem : public SystemBase // Emergency Fix: We have a circular dependency issue due to SignalR requiring the AuthContext for construction. To get around this // we pass nullptr to the UserSystem ctor for the NetworkEventBus, and then call this method to set it after the NetworkEventBus has been // constructed. - void SetNetworkEventBus(csp::multiplayer::NetworkEventBus* EventBus); + void SetNetworkEventBus(csp::multiplayer::NetworkEventBus& EventBus); [[nodiscard]] bool EmailCheck(const std::string& Email) const; diff --git a/Library/src/Multiplayer/Election/ClientElectionManager.cpp b/Library/src/Multiplayer/Election/ClientElectionManager.cpp index 35516bdc0..96993ed9f 100644 --- a/Library/src/Multiplayer/Election/ClientElectionManager.cpp +++ b/Library/src/Multiplayer/Election/ClientElectionManager.cpp @@ -484,21 +484,21 @@ bool ClientElectionManager::IsConnected() const void ClientElectionManager::BindNetworkEvents() { - NetworkEventBus* NetworkEventBus = OnlineRealtimeEnginePtr->GetMultiplayerConnectionInstance()->GetEventBusPtr(); + NetworkEventBus& NetworkEventBus = OnlineRealtimeEnginePtr->GetMultiplayerConnectionInstance()->GetEventBus(); - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", ClientElectionMessage), + NetworkEventBus.ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", ClientElectionMessage), [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnClientElectionEvent(NetworkEventData.EventValues); }); - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", RemoteRunScriptMessage), + NetworkEventBus.ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", RemoteRunScriptMessage), [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnRemoteRunScriptEvent(NetworkEventData.EventValues); }); } void ClientElectionManager::UnBindNetworkEvents() { - NetworkEventBus* NetworkEventBus = OnlineRealtimeEnginePtr->GetMultiplayerConnectionInstance()->GetEventBusPtr(); + NetworkEventBus& NetworkEventBus = OnlineRealtimeEnginePtr->GetMultiplayerConnectionInstance()->GetEventBus(); - NetworkEventBus->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", ClientElectionMessage)); - NetworkEventBus->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", RemoteRunScriptMessage)); + NetworkEventBus.StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", ClientElectionMessage)); + NetworkEventBus.StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ClientElectionManager", RemoteRunScriptMessage)); } void ClientElectionManager::OnClientElectionEvent(const csp::common::Array& Data) diff --git a/Library/src/Multiplayer/MultiplayerConnection.cpp b/Library/src/Multiplayer/MultiplayerConnection.cpp index 3bc8add18..50aede1af 100644 --- a/Library/src/Multiplayer/MultiplayerConnection.cpp +++ b/Library/src/Multiplayer/MultiplayerConnection.cpp @@ -149,7 +149,7 @@ MultiplayerConnection::MultiplayerConnection(csp::common::LogSystem& LogSystem, , Connected(false) , MultiplayerHubMethods(MultiplayerHubMethodMap()) { - EventBusPtr = new NetworkEventBus(this, LogSystem); + EventBus = new NetworkEventBus(this, LogSystem); } MultiplayerConnection::~MultiplayerConnection() @@ -170,7 +170,7 @@ MultiplayerConnection::~MultiplayerConnection() delete (Connection); delete (WebSocketClient); delete (NetworkEventManager); - delete (EventBusPtr); + delete (EventBus); } } @@ -191,7 +191,7 @@ MultiplayerConnection::MultiplayerConnection(const MultiplayerConnection& InBoun DisconnectionCallback = InBoundConnection.DisconnectionCallback; ConnectionCallback = InBoundConnection.ConnectionCallback; NetworkInterruptionCallback = InBoundConnection.NetworkInterruptionCallback; - EventBusPtr = InBoundConnection.EventBusPtr; + EventBus = InBoundConnection.EventBus; Connected = (InBoundConnection.Connected) ? true : false; } @@ -373,7 +373,7 @@ void MultiplayerConnection::Connect(ErrorCodeCallbackHandler Callback, [[maybe_u BindOnRequestToSendObject(); BindOnRequestToDisconnect(); - EventBusPtr->StartEventMessageListening(); + EventBus->StartEventMessageListening(); // We register the network interruption callback as a wrapper because we want to unwrap any signalR exceptions. RegisterNetworkInterruptedCallback(Connection, LogSystem, NetworkInterruptionCallback); diff --git a/Library/src/Systems/Assets/AssetSystem.cpp b/Library/src/Systems/Assets/AssetSystem.cpp index 1db8acf43..2a3bd3a5b 100644 --- a/Library/src/Systems/Assets/AssetSystem.cpp +++ b/Library/src/Systems/Assets/AssetSystem.cpp @@ -358,13 +358,13 @@ AssetSystem::AssetSystem() { } -AssetSystem::AssetSystem(web::WebClient* InWebClient, multiplayer::NetworkEventBus* InEventBus, common::LogSystem& LogSystem) - : SystemBase(InWebClient, InEventBus, &LogSystem) +AssetSystem::AssetSystem(web::WebClient* WebClient, multiplayer::NetworkEventBus& EventBus, common::LogSystem& LogSystem) + : SystemBase(WebClient, &EventBus, &LogSystem) { - PrototypeAPI = new chs::PrototypeApi(InWebClient); - AssetDetailAPI = new chs::AssetDetailApi(InWebClient); + PrototypeAPI = new chs::PrototypeApi(WebClient); + AssetDetailAPI = new chs::AssetDetailApi(WebClient); - FileManager = new web::RemoteFileManager(InWebClient); + FileManager = new web::RemoteFileManager(WebClient); RegisterSystemCallback(); } diff --git a/Library/src/Systems/Conversation/ConversationSystemInternal.cpp b/Library/src/Systems/Conversation/ConversationSystemInternal.cpp index 9c58d0342..7ce253c2b 100644 --- a/Library/src/Systems/Conversation/ConversationSystemInternal.cpp +++ b/Library/src/Systems/Conversation/ConversationSystemInternal.cpp @@ -335,12 +335,11 @@ namespace } ConversationSystemInternal::ConversationSystemInternal(systems::AssetSystem* AssetSystem, systems::SpaceSystem* SpaceSystem, - systems::UserSystem* UserSystem, multiplayer::NetworkEventBus* NetworkEventBus, csp::common::LogSystem& LogSystem) - : SystemBase(NetworkEventBus, &LogSystem) + systems::UserSystem* UserSystem, multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem) + : SystemBase(&EventBus, &LogSystem) , AssetSystem { AssetSystem } , SpaceSystem { SpaceSystem } , UserSystem { UserSystem } - , NetworkEventBus { NetworkEventBus } { RegisterSystemCallback(); } @@ -384,7 +383,7 @@ void ConversationSystemInternal::CreateConversation(const common::String& Messag multiplayer::MessageInfo MessageInfo = ConversationSystemHelpers::GetConversationInfoFromConversationAssetCollection(AddCommentContainerResult.GetAssetCollection()); - SendConversationEvent(multiplayer::ConversationEventType::NewConversation, MessageInfo, NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::NewConversation, MessageInfo, EventBusPtr, SignalRCallback); }; const auto UniqueAssetCollectionName = ConversationSystemHelpers::GetUniqueConversationContainerAssetCollectionName(SpaceId, UserId); @@ -437,7 +436,7 @@ void ConversationSystemInternal::DeleteConversation(const common::String& Conver multiplayer::MessageInfo MessageInfo = ConversationSystemHelpers::GetConversationInfoFromConversationAssetCollection(ConversationAssetCollection); - SendConversationEvent(multiplayer::ConversationEventType::DeleteConversation, MessageInfo, NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::DeleteConversation, MessageInfo, EventBusPtr, SignalRCallback); }; AssetSystem->GetAssetCollectionById(ConversationId, GetConversationCallback); @@ -472,7 +471,7 @@ void ConversationSystemInternal::AddMessage( }; const multiplayer::MessageInfo& MessageInfo = MessageResultCallbackResult.GetMessageInfo(); - SendConversationEvent(multiplayer::ConversationEventType::NewMessage, MessageInfo, NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::NewMessage, MessageInfo, EventBusPtr, SignalRCallback); }; multiplayer::MessageInfo MessageInfo(ConversationId, false, Message); @@ -531,7 +530,7 @@ void ConversationSystemInternal::DeleteMessage(const common::String& Conversatio this->AssetSystem->DeleteAssetCollection(MessageAssetCollection, DeleteAssetCollectionCallback); }; - SendConversationEvent(multiplayer::ConversationEventType::DeleteMessage, Info, NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::DeleteMessage, Info, EventBusPtr, SignalRCallback); }; AssetSystem->GetAssetCollectionById(MessageId, GetMessageCallback); @@ -633,7 +632,7 @@ void ConversationSystemInternal::UpdateConversation( auto UpdatedInfo = systems::ConversationSystemHelpers::GetConversationInfoFromConversationAssetCollection( GetUpdatedConversationResult.GetAssetCollection()); - SendConversationEvent(multiplayer::ConversationEventType::ConversationInformation, UpdatedInfo, NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::ConversationInformation, UpdatedInfo, EventBusPtr, SignalRCallback); }; const AssetCollection& ConversationAssetCollection = GetConversationResult.GetAssetCollection(); @@ -722,7 +721,7 @@ void ConversationSystemInternal::UpdateMessage(const common::String& /*Conversat INVOKE_IF_NOT_NULL(Callback, Result); }; - SendConversationEvent(multiplayer::ConversationEventType::MessageInformation, Result.GetMessageInfo(), NetworkEventBus, SignalRCallback); + SendConversationEvent(multiplayer::ConversationEventType::MessageInformation, Result.GetMessageInfo(), EventBusPtr, SignalRCallback); }; const AssetCollection& MessageAssetCollection = GetMessageResult.GetAssetCollection(); @@ -889,7 +888,7 @@ void ConversationSystemInternal::SetConversationAnnotation(const csp::common::St "Failed to update message asset collection metadata.", {}, {}, {})) .then(SetMessageAssetCollection(ConversationAssetCollection)) // 7. Send multiplayer event - .then(SendConversationEvent(multiplayer::ConversationEventType::SetConversationAnnotation, ConversationAssetCollection, NetworkEventBus)) + .then(SendConversationEvent(multiplayer::ConversationEventType::SetConversationAnnotation, ConversationAssetCollection, EventBusPtr)) .then(common::continuations::AssertRequestSuccessOrErrorFromMultiplayerErrorCode( "ConversationSystemInternal::SetConversationAnnotation, successfully sent multiplayer event", MakeInvalid(), *LogSystem)) @@ -916,7 +915,7 @@ void ConversationSystemInternal::DeleteConversationAnnotation(const csp::common: .then(RemoveAnnotationMetadata(AssetSystem)) .then(SetMessageAssetCollection(ConversationAssetCollection)) // 3. Send multiplayer event - .then(SendConversationEvent(multiplayer::ConversationEventType::DeleteConversationAnnotation, ConversationAssetCollection, NetworkEventBus)) + .then(SendConversationEvent(multiplayer::ConversationEventType::DeleteConversationAnnotation, ConversationAssetCollection, EventBusPtr)) .then(common::continuations::AssertRequestSuccessOrErrorFromMultiplayerErrorCode( "ConversationSystemInternal::DeleteAnnotation, successfully sent multiplayer event", MakeInvalid(), *LogSystem)) // 4. Delete annoation asset @@ -1039,7 +1038,7 @@ void ConversationSystemInternal::SetAnnotation(const csp::common::String& Conver "Failed to update message asset collection metadata.", {}, {}, {})) .then(SetMessageAssetCollection(MessageAssetCollection)) // 7. Send multiplayer event - .then(SendConversationMessageEvent(multiplayer::ConversationEventType::SetAnnotation, MessageAssetCollection, NetworkEventBus)) + .then(SendConversationMessageEvent(multiplayer::ConversationEventType::SetAnnotation, MessageAssetCollection, EventBusPtr)) .then(common::continuations::AssertRequestSuccessOrErrorFromMultiplayerErrorCode( "ConversationSystemInternal::SetAnnotation, successfully sent multiplayer event", MakeInvalid(), *LogSystem)) @@ -1070,7 +1069,7 @@ void ConversationSystemInternal::DeleteAnnotation( .then(RemoveAnnotationMetadata(AssetSystem)) .then(SetMessageAssetCollection(MessageAssetCollection)) // 3. Send multiplayer event - .then(SendConversationMessageEvent(multiplayer::ConversationEventType::DeleteAnnotation, MessageAssetCollection, NetworkEventBus)) + .then(SendConversationMessageEvent(multiplayer::ConversationEventType::DeleteAnnotation, MessageAssetCollection, EventBusPtr)) .then(common::continuations::AssertRequestSuccessOrErrorFromMultiplayerErrorCode( "ConversationSystemInternal::DeleteAnnotation, successfully sent multiplayer event", MakeInvalid(), *LogSystem)) // 4. Delete annoation asset diff --git a/Library/src/Systems/Conversation/ConversationSystemInternal.h b/Library/src/Systems/Conversation/ConversationSystemInternal.h index e68073ada..ef95b9062 100644 --- a/Library/src/Systems/Conversation/ConversationSystemInternal.h +++ b/Library/src/Systems/Conversation/ConversationSystemInternal.h @@ -50,7 +50,7 @@ class CSP_API ConversationSystemInternal : public SystemBase CSP_END_IGNORE ConversationSystemInternal(csp::systems::AssetSystem* AssetSystem, csp::systems::SpaceSystem* SpaceSystem, csp::systems::UserSystem* UserSystem, - csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem); + csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem); ~ConversationSystemInternal(); @@ -125,8 +125,6 @@ class CSP_API ConversationSystemInternal : public SystemBase csp::systems::SpaceSystem* SpaceSystem; csp::systems::UserSystem* UserSystem; - csp::multiplayer::NetworkEventBus* NetworkEventBus; - std::unordered_set Components; std::vector> Events; }; diff --git a/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp b/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp index 2f0e5ff4d..771d75c82 100644 --- a/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp +++ b/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp @@ -88,8 +88,8 @@ namespace } // namespace HotspotSequenceSystem::HotspotSequenceSystem(csp::systems::SequenceSystem* SequenceSystem, csp::systems::SpaceSystem* SpaceSystem, - csp::multiplayer::NetworkEventBus* NetworkEventBus, csp::common::LogSystem& LogSystem) - : SystemBase(NetworkEventBus, &LogSystem) + csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem) + : SystemBase(&EventBus, &LogSystem) { this->SequenceSystem = SequenceSystem; this->SpaceSystem = SpaceSystem; diff --git a/Library/src/Systems/Sequence/SequenceSystem.cpp b/Library/src/Systems/Sequence/SequenceSystem.cpp index cbfda1cb1..f6891667d 100644 --- a/Library/src/Systems/Sequence/SequenceSystem.cpp +++ b/Library/src/Systems/Sequence/SequenceSystem.cpp @@ -303,10 +303,10 @@ SequenceSystem::SequenceSystem() { } -SequenceSystem::SequenceSystem(web::WebClient* InWebClient, multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem) - : SystemBase(InWebClient, InEventBus, &LogSystem) +SequenceSystem::SequenceSystem(web::WebClient* WebClient, multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem) + : SystemBase(WebClient, &EventBus, &LogSystem) { - SequenceAPI = new chs::SequenceApi(InWebClient); + SequenceAPI = new chs::SequenceApi(WebClient); RegisterSystemCallback(); } diff --git a/Library/src/Systems/Spaces/SpaceSystem.cpp b/Library/src/Systems/Spaces/SpaceSystem.cpp index 0ac0af2b5..e532801c1 100644 --- a/Library/src/Systems/Spaces/SpaceSystem.cpp +++ b/Library/src/Systems/Spaces/SpaceSystem.cpp @@ -100,23 +100,20 @@ SpaceSystem::SpaceSystem() { } -SpaceSystem::SpaceSystem(csp::web::WebClient* InWebClient, multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem& LogSystem) - : SystemBase(InWebClient, InEventBus, &LogSystem) +SpaceSystem::SpaceSystem(csp::web::WebClient* WebClient, multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem) + : SystemBase(WebClient, &EventBus, &LogSystem) , CurrentSpace() { - GroupAPI = new chs::GroupApi(InWebClient); - SpaceAPI = new chsaggregation::SpaceApi(InWebClient); + GroupAPI = new chs::GroupApi(WebClient); + SpaceAPI = new chsaggregation::SpaceApi(WebClient); } SpaceSystem::~SpaceSystem() { delete (GroupAPI); - if (EventBusPtr) - { - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::SpaceSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AsyncCallCompleted))); - } + EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::SpaceSystem", + csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AsyncCallCompleted))); } /* CreateSpace Continuations */ @@ -2001,12 +1998,6 @@ void SpaceSystem::SetAsyncCallCompletedCallback(AsyncCallCompletedCallbackHandle { AsyncCallCompletedCallback = std::move(Callback); - if (!EventBusPtr) - { - CSP_LOG_ERROR_MSG("Error: Failed to register SpaceSystem. NetworkEventBus must be instantiated in the MultiplayerConnection first."); - return; - } - if (!AsyncCallCompletedCallback) { CSP_LOG_ERROR_MSG("Error: The AsyncCallCompletedCallback handler has not been set and the SpaceSystem has not been registered with the " diff --git a/Library/src/Systems/SystemBase.cpp b/Library/src/Systems/SystemBase.cpp index 1134ab7e1..2a24953a2 100644 --- a/Library/src/Systems/SystemBase.cpp +++ b/Library/src/Systems/SystemBase.cpp @@ -28,16 +28,16 @@ SystemBase::SystemBase() { } -SystemBase::SystemBase(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem* LogSystem) +SystemBase::SystemBase(csp::web::WebClient* InWebClient, csp::multiplayer::NetworkEventBus* EventBus, csp::common::LogSystem* LogSystem) : WebClient(InWebClient) - , EventBusPtr(InEventBus) + , EventBusPtr(EventBus) , LogSystem(LogSystem) { } -SystemBase::SystemBase(csp::multiplayer::NetworkEventBus* InEventBus, csp::common::LogSystem* LogSystem) +SystemBase::SystemBase(csp::multiplayer::NetworkEventBus* EventBus, csp::common::LogSystem* LogSystem) : WebClient(nullptr) - , EventBusPtr(InEventBus) + , EventBusPtr(EventBus) , LogSystem(LogSystem) { } diff --git a/Library/src/Systems/SystemsManager.cpp b/Library/src/Systems/SystemsManager.cpp index 05b4e50ff..c92dccdb5 100644 --- a/Library/src/Systems/SystemsManager.cpp +++ b/Library/src/Systems/SystemsManager.cpp @@ -102,11 +102,11 @@ ExternalServiceProxySystem* SystemsManager::GetExternalServicesProxySystem() { r csp::multiplayer::MultiplayerConnection* SystemsManager::GetMultiplayerConnection() { return MultiplayerConnection; } -csp::multiplayer::NetworkEventBus* SystemsManager::GetEventBus() { return NetworkEventBus; } +csp::multiplayer::NetworkEventBus& SystemsManager::GetEventBus() { return MultiplayerConnection->GetEventBus(); } csp::multiplayer::OnlineRealtimeEngine* SystemsManager::MakeOnlineRealtimeEngine() { - return new csp::multiplayer::OnlineRealtimeEngine { *GetMultiplayerConnection(), *GetLogSystem(), *GetEventBus(), *GetScriptSystem() }; + return new csp::multiplayer::OnlineRealtimeEngine { *GetMultiplayerConnection(), *GetLogSystem(), GetEventBus(), *GetScriptSystem() }; } csp::multiplayer::OfflineRealtimeEngine* SystemsManager::MakeOfflineRealtimeEngine() @@ -130,7 +130,6 @@ csp::common::IRealtimeEngine* SystemsManager::MakeRealtimeEngine(csp::common::Re SystemsManager::SystemsManager() : WebClient(nullptr) , MultiplayerConnection(nullptr) - , NetworkEventBus(nullptr) , RealtimeEngine(nullptr) , UserSystem(nullptr) , SpaceSystem(nullptr) @@ -184,17 +183,15 @@ void SystemsManager::CreateSystems(csp::multiplayer::ISignalRConnection* SignalR MultiplayerConnection = new csp::multiplayer::MultiplayerConnection(*LogSystem, *SignalRConnection); - NetworkEventBus = MultiplayerConnection->GetEventBusPtr(); - // Set the NetworkEventBus now that it has been initialized. - UserSystem->SetNetworkEventBus(NetworkEventBus); + UserSystem->SetNetworkEventBus(MultiplayerConnection->GetEventBus()); VoipSystem = new csp::systems::VoipSystem(); // SystemBase inheritors - SpaceSystem = new csp::systems::SpaceSystem(WebClient, NetworkEventBus, *LogSystem); - AssetSystem = new csp::systems::AssetSystem(WebClient, NetworkEventBus, *LogSystem); + SpaceSystem = new csp::systems::SpaceSystem(WebClient, MultiplayerConnection->GetEventBus(), *LogSystem); + AssetSystem = new csp::systems::AssetSystem(WebClient, MultiplayerConnection->GetEventBus(), *LogSystem); AnchorSystem = new csp::systems::AnchorSystem(WebClient, *LogSystem); PointOfInterestSystem = new csp::systems::PointOfInterestInternalSystem(WebClient, *LogSystem); ApplicationSettingsSystem = new csp::systems::ApplicationSettingsSystem(WebClient, *LogSystem); @@ -204,9 +201,10 @@ void SystemsManager::CreateSystems(csp::multiplayer::ISignalRConnection* SignalR EventTicketingSystem = new csp::systems::EventTicketingSystem(WebClient, *LogSystem); ECommerceSystem = new csp::systems::ECommerceSystem(WebClient, *LogSystem); QuotaSystem = new csp::systems::QuotaSystem(WebClient, *LogSystem); - SequenceSystem = new csp::systems::SequenceSystem(WebClient, NetworkEventBus, *LogSystem); - HotspotSequenceSystem = new csp::systems::HotspotSequenceSystem(SequenceSystem, SpaceSystem, NetworkEventBus, *LogSystem); - ConversationSystem = new csp::systems::ConversationSystemInternal(AssetSystem, SpaceSystem, UserSystem, NetworkEventBus, *LogSystem); + SequenceSystem = new csp::systems::SequenceSystem(WebClient, MultiplayerConnection->GetEventBus(), *LogSystem); + HotspotSequenceSystem = new csp::systems::HotspotSequenceSystem(SequenceSystem, SpaceSystem, MultiplayerConnection->GetEventBus(), *LogSystem); + ConversationSystem + = new csp::systems::ConversationSystemInternal(AssetSystem, SpaceSystem, UserSystem, MultiplayerConnection->GetEventBus(), *LogSystem); AnalyticsSystem = new csp::systems::AnalyticsSystem(WebClient, &(csp::CSPFoundation::GetClientUserAgentInfo()), *LogSystem); ExternalServiceProxySystem = new csp::systems::ExternalServiceProxySystem(WebClient, *LogSystem); } diff --git a/Library/src/Systems/Users/UserSystem.cpp b/Library/src/Systems/Users/UserSystem.cpp index 5fefde205..71514d2ea 100644 --- a/Library/src/Systems/Users/UserSystem.cpp +++ b/Library/src/Systems/Users/UserSystem.cpp @@ -203,9 +203,9 @@ UserSystem::~UserSystem() DeregisterSystemCallback(); } -void UserSystem::SetNetworkEventBus(csp::multiplayer::NetworkEventBus* EventBus) +void UserSystem::SetNetworkEventBus(csp::multiplayer::NetworkEventBus& EventBus) { - EventBusPtr = EventBus; + EventBusPtr = &EventBus; RegisterSystemCallback(); } diff --git a/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp b/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp index 7fa7f8a71..42fecf599 100644 --- a/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp +++ b/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp @@ -28,10 +28,10 @@ namespace EventBusPing void RunTest() { // Listen for an event, then ping it back to the client that sent it. - csp::systems::SystemsManager::Get().GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("Receiver", "EventPingRequest"), + csp::systems::SystemsManager::Get().GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("Receiver", "EventPingRequest"), [](const csp::common::NetworkEventData& NetworkEventData) { - csp::systems::SystemsManager::Get().GetEventBus()->SendNetworkEventToClient( + csp::systems::SystemsManager::Get().GetEventBus().SendNetworkEventToClient( "EventPingResponse", {}, NetworkEventData.SenderClientId, [](csp::multiplayer::ErrorCode) {}); }); } diff --git a/Tests/src/PublicAPITests/AssetSystemTests.cpp b/Tests/src/PublicAPITests/AssetSystemTests.cpp index 06f7be466..249b3349b 100644 --- a/Tests/src/PublicAPITests/AssetSystemTests.cpp +++ b/Tests/src/PublicAPITests/AssetSystemTests.cpp @@ -2065,7 +2065,6 @@ CSP_PUBLIC_TEST(CSPEngine, AssetSystemTests, AssetProcessGracefulFailureCallback auto* SpaceSystem = SystemsManager.GetSpaceSystem(); auto* AssetSystem = SystemsManager.GetAssetSystem(); auto* Connection = SystemsManager.GetMultiplayerConnection(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const char* TestSpaceName = "CSP-UNITTEST-SPACE-MAG"; const char* TestSpaceDescription = "CSP-UNITTEST-SPACEDESC-MAG"; @@ -2115,8 +2114,9 @@ CSP_PUBLIC_TEST(CSPEngine, AssetSystemTests, AssetProcessGracefulFailureCallback csp::common::ReplicatedValue Param4 = ""; csp::common::ReplicatedValue Param5 = ""; - NetworkEventBus->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::AssetDetailBlobChanged), - { Param1, Param2, Param3, Param4, Param5 }, Connection->GetClientId(), [](ErrorCode Error) { EXPECT_EQ(Error, ErrorCode::None); }); + SystemsManager.GetEventBus().SendNetworkEventToClient( + NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::AssetDetailBlobChanged), { Param1, Param2, Param3, Param4, Param5 }, + Connection->GetClientId(), [](ErrorCode Error) { EXPECT_EQ(Error, ErrorCode::None); }); // Wait for message WaitForCallback(AssetDetailBlobChangedCallbackCalled); diff --git a/Tests/src/PublicAPITests/ConversationSystemTests.cpp b/Tests/src/PublicAPITests/ConversationSystemTests.cpp index 8eb586077..249ef2af9 100644 --- a/Tests/src/PublicAPITests/ConversationSystemTests.cpp +++ b/Tests/src/PublicAPITests/ConversationSystemTests.cpp @@ -18,8 +18,8 @@ #include "CSP/Common/Optional.h" #include "CSP/Multiplayer/Components/ConversationSpaceComponent.h" #include "CSP/Multiplayer/MultiPlayerConnection.h" -#include "CSP/Multiplayer/SpaceEntity.h" #include "CSP/Multiplayer/OnlineRealtimeEngine.h" +#include "CSP/Multiplayer/SpaceEntity.h" #include "CSP/Systems/Spaces/Space.h" #include "CSP/Systems/Spaces/UserRoles.h" #include "CSP/Systems/SystemsManager.h" @@ -72,7 +72,6 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventTest) auto* UserSystem = SystemsManager.GetUserSystem(); auto* SpaceSystem = SystemsManager.GetSpaceSystem(); auto* Connection = SystemsManager.GetMultiplayerConnection(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); // Log in csp::common::String UserId; @@ -118,7 +117,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventTest) bool EventSent = false; - NetworkEventBus->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); @@ -153,7 +152,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventTest) bool EventSent = false; - NetworkEventBus->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); @@ -185,7 +184,6 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventDelay auto* UserSystem = SystemsManager.GetUserSystem(); auto* SpaceSystem = SystemsManager.GetSpaceSystem(); auto* Connection = SystemsManager.GetMultiplayerConnection(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); // Log in csp::common::String UserId; @@ -210,7 +208,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventDelay bool EventSent = false; - NetworkEventBus->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); diff --git a/Tests/src/PublicAPITests/EventBusTests.cpp b/Tests/src/PublicAPITests/EventBusTests.cpp index 3386e6743..925487acb 100644 --- a/Tests/src/PublicAPITests/EventBusTests.cpp +++ b/Tests/src/PublicAPITests/EventBusTests.cpp @@ -68,22 +68,21 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregister) { using namespace csp::multiplayer; auto& SystemsManager = csp::systems::SystemsManager::Get(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; - const csp::common::Array InitialRegisteredEvents = NetworkEventBus->AllRegistrations(); - NetworkEventBus->ListenNetworkEvent( + const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus().AllRegistrations(); + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - const csp::common::Array AddedRegistration = NetworkEventBus->AllRegistrations(); + const csp::common::Array AddedRegistration = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_TRUE(AddedRegistration.Size() == InitialRegisteredEvents.Size() + 1); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); - NetworkEventBus->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - const csp::common::Array RemovedRegistration = NetworkEventBus->AllRegistrations(); + const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_TRUE(RemovedRegistration.Size() == InitialRegisteredEvents.Size()); EXPECT_FALSE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); } @@ -92,7 +91,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) { using namespace csp::multiplayer; auto& SystemsManager = csp::systems::SystemsManager::Get(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; @@ -102,20 +100,20 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) const char* EventName3 = "TestEventName3"; - const csp::common::Array InitialRegisteredEvents = NetworkEventBus->AllRegistrations(); - NetworkEventBus->ListenNetworkEvent( + const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus().AllRegistrations(); + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName3 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName3 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - const csp::common::Array AddedRegistration = NetworkEventBus->AllRegistrations(); + const csp::common::Array AddedRegistration = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_TRUE(AddedRegistration.Size() == InitialRegisteredEvents.Size() + 6); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); @@ -125,9 +123,9 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName2 })); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName3 })); - NetworkEventBus->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - const csp::common::Array RemovedRegistration = NetworkEventBus->AllRegistrations(); + const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_TRUE(RemovedRegistration.Size() == InitialRegisteredEvents.Size() + 5); EXPECT_FALSE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName2 })); @@ -136,9 +134,9 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName2 })); EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName3 })); - NetworkEventBus->StopListenAllNetworkEvents(ReceiverId2); + SystemsManager.GetEventBus().StopListenAllNetworkEvents(ReceiverId2); - const csp::common::Array RemovedAllTestReceivedOneRegistrations = NetworkEventBus->AllRegistrations(); + const csp::common::Array RemovedAllTestReceivedOneRegistrations = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_TRUE(RemovedAllTestReceivedOneRegistrations.Size() == InitialRegisteredEvents.Size() + 2); EXPECT_FALSE(RemovedAllTestReceivedOneRegistrations.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); EXPECT_TRUE(RemovedAllTestReceivedOneRegistrations.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName2 })); @@ -155,7 +153,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectNullEvent) RAIIMockLogger MockLogger {}; auto& SystemsManager = csp::systems::SystemsManager::Get(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const csp::common::String Error = "Error: Expected non-null callback."; EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Error, Error)).Times(1); @@ -163,8 +160,8 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectNullEvent) const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; - NetworkEventBus->ListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }, nullptr); - auto AllRegistrations = NetworkEventBus->AllRegistrations(); + SystemsManager.GetEventBus().ListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }, nullptr); + auto AllRegistrations = SystemsManager.GetEventBus().AllRegistrations(); EXPECT_FALSE(std::any_of(AllRegistrations.begin(), AllRegistrations.end(), [ReceiverId](const NetworkEventRegistration& Registration) { return Registration.EventReceiverId == ReceiverId; })); } @@ -176,7 +173,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectDuplicateRegistration) RAIIMockLogger MockLogger {}; auto& SystemsManager = csp::systems::SystemsManager::Get(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; @@ -198,22 +194,22 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectDuplicateRegistration) .c_str(); EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Warning, Error)).Times(1); - const auto StartSize = NetworkEventBus->AllRegistrations().Size(); + const auto StartSize = SystemsManager.GetEventBus().AllRegistrations().Size(); - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(NetworkEventBus->AllRegistrations().Size(), StartSize + 1); - NetworkEventBus->ListenNetworkEvent( + EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 1); + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(NetworkEventBus->AllRegistrations().Size(), StartSize + 2); - NetworkEventBus->ListenNetworkEvent( + EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 2); + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(NetworkEventBus->AllRegistrations().Size(), StartSize + 3); + EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 3); // This one should be rejected - NetworkEventBus->ListenNetworkEvent( + SystemsManager.GetEventBus().ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(NetworkEventBus->AllRegistrations().Size(), StartSize + 3); + EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 3); } CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectUnknownDeregistration) @@ -223,7 +219,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectUnknownDeregistration) RAIIMockLogger MockLogger {}; auto& SystemsManager = csp::systems::SystemsManager::Get(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; @@ -236,15 +231,14 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectUnknownDeregistration) EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Verbose, Error)).Times(1); EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Log, Error1)).Times(1); - NetworkEventBus->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - NetworkEventBus->StopListenAllNetworkEvents(ReceiverId); + SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus().StopListenAllNetworkEvents(ReceiverId); } CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventSingleReciever) { auto& SystemsManager = csp::systems::SystemsManager::Get(); auto* UserSystem = SystemsManager.GetUserSystem(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); auto* Connection = SystemsManager.GetMultiplayerConnection(); const char* ReceiverId = "TestReceiverId"; @@ -268,11 +262,11 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventSingleReciever) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); - NetworkEventBus->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals = NetworkEventFuture.get(); EXPECT_EQ(ReceivedVals.Size(), 2); @@ -286,7 +280,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventMultiReciever) { auto& SystemsManager = csp::systems::SystemsManager::Get(); auto* UserSystem = SystemsManager.GetUserSystem(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); auto* Connection = SystemsManager.GetMultiplayerConnection(); const char* ReceiverId = "TestReceiverId"; @@ -312,18 +305,18 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventMultiReciever) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); std::promise> NetworkEventPromise1; std::future> NetworkEventFuture1 = NetworkEventPromise1.get_future(); - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId2, EventName), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId2, EventName), [&NetworkEventPromise1](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise1.set_value(NetworkEventData.EventValues); }); - NetworkEventBus->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); // Both recievers should recieve this event const csp::common::Array ReceivedVals = NetworkEventFuture.get(); @@ -339,7 +332,6 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, MultiEventSingleReceiver) { auto& SystemsManager = csp::systems::SystemsManager::Get(); auto* UserSystem = SystemsManager.GetUserSystem(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); auto* Connection = SystemsManager.GetMultiplayerConnection(); const char* ReceiverId = "TestReceiverId"; @@ -368,14 +360,14 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, MultiEventSingleReceiver) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName2), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName2), [&NetworkEventPromise1](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise1.set_value(NetworkEventData.EventValues); }); - NetworkEventBus->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals = NetworkEventFuture.get(); EXPECT_EQ(ReceivedVals.Size(), 2); @@ -387,7 +379,7 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, MultiEventSingleReceiver) // The other event should not have been recieved as it has not been fired EXPECT_TRUE(NetworkEventFuture1.wait_for(std::chrono::milliseconds { 0 }) != std::future_status::ready); - NetworkEventBus->SendNetworkEventToClient(EventName2, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus().SendNetworkEventToClient(EventName2, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals1 = NetworkEventFuture1.get(); EXPECT_EQ(ReceivedVals1.Size(), 2); } @@ -412,7 +404,6 @@ CSP_PUBLIC_TEST(DISABLED_CSPEngine, EventBusTests, TestMulticastEventToAllClient // Spin up 2 other clients auto& SystemsManager = csp::systems::SystemsManager::Get(); auto* UserSystem = SystemsManager.GetUserSystem(); - auto* NetworkEventBus = SystemsManager.GetEventBus(); auto* Connection = SystemsManager.GetMultiplayerConnection(); auto* SpaceSystem = SystemsManager.GetSpaceSystem(); @@ -461,7 +452,7 @@ CSP_PUBLIC_TEST(DISABLED_CSPEngine, EventBusTests, TestMulticastEventToAllClient const char* PintRequestEventName = "EventPingRequest"; const char* PingResponseEventName = "EventPingResponse"; - NetworkEventBus->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, PingResponseEventName), + SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, PingResponseEventName), [&ReceivedPings, &TwoPingsResponsePromise](const csp::common::NetworkEventData& /*NetworkEventData*/) { std::cout << "Received Event Bus Ping." << std::endl; @@ -473,7 +464,7 @@ CSP_PUBLIC_TEST(DISABLED_CSPEngine, EventBusTests, TestMulticastEventToAllClient }); // Send the ping event to all clients - NetworkEventBus->SendNetworkEvent(PintRequestEventName, {}, [](ErrorCode Error) { ASSERT_EQ(Error, ErrorCode::None); }); + SystemsManager.GetEventBus().SendNetworkEvent(PintRequestEventName, {}, [](ErrorCode Error) { ASSERT_EQ(Error, ErrorCode::None); }); // Expect to have had two responses auto Status = TwoPingsResponseFuture.wait_for(30s); From 924779e0006c9c82e6b256a05bd31d9e9b34d3b2 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 09:01:48 +0000 Subject: [PATCH 04/10] [OF-1736] docs: Added more detailed comments - Added more detailed comments to the DuplicateSpaceAsync() method to enumerate the operation data that would be returned via the AsyncCallCompletedCallback. - Updated the comments for the OnAsyncCallCompletedEvent() method to match. --- Library/include/CSP/Systems/Spaces/SpaceSystem.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Library/include/CSP/Systems/Spaces/SpaceSystem.h b/Library/include/CSP/Systems/Spaces/SpaceSystem.h index 2636d13e8..cfdbc3620 100644 --- a/Library/include/CSP/Systems/Spaces/SpaceSystem.h +++ b/Library/include/CSP/Systems/Spaces/SpaceSystem.h @@ -360,7 +360,11 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase /// @brief Duplicate an existing space and assign it to the current user. /// This is an asynchronous operation. Please subcribe to the AsyncCallCompletedCallback via @ref SpaceSystem::SetAsyncCallCompletedCallback() to - /// be notified when the duplication operation is complete. + /// be notified when the duplication operation is complete. The AsyncCallCompletedEventData returned by the AsyncCallCompletedCallback will + /// contain the following information: + /// - OperationName: "DuplicateSpaceAsync". + /// - ReferenceId: Id of the newly duplicated Space. + /// - ReferenceType: "GroupId". /// @param SpaceId csp::common::String : Id of the space to duplicate. /// @param NewName csp::common::String : A unique name for the duplicated space. /// @param NewAttributes csp::systems::SpaceAttributes : Attributes to apply to the duplicated space. @@ -384,8 +388,10 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase CSP_EVENT void SetAsyncCallCompletedCallback(AsyncCallCompletedCallbackHandler Callback); /// @brief Deserialises the AsyncCallCompleted event values. - /// The AsyncCallCompletedEventData will contain the name of the operation ("DuplicateSpaceAsync"), the reference Id of the newly created Space as - /// well as the reference type ("GroupId"). + /// The AsyncCallCompletedEventData returned by the AsyncCallCompletedCallback will contain the following information: + /// - OperationName: "DuplicateSpaceAsync". + /// - ReferenceId: Id of the newly duplicated Space. + /// - ReferenceType: "GroupId". /// @param EventValues std::vector : event values to deserialise CSP_NO_EXPORT void OnAsyncCallCompletedEvent(const csp::common::NetworkEventData& NetworkEventData); From e6d8ab21c72f7e5a7999dc6b50f11ebde8332e88 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 09:55:06 +0000 Subject: [PATCH 05/10] [OF-1736] test: Test updates -Updated the DuplicateSpaceAsyncTest promise to capture the NetworkEventData rather than asserting equality within the lambda. - Added a 30 second timeout to the future wait to account for the async operation timing out due to backed service load. - Updated the EXPECT_* to be ASSERT_*. --- Tests/src/PublicAPITests/SpaceSystemTests.cpp | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/Tests/src/PublicAPITests/SpaceSystemTests.cpp b/Tests/src/PublicAPITests/SpaceSystemTests.cpp index 6019a69d7..1bc41a8d2 100644 --- a/Tests/src/PublicAPITests/SpaceSystemTests.cpp +++ b/Tests/src/PublicAPITests/SpaceSystemTests.cpp @@ -3223,16 +3223,16 @@ CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceTest) auto [Result] = AWAIT_PRE(SpaceSystem, DuplicateSpace, RequestPredicate, Space.Id, UniqueSpaceName, SpaceAttributes::Private, nullptr, true); - EXPECT_EQ(Result.GetResultCode(), EResultCode::Success); + ASSERT_EQ(Result.GetResultCode(), EResultCode::Success); const auto& NewSpace = Result.GetSpace(); - EXPECT_NE(NewSpace.Id, Space.Id); - EXPECT_EQ(NewSpace.Name, UniqueSpaceName); - EXPECT_EQ(NewSpace.Description, Space.Description); - EXPECT_EQ(NewSpace.Attributes, SpaceAttributes::Private); - EXPECT_EQ(NewSpace.OwnerId, UserId); - EXPECT_NE(Space.OwnerId, UserId); + ASSERT_NE(NewSpace.Id, Space.Id); + ASSERT_EQ(NewSpace.Name, UniqueSpaceName); + ASSERT_EQ(NewSpace.Description, Space.Description); + ASSERT_EQ(NewSpace.Attributes, SpaceAttributes::Private); + ASSERT_EQ(NewSpace.OwnerId, UserId); + ASSERT_NE(Space.OwnerId, UserId); // Ensure we can enter the newly duplicated Space std::unique_ptr RealtimeEngine { SystemsManager.MakeOnlineRealtimeEngine() }; @@ -3296,21 +3296,15 @@ CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceAsyncTest) LogOut(UserSystem); LogIn(UserSystem, UserId, AlternativeUser.Email, GeneratedTestAccountPassword); - csp::common::String NewSpaceId; + String NewSpaceId; // Attempt to duplicate space asynchrously { - std::promise AsyncCallCompletedPromise; - std::future AsyncCallCompletedFuture = AsyncCallCompletedPromise.get_future(); + std::promise> AsyncCallCompletedPromise; + std::future> AsyncCallCompletedFuture = AsyncCallCompletedPromise.get_future(); - auto AsyncCallCompletedCallback = [&](const csp::common::AsyncCallCompletedEventData& NetworkEventData) - { - EXPECT_EQ(NetworkEventData.OperationName, "DuplicateSpaceAsync"); - EXPECT_EQ(NetworkEventData.ReferenceType, "GroupId"); - - NewSpaceId = NetworkEventData.ReferenceId; - - AsyncCallCompletedPromise.set_value(true); + auto AsyncCallCompletedCallback = [&](const csp::common::AsyncCallCompletedEventData& NetworkEventData) { + AsyncCallCompletedPromise.set_value({ NetworkEventData.OperationName, NetworkEventData.ReferenceId, NetworkEventData.ReferenceType }); }; SpaceSystem->SetAsyncCallCompletedCallback(AsyncCallCompletedCallback); @@ -3320,11 +3314,24 @@ CSP_PUBLIC_TEST(CSPEngine, SpaceSystemTests, DuplicateSpaceAsyncTest) auto [Result] = AWAIT_PRE(SpaceSystem, DuplicateSpaceAsync, RequestPredicate, Space.Id, UniqueSpaceName, SpaceAttributes::Private, nullptr, true); - EXPECT_EQ(Result.GetResultCode(), EResultCode::Success); + ASSERT_EQ(Result.GetResultCode(), EResultCode::Success); + + // It is possible for this test to take an extended period of time to complete if the backend services are under load. + // We are therefore setting a timeout on waiting for the async callback to be received. + const std::chrono::seconds TimeoutDuration(30); + + std::future_status Status = AsyncCallCompletedFuture.wait_for(TimeoutDuration); + + ASSERT_NE(Status, std::future_status::timeout) << "The DuplicateSpaceAsync operation timed out after 30 seconds."; + + std::tuple AsyncCallResult = AsyncCallCompletedFuture.get(); + + String OperationName = std::get<0>(AsyncCallResult); + String ReferenceType = std::get<2>(AsyncCallResult); + NewSpaceId = std::get<1>(AsyncCallResult); - // Wait for the callback to be received - AsyncCallCompletedFuture.wait(); - EXPECT_TRUE(AsyncCallCompletedFuture.get() == true); + ASSERT_TRUE(OperationName == "DuplicateSpaceAsync"); + ASSERT_TRUE(ReferenceType == "GroupId"); } // Ensure we can enter the newly duplicated Space From 41243791d38a784c5caeba8c92b7f64a4c2a590d Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 14:53:31 +0000 Subject: [PATCH 06/10] [OF-1736] refac: Have the NetworkEventBus clean up event listeners in dtor Previously individual systems were responsible for deregistering their system callbacks with the NetworkEventBus on destruction. However, the NetworkEventBus (which is owned by the MultiplayerConnection) is one of the last systems to be cleaned up by the SystemsManager, so it made sense to move this logic to the NetworkEventBus dtor. --- Library/include/CSP/Systems/Assets/AssetSystem.h | 2 -- .../HotspotSequence/HotspotSequenceSystem.h | 2 -- .../CSP/Systems/Sequence/SequenceSystem.h | 2 -- Library/include/CSP/Systems/SystemBase.h | 3 --- Library/include/CSP/Systems/Users/UserSystem.h | 2 -- Library/src/Multiplayer/NetworkEventBus.cpp | 11 ++++++++++- Library/src/Systems/Assets/AssetSystem.cpp | 12 ------------ .../Conversation/ConversationSystemInternal.cpp | 11 +---------- .../Conversation/ConversationSystemInternal.h | 2 -- .../HotspotSequence/HotspotSequenceSystem.cpp | 11 ----------- Library/src/Systems/Sequence/SequenceSystem.cpp | 16 +--------------- Library/src/Systems/Spaces/SpaceSystem.cpp | 8 +------- Library/src/Systems/SystemBase.cpp | 11 +---------- Library/src/Systems/Users/UserSystem.cpp | 11 ----------- 14 files changed, 14 insertions(+), 90 deletions(-) diff --git a/Library/include/CSP/Systems/Assets/AssetSystem.h b/Library/include/CSP/Systems/Assets/AssetSystem.h index e342da8ef..0bbd2c4e9 100644 --- a/Library/include/CSP/Systems/Assets/AssetSystem.h +++ b/Library/include/CSP/Systems/Assets/AssetSystem.h @@ -354,8 +354,6 @@ class CSP_API AssetSystem : public SystemBase /// @brief Registers the system to listen for the named event. void RegisterSystemCallback() override; - /// @brief Deregisters the system from listening for the named event. - void DeregisterSystemCallback() override; /// @brief Deserialises the event values of the system. /// @param EventValues std::vector : event values to deserialise CSP_NO_EXPORT void OnAssetDetailBlobChangedEvent(const csp::common::NetworkEventData& NetworkEventData); diff --git a/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h b/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h index 304a2fe31..c027a95c4 100644 --- a/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h +++ b/Library/include/CSP/Systems/HotspotSequence/HotspotSequenceSystem.h @@ -100,8 +100,6 @@ class CSP_API HotspotSequenceSystem : public SystemBase /// @brief Registers the system to listen for the named event. void RegisterSystemCallback() override; - /// @brief Deregisters the system from listening for the named event. - void DeregisterSystemCallback() override; /// @brief Deserialises the event values of the system. /// @param EventValues std::vector : event values to deserialise CSP_NO_EXPORT void OnSequenceChangedEvent(const csp::common::NetworkEventData& NetworkEventData); diff --git a/Library/include/CSP/Systems/Sequence/SequenceSystem.h b/Library/include/CSP/Systems/Sequence/SequenceSystem.h index b1e5699d7..c2594196c 100644 --- a/Library/include/CSP/Systems/Sequence/SequenceSystem.h +++ b/Library/include/CSP/Systems/Sequence/SequenceSystem.h @@ -119,8 +119,6 @@ class CSP_API SequenceSystem : public SystemBase /// @brief Registers the system to listen for the named event. void RegisterSystemCallback() override; - /// @brief Deregisters the system from listening for the named event. - void DeregisterSystemCallback() override; /// @brief Deserialises the event values of the system. /// @param EventValues std::vector : event values to deserialise CSP_NO_EXPORT void OnSequenceChangedEvent(const csp::common::NetworkEventData& NetworkEventData); diff --git a/Library/include/CSP/Systems/SystemBase.h b/Library/include/CSP/Systems/SystemBase.h index cf6ef3a09..9fbcefc53 100644 --- a/Library/include/CSP/Systems/SystemBase.h +++ b/Library/include/CSP/Systems/SystemBase.h @@ -71,9 +71,6 @@ class CSP_API CSP_NO_DISPOSE SystemBase /// @brief Registers the system to listen for the default event. virtual void RegisterSystemCallback(); - /// @brief Deregisters the system from listening for the default event. - virtual void DeregisterSystemCallback(); - protected: // EM, June2025: Having this on system base makes it quite simple to quit using the singleton macros in all the systems if we wanted to. // Should NOT be null. The only reason this is a pointer is because we can't get the wrapper gen work required to support reference injections diff --git a/Library/include/CSP/Systems/Users/UserSystem.h b/Library/include/CSP/Systems/Users/UserSystem.h index d92fa2950..dc82a2493 100644 --- a/Library/include/CSP/Systems/Users/UserSystem.h +++ b/Library/include/CSP/Systems/Users/UserSystem.h @@ -291,8 +291,6 @@ class CSP_API UserSystem : public SystemBase /// @brief Registers the system to listen for the named event. void RegisterSystemCallback() override; - /// @brief Deregisters the system from listening for the named event. - void DeregisterSystemCallback() override; /// @brief Deserialises the event values of the system. /// @param EventValues std::vector : event values to deserialise CSP_NO_EXPORT void OnAccessControlChangedEvent(const csp::common::NetworkEventData& NetworkEventData); diff --git a/Library/src/Multiplayer/NetworkEventBus.cpp b/Library/src/Multiplayer/NetworkEventBus.cpp index da68a33da..706999d45 100644 --- a/Library/src/Multiplayer/NetworkEventBus.cpp +++ b/Library/src/Multiplayer/NetworkEventBus.cpp @@ -34,7 +34,16 @@ namespace csp::multiplayer constexpr const uint64_t ALL_CLIENTS_ID = std::numeric_limits::max(); -NetworkEventBus::~NetworkEventBus() { } +NetworkEventBus::~NetworkEventBus() +{ + // Clean up all registered listeners. + // The NetworkEventBus is owned by the MultiplayerConnection which is one of the last systems to be destroyed by the Systems Manager. + auto Registrations = AllRegistrations(); + for (const NetworkEventRegistration& Registration : Registrations) + { + StopListenNetworkEvent(Registration); + } +} NetworkEventBus::NetworkEventBus(MultiplayerConnection* InMultiplayerConnection, csp::common::LogSystem& LogSystem) : LogSystem(LogSystem) diff --git a/Library/src/Systems/Assets/AssetSystem.cpp b/Library/src/Systems/Assets/AssetSystem.cpp index 2a3bd3a5b..7e1a21cd5 100644 --- a/Library/src/Systems/Assets/AssetSystem.cpp +++ b/Library/src/Systems/Assets/AssetSystem.cpp @@ -375,8 +375,6 @@ AssetSystem::~AssetSystem() delete (AssetDetailAPI); delete (PrototypeAPI); - - DeregisterSystemCallback(); } void AssetSystem::DeleteAssetCollectionById(const csp::common::String& AssetCollectionId, NullResultCallback Callback) @@ -1801,16 +1799,6 @@ void AssetSystem::RegisterSystemCallback() [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnAssetDetailBlobChangedEvent(NetworkEventData); }); } -void AssetSystem::DeregisterSystemCallback() -{ - if (EventBusPtr) - { - - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::AssetSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AssetDetailBlobChanged))); - } -} - void AssetSystem::OnAssetDetailBlobChangedEvent(const csp::common::NetworkEventData& NetworkEventData) { if (!AssetDetailBlobChangedCallback && !MaterialChangedCallback) diff --git a/Library/src/Systems/Conversation/ConversationSystemInternal.cpp b/Library/src/Systems/Conversation/ConversationSystemInternal.cpp index 7ce253c2b..dcef5422b 100644 --- a/Library/src/Systems/Conversation/ConversationSystemInternal.cpp +++ b/Library/src/Systems/Conversation/ConversationSystemInternal.cpp @@ -344,7 +344,7 @@ ConversationSystemInternal::ConversationSystemInternal(systems::AssetSystem* Ass RegisterSystemCallback(); } -ConversationSystemInternal::~ConversationSystemInternal() { DeregisterSystemCallback(); } +ConversationSystemInternal::~ConversationSystemInternal() { } void ConversationSystemInternal::CreateConversation(const common::String& Message, StringResultCallback Callback) { @@ -1153,15 +1153,6 @@ void ConversationSystemInternal::RegisterSystemCallback() }); } -void ConversationSystemInternal::DeregisterSystemCallback() -{ - if (EventBusPtr) - { - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::ConversationSystemInternal", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::Conversation))); - } -} - void ConversationSystemInternal::FlushEvents() { for (auto It = std::begin(Events); It != std::end(Events);) diff --git a/Library/src/Systems/Conversation/ConversationSystemInternal.h b/Library/src/Systems/Conversation/ConversationSystemInternal.h index ef95b9062..2ec70b87b 100644 --- a/Library/src/Systems/Conversation/ConversationSystemInternal.h +++ b/Library/src/Systems/Conversation/ConversationSystemInternal.h @@ -111,8 +111,6 @@ class CSP_API ConversationSystemInternal : public SystemBase /// @brief Registers the system to listen for the named event. void RegisterSystemCallback() override; - /// @brief Deregisters the system from listening for the named event. - void DeregisterSystemCallback() override; // Attempt to flush any events that haven't been sent. // They may fail to send in situtations where the conversation component hasn't been created before the creation event fires. diff --git a/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp b/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp index 771d75c82..a1e63b586 100644 --- a/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp +++ b/Library/src/Systems/HotspotSequence/HotspotSequenceSystem.cpp @@ -263,8 +263,6 @@ HotspotSequenceSystem::~HotspotSequenceSystem() { SpaceSystem = nullptr; SequenceSystem = nullptr; - - DeregisterSystemCallback(); } void HotspotSequenceSystem::RemoveItemFromGroups(const csp::common::String& ItemID, csp::systems::NullResultCallback /*Callback*/) @@ -343,15 +341,6 @@ void HotspotSequenceSystem::RegisterSystemCallback() [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnSequenceChangedEvent(NetworkEventData); }); } -void HotspotSequenceSystem::DeregisterSystemCallback() -{ - if (EventBusPtr) - { - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::HotspotSequenceSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::SequenceChanged))); - } -} - void HotspotSequenceSystem::OnSequenceChangedEvent(const csp::common::NetworkEventData& NetworkEventData) { // This may be either a hotspot sequence event or a regular sequence event.. we're only interested in hotspot. diff --git a/Library/src/Systems/Sequence/SequenceSystem.cpp b/Library/src/Systems/Sequence/SequenceSystem.cpp index f6891667d..fefb879ea 100644 --- a/Library/src/Systems/Sequence/SequenceSystem.cpp +++ b/Library/src/Systems/Sequence/SequenceSystem.cpp @@ -311,12 +311,7 @@ SequenceSystem::SequenceSystem(web::WebClient* WebClient, multiplayer::NetworkEv RegisterSystemCallback(); } -SequenceSystem::~SequenceSystem() -{ - delete (SequenceAPI); - - DeregisterSystemCallback(); -} +SequenceSystem::~SequenceSystem() { delete (SequenceAPI); } void SequenceSystem::SetSequenceChangedCallback(SequenceChangedCallbackHandler Callback) { @@ -343,15 +338,6 @@ void SequenceSystem::RegisterSystemCallback() [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnSequenceChangedEvent(NetworkEventData); }); } -void SequenceSystem::DeregisterSystemCallback() -{ - if (EventBusPtr) - { - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::SequenceSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::SequenceChanged))); - } -} - void SequenceSystem::OnSequenceChangedEvent(const csp::common::NetworkEventData& NetworkEventData) { // This may be either a hotspot sequence event or a regular sequence event.. we're only interested in non-hotspot. diff --git a/Library/src/Systems/Spaces/SpaceSystem.cpp b/Library/src/Systems/Spaces/SpaceSystem.cpp index e532801c1..ac7116e56 100644 --- a/Library/src/Systems/Spaces/SpaceSystem.cpp +++ b/Library/src/Systems/Spaces/SpaceSystem.cpp @@ -108,13 +108,7 @@ SpaceSystem::SpaceSystem(csp::web::WebClient* WebClient, multiplayer::NetworkEve SpaceAPI = new chsaggregation::SpaceApi(WebClient); } -SpaceSystem::~SpaceSystem() -{ - delete (GroupAPI); - - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::SpaceSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AsyncCallCompleted))); -} +SpaceSystem::~SpaceSystem() { delete (GroupAPI); } /* CreateSpace Continuations */ async::task SpaceSystem::CreateSpaceGroupInfo( diff --git a/Library/src/Systems/SystemBase.cpp b/Library/src/Systems/SystemBase.cpp index 2a24953a2..31342fbd6 100644 --- a/Library/src/Systems/SystemBase.cpp +++ b/Library/src/Systems/SystemBase.cpp @@ -42,20 +42,11 @@ SystemBase::SystemBase(csp::multiplayer::NetworkEventBus* EventBus, csp::common: { } -SystemBase::~SystemBase() -{ - DeregisterSystemCallback(); - EventBusPtr = nullptr; -} +SystemBase::~SystemBase() { EventBusPtr = nullptr; } void SystemBase::RegisterSystemCallback() { // Do nothing. } -void SystemBase::DeregisterSystemCallback() -{ - // Do nothing. -} - } // namespace csp::systems diff --git a/Library/src/Systems/Users/UserSystem.cpp b/Library/src/Systems/Users/UserSystem.cpp index 71514d2ea..8a9db3b4e 100644 --- a/Library/src/Systems/Users/UserSystem.cpp +++ b/Library/src/Systems/Users/UserSystem.cpp @@ -199,8 +199,6 @@ UserSystem::~UserSystem() delete (ProfileAPI); delete (AuthenticationAPI); delete (StripeAPI); - - DeregisterSystemCallback(); } void UserSystem::SetNetworkEventBus(csp::multiplayer::NetworkEventBus& EventBus) @@ -929,15 +927,6 @@ void UserSystem::RegisterSystemCallback() [this](const csp::common::NetworkEventData& NetworkEventData) { this->OnAccessControlChangedEvent(NetworkEventData); }); } -void UserSystem::DeregisterSystemCallback() -{ - if (EventBusPtr) - { - EventBusPtr->StopListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("CSPInternal::UserSystem", - csp::multiplayer::NetworkEventBus::StringFromNetworkEvent(csp::multiplayer::NetworkEventBus::NetworkEvent::AccessControlChanged))); - } -} - void UserSystem::OnAccessControlChangedEvent(const csp::common::NetworkEventData& NetworkEventData) { if (!UserPermissionsChangedCallback) From 0d8959f4cbc855aeff63d0bd037d30e4bd3f65e7 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 15:04:39 +0000 Subject: [PATCH 07/10] [OF-1736] docs: Added docs for AsyncCallCompletedEventData class --- Library/include/CSP/Common/NetworkEventData.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Library/include/CSP/Common/NetworkEventData.h b/Library/include/CSP/Common/NetworkEventData.h index d5635dd4f..8b67eb43e 100644 --- a/Library/include/CSP/Common/NetworkEventData.h +++ b/Library/include/CSP/Common/NetworkEventData.h @@ -152,6 +152,8 @@ class CSP_API SequenceChangedNetworkEventData : public NetworkEventData csp::common::Optional HotspotData = nullptr; }; +// @brief Data for an event signalling the completion of an async operation. +// This is general purpose event data that can be used by any system exposing async operations. class CSP_API AsyncCallCompletedEventData : public NetworkEventData { public: From e000f110a722e67722b1d5130eb05b2fcd7d7ef1 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 15:40:26 +0000 Subject: [PATCH 08/10] [OF-1736] docs: Updated docs Updated docs for the DuplicateSpace and DuplicateSpaceAsync methods to outline behaviour if the user disconnects while the operation is being carried out. --- Library/include/CSP/Systems/Spaces/SpaceSystem.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Library/include/CSP/Systems/Spaces/SpaceSystem.h b/Library/include/CSP/Systems/Spaces/SpaceSystem.h index cfdbc3620..2aa75e3dc 100644 --- a/Library/include/CSP/Systems/Spaces/SpaceSystem.h +++ b/Library/include/CSP/Systems/Spaces/SpaceSystem.h @@ -344,7 +344,8 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase CSP_ASYNC_RESULT void DeleteSpaceGeoLocation(const csp::common::String& SpaceId, NullResultCallback Callback); /// @brief Duplicate an existing space and assign it to the current user. - /// This is a synchronous operation and can have a high execution time for complex spaces. + /// This is a synchronous operation and can have a high execution time for complex spaces. If the user disconnects while waiting for the operation + /// to complete, the duplicate space request will be cancelled. /// \deprecated Use DuplicateSpaceAsync() instead. This method performs a synchronous duplication of a Space which can timeout and fail for /// complex Spaces or if the backend services are under excessive load. /// @param SpaceId csp::common::String : Id of the space to duplicate. @@ -359,9 +360,9 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase const csp::common::Optional>& MemberGroupIds, bool ShallowCopy, SpaceResultCallback Callback); /// @brief Duplicate an existing space and assign it to the current user. - /// This is an asynchronous operation. Please subcribe to the AsyncCallCompletedCallback via @ref SpaceSystem::SetAsyncCallCompletedCallback() to - /// be notified when the duplication operation is complete. The AsyncCallCompletedEventData returned by the AsyncCallCompletedCallback will - /// contain the following information: + /// This is an asynchronous operation. If the user disconnects while waiting for the operation to complete it will continue unaffected. Please + /// subcribe to the AsyncCallCompletedCallback via @ref SpaceSystem::SetAsyncCallCompletedCallback() to be notified when the duplication operation + /// is complete. The AsyncCallCompletedEventData returned by the AsyncCallCompletedCallback will contain the following information: /// - OperationName: "DuplicateSpaceAsync". /// - ReferenceId: Id of the newly duplicated Space. /// - ReferenceType: "GroupId". From ce05c62cee81ad5609d4c4fa637170e2b91816c4 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Thu, 30 Oct 2025 17:09:55 +0000 Subject: [PATCH 09/10] [OF-1736] refac: Updates to SpaceSystem - Inject UserSystem into the SpaceSystem via it's ctor so that it can be used without having to rely on the singleton. - Adopt the Convert utility for creating a vector of MemberGroupIds from the provided Optional Array. --- .../include/CSP/Systems/Spaces/SpaceSystem.h | 7 +++- Library/src/Systems/Spaces/SpaceSystem.cpp | 33 ++++++++++--------- Library/src/Systems/SystemsManager.cpp | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Library/include/CSP/Systems/Spaces/SpaceSystem.h b/Library/include/CSP/Systems/Spaces/SpaceSystem.h index 2aa75e3dc..593edf5b7 100644 --- a/Library/include/CSP/Systems/Spaces/SpaceSystem.h +++ b/Library/include/CSP/Systems/Spaces/SpaceSystem.h @@ -55,6 +55,8 @@ CSP_END_IGNORE namespace csp::systems { +class UserSystem; + /// @ingroup Space System /// @brief Public facing system that allows interfacing with Magnopus Connected Services' concept of a Group. /// Offers methods for creating, deleting and joining spaces. @@ -398,7 +400,8 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase private: SpaceSystem(); // This constructor is only provided to appease the wrapper generator and should not be used - SpaceSystem(csp::web::WebClient* WebClient, csp::multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem); + SpaceSystem( + csp::web::WebClient* WebClient, csp::multiplayer::NetworkEventBus& EventBus, UserSystem* UserSystem, csp::common::LogSystem& LogSystem); ~SpaceSystem(); // Space Metadata @@ -441,6 +444,8 @@ class CSP_API CSP_NO_DISPOSE SpaceSystem : public SystemBase auto AddUserToSpaceIfNecessary(SpaceResultCallback Callback, SpaceSystem& SpaceSystem); auto FireEnterSpaceEvent(Space& OutCurrentSpace); + UserSystem* UserSystem; + csp::services::ApiBase* GroupAPI; csp::services::ApiBase* SpaceAPI; Space CurrentSpace; diff --git a/Library/src/Systems/Spaces/SpaceSystem.cpp b/Library/src/Systems/Spaces/SpaceSystem.cpp index ac7116e56..e2df42149 100644 --- a/Library/src/Systems/Spaces/SpaceSystem.cpp +++ b/Library/src/Systems/Spaces/SpaceSystem.cpp @@ -60,12 +60,13 @@ constexpr const int MAX_SPACES_RESULTS = 100; // Construct a new DuplicateSpaceOptions dto request object. This function is called by both DuplicateSpace and DuplicateSpaceAsync methods. // The only difference is in the value they pass for the AsyncCall parameter. -std::shared_ptr ConstructDuplicateSpaceOptions(const String& SpaceId, const String& NewName, - csp::systems::SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, bool AsyncCall) +std::shared_ptr ConstructDuplicateSpaceOptions(csp::systems::UserSystem* UserSystem, const String& SpaceId, + const String& NewName, csp::systems::SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, + bool AsyncCall) { auto Request = std::make_shared(); Request->SetSpaceId(SpaceId); - Request->SetNewGroupOwnerId(csp::systems::SystemsManager::Get().GetUserSystem()->GetLoginState().UserId); + Request->SetNewGroupOwnerId(UserSystem->GetLoginState().UserId); Request->SetNewUniqueName(NewName); Request->SetDiscoverable(HasFlag(NewAttributes, csp::systems::SpaceAttributes::IsDiscoverable)); Request->SetRequiresInvite(HasFlag(NewAttributes, csp::systems::SpaceAttributes::RequiresInvite)); @@ -74,15 +75,9 @@ std::shared_ptr ConstructDuplicateSpaceOp if (MemberGroupIds.HasValue()) { - std::vector GroupIds; - GroupIds.reserve(MemberGroupIds->Size()); + auto MemberGroupIdsVec = Convert(MemberGroupIds); - for (size_t i = 0; i < MemberGroupIds->Size(); ++i) - { - GroupIds.push_back(MemberGroupIds->operator[](i)); - } - - Request->SetMemberGroupIds(GroupIds); + Request->SetMemberGroupIds(*MemberGroupIdsVec); } return Request; @@ -95,20 +90,27 @@ namespace csp::systems SpaceSystem::SpaceSystem() : SystemBase(nullptr, nullptr, nullptr) + , UserSystem(nullptr) , GroupAPI(nullptr) , SpaceAPI(nullptr) { } -SpaceSystem::SpaceSystem(csp::web::WebClient* WebClient, multiplayer::NetworkEventBus& EventBus, csp::common::LogSystem& LogSystem) +SpaceSystem::SpaceSystem( + csp::web::WebClient* WebClient, multiplayer::NetworkEventBus& EventBus, csp::systems::UserSystem* UserSystem, csp::common::LogSystem& LogSystem) : SystemBase(WebClient, &EventBus, &LogSystem) + , UserSystem(UserSystem) , CurrentSpace() { GroupAPI = new chs::GroupApi(WebClient); SpaceAPI = new chsaggregation::SpaceApi(WebClient); } -SpaceSystem::~SpaceSystem() { delete (GroupAPI); } +SpaceSystem::~SpaceSystem() +{ + delete (GroupAPI); + delete (SpaceAPI); +} /* CreateSpace Continuations */ async::task SpaceSystem::CreateSpaceGroupInfo( @@ -745,7 +747,6 @@ void SpaceSystem::DeleteSpace(const csp::common::String& SpaceId, NullResultCall void SpaceSystem::GetSpaces(SpacesResultCallback Callback) { - const auto* UserSystem = SystemsManager::Get().GetUserSystem(); const String InUserId = UserSystem->GetLoginState().UserId; csp::services::ResponseHandlerPtr ResponseHandler @@ -1955,7 +1956,7 @@ void SpaceSystem::DeleteSpaceGeoLocation(const csp::common::String& SpaceId, Nul void SpaceSystem::DuplicateSpace(const String& SpaceId, const String& NewName, SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, SpaceResultCallback Callback) { - auto Request = ConstructDuplicateSpaceOptions(SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, false); + auto Request = ConstructDuplicateSpaceOptions(UserSystem, SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, false); csp::services::ResponseHandlerPtr ResponseHandler = SpaceAPI->CreateHandler(Callback, nullptr); @@ -1973,7 +1974,7 @@ void SpaceSystem::DuplicateSpace(const String& SpaceId, const String& NewName, S void SpaceSystem::DuplicateSpaceAsync(const String& SpaceId, const String& NewName, SpaceAttributes NewAttributes, const Optional>& MemberGroupIds, bool ShallowCopy, NullResultCallback Callback) { - auto Request = ConstructDuplicateSpaceOptions(SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, true); + auto Request = ConstructDuplicateSpaceOptions(UserSystem, SpaceId, NewName, NewAttributes, MemberGroupIds, ShallowCopy, true); csp::services::ResponseHandlerPtr ResponseHandler = SpaceAPI->CreateHandler(Callback, nullptr); diff --git a/Library/src/Systems/SystemsManager.cpp b/Library/src/Systems/SystemsManager.cpp index c92dccdb5..9e8d71e6a 100644 --- a/Library/src/Systems/SystemsManager.cpp +++ b/Library/src/Systems/SystemsManager.cpp @@ -190,7 +190,7 @@ void SystemsManager::CreateSystems(csp::multiplayer::ISignalRConnection* SignalR // SystemBase inheritors - SpaceSystem = new csp::systems::SpaceSystem(WebClient, MultiplayerConnection->GetEventBus(), *LogSystem); + SpaceSystem = new csp::systems::SpaceSystem(WebClient, MultiplayerConnection->GetEventBus(), UserSystem, *LogSystem); AssetSystem = new csp::systems::AssetSystem(WebClient, MultiplayerConnection->GetEventBus(), *LogSystem); AnchorSystem = new csp::systems::AnchorSystem(WebClient, *LogSystem); PointOfInterestSystem = new csp::systems::PointOfInterestInternalSystem(WebClient, *LogSystem); From 40ad68ae83453d8908efb8d6db9b5081c3c8d113 Mon Sep 17 00:00:00 2001 From: MAG-AdamThorn Date: Fri, 31 Oct 2025 17:33:03 +0000 Subject: [PATCH 10/10] [OF-1736] fix: Update public getter for EventBus to return a ptr Updated the SystemsManager::GetEventBus() method to return a ptr to the EventBus. I had updated it to return a ref forgetting that the wrapper generator does not support that. --- Library/include/CSP/Systems/SystemsManager.h | 2 +- Library/src/Systems/SystemsManager.cpp | 4 +- .../src/RunnableTests/EventBusPing.cpp | 4 +- Tests/src/PublicAPITests/AssetSystemTests.cpp | 2 +- .../ConversationSystemTests.cpp | 6 +- Tests/src/PublicAPITests/EventBusTests.cpp | 82 +++++++++---------- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/Library/include/CSP/Systems/SystemsManager.h b/Library/include/CSP/Systems/SystemsManager.h index a3f9e27ae..5e992d633 100644 --- a/Library/include/CSP/Systems/SystemsManager.h +++ b/Library/include/CSP/Systems/SystemsManager.h @@ -171,7 +171,7 @@ class CSP_API SystemsManager csp::multiplayer::MultiplayerConnection* GetMultiplayerConnection(); - csp::multiplayer::NetworkEventBus& GetEventBus(); + csp::multiplayer::NetworkEventBus* GetEventBus(); // Convenience methods for the moment. This will need to be broken at formal modularization, but the standard pattern it creates throughout // integrations/tests will no doubt be helpful in doing that anyhow, rather than having big constructors everywhere. diff --git a/Library/src/Systems/SystemsManager.cpp b/Library/src/Systems/SystemsManager.cpp index 9e8d71e6a..ea828df94 100644 --- a/Library/src/Systems/SystemsManager.cpp +++ b/Library/src/Systems/SystemsManager.cpp @@ -102,11 +102,11 @@ ExternalServiceProxySystem* SystemsManager::GetExternalServicesProxySystem() { r csp::multiplayer::MultiplayerConnection* SystemsManager::GetMultiplayerConnection() { return MultiplayerConnection; } -csp::multiplayer::NetworkEventBus& SystemsManager::GetEventBus() { return MultiplayerConnection->GetEventBus(); } +csp::multiplayer::NetworkEventBus* SystemsManager::GetEventBus() { return &MultiplayerConnection->GetEventBus(); } csp::multiplayer::OnlineRealtimeEngine* SystemsManager::MakeOnlineRealtimeEngine() { - return new csp::multiplayer::OnlineRealtimeEngine { *GetMultiplayerConnection(), *GetLogSystem(), GetEventBus(), *GetScriptSystem() }; + return new csp::multiplayer::OnlineRealtimeEngine { *GetMultiplayerConnection(), *GetLogSystem(), *GetEventBus(), *GetScriptSystem() }; } csp::multiplayer::OfflineRealtimeEngine* SystemsManager::MakeOfflineRealtimeEngine() diff --git a/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp b/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp index 42fecf599..7fa7f8a71 100644 --- a/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp +++ b/MultiplayerTestRunner/src/RunnableTests/EventBusPing.cpp @@ -28,10 +28,10 @@ namespace EventBusPing void RunTest() { // Listen for an event, then ping it back to the client that sent it. - csp::systems::SystemsManager::Get().GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("Receiver", "EventPingRequest"), + csp::systems::SystemsManager::Get().GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration("Receiver", "EventPingRequest"), [](const csp::common::NetworkEventData& NetworkEventData) { - csp::systems::SystemsManager::Get().GetEventBus().SendNetworkEventToClient( + csp::systems::SystemsManager::Get().GetEventBus()->SendNetworkEventToClient( "EventPingResponse", {}, NetworkEventData.SenderClientId, [](csp::multiplayer::ErrorCode) {}); }); } diff --git a/Tests/src/PublicAPITests/AssetSystemTests.cpp b/Tests/src/PublicAPITests/AssetSystemTests.cpp index 249b3349b..eefb86203 100644 --- a/Tests/src/PublicAPITests/AssetSystemTests.cpp +++ b/Tests/src/PublicAPITests/AssetSystemTests.cpp @@ -2114,7 +2114,7 @@ CSP_PUBLIC_TEST(CSPEngine, AssetSystemTests, AssetProcessGracefulFailureCallback csp::common::ReplicatedValue Param4 = ""; csp::common::ReplicatedValue Param5 = ""; - SystemsManager.GetEventBus().SendNetworkEventToClient( + SystemsManager.GetEventBus()->SendNetworkEventToClient( NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::AssetDetailBlobChanged), { Param1, Param2, Param3, Param4, Param5 }, Connection->GetClientId(), [](ErrorCode Error) { EXPECT_EQ(Error, ErrorCode::None); }); diff --git a/Tests/src/PublicAPITests/ConversationSystemTests.cpp b/Tests/src/PublicAPITests/ConversationSystemTests.cpp index 249ef2af9..446619274 100644 --- a/Tests/src/PublicAPITests/ConversationSystemTests.cpp +++ b/Tests/src/PublicAPITests/ConversationSystemTests.cpp @@ -117,7 +117,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventTest) bool EventSent = false; - SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus()->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); @@ -152,7 +152,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventTest) bool EventSent = false; - SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus()->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); @@ -208,7 +208,7 @@ CSP_PUBLIC_TEST(CSPEngine, ConversationSystemTests, ConversationSystemEventDelay bool EventSent = false; - SystemsManager.GetEventBus().SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), + SystemsManager.GetEventBus()->SendNetworkEventToClient(NetworkEventBus::StringFromNetworkEvent(NetworkEventBus::NetworkEvent::Conversation), csp::systems::ConversationSystemHelpers::MessageInfoToReplicatedValueArray(Params.MessageType, Params.MessageInfo), Connection->GetClientId(), [&EventSent](csp::multiplayer::ErrorCode) { EventSent = true; }); diff --git a/Tests/src/PublicAPITests/EventBusTests.cpp b/Tests/src/PublicAPITests/EventBusTests.cpp index 925487acb..bba4d3375 100644 --- a/Tests/src/PublicAPITests/EventBusTests.cpp +++ b/Tests/src/PublicAPITests/EventBusTests.cpp @@ -72,17 +72,17 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregister) const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; - const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus().AllRegistrations(); - SystemsManager.GetEventBus().ListenNetworkEvent( + const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus()->AllRegistrations(); + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - const csp::common::Array AddedRegistration = SystemsManager.GetEventBus().AllRegistrations(); + const csp::common::Array AddedRegistration = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_TRUE(AddedRegistration.Size() == InitialRegisteredEvents.Size() + 1); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); - SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus()->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus().AllRegistrations(); + const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_TRUE(RemovedRegistration.Size() == InitialRegisteredEvents.Size()); EXPECT_FALSE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); } @@ -100,20 +100,20 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) const char* EventName3 = "TestEventName3"; - const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus().AllRegistrations(); - SystemsManager.GetEventBus().ListenNetworkEvent( + const csp::common::Array InitialRegisteredEvents = SystemsManager.GetEventBus()->AllRegistrations(); + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName3 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName3 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - const csp::common::Array AddedRegistration = SystemsManager.GetEventBus().AllRegistrations(); + const csp::common::Array AddedRegistration = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_TRUE(AddedRegistration.Size() == InitialRegisteredEvents.Size() + 6); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); @@ -123,9 +123,9 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName2 })); EXPECT_TRUE(AddedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName3 })); - SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus()->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus().AllRegistrations(); + const csp::common::Array RemovedRegistration = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_TRUE(RemovedRegistration.Size() == InitialRegisteredEvents.Size() + 5); EXPECT_FALSE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName2 })); @@ -134,9 +134,9 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RegisterDeregisterMulti) EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName2 })); EXPECT_TRUE(RemovedRegistration.ToList().Contains(NetworkEventRegistration { ReceiverId2, EventName3 })); - SystemsManager.GetEventBus().StopListenAllNetworkEvents(ReceiverId2); + SystemsManager.GetEventBus()->StopListenAllNetworkEvents(ReceiverId2); - const csp::common::Array RemovedAllTestReceivedOneRegistrations = SystemsManager.GetEventBus().AllRegistrations(); + const csp::common::Array RemovedAllTestReceivedOneRegistrations = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_TRUE(RemovedAllTestReceivedOneRegistrations.Size() == InitialRegisteredEvents.Size() + 2); EXPECT_FALSE(RemovedAllTestReceivedOneRegistrations.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName })); EXPECT_TRUE(RemovedAllTestReceivedOneRegistrations.ToList().Contains(NetworkEventRegistration { ReceiverId, EventName2 })); @@ -160,8 +160,8 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectNullEvent) const char* ReceiverId = "TestReceiverId"; const char* EventName = "TestEventName"; - SystemsManager.GetEventBus().ListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }, nullptr); - auto AllRegistrations = SystemsManager.GetEventBus().AllRegistrations(); + SystemsManager.GetEventBus()->ListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }, nullptr); + auto AllRegistrations = SystemsManager.GetEventBus()->AllRegistrations(); EXPECT_FALSE(std::any_of(AllRegistrations.begin(), AllRegistrations.end(), [ReceiverId](const NetworkEventRegistration& Registration) { return Registration.EventReceiverId == ReceiverId; })); } @@ -194,22 +194,22 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectDuplicateRegistration) .c_str(); EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Warning, Error)).Times(1); - const auto StartSize = SystemsManager.GetEventBus().AllRegistrations().Size(); + const auto StartSize = SystemsManager.GetEventBus()->AllRegistrations().Size(); - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 1); - SystemsManager.GetEventBus().ListenNetworkEvent( + EXPECT_EQ(SystemsManager.GetEventBus()->AllRegistrations().Size(), StartSize + 1); + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 2); - SystemsManager.GetEventBus().ListenNetworkEvent( + EXPECT_EQ(SystemsManager.GetEventBus()->AllRegistrations().Size(), StartSize + 2); + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId, EventName2 }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 3); + EXPECT_EQ(SystemsManager.GetEventBus()->AllRegistrations().Size(), StartSize + 3); // This one should be rejected - SystemsManager.GetEventBus().ListenNetworkEvent( + SystemsManager.GetEventBus()->ListenNetworkEvent( NetworkEventRegistration { ReceiverId2, EventName }, [](const csp::common::NetworkEventData& /*NetworkEventData*/) {}); - EXPECT_EQ(SystemsManager.GetEventBus().AllRegistrations().Size(), StartSize + 3); + EXPECT_EQ(SystemsManager.GetEventBus()->AllRegistrations().Size(), StartSize + 3); } CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectUnknownDeregistration) @@ -231,8 +231,8 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, RejectUnknownDeregistration) EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Verbose, Error)).Times(1); EXPECT_CALL(MockLogger.MockLogCallback, Call(csp::common::LogLevel::Log, Error1)).Times(1); - SystemsManager.GetEventBus().StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); - SystemsManager.GetEventBus().StopListenAllNetworkEvents(ReceiverId); + SystemsManager.GetEventBus()->StopListenNetworkEvent(NetworkEventRegistration { ReceiverId, EventName }); + SystemsManager.GetEventBus()->StopListenAllNetworkEvents(ReceiverId); } CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventSingleReciever) @@ -262,11 +262,11 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventSingleReciever) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); - SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus()->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals = NetworkEventFuture.get(); EXPECT_EQ(ReceivedVals.Size(), 2); @@ -305,18 +305,18 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, SingleEventMultiReciever) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); std::promise> NetworkEventPromise1; std::future> NetworkEventFuture1 = NetworkEventPromise1.get_future(); - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId2, EventName), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId2, EventName), [&NetworkEventPromise1](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise1.set_value(NetworkEventData.EventValues); }); - SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus()->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); // Both recievers should recieve this event const csp::common::Array ReceivedVals = NetworkEventFuture.get(); @@ -360,14 +360,14 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, MultiEventSingleReceiver) const csp::common::Array ValsToSend = { csp::common::ReplicatedValue { TestValValue }, csp::common::ReplicatedValue { 1.0f } }; - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName), [&NetworkEventPromise](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise.set_value(NetworkEventData.EventValues); }); - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName2), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, EventName2), [&NetworkEventPromise1](const csp::common::NetworkEventData& NetworkEventData) { NetworkEventPromise1.set_value(NetworkEventData.EventValues); }); - SystemsManager.GetEventBus().SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus()->SendNetworkEventToClient(EventName, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals = NetworkEventFuture.get(); EXPECT_EQ(ReceivedVals.Size(), 2); @@ -379,7 +379,7 @@ CSP_PUBLIC_TEST(CSPEngine, EventBusTests, MultiEventSingleReceiver) // The other event should not have been recieved as it has not been fired EXPECT_TRUE(NetworkEventFuture1.wait_for(std::chrono::milliseconds { 0 }) != std::future_status::ready); - SystemsManager.GetEventBus().SendNetworkEventToClient(EventName2, ValsToSend, Connection->GetClientId(), ErrorCallback); + SystemsManager.GetEventBus()->SendNetworkEventToClient(EventName2, ValsToSend, Connection->GetClientId(), ErrorCallback); const csp::common::Array ReceivedVals1 = NetworkEventFuture1.get(); EXPECT_EQ(ReceivedVals1.Size(), 2); } @@ -452,7 +452,7 @@ CSP_PUBLIC_TEST(DISABLED_CSPEngine, EventBusTests, TestMulticastEventToAllClient const char* PintRequestEventName = "EventPingRequest"; const char* PingResponseEventName = "EventPingResponse"; - SystemsManager.GetEventBus().ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, PingResponseEventName), + SystemsManager.GetEventBus()->ListenNetworkEvent(csp::multiplayer::NetworkEventRegistration(ReceiverId, PingResponseEventName), [&ReceivedPings, &TwoPingsResponsePromise](const csp::common::NetworkEventData& /*NetworkEventData*/) { std::cout << "Received Event Bus Ping." << std::endl; @@ -464,7 +464,7 @@ CSP_PUBLIC_TEST(DISABLED_CSPEngine, EventBusTests, TestMulticastEventToAllClient }); // Send the ping event to all clients - SystemsManager.GetEventBus().SendNetworkEvent(PintRequestEventName, {}, [](ErrorCode Error) { ASSERT_EQ(Error, ErrorCode::None); }); + SystemsManager.GetEventBus()->SendNetworkEvent(PintRequestEventName, {}, [](ErrorCode Error) { ASSERT_EQ(Error, ErrorCode::None); }); // Expect to have had two responses auto Status = TwoPingsResponseFuture.wait_for(30s);