merging latest dev

Signed-off-by: Gene Walters <genewalt@amazon.com>
This commit is contained in:
Gene Walters
2021-10-22 17:00:47 -07:00
835 changed files with 23255 additions and 9255 deletions
@@ -57,6 +57,14 @@ namespace Multiplayer
const AzNetworking::PacketEncodingBuffer& correction
) override;
//! Forcibly enables ProcessInput to execute on the entity.
//! Note that this function is quite dangerous and should normally never be used
void ForceEnableAutonomousUpdate();
//! Forcibly disables ProcessInput from executing on the entity.
//! Note that this function is quite dangerous and should normally never be used
void ForceDisableAutonomousUpdate();
//! Return true if we're currently migrating from one host to another.
//! @return boolean true if we're currently migrating from one host to another
bool IsMigrating() const;
@@ -71,6 +79,8 @@ namespace Multiplayer
void UpdateAutonomous(AZ::TimeMs deltaTimeMs);
void UpdateBankedTime(AZ::TimeMs deltaTimeMs);
bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer);
using StateHistoryItem = AZStd::unique_ptr<AzNetworking::StringifySerializer>;
AZStd::map<ClientInputId, StateHistoryItem> m_predictiveStateHistory;
@@ -32,7 +32,7 @@ namespace Multiplayer
using EntityStopEvent = AZ::Event<const ConstNetworkEntityHandle&>;
using EntityDirtiedEvent = AZ::Event<>;
using EntitySyncRewindEvent = AZ::Event<>;
using EntityServerMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, const HostId&, AzNetworking::ConnectionId>;
using EntityServerMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, const HostId&>;
using EntityPreRenderEvent = AZ::Event<float>;
using EntityCorrectionEvent = AZ::Event<>;
@@ -113,7 +113,7 @@ namespace Multiplayer
void MarkDirty();
void NotifyLocalChanges();
void NotifySyncRewindState();
void NotifyServerMigration(const HostId& hostId, AzNetworking::ConnectionId connectionId);
void NotifyServerMigration(const HostId& remoteHostId);
void NotifyPreRender(float deltaTime);
void NotifyCorrection();
@@ -58,16 +58,13 @@ namespace Multiplayer
void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override;
//! @}
protected:
//! Used by @NetworkHierarchyRootComponent
void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot);
private:
//! Used by @NetworkHierarchyRootComponent
void SetTopLevelHierarchyRootEntity(AZ::Entity* previousHierarchyRoot, AZ::Entity* newHierarchyRoot);
AZ::ChildChangedEvent::Handler m_childChangedHandler;
AZ::ParentChangedEvent::Handler m_parentChangedHandler;
void OnChildChanged(AZ::ChildChangeType type, AZ::EntityId child);
void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId parent);
//! Points to the top level root.
AZ::Entity* m_rootEntity = nullptr;
@@ -82,5 +79,8 @@ namespace Multiplayer
bool m_isHierarchyEnabled = true;
void NotifyChildrenHierarchyDisbanded();
AzNetworking::ConnectionId m_previousOwningConnectionId = AzNetworking::InvalidConnectionId;
void SetOwningConnectionId(AzNetworking::ConnectionId connectionId) override;
};
}
@@ -29,6 +29,7 @@ namespace Multiplayer
, public NetworkHierarchyRequestBus::Handler
{
friend class NetworkHierarchyChildComponent;
friend class NetworkHierarchyRootComponentController;
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase);
@@ -57,10 +58,11 @@ namespace Multiplayer
void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override;
//! @}
protected:
void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot);
bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer);
private:
void SetTopLevelHierarchyRootEntity(AZ::Entity* previousHierarchyRoot, AZ::Entity* newHierarchyRoot);
AZ::ChildChangedEvent::Handler m_childChangedHandler;
AZ::ParentChangedEvent::Handler m_parentChangedHandler;
@@ -77,26 +79,39 @@ namespace Multiplayer
//! Rebuilds hierarchy starting from this root component's entity.
void RebuildHierarchy();
//! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy
//! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method,
//! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities.
//! @currentEntityCount will be modified to reflect the total entity count upon completion of this method.
//! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise
bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount);
//! @param entity Add the child entity and any of its relevant children to the hierarchy
//! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method,
//! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities.
//! @currentEntityCount will be modified to reflect the total entity count upon completion of this method.
//! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise
bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount);
//! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy.
//! Builds the hierarchy using breadth-first iterative method.
void InternalBuildHierarchyList(AZ::Entity* underEntity);
void SetRootForEntity(AZ::Entity* previousKnownRoot, AZ::Entity* newRoot, const AZ::Entity* childEntity);
void SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity);
//! Set to false when deactivating or otherwise not to be included in hierarchy considerations.
bool m_isHierarchyEnabled = true;
AzNetworking::ConnectionId m_previousOwningConnectionId = AzNetworking::InvalidConnectionId;
void SetOwningConnectionId(AzNetworking::ConnectionId connectionId) override;
friend class HierarchyBenchmarkBase;
};
//! NetworkHierarchyRootComponentController
//! This is the network controller for NetworkHierarchyRootComponent.
//! Class provides the ability to process input for hierarchies.
class NetworkHierarchyRootComponentController final
: public NetworkHierarchyRootComponentControllerBase
{
public:
NetworkHierarchyRootComponentController(NetworkHierarchyRootComponent& parent);
// NetworkHierarchyRootComponentControllerBase
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
//! MultiplayerController interface
Multiplayer::MultiplayerController::InputPriorityOrder GetInputOrder() const override;
void CreateInput(Multiplayer::NetworkInput& input, float deltaTime) override;
void ProcessInput(Multiplayer::NetworkInput& input, float deltaTime) override;
};
}
@@ -45,7 +45,7 @@ namespace Multiplayer
using ClientMigrationStartEvent = AZ::Event<ClientInputId>;
using ClientMigrationEndEvent = AZ::Event<>;
using ClientDisconnectedEvent = AZ::Event<>;
using NotifyClientMigrationEvent = AZ::Event<const HostId&, uint64_t, ClientInputId>;
using NotifyClientMigrationEvent = AZ::Event<AzNetworking::ConnectionId, const HostId&, uint64_t, ClientInputId, NetEntityId>;
using NotifyEntityMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, const HostId&>;
using ConnectionAcquiredEvent = AZ::Event<MultiplayerAgentDatum>;
using ServerAcceptanceReceivedEvent = AZ::Event<>;
@@ -136,10 +136,12 @@ namespace Multiplayer
virtual void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) = 0;
//! 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(const HostId& hostId, uint64_t userIdentifier, ClientInputId lastClientInputId) = 0;
//! @param connectionId the connection id of the client that is migrating
//! @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
//! @param controlledEntityId the entityId of the clients autonomous entity
virtual void SendNotifyClientMigrationEvent(AzNetworking::ConnectionId connectionId, const HostId& hostId, uint64_t userIdentifier, ClientInputId lastClientInputId, NetEntityId controlledEntityId) = 0;
//! Signals a NotifyEntityMigrationEvent with the provided parameters.
//! @param entityHandle the network entity handle of the entity being migrated
@@ -181,6 +183,18 @@ namespace Multiplayer
//! @return pointer to the filtered entity manager, or nullptr if not set
virtual IFilterEntityManager* GetFilterEntityManager() = 0;
//! Registers a temp userId to allow a host to look up a players controlled entity in the event of a rejoin or migration event.
//! @param temporaryUserIdentifier the temporary user identifier used to identify a player across hosts
//! @param controlledEntityId the controlled entityId of the players autonomous entity
virtual void RegisterPlayerIdentifierForRejoin(uint64_t temporaryUserIdentifier, NetEntityId controlledEntityId) = 0;
//! Completes a client migration event by informing the appropriate client to migrate between hosts.
//! @param temporaryUserIdentifier the temporary user identifier used to identify a player across hosts
//! @param connectionId the connection id of the player being migrated
//! @param publicHostId the public address of the new host the client should connect to
//! @param migratedClientInputId the last clientInputId processed prior to migration
virtual void CompleteClientMigration(uint64_t temporaryUserIdentifier, AzNetworking::ConnectionId connectionId, const HostId& publicHostId, ClientInputId migratedClientInputId) = 0;
//! Enables or disables automatic instantiation of netbound entities.
//! This setting is controlled by the networking layer and should not be touched
//! If enabled, netbound entities will instantiate as spawnables are loaded into the game world, generally true for the server
@@ -29,7 +29,7 @@ namespace Multiplayer
using HostId = AzNetworking::IpAddress;
static const HostId InvalidHostId = HostId();
AZ_TYPE_SAFE_INTEGRAL(NetEntityId, uint32_t);
AZ_TYPE_SAFE_INTEGRAL(NetEntityId, uint64_t);
static constexpr NetEntityId InvalidNetEntityId = static_cast<NetEntityId>(-1);
AZ_TYPE_SAFE_INTEGRAL(NetComponentId, uint16_t);
@@ -68,6 +68,7 @@ namespace Multiplayer
Server, // A simulated proxy on a server
Authority // An authoritative proxy on a server (full authority)
};
const char* GetEnumString(NetEntityRole value);
enum class ComponentSerializationType : uint8_t
{
@@ -113,6 +114,24 @@ namespace Multiplayer
bool Serialize(AzNetworking::ISerializer& serializer);
};
inline const char* GetEnumString(NetEntityRole value)
{
switch (value)
{
case NetEntityRole::InvalidRole:
return "InvalidRole";
case NetEntityRole::Client:
return "Client";
case NetEntityRole::Autonomous:
return "Autonomous";
case NetEntityRole::Server:
return "Server";
case NetEntityRole::Authority:
return "Authority";
}
return "Unknown";
}
inline PrefabEntityId::PrefabEntityId(AZ::Name name, uint32_t entityOffset)
: m_prefabName(name)
, m_entityOffset(entityOffset)
@@ -57,7 +57,6 @@ namespace Multiplayer
EntityReplicationManager(AzNetworking::IConnection& connection, AzNetworking::IConnectionListener& connectionListener, Mode mode);
~EntityReplicationManager() = default;
void SetRemoteHostId(const HostId& hostId);
const HostId& GetRemoteHostId() const;
void ActivatePendingEntities();
@@ -43,8 +43,7 @@ namespace Multiplayer
//! Constructor for an entity delete message.
//! @param entityId the networkId of the entity being deleted
//! @param isMigrated whether or not the entity is being migrated or deleted
//! @param takeOwnership true if the remote replicator should take ownership of the entity
explicit NetworkEntityUpdateMessage(NetEntityId entityId, bool isMigrated, bool takeOwnership);
explicit NetworkEntityUpdateMessage(NetEntityId entityId, bool isMigrated);
NetworkEntityUpdateMessage& operator =(NetworkEntityUpdateMessage&& rhs);
NetworkEntityUpdateMessage& operator =(const NetworkEntityUpdateMessage& rhs);
@@ -71,10 +70,6 @@ namespace Multiplayer
//! @return whether or not the entity was migrated
bool GetWasMigrated() const;
//! Gets the current value of TakeOwnership.
//! @return the current value of TakeOwnership
bool GetTakeOwnership() const;
//! Gets the current value of HasValidPrefabId.
//! @return the current value of HasValidPrefabId
bool GetHasValidPrefabId() const;
@@ -110,7 +105,6 @@ namespace Multiplayer
NetEntityId m_entityId = InvalidNetEntityId;
bool m_isDelete = false;
bool m_wasMigrated = false;
bool m_takeOwnership = false;
bool m_hasValidPrefabId = false;
PrefabEntityId m_prefabEntityId;
@@ -0,0 +1,46 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Multiplayer/NetworkInput/NetworkInput.h>
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/containers/fixed_vector.h>
namespace Multiplayer
{
//! @class NetworkInputArray
//! @brief An array of network inputs. Used to mitigate loss of input packets on the server. Compresses subsequent elements.
class NetworkInputArray final
{
public:
static constexpr uint32_t MaxElements = 8; // Never try to replicate a list larger than this amount
NetworkInputArray();
NetworkInputArray(const ConstNetworkEntityHandle& entityHandle);
~NetworkInputArray() = default;
NetworkInput& operator[](uint32_t index);
const NetworkInput& operator[](uint32_t index) const;
bool Serialize(AzNetworking::ISerializer& serializer);
private:
struct Wrapper // Strictly a workaround to deal with the private constructor of NetworkInput
{
Wrapper() : m_networkInput() {}
Wrapper(const NetworkInput& networkInput) : m_networkInput(networkInput) {}
NetworkInput m_networkInput;
};
ConstNetworkEntityHandle m_owner;
AZStd::array<Wrapper, MaxElements> m_inputs;
};
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Multiplayer/NetworkInput/NetworkInput.h>
namespace Multiplayer
{
//! Used by the NetworkHierarchyRootComponent. This component allows the gameplay programmer to specify inputs for dependent entities.
//! Since it is possible to for the Client/Server to disagree about the state of related entities,
//! this network input encodes the entity that is associated with it.
class NetworkInputChild
{
public:
NetworkInputChild() = default;
NetworkInputChild(const NetworkInputChild& rhs) = default;
NetworkInputChild(const ConstNetworkEntityHandle& entityHandle);
NetworkInputChild& operator= (const NetworkInputChild& rhs);
void Attach(const ConstNetworkEntityHandle& entityHandle);
const ConstNetworkEntityHandle& GetOwner() const;
const NetworkInput& GetNetworkInput() const;
NetworkInput& GetNetworkInput();
bool Serialize(AzNetworking::ISerializer& serializer);
private:
ConstNetworkEntityHandle m_owner;
NetworkInput m_networkInput;
};
using NetworkInputChildList = AZStd::vector<NetworkInputChild>;
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Multiplayer/NetworkInput/NetworkInput.h>
#include <AzCore/std/containers/deque.h>
namespace Multiplayer
{
//! @class NetworkInputHistory
//! @brief A list of input commands, used for bookkeeping on the client.
class NetworkInputHistory final
{
public:
AZStd::size_t Size() const;
const NetworkInput& operator[](AZStd::size_t index) const;
NetworkInput& operator[](AZStd::size_t index);
void PushBack(NetworkInput& networkInput);
void PopFront();
const NetworkInput& Front() const;
private:
struct Wrapper // Strictly a workaround to deal with the private constructor of NetworkInput
{
Wrapper() : m_networkInput() {}
Wrapper(const NetworkInput& networkInput) : m_networkInput(networkInput) {}
NetworkInput m_networkInput;
};
AZStd::deque<Wrapper> m_history;
};
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Multiplayer/NetworkInput/NetworkInput.h>
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/containers/fixed_vector.h>
namespace Multiplayer
{
//! @class NetworkInputMigrationVector
//! @brief A variable sized array of input commands, used specifically when migrate a clients inputs.
class NetworkInputMigrationVector final
{
public:
static constexpr uint32_t MaxElements = 90; // Never try to migrate a list larger than this amount, bumped up to handle DTLS connection time
NetworkInputMigrationVector();
NetworkInputMigrationVector(const ConstNetworkEntityHandle& entityHandle);
virtual ~NetworkInputMigrationVector() = default;
uint32_t GetSize() const;
NetworkInput& operator[](uint32_t index);
const NetworkInput& operator[](uint32_t index) const;
bool PushBack(const NetworkInput& networkInput);
bool Serialize(AzNetworking::ISerializer& serializer);
private:
struct Wrapper // Strictly a workaround to deal with the private constructor of NetworkInput
{
Wrapper() : m_networkInput() {}
Wrapper(const NetworkInput& networkInput) : m_networkInput(networkInput) {}
bool Serialize(AzNetworking::ISerializer& serializer) { return m_networkInput.Serialize(serializer); }
NetworkInput m_networkInput;
};
ConstNetworkEntityHandle m_owner;
AZStd::fixed_vector<Wrapper, MaxElements> m_inputs;
};
}