Reverts changes to component application and adds further client migration handling hookup
Signed-off-by: kberg-amzn <karlberg@amazon.com>
This commit is contained in:
@@ -121,9 +121,9 @@ namespace AZ
|
||||
return environment ? environment->Get() : nullptr;
|
||||
}
|
||||
|
||||
ComponentApplication::EventLoggerDeleter::EventLoggerDeleter() noexcept= default;
|
||||
ComponentApplication::EventLoggerDeleter::EventLoggerDeleter() noexcept = default;
|
||||
ComponentApplication::EventLoggerDeleter::EventLoggerDeleter(bool skipDelete) noexcept
|
||||
: m_skipDelete{skipDelete}
|
||||
: m_skipDelete{ skipDelete }
|
||||
{}
|
||||
void ComponentApplication::EventLoggerDeleter::operator()(AZ::Debug::LocalFileEventLogger* ptr)
|
||||
{
|
||||
@@ -332,27 +332,27 @@ namespace AZ
|
||||
->Value("Stack trace always", Debug::AllocationRecords::RECORD_FULL);
|
||||
ec->Class<Descriptor>("System memory settings", "Settings for managing application memory usage")
|
||||
->ClassElement(Edit::ClassElements::EditorData, "")
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_grabAllMemory, "Allocate all memory at startup", "Allocate all system memory at startup if enabled, or allocate as needed if disabled")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_allocationRecords, "Record allocations", "Collect information on each allocation made for debugging purposes (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_allocationRecordsSaveNames, "Record allocations with name saving", "Saves names/filenames information on each allocation made, useful for tracking down leaks in dynamic modules (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_allocationRecordsAttemptDecodeImmediately, "Record allocations and attempt immediate decode", "Decode callstacks for each allocation when they occur, used for tracking allocations that fail decoding. Very expensive. (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &Descriptor::m_recordingMode, "Stack recording mode", "Stack record mode. (Ignored in final builds)")
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_stackRecordLevels, "Stack entries to record", "Number of stack levels to record for each allocation (ignored in Release builds)")
|
||||
->Attribute(Edit::Attributes::Step, 1)
|
||||
->Attribute(Edit::Attributes::Max, 1024)
|
||||
->Attribute(Edit::Attributes::Step, 1)
|
||||
->Attribute(Edit::Attributes::Max, 1024)
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_autoIntegrityCheck, "Validate allocations", "Check allocations for integrity on each allocation/free (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_markUnallocatedMemory, "Mark freed memory", "Set memory to 0xcd when a block is freed for debugging (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_doNotUsePools, "Don't pool allocations", "Pipe pool allocations in system/tree heap (ignored in Release builds)")
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_pageSize, "Page size", "Memory page size in bytes (must be OS page size aligned)")
|
||||
->Attribute(Edit::Attributes::Step, 1024)
|
||||
->Attribute(Edit::Attributes::Step, 1024)
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_poolPageSize, "Pool page size", "Memory pool page size in bytes (must be a multiple of page size)")
|
||||
->Attribute(Edit::Attributes::Max, &Descriptor::m_pageSize)
|
||||
->Attribute(Edit::Attributes::Step, 1024)
|
||||
->Attribute(Edit::Attributes::Max, &Descriptor::m_pageSize)
|
||||
->Attribute(Edit::Attributes::Step, 1024)
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_memoryBlockAlignment, "Block alignment", "Memory block alignment in bytes (must be multiple of the page size)")
|
||||
->Attribute(Edit::Attributes::Step, &Descriptor::m_pageSize)
|
||||
->Attribute(Edit::Attributes::Step, &Descriptor::m_pageSize)
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_memoryBlocksByteSize, "Block size", "Memory block size in bytes (must be multiple of the page size)")
|
||||
->Attribute(Edit::Attributes::Step, &Descriptor::m_pageSize)
|
||||
->Attribute(Edit::Attributes::Step, &Descriptor::m_pageSize)
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_reservedOS, "OS reserved memory", "System memory reserved for OS (used only when 'Allocate all memory at startup' is true)")
|
||||
->DataElement(Edit::UIHandlers::SpinBox, &Descriptor::m_reservedDebug, "Memory reserved for debugger", "System memory reserved for Debug allocator, like memory tracking (used only when 'Allocate all memory at startup' is true)")
|
||||
->DataElement(Edit::UIHandlers::CheckBox, &Descriptor::m_enableDrilling, "Enable Driller", "Enable Drilling support for the application (ignored in Release builds)")
|
||||
@@ -419,11 +419,11 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
azstrcpy(m_commandLineBuffer, AZ_ARRAY_SIZE(m_commandLineBuffer), "no_argv_supplied");
|
||||
azstrcpy(m_commandLineBuffer, AZ_ARRAY_SIZE(m_commandLineBuffer), "no_argv_supplied");
|
||||
// use a "valid" value here. This is because Qt and potentially other third party libraries require
|
||||
// that ArgC be 'at least 1' and that (*argV)[0] be a valid pointer to a real null terminated string.
|
||||
m_argC = 1;
|
||||
m_argV = &m_commandLineBufferAddress;
|
||||
m_argC = 1;
|
||||
m_argV = &m_commandLineBufferAddress;
|
||||
}
|
||||
|
||||
// Create the Event logger if it doesn't exist, otherwise reuse the one registered
|
||||
@@ -557,8 +557,8 @@ namespace AZ
|
||||
|
||||
void ReportBadEngineRoot()
|
||||
{
|
||||
AZStd::string errorMessage = {"Unable to determine a valid path to the engine.\n"
|
||||
"Check parameters such as --project-path and --engine-path and make sure they are valid.\n"};
|
||||
AZStd::string errorMessage = { "Unable to determine a valid path to the engine.\n"
|
||||
"Check parameters such as --project-path and --engine-path and make sure they are valid.\n" };
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString filePathErrorStr;
|
||||
@@ -614,7 +614,6 @@ namespace AZ
|
||||
AZ_Assert(m_systemEntity, "SystemEntity failed to initialize!");
|
||||
|
||||
AddRequiredSystemComponents(m_systemEntity.get());
|
||||
//m_currentTime = GetElapsedTimeUs();
|
||||
m_isStarted = true;
|
||||
return m_systemEntity.get();
|
||||
}
|
||||
@@ -1372,38 +1371,44 @@ namespace AZ
|
||||
|
||||
void ComponentApplication::Tick(float deltaOverride /*= -1.f*/)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application simulation tick");
|
||||
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
|
||||
m_deltaTime = 0.0f;
|
||||
if (now >= m_currentTime)
|
||||
{
|
||||
AZStd::chrono::duration<float> delta = now - m_currentTime;
|
||||
m_deltaTime = deltaOverride >= 0.f ? deltaOverride : delta.count();
|
||||
}
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:ExecuteQueuedEvents");
|
||||
TickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
m_currentTime = now;
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick");
|
||||
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now));
|
||||
}
|
||||
AZ_PROFILE_SCOPE(System, "Component application simulation tick");
|
||||
|
||||
// If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame,
|
||||
// sleeping if there's still time remaining.
|
||||
if (g_simulation_tick_rate > 0.f)
|
||||
{
|
||||
now = AZStd::chrono::system_clock::now();
|
||||
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
|
||||
|
||||
// Work in microsecond durations here as that's the native measurement time for time_point
|
||||
constexpr float microsecondsPerSecond = 1000.f * 1000.f;
|
||||
const AZStd::chrono::microseconds timeBudgetPerTick(static_cast<int>(microsecondsPerSecond / g_simulation_tick_rate));
|
||||
AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now;
|
||||
m_deltaTime = 0.0f;
|
||||
|
||||
if (timeUntilNextTick.count() > 0)
|
||||
if (now >= m_currentTime)
|
||||
{
|
||||
AZStd::this_thread::sleep_for(timeUntilNextTick);
|
||||
AZStd::chrono::duration<float> delta = now - m_currentTime;
|
||||
m_deltaTime = deltaOverride >= 0.f ? deltaOverride : delta.count();
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:ExecuteQueuedEvents");
|
||||
TickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
m_currentTime = now;
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick");
|
||||
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now));
|
||||
}
|
||||
|
||||
// If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame,
|
||||
// sleeping if there's still time remaining.
|
||||
if (g_simulation_tick_rate > 0.f)
|
||||
{
|
||||
now = AZStd::chrono::system_clock::now();
|
||||
|
||||
// Work in microsecond durations here as that's the native measurement time for time_point
|
||||
constexpr float microsecondsPerSecond = 1000.f * 1000.f;
|
||||
const AZStd::chrono::microseconds timeBudgetPerTick(static_cast<int>(microsecondsPerSecond / g_simulation_tick_rate));
|
||||
AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now;
|
||||
|
||||
if (timeUntilNextTick.count() > 0)
|
||||
{
|
||||
AZStd::this_thread::sleep_for(timeUntilNextTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1555,5 +1560,4 @@ namespace AZ
|
||||
AZ::SettingsRegistryScriptUtils::ReflectSettingsRegistryToBehaviorContext(*behaviorContext);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Time/ITime.h>
|
||||
#include <AzCore/Memory/AllocationRecords.h>
|
||||
#include <AzCore/Debug/BudgetTracker.h>
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
@@ -377,14 +377,14 @@ namespace AZ
|
||||
EntityRemovedEvent m_entityRemovedEvent;
|
||||
EntityAddedEvent m_entityActivatedEvent;
|
||||
EntityRemovedEvent m_entityDeactivatedEvent;
|
||||
AZ::IConsole* m_console{};
|
||||
AZ::IConsole* m_console{};
|
||||
Descriptor m_descriptor;
|
||||
bool m_isStarted{ false };
|
||||
bool m_isSystemAllocatorOwner{ false };
|
||||
bool m_isOSAllocatorOwner{ false };
|
||||
bool m_ownsConsole{};
|
||||
void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
|
||||
IAllocatorAllocate* m_osAllocator{ nullptr };
|
||||
void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
|
||||
IAllocatorAllocate* m_osAllocator{ nullptr };
|
||||
EntitySetType m_entities;
|
||||
AZ::IO::FixedMaxPath m_exeDirectory;
|
||||
AZ::IO::FixedMaxPath m_engineRoot;
|
||||
@@ -405,11 +405,11 @@ namespace AZ
|
||||
// we create a buffer that can be written to (up to AZ_MAX_PATH_LEN) and then
|
||||
// pack it with a single param.
|
||||
char m_commandLineBuffer[AZ_MAX_PATH_LEN];
|
||||
char* m_commandLineBufferAddress{ m_commandLineBuffer };
|
||||
char* m_commandLineBufferAddress{ m_commandLineBuffer };
|
||||
|
||||
StartupParameters m_startupParameters;
|
||||
|
||||
char** m_argV{ nullptr };
|
||||
char** m_argV{ nullptr };
|
||||
int m_argC{ 0 };
|
||||
AZ::CommandLine m_commandLine; // < Stores parsed command line supplied to the constructor
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Multiplayer
|
||||
using ClientMigrationStartEvent = AZ::Event<ClientInputId>;
|
||||
using ClientMigrationEndEvent = AZ::Event<>;
|
||||
using ClientDisconnectedEvent = AZ::Event<>;
|
||||
using NotifyClientMigrationEvent = AZ::Event<HostId, uint64_t, ClientInputId>;
|
||||
using ConnectionAcquiredEvent = AZ::Event<MultiplayerAgentDatum>;
|
||||
using SessionInitEvent = AZ::Event<AzNetworking::INetworkInterface*>;
|
||||
using SessionShutdownEvent = AZ::Event<AzNetworking::INetworkInterface*>;
|
||||
@@ -80,34 +81,38 @@ namespace Multiplayer
|
||||
//! @param state The state of this connection
|
||||
virtual void InitializeMultiplayer(MultiplayerAgentType state) = 0;
|
||||
|
||||
//! Starts hosting a server
|
||||
//! Starts hosting a server.
|
||||
//! @param port The port to listen for connection on
|
||||
//! @param isDedicated Whether the server is dedicated or client hosted
|
||||
//! @return if the application successfully started hosting
|
||||
virtual bool StartHosting(uint16_t port, bool isDedicated = true) = 0;
|
||||
|
||||
//! Connects to the specified IP as a Client
|
||||
//! Connects to the specified IP as a Client.
|
||||
//! @param remoteAddress The domain or IP to connect to
|
||||
//! @param port The port to connect to
|
||||
//! @result if a connection was successfully created
|
||||
virtual bool Connect(AZStd::string remoteAddress, uint16_t port) = 0;
|
||||
|
||||
// Disconnects all multiplayer connections, stops listening on the server and invokes handlers appropriate to network context
|
||||
// Disconnects all multiplayer connections, stops listening on the server and invokes handlers appropriate to network context.
|
||||
//! @param reason The reason for terminating connections
|
||||
virtual void Terminate(AzNetworking::DisconnectReason reason) = 0;
|
||||
|
||||
//! Adds a ClientMigrationStartEvent Handler which is invoked at the start of a client migration
|
||||
//! Adds a ClientMigrationStartEvent Handler which is invoked at the start of a client migration.
|
||||
//! @param handler The ClientMigrationStartEvent Handler to add
|
||||
virtual void AddClientMigrationStartEventHandler(ClientMigrationStartEvent::Handler& handler) = 0;
|
||||
|
||||
//! Adds a ClientMigrationEndEvent Handler which is invoked when a client completes migration
|
||||
//! Adds a ClientMigrationEndEvent Handler which is invoked when a client completes migration.
|
||||
//! @param handler The ClientMigrationEndEvent Handler to add
|
||||
virtual void AddClientMigrationEndEventHandler(ClientMigrationEndEvent::Handler& handler) = 0;
|
||||
|
||||
//! Adds a ClientDisconnectedEvent Handler which is invoked on the client when a disconnection occurs
|
||||
//! Adds a ClientDisconnectedEvent Handler which is invoked on the client when a disconnection occurs.
|
||||
//! @param handler The ClientDisconnectedEvent Handler to add
|
||||
virtual void AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler) = 0;
|
||||
|
||||
//! Adds a NotifyClientMigrationEvent Handler which is invoked when a client migrates from one host to another.
|
||||
//! @param handler The NotifyClientMigrationEvent Handler to add
|
||||
virtual void AddNotifyClientMigrationHandler(NotifyClientMigrationEvent::Handler& handler) = 0;
|
||||
|
||||
//! Adds a ConnectionAcquiredEvent Handler which is invoked when a new endpoint connects to the session.
|
||||
//! @param handler The ConnectionAcquiredEvent Handler to add
|
||||
virtual void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) = 0;
|
||||
@@ -120,7 +125,13 @@ namespace Multiplayer
|
||||
//! @param handler The SessionShutdownEvent handler to add
|
||||
virtual void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) = 0;
|
||||
|
||||
//! Sends a packet telling if entity update messages can be sent
|
||||
//! Signals a NotifyClientMigrationEvent with the provided parameters.
|
||||
//! @param hostId the host id of the host the client is migrating to
|
||||
//! @param userIdentifier the user identifier the client will provide the new host to validate identity
|
||||
//! @param lastClientInputId the last processed clientInputId by the current host
|
||||
virtual void SendNotifyClientMigrationEvent(HostId hostId, uint64_t userIdentifier, ClientInputId lastClientInputId);
|
||||
|
||||
//! Sends a packet telling if entity update messages can be sent.
|
||||
//! @param readyForEntityUpdates Ready for entity updates or not
|
||||
virtual void SendReadyForEntityUpdates(bool readyForEntityUpdates) = 0;
|
||||
|
||||
@@ -132,7 +143,7 @@ namespace Multiplayer
|
||||
//! @return the current server time in milliseconds
|
||||
virtual AZ::TimeMs GetCurrentHostTimeMs() const = 0;
|
||||
|
||||
//! Returns the current blend factor for client side interpolation
|
||||
//! Returns the current blend factor for client side interpolation.
|
||||
//! This value is only relevant on the client and is used to smooth between host frames
|
||||
//! @return the current blend factor
|
||||
virtual float GetCurrentBlendFactor() const = 0;
|
||||
|
||||
@@ -403,6 +403,8 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
: public Multiplayer::MultiplayerController
|
||||
{
|
||||
public:
|
||||
using ComponentType = {{ ComponentName }};
|
||||
|
||||
{{ ControllerBaseName }}({{ ComponentName }}& owner);
|
||||
~{{ ControllerBaseName }}() override = default;
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
</Packet>
|
||||
|
||||
<Packet Name="ClientMigration" Desc="Tell a client to migrate to a new server">
|
||||
<Member Type="uint64_t" Name="temporaryUserIdentifier" Init="0" />
|
||||
<Member Type="AzNetworking::IpAddress" Name="remoteServerAddress" Init="AzNetworking::IpAddress()" />
|
||||
<Member Type="AZ::TimeMs" Name="lastInputGameTimeMs" Init="AZ::TimeMs{ 0 }" />
|
||||
<Member Type="AzNetworking::IpAddress" Name="remoteServerAddress" Init="AzNetworking::IpAddress()" />
|
||||
<Member Type="uint64_t" Name="temporaryUserIdentifier" Init="0" />
|
||||
<Member Type="Multiplayer::ClientInputId" Name="lastClientInputId" Init="Multiplayer::ClientInputId{ 0 }" />
|
||||
</Packet>
|
||||
</PacketGroup>
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
*/
|
||||
|
||||
#include <Source/ConnectionData/ServerToClientConnectionData.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
|
||||
#include <Multiplayer/Components/LocalPredictionPlayerInputComponent.h>
|
||||
#include <Multiplayer/IMultiplayer.h>
|
||||
#include <AzNetworking/Utilities/EncryptionCommon.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -95,36 +98,31 @@ namespace Multiplayer
|
||||
[[maybe_unused]] AzNetworking::ConnectionId connectionId
|
||||
)
|
||||
{
|
||||
//Multiplayer::ServerAddrInfo serverAddr;
|
||||
//if (gNovaGame->GetMultiplayerworkAgent().GetServerToServerNetwork().GetServerAddrInfoFromConnectionId(newConnectionId, serverAddr) == false)
|
||||
//{
|
||||
// AZLOG_WARN("MigrateClient::Failed to find servershard address, userID:%d", static_cast<uint32_t>(GetUserId()));
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//Multiplayer::GameTimePoint migratedClientGameTimePoint;
|
||||
//
|
||||
//if (m_ControlledEntity != nullptr)
|
||||
//{
|
||||
// if (const PlayerNetworkInputComponent::Authority* pComponent = Multiplayer::FindController<PlayerNetworkInputComponent::Authority>(m_ControlledEntity))
|
||||
// {
|
||||
// migratedClientGameTimePoint = pComponent->GetLastInputId().GetServerGameTimePoint();
|
||||
// }
|
||||
//}
|
||||
//
|
||||
// generate crypto-rand user identifier, send to both server and client so they can negotiate the autonomous entity to assume predictive control over after migration
|
||||
//const uint64_t randomUserIdentifier = 0;
|
||||
//
|
||||
//// Tell the server a new client is about to join
|
||||
//MultiplayerPackets::NotifyClientMigration notifyClientMigration(randomUserIdentifier);
|
||||
//gNovaGame->GetMultiplayerworkAgent().GetServerToServerNetwork().SendReliablePacket(newConnectionId, notifyClientMigration);
|
||||
//
|
||||
//// Tell the client who to join
|
||||
//MultiplayerPackets::ClientMigration clientMigration(randomUserIdentifier, serverAddr, migratedClientGameTimePoint);
|
||||
//GetConnection()->SendReliablePacket(clientMigration);
|
||||
//
|
||||
//m_controlledEntity = nullptr;
|
||||
//m_canSendUpdates = false;
|
||||
AzNetworking::IpAddress serverAddress;
|
||||
// serverAddress = GetHost(remoteHostId).GetAddress();
|
||||
|
||||
ClientInputId migratedClientInputId = ClientInputId{ 0 };
|
||||
if (m_controlledEntity != nullptr)
|
||||
{
|
||||
auto controller = m_controlledEntity.FindController<LocalPredictionPlayerInputComponentController>();
|
||||
if (controller != nullptr)
|
||||
{
|
||||
migratedClientInputId = controller->GetLastInputId();
|
||||
}
|
||||
}
|
||||
|
||||
// Generate crypto-rand user identifier, send to both server and client so they can negotiate the autonomous entity to assume predictive control over after migration
|
||||
const uint64_t randomUserIdentifier = AzNetworking::CryptoRand64();
|
||||
|
||||
// Tell the new host that a client is about to (re)join
|
||||
GetMultiplayer()->SendNotifyClientMigrationEvent(remoteHostId, randomUserIdentifier, migratedClientInputId);
|
||||
|
||||
// Tell the client who to join
|
||||
MultiplayerPackets::ClientMigration clientMigration(serverAddress, randomUserIdentifier, migratedClientInputId);
|
||||
GetConnection()->SendReliablePacket(clientMigration);
|
||||
|
||||
m_controlledEntity = NetworkEntityHandle();
|
||||
m_canSendUpdates = false;
|
||||
}
|
||||
|
||||
void ServerToClientConnectionData::OnGameplayStarted()
|
||||
|
||||
@@ -617,7 +617,7 @@ namespace Multiplayer
|
||||
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::ClientMigrated, TerminationEndpoint::Local); };
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(visitor);
|
||||
AZLOG_INFO("Migrating to new server shard");
|
||||
//m_clientMigrateStartEvent(packet.GetLastInputGameTimeMs());
|
||||
m_clientMigrationStartEvent.Signal(ClientInputId{ 0 });
|
||||
m_networkInterface->Connect(packet.GetRemoteServerAddress());
|
||||
return true;
|
||||
}
|
||||
@@ -795,6 +795,11 @@ namespace Multiplayer
|
||||
handler.Connect(m_clientDisconnectedEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddNotifyClientMigrationHandler(NotifyClientMigrationEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_notifyClientMigrationEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_connectionAcquiredEvent);
|
||||
@@ -810,6 +815,11 @@ namespace Multiplayer
|
||||
handler.Connect(m_shutdownEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::SendNotifyClientMigrationEvent(HostId hostId, uint64_t userIdentifier, ClientInputId lastClientInputId)
|
||||
{
|
||||
m_notifyClientMigrationEvent.Signal(hostId, userIdentifier, lastClientInputId);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::SendReadyForEntityUpdates(bool readyForEntityUpdates)
|
||||
{
|
||||
IConnectionSet& connectionSet = m_networkInterface->GetConnectionSet();
|
||||
|
||||
@@ -111,9 +111,11 @@ namespace Multiplayer
|
||||
void AddClientMigrationStartEventHandler(ClientMigrationStartEvent::Handler& handler) override;
|
||||
void AddClientMigrationEndEventHandler(ClientMigrationEndEvent::Handler& handler) override;
|
||||
void AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler) override;
|
||||
void AddNotifyClientMigrationHandler(NotifyClientMigrationEvent::Handler& handler) override;
|
||||
void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override;
|
||||
void AddSessionInitHandler(SessionInitEvent::Handler& handler) override;
|
||||
void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override;
|
||||
void SendNotifyClientMigrationEvent(HostId hostId, uint64_t userIdentifier, ClientInputId lastClientInputId) override;
|
||||
void SendReadyForEntityUpdates(bool readyForEntityUpdates) override;
|
||||
AZ::TimeMs GetCurrentHostTimeMs() const override;
|
||||
float GetCurrentBlendFactor() const override;
|
||||
@@ -154,6 +156,7 @@ namespace Multiplayer
|
||||
ClientDisconnectedEvent m_clientDisconnectedEvent;
|
||||
ClientMigrationStartEvent m_clientMigrationStartEvent;
|
||||
ClientMigrationEndEvent m_clientMigrationEndEvent;
|
||||
NotifyClientMigrationEvent m_notifyClientMigrationEvent;
|
||||
|
||||
AZStd::queue<AZStd::string> m_pendingConnectionTickets;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user