From 5acdc4059531f2aeab472369ce4f5c1214bf147e Mon Sep 17 00:00:00 2001 From: karlberg Date: Fri, 14 May 2021 14:24:33 -0700 Subject: [PATCH 1/5] Many fixes for external gem multiplayer components and component network inputs, fixes an uninitialized variable resulting in continual desyncs, restructures our public includes to match the directory structure of source, allows autogen artefacts to be included by external gems, allowing for external multiplayer components to interact with multiplayer gem components with no extra code --- .../Serialization/HashSerializer.h | 2 +- .../LocalPredictionPlayerInputComponent.h | 2 +- .../{ => Components}/MultiplayerComponent.h | 8 ++- .../MultiplayerComponentRegistry.h | 12 ++++- .../{ => Components}/MultiplayerController.h | 12 +++-- .../{ => Components}/NetBindComponent.h | 13 +++-- .../Components/NetworkTransformComponent.h | 0 .../{ => ConnectionData}/IConnectionData.h | 2 +- .../{ => EntityDomains}/IEntityDomain.h | 2 +- .../Code/Include/Multiplayer/IMultiplayer.h | 27 ++-------- .../Multiplayer/INetworkPlayerSpawner.h | 18 ------- .../EntityReplication}/ReplicationRecord.h | 0 .../INetworkEntityManager.h | 2 +- .../{ => NetworkEntity}/NetworkEntityHandle.h | 2 +- .../NetworkEntityHandle.inl | 0 .../NetworkEntityRpcMessage.h | 0 .../NetworkEntityUpdateMessage.h | 0 .../IMultiplayerComponentInput.h | 2 +- .../{ => NetworkInput}/NetworkInput.h | 14 ++--- .../{ => NetworkTime}/INetworkTime.h | 0 .../{ => NetworkTime}/RewindableObject.h | 4 +- .../{ => NetworkTime}/RewindableObject.inl | 0 .../IReplicationWindow.h | 2 +- .../AutoGen/AutoComponentTypes_Source.jinja | 8 ++- .../Source/AutoGen/AutoComponent_Common.jinja | 54 +++++++++++++++---- .../Source/AutoGen/AutoComponent_Header.jinja | 39 ++++++++------ .../Source/AutoGen/AutoComponent_Source.jinja | 51 +++++++++++++----- ...tionPlayerInputComponent.AutoComponent.xml | 6 +-- .../AutoGen/Multiplayer.AutoPackets.xml | 6 +-- ...etworkTransformComponent.AutoComponent.xml | 2 +- .../LocalPredictionPlayerInputComponent.cpp | 16 +++--- .../Components/MultiplayerComponent.cpp | 23 ++++++-- .../MultiplayerComponentRegistry.cpp | 8 ++- .../Components/MultiplayerController.cpp | 15 ++++-- .../Source/Components/NetBindComponent.cpp | 41 ++++++++++---- .../Components/NetworkTransformComponent.cpp | 4 +- .../ClientToServerConnectionData.h | 2 +- .../ServerToClientConnectionData.h | 2 +- .../Debug/MultiplayerDebugSystemComponent.cpp | 15 +++--- .../EntityDomains/FullOwnershipEntityDomain.h | 2 +- .../Code/Source/MultiplayerGem.cpp | 2 +- .../MultiplayerStats.cpp | 0 .../Source/MultiplayerSystemComponent.cpp | 22 +------- .../Code/Source/MultiplayerSystemComponent.h | 4 -- .../EntityReplicationManager.cpp | 17 +++--- .../EntityReplicationManager.h | 10 ++-- .../EntityReplication/EntityReplicator.cpp | 6 +-- .../EntityReplication/EntityReplicator.h | 4 +- .../EntityReplication/PropertyPublisher.h | 2 +- .../EntityReplication/PropertySubscriber.cpp | 2 +- .../EntityReplication/ReplicationRecord.cpp | 2 +- .../NetworkEntityAuthorityTracker.cpp | 4 +- .../NetworkEntity/NetworkEntityHandle.cpp | 8 +-- .../NetworkEntity/NetworkEntityManager.cpp | 2 +- .../NetworkEntity/NetworkEntityManager.h | 8 +-- .../NetworkEntity/NetworkEntityRpcMessage.cpp | 2 +- .../NetworkEntity/NetworkEntityTracker.cpp | 2 +- .../NetworkEntity/NetworkEntityTracker.h | 2 +- .../NetworkEntityUpdateMessage.cpp | 2 +- .../Code/Source/NetworkInput/NetworkInput.cpp | 23 ++++---- .../Source/NetworkInput/NetworkInputArray.cpp | 2 +- .../Source/NetworkInput/NetworkInputArray.h | 4 +- .../Source/NetworkInput/NetworkInputChild.h | 2 +- .../Source/NetworkInput/NetworkInputHistory.h | 2 +- .../NetworkInputMigrationVector.h | 4 +- .../Code/Source/NetworkTime/NetworkTime.cpp | 2 +- .../Code/Source/NetworkTime/NetworkTime.h | 2 +- .../Pipeline/NetworkPrefabProcessor.cpp | 2 +- .../NullReplicationWindow.h | 2 +- .../ServerToClientReplicationWindow.cpp | 2 +- .../ServerToClientReplicationWindow.h | 4 +- .../Code/Tests/RewindableObjectTests.cpp | 2 +- Gems/Multiplayer/Code/multiplayer_files.cmake | 43 ++++++++------- 73 files changed, 348 insertions(+), 267 deletions(-) rename Gems/Multiplayer/Code/{Source => Include/Multiplayer}/Components/LocalPredictionPlayerInputComponent.h (98%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => Components}/MultiplayerComponent.h (96%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => Components}/MultiplayerComponentRegistry.h (83%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => Components}/MultiplayerController.h (92%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => Components}/NetBindComponent.h (93%) rename Gems/Multiplayer/Code/{Source => Include/Multiplayer}/Components/NetworkTransformComponent.h (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => ConnectionData}/IConnectionData.h (97%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => EntityDomains}/IEntityDomain.h (96%) delete mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/INetworkPlayerSpawner.h rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity/EntityReplication}/ReplicationRecord.h (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity}/INetworkEntityManager.h (99%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity}/NetworkEntityHandle.h (99%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity}/NetworkEntityHandle.inl (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity}/NetworkEntityRpcMessage.h (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkEntity}/NetworkEntityUpdateMessage.h (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkInput}/IMultiplayerComponentInput.h (94%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkInput}/NetworkInput.h (85%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkTime}/INetworkTime.h (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkTime}/RewindableObject.h (97%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => NetworkTime}/RewindableObject.inl (100%) rename Gems/Multiplayer/Code/Include/Multiplayer/{ => ReplicationWindows}/IReplicationWindow.h (96%) rename Gems/Multiplayer/Code/{Include/Multiplayer => Source}/MultiplayerStats.cpp (100%) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.h index 2f86d1aafe..1cc44cf5bd 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.h @@ -56,6 +56,6 @@ namespace AzNetworking private: - AZ::HashValue64 m_hash; + AZ::HashValue64 m_hash = AZ::HashValue64{ 0 }; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h similarity index 98% rename from Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index 924fd78391..7a6105a7e3 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -13,7 +13,7 @@ #pragma once #include -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h similarity index 96% rename from Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponent.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h index 29348a698a..6f410dd97c 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #include #include @@ -62,7 +63,10 @@ namespace Multiplayer //! @} NetEntityId GetNetEntityId() const; - NetEntityRole GetNetEntityRole() const; + bool IsAuthority() const; + bool IsAutonomous() const; + bool IsServer() const; + bool IsClient() const; ConstNetworkEntityHandle GetEntityHandle() const; NetworkEntityHandle GetEntityHandle(); void MarkDirty(); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponentRegistry.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponentRegistry.h similarity index 83% rename from Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponentRegistry.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponentRegistry.h index d06362ed4b..d3064d87dd 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerComponentRegistry.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponentRegistry.h @@ -14,7 +14,8 @@ #include #include -#include +#include +#include namespace Multiplayer { @@ -22,13 +23,15 @@ namespace Multiplayer { public: using PropertyNameLookupFunction = AZStd::function; - using RpcNameLookupFunction = AZStd::function; + using RpcNameLookupFunction = AZStd::function; + using AllocComponentInputFunction = AZStd::function()>; struct ComponentData { AZ::Name m_gemName; AZ::Name m_componentName; PropertyNameLookupFunction m_componentPropertyNameLookupFunction; RpcNameLookupFunction m_componentRpcNameLookupFunction; + AllocComponentInputFunction m_allocComponentInputFunction; }; //! Registers a multiplayer component with the multiplayer system. @@ -36,6 +39,11 @@ namespace Multiplayer //! @return the NetComponentId assigned to this particular component NetComponentId RegisterMultiplayerComponent(const ComponentData& componentData); + //! Allocates a new component input for the provided netComponentId. + //! @param netComponentId the NetComponentId to allocate a component input for + //! @return pointer to the allocated component input, caller assumes ownership + AZStd::unique_ptr AllocateComponentInput(NetComponentId netComponentId); + //! Returns the gem name associated with the provided NetComponentId. //! @param netComponentId the NetComponentId to return the gem name of //! @return the name of the gem that contains the requested component diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerController.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h similarity index 92% rename from Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerController.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h index 89c47c40d4..a8017ef9d1 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerController.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace Multiplayer @@ -47,9 +47,13 @@ namespace Multiplayer //! @return the networkId for the entity that owns this controller NetEntityId GetNetEntityId() const; - //! Returns the networkRole for the entity that owns this controller. - //! @return the networkRole for the entity that owns this controller - NetEntityRole GetNetEntityRole() const; + //! Returns true if this controller has authority. + //! @return boolean true if this controller has authority + bool IsAuthority() const; + + //! Returns true if this controller has autonomy (can locally predict). + //! @return boolean true if this controller has autonomy + bool IsAutonomous() const; //! Returns the raw AZ::Entity pointer for the entity that owns this controller. //! @return the raw AZ::Entity pointer for the entity that owns this controller diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h similarity index 93% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetBindComponent.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index 464333e3b2..257e7cab4b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -20,10 +20,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -63,12 +63,16 @@ namespace Multiplayer NetEntityRole GetNetEntityRole() const; bool IsAuthority() const; + bool IsAutonomous() const; + bool IsServer() const; + bool IsClient() const; bool HasController() const; NetEntityId GetNetEntityId() const; const PrefabEntityId& GetPrefabEntityId() const; ConstNetworkEntityHandle GetEntityHandle() const; NetworkEntityHandle GetEntityHandle(); + void SetAllowAutonomy(bool value); MultiplayerComponentInputVector AllocateComponentInputs(); bool IsProcessingInput() const; void CreateInput(NetworkInput& networkInput, float deltaTime); @@ -155,6 +159,7 @@ namespace Multiplayer bool m_isProcessingInput = false; bool m_isMigrationDataValid = false; bool m_needsToBeStopped = false; + bool m_allowAutonomy = false; // Set to true for the hosts controlled entity friend class NetworkEntityManager; friend class EntityReplicationManager; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h similarity index 100% rename from Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h rename to Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IConnectionData.h b/Gems/Multiplayer/Code/Include/Multiplayer/ConnectionData/IConnectionData.h similarity index 97% rename from Gems/Multiplayer/Code/Include/Multiplayer/IConnectionData.h rename to Gems/Multiplayer/Code/Include/Multiplayer/ConnectionData/IConnectionData.h index 39fdb61435..1fb3003c7b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IConnectionData.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/ConnectionData/IConnectionData.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IEntityDomain.h b/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h similarity index 96% rename from Gems/Multiplayer/Code/Include/Multiplayer/IEntityDomain.h rename to Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h index 70215612b0..dd7a11bb4a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IEntityDomain.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h @@ -12,7 +12,7 @@ #pragma once -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index 4931fb167f..6a615465c2 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -15,8 +15,9 @@ #include #include #include -#include -#include +#include +#include +#include #include namespace AzNetworking @@ -101,28 +102,6 @@ namespace Multiplayer //! @return pointer to the network entity manager instance bound to this multiplayer instance virtual INetworkEntityManager* GetNetworkEntityManager() = 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 - virtual const char* GetComponentGemName(NetComponentId netComponentId) const = 0; - - //! Returns the component name associated with the provided component index. - //! @param netComponentId the componentId to return the component name of - //! @return the name of the component - virtual const char* GetComponentName(NetComponentId netComponentId) const = 0; - - //! Returns the property name associated with the provided component index and property index. - //! @param netComponentId the component index to return the property name of - //! @param propertyIndex the index of the network property to return the property name of - //! @return the name of the network property - virtual const char* GetComponentPropertyName(NetComponentId netComponentId, PropertyIndex propertyIndex) const = 0; - - //! Returns the Rpc name associated with the provided component index and rpc index. - //! @param netComponentId the componentId to return the property name of - //! @param rpcIndex the index of the rpc to return the rpc name of - //! @return the name of the requested rpc - virtual const char* GetComponentRpcName(NetComponentId netComponentId, RpcIndex rpcIndex) const = 0; - //! Retrieve the stats object bound to this multiplayer instance. //! @return the stats object bound to this multiplayer instance MultiplayerStats& GetStats() { return m_stats; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/INetworkPlayerSpawner.h b/Gems/Multiplayer/Code/Include/Multiplayer/INetworkPlayerSpawner.h deleted file mode 100644 index f50d60e82d..0000000000 --- a/Gems/Multiplayer/Code/Include/Multiplayer/INetworkPlayerSpawner.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -* 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 - -namespace Multiplayer -{ - -} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/ReplicationRecord.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/ReplicationRecord.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/INetworkEntityManager.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h similarity index 99% rename from Gems/Multiplayer/Code/Include/Multiplayer/INetworkEntityManager.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h index 17224e64cb..72dbe201e5 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h @@ -13,7 +13,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityHandle.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h similarity index 99% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityHandle.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h index 813589fac6..21d4ae9c62 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityHandle.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h @@ -138,4 +138,4 @@ namespace Multiplayer }; } -#include +#include diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityHandle.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityHandle.inl similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityHandle.inl rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityHandle.inl diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityRpcMessage.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityRpcMessage.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityUpdateMessage.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntityUpdateMessage.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerComponentInput.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h similarity index 94% rename from Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerComponentInput.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h index b26feadc4f..13faff3a7e 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerComponentInput.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h @@ -28,7 +28,7 @@ namespace Multiplayer { public: virtual ~IMultiplayerComponentInput() = default; - virtual NetComponentId GetComponentId() const = 0; + virtual NetComponentId GetNetComponentId() const = 0; virtual bool Serialize(AzNetworking::ISerializer& serializer) = 0; }; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h similarity index 85% rename from Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h index 9c6d2ce66a..b2e0134ea9 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/NetworkInput.h @@ -12,9 +12,9 @@ #pragma once -#include -#include -#include +#include +#include +#include #include namespace Multiplayer @@ -57,15 +57,15 @@ namespace Multiplayer IMultiplayerComponentInput* FindComponentInput(NetComponentId componentId); template - const InputType* FindInput() const + const InputType* FindComponentInput() const { - return static_cast(FindInput(InputType::s_Type)); + return static_cast(FindComponentInput(InputType::s_netComponentId)); } template - InputType* FindInput() + InputType* FindComponentInput() { - return static_cast(FindInput(InputType::s_Type)); + return static_cast(FindComponentInput(InputType::s_netComponentId)); } private: diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/INetworkTime.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/RewindableObject.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h similarity index 97% rename from Gems/Multiplayer/Code/Include/Multiplayer/RewindableObject.h rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h index 9e1655aec7..d5b7d563ab 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/RewindableObject.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include #include #include @@ -115,4 +115,4 @@ namespace AZ AZ_TYPE_INFO_TEMPLATE(Multiplayer::RewindableObject, "{B2937B44-FEE1-4277-B1E0-863DE76D363F}", AZ_TYPE_INFO_TYPENAME, AZ_TYPE_INFO_AUTO); } -#include +#include diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/RewindableObject.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/RewindableObject.inl rename to Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IReplicationWindow.h b/Gems/Multiplayer/Code/Include/Multiplayer/ReplicationWindows/IReplicationWindow.h similarity index 96% rename from Gems/Multiplayer/Code/Include/Multiplayer/IReplicationWindow.h rename to Gems/Multiplayer/Code/Include/Multiplayer/ReplicationWindows/IReplicationWindow.h index d0192e8aa4..5d90fc286b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IReplicationWindow.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/ReplicationWindows/IReplicationWindow.h @@ -13,7 +13,7 @@ #pragma once #include -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja index 453d74c907..7bb4bdcc2c 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include {% for Component in dataFiles %} {% set ComponentDerived = Component.attrib['OverrideComponent']|booleanTrue %} {% set ControllerDerived = Component.attrib['OverrideController']|booleanTrue %} @@ -38,7 +38,11 @@ namespace {{ Namespace }} componentData.m_componentName = AZ::Name("{{ Component.attrib['Name'] }}"); componentData.m_componentPropertyNameLookupFunction = {{ ComponentBaseName }}::GetNetworkPropertyName; componentData.m_componentRpcNameLookupFunction = {{ ComponentBaseName }}::GetRpcName; + componentData.m_allocComponentInputFunction = {{ ComponentBaseName }}::AllocateComponentInput; {{ ComponentBaseName }}::s_netComponentId = multiplayerComponentRegistry->RegisterMultiplayerComponent(componentData); +{% if NetworkInputCount > 0 %} + {{ ComponentName }}NetworkInput::s_netComponentId = {{ ComponentBaseName }}::s_netComponentId; +{% endif %} stats.ReserveComponentStats({{ ComponentBaseName }}::s_netComponentId, static_cast({{ NetworkPropertyCount }}), static_cast({{ RpcCount }})); } {% endfor %} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja index d211b933c5..d187a151fd 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja @@ -207,11 +207,11 @@ namespace {{ Component.attrib['Namespace'] }} public: AZ_MULTIPLAYER_COMPONENT({{ Component.attrib['Namespace'] }}::{{ ComponentName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, {{ Component.attrib['Namespace'] }}::{{ ComponentNameBase }}); - static void Reflect([[maybe_unused]] AZ::ReflectContext* context); + static void Reflect(AZ::ReflectContext* context); - void OnInit() override {} - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; {{ DeclareRpcHandlers(Component, 'Authority', 'Client', true)|indent(8) }} }; @@ -222,15 +222,15 @@ namespace {{ Component.attrib['Namespace'] }} : public {{ ControllerNameBase }} { public: - {{ ControllerName }}({{ ComponentName }}& parent) : {{ ControllerNameBase }}(parent) {} + {{ ControllerName }}({{ ComponentName }}& parent); - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; {% if NetworkInputCount > 0 %} //! Common input processing logic for the NetworkInput. //! @param input input structure to process //! @param deltaTime amount of time to integrate the provided inputs over - void ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {} + void ProcessInput(Multiplayer::NetworkInput& input, float deltaTime) override; {%endif %} {{ DeclareRpcHandlers(Component, 'Server', 'Authority', true)|indent(8) }} {{ DeclareRpcHandlers(Component, 'Client', 'Authority', true)|indent(8) }} @@ -239,10 +239,12 @@ namespace {{ Component.attrib['Namespace'] }} }; {% endif %} } -{% if ComponentDerived %} /// Place in your .cpp +#include <{{ Component.attrib['OverrideInclude'] }}> + namespace {{ Component.attrib['Namespace'] }} { +{% if ComponentDerived %} void {{ ComponentName }}::{{ ComponentName }}::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serializeContext = azrtti_cast(context); @@ -251,7 +253,41 @@ namespace {{ Component.attrib['Namespace'] }} serializeContext->Class<{{ ComponentName }}, {{ ComponentNameBase }}>() ->Version(1); } + {{ ComponentNameBase }}::Reflect(context); } + + void {{ ComponentName }}::OnInit() + { + } + + void {{ ComponentName }}::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + } + + void {{ ComponentName }}::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + } + +{% endif %} +{% if ControllerDerived %} + {{ ControllerName }}::{{ ControllerName }}({{ ComponentName }}& parent) + : {{ ControllerNameBase }}(parent) + { + } + + void {{ ControllerName }}::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + } + + void {{ ControllerName }}::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + } +{% if NetworkInputCount > 0 %} + + void {{ ControllerName }}::ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) + { + } +{% endif %} } {% endif %} */ diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index c22945c983..0d4e7146a0 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -7,25 +7,25 @@ {% macro DeclareNetworkPropertyGetter(Property) %} {% set PropertyName = UpperFirst(Property.attrib['Name']) %} {% if Property.attrib['Container'] == 'Array' %} -{% if Property.attrib['GenerateEventBindings']|booleanTrue %} -void {{ PropertyName }}AddEvent(AZ::Event::Handler& handler); -{% endif %} const AZStd::array<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::k_RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Array() const; const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const; -{% elif Property.attrib['Container'] == 'Vector' %} {% if Property.attrib['GenerateEventBindings']|booleanTrue %} void {{ PropertyName }}AddEvent(AZ::Event::Handler& handler); -void {{ PropertyName }}SizeChangedAddEvent(AZ::Event::Handler& handler); {% endif %} +{% elif Property.attrib['Container'] == 'Vector' %} const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Vector() const; const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const; const {{ Property.attrib['Type'] }} &{{ PropertyName }}GetBack() const; uint32_t {{ PropertyName }}GetSize() const; +{% if Property.attrib['GenerateEventBindings']|booleanTrue %} +void {{ PropertyName }}AddEvent(AZ::Event::Handler& handler); +void {{ PropertyName }}SizeChangedAddEvent(AZ::Event::Handler& handler); +{% endif %} {% else %} +const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const; {% if Property.attrib['GenerateEventBindings']|booleanTrue %} void {{ PropertyName }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler); {% endif %} -const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const; {% endif %} {% endmacro %} {# @@ -221,14 +221,14 @@ AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] } #include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include {% call(Include) AutoComponentMacros.ParseIncludes(Component) %} #include <{{ Include.attrib['File'] }}> {% endcall %} @@ -323,17 +323,19 @@ namespace {{ Component.attrib['Namespace'] }} }; {% if NetworkInputCount > 0 %} - class NetworkInput + class {{ ComponentName }}NetworkInput : public Multiplayer::IMultiplayerComponentInput { public: - Multiplayer::NetComponentId GetComponentId() const override; - INetworkInput& operator=(const INetworkInput& rhs) override; - bool Serialize(AzNetworking::ISerializer& serializer); + Multiplayer::NetComponentId GetNetComponentId() const override; + bool Serialize(AzNetworking::ISerializer& serializer) override; {% call(Input) AutoComponentMacros.ParseNetworkInputs(Component) %} {{ Input.attrib['Type'] }} m_{{ LowerFirst(Input.attrib['Name']) }} = {{ Input.attrib['Type'] }}({{ Input.attrib['Init'] }}); {% endcall %} + + static Multiplayer::NetComponentId s_netComponentId; + friend void RegisterMultiplayerComponents(); }; {% endif %} @@ -415,6 +417,8 @@ namespace {{ Component.attrib['Namespace'] }} static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static AZStd::unique_ptr AllocateComponentInput(); + {{ ComponentBaseName }}() = default; ~{{ ComponentBaseName }}() override = default; @@ -428,6 +432,7 @@ namespace {{ Component.attrib['Namespace'] }} {% endif %} {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', false)|indent(8) -}} + {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', false)|indent(8) -}} {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', false)|indent(8) }} {{ DeclareArchetypePropertyGetters(Component)|indent(8) -}} {{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) }} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 200d38910b..516e6a05e8 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -476,7 +476,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re {%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%} {% endcall %} {% if networkPropertyCount.value > 0 %} - MultiplayerStats& stats = GetMultiplayer()->GetStats(); + Multiplayer::MultiplayerStats& stats = Multiplayer::GetMultiplayer()->GetStats(); // We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server) [[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} @@ -492,9 +492,9 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re if (deltaRecord.AnySet()) { {% if Property.attrib['Container'] == 'Vector' %} - NovaNet::SerializableFixedSizeVectorDeltaStruct<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ LowerFirst(Property.attrib['Name']) }}, deltaRecord); + Multiplayer::SerializableFixedSizeVectorDeltaStruct<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ LowerFirst(Property.attrib['Name']) }}, deltaRecord); {% else %} - NovaNet::SerializableFixedSizeArrayDeltaStruct<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ Property.attrib['Name'] }}, deltaRecord); + Multiplayer::SerializableFixedSizeArrayDeltaStruct<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ Property.attrib['Name'] }}, deltaRecord); {% endif %} serializer.Serialize(deltaStruct, "{{ UpperFirst(Property.attrib['Name']) }}"); } @@ -509,7 +509,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ Property.attrib['Name'] }}", GetNetComponentId(), - static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties::{{ UpperFirst(Property.attrib['Name']) }}), + static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties::{{ UpperFirst(Property.attrib['Name']) }}), stats ); {% endif %} @@ -902,8 +902,8 @@ m_{{ LowerFirst(Property.attrib['Name']) }} = m_{{ LowerFirst(Property.attrib['N #include #include #include -#include -#include +#include +#include {% if ComponentDerived or ControllerDerived %} #include <{{ Component.attrib['OverrideInclude'] }}> {% endif %} @@ -916,6 +916,9 @@ m_{{ LowerFirst(Property.attrib['Name']) }} = m_{{ LowerFirst(Property.attrib['N namespace {{ Component.attrib['Namespace'] }} { Multiplayer::NetComponentId {{ UpperFirst(ComponentBaseName) }}::s_netComponentId = Multiplayer::InvalidNetComponentId; +{% if NetworkInputCount > 0 %} + Multiplayer::NetComponentId {{ ComponentName }}NetworkInput::s_netComponentId = Multiplayer::InvalidNetComponentId; +{% endif %} namespace {{ UpperFirst(Component.attrib['Name']) }}Internal { @@ -1051,6 +1054,21 @@ namespace {{ Component.attrib['Namespace'] }} {{ GenerateModelReplicationRecordPredictableBits(Component, ClassType, 'Autonomous', 'Authority')|indent(8) }} } +{% if NetworkInputCount > 0 %} + Multiplayer::NetComponentId {{ ComponentName }}NetworkInput::GetNetComponentId() const + { + return {{ ComponentName }}NetworkInput::s_netComponentId; + } + + bool {{ ComponentName }}NetworkInput::Serialize(AzNetworking::ISerializer& serializer) + { +{% call(Input) AutoComponentMacros.ParseNetworkInputs(Component) %} + serializer.Serialize(m_{{ LowerFirst(Input.attrib['Name']) }}, "{{ UpperFirst(Input.attrib['Name']) }}"); +{% endcall %} + return serializer.IsValid(); + } + +{% endif %} {{ ControllerBaseName }}::{{ ControllerBaseName }}({{ ComponentName }}& parent) : MultiplayerController(parent) { @@ -1107,10 +1125,10 @@ namespace {{ Component.attrib['Namespace'] }} {{ DefineRpcInvocations(Component, ControllerBaseName, 'Authority', 'Client', true)|indent(4) }} {% for Service in Component.iter('ComponentRelation') %} {% if (Service.attrib['HasController']|booleanTrue) and (Service.attrib['Constraint'] != 'Incompatible') %} - {{ Service.attrib['Name'] }}Controller* {{ ControllerBaseName }}::Get{{ Service.attrib['Name'] }}Controller() + {{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}Controller* {{ ControllerBaseName }}::Get{{ Service.attrib['Name'] }}Controller() { - MultiplayerComponent* controllerComponent = GetParent().Get{{ Service.attrib['Name'] }}(); - return static_cast<{{ Service.attrib['Name'] }}Controller*>(controllerComponent->GetController()); + Multiplayer::MultiplayerComponent* controllerComponent = GetParent().Get{{ Service.attrib['Name'] }}(); + return static_cast<{{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}Controller*>(controllerComponent->GetController()); } {% endif %} @@ -1164,7 +1182,7 @@ namespace {{ Component.attrib['Namespace'] }} void {{ ComponentBaseName }}::{{ ComponentBaseName }}::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC_CE("{{ ComponentName }}Service")); + provided.push_back(AZ_CRC_CE("{{ ComponentName }}")); } void {{ ComponentBaseName }}::{{ ComponentBaseName }}::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) @@ -1184,12 +1202,21 @@ namespace {{ Component.attrib['Namespace'] }} void {{ ComponentBaseName }}::{{ ComponentBaseName }}::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC_CE("{{ ComponentName }}Service")); + incompatible.push_back(AZ_CRC_CE("{{ ComponentName }}")); {% call(ComponentService) ParseComponentServiceNames(Component, ClassType, 'Incompatible') %} incompatible.push_back(AZ_CRC_CE("{{ ComponentService }}")); {% endcall %} } + AZStd::unique_ptr {{ ComponentBaseName }}::AllocateComponentInput() + { +{% if NetworkInputCount > 0 %} + return AZStd::make_unique<{{ ComponentName }}NetworkInput>(); +{% else %} + return nullptr; +{% endif %} + } + void {{ ComponentBaseName }}::Init() { if (m_netBindComponent == nullptr) @@ -1408,6 +1435,7 @@ namespace {{ Component.attrib['Namespace'] }} } {% endif %} +{% endfor %} const char* {{ ComponentBaseName }}::GetNetworkPropertyName([[maybe_unused]] Multiplayer::PropertyIndex propertyIndex) { {% if NetworkPropertyCount > 0 %} @@ -1437,6 +1465,5 @@ namespace {{ Component.attrib['Namespace'] }} {% endif %} return "Unknown Rpc"; } -{% endfor %} } {% endfor %} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index a5a7e8decd..94bdac2b5d 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -5,13 +5,13 @@ Namespace="Multiplayer" OverrideComponent="true" OverrideController="true" - OverrideInclude="Source/Components/LocalPredictionPlayerInputComponent.h" + OverrideInclude="Multiplayer/Components/LocalPredictionPlayerInputComponent.h" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - + - + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml index 1260075cba..2f934979b1 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml @@ -3,9 +3,9 @@ - - - + + + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml index e76ac75edc..96653a607c 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml @@ -5,7 +5,7 @@ Namespace="Multiplayer" OverrideComponent="true" OverrideController="true" - OverrideInclude="Source/Components/NetworkTransformComponent.h" + OverrideInclude="Multiplayer/Components/NetworkTransformComponent.h" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index b57c465df2..46136fcde9 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include #include @@ -81,12 +81,7 @@ namespace Multiplayer , m_migrateStartHandler([this](ClientInputId migratedInputId) { OnMigrateStart(migratedInputId); }) , m_migrateEndHandler([this]() { OnMigrateEnd(); }) { - if (GetNetEntityRole() == NetEntityRole::Autonomous) - { - m_autonomousUpdateEvent.Enqueue(AZ::TimeMs{ 1 }, true); - parent.GetNetBindComponent()->AddEntityMigrationStartEventHandler(m_migrateStartHandler); - parent.GetNetBindComponent()->AddEntityMigrationEndEventHandler(m_migrateEndHandler); - } + ; } void LocalPredictionPlayerInputComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) @@ -96,6 +91,13 @@ namespace Multiplayer m_allowMigrateClientInput = true; m_serverMigrateFrameId = GetNetworkTime()->GetHostFrameId(); } + + if (IsAutonomous()) + { + m_autonomousUpdateEvent.Enqueue(AZ::TimeMs{ 1 }, true); + GetParent().GetNetBindComponent()->AddEntityMigrationStartEventHandler(m_migrateStartHandler); + GetParent().GetNetBindComponent()->AddEntityMigrationEndEventHandler(m_migrateEndHandler); + } } void LocalPredictionPlayerInputComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp index ae6fc50f5a..8542288b23 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp @@ -10,8 +10,8 @@ * */ -#include -#include +#include +#include #include namespace Multiplayer @@ -46,9 +46,24 @@ namespace Multiplayer return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId; } - NetEntityRole MultiplayerComponent::GetNetEntityRole() const + bool MultiplayerComponent::IsAuthority() const { - return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole; + return m_netBindComponent ? m_netBindComponent->IsAuthority() : false; + } + + bool MultiplayerComponent::IsAutonomous() const + { + return m_netBindComponent ? m_netBindComponent->IsAutonomous() : false; + } + + bool MultiplayerComponent::IsServer() const + { + return m_netBindComponent ? m_netBindComponent->IsServer() : false; + } + + bool MultiplayerComponent::IsClient() const + { + return m_netBindComponent ? m_netBindComponent->IsClient() : false; } ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp index 648b28633e..7e7cbfc480 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp @@ -10,7 +10,7 @@ * */ -#include +#include namespace Multiplayer { @@ -21,6 +21,12 @@ namespace Multiplayer return netComponentId; } + AZStd::unique_ptr MultiplayerComponentRegistry::AllocateComponentInput(NetComponentId netComponentId) + { + const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); + return AZStd::move(componentData.m_allocComponentInputFunction()); + } + const char* MultiplayerComponentRegistry::GetComponentGemName(NetComponentId netComponentId) const { const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp index 9b8f41d5bc..b0bafccf79 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp @@ -10,9 +10,9 @@ * */ -#include -#include -#include +#include +#include +#include namespace Multiplayer { @@ -27,9 +27,14 @@ namespace Multiplayer return m_owner.GetNetEntityId(); } - NetEntityRole MultiplayerController::GetNetEntityRole() const + bool MultiplayerController::IsAuthority() const { - return GetNetBindComponent()->GetNetEntityRole(); + return GetNetBindComponent() ? GetNetBindComponent()->IsAuthority() : false; + } + + bool MultiplayerController::IsAutonomous() const + { + return GetNetBindComponent() ? GetNetBindComponent()->IsAutonomous() : false; } AZ::Entity* MultiplayerController::GetEntity() const diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index 6dc661415e..6449f57e8e 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -10,13 +10,13 @@ * */ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -110,6 +110,22 @@ namespace Multiplayer return (m_netEntityRole == NetEntityRole::Authority); } + bool NetBindComponent::IsAutonomous() const + { + return (m_netEntityRole == NetEntityRole::Autonomous) + || (m_netEntityRole == NetEntityRole::Authority) && m_allowAutonomy; + } + + bool NetBindComponent::IsServer() const + { + return (m_netEntityRole == NetEntityRole::Server); + } + + bool NetBindComponent::IsClient() const + { + return (m_netEntityRole == NetEntityRole::Client); + } + bool NetBindComponent::HasController() const { return (m_netEntityRole == NetEntityRole::Authority) @@ -136,14 +152,21 @@ namespace Multiplayer return m_netEntityHandle; } + void NetBindComponent::SetAllowAutonomy(bool value) + { + // This flag allows a player host to autonomously control their player entity, even though the entity is in an authority role + m_allowAutonomy = value; + } + MultiplayerComponentInputVector NetBindComponent::AllocateComponentInputs() { MultiplayerComponentInputVector componentInputs; const size_t multiplayerComponentSize = m_multiplayerInputComponentVector.size(); for (size_t i = 0; i < multiplayerComponentSize; ++i) { - // TODO: ComponentInput factory, needs multiplayer component architecture and autogen - AZStd::unique_ptr componentInput = nullptr; // ComponentInputFactory(multiplayerComponent->GetComponentId()); + const NetComponentId netComponentId = m_multiplayerInputComponentVector[i]->GetNetComponentId(); + AZStd::unique_ptr componentInput = AZStd::move(GetMultiplayerComponentRegistry()->AllocateComponentInput(netComponentId)); + if (componentInput != nullptr) { componentInputs.emplace_back(AZStd::move(componentInput)); diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 607e2813ec..0cc4cb131e 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include #include @@ -96,7 +96,7 @@ namespace Multiplayer void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm) { - if (GetNetEntityRole() == NetEntityRole::Authority) + if (IsAuthority()) { SetRotation(worldTm.GetRotation()); SetTranslation(worldTm.GetTranslation()); diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h index 449ffafe45..2e7be47842 100644 --- a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h index 6274a6ba31..faa11bc225 100644 --- a/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ServerToClientConnectionData.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 1ae4bffd07..4ae7c3fdfe 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -138,7 +138,7 @@ namespace Multiplayer void DrawComponentDetails(const MultiplayerStats& stats, NetComponentId netComponentId) { - IMultiplayer* multiplayer = AZ::Interface::Get(); + MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry(); { const MultiplayerStats::Metric metric = stats.CalculateComponentPropertyUpdateSentMetrics(netComponentId); float callsPerSecond = 0.0f; @@ -150,7 +150,7 @@ namespace Multiplayer for (AZStd::size_t index = 0; index < componentStats.m_propertyUpdatesSent.size(); ++index) { const PropertyIndex propertyIndex = aznumeric_cast(index); - const char* propertyName = multiplayer->GetComponentPropertyName(netComponentId, propertyIndex); + const char* propertyName = componentRegistry->GetComponentPropertyName(netComponentId, propertyIndex); const MultiplayerStats::Metric& subMetric = componentStats.m_propertyUpdatesSent[index]; callsPerSecond = 0.0f; bytesPerSecond = 0.0f; @@ -172,7 +172,7 @@ namespace Multiplayer for (AZStd::size_t index = 0; index < componentStats.m_propertyUpdatesRecv.size(); ++index) { const PropertyIndex propertyIndex = aznumeric_cast(index); - const char* propertyName = multiplayer->GetComponentPropertyName(netComponentId, propertyIndex); + const char* propertyName = componentRegistry->GetComponentPropertyName(netComponentId, propertyIndex); const MultiplayerStats::Metric& subMetric = componentStats.m_propertyUpdatesRecv[index]; callsPerSecond = 0.0f; bytesPerSecond = 0.0f; @@ -194,7 +194,7 @@ namespace Multiplayer for (AZStd::size_t index = 0; index < componentStats.m_rpcsSent.size(); ++index) { const RpcIndex rpcIndex = aznumeric_cast(index); - const char* rpcName = multiplayer->GetComponentRpcName(netComponentId, rpcIndex); + const char* rpcName = componentRegistry->GetComponentRpcName(netComponentId, rpcIndex); const MultiplayerStats::Metric& subMetric = componentStats.m_rpcsSent[index]; callsPerSecond = 0.0f; bytesPerSecond = 0.0f; @@ -216,7 +216,7 @@ namespace Multiplayer for (AZStd::size_t index = 0; index < componentStats.m_rpcsRecv.size(); ++index) { const RpcIndex rpcIndex = aznumeric_cast(index); - const char* rpcName = multiplayer->GetComponentRpcName(netComponentId, rpcIndex); + const char* rpcName = componentRegistry->GetComponentRpcName(netComponentId, rpcIndex); const MultiplayerStats::Metric& subMetric = componentStats.m_rpcsRecv[index]; callsPerSecond = 0.0f; bytesPerSecond = 0.0f; @@ -238,6 +238,7 @@ namespace Multiplayer if (ImGui::Begin("Multiplayer Stats", &m_displayMultiplayerStats, ImGuiWindowFlags_None)) { IMultiplayer* multiplayer = AZ::Interface::Get(); + MultiplayerComponentRegistry* componentRegistry = GetMultiplayerComponentRegistry(); const Multiplayer::MultiplayerStats& stats = multiplayer->GetStats(); ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType())); ImGui::Text("Total networked entities: %llu", aznumeric_cast(stats.m_entityCount)); @@ -267,8 +268,8 @@ namespace Multiplayer { const NetComponentId netComponentId = aznumeric_cast(index); using StringLabel = AZStd::fixed_string<128>; - const StringLabel gemName = multiplayer->GetComponentGemName(netComponentId); - const StringLabel componentName = multiplayer->GetComponentName(netComponentId); + const StringLabel gemName = componentRegistry->GetComponentGemName(netComponentId); + const StringLabel componentName = componentRegistry->GetComponentName(netComponentId); const StringLabel label = gemName + "::" + componentName; if (DrawComponentRow(label.c_str(), stats, netComponentId)) { diff --git a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h index 3bf6eb554f..d8d264dc34 100644 --- a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h +++ b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h @@ -12,7 +12,7 @@ #pragma once -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index aef3e546ad..14bb71bcd5 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.cpp b/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp similarity index 100% rename from Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerStats.cpp rename to Gems/Multiplayer/Code/Source/MultiplayerStats.cpp diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 80a09d7d48..a10bbf8a1a 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -576,26 +576,6 @@ namespace Multiplayer return &m_networkEntityManager; } - const char* MultiplayerSystemComponent::GetComponentGemName(NetComponentId netComponentId) const - { - return GetMultiplayerComponentRegistry()->GetComponentGemName(netComponentId); - } - - const char* MultiplayerSystemComponent::GetComponentName(NetComponentId netComponentId) const - { - return GetMultiplayerComponentRegistry()->GetComponentName(netComponentId); - } - - const char* MultiplayerSystemComponent::GetComponentPropertyName(NetComponentId netComponentId, PropertyIndex propertyIndex) const - { - return GetMultiplayerComponentRegistry()->GetComponentPropertyName(netComponentId, propertyIndex); - } - - const char* MultiplayerSystemComponent::GetComponentRpcName(NetComponentId netComponentId, RpcIndex rpcIndex) const - { - return GetMultiplayerComponentRegistry()->GetComponentRpcName(netComponentId, rpcIndex); - } - void MultiplayerSystemComponent::DumpStats([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { const MultiplayerStats& stats = GetStats(); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index ba59a82eae..6bedd0599b 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -94,10 +94,6 @@ namespace Multiplayer AZ::TimeMs GetCurrentHostTimeMs() const override; INetworkTime* GetNetworkTime() override; INetworkEntityManager* GetNetworkEntityManager() override; - const char* GetComponentGemName(NetComponentId netComponentId) const override; - const char* GetComponentName(NetComponentId netComponentId) const override; - const char* GetComponentPropertyName(NetComponentId netComponentId, PropertyIndex propertyIndex) const override; - const char* GetComponentRpcName(NetComponentId netComponentId, RpcIndex rpcIndex) const override; //! @} //! Console commands. diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index 286090ca74..e47d142be8 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -15,13 +15,13 @@ #include #include #include -#include -#include -#include -#include #include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -828,12 +828,11 @@ namespace Multiplayer { if (entityReplicator == nullptr) { - IMultiplayer* multiplayer = GetMultiplayer(); AZLOG_INFO ( "EntityReplicationManager: Dropping remote RPC message for component %s of rpc index %s, entityId %u has already been deleted", - multiplayer->GetComponentName(message.GetComponentId()), - multiplayer->GetComponentRpcName(message.GetComponentId(), message.GetRpcIndex()), + GetMultiplayerComponentRegistry()->GetComponentName(message.GetComponentId()), + GetMultiplayerComponentRegistry()->GetComponentRpcName(message.GetComponentId(), message.GetRpcIndex()), message.GetEntityId() ); return false; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 50a4ad43d4..083413e19e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -13,11 +13,11 @@ #pragma once #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 15293d518d..f84487080b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -16,11 +16,11 @@ #include #include #include -#include #include #include -#include -#include +#include +#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h index 3587c28975..ced665abf3 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h @@ -18,8 +18,8 @@ #include #include #include -#include -#include +#include +#include namespace AzNetworking { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertyPublisher.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertyPublisher.h index be8ac1b65b..fb23adfbd5 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertyPublisher.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertyPublisher.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace AzNetworking diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertySubscriber.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertySubscriber.cpp index 4994884364..b74c8af081 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertySubscriber.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/PropertySubscriber.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/ReplicationRecord.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/ReplicationRecord.cpp index 6aa6c10b11..41cc86aaee 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/ReplicationRecord.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/ReplicationRecord.cpp @@ -10,7 +10,7 @@ * */ -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp index ecfd416380..f30b7ee9e0 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp @@ -11,8 +11,8 @@ */ #include -#include -#include +#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityHandle.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityHandle.cpp index 0dd7292d25..3ca56f01b3 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityHandle.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityHandle.cpp @@ -10,10 +10,10 @@ * */ -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 28b72abf25..6f3fdf2b23 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index e763e7ebca..3291f2c38d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -18,10 +18,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp index d58c192162..f636fb6447 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.cpp index 42104e79fd..2dac90deee 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.cpp @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h index 34f5d03f2f..1b4b7f15f1 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h @@ -13,7 +13,7 @@ #pragma once #include -#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityUpdateMessage.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityUpdateMessage.cpp index 5ece0c7157..3fe5a497cb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityUpdateMessage.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityUpdateMessage.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index eafd4375e7..7b9cba5a93 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -10,8 +10,10 @@ * */ -#include -#include +#include +#include +#include +#include #include #include @@ -111,13 +113,12 @@ namespace Multiplayer // This happens when deserializing a non-delta'd input command // However in the delta serializer case, we use the previous input as our initial value // which will have the NetworkInputs setup and therefore won't write out the componentId - NetComponentId componentId = m_componentInputs[i] ? m_componentInputs[i]->GetComponentId() : InvalidNetComponentId; + NetComponentId componentId = m_componentInputs[i] ? m_componentInputs[i]->GetNetComponentId() : InvalidNetComponentId; serializer.Serialize(componentId, "ComponentType"); // Create a new input if we don't have one or the types do not match - if ((m_componentInputs[i] == nullptr) || (componentId != m_componentInputs[i]->GetComponentId())) + if ((m_componentInputs[i] == nullptr) || (componentId != m_componentInputs[i]->GetNetComponentId())) { - // TODO: ComponentInput factory, needs multiplayer component architecture and autogen - m_componentInputs[i] = nullptr; // ComponentInputFactory(componentId); + m_componentInputs[i] = AZStd::move(GetMultiplayerComponentRegistry()->AllocateComponentInput(componentId)); } if (!m_componentInputs[i]) { @@ -135,7 +136,7 @@ namespace Multiplayer // We assume that the order of the network inputs is fixed between the server and client for (auto& componentInput : m_componentInputs) { - NetComponentId componentId = componentInput->GetComponentId(); + NetComponentId componentId = componentInput->GetNetComponentId(); serializer.Serialize(componentId, "ComponentId"); serializer.Serialize(*componentInput, "ComponentInput"); } @@ -148,7 +149,7 @@ namespace Multiplayer // linear search since we expect to have very few components for (auto& componentInput : m_componentInputs) { - if (componentInput->GetComponentId() == componentId) + if (componentInput->GetNetComponentId() == componentId) { return componentInput.get(); } @@ -169,10 +170,10 @@ namespace Multiplayer m_componentInputs.resize(rhs.m_componentInputs.size()); for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i) { - if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetComponentId() != rhs.m_componentInputs[i]->GetComponentId()) + const NetComponentId rhsComponentId = rhs.m_componentInputs[i]->GetNetComponentId(); + if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetNetComponentId() != rhsComponentId) { - // TODO: ComponentInput factory, needs multiplayer component architecture and autogen - m_componentInputs[i] = nullptr; // ComponentInputFactory(rhs.m_componentInputs[i]->GetComponentId()); + m_componentInputs[i] = AZStd::move(GetMultiplayerComponentRegistry()->AllocateComponentInput(rhsComponentId)); } *m_componentInputs[i] = *rhs.m_componentInputs[i]; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp index 82e5cea0c4..d95310e4b5 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h index d5cbcbbed3..b67ce79112 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h @@ -12,8 +12,8 @@ #pragma once -#include -#include +#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputChild.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputChild.h index fa4ab1e4e9..e81bce0210 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputChild.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputChild.h @@ -12,7 +12,7 @@ #pragma once -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputHistory.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputHistory.h index c5f0a70fd3..76eeebf73a 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputHistory.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputHistory.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputMigrationVector.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputMigrationVector.h index 454cef4e0a..e5f8fdf648 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputMigrationVector.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputMigrationVector.h @@ -12,8 +12,8 @@ #pragma once -#include -#include +#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index d991e59d05..98ece0a8cc 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -11,8 +11,8 @@ */ #include -#include #include +#include #include namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index ff2da0f759..f714e046b3 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index 805a982506..4661df7564 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h index 5cb9c0de70..f633a35a14 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h @@ -12,7 +12,7 @@ #pragma once -#include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp index bf370c1952..d048476cc0 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.h b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.h index 25fbfd481d..fc143a7cc4 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.h +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.h @@ -13,8 +13,8 @@ #pragma once #include -#include -#include +#include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp index f614dc2690..4596e3b35c 100644 --- a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp +++ b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp @@ -10,8 +10,8 @@ * */ -#include #include +#include #include #include #include diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 26909cbfd3..7b335854fa 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -10,33 +10,34 @@ # set(FILES - Include/Multiplayer/IConnectionData.h - Include/Multiplayer/IEntityDomain.h Include/Multiplayer/IMultiplayer.h - Include/Multiplayer/IMultiplayerComponentInput.h - Include/Multiplayer/INetworkEntityManager.h - Include/Multiplayer/INetworkPlayerSpawner.h - Include/Multiplayer/INetworkTime.h - Include/Multiplayer/IReplicationWindow.h - Include/Multiplayer/MultiplayerComponent.h - Include/Multiplayer/MultiplayerController.h - Include/Multiplayer/MultiplayerComponentRegistry.h - Include/Multiplayer/MultiplayerStats.cpp Include/Multiplayer/MultiplayerStats.h Include/Multiplayer/MultiplayerTypes.h - Include/Multiplayer/NetBindComponent.h - Include/Multiplayer/NetworkEntityRpcMessage.h - Include/Multiplayer/NetworkEntityUpdateMessage.h - Include/Multiplayer/NetworkEntityHandle.h - Include/Multiplayer/NetworkEntityHandle.inl - Include/Multiplayer/NetworkInput.h - Include/Multiplayer/ReplicationRecord.h - Include/Multiplayer/RewindableObject.h - Include/Multiplayer/RewindableObject.inl + Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h + Include/Multiplayer/Components/MultiplayerComponent.h + Include/Multiplayer/Components/MultiplayerController.h + Include/Multiplayer/Components/MultiplayerComponentRegistry.h + Include/Multiplayer/Components/NetBindComponent.h + Include/Multiplayer/Components/NetworkTransformComponent.h + Include/Multiplayer/ConnectionData/IConnectionData.h + Include/Multiplayer/EntityDomains/IEntityDomain.h + Include/Multiplayer/NetworkEntity/INetworkEntityManager.h + Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h + Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h + Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h + Include/Multiplayer/NetworkEntity/NetworkEntityHandle.inl + Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h + Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h + Include/Multiplayer/NetworkInput/NetworkInput.h + Include/Multiplayer/NetworkTime/INetworkTime.h + Include/Multiplayer/NetworkTime/RewindableObject.h + Include/Multiplayer/NetworkTime/RewindableObject.inl + Include/Multiplayer/ReplicationWindows/IReplicationWindow.h Source/Multiplayer_precompiled.cpp Source/Multiplayer_precompiled.h Source/MultiplayerSystemComponent.cpp Source/MultiplayerSystemComponent.h + Source/MultiplayerStats.cpp Source/AutoGen/AutoComponent_Header.jinja Source/AutoGen/AutoComponent_Source.jinja Source/AutoGen/AutoComponent_Common.jinja @@ -46,13 +47,11 @@ set(FILES Source/AutoGen/Multiplayer.AutoPackets.xml Source/AutoGen/NetworkTransformComponent.AutoComponent.xml Source/Components/LocalPredictionPlayerInputComponent.cpp - Source/Components/LocalPredictionPlayerInputComponent.h Source/Components/MultiplayerComponent.cpp Source/Components/MultiplayerController.cpp Source/Components/MultiplayerComponentRegistry.cpp Source/Components/NetBindComponent.cpp Source/Components/NetworkTransformComponent.cpp - Source/Components/NetworkTransformComponent.h Source/ConnectionData/ClientToServerConnectionData.cpp Source/ConnectionData/ClientToServerConnectionData.h Source/ConnectionData/ClientToServerConnectionData.inl From bb3142278e2bb90049f5ccb06a846a49724a190e Mon Sep 17 00:00:00 2001 From: karlberg Date: Fri, 14 May 2021 15:03:11 -0700 Subject: [PATCH 2/5] Fixes an example comment error in multiplayer component jinjas --- .../Code/Source/AutoGen/AutoComponent_Common.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja index d187a151fd..4279c26cf2 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja @@ -282,14 +282,14 @@ namespace {{ Component.attrib['Namespace'] }} void {{ ControllerName }}::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { } -{% if NetworkInputCount > 0 %} +{% if NetworkInputCount > 0 %} void {{ ControllerName }}::ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) { } +{% endif %} {% endif %} } -{% endif %} */ {% else %} // NOTE: From 61c24ee265f4f7d8fdf69785ac900f7ed88da214 Mon Sep 17 00:00:00 2001 From: karlberg Date: Fri, 14 May 2021 15:22:57 -0700 Subject: [PATCH 3/5] Removing tab in cmake file --- Gems/Multiplayer/Code/multiplayer_files.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 7b335854fa..8dd7c07689 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -37,7 +37,7 @@ set(FILES Source/Multiplayer_precompiled.h Source/MultiplayerSystemComponent.cpp Source/MultiplayerSystemComponent.h - Source/MultiplayerStats.cpp + Source/MultiplayerStats.cpp Source/AutoGen/AutoComponent_Header.jinja Source/AutoGen/AutoComponent_Source.jinja Source/AutoGen/AutoComponent_Common.jinja From c6ea0c0a46c2d6df0bc20734440735349af073e3 Mon Sep 17 00:00:00 2001 From: karlberg Date: Sat, 15 May 2021 15:10:17 -0700 Subject: [PATCH 4/5] Various local prediction and input processing related fixes --- .../Serialization/HashSerializer.cpp | 4 +- .../LocalPredictionPlayerInputComponent.h | 3 +- .../Components/MultiplayerComponent.h | 1 + .../Multiplayer/Components/NetBindComponent.h | 1 + .../NetworkInput/IMultiplayerComponentInput.h | 1 + .../Source/AutoGen/AutoComponent_Header.jinja | 4 +- .../Source/AutoGen/AutoComponent_Source.jinja | 16 ++++ .../LocalPredictionPlayerInputComponent.cpp | 93 ++++++++----------- .../Source/Components/NetBindComponent.cpp | 8 ++ .../Source/MultiplayerSystemComponent.cpp | 1 + .../Code/Source/NetworkInput/NetworkInput.cpp | 5 +- .../Source/NetworkInput/NetworkInputArray.cpp | 11 --- .../Source/NetworkInput/NetworkInputArray.h | 4 - 13 files changed, 78 insertions(+), 74 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.cpp b/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.cpp index c7f47cbc04..479299a87b 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.cpp +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/HashSerializer.cpp @@ -22,7 +22,9 @@ namespace AzNetworking AZ::HashValue32 HashSerializer::GetHash() const { // Just truncate the upper bits - return static_cast(m_hash); + const AZ::HashValue32 lower = static_cast(m_hash); + const AZ::HashValue32 upper = static_cast(m_hash >> 32); + return lower ^ upper; } SerializerMode HashSerializer::GetSerializerMode() const diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h index 7a6105a7e3..c69623a9e9 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h @@ -102,7 +102,8 @@ namespace Multiplayer AZ::TimeMs m_lastInputReceivedTimeMs = AZ::TimeMs{ 0 }; AZ::TimeMs m_lastCorrectionSentTimeMs = AZ::TimeMs{ 0 }; - ClientInputId m_clientInputId = ClientInputId{ 0 }; + ClientInputId m_clientInputId = ClientInputId{ 0 }; // Clients incrementing inputId + ClientInputId m_lastClientInputId = ClientInputId{ 0 }; // Last inputId processed by the server ClientInputId m_lastCorrectionInputId = ClientInputId{ 0 }; ClientInputId m_lastMigratedInputId = ClientInputId{ 0 }; // Used to resend inputs that were queued during a migration event HostFrameId m_serverMigrateFrameId = InvalidHostFrameId; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h index 6f410dd97c..19689171c5 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerComponent.h @@ -71,6 +71,7 @@ namespace Multiplayer NetworkEntityHandle GetEntityHandle(); void MarkDirty(); + virtual void SetOwningConnectionId(AzNetworking::ConnectionId connectionId) = 0; virtual NetComponentId GetNetComponentId() const = 0; virtual bool HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetEntityRole netEntityRole, NetworkEntityRpcMessage& rpcMessage) = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index 257e7cab4b..41503396fb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -72,6 +72,7 @@ namespace Multiplayer ConstNetworkEntityHandle GetEntityHandle() const; NetworkEntityHandle GetEntityHandle(); + void SetOwningConnectionId(AzNetworking::ConnectionId connectionId); void SetAllowAutonomy(bool value); MultiplayerComponentInputVector AllocateComponentInputs(); bool IsProcessingInput() const; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h index 13faff3a7e..7af1bf3f60 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h @@ -30,6 +30,7 @@ namespace Multiplayer virtual ~IMultiplayerComponentInput() = default; virtual NetComponentId GetNetComponentId() const = 0; virtual bool Serialize(AzNetworking::ISerializer& serializer) = 0; + virtual IMultiplayerComponentInput& operator= (const IMultiplayerComponentInput&) { return *this; } }; using MultiplayerComponentInputVector = AZStd::vector>; diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 0d4e7146a0..8eede21452 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -329,6 +329,7 @@ namespace {{ Component.attrib['Namespace'] }} public: Multiplayer::NetComponentId GetNetComponentId() const override; bool Serialize(AzNetworking::ISerializer& serializer) override; + Multiplayer::IMultiplayerComponentInput& operator =(const Multiplayer::IMultiplayerComponentInput& rhs) override; {% call(Input) AutoComponentMacros.ParseNetworkInputs(Component) %} {{ Input.attrib['Type'] }} m_{{ LowerFirst(Input.attrib['Name']) }} = {{ Input.attrib['Type'] }}({{ Input.attrib['Init'] }}); @@ -439,6 +440,7 @@ namespace {{ Component.attrib['Namespace'] }} //! MultiplayerComponent interface //! @{ + void SetOwningConnectionId(AzNetworking::ConnectionId connectionId) override; Multiplayer::NetComponentId GetNetComponentId() const override; bool HandleRpcMessage(AzNetworking::IConnection* invokingConnection, Multiplayer::NetEntityRole remoteRole, Multiplayer::NetworkEntityRpcMessage& rpcMessage) override; bool SerializeStateDeltaMessage(Multiplayer::ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) override; @@ -519,7 +521,7 @@ namespace {{ Component.attrib['Namespace'] }} //! Archetype Properties {{ DeclareArchetypePropertyVars(Component)|indent(8) }} {% call(Type, Name) AutoComponentMacros.ParseComponentServiceTypeAndName(Component) %} - {{ Type }}* {{ Name }} = nullptr; + {{ Type }}* {{ Name }} = nullptr; {% endcall %} static Multiplayer::NetComponentId s_netComponentId; diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 516e6a05e8..3b3fa817cd 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1068,6 +1068,13 @@ namespace {{ Component.attrib['Namespace'] }} return serializer.IsValid(); } + Multiplayer::IMultiplayerComponentInput& {{ ComponentName }}NetworkInput::operator =([[maybe_unused]] const Multiplayer::IMultiplayerComponentInput& rhs) + { + AZ_Assert(s_netComponentId == rhs.GetNetComponentId(), "AttachNetSystemComponent was not called on the owning NetworkInput"); + *this = *static_cast(&rhs); + return *this; + } + {% endif %} {{ ControllerBaseName }}::{{ ControllerBaseName }}({{ ComponentName }}& parent) : MultiplayerController(parent) @@ -1278,6 +1285,15 @@ namespace {{ Component.attrib['Namespace'] }} {{ DefineRpcInvocations(Component, ComponentBaseName, 'Server', 'Authority', false)|indent(4) -}} {{ DefineRpcInvocations(Component, ComponentBaseName, 'Server', 'Authority', true)|indent(4) }} + void {{ ComponentBaseName }}::SetOwningConnectionId([[maybe_unused]] AzNetworking::ConnectionId connectionId) + { +{% for Property in Component.iter('NetworkProperty') %} +{% if Property.attrib['IsRewindable']|booleanTrue %} + m_{{ LowerFirst(Property.attrib['Name']) }}.SetOwningConnectionId(connectionId); +{% endif %} +{% endfor %} + } + Multiplayer::NetComponentId {{ ComponentBaseName }}::GetNetComponentId() const { return s_netComponentId; diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 46136fcde9..10a0d17e73 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -113,73 +113,57 @@ namespace Multiplayer [[maybe_unused]] const AzNetworking::PacketEncodingBuffer& clientState ) { - // After receiving the first input from the client, start the update event to check for slow hacking - if (!m_updateBankedTimeEvent.IsScheduled()) - { - m_updateBankedTimeEvent.Enqueue(sv_InputUpdateTimeMs, true); - } - if (invokingConnection == nullptr) { // Discard any input messages that were locally dispatched or sent by disconnected clients return; } + const ClientInputId clientInputId = inputArray[0].GetClientInputId(); + if (clientInputId <= m_lastClientInputId) + { + AZLOG(NET_Prediction, "Discarding old or out of order move input (current: %u, received %u)", + aznumeric_cast(m_lastClientInputId), aznumeric_cast(clientInputId)); + return; + } + + // After receiving the first input from the client, start the update event to check for slow hacking + if (!m_updateBankedTimeEvent.IsScheduled()) + { + m_updateBankedTimeEvent.Enqueue(sv_InputUpdateTimeMs, true); + } + const AZ::TimeMs currentTimeMs = AZ::GetElapsedTimeMs(); const double clientInputRateSec = static_cast(static_cast(cl_InputRateMs)) / 1000.0; m_lastInputReceivedTimeMs = currentTimeMs; // Keep track of last inputs received, also allows us to update frame ids m_lastInputReceived = inputArray; - - // Figure out which index from the input array we want - // we start at the oldest input that has not been processed - int32_t inputArrayIndex = -1; - for (int32_t i = NetworkInputArray::MaxElements - 1; i >= 0; --i) - { - // Find an input that is newer than the last one we processed - if (m_lastInputReceived[i].GetClientInputId() > GetLastInputId()) - { - inputArrayIndex = i; - break; - } - } - - if (inputArrayIndex < 0) - { - AZLOG - ( - NET_Prediction, - "Discarding old or out of order move input (current: %u, received %u)", - aznumeric_cast(GetLastInputId()), - aznumeric_cast(m_lastInputReceived[0].GetClientInputId()) - ); - return; - } - - bool lostInput = false; - if (GetLastInputId() < inputArray.GetPreviousInputId()) - { - // last move id processed is older than the previous input id, we missed some input packets - lostInput = true; - } - SetLastInputId(m_lastInputReceived[0].GetClientInputId()); // Set this variable in case of migration - while (inputArrayIndex >= 0) + while (m_lastClientInputId < clientInputId) { - NetworkInput& input = m_lastInputReceived[inputArrayIndex]; + ++m_lastClientInputId; + + // Figure out which index from the input array we want + // If we have skipped an id, check if it was sent to us in the array. If we have lost too many, just use the oldest one in the array + const uint32_t deltaFrameId = aznumeric_cast(clientInputId - m_lastClientInputId); // always >= 0 because of while loop check + const uint32_t inputArrayIdx = AZStd::min(deltaFrameId, NetworkInputArray::MaxElements - 1); + const bool lostInput = deltaFrameId >= NetworkInputArray::MaxElements; // For logging only + + NetworkInput &input = m_lastInputReceived[inputArrayIdx]; + input.SetClientInputId(m_lastClientInputId); // Anticheat, if we're receiving too many inputs, and fall outside our variable latency input window // Discard move input events, client may be speed hacking if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary - { ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); } + if (lostInput) { AZLOG(NET_Prediction, "InputLost InputId=%u", aznumeric_cast(input.GetClientInputId())); @@ -193,7 +177,6 @@ namespace Multiplayer { AZLOG(NET_Prediction, "Dropped InputId=%u", aznumeric_cast(input.GetClientInputId())); } - --inputArrayIndex; } if (sv_EnableCorrections && (currentTimeMs - m_lastCorrectionSentTimeMs > sv_MinCorrectionTimeMs)) @@ -205,6 +188,14 @@ namespace Multiplayer const AZ::HashValue32 localAuthorityHash = hashSerializer.GetHash(); + AZLOG + ( + NET_Prediction, + "Hash values for ProcessInput: client=%u, server=%u", + aznumeric_cast(stateHash), + aznumeric_cast(localAuthorityHash) + ); + if (stateHash != localAuthorityHash) { // Produce correction for client @@ -542,21 +533,15 @@ namespace Multiplayer m_inputHistory.PopFront(); } - const size_t inputHistorySize = m_inputHistory.Size(); + const int64_t inputHistorySize = aznumeric_cast(m_inputHistory.Size()); // Form the rest of the input array using the n most recent elements in the history buffer // NOTE: inputArray[0] has already been initialized hence start at i = 1 - for (uint32_t i = 1; i < NetworkInputArray::MaxElements; ++i) + for (int64_t i = 1; i < aznumeric_cast(NetworkInputArray::MaxElements); ++i) { - if (i < inputHistorySize) - { - inputArray[i] = m_inputHistory[inputHistorySize - 1 - i]; - } - else // History is too small? - { - // Plug in the most recent input - inputArray[i] = input; - } + // Clamp to oldest element if history is too small + const int64_t historyIndex = AZStd::max(inputHistorySize - 1 - i, 0); + inputArray[i] = m_inputHistory[historyIndex]; } // Send the input to server (only when we are not migrating) diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index 6449f57e8e..e48d0b0d09 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -152,6 +152,14 @@ namespace Multiplayer return m_netEntityHandle; } + void NetBindComponent::SetOwningConnectionId(AzNetworking::ConnectionId connectionId) + { + for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) + { + multiplayerComponent->SetOwningConnectionId(connectionId); + } + } + void NetBindComponent::SetAllowAutonomy(bool value) { // This flag allows a player host to autonomously control their player entity, even though the entity is in an authority role diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index a10bbf8a1a..723fada6d1 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -448,6 +448,7 @@ namespace Multiplayer if (entityList.size() > 0) { controlledEntity = entityList[0]; + controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId()); } if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index 7b9cba5a93..ba87849047 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ - +#pragma optimize ("", off) #include #include #include @@ -166,6 +166,7 @@ namespace Multiplayer void NetworkInput::CopyInternal(const NetworkInput& rhs) { m_inputId = rhs.m_inputId; + m_hostFrameId = rhs.m_hostFrameId; m_hostTimeMs = rhs.m_hostTimeMs; m_componentInputs.resize(rhs.m_componentInputs.size()); for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i) @@ -175,7 +176,7 @@ namespace Multiplayer { m_componentInputs[i] = AZStd::move(GetMultiplayerComponentRegistry()->AllocateComponentInput(rhsComponentId)); } - *m_componentInputs[i] = *rhs.m_componentInputs[i]; + *(m_componentInputs[i]) = *(rhs.m_componentInputs[i]); } m_wasAttached = rhs.m_wasAttached; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp index d95310e4b5..e736cd4da2 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.cpp @@ -48,16 +48,6 @@ namespace Multiplayer return m_inputs[index].m_networkInput; } - void NetworkInputArray::SetPreviousInputId(ClientInputId previousInputId) - { - m_previousInputId = previousInputId; - } - - ClientInputId NetworkInputArray::GetPreviousInputId() const - { - return m_previousInputId; - } - bool NetworkInputArray::Serialize(AzNetworking::ISerializer& serializer) { // Always serialize the full first element @@ -102,7 +92,6 @@ namespace Multiplayer } } } - serializer.Serialize(m_previousInputId, "PreviousInputId"); return true; } } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h index b67ce79112..293fb18928 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputArray.h @@ -33,9 +33,6 @@ namespace Multiplayer NetworkInput& operator[](uint32_t index); const NetworkInput& operator[](uint32_t index) const; - void SetPreviousInputId(ClientInputId previousInputId); - ClientInputId GetPreviousInputId() const; - bool Serialize(AzNetworking::ISerializer& serializer); private: @@ -49,6 +46,5 @@ namespace Multiplayer ConstNetworkEntityHandle m_owner; AZStd::array m_inputs; - ClientInputId m_previousInputId; }; } From e0ea9e6224e02dab83dc57914242533f12528ec3 Mon Sep 17 00:00:00 2001 From: karlberg Date: Sat, 15 May 2021 15:29:22 -0700 Subject: [PATCH 5/5] Removing debug code --- Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index ba87849047..2589f52d87 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#pragma optimize ("", off) + #include #include #include