Merging latest main
This commit is contained in:
+3
-3
@@ -555,10 +555,10 @@ namespace Multiplayer
|
||||
{
|
||||
replicatorEntity = entityList[0];
|
||||
}
|
||||
|
||||
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr());
|
||||
if (replicatorEntity == nullptr)
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "There should be exactly one created entity out of prefab %s, index %d. Got: %d",
|
||||
prefabEntityId.m_prefabName.GetCStr(), prefabEntityId.m_entityOffset, entityList.size());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,18 +34,15 @@ 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_onSpawnedHandler([this](AZ::Data::Asset<AzFramework::Spawnable> spawnable) { this->OnSpawned(spawnable); })
|
||||
, m_onDespawnedHandler([this](AZ::Data::Asset<AzFramework::Spawnable> spawnable) { this->OnDespawned(spawnable); })
|
||||
{
|
||||
AZ::Interface<INetworkEntityManager>::Register(this);
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusConnect();
|
||||
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->AddOnSpawnedHandler(m_onSpawnedHandler);
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->AddOnDespawnedHandler(m_onDespawnedHandler);
|
||||
}
|
||||
|
||||
NetworkEntityManager::~NetworkEntityManager()
|
||||
{
|
||||
AzFramework::RootSpawnableNotificationBus::Handler::BusDisconnect();
|
||||
AZ::Interface<INetworkEntityManager>::Unregister(this);
|
||||
}
|
||||
|
||||
void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain)
|
||||
@@ -331,17 +328,41 @@ namespace Multiplayer
|
||||
const AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities();
|
||||
size_t entitiesSize = entities.size();
|
||||
|
||||
using EntityIdMap = AZStd::unordered_map<AZ::EntityId, AZ::EntityId>;
|
||||
EntityIdMap originalToCloneIdMap;
|
||||
|
||||
for (size_t i = 0; i < entitiesSize; ++i)
|
||||
{
|
||||
AZ::Entity* clone = serializeContext->CloneObject(entities[i].get());
|
||||
AZ::Entity* originalEntity = entities[i].get();
|
||||
AZ::Entity* clone = serializeContext->CloneObject(originalEntity);
|
||||
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
|
||||
|
||||
clone->SetId(AZ::Entity::MakeId());
|
||||
|
||||
originalToCloneIdMap[originalEntity->GetId()] = clone->GetId();
|
||||
|
||||
NetBindComponent* netBindComponent = clone->FindComponent<NetBindComponent>();
|
||||
if (netBindComponent != nullptr)
|
||||
{
|
||||
// Update TransformComponent parent Id. It is guaranteed for the entities array to be sorted from parent->child here.
|
||||
auto* transformComponent = clone->FindComponent<AzFramework::TransformComponent>();
|
||||
AZ::EntityId parentId = transformComponent->GetParentId();
|
||||
if (parentId.IsValid())
|
||||
{
|
||||
auto it = originalToCloneIdMap.find(parentId);
|
||||
if (it != originalToCloneIdMap.end())
|
||||
{
|
||||
transformComponent->SetParentRelative(it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("NetworkEntityManager", false, "Entity %s doesn't have the parent entity %s present in network.spawnable",
|
||||
clone->GetName().c_str(), parentId.ToString().data());
|
||||
}
|
||||
}
|
||||
|
||||
PrefabEntityId prefabEntityId;
|
||||
prefabEntityId.m_prefabName = m_networkPrefabLibrary.GetPrefabNameFromAssetId(spawnable.GetId());
|
||||
prefabEntityId.m_prefabName = m_networkPrefabLibrary.GetSpawnableNameFromAssetId(spawnable.GetId());
|
||||
prefabEntityId.m_entityOffset = aznumeric_cast<uint32_t>(i);
|
||||
|
||||
const NetEntityId netEntityId = NextId();
|
||||
@@ -469,57 +490,19 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnSpawned(AZ::Data::Asset<AzFramework::Spawnable> spawnable)
|
||||
void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole)
|
||||
{
|
||||
AzFramework::Spawnable* spawnableData = spawnable.GetAs<AzFramework::Spawnable>();
|
||||
const auto& entityList = spawnableData->GetEntities();
|
||||
if (entityList.size() == 0)
|
||||
auto* netBindComponent = netEntity->FindComponent<NetBindComponent>();
|
||||
|
||||
if (netBindComponent)
|
||||
{
|
||||
AZ_Error("NetworkEntityManager", false, "OnSpawned: Spawnable %s doesn't have any entities.",
|
||||
spawnable.GetHint().c_str());
|
||||
return;
|
||||
const NetEntityId netEntityId = NextId();
|
||||
netBindComponent->PreInit(netEntity, prefabEntityId, netEntityId, netEntityRole);
|
||||
}
|
||||
|
||||
const auto& rootEntity = entityList[0];
|
||||
auto* spawnableHolder = rootEntity->FindComponent<NetworkSpawnableHolderComponent>();
|
||||
if (!spawnableHolder)
|
||||
else
|
||||
{
|
||||
// Root entity doesn't have NetworkSpawnableHolderComponent. It means there's no corresponding network spawnable.
|
||||
return;
|
||||
AZ_Error("NetworkEntityManager", false, "SetupNetEntity called for an entity with no NetBindComponent. Entity: %s",
|
||||
netEntity->GetName().c_str());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
auto* multiplayer = GetMultiplayer();
|
||||
|
||||
const auto agentType = multiplayer->GetAgentType();
|
||||
const bool spawnImmediately =
|
||||
(agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer);
|
||||
|
||||
if (spawnImmediately)
|
||||
{
|
||||
CreateEntitiesImmediate(*netSpawnable, NetEntityRole::Authority);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkEntityManager::OnDespawned([[maybe_unused]]AZ::Data::Asset<AzFramework::Spawnable> spawnable)
|
||||
{
|
||||
// TODO: Remove entities instantiated from the spawnable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace Multiplayer
|
||||
const AZ::Transform& transform
|
||||
) override;
|
||||
|
||||
void SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) override;
|
||||
|
||||
uint32_t GetEntityCount() const override;
|
||||
NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override;
|
||||
void MarkForRemoval(const ConstNetworkEntityHandle& entityHandle) override;
|
||||
@@ -93,9 +95,6 @@ namespace Multiplayer
|
||||
void RemoveEntities();
|
||||
NetEntityId NextId();
|
||||
|
||||
void OnSpawned(AZ::Data::Asset<AzFramework::Spawnable> spawnable);
|
||||
void OnDespawned(AZ::Data::Asset<AzFramework::Spawnable> spawnable);
|
||||
|
||||
NetworkEntityTracker m_networkEntityTracker;
|
||||
NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker;
|
||||
MultiplayerComponentRegistry m_multiplayerComponentRegistry;
|
||||
@@ -123,8 +122,5 @@ namespace Multiplayer
|
||||
DeferredRpcMessages m_localDeferredRpcMessages;
|
||||
|
||||
NetworkSpawnableLibrary m_networkPrefabLibrary;
|
||||
|
||||
AZ::Event<AZ::Data::Asset<AzFramework::Spawnable>>::Handler m_onSpawnedHandler;
|
||||
AZ::Event<AZ::Data::Asset<AzFramework::Spawnable>>::Handler m_onDespawnedHandler;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,20 +14,23 @@
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
NetworkSpawnableLibrary::NetworkSpawnableLibrary()
|
||||
{
|
||||
AZ::Interface<INetworkSpawnableLibrary>::Register(this);
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
NetworkSpawnableLibrary::~NetworkSpawnableLibrary()
|
||||
{
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
AZ::Interface<INetworkSpawnableLibrary>::Unregister(this);
|
||||
}
|
||||
|
||||
void NetworkSpawnableLibrary::BuildPrefabsList()
|
||||
void NetworkSpawnableLibrary::BuildSpawnablesList()
|
||||
{
|
||||
auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
@@ -50,10 +53,10 @@ namespace Multiplayer
|
||||
|
||||
void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
|
||||
{
|
||||
BuildPrefabsList();
|
||||
BuildSpawnablesList();
|
||||
}
|
||||
|
||||
AZ::Name NetworkSpawnableLibrary::GetPrefabNameFromAssetId(AZ::Data::AssetId assetId)
|
||||
AZ::Name NetworkSpawnableLibrary::GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId)
|
||||
{
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
|
||||
@@ -12,30 +12,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <Multiplayer/INetworkSpawnableLibrary.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 INetworkSpawnableLibrary
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(NetworkSpawnableLibrary, "{65E15F33-E893-49C2-A8E2-B6A8A6EF31E0}", INetworkSpawnableLibrary);
|
||||
|
||||
NetworkSpawnableLibrary();
|
||||
~NetworkSpawnableLibrary();
|
||||
|
||||
void BuildPrefabsList();
|
||||
void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id);
|
||||
/// INetworkSpawnableLibrary overrides.
|
||||
void BuildSpawnablesList() override;
|
||||
void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id) override;
|
||||
AZ::Name GetSpawnableNameFromAssetId(AZ::Data::AssetId assetId) override;
|
||||
AZ::Data::AssetId GetAssetIdByName(AZ::Name name) override;
|
||||
|
||||
/// 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;
|
||||
|
||||
Reference in New Issue
Block a user