Refactored spawning network entities to use SpawnableEntityManager instead of duplicating the code in NetworkEntityManager
This commit is contained in:
@@ -11,7 +11,12 @@
|
||||
*/
|
||||
|
||||
#include <Source/Pipeline/NetBindMarkerComponent.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <Multiplayer/IMultiplayer.h>
|
||||
#include <Multiplayer/INetworkSpawnableLibrary.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -21,15 +26,91 @@ namespace Multiplayer
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<NetBindMarkerComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
->Version(1)
|
||||
->Field("NetEntityIndex", &NetBindMarkerComponent::m_netEntityIndex)
|
||||
->Field("NetSpawnableAsset", &NetBindMarkerComponent::m_networkSpawnableAsset);
|
||||
}
|
||||
}
|
||||
|
||||
AzFramework::Spawnable* GetSpawnableFromAsset(AZ::Data::Asset<AzFramework::Spawnable>& asset)
|
||||
{
|
||||
AzFramework::Spawnable* spawnable = asset.GetAs<AzFramework::Spawnable>();
|
||||
if (!spawnable)
|
||||
{
|
||||
asset =
|
||||
AZ::Data::AssetManager::Instance().GetAsset<AzFramework::Spawnable>(asset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(asset);
|
||||
|
||||
spawnable = asset.GetAs<AzFramework::Spawnable>();
|
||||
}
|
||||
|
||||
return spawnable;
|
||||
}
|
||||
|
||||
|
||||
void NetBindMarkerComponent::Activate()
|
||||
{
|
||||
const auto agentType = AZ::Interface<IMultiplayer>::Get()->GetAgentType();
|
||||
const bool spawnImmediately =
|
||||
(agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer);
|
||||
|
||||
if (spawnImmediately && m_networkSpawnableAsset.GetId().IsValid())
|
||||
{
|
||||
AZ::Transform worldTm = GetEntity()->FindComponent<AzFramework::TransformComponent>()->GetWorldTM();
|
||||
auto preInsertionCallback =
|
||||
[worldTm = AZStd::move(worldTm), netEntityIndex = m_netEntityIndex, spawnableAssetId = m_networkSpawnableAsset.GetId()]
|
||||
(AzFramework::EntitySpawnTicket&, AzFramework::SpawnableEntityContainerView entities)
|
||||
{
|
||||
if (entities.size() == 1)
|
||||
{
|
||||
AZ::Entity* netEntity = *entities.begin();
|
||||
|
||||
auto* transformComponent = netEntity->FindComponent<AzFramework::TransformComponent>();
|
||||
transformComponent->SetWorldTM(worldTm);
|
||||
|
||||
AZ::Name spawnableName = AZ::Interface<INetworkSpawnableLibrary>::Get()->GetSpawnableNameFromAssetId(spawnableAssetId);
|
||||
PrefabEntityId prefabEntityId;
|
||||
prefabEntityId.m_prefabName = spawnableName;
|
||||
prefabEntityId.m_entityOffset = netEntityIndex;
|
||||
AZ::Interface<INetworkEntityManager>::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("NetBindMarkerComponent", false, "Requested to spawn 1 entity, but received %d", entities.size());
|
||||
}
|
||||
};
|
||||
|
||||
m_netSpawnTicket = AzFramework::EntitySpawnTicket(m_networkSpawnableAsset);
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnEntities(m_netSpawnTicket, {m_netEntityIndex}, preInsertionCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void NetBindMarkerComponent::Deactivate()
|
||||
{
|
||||
if(m_netSpawnTicket.IsValid())
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_netSpawnTicket);
|
||||
}
|
||||
}
|
||||
|
||||
size_t NetBindMarkerComponent::GetNetEntityIndex() const
|
||||
{
|
||||
return m_netEntityIndex;
|
||||
}
|
||||
|
||||
void NetBindMarkerComponent::SetNetEntityIndex(size_t netEntityIndex)
|
||||
{
|
||||
m_netEntityIndex = netEntityIndex;
|
||||
}
|
||||
|
||||
void NetBindMarkerComponent::SetNetworkSpawnableAsset(AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset)
|
||||
{
|
||||
m_networkSpawnableAsset = networkSpawnableAsset;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> NetBindMarkerComponent::GetNetworkSpawnableAsset() const
|
||||
{
|
||||
return m_networkSpawnableAsset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -34,6 +37,15 @@ namespace Multiplayer
|
||||
void Deactivate() override;
|
||||
//! @}
|
||||
|
||||
size_t GetNetEntityIndex() const;
|
||||
void SetNetEntityIndex(size_t val);
|
||||
|
||||
void SetNetworkSpawnableAsset(AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset);
|
||||
AZ::Data::Asset<AzFramework::Spawnable> GetNetworkSpawnableAsset() const;
|
||||
|
||||
private:
|
||||
AZ::Data::Asset<AzFramework::Spawnable> m_networkSpawnableAsset{AZ::Data::AssetLoadBehavior::PreLoad};
|
||||
size_t m_netEntityIndex = 0;
|
||||
AzFramework::EntitySpawnTicket m_netSpawnTicket;
|
||||
};
|
||||
} // namespace Multiplayer
|
||||
|
||||
@@ -114,29 +114,31 @@ namespace Multiplayer
|
||||
|
||||
AZStd::unique_ptr<Instance> networkInstance(aznew Instance());
|
||||
|
||||
for (auto entityId : networkedEntityIds)
|
||||
AZ::Data::Asset<AzFramework::Spawnable> networkSpawnableAsset;
|
||||
networkSpawnableAsset.Create(networkSpawnable->GetId());
|
||||
networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
for (size_t entityIndex = 0; entityIndex < networkedEntityIds.size(); ++entityIndex)
|
||||
{
|
||||
AZ::EntityId entityId = networkedEntityIds[entityIndex];
|
||||
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>();
|
||||
NetBindMarkerComponent* netBindMarkerComponent = breadcrumbEntity->CreateComponent<NetBindMarkerComponent>();
|
||||
// Each spawnable has a root meta-data entity at position 0, so starting net indices from 1
|
||||
netBindMarkerComponent->SetNetEntityIndex(entityIndex + 1);
|
||||
netBindMarkerComponent->SetNetworkSpawnableAsset(networkSpawnableAsset);
|
||||
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())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user