From 12d0d9e7b78edff156a4cdc3abfb42879126eab5 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Mon, 24 May 2021 12:49:38 -0700 Subject: [PATCH 1/3] The host will now have autonomy over the default player is has spawned for itself using the sv_defaultPlayerSpawnAsset cvar --- Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index ef8627fe54..39bbf6644e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -449,6 +449,7 @@ namespace Multiplayer { controlledEntity = entityList[0]; controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId()); + controlledEntity.GetNetBindComponent()->SetAllowAutonomy(true); } if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so From b5a0df00e1a14ad5f9aefb1063612953b3db8a5d Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 25 May 2021 17:21:03 -0700 Subject: [PATCH 2/3] Hosts which are not a dedicated server (meaning they also play the game) will spawn a default player for themselves --- .../Source/MultiplayerSystemComponent.cpp | 36 ++++++++++++++----- .../Code/Source/MultiplayerSystemComponent.h | 3 +- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 39bbf6644e..0818f605df 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -438,20 +438,16 @@ namespace Multiplayer m_connAcquiredEvent.Signal(datum); } + // Hosts will spawn a new default player prefab for the user that just connected if (GetAgentType() == MultiplayerAgentType::ClientServer || GetAgentType() == MultiplayerAgentType::DedicatedServer) { - PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1); - INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity()); - - NetworkEntityHandle controlledEntity; - if (entityList.size() > 0) + NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab(); + if (controlledEntity.Exists()) { - controlledEntity = entityList[0]; controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId()); - controlledEntity.GetNetBindComponent()->SetAllowAutonomy(true); } - + if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so { connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity)); @@ -523,6 +519,17 @@ namespace Multiplayer } } m_agentType = multiplayerType; + + // Spawn the default player for this host since the host is also a player (not a dedicated server) + if (m_agentType == MultiplayerAgentType::ClientServer) + { + NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab(); + if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent()) + { + controlledEntityNetBindComponent->SetAllowAutonomy(true); + } + } + AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType)); } @@ -630,6 +637,19 @@ namespace Multiplayer } } + NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab() + { + PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1); + INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity()); + + NetworkEntityHandle controlledEntity; + if (entityList.size() > 0) + { + controlledEntity = entityList[0]; + } + return controlledEntity; + } + void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index db83c50fb5..e8e05a9d4c 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -104,7 +104,8 @@ namespace Multiplayer void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom); void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector& commands); - + NetworkEntityHandle SpawnDefaultPlayerPrefab(); + AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session"); AzNetworking::INetworkInterface* m_networkInterface = nullptr; From 0f258954fbd8a0bd2279b4a29369dc0667c3f2bf Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Thu, 27 May 2021 22:29:40 -0700 Subject: [PATCH 3/3] Fix for unit test. Checking that AssetManager is ready before spawning entities; MultiplayerSystemComponent will attempt to spawn a default player on init(), but during unit tests the AssetManager isn't stood up --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index dda3f18ad4..eaf89f3489 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -402,8 +402,12 @@ namespace Multiplayer const AZ::Transform& transform ) { - INetworkEntityManager::EntityList returnList; - + EntityList returnList; + if (!AZ::Data::AssetManager::IsReady()) + { + return returnList; + } + auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName); // Required for sync-instantiation. Todo: keep the reference in NetworkSpawnableLibrary auto netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset(spawnableAssetId, AZ::Data::AssetLoadBehavior::PreLoad);