@@ -745,7 +745,7 @@ bool NetworkReplicator::InvokeSerializer(const ScriptingTypeHandle& typeHandle,
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkReplicator::AddObject(ScriptingObject* obj, ScriptingObject* parent)
|
||||
void NetworkReplicator::AddObject(ScriptingObject* obj, const ScriptingObject* parent)
|
||||
{
|
||||
if (!obj || NetworkManager::IsOffline())
|
||||
return;
|
||||
@@ -774,6 +774,19 @@ void NetworkReplicator::AddObject(ScriptingObject* obj, ScriptingObject* parent)
|
||||
item.OwnerClientId = NetworkManager::ServerClientId; // Server owns objects by default
|
||||
item.Role = NetworkManager::IsClient() ? NetworkObjectRole::Replicated : NetworkObjectRole::OwnedAuthoritative;
|
||||
NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Add new object {}:{}, parent {}:{}", item.ToString(), obj->GetType().ToString(), item.ParentId.ToString(), parent ? parent->GetType().ToString() : String::Empty);
|
||||
for (const SpawnItem& spawnItem : SpawnQueue)
|
||||
{
|
||||
if (spawnItem.HasOwnership && spawnItem.HierarchicalOwnership)
|
||||
{
|
||||
if (IsParentOf(obj, spawnItem.Object))
|
||||
{
|
||||
// Inherit ownership
|
||||
item.Role = spawnItem.Role;
|
||||
item.OwnerClientId = spawnItem.OwnerClientId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Objects.Add(MoveTemp(item));
|
||||
}
|
||||
|
||||
@@ -864,7 +877,7 @@ void NetworkReplicator::DespawnObject(ScriptingObject* obj)
|
||||
uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj)
|
||||
{
|
||||
uint32 id = NetworkManager::ServerClientId;
|
||||
if (obj)
|
||||
if (obj && NetworkManager::IsConnected())
|
||||
{
|
||||
ScopeLock lock(ObjectsLock);
|
||||
const auto it = Objects.Find(obj->GetID());
|
||||
@@ -896,7 +909,7 @@ uint32 NetworkReplicator::GetObjectOwnerClientId(const ScriptingObject* obj)
|
||||
NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj)
|
||||
{
|
||||
NetworkObjectRole role = NetworkObjectRole::None;
|
||||
if (obj)
|
||||
if (obj && NetworkManager::IsConnected())
|
||||
{
|
||||
ScopeLock lock(ObjectsLock);
|
||||
const auto it = Objects.Find(obj->GetID());
|
||||
@@ -927,10 +940,11 @@ NetworkObjectRole NetworkReplicator::GetObjectRole(const ScriptingObject* obj)
|
||||
|
||||
void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerClientId, NetworkObjectRole localRole, bool hierarchical)
|
||||
{
|
||||
if (!obj)
|
||||
if (!obj || NetworkManager::IsOffline())
|
||||
return;
|
||||
const Guid objectId = obj->GetID();
|
||||
ScopeLock lock(ObjectsLock);
|
||||
const auto it = Objects.Find(obj->GetID());
|
||||
const auto it = Objects.Find(objectId);
|
||||
if (it == Objects.End())
|
||||
{
|
||||
// Special case if we're just spawning this object
|
||||
@@ -958,31 +972,33 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto& item = it->Item;
|
||||
if (item.Object != obj)
|
||||
return;
|
||||
|
||||
// Check if this client is object owner
|
||||
if (item.OwnerClientId == NetworkManager::LocalClientId)
|
||||
{
|
||||
// Check if object owner will change
|
||||
if (item.OwnerClientId != ownerClientId)
|
||||
{
|
||||
// Change role locally
|
||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
||||
item.OwnerClientId = ownerClientId;
|
||||
item.LastOwnerFrame = 1;
|
||||
item.Role = localRole;
|
||||
SendObjectRoleMessage(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow to change local role of the object (except ownership)
|
||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
||||
item.Role = localRole;
|
||||
auto& item = it->Item;
|
||||
if (item.Object != obj)
|
||||
return;
|
||||
|
||||
// Check if this client is object owner
|
||||
if (item.OwnerClientId == NetworkManager::LocalClientId)
|
||||
{
|
||||
// Check if object owner will change
|
||||
if (item.OwnerClientId != ownerClientId)
|
||||
{
|
||||
// Change role locally
|
||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
||||
item.OwnerClientId = ownerClientId;
|
||||
item.LastOwnerFrame = 1;
|
||||
item.Role = localRole;
|
||||
SendObjectRoleMessage(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow to change local role of the object (except ownership)
|
||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
||||
item.Role = localRole;
|
||||
}
|
||||
}
|
||||
|
||||
// Go down hierarchy
|
||||
@@ -990,7 +1006,7 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
|
||||
{
|
||||
for (auto& e : Objects)
|
||||
{
|
||||
if (e.Item.ParentId == item.ObjectId)
|
||||
if (e.Item.ParentId == objectId)
|
||||
SetObjectOwnership(e.Item.Object.Get(), ownerClientId, localRole, hierarchical);
|
||||
}
|
||||
}
|
||||
@@ -1196,9 +1212,11 @@ void NetworkInternal::NetworkReplicatorUpdate()
|
||||
{
|
||||
if (!q.HasOwnership && IsParentOf(q.Object, e.Object))
|
||||
{
|
||||
// Inherit ownership
|
||||
q.HasOwnership = true;
|
||||
q.Role = e.Role;
|
||||
q.OwnerClientId = e.OwnerClientId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1637,7 +1655,7 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
|
||||
}
|
||||
}
|
||||
|
||||
// Setup all newly spawned objects
|
||||
// Add all newly spawned objects
|
||||
for (int32 i = 0; i < msgData.ItemsCount; i++)
|
||||
{
|
||||
auto& msgDataItem = msgDataItems[i];
|
||||
@@ -1666,6 +1684,16 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl
|
||||
// Boost future lookups by using indirection
|
||||
NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", msgDataItem.ObjectId, item.ToString(), obj->GetType().ToString());
|
||||
IdsRemappingTable.Add(msgDataItem.ObjectId, item.ObjectId);
|
||||
}
|
||||
|
||||
// Spawn all newly spawned objects (ensure to have valid ownership hierarchy set before spawning object)
|
||||
for (int32 i = 0; i < msgData.ItemsCount; i++)
|
||||
{
|
||||
auto& msgDataItem = msgDataItems[i];
|
||||
ScriptingObject* obj = objects[i];
|
||||
auto it = Objects.Find(obj->GetID());
|
||||
auto& item = it->Item;
|
||||
const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId);
|
||||
|
||||
// Automatic parenting for scene objects
|
||||
auto sceneObject = ScriptingObject::Cast<SceneObject>(obj);
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
/// <remarks>Does nothing if network is offline.</remarks>
|
||||
/// <param name="obj">The object to replicate.</param>
|
||||
/// <param name="parent">The parent of the object (eg. player that spawned it).</param>
|
||||
API_FUNCTION() static void AddObject(ScriptingObject* obj, ScriptingObject* parent = nullptr);
|
||||
API_FUNCTION() static void AddObject(ScriptingObject* obj, const ScriptingObject* parent = nullptr);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the object from the network replication system.
|
||||
@@ -80,14 +80,14 @@ public:
|
||||
/// <summary>
|
||||
/// Spawns the object to the other clients. Can be spawned by the owner who locally created it (eg. from prefab).
|
||||
/// </summary>
|
||||
/// <remarks>Does nothing if network is offline.</remarks>
|
||||
/// <remarks>Does nothing if network is offline. Doesn't spawn actor in a level - but in network replication system.</remarks>
|
||||
/// <param name="obj">The object to spawn on other clients.</param>
|
||||
API_FUNCTION() static void SpawnObject(ScriptingObject* obj);
|
||||
|
||||
/// <summary>
|
||||
/// Spawns the object to the other clients. Can be spawned by the owner who locally created it (eg. from prefab).
|
||||
/// </summary>
|
||||
/// <remarks>Does nothing if network is offline.</remarks>
|
||||
/// <remarks>Does nothing if network is offline. Doesn't spawn actor in a level - but in network replication system.</remarks>
|
||||
/// <param name="obj">The object to spawn on other clients.</param>
|
||||
/// <param name="clientIds">List with network client IDs that should receive network spawn event. Empty to spawn on all clients.</param>
|
||||
API_FUNCTION() static void SpawnObject(ScriptingObject* obj, const DataContainer<uint32>& clientIds);
|
||||
|
||||
Reference in New Issue
Block a user