Index: ps/trunk/source/simulation2/system/ComponentManager.h =================================================================== --- ps/trunk/source/simulation2/system/ComponentManager.h +++ ps/trunk/source/simulation2/system/ComponentManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -197,6 +197,11 @@ CEntityHandle LookupEntityHandle(entity_id_t ent, bool allowCreate = false); /** + * Returns true if the entity with id @p ent exists. + */ + bool EntityExists(entity_id_t ent) const; + + /** * Returns a new entity ID that has never been used before. * This affects the simulation state so it must only be called in network-synchronised ways. */ Index: ps/trunk/source/simulation2/system/ComponentManager.cpp =================================================================== --- ps/trunk/source/simulation2/system/ComponentManager.cpp +++ ps/trunk/source/simulation2/system/ComponentManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -816,6 +816,8 @@ CEntityHandle CComponentManager::AllocateEntityHandle(entity_id_t ent) { + ENSURE(!EntityExists(ent)); + // Interface IDs start at 1, and SEntityComponentCache is defined with a 1-sized array, // so we need space for an extra m_InterfaceIdsByName.size() items SEntityComponentCache* cache = (SEntityComponentCache*)calloc(1, @@ -823,7 +825,6 @@ ENSURE(cache != NULL); cache->numInterfaces = m_InterfaceIdsByName.size() + 1; - ENSURE(m_ComponentCaches.find(ent) == m_ComponentCaches.end()); m_ComponentCaches[ent] = cache; return CEntityHandle(ent, cache); @@ -896,6 +897,12 @@ return ent; } +bool CComponentManager::EntityExists(entity_id_t ent) const +{ + return m_ComponentCaches.find(ent) != m_ComponentCaches.end(); +} + + void CComponentManager::DestroyComponentsSoon(entity_id_t ent) { m_DestructionQueue.push_back(ent); @@ -914,6 +921,11 @@ for (std::vector::iterator it = queue.begin(); it != queue.end(); ++it) { entity_id_t ent = *it; + + // Do nothing if invalid, destroyed, etc. + if (!EntityExists(ent)) + continue; + CEntityHandle handle = LookupEntityHandle(ent); CMessageDestroy msg(ent);