Merge pull request #173 from aws-lumberyard-dev/MultiplayerPipeline
Merging current state of multiplayer pipeline to main
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
#include <AzCore/std/typetraits/is_enum.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
@@ -173,6 +175,22 @@ namespace AzNetworking
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SerializeObjectHelper<AZ::Name>
|
||||
{
|
||||
static bool SerializeObject(ISerializer& serializer, AZ::Name& value)
|
||||
{
|
||||
AZ::Name::Hash nameHash = value.GetHash();
|
||||
bool result = serializer.Serialize(nameHash, "NameHash");
|
||||
|
||||
if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject)
|
||||
{
|
||||
value = AZ::NameDictionary::Instance().FindName(nameHash);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include <AzNetworking/Serialization/AzContainerSerializers.h>
|
||||
|
||||
@@ -18,16 +18,16 @@ ly_add_target(
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
${pal_source_dir}
|
||||
Source
|
||||
AZ::AzNetworking
|
||||
Source
|
||||
.
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzNetworking
|
||||
Gem::CertificateManager
|
||||
3rdParty::AWSNativeSDK::Core
|
||||
AUTOGEN_RULES
|
||||
*.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h
|
||||
*.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl
|
||||
@@ -49,6 +49,8 @@ ly_add_target(
|
||||
PRIVATE
|
||||
Source
|
||||
.
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Gem::Multiplayer.Static
|
||||
@@ -56,10 +58,27 @@ ly_add_target(
|
||||
Gem::CertificateManager
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Tests
|
||||
################################################################################
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
ly_add_target(
|
||||
NAME Multiplayer.Tools MODULE
|
||||
NAMESPACE Gem
|
||||
OUTPUT_NAME Gem.Multiplayer.Tools
|
||||
FILES_CMAKE
|
||||
multiplayer_tools_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
.
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzToolsFramework
|
||||
Gem::Multiplayer.Static
|
||||
)
|
||||
endif()
|
||||
|
||||
if (PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_add_target(
|
||||
NAME Multiplayer.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE Gem
|
||||
@@ -71,6 +90,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
${pal_source_dir}
|
||||
Source
|
||||
.
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzTest
|
||||
@@ -80,3 +101,25 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
NAME Gem::Multiplayer.Tests
|
||||
)
|
||||
endif()
|
||||
|
||||
ly_add_target(
|
||||
NAME Multiplayer.Debug ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
|
||||
NAMESPACE Gem
|
||||
FILES_CMAKE
|
||||
multiplayer_debug_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
.
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzCore
|
||||
AZ::AtomCore
|
||||
AZ::AzFramework
|
||||
AZ::AzNetworking
|
||||
Gem::Atom_Feature_Common.Static
|
||||
Gem::Multiplayer.Static
|
||||
Gem::ImGui.Static
|
||||
)
|
||||
|
||||
@@ -1168,6 +1168,12 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
|
||||
void {{ ComponentBaseName }}::Init()
|
||||
{
|
||||
if (m_netBindComponent == nullptr)
|
||||
{
|
||||
AZLOG_ERROR("NetBindComponent is null, ensure NetworkAttach is called prior to activating a networked entity");
|
||||
return;
|
||||
}
|
||||
|
||||
{{ DefineComponentServiceProxyGrabs(Component, ClassType, ComponentName)|indent(8) }}
|
||||
{% if ComponentDerived %}
|
||||
OnInit();
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Source/Multiplayer_precompiled.h>
|
||||
#include <Source/Debug/MultiplayerDebugModule.h>
|
||||
#include <Source/Debug/MultiplayerDebugSystemComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
MultiplayerDebugModule::MultiplayerDebugModule()
|
||||
: AZ::Module()
|
||||
{
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
MultiplayerDebugSystemComponent::CreateDescriptor(),
|
||||
});
|
||||
}
|
||||
|
||||
AZ::ComponentTypeList MultiplayerDebugModule::GetRequiredSystemComponents() const
|
||||
{
|
||||
return AZ::ComponentTypeList
|
||||
{
|
||||
azrtti_typeid<MultiplayerDebugSystemComponent>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerDebugModule);
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Module/Module.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class MultiplayerDebugModule
|
||||
: public AZ::Module
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(MultiplayerDebugModule, "{9E1460FA-4513-4B5E-86B4-9DD8ADEFA714}", AZ::Module);
|
||||
AZ_CLASS_ALLOCATOR(MultiplayerDebugModule, AZ::SystemAllocator, 0);
|
||||
|
||||
MultiplayerDebugModule();
|
||||
~MultiplayerDebugModule() override = default;
|
||||
|
||||
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 <Source/Debug/MultiplayerDebugSystemComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <Include/IMultiplayer.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<MultiplayerDebugSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent"));
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile)
|
||||
{
|
||||
incompatbile.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent"));
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::Activate()
|
||||
{
|
||||
#ifdef IMGUI_ENABLED
|
||||
ImGui::ImGuiUpdateListenerBus::Handler::BusConnect();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::Deactivate()
|
||||
{
|
||||
#ifdef IMGUI_ENABLED
|
||||
ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IMGUI_ENABLED
|
||||
void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate()
|
||||
{
|
||||
if (ImGui::BeginMenu("Multiplayer"))
|
||||
{
|
||||
//{
|
||||
// static int lossPercent{ 0 };
|
||||
// lossPercent = static_cast<int>(net_UdpDebugLossPercent);
|
||||
// if (ImGui::SliderInt("UDP Loss Percent", &lossPercent, 0, 100))
|
||||
// {
|
||||
// net_UdpDebugLossPercent = lossPercent;
|
||||
// m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLossPercent);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//{
|
||||
// static int latency{ 0 };
|
||||
// latency = static_cast<int>(net_UdpDebugLatencyMs);
|
||||
// if (ImGui::SliderInt("UDP Latency Ms", &latency, 0, 3000))
|
||||
// {
|
||||
// net_UdpDebugLatencyMs = latency;
|
||||
// m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLatencyMs);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//{
|
||||
// static int variance{ 0 };
|
||||
// variance = static_cast<int>(net_UdpDebugVarianceMs);
|
||||
// if (ImGui::SliderInt("UDP Variance Ms", &variance, 0, 1000))
|
||||
// {
|
||||
// net_UdpDebugVarianceMs = variance;
|
||||
// m_ClientAgent.UpdateConnectionCvars(net_UdpDebugVarianceMs);
|
||||
// }
|
||||
//}
|
||||
|
||||
ImGui::Checkbox("Multiplayer Stats", &m_displayStats);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::OnImGuiUpdate()
|
||||
{
|
||||
if (m_displayStats)
|
||||
{
|
||||
if (ImGui::Begin("Multiplayer Stats", &m_displayStats, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
IMultiplayer* multiplayer = AZ::Interface<IMultiplayer>::Get();
|
||||
Multiplayer::MultiplayerStats& stats = multiplayer->GetStats();
|
||||
ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType()));
|
||||
ImGui::Text("Total networked entities: %llu", aznumeric_cast<AZ::u64>(stats.m_entityCount));
|
||||
ImGui::Text("Total client connections: %llu", aznumeric_cast<AZ::u64>(stats.m_clientConnectionCount));
|
||||
ImGui::Text("Total server connections: %llu", aznumeric_cast<AZ::u64>(stats.m_serverConnectionCount));
|
||||
ImGui::Text("Total property updates sent: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSent));
|
||||
ImGui::Text("Total property updates sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSentBytes));
|
||||
ImGui::Text("Total property updates received: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecv));
|
||||
ImGui::Text("Total property updates received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecvBytes));
|
||||
ImGui::Text("Total RPCs sent: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSent));
|
||||
ImGui::Text("Total RPCs sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSentBytes));
|
||||
ImGui::Text("Total RPCs received: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecv));
|
||||
ImGui::Text("Total RPCs received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecvBytes));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* All or portions of this file Copyright(c) Amazon.com, Inc.or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution(the "License").All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file.Do not
|
||||
* remove or modify any license notices.This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
#ifdef IMGUI_ENABLED
|
||||
# include <imgui/imgui.h>
|
||||
# include <ImGuiBus.h>
|
||||
#endif
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class MultiplayerDebugSystemComponent final
|
||||
: public AZ::Component
|
||||
#ifdef IMGUI_ENABLED
|
||||
, public ImGui::ImGuiUpdateListenerBus::Handler
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MultiplayerDebugSystemComponent, "{060BF3F1-0BFE-4FCE-9C3C-EE991F0DA581}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile);
|
||||
|
||||
~MultiplayerDebugSystemComponent() override = default;
|
||||
|
||||
//! AZ::Component overrides
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
#ifdef IMGUI_ENABLED
|
||||
//! ImGui::ImGuiUpdateListenerBus overrides
|
||||
//! @{
|
||||
void OnImGuiMainMenuUpdate() override;
|
||||
void OnImGuiUpdate() override;
|
||||
//! @}
|
||||
#endif
|
||||
private:
|
||||
bool m_displayStats = false;
|
||||
};
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <Source/MultiplayerSystemComponent.h>
|
||||
#include <Source/Components/NetBindComponent.h>
|
||||
#include <Source/AutoGen/AutoComponentTypes.h>
|
||||
#include <Source/Pipeline/NetBindMarkerComponent.h>
|
||||
#include <Source/Pipeline/NetworkSpawnableHolderComponent.h>
|
||||
#include <AzNetworking/Framework/NetworkingSystemComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
@@ -26,6 +28,8 @@ namespace Multiplayer
|
||||
AzNetworking::NetworkingSystemComponent::CreateDescriptor(),
|
||||
MultiplayerSystemComponent::CreateDescriptor(),
|
||||
NetBindComponent::CreateDescriptor(),
|
||||
NetBindMarkerComponent::CreateDescriptor(),
|
||||
NetworkSpawnableHolderComponent::CreateDescriptor(),
|
||||
});
|
||||
|
||||
CreateComponentDescriptors(m_descriptors);
|
||||
|
||||
@@ -133,23 +133,33 @@ namespace Multiplayer
|
||||
// Let the network system know the frame is done and we can collect dirty bits
|
||||
m_networkEntityManager.NotifyEntitiesDirtied();
|
||||
|
||||
MultiplayerStats& stats = GetStats();
|
||||
stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount();
|
||||
stats.m_serverConnectionCount = 0;
|
||||
stats.m_clientConnectionCount = 0;
|
||||
|
||||
// Send out the game state update to all connections
|
||||
{
|
||||
auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection)
|
||||
auto sendNetworkUpdates = [serverGameTimeMs, &stats](IConnection& connection)
|
||||
{
|
||||
if (connection.GetUserData() != nullptr)
|
||||
{
|
||||
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
|
||||
connectionData->Update(serverGameTimeMs);
|
||||
if (connectionData->GetConnectionDataType() == ConnectionDataType::ServerToClient)
|
||||
{
|
||||
stats.m_clientConnectionCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.m_serverConnectionCount++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates);
|
||||
}
|
||||
|
||||
MultiplayerStats& stats = GetStats();
|
||||
stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount();
|
||||
|
||||
MultiplayerPackets::SyncConsole packet;
|
||||
AZ::ThreadSafeDeque<AZStd::string>::DequeType cvarUpdates;
|
||||
m_cvarCommands.Swap(cvarUpdates);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <Source/Multiplayer_precompiled.h>
|
||||
#include <Source/MultiplayerToolsModule.h>
|
||||
#include <Pipeline/NetworkPrefabProcessor.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <Prefab/Instance/InstanceSerializer.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! Multiplayer Tools system component provides serialize context reflection for tools-only systems.
|
||||
class MultiplayerToolsSystemComponent final
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MultiplayerToolsSystemComponent, "{65AF5342-0ECE-423B-B646-AF55A122F72B}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
NetworkPrefabProcessor::Reflect(context);
|
||||
}
|
||||
|
||||
MultiplayerToolsSystemComponent() = default;
|
||||
~MultiplayerToolsSystemComponent() override = default;
|
||||
|
||||
/// AZ::Component overrides.
|
||||
void Activate() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Deactivate() override
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
MultiplayerToolsModule::MultiplayerToolsModule()
|
||||
: AZ::Module()
|
||||
{
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
MultiplayerToolsSystemComponent::CreateDescriptor(),
|
||||
});
|
||||
}
|
||||
|
||||
AZ::ComponentTypeList MultiplayerToolsModule::GetRequiredSystemComponents() const
|
||||
{
|
||||
return AZ::ComponentTypeList
|
||||
{
|
||||
azrtti_typeid<MultiplayerToolsSystemComponent>(),
|
||||
};
|
||||
}
|
||||
} // namespace Multiplayer
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Tools, Multiplayer::MultiplayerToolsModule);
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Module/Module.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class MultiplayerToolsModule
|
||||
: public AZ::Module
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_RTTI(MultiplayerToolsModule, "{3F726172-21FC-48FA-8CFA-7D87EBA07E55}", AZ::Module);
|
||||
AZ_CLASS_ALLOCATOR(MultiplayerToolsModule, AZ::SystemAllocator, 0);
|
||||
|
||||
MultiplayerToolsModule();
|
||||
~MultiplayerToolsModule() override = default;
|
||||
|
||||
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
|
||||
};
|
||||
} // namespace Multiplayer
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
@@ -74,9 +75,36 @@ namespace Multiplayer
|
||||
struct PrefabEntityId
|
||||
{
|
||||
AZ_TYPE_INFO(PrefabEntityId, "{EFD37465-CCAC-4E87-A825-41B4010A2C75}");
|
||||
bool operator==(const PrefabEntityId&) const { return true; }
|
||||
bool operator!=(const PrefabEntityId& rhs) const { return !(*this == rhs); }
|
||||
bool Serialize(AzNetworking::ISerializer&) { return true; }
|
||||
|
||||
static constexpr uint32_t AllIndices = AZStd::numeric_limits<uint32_t>::max();
|
||||
|
||||
AZ::Name m_prefabName;
|
||||
uint32_t m_entityOffset = AllIndices;
|
||||
|
||||
PrefabEntityId() = default;
|
||||
|
||||
explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices)
|
||||
: m_prefabName(name)
|
||||
, m_entityOffset(entityOffset)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const PrefabEntityId& rhs) const
|
||||
{
|
||||
return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset;
|
||||
}
|
||||
|
||||
bool operator!=(const PrefabEntityId& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
serializer.Serialize(m_prefabName, "prefabName");
|
||||
serializer.Serialize(m_entityOffset, "entityOffset");
|
||||
return serializer.IsValid();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+12
-2
@@ -18,6 +18,7 @@
|
||||
#include <Source/EntityDomains/IEntityDomain.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityUpdateMessage.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityRpcMessage.h>
|
||||
#include <Source/NetworkEntity/INetworkEntityManager.h>
|
||||
#include <Source/Components/NetBindComponent.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
@@ -530,7 +531,7 @@ namespace Multiplayer
|
||||
NetEntityId netEntityId,
|
||||
NetEntityRole localNetworkRole,
|
||||
AzNetworking::ISerializer& serializer,
|
||||
[[maybe_unused]] const PrefabEntityId& prefabEntityId
|
||||
const PrefabEntityId& prefabEntityId
|
||||
)
|
||||
{
|
||||
ConstNetworkEntityHandle replicatorEntity = GetNetworkEntityManager()->GetEntity(netEntityId);
|
||||
@@ -543,7 +544,16 @@ namespace Multiplayer
|
||||
{
|
||||
// @pereslav
|
||||
//replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity());
|
||||
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString());
|
||||
INetworkEntityManager::EntityList entityList = GetNetworkEntityManager()->CreateEntitiesImmediate(
|
||||
prefabEntityId, netEntityId, localNetworkRole,
|
||||
AZ::Transform::Identity());
|
||||
|
||||
if (entityList.size() == 1)
|
||||
{
|
||||
replicatorEntity = entityList[0];
|
||||
}
|
||||
|
||||
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr());
|
||||
if (replicatorEntity == nullptr)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <Source/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -35,6 +36,7 @@ namespace Multiplayer
|
||||
AZ_RTTI(INetworkEntityManager, "{109759DE-9492-439C-A0B1-AE46E6FD029C}");
|
||||
|
||||
using OwnedEntitySet = AZStd::unordered_set<ConstNetworkEntityHandle>;
|
||||
using EntityList = AZStd::vector<NetworkEntityHandle>;
|
||||
|
||||
virtual ~INetworkEntityManager() = default;
|
||||
|
||||
@@ -50,7 +52,10 @@ namespace Multiplayer
|
||||
//! @return the HostId for this INetworkEntityManager instance
|
||||
virtual HostId GetHostId() const = 0;
|
||||
|
||||
// TODO: Spawn methods for entities within slices/prefabs/levels
|
||||
//! Creates new entities of the given archetype
|
||||
//! @param prefabEntryId the name of the spawnable to spawn
|
||||
virtual EntityList CreateEntitiesImmediate(
|
||||
const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, const AZ::Transform& transform) = 0;
|
||||
|
||||
//! Returns an ConstEntityPtr for the provided entityId.
|
||||
//! @param netEntityId the netEntityId to get an ConstEntityPtr for
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <Include/IMultiplayer.h>
|
||||
#include <Pipeline/NetworkSpawnableHolderComponent.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -31,20 +34,14 @@ namespace Multiplayer
|
||||
: m_networkEntityAuthorityTracker(*this)
|
||||
, m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event"))
|
||||
, m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event"))
|
||||
, m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); })
|
||||
, m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); })
|
||||
{
|
||||
AZ::Interface<INetworkEntityManager>::Register(this);
|
||||
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
|
||||
{
|
||||
// Null guard needed for unit tests
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
|
||||
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
|
||||
}
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
NetworkEntityManager::~NetworkEntityManager()
|
||||
{
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusDisconnect();
|
||||
AZ::Interface<INetworkEntityManager>::Unregister(this);
|
||||
}
|
||||
|
||||
@@ -147,7 +144,6 @@ namespace Multiplayer
|
||||
//{
|
||||
// rootSlice->RemoveEntity(entity);
|
||||
//}
|
||||
m_nonNetworkedEntities.clear();
|
||||
m_networkEntityTracker.clear();
|
||||
}
|
||||
|
||||
@@ -277,30 +273,6 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnEntityAdded(AZ::Entity* entity)
|
||||
{
|
||||
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent != nullptr)
|
||||
{
|
||||
// @pereslav
|
||||
// Note that this is a total hack.. we should not be listening to this event on a client
|
||||
// Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage()
|
||||
const bool isClient = AZ::Interface<IMultiplayer>::Get()->GetAgentType() == MultiplayerAgentType::Client;
|
||||
const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority;
|
||||
const NetEntityId netEntityId = m_nextEntityId++;
|
||||
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnEntityRemoved(AZ::Entity* entity)
|
||||
{
|
||||
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent != nullptr)
|
||||
{
|
||||
MarkForRemoval(netBindComponent->GetEntityHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::RemoveEntities()
|
||||
{
|
||||
//RewindableObjectState::ClearRewoundEntities();
|
||||
@@ -339,4 +311,165 @@ namespace Multiplayer
|
||||
m_networkEntityTracker.erase(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(
|
||||
const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole)
|
||||
{
|
||||
INetworkEntityManager::EntityList returnList;
|
||||
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
|
||||
const AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities();
|
||||
size_t entitiesSize = entities.size();
|
||||
|
||||
for (size_t i = 0; i < entitiesSize; ++i)
|
||||
{
|
||||
AZ::Entity* clone = serializeContext->CloneObject(entities[i].get());
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
clone->SetId(AZ::Entity::MakeId());
|
||||
|
||||
NetBindComponent* netBindComponent = clone->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent != nullptr)
|
||||
{
|
||||
PrefabEntityId prefabEntityId;
|
||||
prefabEntityId.m_prefabName = m_networkPrefabLibrary.GetPrefabNameFromAssetId(spawnable.GetId());
|
||||
prefabEntityId.m_entityOffset = aznumeric_cast<uint32_t>(i);
|
||||
|
||||
const NetEntityId netEntityId = NextId();
|
||||
netBindComponent->PreInit(clone, prefabEntityId, netEntityId, netEntityRole);
|
||||
|
||||
AzFramework::GameEntityContextRequestBus::Broadcast(
|
||||
&AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone);
|
||||
|
||||
returnList.push_back(netBindComponent->GetEntityHandle());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
delete clone;
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(
|
||||
const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole,
|
||||
const AZ::Transform& transform)
|
||||
{
|
||||
INetworkEntityManager::EntityList returnList;
|
||||
|
||||
// TODO: Implement for non-root spawnables
|
||||
auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName);
|
||||
if (spawnableAssetId == m_rootSpawnableAsset.GetId())
|
||||
{
|
||||
AzFramework::Spawnable* netSpawnable = m_rootSpawnableAsset.GetAs<AzFramework::Spawnable>();
|
||||
if (!netSpawnable)
|
||||
{
|
||||
return returnList;
|
||||
}
|
||||
|
||||
const uint32_t entityIndex = prefabEntryId.m_entityOffset;
|
||||
|
||||
if (entityIndex == PrefabEntityId::AllIndices)
|
||||
{
|
||||
return CreateEntitiesImmediate(*netSpawnable, netEntityRole);
|
||||
}
|
||||
|
||||
const AzFramework::Spawnable::EntityList& entities = netSpawnable->GetEntities();
|
||||
size_t entitiesSize = entities.size();
|
||||
if (entityIndex >= entitiesSize)
|
||||
{
|
||||
return returnList;
|
||||
}
|
||||
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
|
||||
AZ::Entity* clone = serializeContext->CloneObject(entities[entityIndex].get());
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
clone->SetId(AZ::Entity::MakeId());
|
||||
|
||||
NetBindComponent* netBindComponent = clone->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent)
|
||||
{
|
||||
netBindComponent->PreInit(clone, prefabEntryId, netEntityId, netEntityRole);
|
||||
|
||||
auto* transformComponent = clone->FindComponent<AzFramework::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldTM(transform);
|
||||
}
|
||||
|
||||
AzFramework::GameEntityContextRequestBus::Broadcast(
|
||||
&AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone);
|
||||
|
||||
returnList.push_back(netBindComponent->GetEntityHandle());
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
Multiplayer::NetEntityId NetworkEntityManager::NextId()
|
||||
{
|
||||
const NetEntityId netEntityId = m_nextEntityId++;
|
||||
return netEntityId;
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnRootSpawnableAssigned(
|
||||
AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, [[maybe_unused]] uint32_t generation)
|
||||
{
|
||||
AzFramework::Spawnable* rootSpawnableData = rootSpawnable.GetAs<AzFramework::Spawnable>();
|
||||
const auto& entityList = rootSpawnableData->GetEntities();
|
||||
if (entityList.size() == 0)
|
||||
{
|
||||
AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable doesn't have any entities.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& rootEntity = entityList[0];
|
||||
auto* spawnableHolder = rootEntity->FindComponent<NetworkSpawnableHolderComponent>();
|
||||
if (!spawnableHolder)
|
||||
{
|
||||
AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root entity doesn't have NetworkSpawnableHolderComponent.");
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> netSpawnableAsset = spawnableHolder->GetNetworkSpawnableAsset();
|
||||
AzFramework::Spawnable* netSpawnable = netSpawnableAsset.GetAs<AzFramework::Spawnable>();
|
||||
if (!netSpawnable)
|
||||
{
|
||||
// TODO: Temp sync load until JsonSerialization of loadBehavior is fixed.
|
||||
netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset<AzFramework::Spawnable>(
|
||||
netSpawnableAsset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(netSpawnableAsset);
|
||||
|
||||
netSpawnable = netSpawnableAsset.GetAs<AzFramework::Spawnable>();
|
||||
}
|
||||
|
||||
if (!netSpawnable)
|
||||
{
|
||||
AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Net spawnable doesn't have any data.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_rootSpawnableAsset = netSpawnableAsset;
|
||||
|
||||
const auto agentType = AZ::Interface<IMultiplayer>::Get()->GetAgentType();
|
||||
const bool spawnImmediately =
|
||||
(agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer);
|
||||
|
||||
if (spawnImmediately)
|
||||
{
|
||||
CreateEntitiesImmediate(*netSpawnable, NetEntityRole::Authority);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation)
|
||||
{
|
||||
// TODO: Do we need to clear all entities here?
|
||||
m_rootSpawnableAsset.Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
|
||||
#include <AzCore/EBus/ScheduledEvent.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
|
||||
#include <Source/NetworkEntity/INetworkEntityManager.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityAuthorityTracker.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityTracker.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityRpcMessage.h>
|
||||
#include <Source/EntityDomains/IEntityDomain.h>
|
||||
#include <Source/NetworkEntity/NetworkSpawnableLibrary.h>
|
||||
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -26,6 +29,7 @@ namespace Multiplayer
|
||||
//! This class creates and manages all networked entities.
|
||||
class NetworkEntityManager final
|
||||
: public INetworkEntityManager
|
||||
, public AzFramework::RootSpawnableNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
NetworkEntityManager();
|
||||
@@ -40,6 +44,13 @@ namespace Multiplayer
|
||||
NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override;
|
||||
HostId GetHostId() const override;
|
||||
ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override;
|
||||
|
||||
EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole);
|
||||
|
||||
EntityList CreateEntitiesImmediate(
|
||||
const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole,
|
||||
const AZ::Transform& transform) override;
|
||||
|
||||
uint32_t GetEntityCount() const override;
|
||||
NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override;
|
||||
void MarkForRemoval(const ConstNetworkEntityHandle& entityHandle) override;
|
||||
@@ -61,19 +72,21 @@ namespace Multiplayer
|
||||
void DispatchLocalDeferredRpcMessages();
|
||||
void UpdateEntityDomain();
|
||||
void OnEntityExitDomain(NetEntityId entityId);
|
||||
//! RootSpawnableNotificationBus
|
||||
//! @{
|
||||
void OnRootSpawnableAssigned(AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, uint32_t generation) override;
|
||||
void OnRootSpawnableReleased(uint32_t generation) override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
||||
void OnEntityAdded(AZ::Entity* entity);
|
||||
void OnEntityRemoved(AZ::Entity* entity);
|
||||
void RemoveEntities();
|
||||
|
||||
NetEntityId NextId();
|
||||
|
||||
NetworkEntityTracker m_networkEntityTracker;
|
||||
NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker;
|
||||
AZ::ScheduledEvent m_removeEntitiesEvent;
|
||||
AZStd::vector<NetEntityId> m_removeList;
|
||||
AZStd::vector<AZ::Entity*> m_nonNetworkedEntities; // Contains entities that we've instantiated, but are not networked entities
|
||||
|
||||
AZStd::unique_ptr<IEntityDomain> m_entityDomain;
|
||||
AZ::ScheduledEvent m_updateEntityDomainEvent;
|
||||
|
||||
@@ -85,8 +98,6 @@ namespace Multiplayer
|
||||
AZ::Event<> m_onEntityNotifyChanges;
|
||||
ControllersActivatedEvent m_controllersActivatedEvent;
|
||||
ControllersDeactivatedEvent m_controllersDeactivatedEvent;
|
||||
AZ::EntityAddedEvent::Handler m_entityAddedEventHandler;
|
||||
AZ::EntityRemovedEvent::Handler m_entityRemovedEventHandler;
|
||||
|
||||
HostId m_hostId = InvalidHostId;
|
||||
NetEntityId m_nextEntityId = NetEntityId{ 0 };
|
||||
@@ -95,5 +106,8 @@ namespace Multiplayer
|
||||
// This is done to prevent local and network sent RPC's from having different dispatch behaviours
|
||||
typedef AZStd::deque<NetworkEntityRpcMessage> DeferredRpcMessages;
|
||||
DeferredRpcMessages m_localDeferredRpcMessages;
|
||||
|
||||
NetworkSpawnableLibrary m_networkPrefabLibrary;
|
||||
AZ::Data::Asset<AzFramework::Spawnable> m_rootSpawnableAsset;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 <Source/NetworkEntity/NetworkSpawnableLibrary.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
NetworkSpawnableLibrary::NetworkSpawnableLibrary()
|
||||
{
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
NetworkSpawnableLibrary::~NetworkSpawnableLibrary()
|
||||
{
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void NetworkSpawnableLibrary::BuildPrefabsList()
|
||||
{
|
||||
auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
if (info.m_assetType == AZ::AzTypeInfo<AzFramework::Spawnable>::Uuid())
|
||||
{
|
||||
ProcessSpawnableAsset(info.m_relativePath, id);
|
||||
}
|
||||
};
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnumerateAssets, nullptr,
|
||||
enumerateCallback, nullptr);
|
||||
}
|
||||
|
||||
void NetworkSpawnableLibrary::ProcessSpawnableAsset(const AZStd::string& relativePath, const AZ::Data::AssetId id)
|
||||
{
|
||||
const AZ::Name name = AZ::Name(relativePath);
|
||||
m_spawnables[name] = id;
|
||||
m_spawnablesReverseLookup[id] = name;
|
||||
|
||||
}
|
||||
|
||||
void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
|
||||
{
|
||||
BuildPrefabsList();
|
||||
}
|
||||
|
||||
AZ::Name NetworkSpawnableLibrary::GetPrefabNameFromAssetId(AZ::Data::AssetId assetId)
|
||||
{
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
auto it = m_spawnablesReverseLookup.find(assetId);
|
||||
if (it != m_spawnablesReverseLookup.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
AZ::Data::AssetId NetworkSpawnableLibrary::GetAssetIdByName(AZ::Name name)
|
||||
{
|
||||
auto it = m_spawnables.find(name);
|
||||
if (it != m_spawnables.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
/// Implementation of the network prefab library interface.
|
||||
class NetworkSpawnableLibrary final
|
||||
: private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
public:
|
||||
NetworkSpawnableLibrary();
|
||||
~NetworkSpawnableLibrary();
|
||||
|
||||
void BuildPrefabsList();
|
||||
void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id);
|
||||
|
||||
/// AssetCatalogEventBus overrides.
|
||||
void OnCatalogLoaded(const char* catalogFile) override;
|
||||
|
||||
AZ::Name GetPrefabNameFromAssetId(AZ::Data::AssetId assetId);
|
||||
AZ::Data::AssetId GetAssetIdByName(AZ::Name name);
|
||||
|
||||
private:
|
||||
AZStd::unordered_map<AZ::Name, AZ::Data::AssetId> m_spawnables;
|
||||
AZStd::unordered_map<AZ::Data::AssetId, AZ::Name> m_spawnablesReverseLookup;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 <Source/Pipeline/NetBindMarkerComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void NetBindMarkerComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<NetBindMarkerComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void NetBindMarkerComponent::Activate()
|
||||
{
|
||||
}
|
||||
|
||||
void NetBindMarkerComponent::Deactivate()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! @class NetBindMarkerComponent
|
||||
//! @brief Component for tracking net entities in the original non-networked spawnable.
|
||||
class NetBindMarkerComponent final : public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(NetBindMarkerComponent, "{40612C1B-427D-45C6-A2F0-04E16DF5B718}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
NetBindMarkerComponent() = default;
|
||||
~NetBindMarkerComponent() override = default;
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
};
|
||||
} // namespace Multiplayer
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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 <Source/Pipeline/NetworkPrefabProcessor.h>
|
||||
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <Prefab/Spawnable/SpawnableUtils.h>
|
||||
#include <Source/Components/NetBindComponent.h>
|
||||
#include <Source/Pipeline/NetBindMarkerComponent.h>
|
||||
#include <Source/Pipeline/NetworkSpawnableHolderComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor;
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore;
|
||||
|
||||
void NetworkPrefabProcessor::Process(PrefabProcessorContext& context)
|
||||
{
|
||||
context.ListPrefabs([&context](AZStd::string_view prefabName, PrefabDom& prefab) {
|
||||
ProcessPrefab(context, prefabName, prefab);
|
||||
});
|
||||
}
|
||||
|
||||
void NetworkPrefabProcessor::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
|
||||
{
|
||||
serializeContext->Class<NetworkPrefabProcessor, PrefabProcessor>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
static AZStd::vector<AZ::Entity*> GetEntitiesFromInstance(AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*> result;
|
||||
|
||||
instance->GetNestedEntities([&result](const AZStd::unique_ptr<AZ::Entity>& entity) {
|
||||
result.emplace_back(entity.get());
|
||||
return true;
|
||||
});
|
||||
|
||||
if (instance->HasContainerEntity())
|
||||
{
|
||||
auto containerEntityReference = instance->GetContainerEntity();
|
||||
result.emplace_back(&containerEntityReference->get());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
void NetworkPrefabProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> sourceInstance(aznew Instance());
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab,
|
||||
PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
AZStd::string errorMessage("NetworkPrefabProcessor: Failed to Load Prefab Instance from given Prefab Dom.");
|
||||
if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source));
|
||||
}
|
||||
AZ_Error("NetworkPrefabProcessor", false, errorMessage.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string uniqueName = prefabName;
|
||||
uniqueName += ".network.spawnable";
|
||||
|
||||
auto serializer = [](AZStd::vector<uint8_t>& output, const ProcessedObjectStore& object) -> bool {
|
||||
AZ::IO::ByteContainerStream stream(&output);
|
||||
auto& asset = object.GetAsset();
|
||||
return AZ::Utils::SaveObjectToStream(stream, AZ::DataStream::ST_JSON, &asset, asset.GetType());
|
||||
};
|
||||
|
||||
auto&& [object, networkSpawnable] =
|
||||
ProcessedObjectStore::Create<AzFramework::Spawnable>(uniqueName, context.GetSourceUuid(), AZStd::move(serializer));
|
||||
|
||||
// grab all nested entities from the Instance as source entities.
|
||||
AZStd::vector<AZ::Entity*> sourceEntities = GetEntitiesFromInstance(sourceInstance);
|
||||
AZStd::vector<AZ::EntityId> networkedEntityIds;
|
||||
networkedEntityIds.reserve(sourceEntities.size());
|
||||
|
||||
for (auto* sourceEntity : sourceEntities)
|
||||
{
|
||||
if (sourceEntity->FindComponent<NetBindComponent>())
|
||||
{
|
||||
networkedEntityIds.push_back(sourceEntity->GetId());
|
||||
}
|
||||
}
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab))
|
||||
{
|
||||
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Instance> networkInstance(aznew Instance());
|
||||
|
||||
for (auto entityId : networkedEntityIds)
|
||||
{
|
||||
AZ::Entity* netEntity = sourceInstance->DetachEntity(entityId).release();
|
||||
|
||||
networkInstance->AddEntity(*netEntity);
|
||||
|
||||
AZ::Entity* breadcrumbEntity = aznew AZ::Entity(netEntity->GetName());
|
||||
breadcrumbEntity->SetRuntimeActiveByDefault(netEntity->IsRuntimeActiveByDefault());
|
||||
breadcrumbEntity->CreateComponent<NetBindMarkerComponent>();
|
||||
AzFramework::TransformComponent* transformComponent = netEntity->FindComponent<AzFramework::TransformComponent>();
|
||||
breadcrumbEntity->CreateComponent<AzFramework::TransformComponent>(*transformComponent);
|
||||
|
||||
// TODO: Configure NetBindMarkerComponent to refer to the net entity
|
||||
sourceInstance->AddEntity(*breadcrumbEntity);
|
||||
}
|
||||
|
||||
// Add net spawnable asset holder
|
||||
{
|
||||
AZ::Data::AssetId assetId = networkSpawnable->GetId();
|
||||
AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset;
|
||||
networkSpawnableAsset.Create(assetId);
|
||||
networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity();
|
||||
if (containerEntityRef.has_value())
|
||||
{
|
||||
auto* networkSpawnableHolderComponent = containerEntityRef.value().get().CreateComponent<NetworkSpawnableHolderComponent>();
|
||||
networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName);
|
||||
auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent<NetworkSpawnableHolderComponent>();
|
||||
networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset);
|
||||
sourceInstance->AddEntity(*networkSpawnableHolderEntity);
|
||||
}
|
||||
}
|
||||
|
||||
// save the final result in the target Prefab DOM.
|
||||
PrefabDom networkPrefab;
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*networkInstance, networkPrefab))
|
||||
{
|
||||
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab))
|
||||
{
|
||||
AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool result = SpawnableUtils::CreateSpawnable(*networkSpawnable, networkPrefab);
|
||||
if (result)
|
||||
{
|
||||
AzFramework::Spawnable::EntityList& entities = networkSpawnable->GetEntities();
|
||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||
{
|
||||
(*it)->InvalidateDependencies();
|
||||
(*it)->EvaluateDependencies();
|
||||
}
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName));
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/Prefab/Spawnable/PrefabProcessor.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor;
|
||||
using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext;
|
||||
using AzToolsFramework::Prefab::PrefabDom;
|
||||
|
||||
class NetworkPrefabProcessor : public PrefabProcessor
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor);
|
||||
|
||||
~NetworkPrefabProcessor() override = default;
|
||||
|
||||
void Process(PrefabProcessorContext& context) override;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
protected:
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 <Source/Pipeline/NetworkSpawnableHolderComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void NetworkSpawnableHolderComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<NetworkSpawnableHolderComponent, AZ::Component>()
|
||||
->Version(1)
|
||||
->Field("AssetRef", &NetworkSpawnableHolderComponent::m_networkSpawnableAsset);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void NetworkSpawnableHolderComponent::Activate()
|
||||
{
|
||||
}
|
||||
|
||||
void NetworkSpawnableHolderComponent::Deactivate()
|
||||
{
|
||||
}
|
||||
|
||||
void NetworkSpawnableHolderComponent::SetNetworkSpawnableAsset(AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset)
|
||||
{
|
||||
m_networkSpawnableAsset = networkSpawnableAsset;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset()
|
||||
{
|
||||
return m_networkSpawnableAsset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! @class NetworkSpawnableHolderComponent
|
||||
//! @brief Component for holding a reference to the network spawnable to make sure it is loaded with the original one.
|
||||
class NetworkSpawnableHolderComponent final : public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(NetworkSpawnableHolderComponent, "{B0E3ADEE-FCB4-4A32-8D4F-6920F1CB08E4}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
NetworkSpawnableHolderComponent();;
|
||||
~NetworkSpawnableHolderComponent() override = default;
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
void SetNetworkSpawnableAsset(AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset);
|
||||
AZ::Data::Asset<AzFramework::Spawnable> GetNetworkSpawnableAsset();
|
||||
|
||||
private:
|
||||
AZ::Data::Asset<AzFramework::Spawnable> m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
};
|
||||
} // namespace Multiplayer
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Source/Multiplayer_precompiled.cpp
|
||||
Source/Multiplayer_precompiled.h
|
||||
Source/Debug/MultiplayerDebugModule.cpp
|
||||
Source/Debug/MultiplayerDebugModule.h
|
||||
Source/Debug/MultiplayerDebugSystemComponent.cpp
|
||||
Source/Debug/MultiplayerDebugSystemComponent.h
|
||||
)
|
||||
@@ -63,6 +63,8 @@ set(FILES
|
||||
Source/NetworkEntity/NetworkEntityHandle.inl
|
||||
Source/NetworkEntity/NetworkEntityManager.cpp
|
||||
Source/NetworkEntity/NetworkEntityManager.h
|
||||
Source/NetworkEntity/NetworkSpawnableLibrary.cpp
|
||||
Source/NetworkEntity/NetworkSpawnableLibrary.h
|
||||
Source/NetworkEntity/NetworkEntityRpcMessage.cpp
|
||||
Source/NetworkEntity/NetworkEntityRpcMessage.h
|
||||
Source/NetworkEntity/NetworkEntityTracker.cpp
|
||||
@@ -84,6 +86,10 @@ set(FILES
|
||||
Source/NetworkTime/NetworkTime.h
|
||||
Source/NetworkTime/RewindableObject.h
|
||||
Source/NetworkTime/RewindableObject.inl
|
||||
Source/Pipeline/NetBindMarkerComponent.cpp
|
||||
Source/Pipeline/NetBindMarkerComponent.h
|
||||
Source/Pipeline/NetworkSpawnableHolderComponent.cpp
|
||||
Source/Pipeline/NetworkSpawnableHolderComponent.h
|
||||
Source/ReplicationWindows/NullReplicationWindow.cpp
|
||||
Source/ReplicationWindows/NullReplicationWindow.h
|
||||
Source/ReplicationWindows/IReplicationWindow.h
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Source/Multiplayer_precompiled.cpp
|
||||
Source/Multiplayer_precompiled.h
|
||||
Source/Pipeline/NetworkPrefabProcessor.cpp
|
||||
Source/Pipeline/NetworkPrefabProcessor.h
|
||||
Source/MultiplayerToolsModule.h
|
||||
Source/MultiplayerToolsModule.cpp
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"Amazon":
|
||||
{
|
||||
"Tools":
|
||||
{
|
||||
"Prefab":
|
||||
{
|
||||
"Processing":
|
||||
{
|
||||
"Stack":
|
||||
{
|
||||
"GameObjectCreation":
|
||||
[
|
||||
{ "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover" },
|
||||
{ "$type": "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}" },
|
||||
{
|
||||
"$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor",
|
||||
"SerializationFormat": "Text" // Options are "Binary" (default) or "Text". Prefer "Binary" for performance.
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user