diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja index 090bd4f0e0..1490d91f19 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja @@ -12,15 +12,8 @@ namespace AZ {% set Namespace = dataFiles[0].attrib['Namespace'] %} namespace {{ Namespace }} { - enum class ComponentTypes - { -{% for Component in dataFiles %} -{% set ComponentName = Component.attrib['Name'] %} - {{ ComponentName }}, -{% endfor %} - Count - }; - static_assert(ComponentTypes::Count < static_cast(Multiplayer::InvalidNetComponentId), "ComponentId overflow"); + //! Registers all multiplayer components contained within this gem with the MultiplayerComponentRegistry. + void RegisterMultiplayerComponents(); //! For reflecting multiplayer components into the serialize, edit, and behaviour contexts. void CreateComponentDescriptors(AZStd::list& descriptors); diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja index 40f20dd04b..1726aa17e8 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja @@ -1,4 +1,6 @@ #include +#include +#include {% for Component in dataFiles %} {% set ComponentDerived = Component.attrib['OverrideComponent']|booleanTrue %} {% set ControllerDerived = Component.attrib['OverrideController']|booleanTrue %} @@ -10,8 +12,33 @@ {% endfor %} {% set Namespace = dataFiles[0].attrib['Namespace'] %} +{% for Component in dataFiles %} +{% if Component.attrib['Namespace'] != Namespace %} +#error "mismatched component namespaces detected in declared multiplayer components, expected {{ Namespace }} but found {{ Component.attrib['Namespace'] }}" +{% endif %} +{% endfor %} namespace {{ Namespace }} { + void RegisterMultiplayerComponents() + { + Multiplayer::MultiplayerComponentRegistry* multiplayerComponentRegistry = GetMultiplayerComponentRegistry(); +{% for Component in dataFiles %} +{% set ComponentName = Component.attrib['Name'] %} +{% set ComponentBaseName = ComponentName %} +{% if Component.attrib['OverrideComponent']|booleanTrue %} +{% set ComponentBaseName = ComponentName + "Base" %} +{% endif %} + { + Multiplayer::MultiplayerComponentRegistry::ComponentData componentData; + componentData.m_gemName = AZ::Name("{{ Namespace }}"); + componentData.m_componentName = AZ::Name("{{ Component.attrib['Name'] }}"); + componentData.m_componentPropertyNameLookupFunction = {{ ComponentBaseName }}::GetNetworkPropertyName; + componentData.m_componentRpcNameLookupFunction = {{ ComponentBaseName }}::GetRpcName; + {{ ComponentBaseName }}::s_netComponentId = multiplayerComponentRegistry->RegisterMultiplayerComponent(componentData); + } +{% endfor %} + } + void CreateComponentDescriptors(AZStd::list& descriptors) { descriptors.insert(descriptors.end(), { diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index f5774b07c0..a91792bae6 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -329,7 +329,6 @@ namespace {{ Component.attrib['Namespace'] }} : public Multiplayer::IMultiplayerComponentInput { public: - static const Multiplayer::NetComponentId s_componentId = static_cast({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }}); Multiplayer::NetComponentId GetComponentId() const override; INetworkInput& operator=(const INetworkInput& rhs) override; bool Serialize(AzNetworking::ISerializer& serializer); @@ -412,8 +411,6 @@ namespace {{ Component.attrib['Namespace'] }} AZ_MULTIPLAYER_COMPONENT({{ Component.attrib['Namespace'] }}::{{ ComponentBaseName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, Multiplayer::MultiplayerComponent); {% endif %} - static const Multiplayer::NetComponentId s_componentId = static_cast({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }}); - static void Reflect(AZ::ReflectContext* context); static void ReflectToEditContext(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); @@ -489,6 +486,10 @@ namespace {{ Component.attrib['Namespace'] }} bool SerializeAutonomousToAuthorityProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer); void NotifyChangesAutonomousToAuthorityProperties(const {{ RecordName }}& replicationRecord) const; + //! Debug name helpers + static const char* GetNetworkPropertyName(uint16_t propertyIndex); + static const char* GetRpcName(uint16_t rpcIndex); + AZStd::unique_ptr<{{ RecordName }}> m_currentRecord; AZStd::unique_ptr<{{ ControllerName }}> m_controller; @@ -518,6 +519,9 @@ namespace {{ Component.attrib['Namespace'] }} {% call(Type, Name) AutoComponentMacros.ParseComponentServiceTypeAndName(Component) %} {{ Type }}* {{ Name }} = nullptr; {% endcall %} + + static NetComponentId s_netComponentId; + friend void RegisterMultiplayerComponents(); }; } {% endfor %} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index d6907876e1..0b1df34ed7 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -285,15 +285,15 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop {{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }} void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }}) { - constexpr uint8_t rpcId = static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }}); - constexpr Multiplayer::NetComponentId componentId = static_cast({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }}); + constexpr uint16_t rpcId = static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }}); {% if Property.attrib['IsReliable']|booleanTrue %} constexpr AzNetworking::ReliabilityType isReliable = Multiplayer::ReliabilityType::Reliable; {% else %} constexpr AzNetworking::ReliabilityType isReliable = Multiplayer::ReliabilityType::Unreliable; {% endif %} - Multiplayer::NetworkEntityRpcMessage rpcMessage(Multiplayer::RpcDeliveryType::{{ InvokeFrom }}To{{ HandleOn }}, GetNetEntityId(), componentId, rpcId, isReliable); + const Multiplayer::NetComponentId netComponentId = GetParent().GetNetComponentId(); + Multiplayer::NetworkEntityRpcMessage rpcMessage(Multiplayer::RpcDeliveryType::{{ InvokeFrom }}To{{ HandleOn }}, GetNetEntityId(), netComponentId, rpcId, isReliable); {% if paramNames|count > 0 %} {{ UpperFirst(Component.attrib['Name']) }}Internal::{{ UpperFirst(Property.attrib['Name']) }}RpcStruct rpcStruct({{ ', '.join(paramNames) }}); {% else %} @@ -901,6 +901,8 @@ m_{{ LowerFirst(Property.attrib['Name']) }} = m_{{ LowerFirst(Property.attrib['N namespace {{ Component.attrib['Namespace'] }} { + NetComponentId {{ UpperFirst(Component.attrib['Name']) }}::s_netComponentId = InvalidNetComponentId; + namespace {{ UpperFirst(Component.attrib['Name']) }}Internal { {{ DeclareRemoteProcedureEnumerations(Component)|indent(8) }} @@ -1229,7 +1231,7 @@ namespace {{ Component.attrib['Namespace'] }} Multiplayer::NetComponentId {{ ComponentBaseName }}::GetNetComponentId() const { - return s_componentId; + return s_netComponentId; } #pragma warning(push) @@ -1379,6 +1381,15 @@ namespace {{ Component.attrib['Namespace'] }} } {% endif %} + const char* {{ ComponentBaseName }}::GetNetworkPropertyName([[maybe_unused]] uint16_t propertyIndex) + { + return ""; + } + + const char* {{ ComponentBaseName }}::GetRpcName([[maybe_unused]] uint16_t rpcIndex) + { + return ""; + } {% endfor %} } {% endfor %} diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp new file mode 100644 index 0000000000..6d2d1bcf85 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.cpp @@ -0,0 +1,58 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +namespace Multiplayer +{ + NetComponentId MultiplayerComponentRegistry::RegisterMultiplayerComponent(const ComponentData& componentData) + { + NetComponentId netComponentId = m_nextNetComponentId++; + m_componentData[netComponentId] = componentData; + return netComponentId; + } + + const char* MultiplayerComponentRegistry::GetComponentGemName(NetComponentId netComponentId) const + { + const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); + return componentData.m_gemName.GetCStr(); + } + + const char* MultiplayerComponentRegistry::GetComponentName(NetComponentId netComponentId) const + { + const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); + return componentData.m_componentName.GetCStr(); + } + + const char* MultiplayerComponentRegistry::GetComponentPropertyName(NetComponentId netComponentId, uint16_t propertyIndex) const + { + const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); + return componentData.m_componentPropertyNameLookupFunction(propertyIndex); + } + + const char* MultiplayerComponentRegistry::GetComponentRpcName(NetComponentId netComponentId, uint16_t rpcId) const + { + const ComponentData& componentData = GetMultiplayerComponentData(netComponentId); + return componentData.m_componentRpcNameLookupFunction(rpcId); + } + + const MultiplayerComponentRegistry::ComponentData& MultiplayerComponentRegistry::GetMultiplayerComponentData(NetComponentId netComponentId) const + { + static ComponentData nullComponentData; + auto it = m_componentData.find(netComponentId); + if (it != m_componentData.end()) + { + return it->second; + } + return nullComponentData; + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.h b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.h new file mode 100644 index 0000000000..550301b2d8 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponentRegistry.h @@ -0,0 +1,69 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include + +namespace Multiplayer +{ + class MultiplayerComponentRegistry + { + public: + using NameLookupFunction = AZStd::function; + struct ComponentData + { + AZ::Name m_gemName; + AZ::Name m_componentName; + NameLookupFunction m_componentPropertyNameLookupFunction; + NameLookupFunction m_componentRpcNameLookupFunction; + }; + + //! Registers a multiplayer component with the multiplayer system. + //! @param componentData the data associated with the component being registered + //! @return the NetComponentId assigned to this particular component + NetComponentId RegisterMultiplayerComponent(const ComponentData& componentData); + + //! 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 + const char* GetComponentGemName(NetComponentId netComponentId) const; + + //! Returns the component name associated with the provided NetComponentId. + //! @param netComponentId the NetComponentId to return the component name of + //! @return the name of the component + const char* GetComponentName(NetComponentId netComponentId) const; + + //! Returns the property name associated with the provided NetComponentId and propertyIndex. + //! @param netComponentId the NetComponentId to return the property name of + //! @param propertyIndex the index off the network property to return the property name of + //! @return the name of the network property + const char* GetComponentPropertyName(NetComponentId netComponentId, uint16_t propertyIndex) const; + + //! Returns the Rpc name associated with the provided NetComponentId and rpcId. + //! @param netComponentId the NetComponentId to return the property name of + //! @param rpcId the index off the rpc to return the rpc name of + //! @return the name of the requested rpc + const char* GetComponentRpcName(NetComponentId netComponentId, uint16_t rpcId) const; + + //! Retrieves the stored component data for a given NetComponentId. + //! @param netComponentId the NetComponentId to return component data for + //! @return reference to the requested component data, an empty container will be returned if the NetComponentId does not exist + const ComponentData& GetMultiplayerComponentData(NetComponentId netComponentId) const; + + private: + NetComponentId m_nextNetComponentId = NetComponentId{ 0 }; + AZStd::unordered_map m_componentData; + }; +} diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index e40e9e9d66..b933e71a97 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -114,6 +114,9 @@ namespace Multiplayer m_networkInterface = AZ::Interface::Get()->CreateNetworkInterface(AZ::Name(s_networkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this); m_consoleCommandHandler.Connect(AZ::Interface::Get()->GetConsoleCommandInvokedEvent()); AZ::Interface::Register(this); + + //! Register our gems multiplayer components to assign NetComponentIds + RegisterMultiplayerComponents(); } void MultiplayerSystemComponent::Deactivate() diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 5a223d6214..4c57924eb4 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -49,7 +49,7 @@ namespace Multiplayer : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { - MultiplayerToolsSystemComponent::CreateDescriptor(), + MultiplayerToolsSystemComponent::CreateDescriptor(), }); } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h index 557a912a31..82b13841c8 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h @@ -23,6 +23,7 @@ namespace Multiplayer class NetworkEntityTracker; class NetworkEntityAuthorityTracker; class NetworkEntityRpcMessage; + class MultiplayerComponentRegistry; using EntityExitDomainEvent = AZ::Event; using ControllersActivatedEvent = AZ::Event; @@ -48,6 +49,10 @@ namespace Multiplayer //! @return the NetworkEntityAuthorityTracker for this INetworkEntityManager instance virtual NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() = 0; + //! Returns the MultiplayerComponentRegistry for this INetworkEntityManager instance. + //! @return the MultiplayerComponentRegistry for this INetworkEntityManager instance + virtual MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() = 0; + //! Returns the HostId for this INetworkEntityManager instance. //! @return the HostId for this INetworkEntityManager instance virtual HostId GetHostId() const = 0; @@ -144,4 +149,9 @@ namespace Multiplayer { return GetNetworkEntityManager()->GetNetworkEntityAuthorityTracker(); } + + inline MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() + { + return GetNetworkEntityManager()->GetMultiplayerComponentRegistry(); + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 43302efdaa..ca1b40ca9b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -62,6 +62,11 @@ namespace Multiplayer return &m_networkEntityAuthorityTracker; } + MultiplayerComponentRegistry* NetworkEntityManager::GetMultiplayerComponentRegistry() + { + return &m_multiplayerComponentRegistry; + } + HostId NetworkEntityManager::GetHostId() const { return m_hostId; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 148645c638..46f59f3762 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -21,7 +21,7 @@ #include #include #include - +#include namespace Multiplayer { @@ -42,6 +42,7 @@ namespace Multiplayer //! @{ NetworkEntityTracker* GetNetworkEntityTracker() override; NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override; + MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() override; HostId GetHostId() const override; ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override; @@ -85,6 +86,8 @@ namespace Multiplayer NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; + MultiplayerComponentRegistry m_multiplayerComponentRegistry; + AZ::ScheduledEvent m_removeEntitiesEvent; AZStd::vector m_removeList; AZStd::unique_ptr m_entityDomain; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp index cde8367bc6..e4cffc14fa 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.cpp @@ -42,7 +42,7 @@ namespace Multiplayer } } - NetworkEntityRpcMessage::NetworkEntityRpcMessage(RpcDeliveryType rpcDeliveryType, NetEntityId entityId, NetComponentId componentId, uint8_t rpcMessageType, ReliabilityType isReliable) + NetworkEntityRpcMessage::NetworkEntityRpcMessage(RpcDeliveryType rpcDeliveryType, NetEntityId entityId, NetComponentId componentId, uint16_t rpcMessageType, ReliabilityType isReliable) : m_rpcDeliveryType(rpcDeliveryType) , m_entityId(entityId) , m_componentId(componentId) @@ -98,7 +98,7 @@ namespace Multiplayer static constexpr uint32_t sizeOfFields = sizeof(RpcDeliveryType) + sizeof(NetEntityId) + sizeof(NetComponentId) - + sizeof(uint8_t); + + sizeof(uint16_t); // 2-byte size header + the actual blob payload itself const uint32_t sizeOfBlob = (m_data != nullptr) ? sizeof(uint16_t) + m_data->GetSize() : 0; @@ -127,7 +127,7 @@ namespace Multiplayer return m_componentId; } - uint8_t NetworkEntityRpcMessage::GetRpcMessageType() const + uint16_t NetworkEntityRpcMessage::GetRpcMessageType() const { return m_rpcMessageType; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.h index 503a5900bd..87a4a5d6af 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityRpcMessage.h @@ -40,7 +40,7 @@ namespace Multiplayer //! @param componentType the networked componentId of the component handling this RPC //! @param rpcMessageType the component defined RPC type, so the component knows which RPC this message corresponds to //! @param isReliable whether or not this RPC should be sent reliably - explicit NetworkEntityRpcMessage(RpcDeliveryType rpcDeliveryType, NetEntityId entityId, NetComponentId componentId, uint8_t rpcMessageType, ReliabilityType isReliable); + explicit NetworkEntityRpcMessage(RpcDeliveryType rpcDeliveryType, NetEntityId entityId, NetComponentId componentId, uint16_t rpcMessageType, ReliabilityType isReliable); NetworkEntityRpcMessage& operator =(NetworkEntityRpcMessage&& rhs); NetworkEntityRpcMessage& operator =(const NetworkEntityRpcMessage& rhs); @@ -69,7 +69,7 @@ namespace Multiplayer //! Gets the current value of RpcMessageType. //! @return the current value of RpcMessageType - uint8_t GetRpcMessageType() const; + uint16_t GetRpcMessageType() const; //! Writes the data contained inside a_Params to this NetworkEntityRpcMessage's blob buffer. //! @param params the parameters to save inside this NetworkEntityRpcMessage instance @@ -98,7 +98,7 @@ namespace Multiplayer RpcDeliveryType m_rpcDeliveryType = RpcDeliveryType::None; NetEntityId m_entityId = InvalidNetEntityId; NetComponentId m_componentId = InvalidNetComponentId; - uint8_t m_rpcMessageType = 0; + uint16_t m_rpcMessageType = 0; // Only allocated if we actually have data // This is to prevent blowing out stack memory if we declare an array of these EntityUpdateMessages diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp index ebf5d2609b..ad2e18e222 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -46,6 +46,7 @@ namespace Multiplayer const AZ::Name name = AZ::Name(relativePath); m_spawnables[name] = id; m_spawnablesReverseLookup[id] = name; + } void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 110de8445f..c1f8fb3111 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -26,6 +26,8 @@ set(FILES Source/AutoGen/NetworkTransformComponent.AutoComponent.xml Source/Components/LocalPredictionPlayerInputComponent.cpp Source/Components/LocalPredictionPlayerInputComponent.h + Source/Components/MultiplayerComponentRegistry.cpp + Source/Components/MultiplayerComponentRegistry.h Source/Components/MultiplayerComponent.cpp Source/Components/MultiplayerComponent.h Source/Components/MultiplayerController.cpp