Enabled multi-entities player prefabs. Added updating replication set for hierarchy children. PR feedback addressing
Signed-off-by: pereslav <pereslav@amazon.com>
This commit is contained in:
+3
-3
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -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<NetworkSubInput>" Name="ChildInputs" Init="" />
|
||||
|
||||
<NetworkInput Type="AZStd::vector<NetworkInputChild>" 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
|
||||
|
||||
+20
-19
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user