Add support for spawning multiple objects over network within a single group that is not from Prefabs

#1066
This commit is contained in:
Wojtek Figat
2023-05-07 19:40:31 +02:00
parent 531d005169
commit 0a5d37fd9b

View File

@@ -1505,8 +1505,8 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
} }
// Recreate object locally (spawn only root) // Recreate object locally (spawn only root)
ScriptingObject* obj = nullptr;
Actor* prefabInstance = nullptr; Actor* prefabInstance = nullptr;
Array<ScriptingObject*> objects;
if (msgData.PrefabId.IsValid()) if (msgData.PrefabId.IsValid())
{ {
const NetworkReplicatedObject* parent = ResolveObject(rootItem.ParentId); const NetworkReplicatedObject* parent = ResolveObject(rootItem.ParentId);
@@ -1525,7 +1525,7 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
{ {
if (Objects.Contains(child->GetID())) if (Objects.Contains(child->GetID()))
{ {
obj = FindPrefabObject(child, rootItem.PrefabObjectID); ScriptingObject* obj = FindPrefabObject(child, rootItem.PrefabObjectID);
if (Objects.Contains(obj->GetID())) if (Objects.Contains(obj->GetID()))
{ {
// Other instance with already spawned network object // Other instance with already spawned network object
@@ -1557,46 +1557,77 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
return; return;
} }
} }
if (!obj)
obj = FindPrefabObject(prefabInstance, rootItem.PrefabObjectID); // Resolve objects from prefab instance
if (!obj) 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()); auto& msgDataItem = msgDataItems[i];
Delete(prefabInstance); ScriptingObject* obj = FindPrefabObject(prefabInstance, msgDataItem.PrefabObjectID);
return; 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 // 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); const ScriptingTypeHandle objectType = Scripting::FindScriptingType(rootItem.ObjectTypeName);
obj = ScriptingObject::NewObject(objectType); ScriptingObject* obj = ScriptingObject::NewObject(objectType);
if (!obj) if (!obj)
{ {
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(rootItem.ObjectTypeName)); NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(rootItem.ObjectTypeName));
return; 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 // Setup all newly spawned objects
for (int32 i = 0; i < msgData.ItemsCount; i++) for (int32 i = 0; i < msgData.ItemsCount; i++)
{ {
auto& msgDataItem = msgDataItems[i]; auto& msgDataItem = msgDataItems[i];
if (i != 0) ScriptingObject* obj = objects[i];
{
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;
}
}
if (!obj->IsRegistered()) if (!obj->IsRegistered())
obj->RegisterObject(); obj->RegisterObject();
const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId); const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId);