Enabled multi-entities player prefabs. Added updating replication set for hierarchy children. PR feedback addressing

Signed-off-by: pereslav <pereslav@amazon.com>
monroegm-disable-blank-issue-2
pereslav 4 years ago
parent 801e54c599
commit a58325e691

@ -29,6 +29,8 @@ namespace Multiplayer
, public NetworkHierarchyRequestBus::Handler
{
friend class NetworkHierarchyChildComponent;
friend class NetworkHierarchyRootComponentController;
friend class ServerToClientReplicationWindow;
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase);
@ -57,8 +59,6 @@ namespace Multiplayer
void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override;
//! @}
const AZStd::vector<AZ::Entity*>& GetHierarchicalEntitiesRef() const;
protected:
void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot);
@ -103,7 +103,7 @@ namespace Multiplayer
};
//! NetworkCharacterComponentController
//! NetworkHierarchyRootComponentController
//! This is the network controller for NetworkHierarchyRootComponent.
//! Class provides the ability to process input for hierarchies.
class NetworkHierarchyRootComponentController

@ -29,7 +29,6 @@ namespace Multiplayer
friend class NetworkInputMigrationVector;
friend class NetworkInputHistory;
friend class NetworkInputChild;
friend class NetworkSubInput;
NetworkInput(const NetworkInput&);
NetworkInput& operator= (const NetworkInput&);
@ -81,28 +80,4 @@ namespace Multiplayer
ConstNetworkEntityHandle m_owner;
bool m_wasAttached = false;
};
// Used by the NetworkHierarchyRootComponent. This component allows the gameplay programmer to specify dependent entities
// Since it is possible to for the Client/Server to disagree about the state of related entities, this input encodes the entity that
// is associated with it.
class NetworkSubInput final
{
public:
NetworkSubInput() = default;
NetworkSubInput(const NetworkSubInput&) = default;
NetworkSubInput(const ConstNetworkEntityHandle& entityHandle);
NetworkSubInput& operator=(const NetworkSubInput&) = default;
void Attach(const ConstNetworkEntityHandle& entityHandle);
const ConstNetworkEntityHandle& GetOwner() const;
NetworkInput& GetNetworkInput();
const NetworkInput& GetNetworkInput() const;
bool Serialize(AzNetworking::ISerializer& serializer);
private:
ConstNetworkEntityHandle m_owner;
NetworkInput m_networkInput;
};
}

@ -8,9 +8,11 @@
OverrideInclude="Multiplayer/Components/NetworkHierarchyRootComponent.h"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Include File="Source/NetworkInput/NetworkInputChild.h"/>
<ComponentRelation Constraint="Required" HasController="true" Name="NetworkTransformComponent" Namespace="Multiplayer" Include="Multiplayer/Components/NetworkTransformComponent.h" />
<NetworkInput Type="AZStd::vector&lt;NetworkSubInput&gt;" Name="ChildInputs" Init="" />
<NetworkInput Type="AZStd::vector&lt;NetworkInputChild&gt;" Name="ChildInputs" Init="" />
<NetworkProperty Type="NetEntityId" Name="hierarchyRoot" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="false" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
</Component>

