Merge branch 'FlaxEngine:master' into master

This commit is contained in:
Menotdan
2023-05-07 15:38:07 -04:00
committed by GitHub
2 changed files with 99 additions and 32 deletions

View File

@@ -861,7 +861,7 @@ void NetworkReplicator::DespawnObject(ScriptingObject* obj)
DeleteNetworkObject(obj);
}
uint32 NetworkReplicator::GetObjectOwnerClientId(ScriptingObject* obj)
uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj)
{
uint32 id = NetworkManager::ServerClientId;
if (obj)
@@ -870,11 +870,23 @@ uint32 NetworkReplicator::GetObjectOwnerClientId(ScriptingObject* obj)
const auto it = Objects.Find(obj->GetID());
if (it != Objects.End())
id = it->Item.OwnerClientId;
else
{
for (const SpawnItem& item : SpawnQueue)
{
if (item.Object == obj)
{
if (item.HasOwnership)
id = item.OwnerClientId;
break;
}
}
}
}
return id;
}
NetworkObjectRole NetworkReplicator::GetObjectRole(ScriptingObject* obj)
NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj)
{
NetworkObjectRole role = NetworkObjectRole::None;
if (obj)
@@ -883,6 +895,18 @@ NetworkObjectRole NetworkReplicator::GetObjectRole(ScriptingObject* obj)
const auto it = Objects.Find(obj->GetID());
if (it != Objects.End())
role = it->Item.Role;
else
{
for (const SpawnItem& item : SpawnQueue)
{
if (item.Object == obj)
{
if (item.HasOwnership)
role = item.Role;
break;
}
}
}
}
return role;
}
@@ -901,6 +925,18 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
auto& item = SpawnQueue[i];
if (item.Object == obj)
{
#if !BUILD_RELEASE
if (ownerClientId == NetworkManager::LocalClientId)
{
// Ensure local client owns that object actually
CHECK(localRole == NetworkObjectRole::OwnedAuthoritative);
}
else
{
// Ensure local client doesn't own that object since it's owned by other client
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
}
#endif
item.HasOwnership = true;
item.HierarchicalOwnership = hierarchical;
item.OwnerClientId = ownerClientId;
@@ -1469,8 +1505,8 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
}
// Recreate object locally (spawn only root)
ScriptingObject* obj = nullptr;
Actor* prefabInstance = nullptr;
Array<ScriptingObject*> objects;
if (msgData.PrefabId.IsValid())
{
const NetworkReplicatedObject* parent = ResolveObject(rootItem.ParentId);
@@ -1489,7 +1525,7 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
{
if (Objects.Contains(child->GetID()))
{
obj = FindPrefabObject(child, rootItem.PrefabObjectID);
ScriptingObject* obj = FindPrefabObject(child, rootItem.PrefabObjectID);
if (Objects.Contains(obj->GetID()))
{
// Other instance with already spawned network object
@@ -1521,46 +1557,77 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
return;
}
}
if (!obj)
obj = FindPrefabObject(prefabInstance, rootItem.PrefabObjectID);
if (!obj)
// Resolve objects from prefab instance
objects.Resize(msgData.ItemsCount);
for (int32 i = 0; i < msgData.ItemsCount; i++)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", rootItem.PrefabObjectID.ToString(), msgData.PrefabId.ToString());
Delete(prefabInstance);
return;
auto& msgDataItem = msgDataItems[i];
ScriptingObject* obj = FindPrefabObject(prefabInstance, msgDataItem.PrefabObjectID);
if (!obj)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", msgDataItem.PrefabObjectID.ToString(), msgData.PrefabId.ToString());
Delete(prefabInstance);
return;
}
objects[i] = obj;
}
}
else
else if (msgData.ItemsCount == 1)
{
// Spawn object
if (msgData.ItemsCount != 1)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Only prefab object spawning can contain more than one object (for type {})", String(rootItem.ObjectTypeName));
return;
}
const ScriptingTypeHandle objectType = Scripting::FindScriptingType(rootItem.ObjectTypeName);
obj = ScriptingObject::NewObject(objectType);
ScriptingObject* obj = ScriptingObject::NewObject(objectType);
if (!obj)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(rootItem.ObjectTypeName));
return;
}
objects.Add(obj);
}
else
{
// Spawn objects
objects.Resize(msgData.ItemsCount);
for (int32 i = 0; i < msgData.ItemsCount; i++)
{
auto& msgDataItem = msgDataItems[i];
const ScriptingTypeHandle objectType = Scripting::FindScriptingType(msgDataItem.ObjectTypeName);
ScriptingObject* obj = ScriptingObject::NewObject(objectType);
if (!obj)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(msgDataItem.ObjectTypeName));
for (ScriptingObject* e : objects)
Delete(e);
return;
}
objects[i] = obj;
if (i != 0)
{
// Link hierarchy of spawned objects before calling any networking code for them
if (auto sceneObject = ScriptingObject::Cast<SceneObject>(obj))
{
Actor* parent = nullptr;
for (int32 j = 0; j < i; j++)
{
if (msgDataItems[j].ObjectId == msgDataItem.ParentId)
{
parent = ScriptingObject::Cast<Actor>(objects[j]);
break;
}
}
if (parent)
sceneObject->SetParent(parent);
}
}
}
}
// Setup all newly spawned objects
for (int32 i = 0; i < msgData.ItemsCount; i++)
{
auto& msgDataItem = msgDataItems[i];
if (i != 0)
{
obj = FindPrefabObject(prefabInstance, msgDataItem.PrefabObjectID);
if (!obj)
{
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", msgDataItem.PrefabObjectID.ToString(), msgData.PrefabId.ToString());
Delete(prefabInstance);
return;
}
}
ScriptingObject* obj = objects[i];
if (!obj->IsRegistered())
obj->RegisterObject();
const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId);

View File

@@ -104,14 +104,14 @@ public:
/// </summary>
/// <param name="obj">The network object.</param>
/// <returns>The Client Id.</returns>
API_FUNCTION() static uint32 GetObjectOwnerClientId(ScriptingObject* obj);
API_FUNCTION() static uint32 GetObjectOwnerClientId(const ScriptingObject* obj);
/// <summary>
/// Gets the role of the network object used locally (eg. to check if can simulate object).
/// </summary>
/// <param name="obj">The network object.</param>
/// <returns>The object role.</returns>
API_FUNCTION() static NetworkObjectRole GetObjectRole(ScriptingObject* obj);
API_FUNCTION() static NetworkObjectRole GetObjectRole(const ScriptingObject* obj);
/// <summary>
/// Checks if the network object is owned locally (thus current client has authority to manage it).
@@ -119,7 +119,7 @@ public:
/// <remarks>Equivalent to GetObjectRole == OwnedAuthoritative.</remarks>
/// <param name="obj">The network object.</param>
/// <returns>True if object is owned by this client, otherwise false.</returns>
API_FUNCTION() FORCE_INLINE static bool IsObjectOwned(ScriptingObject* obj)
API_FUNCTION() FORCE_INLINE static bool IsObjectOwned(const ScriptingObject* obj)
{
return GetObjectRole(obj) == NetworkObjectRole::OwnedAuthoritative;
}
@@ -130,7 +130,7 @@ public:
/// <remarks>Equivalent to GetObjectRole != Replicated.</remarks>
/// <param name="obj">The network object.</param>
/// <returns>True if object is simulated on this client, otherwise false.</returns>
API_FUNCTION() FORCE_INLINE static bool IsObjectSimulated(ScriptingObject* obj)
API_FUNCTION() FORCE_INLINE static bool IsObjectSimulated(const ScriptingObject* obj)
{
return GetObjectRole(obj) != NetworkObjectRole::Replicated;
}
@@ -141,7 +141,7 @@ public:
/// <remarks>Equivalent to (GetObjectRole == Replicated or GetObjectRole == ReplicatedAutonomous).</remarks>
/// <param name="obj">The network object.</param>
/// <returns>True if object is simulated on this client, otherwise false.</returns>
API_FUNCTION() FORCE_INLINE static bool IsObjectReplicated(ScriptingObject* obj)
API_FUNCTION() FORCE_INLINE static bool IsObjectReplicated(const ScriptingObject* obj)
{
const NetworkObjectRole role = GetObjectRole(obj);
return role == NetworkObjectRole::Replicated || role == NetworkObjectRole::ReplicatedSimulated;