| 1052 | } |
| 1053 | |
| 1054 | void InvokeObjectSpawn(const NetworkMessageObjectSpawn& msgData, const Guid& prefabId, const NetworkMessageObjectSpawnItem* msgDataItems) |
| 1055 | { |
| 1056 | ScopeLock lock(ObjectsLock); |
| 1057 | |
| 1058 | // Check if that object has been already spawned |
| 1059 | auto& rootItem = msgDataItems[0]; |
| 1060 | NetworkReplicatedObject* root = ResolveObject(rootItem.ObjectId, rootItem.ParentId, rootItem.ObjectTypeName); |
| 1061 | if (root) |
| 1062 | { |
| 1063 | // Object already exists locally so just synchronize the ownership (and mark as spawned) |
| 1064 | for (int32 i = 0; i < msgData.ItemsCount; i++) |
| 1065 | { |
| 1066 | auto& msgDataItem = msgDataItems[i]; |
| 1067 | NetworkReplicatedObject* e = ResolveObject(msgDataItem.ObjectId, msgDataItem.ParentId, msgDataItem.ObjectTypeName); |
| 1068 | auto& item = *e; |
| 1069 | item.Spawned = true; |
| 1070 | if (NetworkManager::IsClient()) |
| 1071 | { |
| 1072 | // Server always knows the best so update ownership of the existing object |
| 1073 | item.OwnerClientId = msgData.OwnerClientId; |
| 1074 | item.RepCache.Clear(); |
| 1075 | if (item.Role == NetworkObjectRole::OwnedAuthoritative) |
| 1076 | { |
| 1077 | if (Hierarchy) |
| 1078 | Hierarchy->AddObject(item.Object); |
| 1079 | item.Role = NetworkObjectRole::Replicated; |
| 1080 | } |
| 1081 | } |
| 1082 | else if (item.OwnerClientId != msgData.OwnerClientId) |
| 1083 | { |
| 1084 | // Other client spawned object with a different owner |
| 1085 | // TODO: send reply message to inform about proper object ownership that client |
| 1086 | } |
| 1087 | } |
| 1088 | return; |
| 1089 | } |
| 1090 | |
| 1091 | // Recreate object locally (spawn only root) |
| 1092 | Actor* prefabInstance = nullptr; |
| 1093 | Array<ScriptingObject*> objects; |
| 1094 | if (prefabId.IsValid()) |
| 1095 | { |
| 1096 | const NetworkReplicatedObject* parent = ResolveObject(rootItem.ParentId); |
| 1097 | Actor* parentActor = parent && parent->Object && parent->Object->Is<Actor>() ? parent->Object.As<Actor>() : nullptr; |
| 1098 | if (parentActor && parentActor->GetPrefabID() == prefabId) |
| 1099 | { |
| 1100 | // Reuse parent object as prefab instance |
| 1101 | prefabInstance = parentActor; |
| 1102 | } |
| 1103 | else if ((parentActor = Scripting::TryFindObject<Actor>(rootItem.ParentId))) |
| 1104 | { |
| 1105 | // Try to find that spawned prefab (eg. prefab with networked script was spawned before so now we need to link it) |
| 1106 | for (Actor* child : parentActor->Children) |
| 1107 | { |
| 1108 | if (child->GetPrefabID() == prefabId) |
| 1109 | { |
| 1110 | if (Objects.Contains(child->GetID())) |
| 1111 | { |
no test coverage detected