+10
@@ -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();
|
||||
|
||||
|
||||
+6
-6
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
+32
-17
@@ -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)
|
||||
|
||||
-1
@@ -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();
|
||||
|
||||
+1
-7
@@ -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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user