Ported the local prediction player controller component

This commit is contained in:
karlberg
2021-05-05 20:07:16 -07:00
parent bbe3fcfdd9
commit a1fe8fe419
55 changed files with 1164 additions and 275 deletions
@@ -0,0 +1,58 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Include/INetworkEntityManager.h>
#include <AzNetworking/ConnectionLayer/IConnection.h>
namespace Multiplayer
{
class EntityReplicationManager;
enum class ConnectionDataType
{
ClientToServer,
ServerToClient,
ServerToServer
};
class IConnectionData
{
public:
virtual ~IConnectionData() = default;
//! Returns whether or not this is a ServerToClient or ServerToServer connection data instance.
//! @return ConnectionDataType::ServerToClient or ConnectionDataType::ServerToServer
virtual ConnectionDataType GetConnectionDataType() const = 0;
//! Returns the connection bound to this connection data instance.
//! @return pointer to the connection bound to this connection data instance
virtual AzNetworking::IConnection* GetConnection() const = 0;
//! Returns the EntityReplicationManager for this connection data instance.
//! @return reference to the EntityReplicationManager for this connection data instance
virtual EntityReplicationManager& GetReplicationManager() = 0;
//! Creates and manages sending updates to the remote endpoint.
//! @param hostTimeMs current server game time in milliseconds
virtual void Update(AZ::TimeMs hostTimeMs) = 0;
//! Returns whether update messages can be sent to the connection.
//! @return true if update messages can be sent
virtual bool CanSendUpdates() const = 0;
//! Sets the state of connection whether update messages can be sent or not.
//! @param canSendUpdates the state value
virtual void SetCanSendUpdates(bool canSendUpdates) = 0;
};
}
@@ -0,0 +1,44 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Include/INetworkEntityManager.h>
namespace Multiplayer
{
//! @class IEntityDomain
//! @brief A class that determines if an entity should belong to a particular INetworkEntityManager.
class IEntityDomain
{
public:
using EntitiesNotInDomain = AZStd::unordered_set<NetEntityId>;
virtual ~IEntityDomain() = default;
//! Returns whether or not an entity should be owned by an entity manager.
//! @param entityHandle the handle of the netbound entity to check
//! @return false if this entity should not belong to the entity manger, true if it could be owned by the entity manager
virtual bool IsInDomain(const ConstNetworkEntityHandle& entityHandle) const = 0;
//! Enable Entity Domain Exit Tracking for entities on the host.
//! @param ownedEntitySet the set of entities to activate tracking for
virtual void ActivateTracking(const INetworkEntityManager::OwnedEntitySet& ownedEntitySet) = 0;
//! Return the set of netbound entities not included in this domain.
//! @param outEntitiesNotInDomain the set of known networked entities not included in this domain
virtual void RetrieveEntitiesNotInDomain(EntitiesNotInDomain& outEntitiesNotInDomain) const = 0;
//! Debug draw to visualize host entity domains.
virtual void DebugDraw() const = 0;
};
}
+10 -1
View File
@@ -15,6 +15,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzNetworking/ConnectionLayer/IConnection.h>
#include <AzNetworking/DataStructures/ByteBuffer.h>
#include <Include/INetworkTime.h>
#include <Include/MultiplayerStats.h>
namespace AzNetworking
@@ -56,7 +57,7 @@ namespace Multiplayer
//! Gets the type of Agent this IMultiplayer impl represents
//! @return The type of agents represented
virtual MultiplayerAgentType GetAgentType() = 0;
virtual MultiplayerAgentType GetAgentType() const = 0;
//! Sets the type of this Multiplayer connection and calls any related callback
//! @param state The state of this connection
@@ -78,6 +79,14 @@ namespace Multiplayer
//! @param readyForEntityUpdates Ready for entity updates or not
virtual void SendReadyForEntityUpdates(bool readyForEntityUpdates) = 0;
//! Returns the current server time in milliseconds.
//! This can be one of three possible values:
//! 1. On the host outside of rewind scope, this will return the latest application elapsed time in ms.
//! 2. On the host within rewind scope, this will return the rewound time in ms.
//! 3. On the client, this will return the most recently replicated server time in ms.
//! @return the current server time in milliseconds
virtual AZ::TimeMs GetCurrentHostTimeMs() const = 0;
//! Returns the gem name associated with the provided component index.
//! @param netComponentId the componentId to return the gem name of
//! @return the name of the gem that contains the requested component
@@ -0,0 +1,36 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Include/MultiplayerTypes.h>
#include <AzNetworking/DataStructures/FixedSizeBitset.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
namespace AzNetworking
{
class ISerializer;
}
namespace Multiplayer
{
class IMultiplayerComponentInput
{
public:
virtual ~IMultiplayerComponentInput() = default;
virtual NetComponentId GetComponentId() const = 0;
virtual bool Serialize(AzNetworking::ISerializer& serializer) = 0;
};
using MultiplayerComponentInputVector = AZStd::vector<AZStd::unique_ptr<IMultiplayerComponentInput>>;
}
@@ -0,0 +1,158 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Include/MultiplayerTypes.h>
#include <Include/NetworkEntityHandle.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/EBus/Event.h>
#include <AzCore/Asset/AssetCommon.h>
namespace Multiplayer
{
class NetworkEntityTracker;
class NetworkEntityAuthorityTracker;
class NetworkEntityRpcMessage;
class MultiplayerComponentRegistry;
using EntityExitDomainEvent = AZ::Event<const ConstNetworkEntityHandle&>;
using ControllersActivatedEvent = AZ::Event<const ConstNetworkEntityHandle&, EntityIsMigrating>;
using ControllersDeactivatedEvent = AZ::Event<const ConstNetworkEntityHandle&, EntityIsMigrating>;
//! @class INetworkEntityManager
//! @brief The interface for managing all networked entities.
class INetworkEntityManager
{
public:
AZ_RTTI(INetworkEntityManager, "{109759DE-9492-439C-A0B1-AE46E6FD029C}");
using OwnedEntitySet = AZStd::unordered_set<ConstNetworkEntityHandle>;
using EntityList = AZStd::vector<NetworkEntityHandle>;
virtual ~INetworkEntityManager() = default;
//! Returns the NetworkEntityTracker for this INetworkEntityManager instance.
//! @return the NetworkEntityTracker for this INetworkEntityManager instance
virtual NetworkEntityTracker* GetNetworkEntityTracker() = 0;
//! Returns the NetworkEntityAuthorityTracker for this INetworkEntityManager instance.
//! @return the NetworkEntityAuthorityTracker for this INetworkEntityManager instance
virtual NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() = 0;
//! Returns the MultiplayerComponentRegistry for this INetworkEntityManager instance.
//! @return the MultiplayerComponentRegistry for this INetworkEntityManager instance
virtual MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() = 0;
//! Returns the HostId for this INetworkEntityManager instance.
//! @return the HostId for this INetworkEntityManager instance
virtual HostId GetHostId() const = 0;
//! Creates new entities of the given archetype
//! @param prefabEntryId the name of the spawnable to spawn
virtual EntityList CreateEntitiesImmediate(
const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, AutoActivate autoActivate,
const AZ::Transform& transform) = 0;
//! Returns an ConstEntityPtr for the provided entityId.
//! @param netEntityId the netEntityId to get an ConstEntityPtr for
//! @return the requested ConstEntityPtr
virtual ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const = 0;
//! Returns the total number of entities tracked by this INetworkEntityManager instance.
//! @return the total number of entities tracked by this INetworkEntityManager instance
virtual uint32_t GetEntityCount() const = 0;
//! Adds the provided entity to the internal entity map identified by the provided netEntityId.
//! @param netEntityId the identifier to use for the added entity
//! @param entity the entity to add to the internal entity map
//! @return a NetworkEntityHandle for the newly added entity
virtual NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) = 0;
//! Marks the specified entity for removal and deletion.
//! @param entityHandle the entity to remove and delete
virtual void MarkForRemoval(const ConstNetworkEntityHandle& entityHandle) = 0;
//! Returns true if the indicated entity is marked for removal.
//! @param entityHandle the entity to test if marked for removal
//! @return boolean true if the specified entity is marked for removal, false otherwise
virtual bool IsMarkedForRemoval(const ConstNetworkEntityHandle& entityHandle) const = 0;
//! Unmarks the specified entity so it will no longer be removed and deleted.
//! @param entityHandle the entity to unmark for removal and deletion
virtual void ClearEntityFromRemovalList(const ConstNetworkEntityHandle& entityHandle) = 0;
//! Clears out and deletes all entities registered with the entity manager.
virtual void ClearAllEntities() = 0;
//! Adds an event handler to be invoked when we notify which entities have been marked dirty.
//! @param entityMarkedDirtyHandle event handler for the dirtied entity
virtual void AddEntityMarkedDirtyHandler(AZ::Event<>::Handler& entityMarkedDirtyHandle) = 0;
//! Adds an event handler to be invoked when we notify entities to send their change notifications.
//! @param entityNotifyChangesHandle event handler for the dirtied entity
virtual void AddEntityNotifyChangesHandler(AZ::Event<>::Handler& entityNotifyChangesHandle) = 0;
//! Adds an event handler to be invoked when we notify entities to send their change notifications.
//! @param entityNotifyChangesHandle event handler for the dirtied entity
virtual void AddEntityExitDomainHandler(EntityExitDomainEvent::Handler& entityExitDomainHandler) = 0;
//! Adds an event handler to be invoked when an entities controllers have activated
//! @param controllersActivatedHandler event handler for the entity
virtual void AddControllersActivatedHandler(ControllersActivatedEvent::Handler& controllersActivatedHandler) = 0;
//! Adds an event handler to be invoked when an entities controllers have been deactivated
//! @param controllersDeactivatedHandler event handler for the entity
virtual void AddControllersDeactivatedHandler(ControllersDeactivatedEvent::Handler& controllersDeactivatedHandler) = 0;
//! Notifies entities that they should process their dirty state.
virtual void NotifyEntitiesDirtied() = 0;
//! Notifies entities that they should process change notifications.
virtual void NotifyEntitiesChanged() = 0;
//! Notifies that an entities controllers have activated.
//! @param entityHandle handle to the entity whose controllers have activated
//! @param entityIsMigrating true if the entity is activating after a migration
virtual void NotifyControllersActivated(const ConstNetworkEntityHandle& entityHandle, EntityIsMigrating entityIsMigrating) = 0;
//! Notifies that an entities controllers have been deactivated.
//! @param entityHandle handle to the entity whose controllers have been deactivated
//! @param entityIsMigrating true if the entity is deactivating due to a migration
virtual void NotifyControllersDeactivated(const ConstNetworkEntityHandle& entityHandle, EntityIsMigrating entityIsMigrating) = 0;
//! Handle a local rpc message.
//! @param entityRpcMessage the local rpc message to handle
virtual void HandleLocalRpcMessage(NetworkEntityRpcMessage& message) = 0;
};
// Convenience helpers
inline INetworkEntityManager* GetNetworkEntityManager()
{
return AZ::Interface<INetworkEntityManager>::Get();
}
inline NetworkEntityTracker* GetNetworkEntityTracker()
{
return GetNetworkEntityManager()->GetNetworkEntityTracker();
}
inline NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker()
{
return GetNetworkEntityManager()->GetNetworkEntityAuthorityTracker();
}
inline MultiplayerComponentRegistry* GetMultiplayerComponentRegistry()
{
return GetNetworkEntityManager()->GetMultiplayerComponentRegistry();
}
}
@@ -0,0 +1,106 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Time/ITime.h>
#include <AzNetworking/ConnectionLayer/IConnection.h>
#include <Include/MultiplayerTypes.h>
namespace Multiplayer
{
//! @class INetworkTime
//! @brief This is an AZ::Interface<> for managing multiplayer specific time related operations.
class INetworkTime
{
public:
AZ_RTTI(INetworkTime, "{7D468063-255B-4FEE-86E1-6D750EEDD42A}");
INetworkTime() = default;
virtual ~INetworkTime() = default;
//! Returns true if the host timeMs and frameId has been temporarily altered.
//! @return true if the host timeMs and frameId has been altered, false otherwise
virtual bool IsTimeRewound() const = 0;
//! Retrieves the hosts current frameId (may be rewound on the server during backward reconciliation).
//! @return the hosts current frameId
virtual HostFrameId GetHostFrameId() const = 0;
//! Retrieves the unaltered hosts current frameId.
//! @return the hosts current frameId, unaltered by any scoped time instance
virtual HostFrameId GetUnalteredHostFrameId() const = 0;
//! Increments the hosts current frameId.
virtual void IncrementHostFrameId() = 0;
//! Retrieves the hosts current timeMs (may be rewound on the server during backward reconciliation).
//! @return the hosts current timeMs
virtual AZ::TimeMs GetHostTimeMs() const = 0;
//! Synchronizes rewindable entity state for the current application time.
virtual void SyncRewindableEntityState() = 0;
//! Get the controlling connection that may be currently altering global game time.
//! Note this abstraction is required at a relatively high level to allow for 'don't rewind the shooter' semantics
//! @return the ConnectionId of the connection requesting the rewind operation
virtual AzNetworking::ConnectionId GetRewindingConnectionId() const = 0;
//! Get the controlling connection that may be currently altering global game time.
//! Note this abstraction is required at a relatively high level to allow for 'don't rewind the shooter' semantics
//! @param rewindConnectionId if this parameter matches the current rewindConnectionId, it will return the unaltered hostFrameId
//! @return the HostFrameId taking into account the provided rewinding connectionId
virtual HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const = 0;
//! Alters the current HostFrameId and binds that alteration to the provided ConnectionId.
//! @param frameId the new HostFrameId to use
//! @param timeMs the new HostTimeMs to use
//! @param rewindConnectionId the rewinding ConnectionId
virtual void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) = 0;
AZ_DISABLE_COPY_MOVE(INetworkTime);
};
// EBus wrapper for ScriptCanvas
class INetworkTimeRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
};
using INetworkTimeRequestBus = AZ::EBus<INetworkTime, INetworkTimeRequests>;
//! @class ScopedAlterTime
//! @brief This is a wrapper that temporarily adjusts global program time for backward reconciliation purposes.
class ScopedAlterTime final
{
public:
inline ScopedAlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId connectionId)
{
INetworkTime* time = AZ::Interface<INetworkTime>::Get();
m_previousHostFrameId = time->GetHostFrameId();
m_previousHostTimeMs = time->GetHostTimeMs();
m_previousRewindConnectionId = time->GetRewindingConnectionId();
time->AlterTime(frameId, timeMs, connectionId);
}
inline ~ScopedAlterTime()
{
INetworkTime* time = AZ::Interface<INetworkTime>::Get();
time->AlterTime(m_previousHostFrameId, m_previousHostTimeMs, m_previousRewindConnectionId);
}
private:
HostFrameId m_previousHostFrameId = InvalidHostFrameId;
AZ::TimeMs m_previousHostTimeMs = AZ::TimeMs{ 0 };
AzNetworking::ConnectionId m_previousRewindConnectionId = AzNetworking::InvalidConnectionId;
};
}
@@ -0,0 +1,42 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Include/MultiplayerTypes.h>
#include <Include/NetworkEntityHandle.h>
#include <AzCore/std/containers/unordered_map.h>
namespace Multiplayer
{
struct EntityReplicationData
{
EntityReplicationData() = default;
NetEntityRole m_netEntityRole = NetEntityRole::InvalidRole;
float m_priority = 0.0f;
};
using ReplicationSet = AZStd::unordered_map<ConstNetworkEntityHandle, EntityReplicationData>;
class IReplicationWindow
{
public:
virtual ~IReplicationWindow() = default;
virtual bool ReplicationSetUpdateReady() = 0;
virtual const ReplicationSet& GetReplicationSet() const = 0;
//! Max number of entities we can send updates for in one frame
virtual uint32_t GetMaxEntityReplicatorSendCount() const = 0;
virtual bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const = 0;
virtual void UpdateWindow() = 0;
virtual void DebugDraw() const = 0;
};
}
@@ -36,6 +36,12 @@ namespace Multiplayer
AZ_TYPE_SAFE_INTEGRAL(PropertyIndex, uint16_t);
AZ_TYPE_SAFE_INTEGRAL(RpcIndex, uint16_t);
AZ_TYPE_SAFE_INTEGRAL(ClientInputId, uint16_t);
//! This is a strong typedef for representing the number of application frames since application start.
AZ_TYPE_SAFE_INTEGRAL(HostFrameId, uint32_t);
static constexpr HostFrameId InvalidHostFrameId = HostFrameId{ 0xFFFFFFFF };
using LongNetworkString = AZ::CVarFixedString;
using ReliabilityType = AzNetworking::ReliabilityType;
@@ -122,3 +128,5 @@ AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetEntityId);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetComponentId);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::PropertyIndex);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::RpcIndex);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::ClientInputId);
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::HostFrameId);
@@ -0,0 +1,141 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Entity.h>
#include <Include/MultiplayerTypes.h>
namespace Multiplayer
{
class MultiplayerController;
class NetworkEntityTracker;
class NetBindComponent;
//! @class ConstNetworkEntityHandle
//! @brief This class provides a wrapping around handle ids.
//! It is optimized to avoid using the hashmap lookup unless the hashmap has had an item removed.
class ConstNetworkEntityHandle
{
public:
//! Constructs a nullptr handle.
ConstNetworkEntityHandle() = default;
//! Constructs a ConstNetworkEntityHandle given an entity, an entity tracker
//! @param entity pointer to the entity to construct a ConstNetworkEntityHandle for
//! @param entityTracker pointer to the entity tracker that tracks the entity
ConstNetworkEntityHandle(AZ::Entity* entity, const NetworkEntityTracker* entityTracker);
//! Constructs a ConstNetworkEntityHandle given an entity, a networkEntityId, and an entity tracker
//! @param entity pointer to the entity to construct a ConstNetworkEntityHandle for
//! @param netEntityId the networkEntityId of the entity
//! @param entityTracker pointer to the entity tracker that tracks the entity
ConstNetworkEntityHandle(AZ::Entity* entity, NetEntityId netEntityId, const NetworkEntityTracker* entityTracker);
//! Constructs a ConstNetworkEntityHandle given an entity, a networked entityId, an entity tracker, and a dirty version
//! @param netBindComponent pointer to the entities NetBindComponent
//! @param entityTracker pointer to the entity tracker that tracks the entity
ConstNetworkEntityHandle(NetBindComponent* netBindComponent, const NetworkEntityTracker* entityTracker);
ConstNetworkEntityHandle(const ConstNetworkEntityHandle&) = default;
//! Access the AZ::Entity if it safely exists, nullptr or false is returned if the entity does not exist.
//! @{
bool Exists() const;
AZ::Entity* GetEntity();
const AZ::Entity* GetEntity() const;
//! @}
//! Operators providing pointer semantics.
//! @{
bool operator ==(const ConstNetworkEntityHandle& rhs) const;
bool operator !=(const ConstNetworkEntityHandle& rhs) const;
friend bool operator ==(const ConstNetworkEntityHandle& lhs, AZStd::nullptr_t);
friend bool operator ==(AZStd::nullptr_t, const ConstNetworkEntityHandle& rhs);
friend bool operator !=(const ConstNetworkEntityHandle& lhs, AZStd::nullptr_t);
friend bool operator !=(AZStd::nullptr_t, const ConstNetworkEntityHandle& rhs);
friend bool operator ==(const ConstNetworkEntityHandle& lhs, const AZ::Entity* rhs);
friend bool operator ==(const AZ::Entity* lhs, const ConstNetworkEntityHandle& rhs);
friend bool operator !=(const ConstNetworkEntityHandle& lhs, const AZ::Entity* rhs);
friend bool operator !=(const AZ::Entity* lhs, const ConstNetworkEntityHandle& rhs);
//! @}
bool operator <(const ConstNetworkEntityHandle& rhs) const;
explicit operator bool() const;
//! Resets the handle to a nullptr state.
void Reset();
void Reset(const ConstNetworkEntityHandle& handle);
//! Returns the networkEntityId of the entity this handle points to.
//! @return the networkEntityId of the entity this handle points to
NetEntityId GetNetEntityId() const;
//! Returns the cached netBindComponent for this entity, or nullptr if it doesn't exist.
//! @return the cached netBindComponent for this entity, or nullptr if it doesn't exist
NetBindComponent* GetNetBindComponent() const;
//! Returns a specific component on of entity given a typeId.
//! @param typeId the typeId of the component to find and return
//! @return pointer to the requested component, or nullptr if it doesn't exist on the entity
const AZ::Component* FindComponent(const AZ::TypeId& typeId) const;
//! Returns a specific component on of entity by class type.
//! @return pointer to the requested component, or nullptr if it doesn't exist on the entity
template <typename Component>
const Component* FindComponent() const;
//! Helper function for sorting EntityHandles by netEntityId.
static bool Compare(const ConstNetworkEntityHandle& lhs, const ConstNetworkEntityHandle& rhs);
protected:
mutable uint32_t m_changeDirty = 0; // Optimization so we don't need to recheck the hashmap
mutable AZ::Entity* m_entity = nullptr;
mutable NetBindComponent* m_netBindComponent = nullptr;
const NetworkEntityTracker* m_networkEntityTracker = nullptr;
NetEntityId m_netEntityId = InvalidNetEntityId;
};
class NetworkEntityHandle
: public ConstNetworkEntityHandle
{
public:
using ConstNetworkEntityHandle::ConstNetworkEntityHandle;
//! Initializes the underlying entity if possible.
void Init();
//! Activates the underlying entity if possible.
void Activate();
//! Deactivates the underlying entity if possible.
void Deactivate();
//! Gets the BaseController from the first component on an Entity with the supplied typeId AND which inherits from Multiplayer::BaseComponent
MultiplayerController* FindController(const AZ::TypeId& typeId);
template <typename Controller>
Controller* FindController();
using ConstNetworkEntityHandle::FindComponent;
AZ::Component* FindComponent(const AZ::TypeId& typeId);
template <typename ComponentType>
ComponentType* FindComponent();
};
}
#include <Include/NetworkEntityHandle.inl>
@@ -0,0 +1,138 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
namespace Multiplayer
{
inline bool operator ==(const ConstNetworkEntityHandle& lhs, AZStd::nullptr_t)
{
return !lhs.Exists();
}
inline bool operator ==(AZStd::nullptr_t, const ConstNetworkEntityHandle& rhs)
{
return !rhs.Exists();
}
inline bool operator !=(const ConstNetworkEntityHandle& lhs, AZStd::nullptr_t)
{
return lhs.Exists();
}
inline bool operator !=(AZStd::nullptr_t, const ConstNetworkEntityHandle& rhs)
{
return rhs.Exists();
}
inline bool operator==(const ConstNetworkEntityHandle& lhs, const AZ::Entity* rhs)
{
return lhs.m_entity == rhs;
}
inline bool operator==(const AZ::Entity* lhs, const ConstNetworkEntityHandle& rhs)
{
return operator==(rhs, lhs);
}
inline bool operator!=(const ConstNetworkEntityHandle& lhs, const AZ::Entity* rhs)
{
return lhs.m_entity != rhs;
}
inline bool operator!=(const AZ::Entity* lhs, const ConstNetworkEntityHandle& rhs)
{
return operator!=(rhs, lhs);
}
inline NetEntityId ConstNetworkEntityHandle::GetNetEntityId() const
{
return m_netEntityId;
}
template <class ComponentType>
inline const ComponentType* ConstNetworkEntityHandle::FindComponent() const
{
if (const AZ::Entity* entity{ GetEntity() })
{
return entity->template FindComponent<ComponentType>();
}
return nullptr;
}
inline bool ConstNetworkEntityHandle::Compare(const ConstNetworkEntityHandle& lhs, const ConstNetworkEntityHandle& rhs)
{
return lhs.m_netEntityId < rhs.m_netEntityId;
}
inline void NetworkEntityHandle::Init()
{
if (AZ::Entity* entity{ GetEntity() })
{
entity->Init();
}
}
inline void NetworkEntityHandle::Activate()
{
if (AZ::Entity* entity{ GetEntity() })
{
entity->Activate();
}
}
inline void NetworkEntityHandle::Deactivate()
{
if (AZ::Entity* entity{ GetEntity() })
{
entity->Deactivate();
}
}
template <typename ControllerType>
inline ControllerType* NetworkEntityHandle::FindController()
{
return static_cast<ControllerType*>(FindController(ControllerType::ComponentType::RTTI_Type()));
}
template <typename ComponentType>
inline ComponentType* NetworkEntityHandle::FindComponent()
{
if (AZ::Entity* entity{ GetEntity() })
{
return entity->template FindComponent<ComponentType>();
}
return nullptr;
}
}
//! AZStd::hash support.
namespace AZStd
{
template <>
class hash<Multiplayer::NetworkEntityHandle>
{
public:
size_t operator()(const Multiplayer::NetworkEntityHandle &rhs) const
{
return hash<Multiplayer::NetEntityId>()(rhs.GetNetEntityId());
}
};
template <>
class hash<Multiplayer::ConstNetworkEntityHandle>
{
public:
size_t operator()(const Multiplayer::ConstNetworkEntityHandle &rhs) const
{
return hash<Multiplayer::NetEntityId>()(rhs.GetNetEntityId());
}
};
}