@ -139,11 +139,6 @@ namespace Multiplayer
return m_hierarchicalEntities;
}
const AZStd::vector<AZ::Entity*>& NetworkHierarchyRootComponent::GetHierarchicalEntitiesRef() const
{
return m_hierarchicalEntities;
}
AZ::Entity* NetworkHierarchyRootComponent::GetHierarchicalRoot() const
{
if (m_rootEntity)
@ -361,7 +356,10 @@ namespace Multiplayer
return;
}
const AZStd::vector<AZ::Entity*>& entities = component.GetHierarchicalEntitiesRef();
INetworkEntityManager* networkEntityManager = AZ::Interface<INetworkEntityManager>::Get();
AZ_Assert(networkEntityManager, "NetworkEntityManager must be created.");
const AZStd::vector<AZ::Entity*>& entities = component.m_hierarchicalEntities;
auto* networkInput = input.FindComponentInput<NetworkHierarchyRootComponentNetworkInput>();
networkInput->m_childInputs.clear();
@ -371,21 +369,23 @@ namespace Multiplayer
{
if(child == component.GetEntity())
{
return; // Avoid infinite recursion
continue; // Avoid infinite recursion
}
auto* netComp = child->FindComponent<NetBindComponent>();
AZ_Assert(netComp, "No NetSystemComponent, this should be impossible");
NetEntityId childNetEntitydId = networkEntityManager->GetNetEntityIdById(child->GetId());
ConstNetworkEntityHandle childEntityHandle = networkEntityManager->GetEntity(childNetEntitydId);
NetBindComponent* netComp = childEntityHandle.GetNetBindComponent();
AZ_Assert(netComp, "No NetBindComponent, this should be impossible");
// Validate we still have a controller and we aren't in the middle of removing them
if (netComp->HasController())
{
ConstNetworkEntityHandle childEntityHandle = netComp->GetEntityHandle();
NetworkSubInput subInput;
NetworkInputChild subInput;
subInput.Attach(childEntityHandle);
subInput.GetNetworkInput().SetClientInputId(input.GetClientInputId());
netComp->CreateInput(subInput.GetNetworkInput(), deltaTime);
// make sure our input sub commands have the same time as the original
subInput.GetNetworkInput().SetClientInputId(input.GetClientInputId());
networkInput->m_childInputs.emplace_back(subInput);
@ -408,13 +408,13 @@ namespace Multiplayer
if (auto* networkInput = input.FindComponentInput<NetworkHierarchyRootComponentNetworkInput>())
{
for (NetworkSubInput& subInput : networkInput->m_childInputs)
for (NetworkInputChild& subInput : networkInput->m_childInputs)
{
const ConstNetworkEntityHandle& childEntity = subInput.GetOwner();
if (auto* localChild = childEntity.GetEntity())
{
auto* netComp = localChild->FindComponent<NetBindComponent>();
AZ_Assert(netComp, "No NetSystemComponent, this should be impossible");
auto* netComp = childEntity.GetNetBindComponent();
AZ_Assert(netComp, "No NetBindComponent, this should be impossible");
// We do not rewind entity role changes, so make sure we are the correct role prior to processing
if (netComp->HasController())
{

@ -665,12 +665,21 @@ namespace Multiplayer
if (GetAgentType() == MultiplayerAgentType::ClientServer
|| GetAgentType() == MultiplayerAgentType::DedicatedServer)
{
NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
if (controlledEntity.Exists())
INetworkEntityManager::EntityList entityList = SpawnDefaultPlayerPrefab();
for (auto& netEntity : entityList)
{
controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
if (netEntity.Exists())
{
netEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
}
netEntity.Activate();
}
NetworkEntityHandle controlledEntity;
if (entityList.size() > 0)
{
controlledEntity = entityList[0];
}
controlledEntity.Activate();
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<ServerToClientReplicationWindow>(controlledEntity, connection);
@ -780,12 +789,16 @@ namespace Multiplayer
// Spawn the default player for this host since the host is also a player (not a dedicated server)
if (m_agentType == MultiplayerAgentType::ClientServer)
{
NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent())
INetworkEntityManager::EntityList entityList = SpawnDefaultPlayerPrefab();
for (NetworkEntityHandle controlledEntity : entityList)
{
controlledEntityNetBindComponent->SetAllowAutonomy(true);
if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent())
{
controlledEntityNetBindComponent->SetAllowAutonomy(true);
}
controlledEntity.Activate();
}
controlledEntity.Activate();
}
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
@ -1028,17 +1041,12 @@ namespace Multiplayer
}
}
NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
INetworkEntityManager::EntityList MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
{
PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset).c_str()));
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate);
NetworkEntityHandle controlledEntity;
if (entityList.size() > 0)
{
controlledEntity = entityList[0];
}
return controlledEntity;
return entityList;
}
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)

@ -139,7 +139,7 @@ namespace Multiplayer
void TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds);
void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom);
void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector<Multiplayer::LongNetworkString, 32>& commands);
NetworkEntityHandle SpawnDefaultPlayerPrefab();
INetworkEntityManager::EntityList SpawnDefaultPlayerPrefab();
AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session");

@ -188,53 +188,4 @@ namespace Multiplayer
}
m_wasAttached = rhs.m_wasAttached;
}
NetworkSubInput::NetworkSubInput(const ConstNetworkEntityHandle& entityHandle)
: m_owner(entityHandle)
{
Attach(m_owner);
}
void NetworkSubInput::Attach(const ConstNetworkEntityHandle& entityHandle)
{
m_owner = entityHandle;
if (auto* localEnt = entityHandle.GetEntity())
{
NetBindComponent* netBindComponent = localEnt->FindComponent<NetBindComponent>();
if (netBindComponent)
{
m_networkInput.AttachNetBindComponent(netBindComponent);
}
}
}
const ConstNetworkEntityHandle& NetworkSubInput::GetOwner() const
{
return m_owner;
}
NetworkInput& NetworkSubInput::GetNetworkInput()
{
return m_networkInput;
}
const NetworkInput& NetworkSubInput::GetNetworkInput() const
{
return m_networkInput;
}
bool NetworkSubInput::Serialize(AzNetworking::ISerializer& serializer)
{
NetEntityId tmpId = m_owner.GetNetEntityId();
serializer.Serialize(tmpId, "OwnerId");
if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)
{
m_owner = AZ::Interface<INetworkEntityManager>::Get()->GetEntity(tmpId);
}
serializer.Serialize(m_networkInput, "NetInput");
return serializer.IsValid();
}
}

