Merge pull request #4461 from aws-lumberyard-dev/LYN-7080_FixEditorServerConnectionRaceCondition

Fix EditorServer Connection
This commit is contained in:
Stephen Tramer
2021-10-08 11:07:52 -07:00
committed by GitHub
8 changed files with 44 additions and 6 deletions
@@ -48,6 +48,7 @@ namespace Multiplayer
using NotifyClientMigrationEvent = AZ::Event<const HostId&, uint64_t, ClientInputId>;
using NotifyEntityMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, const HostId&>;
using ConnectionAcquiredEvent = AZ::Event<MultiplayerAgentDatum>;
using ServerAcceptanceReceivedEvent = AZ::Event<>;
using SessionInitEvent = AZ::Event<AzNetworking::INetworkInterface*>;
using SessionShutdownEvent = AZ::Event<AzNetworking::INetworkInterface*>;
@@ -122,6 +123,10 @@ namespace Multiplayer
//! @param handler The ConnectionAcquiredEvent Handler to add
virtual void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) = 0;
//! Adds a ServerAcceptanceReceived Handler which is invoked when the client receives the accept packet from the server.
//! @param handler The ServerAcceptanceReceived Handler to add
virtual void AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) = 0;
//! Adds a SessionInitEvent Handler which is invoked when a new network session starts.
//! @param handler The SessionInitEvent Handler to add
virtual void AddSessionInitHandler(SessionInitEvent::Handler& handler) = 0;
@@ -146,7 +146,6 @@ namespace Multiplayer
{
// Connect the Editor to the editor server for Multiplayer simulation
AZ::Interface<IMultiplayer>::Get()->Connect(remoteAddress.c_str(), remotePort);
AZ::Interface<IMultiplayer>::Get()->SendReadyForEntityUpdates(true);
}
}
}
@@ -62,6 +62,7 @@ namespace Multiplayer
}
MultiplayerEditorSystemComponent::MultiplayerEditorSystemComponent()
: m_serverAcceptanceReceivedHandler([this](){OnServerAcceptanceReceived();})
{
;
}
@@ -70,6 +71,7 @@ namespace Multiplayer
{
AzFramework::GameEntityContextEventBus::Handler::BusConnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
AZ::Interface<IMultiplayer>::Get()->AddServerAcceptanceReceivedHandler(m_serverAcceptanceReceivedHandler);
}
void MultiplayerEditorSystemComponent::Deactivate()
@@ -143,7 +145,11 @@ namespace Multiplayer
// Start the configured server if it's available
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" --editorsv_isDedicated true", serverPath.c_str());
processLaunchInfo.m_commandlineParameters = AZStd::string::format(
R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s")",
serverPath.c_str(),
AZ::Utils::GetProjectPath().c_str(),
static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset).c_str());
processLaunchInfo.m_showWindow = true;
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL;
@@ -239,4 +245,12 @@ namespace Multiplayer
void MultiplayerEditorSystemComponent::OnGameEntitiesReset()
{
}
void MultiplayerEditorSystemComponent::OnServerAcceptanceReceived()
{
// We're now accepting the connection to the EditorServer.
// In normal game clients SendReadyForEntityUpdates will be enabled once the appropriate level's root spawnable is loaded,
// but since we're in Editor, we're already in the level.
AZ::Interface<IMultiplayer>::Get()->SendReadyForEntityUpdates(true);
}
}
@@ -8,6 +8,8 @@
#pragma once
#include <Multiplayer/IMultiplayer.h>
#include <IEditor.h>
#include <Editor/MultiplayerEditorConnection.h>
@@ -45,6 +47,9 @@ namespace Multiplayer
MultiplayerEditorSystemComponent();
~MultiplayerEditorSystemComponent() override = default;
//! Called once the editor receives the server's accept packet
void OnServerAcceptanceReceived();
//! AZ::Component overrides.
//! @{
void Activate() override;
@@ -71,5 +76,7 @@ namespace Multiplayer
IEditor* m_editor = nullptr;
AzFramework::ProcessWatcher* m_serverProcess = nullptr;
AzNetworking::ConnectionId m_editorConnId;
ServerAcceptanceReceivedEvent::Handler m_serverAcceptanceReceivedHandler;
};
}
@@ -497,6 +497,8 @@ namespace Multiplayer
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str());
AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap();
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(loadLevelString.c_str());
m_serverAcceptanceReceivedEvent.Signal();
return true;
}
@@ -821,6 +823,11 @@ namespace Multiplayer
handler.Connect(m_connectionAcquiredEvent);
}
void MultiplayerSystemComponent::AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler)
{
handler.Connect(m_serverAcceptanceReceivedEvent);
}
void MultiplayerSystemComponent::AddSessionInitHandler(SessionInitEvent::Handler& handler)
{
handler.Connect(m_initEvent);
@@ -1034,7 +1041,7 @@ namespace Multiplayer
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate);
NetworkEntityHandle controlledEntity;
if (entityList.size() > 0)
if (!entityList.empty())
{
controlledEntity = entityList[0];
}
@@ -37,6 +37,8 @@ namespace AzNetworking
namespace Multiplayer
{
AZ_CVAR_EXTERNED(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset);
//! Multiplayer system component wraps the bridging logic between the game and transport layer.
class MultiplayerSystemComponent final
: public AZ::Component
@@ -116,6 +118,7 @@ namespace Multiplayer
void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override;
void AddSessionInitHandler(SessionInitEvent::Handler& handler) override;
void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override;
void AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) override;
void SendNotifyClientMigrationEvent(const HostId& hostId, uint64_t userIdentifier, ClientInputId lastClientInputId) override;
void SendNotifyEntityMigrationEvent(const ConstNetworkEntityHandle& entityHandle, const HostId& remoteHostId) override;
void SendReadyForEntityUpdates(bool readyForEntityUpdates) override;
@@ -157,6 +160,7 @@ namespace Multiplayer
SessionInitEvent m_initEvent;
SessionShutdownEvent m_shutdownEvent;
ConnectionAcquiredEvent m_connectionAcquiredEvent;
ServerAcceptanceReceivedEvent m_serverAcceptanceReceivedEvent;
ClientDisconnectedEvent m_clientDisconnectedEvent;
ClientMigrationStartEvent m_clientMigrationStartEvent;
ClientMigrationEndEvent m_clientMigrationEndEvent;
@@ -328,6 +328,7 @@ namespace Multiplayer
void Terminate([[maybe_unused]] AzNetworking::DisconnectReason reason) override {}
void AddClientDisconnectedHandler([[maybe_unused]] ClientDisconnectedEvent::Handler& handler) override {}
void AddConnectionAcquiredHandler([[maybe_unused]] ConnectionAcquiredEvent::Handler& handler) override {}
void AddServerAcceptanceReceivedHandler([[maybe_unused]] ServerAcceptanceReceivedEvent::Handler& handler) override {}
void AddSessionInitHandler([[maybe_unused]] SessionInitEvent::Handler& handler) override {}
void AddSessionShutdownHandler([[maybe_unused]] SessionShutdownEvent::Handler& handler) override {}
void SendReadyForEntityUpdates([[maybe_unused]] bool readyForEntityUpdates) override {}
+4 -3
View File
@@ -29,9 +29,10 @@ namespace UnitTest
MOCK_METHOD1(AddClientDisconnectedHandler, void(AZ::Event<>::Handler&));
MOCK_METHOD1(AddNotifyClientMigrationHandler, void(Multiplayer::NotifyClientMigrationEvent::Handler&));
MOCK_METHOD1(AddNotifyEntityMigrationEventHandler, void(Multiplayer::NotifyEntityMigrationEvent::Handler&));
MOCK_METHOD1(AddConnectionAcquiredHandler, void(AZ::Event<Multiplayer::MultiplayerAgentDatum>::Handler&));
MOCK_METHOD1(AddSessionInitHandler, void(AZ::Event<AzNetworking::INetworkInterface*>::Handler&));
MOCK_METHOD1(AddSessionShutdownHandler, void(AZ::Event<AzNetworking::INetworkInterface*>::Handler&));
MOCK_METHOD1(AddConnectionAcquiredHandler, void(Multiplayer::ConnectionAcquiredEvent::Handler&));
MOCK_METHOD1(AddServerAcceptanceReceivedHandler, void(Multiplayer::ServerAcceptanceReceivedEvent::Handler&));
MOCK_METHOD1(AddSessionInitHandler, void(Multiplayer::SessionInitEvent::Handler&));
MOCK_METHOD1(AddSessionShutdownHandler, void(Multiplayer::SessionShutdownEvent::Handler&));
MOCK_METHOD3(SendNotifyClientMigrationEvent, void(const Multiplayer::HostId&, uint64_t, Multiplayer::ClientInputId));
MOCK_METHOD2(SendNotifyEntityMigrationEvent, void(const Multiplayer::ConstNetworkEntityHandle&, const Multiplayer::HostId&));
MOCK_METHOD1(SendReadyForEntityUpdates, void(bool));