Fix crashes in various dictionary usages caused by duplicated keys

#1925 #1924
This commit is contained in:
Wojtek Figat
2023-11-16 15:47:42 +01:00
parent f0865c3989
commit bec878cc11
3 changed files with 14 additions and 18 deletions

View File

@@ -253,7 +253,7 @@ void PrefabInstanceData::SerializePrefabInstances(PrefabInstancesData& prefabIns
for (int32 i = 0; i < sceneObjects->Count(); i++) for (int32 i = 0; i < sceneObjects->Count(); i++)
{ {
SceneObject* obj = sceneObjects.Value->At(i); SceneObject* obj = sceneObjects.Value->At(i);
instance.PrefabInstanceIdToDataIndex.Add(obj->GetSceneObjectId(), i); instance.PrefabInstanceIdToDataIndex[obj->GetSceneObjectId()] = i;
} }
} }
tmpBuffer.Clear(); tmpBuffer.Clear();
@@ -313,15 +313,13 @@ bool PrefabInstanceData::SynchronizePrefabInstances(PrefabInstancesData& prefabI
continue; continue;
} }
modifier.Value->IdsMapping.Add(obj->GetPrefabObjectID(), obj->GetSceneObjectId()); modifier.Value->IdsMapping[obj->GetPrefabObjectID()] = obj->GetSceneObjectId();
} }
} }
// Generate new IDs for the added objects (objects in prefab has to have a unique Ids, other than the targetActor instance objects to prevent Id collisions) // Generate new IDs for the added objects (objects in prefab has to have a unique Ids, other than the targetActor instance objects to prevent Id collisions)
for (int32 i = 0; i < newPrefabObjectIds.Count(); i++) for (int32 i = 0; i < newPrefabObjectIds.Count(); i++)
{ modifier->IdsMapping[newPrefabObjectIds[i]] = Guid::New();
modifier->IdsMapping.Add(newPrefabObjectIds[i], Guid::New());
}
// Create new objects added to prefab // Create new objects added to prefab
int32 deserializeSceneObjectIndex = sceneObjects->Count(); int32 deserializeSceneObjectIndex = sceneObjects->Count();
@@ -786,7 +784,7 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr
} }
// Cache connection for fast lookup // Cache connection for fast lookup
diffPrefabObjectIdToDataIndex.Add(obj->GetPrefabObjectID(), i); diffPrefabObjectIdToDataIndex[obj->GetPrefabObjectID()] = i;
// Strip unwanted data // Strip unwanted data
data.RemoveMember("ID"); data.RemoveMember("ID");
@@ -796,7 +794,7 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr
else else
{ {
// Object if a new thing // Object if a new thing
newPrefabInstanceIdToDataIndex.Add(obj->GetSceneObjectId(), i); newPrefabInstanceIdToDataIndex[obj->GetSceneObjectId()] = i;
} }
} }
@@ -836,8 +834,8 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr
for (auto i = newPrefabInstanceIdToDataIndex.Begin(); i.IsNotEnd(); ++i) for (auto i = newPrefabInstanceIdToDataIndex.Begin(); i.IsNotEnd(); ++i)
{ {
const auto prefabObjectId = Guid::New(); const auto prefabObjectId = Guid::New();
newPrefabInstanceIdToPrefabObjectId.Add(i->Key, prefabObjectId); newPrefabInstanceIdToPrefabObjectId[i->Key] = prefabObjectId;
modifier->IdsMapping.Add(i->Key, prefabObjectId); modifier->IdsMapping[i->Key] = prefabObjectId;
} }
// Add inverse IDs mapping to link added objects and references inside them to the prefab objects // Add inverse IDs mapping to link added objects and references inside them to the prefab objects

View File

@@ -374,13 +374,13 @@ bool PrefabManager::CreatePrefab(Actor* targetActor, const StringView& outputPat
if (targetActor->HasParent()) if (targetActor->HasParent())
{ {
// Unlink from parent actor // Unlink from parent actor
objectInstanceIdToPrefabObjectId.Add(targetActor->GetParent()->GetID(), Guid::Empty); objectInstanceIdToPrefabObjectId[targetActor->GetParent()->GetID()] = Guid::Empty;
} }
for (int32 i = 0; i < sceneObjects->Count(); i++) for (int32 i = 0; i < sceneObjects->Count(); i++)
{ {
// Generate new IDs for the prefab objects (other than reference instance used to create prefab) // Generate new IDs for the prefab objects (other than reference instance used to create prefab)
const SceneObject* obj = sceneObjects->At(i); const SceneObject* obj = sceneObjects->At(i);
objectInstanceIdToPrefabObjectId.Add(obj->GetSceneObjectId(), Guid::New()); objectInstanceIdToPrefabObjectId[obj->GetSceneObjectId()] = Guid::New();
} }
{ {
// Parse json to DOM document // Parse json to DOM document

View File

@@ -1026,30 +1026,28 @@ bool Scripting::IsTypeFromGameScripts(MClass* type)
void Scripting::RegisterObject(ScriptingObject* obj) void Scripting::RegisterObject(ScriptingObject* obj)
{ {
const Guid id = obj->GetID();
ScopeLock lock(_objectsLocker); ScopeLock lock(_objectsLocker);
//ASSERT(!_objectsDictionary.ContainsValue(obj)); //ASSERT(!_objectsDictionary.ContainsValue(obj));
#if ENABLE_ASSERTION #if ENABLE_ASSERTION
#if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING #if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING
ScriptingObjectData other; ScriptingObjectData other;
if (_objectsDictionary.TryGet(obj->GetID(), other)) if (_objectsDictionary.TryGet(id, other))
#else #else
ScriptingObject* other; ScriptingObject* other;
if (_objectsDictionary.TryGet(obj->GetID(), other)) if (_objectsDictionary.TryGet(id, other))
#endif #endif
{ {
// Something went wrong... // Something went wrong...
LOG(Error, "Objects registry already contains object with ID={0} (type '{3}')! Trying to register object {1} (type '{2}').", obj->GetID(), obj->ToString(), String(obj->GetClass()->GetFullName()), String(other->GetClass()->GetFullName())); LOG(Error, "Objects registry already contains object with ID={0} (type '{3}')! Trying to register object {1} (type '{2}').", id, obj->ToString(), String(obj->GetClass()->GetFullName()), String(other->GetClass()->GetFullName()));
_objectsDictionary.Remove(obj->GetID());
} }
#else
ASSERT(!_objectsDictionary.ContainsKey(obj->_id));
#endif #endif
#if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING #if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING
LOG(Info, "[RegisterObject] obj = 0x{0:x}, {1}", (uint64)obj, String(ScriptingObjectData(obj).TypeName)); LOG(Info, "[RegisterObject] obj = 0x{0:x}, {1}", (uint64)obj, String(ScriptingObjectData(obj).TypeName));
#endif #endif
_objectsDictionary.Add(obj->GetID(), obj); _objectsDictionary[id] = obj;
} }
void Scripting::UnregisterObject(ScriptingObject* obj) void Scripting::UnregisterObject(ScriptingObject* obj)