@ -12,10 +12,7 @@
namespace Multiplayer
{
//! Max number of entities that can be children of our netbound player entity.
static constexpr uint32_t MaxEntityHierarchyChildren = 16;
//! Used by the EntityHierarchyComponent. This component allows the gameplay programmer to specify inputs for dependent entities.
//! Used by the NetworkHierarchyRootComponent. This component allows the gameplay programmer to specify inputs for dependent entities.
//! Since it is possible to for the Client/Server to disagree about the state of related entities,
//! this network input encodes the entity that is associated with it.
class NetworkInputChild

@ -9,6 +9,7 @@
#include <Source/ReplicationWindows/ServerToClientReplicationWindow.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
#include <Multiplayer/Components/NetBindComponent.h>
#include <Multiplayer/Components/NetworkHierarchyRootComponent.h>
#include <AzFramework/Visibility/IVisibilitySystem.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Console/ILogger.h>
@ -174,11 +175,11 @@ namespace Multiplayer
// Note: Do not add any Client entities after this point, otherwise you stomp over the Autonomous mode
m_replicationSet[m_controlledEntity] = { NetEntityRole::Autonomous, 1.0f }; // Always replicate autonomous entities
//auto hierarchyController = FindController<EntityHierarchyComponent::Authority>(m_ControlledEntity);
//if (hierarchyController != nullptr)
//{
// CollectControlledEntitiesRecursive(m_replicationSet, *hierarchyController);
//}
auto* hierarchyComponent = m_controlledEntity.FindComponent<NetworkHierarchyRootComponent>();
if (hierarchyComponent != nullptr)
{
UpdateHierarchyReplicationSet(m_replicationSet, *hierarchyComponent);
}
}
AzNetworking::PacketId ServerToClientReplicationWindow::SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector)
@ -326,18 +327,18 @@ namespace Multiplayer
}
}
//void ServerToClientReplicationWindow::CollectControlledEntitiesRecursive(ReplicationSet& replicationSet, EntityHierarchyComponent::Authority& hierarchyController)
//{
// auto controlledEnts = hierarchyController.GetChildrenRelatedEntities();
// for (auto& controlledEnt : controlledEnts)
// {
// AZ_Assert(controlledEnt != nullptr, "We have lost a controlled entity unexpectedly");
// replicationSet[controlledEnt.GetConstEntity()] = EntityReplicationData(EntityNetworkRoleT::e_Autonomous, EntityPrioritySystem::k_MaxPriority); // Always replicate controlled entities
// auto hierarchyController = controlledEnt.FindController<EntityHierarchyComponent::Authority>();
// if (hierarchyController != nullptr)
// {
// CollectControlledEntitiesRecursive(replicationSet, *hierarchyController);
// }
// }
//}
void ServerToClientReplicationWindow::UpdateHierarchyReplicationSet(ReplicationSet& replicationSet, NetworkHierarchyRootComponent& hierarchyComponent)
{
INetworkEntityManager* networkEntityManager = AZ::Interface<INetworkEntityManager>::Get();
AZ_Assert(networkEntityManager, "NetworkEntityManager must be created.");
for (const AZ::Entity* controlledEntity : hierarchyComponent.m_hierarchicalEntities)
{
NetEntityId controlledNetEntitydId = networkEntityManager->GetNetEntityIdById(controlledEntity->GetId());
ConstNetworkEntityHandle controlledEntityHandle = networkEntityManager->GetEntity(controlledNetEntitydId);
AZ_Assert(controlledEntityHandle != nullptr, "We have lost a controlled entity unexpectedly");
replicationSet[controlledEntityHandle] = { NetEntityRole::Autonomous, 1.0f };
}
}
}

@ -20,6 +20,7 @@
namespace Multiplayer
{
class NetSystemComponent;
class NetworkHierarchyRootComponent;
class ServerToClientReplicationWindow
: public IReplicationWindow
@ -56,7 +57,7 @@ namespace Multiplayer
void OnEntityActivated(AZ::Entity* entity);
void OnEntityDeactivated(AZ::Entity* entity);
//void CollectControlledEntitiesRecursive(ReplicationSet& replicationSet, EntityHierarchyComponent::Authority& hierarchyController);
void UpdateHierarchyReplicationSet(ReplicationSet& replicationSet, NetworkHierarchyRootComponent& hierarchyComponent);
void EvaluateConnection();
void AddEntityToReplicationSet(ConstNetworkEntityHandle& entityHandle, float priority, float distanceSquared);

Loading…
Cancel
Save