Ticket #4046: EntityMapForComponents.4.patch
File EntityMapForComponents.4.patch, 44.3 KB (added by , 8 years ago) |
---|
-
source/graphics/MapWriter.cpp
326 326 327 327 // This will probably need to be changed in the future, but for now we'll 328 328 // just save all entities that have a position 329 CSimulation2::InterfaceListents = sim.GetEntitiesWithInterface(IID_Position);329 const CSimulation2::InterfaceList& ents = sim.GetEntitiesWithInterface(IID_Position); 330 330 for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 331 331 { 332 332 entity_id_t ent = it->first; -
source/graphics/ObjectManager.cpp
29 29 #include "simulation2/Simulation2.h" 30 30 #include "simulation2/components/ICmpTerrain.h" 31 31 #include "simulation2/components/ICmpVisual.h" 32 #include "simulation2/system/EntityMap.h" 32 33 33 34 34 35 bool CObjectManager::ObjectKey::operator< (const CObjectManager::ObjectKey& a) const … … 197 198 // object with all correct variations, and we don't want to waste space storing it just for the 198 199 // rare occurrence of hotloading, so we'll tell the component (which does preserve the information) 199 200 // to do the reloading itself 200 const CSimulation2::InterfaceList Unordered& cmps = m_Simulation.GetEntitiesWithInterfaceUnordered(IID_Visual);201 for (CSimulation2::InterfaceList Unordered::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit)201 const CSimulation2::InterfaceList& cmps = m_Simulation.GetEntitiesWithInterface(IID_Visual); 202 for (CSimulation2::InterfaceList::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit) 202 203 static_cast<ICmpVisual*>(eit->second)->Hotload(it->first); 203 204 } 204 205 } -
source/gui/MiniMap.cpp
506 506 const float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE); 507 507 const float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE); 508 508 509 CSimulation2::InterfaceListents = sim->GetEntitiesWithInterface(IID_Minimap);509 const CSimulation2::InterfaceList& ents = sim->GetEntitiesWithInterface(IID_Minimap); 510 510 511 511 if (doUpdate) 512 512 { -
source/simulation2/components/CCmpTerritoryManager.cpp
408 408 count = 0; 409 409 410 410 // Find all territory influence entities 411 CComponentManager::InterfaceListinfluences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence);411 const CComponentManager::InterfaceList& influences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence); 412 412 413 413 // Split influence entities into per-player lists, ignoring any with invalid properties 414 414 std::map<player_id_t, std::vector<entity_id_t> > influenceEntities; -
source/simulation2/helpers/Selection.cpp
151 151 } 152 152 else // owner == INVALID_PLAYER; Used when selecting units in Atlas or other mods that allow all kinds of selectables to be selected. 153 153 { 154 const CSimulation2::InterfaceList Unordered& selectableEnts = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);155 for (CSimulation2::InterfaceList Unordered::const_iterator it = selectableEnts.begin(); it != selectableEnts.end(); ++it)154 const CSimulation2::InterfaceList& selectableEnts = simulation.GetEntitiesWithInterface(IID_Selectable); 155 for (CSimulation2::InterfaceList::const_iterator it = selectableEnts.begin(); it != selectableEnts.end(); ++it) 156 156 { 157 157 if (CheckEntityVisibleAndInRect(it->second->GetEntityHandle(), cmpRangeManager, camera, sx0, sy0, sx1, sy1, owner, allowEditorSelectables)) 158 158 hitEnts.push_back(it->first); … … 172 172 173 173 std::vector<entity_id_t> hitEnts; 174 174 175 const CSimulation2::InterfaceList Unordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);176 for (CSimulation2::InterfaceList Unordered::const_iterator it = ents.begin(); it != ents.end(); ++it)175 const CSimulation2::InterfaceList& ents = simulation.GetEntitiesWithInterface(IID_Selectable); 176 for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 177 177 { 178 178 entity_id_t ent = it->first; 179 179 CEntityHandle handle = it->second->GetEntityHandle(); -
source/simulation2/serialization/SerializeTemplates.h
164 164 } 165 165 }; 166 166 167 // We have to order the map before serializing to make things consistent168 template<typename KS, typename VS>169 struct SerializeUnorderedMap170 {171 template<typename K, typename V>172 void operator()(ISerializer& serialize, const char* name, boost::unordered_map<K, V>& value)173 {174 std::map<K, V> ordered_value(value.begin(), value.end());175 SerializeMap<KS, VS>()(serialize, name, ordered_value);176 }177 178 template<typename K, typename V>179 void operator()(IDeserializer& deserialize, const char* name, boost::unordered_map<K, V>& value)180 {181 SerializeMap<KS, VS>()(deserialize, name, value);182 }183 };184 185 167 template<typename T, T max> 186 168 struct SerializeU8_Enum 187 169 { -
source/simulation2/Simulation2.cpp
647 647 m->m_ComponentManager.BroadcastMessage(msg); 648 648 } 649 649 650 CSimulation2::InterfaceListCSimulation2::GetEntitiesWithInterface(int iid)650 const CSimulation2::InterfaceList& CSimulation2::GetEntitiesWithInterface(int iid) 651 651 { 652 652 return m->m_ComponentManager.GetEntitiesWithInterface(iid); 653 653 } 654 654 655 const CSimulation2::InterfaceListUnordered& CSimulation2::GetEntitiesWithInterfaceUnordered(int iid)656 {657 return m->m_ComponentManager.GetEntitiesWithInterfaceUnordered(iid);658 }659 660 655 const CSimContext& CSimulation2::GetSimContext() const 661 656 { 662 657 return m->m_SimContext; -
source/simulation2/Simulation2.h
20 20 21 21 #include "simulation2/system/CmpPtr.h" 22 22 #include "simulation2/system/Components.h" 23 #include "simulation2/system/EntityMap.h" 23 24 #include "simulation2/helpers/SimulationCommand.h" 24 25 #include "scriptinterface/ScriptVal.h" 25 26 26 27 #include "lib/file/vfs/vfs_path.h" 27 28 28 #include <boost/unordered_map.hpp>29 30 29 #include <map> 31 30 32 31 class CSimulation2Impl; … … 202 201 void PostMessage(entity_id_t ent, const CMessage& msg) const; 203 202 void BroadcastMessage(const CMessage& msg) const; 204 203 205 typedef std::vector<std::pair<entity_id_t, IComponent*> > InterfaceList; 206 typedef boost::unordered_map<entity_id_t, IComponent*> InterfaceListUnordered; 204 typedef GlobalEntityMap<IComponent*> InterfaceList; 207 205 208 206 /** 209 207 * Returns a list of components implementing the given interface, and their 210 * associated entities , sorted by entity ID.208 * associated entities. 211 209 */ 212 InterfaceListGetEntitiesWithInterface(int iid);210 const InterfaceList& GetEntitiesWithInterface(int iid); 213 211 214 /**215 * Returns a list of components implementing the given interface, and their216 * associated entities, as an unordered map.217 */218 const InterfaceListUnordered& GetEntitiesWithInterfaceUnordered(int iid);219 220 212 const CSimContext& GetSimContext() const; 221 213 ScriptInterface& GetScriptInterface() const; 222 214 -
source/simulation2/system/ComponentManager.cpp
305 305 { 306 306 // For every script component with this cid, we need to switch its 307 307 // prototype from the old constructor's prototype property to the new one's 308 const std::map<entity_id_t,IComponent*>& comps = componentManager->m_ComponentsByTypeId[cid];309 std::map<entity_id_t,IComponent*>::const_iterator eit = comps.begin();308 const GlobalEntityMap<IComponent*>& comps = componentManager->m_ComponentsByTypeId[cid]; 309 GlobalEntityMap<IComponent*>::const_iterator eit = comps.begin(); 310 310 for (; eit != comps.end(); ++eit) 311 311 { 312 312 JS::RootedValue instance(cx, eit->second->GetJSInstance()); … … 405 405 CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData); 406 406 407 407 std::vector<int> ret; 408 const InterfaceList Unordered& ents = componentManager->GetEntitiesWithInterfaceUnordered(iid);409 for (InterfaceList Unordered::const_iterator it = ents.begin(); it != ents.end(); ++it)408 const InterfaceList& ents = componentManager->GetEntitiesWithInterface(iid); 409 for (InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 410 410 if (!ENTITY_IS_LOCAL(it->first)) 411 411 ret.push_back(it->first); 412 412 std::sort(ret.begin(), ret.end()); … … 418 418 CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData); 419 419 420 420 std::vector<IComponent*> ret; 421 InterfaceListents = componentManager->GetEntitiesWithInterface(iid);421 const InterfaceList& ents = componentManager->GetEntitiesWithInterface(iid); 422 422 for (InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) 423 423 ret.push_back(it->second); // TODO: maybe we should exclude local entities 424 424 return ret; … … 509 509 m_DynamicMessageSubscriptionsNonsyncByComponent.clear(); 510 510 511 511 // Delete all IComponents 512 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::iterator iit = m_ComponentsByTypeId.begin();512 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::iterator iit = m_ComponentsByTypeId.begin(); 513 513 for (; iit != m_ComponentsByTypeId.end(); ++iit) 514 514 { 515 std::map<entity_id_t,IComponent*>::iterator eit = iit->second.begin();515 GlobalEntityMap<IComponent*>::iterator eit = iit->second.begin(); 516 516 for (; eit != iit->second.end(); ++eit) 517 517 { 518 518 eit->second->Deinit(); … … 520 520 } 521 521 } 522 522 523 std::vector< boost::unordered_map<entity_id_t,IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin();523 std::vector<GlobalEntityMap<IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin(); 524 524 for (; ifcit != m_ComponentsByInterface.end(); ++ifcit) 525 525 ifcit->clear(); 526 526 … … 527 527 m_ComponentsByTypeId.clear(); 528 528 529 529 // Delete all SEntityComponentCaches 530 std::map<entity_id_t,SEntityComponentCache*>::iterator ccit = m_ComponentCaches.begin();530 GlobalEntityMap<SEntityComponentCache*>::iterator ccit = m_ComponentCaches.begin(); 531 531 for (; ccit != m_ComponentCaches.end(); ++ccit) 532 532 free(ccit->second); 533 533 m_ComponentCaches.clear(); … … 750 750 751 751 ENSURE((size_t)ct.iid < m_ComponentsByInterface.size()); 752 752 753 boost::unordered_map<entity_id_t,IComponent*>& emap1 = m_ComponentsByInterface[ct.iid];753 GlobalEntityMap<IComponent*>& emap1 = m_ComponentsByInterface[ct.iid]; 754 754 if (emap1.find(ent.GetId()) != emap1.end()) 755 755 { 756 756 LOGERROR("Multiple components for interface %d", ct.iid); … … 757 757 return NULL; 758 758 } 759 759 760 std::map<entity_id_t,IComponent*>& emap2 = m_ComponentsByTypeId[cid];760 GlobalEntityMap<IComponent*>& emap2 = m_ComponentsByTypeId[cid]; 761 761 762 762 // If this is a scripted component, construct the appropriate JS object first 763 763 JS::RootedValue obj(cx); … … 779 779 component->SetSimContext(m_SimContext); 780 780 781 781 // Store a reference to the new component 782 emap1.insert( std::make_pair(ent.GetId(), component));783 emap2.insert( std::make_pair(ent.GetId(), component));782 emap1.insert(ent.GetId(), component); 783 emap2.insert(ent.GetId(), component); 784 784 // TODO: We need to more careful about this - if an entity is constructed by a component 785 785 // while we're iterating over all components, this will invalidate the iterators and everything 786 786 // will break. … … 799 799 // Just add it into the by-interface map, not the by-component-type map, 800 800 // so it won't be considered for messages or deletion etc 801 801 802 boost::unordered_map<entity_id_t,IComponent*>& emap1 = m_ComponentsByInterface.at(iid);802 GlobalEntityMap<IComponent*>& emap1 = m_ComponentsByInterface.at(iid); 803 803 if (emap1.find(ent.GetId()) != emap1.end()) 804 804 debug_warn(L"Multiple components for interface"); 805 emap1.insert( std::make_pair(ent.GetId(), &component));805 emap1.insert(ent.GetId(), &component); 806 806 807 807 SEntityComponentCache* cache = ent.GetComponentCache(); 808 808 ENSURE(cache != NULL && iid < (int)cache->numInterfaces && cache->interfaces[iid] == NULL); … … 819 819 cache->numInterfaces = m_InterfaceIdsByName.size() + 1; 820 820 821 821 ENSURE(m_ComponentCaches.find(ent) == m_ComponentCaches.end()); 822 m_ComponentCaches [ent] = cache;822 m_ComponentCaches.insert(ent, cache); 823 823 824 824 return CEntityHandle(ent, cache); 825 825 } … … 826 826 827 827 CEntityHandle CComponentManager::LookupEntityHandle(entity_id_t ent, bool allowCreate) 828 828 { 829 std::map<entity_id_t, SEntityComponentCache*>::iterator it; 830 it = m_ComponentCaches.find(ent); 829 GlobalEntityMap<SEntityComponentCache*>::iterator it = m_ComponentCaches.find(ent); 831 830 if (it == m_ComponentCaches.end()) 832 831 { 833 832 if (allowCreate) … … 918 917 PostMessage(ent, msg); 919 918 920 919 // Destroy the components, and remove from m_ComponentsByTypeId: 921 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::iterator iit = m_ComponentsByTypeId.begin();920 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::iterator iit = m_ComponentsByTypeId.begin(); 922 921 for (; iit != m_ComponentsByTypeId.end(); ++iit) 923 922 { 924 std::map<entity_id_t,IComponent*>::iterator eit = iit->second.find(ent);923 GlobalEntityMap<IComponent*>::iterator eit = iit->second.find(ent); 925 924 if (eit != iit->second.end()) 926 925 { 927 926 eit->second->Deinit(); … … 936 935 m_ComponentCaches.erase(ent); 937 936 938 937 // Remove from m_ComponentsByInterface 939 std::vector< boost::unordered_map<entity_id_t,IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin();938 std::vector<GlobalEntityMap<IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin(); 940 939 for (; ifcit != m_ComponentsByInterface.end(); ++ifcit) 941 940 { 942 941 ifcit->erase(ent); … … 953 952 return NULL; 954 953 } 955 954 956 boost::unordered_map<entity_id_t,IComponent*>::const_iterator eit = m_ComponentsByInterface[iid].find(ent);955 GlobalEntityMap<IComponent*>::const_iterator eit = m_ComponentsByInterface[iid].find(ent); 957 956 if (eit == m_ComponentsByInterface[iid].end()) 958 957 { 959 958 // This entity doesn't implement this interface … … 963 962 return eit->second; 964 963 } 965 964 966 CComponentManager::InterfaceList CComponentManager::GetEntitiesWithInterface(InterfaceId iid) const 965 static CComponentManager::InterfaceList g_EmptyEntityMap; 966 const CComponentManager::InterfaceList& CComponentManager::GetEntitiesWithInterface(InterfaceId iid) const 967 967 { 968 std::vector<std::pair<entity_id_t, IComponent*> > ret;969 970 968 if ((size_t)iid >= m_ComponentsByInterface.size()) 971 969 { 972 970 // Invalid iid 973 return ret;974 }975 976 ret.reserve(m_ComponentsByInterface[iid].size());977 978 boost::unordered_map<entity_id_t, IComponent*>::const_iterator it = m_ComponentsByInterface[iid].begin();979 for (; it != m_ComponentsByInterface[iid].end(); ++it)980 ret.push_back(*it);981 982 std::sort(ret.begin(), ret.end()); // lexicographic pair comparison means this'll sort by entity ID983 984 return ret;985 }986 987 static CComponentManager::InterfaceListUnordered g_EmptyEntityMap;988 const CComponentManager::InterfaceListUnordered& CComponentManager::GetEntitiesWithInterfaceUnordered(InterfaceId iid) const989 {990 if ((size_t)iid >= m_ComponentsByInterface.size())991 {992 // Invalid iid993 971 return g_EmptyEntityMap; 994 972 } 995 973 … … 1007 985 for (; ctit != it->second.end(); ++ctit) 1008 986 { 1009 987 // Find the component instances of this type (if any) 1010 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit);988 std::map<ComponentTypeId, GlobalEntityMap< IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit); 1011 989 if (emap == m_ComponentsByTypeId.end()) 1012 990 continue; 1013 991 1014 992 // Send the message to all of them 1015 std::map<entity_id_t,IComponent*>::const_iterator eit = emap->second.find(ent);993 GlobalEntityMap<IComponent*>::const_iterator eit = emap->second.find(ent); 1016 994 if (eit != emap->second.end()) 1017 995 eit->second->HandleMessage(msg, false); 1018 996 } … … 1032 1010 for (; ctit != it->second.end(); ++ctit) 1033 1011 { 1034 1012 // Find the component instances of this type (if any) 1035 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit);1013 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit); 1036 1014 if (emap == m_ComponentsByTypeId.end()) 1037 1015 continue; 1038 1016 1039 1017 // Send the message to all of them 1040 std::map<entity_id_t,IComponent*>::const_iterator eit = emap->second.begin();1018 GlobalEntityMap<IComponent*>::const_iterator eit = emap->second.begin(); 1041 1019 for (; eit != emap->second.end(); ++eit) 1042 1020 eit->second->HandleMessage(msg, false); 1043 1021 } … … 1069 1047 } 1070 1048 1071 1049 // Find the component instances of this type (if any) 1072 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit);1050 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit); 1073 1051 if (emap == m_ComponentsByTypeId.end()) 1074 1052 continue; 1075 1053 1076 1054 // Send the message to all of them 1077 std::map<entity_id_t,IComponent*>::const_iterator eit = emap->second.begin();1055 GlobalEntityMap<IComponent*>::const_iterator eit = emap->second.begin(); 1078 1056 for (; eit != emap->second.end(); ++eit) 1079 1057 eit->second->HandleMessage(msg, true); 1080 1058 } -
source/simulation2/system/ComponentManager.h
19 19 #define INCLUDED_COMPONENTMANAGER 20 20 21 21 #include "Entity.h" 22 #include "EntityMap.h" 22 23 #include "Components.h" 23 24 #include "scriptinterface/ScriptInterface.h" 24 25 #include "simulation2/helpers/Player.h" … … 25 26 #include "ps/Filesystem.h" 26 27 27 28 #include <boost/random/linear_congruential.hpp> 28 #include <boost/unordered_map.hpp>29 29 30 30 #include <map> 31 31 … … 270 270 IComponent* QueryInterface(entity_id_t ent, InterfaceId iid) const; 271 271 272 272 typedef std::pair<entity_id_t, IComponent*> InterfacePair; 273 typedef std::vector<InterfacePair> InterfaceList; 274 typedef boost::unordered_map<entity_id_t, IComponent*> InterfaceListUnordered; 273 typedef GlobalEntityMap<IComponent*> InterfaceList; 275 274 276 InterfaceList GetEntitiesWithInterface(InterfaceId iid) const; 277 const InterfaceListUnordered& GetEntitiesWithInterfaceUnordered(InterfaceId iid) const; 275 const InterfaceList& GetEntitiesWithInterface(InterfaceId iid) const; 278 276 279 277 /** 280 278 * Send a message, targeted at a particular entity. The message will be received by any … … 354 352 // TODO: some of these should be vectors 355 353 std::map<ComponentTypeId, ComponentType> m_ComponentTypesById; 356 354 std::vector<CComponentManager::ComponentTypeId> m_ScriptedSystemComponents; 357 std::vector< boost::unordered_map<entity_id_t,IComponent*> > m_ComponentsByInterface; // indexed by InterfaceId358 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> > m_ComponentsByTypeId;355 std::vector<GlobalEntityMap<IComponent*> > m_ComponentsByInterface; // indexed by InterfaceId 356 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> > m_ComponentsByTypeId; 359 357 std::map<MessageTypeId, std::vector<ComponentTypeId> > m_LocalMessageSubscriptions; 360 358 std::map<MessageTypeId, std::vector<ComponentTypeId> > m_GlobalMessageSubscriptions; 361 359 std::map<std::string, ComponentTypeId> m_ComponentTypeIdsByName; … … 366 364 std::map<MessageTypeId, CDynamicSubscription> m_DynamicMessageSubscriptionsNonsync; 367 365 std::map<IComponent*, std::set<MessageTypeId> > m_DynamicMessageSubscriptionsNonsyncByComponent; 368 366 369 std::map<entity_id_t,SEntityComponentCache*> m_ComponentCaches;367 GlobalEntityMap<SEntityComponentCache*> m_ComponentCaches; 370 368 371 369 // TODO: maintaining both ComponentsBy* is nasty; can we get rid of one, 372 370 // while keeping QueryInterface and PostMessage sufficiently efficient? -
source/simulation2/system/ComponentManagerSerialization.cpp
18 18 #include "precompiled.h" 19 19 20 20 #include "ComponentManager.h" 21 #include "EntityMap.h" 21 22 #include "IComponent.h" 22 23 #include "ParamNode.h" 23 24 … … 58 59 std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> > components; 59 60 //std::map<ComponentTypeId, std::string> names; 60 61 61 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator ctit = m_ComponentsByTypeId.begin();62 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator ctit = m_ComponentsByTypeId.begin(); 62 63 for (; ctit != m_ComponentsByTypeId.end(); ++ctit) 63 64 { 64 std::map<entity_id_t,IComponent*>::const_iterator eit = ctit->second.begin();65 GlobalEntityMap<IComponent*>::const_iterator eit = ctit->second.begin(); 65 66 for (; eit != ctit->second.end(); ++eit) 66 67 { 67 68 components[eit->first][ctit->first] = eit->second; … … 109 110 serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); 110 111 serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); 111 112 112 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin();113 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin(); 113 114 for (; cit != m_ComponentsByTypeId.end(); ++cit) 114 115 { 115 116 // In quick mode, only check unit positions … … 118 119 119 120 // Only emit component types if they have a component that will be serialized 120 121 bool needsSerialization = false; 121 for ( std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)122 for (GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) 122 123 { 123 124 // Don't serialize local entities 124 125 if (ENTITY_IS_LOCAL(eit->first)) … … 133 134 134 135 serializer.NumberI32_Unbounded("component type id", cit->first); 135 136 136 for ( std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)137 for (GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) 137 138 { 138 139 // Don't serialize local entities 139 140 if (ENTITY_IS_LOCAL(eit->first)) … … 188 189 serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); 189 190 serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); 190 191 191 std::map<ComponentTypeId, std::map<entity_id_t,IComponent*> >::const_iterator cit;192 std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator cit; 192 193 193 194 uint32_t numSystemComponentTypes = 0; 194 195 uint32_t numComponentTypes = 0; … … 199 200 { 200 201 // Only emit component types if they have a component that will be serialized 201 202 bool needsSerialization = false; 202 for ( std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)203 for (GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) 203 204 { 204 205 // Don't serialize local entities, and handle SYSTEM_ENTITY separately 205 206 if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) … … 238 239 239 240 serializer.StringASCII("name", ctit->second.name, 0, 255); 240 241 241 std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.find(SYSTEM_ENTITY);242 GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.find(SYSTEM_ENTITY); 242 243 if (eit == cit->second.end()) 243 244 { 244 245 debug_warn(L"Invalid eit"); // this should never happen … … 265 266 266 267 // Count the components before serializing any of them 267 268 uint32_t numComponents = 0; 268 for ( std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)269 for (GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) 269 270 { 270 271 // Don't serialize local entities or SYSTEM_ENTITY 271 272 if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) … … 278 279 serializer.NumberU32_Unbounded("num components", numComponents); 279 280 280 281 // Serialize the components now 281 for ( std::map<entity_id_t,IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)282 for (GlobalEntityMap<IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) 282 283 { 283 284 // Don't serialize local entities or SYSTEM_ENTITY 284 285 if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) -
source/simulation2/system/EntityMap.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 18 18 #define INCLUDED_ENTITYMAP 19 19 20 20 #include "Entity.h" 21 #include "simulation2/serialization/ISerializer.h" 22 #include "simulation2/serialization/IDeserializer.h" 21 23 22 24 /** 23 25 * A fast replacement for map<entity_id_t, T>. … … 28 30 */ 29 31 template<class T> class EntityMap 30 32 { 31 private: 32 EntityMap(const EntityMap&); // non-copyable 33 EntityMap& operator=(const EntityMap&); // non-copyable 33 public: 34 EntityMap(const EntityMap&) = delete; 35 EntityMap& operator=(const EntityMap&) = delete; 36 EntityMap(EntityMap&& o) 37 { 38 m_BufferSize = o.m_BufferSize; 39 m_BufferCapacity = o.m_BufferCapacity; 40 m_Buffer = o.m_Buffer; 41 m_FirstEntityID = o.m_FirstEntityID; 42 m_Count = o.m_Count; 43 44 o.m_Buffer = nullptr; 45 } 46 EntityMap& operator=(EntityMap&& o) 47 { 48 if (this != &o) 49 { 50 free(m_Buffer); 34 51 35 public: 52 m_BufferSize = o.m_BufferSize; 53 m_BufferCapacity = o.m_BufferCapacity; 54 m_Buffer = o.m_Buffer; 55 m_FirstEntityID = o.m_FirstEntityID; 56 m_Count = o.m_Count; 57 58 o.m_Buffer = nullptr; 59 } 60 return *this; 61 } 36 62 typedef entity_id_t key_type; 37 63 typedef T mapped_type; 38 64 template<class K, class V> struct key_val { … … 40 66 typedef V second_type; 41 67 K first; 42 68 V second; 69 void operator=(const std::pair<K, V> o) 70 { 71 first = o.first; 72 second = o.second; 73 }; 74 operator std::pair<K, V>() { return std::make_pair(first, second); }; 75 operator std::pair<K, V>() const { return std::make_pair(first, second); }; 43 76 }; 44 77 typedef key_val<entity_id_t, T> value_type; 45 78 … … 48 81 size_t m_BufferCapacity; // capacity of the buffer 49 82 value_type* m_Buffer; // vector with all the mapped key-value pairs 50 83 84 size_t m_FirstEntityID; // real ID of the [0] in the buffer, so we can offset. 51 85 size_t m_Count; // number of 'valid' entity id's 52 86 53 87 public: 54 88 55 inline EntityMap() : m_BufferSize( 1), m_BufferCapacity(4096), m_Count(0)89 inline EntityMap() : m_BufferSize(0), m_BufferCapacity(4096), m_Count(0), m_FirstEntityID(1) 56 90 { 57 91 // for entitymap we allocate the buffer right away 58 92 // with first element in buffer being the Invalid Entity 59 93 m_Buffer = (value_type*)malloc(sizeof(value_type) * (m_BufferCapacity + 1)); 60 94 61 // create the first element: 62 m_Buffer[0].first = INVALID_ENTITY; 63 m_Buffer[1].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF 95 m_Buffer[0].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF 64 96 } 97 inline EntityMap(size_t ID) : EntityMap() 98 { 99 m_FirstEntityID = ID; 100 } 101 65 102 inline ~EntityMap() 66 103 { 67 104 free(m_Buffer); … … 97 134 98 135 inline iterator begin() 99 136 { 100 value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY137 value_type* ptr = m_Buffer; 101 138 while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities 102 139 return ptr; 103 140 } … … 107 144 } 108 145 inline const_iterator begin() const 109 146 { 110 value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY147 value_type* ptr = m_Buffer; 111 148 while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities 112 149 return ptr; 113 150 } … … 121 158 inline size_t size() const { return m_Count; } 122 159 123 160 // Modification 124 void insert(const key_type key, const mapped_type& value)161 void insert(const key_type actual_key, const mapped_type& value) 125 162 { 163 key_type key = actual_key - m_FirstEntityID; 126 164 if (key >= m_BufferCapacity) // do we need to resize buffer? 127 165 { 128 166 size_t newCapacity = m_BufferCapacity + 4096; … … 143 181 fill_gaps: 144 182 // set all entity id's to INVALID_ENTITY inside the new range 145 183 for (size_t i = m_BufferSize; i <= key; ++i) 184 { 146 185 m_Buffer[i].first = INVALID_ENTITY; 186 new (&m_Buffer[i].second) mapped_type(); 187 } 147 188 m_BufferSize = key; // extend the new size 148 189 } 149 190 150 191 value_type& item = m_Buffer[key]; 151 192 key_type oldKey = item.first; 152 item.first = key;193 item.first = actual_key; 153 194 if (key == m_BufferSize) // push_back 154 195 { 155 196 ++m_BufferSize; // expand … … 157 198 new (&item.second) mapped_type(value); // copy ctor to init 158 199 m_Buffer[m_BufferSize].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF 159 200 } 160 else if(!item.first) // insert new to middle161 {162 ++m_Count;163 new (&item.second) mapped_type(value); // copy ctor to init164 }165 201 else // set existing value 166 202 { 167 203 if (oldKey == INVALID_ENTITY) 168 204 m_Count++; 169 item.second = value; // overwrite existing205 item.second = value; 170 206 } 171 207 } 172 208 … … 182 218 } 183 219 void erase(const entity_id_t key) 184 220 { 185 if (key < m_BufferSize)221 if (key - m_FirstEntityID < m_BufferSize) 186 222 { 187 value_type* ptr = m_Buffer + key ;223 value_type* ptr = m_Buffer + key - m_FirstEntityID; 188 224 if (ptr->first != INVALID_ENTITY) 189 225 { 190 226 ptr->first = INVALID_ENTITY; … … 210 246 } 211 247 212 248 // Operations 249 inline value_type& operator[](const entity_id_t key) 250 { 251 return m_Buffer[key - m_FirstEntityID]; 252 }; 253 inline const value_type& operator[](const entity_id_t key) const 254 { 255 return m_Buffer[key - m_FirstEntityID]; 256 }; 213 257 inline iterator find(const entity_id_t key) 214 258 { 215 if (key < m_BufferSize) // is this key in the range of existing entitites?259 if (key - m_FirstEntityID >= 0 && key - m_FirstEntityID < m_BufferSize) // is this key in the range of existing entitites? 216 260 { 217 value_type* ptr = m_Buffer + key ;261 value_type* ptr = m_Buffer + key - m_FirstEntityID; 218 262 if (ptr->first != INVALID_ENTITY) 219 263 return ptr; 220 264 } … … 222 266 } 223 267 inline const_iterator find(const entity_id_t key) const 224 268 { 225 if (key < m_BufferSize) // is this key in the range of existing entitites?269 if (key - m_FirstEntityID >= 0 && key - m_FirstEntityID < m_BufferSize) // is this key in the range of existing entitites? 226 270 { 227 const value_type* ptr = m_Buffer + key ;271 const value_type* ptr = m_Buffer + key - m_FirstEntityID; 228 272 if (ptr->first != INVALID_ENTITY) 229 273 return ptr; 230 274 } … … 232 276 } 233 277 inline size_t count(const entity_id_t key) const 234 278 { 235 if (key < m_BufferSize)279 if (key - m_FirstEntityID >= 0 && key - m_FirstEntityID < m_BufferSize) 236 280 { 237 if (m_Buffer[key ].first != INVALID_ENTITY)281 if (m_Buffer[key - m_FirstEntityID].first != INVALID_ENTITY) 238 282 return 1; 239 283 } 240 284 return 0; … … 278 322 } 279 323 }; 280 324 325 //Implements the same interface as EntityMap but uses two internally to separate local entities 326 template<class T> 327 class GlobalEntityMap 328 { 329 public: 330 GlobalEntityMap(const GlobalEntityMap&) = delete; 331 GlobalEntityMap& operator=(const GlobalEntityMap&) = delete; 332 GlobalEntityMap(GlobalEntityMap&& o) : m_Entities(std::move(o.m_Entities)), 333 m_LocalEntities(std::move(o.m_LocalEntities)) {} 334 GlobalEntityMap& operator=(GlobalEntityMap&& o) 335 { 336 if (this != &o) 337 { 338 m_Entities = o.m_Entities; 339 m_LocalEntities = o.m_LocalEntities; 340 } 341 return *this; 342 } 343 344 EntityMap<T> m_Entities; 345 EntityMap<T> m_LocalEntities; 281 346 347 inline GlobalEntityMap() : m_LocalEntities(ENTITY_TAGMASK) {} 348 349 typedef typename EntityMap<T>::mapped_type mapped_type; 350 typedef typename EntityMap<T>::key_type key_type; 351 typedef typename EntityMap<T>::value_type value_type; 352 353 // iterator aware of GlobalEntityMap to jump between the two vectors 354 template<class U, class V, class W> struct _iter : public std::iterator<std::forward_iterator_tag, U> 355 { 356 U* val; 357 V* orig; 358 inline _iter(V* mapInit) : orig(mapInit), val(orig.begin()) {} 359 inline _iter(V* mapInit, U* init) : orig(mapInit), val(init) {} 360 inline _iter(V* mapInit, W& init) : orig(mapInit), val(&*init) {} 361 inline U& operator*() { return *val; } 362 inline U* operator->() { return val; } 363 inline _iter& operator++() // ++it 364 { 365 ++val; 366 while (val->first == INVALID_ENTITY) ++val; 367 auto end = &*orig->m_Entities.end(); 368 auto toto = &*orig->m_LocalEntities.begin(); 369 auto realtoto = &*orig->m_LocalEntities.end(); 370 if (val == &*orig->m_Entities.end()) 371 val = &*orig->m_LocalEntities.begin(); 372 while (val->first == INVALID_ENTITY) ++val; 373 return *this; 374 } 375 inline _iter& operator++(int) // it++ 376 { 377 U* ptr = val; 378 ++val; 379 while (val->first == INVALID_ENTITY) ++val; // skip any invalid entities 380 if (val == &*orig->m_Entities.end()) 381 val = &*orig->m_LocalEntities.begin(); 382 while (val->first == INVALID_ENTITY) ++val; 383 return ptr; 384 } 385 inline bool operator==(_iter other) { return val == other.val; } 386 inline bool operator!=(_iter other) { return val != other.val; } 387 inline operator _iter<U const, V const, W const>() const { return _iter<U const, V const, W const>(orig, val); } 388 }; 389 390 typedef _iter<value_type, GlobalEntityMap, typename EntityMap<T>::iterator> iterator; 391 typedef _iter<value_type const, GlobalEntityMap const, typename EntityMap<T>::const_iterator> const_iterator; 392 393 inline iterator begin() 394 { 395 if (m_Entities.empty()) 396 return iterator(this, m_LocalEntities.begin()); 397 return iterator(this, m_Entities.begin()); 398 } 399 inline iterator end() 400 { 401 return iterator(this, m_LocalEntities.end()); 402 } 403 inline const_iterator begin() const 404 { 405 if (m_Entities.empty()) 406 return const_iterator(this, m_LocalEntities.begin()); 407 return const_iterator(this, m_Entities.begin()); 408 } 409 inline const_iterator end() const 410 { 411 return const_iterator(this, m_LocalEntities.end()); 412 } 413 414 // Size 415 inline bool empty() const { return m_Entities.empty() && m_LocalEntities.empty(); } 416 inline size_t size() const { return m_Entities.size() + m_LocalEntities.size(); } 417 418 // Modification 419 void insert(const key_type key, const mapped_type& value) 420 { 421 if (key < ENTITY_TAGMASK) 422 m_Entities.insert(key, value); 423 else 424 m_LocalEntities.insert(key, value); 425 } 426 427 void erase(iterator it) 428 { 429 if ((*it)->first < ENTITY_TAGMASK) 430 m_Entities.erase(it); 431 else 432 m_LocalEntities.erase(it); 433 } 434 void erase(const entity_id_t key) 435 { 436 if (key < ENTITY_TAGMASK) 437 m_Entities.erase(key); 438 else 439 m_LocalEntities.erase(key); 440 } 441 inline void clear() 442 { 443 m_Entities.clear(); 444 m_LocalEntities.clear(); 445 } 446 447 // Operations 448 inline value_type& operator[](const entity_id_t key) 449 { 450 if (key < ENTITY_TAGMASK) 451 return m_Entities[key]; 452 else 453 return m_LocalEntities[key]; 454 }; 455 inline const value_type& operator[](const entity_id_t key) const 456 { 457 if (key < ENTITY_TAGMASK) 458 return m_Entities[key]; 459 else 460 return m_LocalEntities[key]; 461 }; 462 inline iterator find(const entity_id_t key) 463 { 464 if (key < ENTITY_TAGMASK) 465 { 466 iterator ret(this, m_Entities.find(key)); 467 if (&*ret == &*m_Entities.end()) 468 return end(); 469 return ret; 470 } 471 else 472 return iterator(this, m_LocalEntities.find(key)); 473 } 474 inline const_iterator find(const entity_id_t key) const 475 { 476 if (key < ENTITY_TAGMASK) 477 { 478 const_iterator ret(this, m_Entities.find(key)); 479 if (&*ret == &*m_Entities.end()) 480 return end(); 481 return ret; 482 } 483 else 484 return const_iterator(this, m_LocalEntities.find(key)); 485 } 486 inline size_t count(const entity_id_t key) const 487 { 488 if (key < ENTITY_TAGMASK) 489 return m_Entities.count(key); 490 else 491 return m_LocalEntities.count(key); 492 } 493 }; 494 282 495 #endif -
source/simulation2/tests/test_EntityMap.h
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "lib/self_test.h" 19 20 #include <array> 21 #include "simulation2/system/EntityMap.h" 22 23 #include <iostream> 24 25 // Test the EntityMap container using the GlobalEntityMap, which uses EntityMap internally. 26 class TestEntityMap : public CxxTest::TestSuite 27 { 28 GlobalEntityMap<int* > map; 29 std::vector<int> verif; 30 31 void clear() 32 { 33 map.clear(); 34 verif.clear(); 35 } 36 public: 37 void test_TestClear() 38 { 39 for (size_t i = 1; i <= 20; ++i) 40 map.insert(i, verif.data()); 41 map.clear(); 42 TS_ASSERT_EQUALS(map.size(), 0); 43 TS_ASSERT_EQUALS(map.begin(), map.end()) 44 } 45 46 void test_TestInsert() 47 { 48 clear(); 49 // insert items in key positions and verify they are retrieved correctly 50 // I don't actually care about the values, so store pointers in the EntityMap 51 verif = std::vector<int>(20); 52 53 for (size_t i = 1; i <= 20; ++i) 54 map.insert(i, verif.data() + i); 55 56 TS_ASSERT_EQUALS(map.size(), 20); 57 58 for (size_t i = 1; i <= 20; ++i) 59 TS_ASSERT_EQUALS(map[i].second, verif.data() + i); 60 61 map.insert(1, verif.data()); 62 map.insert(5, verif.data() + 1); 63 map.insert(1500, verif.data() + 2); 64 65 TS_ASSERT_EQUALS(map[1].second, verif.data()); 66 TS_ASSERT_EQUALS(map[5].second, verif.data() + 1); 67 TS_ASSERT_EQUALS(map[1500].second, verif.data() + 2); 68 69 TS_ASSERT_EQUALS(map[1].first, 1); 70 TS_ASSERT_EQUALS(map[5].first, 5); 71 TS_ASSERT_EQUALS(map[1500].first, 1500); 72 73 // check that we properly pad 74 TS_ASSERT_EQUALS(map[1300].first, INVALID_ENTITY); 75 } 76 void test_TestLargeInsert() 77 { 78 clear(); 79 verif = std::vector<int>(21); 80 81 for (size_t i = 1; i <= 10; ++i) 82 map.insert(i, verif.data() + i); 83 84 for (size_t i = 11; i <= 20; ++i) 85 map.insert(i + ENTITY_TAGMASK, verif.data() + i); 86 87 TS_ASSERT_EQUALS(map.size(), 20); 88 89 for (size_t i = 1; i <= 10; ++i) 90 TS_ASSERT_EQUALS(map[i].second, verif.data() + i); 91 for (size_t i = 11; i <= 20; ++i) 92 TS_ASSERT_EQUALS(map[i + ENTITY_TAGMASK].second, verif.data() + i); 93 } 94 void test_TestIter() 95 { 96 clear(); 97 98 // verify the returned iterators 99 verif = std::vector<int>(20); 100 101 for (size_t i = 1; i < 10; i++) 102 map.insert(i, verif.data() + i-1); 103 for (size_t i = 10; i < 20; i++) 104 map.insert(i + ENTITY_TAGMASK, verif.data() + i - 1); 105 106 TS_ASSERT_EQUALS(map.begin()->second, verif.data()); 107 TS_ASSERT_EQUALS(map.end()->first, 0xFFFFFFFF); 108 109 size_t i = 0; 110 auto it = map.begin(); 111 for (; it != map.end(); ++it) 112 { 113 TS_ASSERT_EQUALS(it->second, verif.data() + i); 114 i++; 115 } 116 TS_ASSERT_EQUALS(i, map.size()) 117 } 118 void test_TestID() 119 { 120 clear(); 121 verif = std::vector<int>(20); 122 123 for (size_t i = 1; i <= 10; ++i) 124 map.insert(i, verif.data()); 125 126 for (size_t i = 11; i <= 20; ++i) 127 map.insert(i + ENTITY_TAGMASK, verif.data()); 128 129 TS_ASSERT_EQUALS(map.begin()->second, verif.data()); 130 TS_ASSERT_EQUALS(map.end()->first, 0xFFFFFFFF); 131 132 size_t i = 1; 133 auto it = map.begin(); 134 for (; it != map.end(); ++it) 135 { 136 TS_ASSERT_EQUALS(it->first, i); 137 i++; 138 if (i == 11) 139 i += ENTITY_TAGMASK; 140 } 141 } 142 void test_TestFind() 143 { 144 clear(); 145 verif = std::vector<int>(20); 146 147 map.insert(5, verif.data()); 148 map.insert(10, verif.data()+5); 149 map.insert(50, verif.data() + 1); 150 map.insert(ENTITY_TAGMASK + 5, verif.data()+2); 151 map.insert(ENTITY_TAGMASK + 50, verif.data()+3); 152 153 TS_ASSERT_EQUALS(map.find(5)->second, verif.data()); 154 TS_ASSERT_EQUALS(map[5].second, verif.data()); 155 TS_ASSERT_EQUALS(map.find(50)->second, verif.data()+1); 156 TS_ASSERT_EQUALS(map[50].second, verif.data() + 1); 157 TS_ASSERT_EQUALS(map.find(40), map.end()); 158 159 TS_ASSERT_EQUALS(map.find(5 + ENTITY_TAGMASK)->second, verif.data()+2); 160 TS_ASSERT_EQUALS(map[5 + ENTITY_TAGMASK].second, verif.data() + 2); 161 TS_ASSERT_EQUALS(map.find(50 + ENTITY_TAGMASK)->second, verif.data()+3); 162 TS_ASSERT_EQUALS(map[50 + ENTITY_TAGMASK].second, verif.data() + 3); 163 TS_ASSERT_EQUALS(map.find(40 + ENTITY_TAGMASK), map.end()); 164 165 TS_ASSERT_EQUALS(map.find(-5), map.end()); 166 } 167 168 void test_TestErase() 169 { 170 clear(); 171 verif = std::vector<int>(21); 172 173 for (size_t i = 1; i <= 10; ++i) 174 map.insert(i, verif.data() + i); 175 176 for (size_t i = 11; i <= 20; ++i) 177 map.insert(i + ENTITY_TAGMASK, verif.data() + i); 178 179 map.erase(5); 180 map.erase(6); 181 map.erase(5); 182 map.erase(5 + ENTITY_TAGMASK); 183 184 TS_ASSERT_EQUALS(map.find(5), map.end()); 185 TS_ASSERT_EQUALS(map.find(6), map.end()); 186 TS_ASSERT_EQUALS(map.find(5 + ENTITY_TAGMASK), map.end()); 187 } 188 189 void test_TestAssign() 190 { 191 clear(); 192 verif = std::vector<int>(21); 193 194 map.insert(5, verif.data()); 195 map.insert(6, verif.data()); 196 map.insert(150, verif.data()); 197 198 map.insert(150 + ENTITY_TAGMASK, verif.data()); 199 200 TS_ASSERT_EQUALS(map[5].second, verif.data()); 201 map[5] = std::make_pair(8, nullptr); 202 TS_ASSERT_EQUALS(map[5].first, 8); 203 TS_ASSERT_EQUALS(map[5].second, nullptr); 204 map[5].first = 4; 205 TS_ASSERT_EQUALS(map[5].first, 4); 206 207 TS_ASSERT_EQUALS(map[150 + ENTITY_TAGMASK].second, verif.data()); 208 map[150 + ENTITY_TAGMASK] = std::make_pair(8, nullptr); 209 TS_ASSERT_EQUALS(map[150 + ENTITY_TAGMASK].first, 8); 210 TS_ASSERT_EQUALS(map[150 + ENTITY_TAGMASK].second, nullptr); 211 map[150 + ENTITY_TAGMASK].first = 4; 212 TS_ASSERT_EQUALS(map[150 + ENTITY_TAGMASK].first, 4); 213 214 }}; -
source/tools/atlas/GameInterface/DeltaArray.h
18 18 #ifndef INCLUDED_DELTAARRAY 19 19 #define INCLUDED_DELTAARRAY 20 20 21 #include <boost/unordered_map.hpp> 22 21 23 template<typename T> class DeltaArray2D 22 24 { 23 25 public: -
source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
50 50 #include "simulation2/components/ICmpTemplateManager.h" 51 51 #include "simulation2/components/ICmpVisual.h" 52 52 #include "simulation2/helpers/Selection.h" 53 #include "simulation2/system/EntityMap.h" 53 54 #include "ps/XML/XMLWriter.h" 54 55 55 56 namespace AtlasMessage { … … 1106 1107 std::vector<entity_id_t> ids; 1107 1108 player_id_t playerID = msg->player; 1108 1109 1109 const CSimulation2::InterfaceList Unordered& cmps = g_Game->GetSimulation2()->GetEntitiesWithInterfaceUnordered(IID_Ownership);1110 for (CSimulation2::InterfaceList Unordered::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit)1110 const CSimulation2::InterfaceList& cmps = g_Game->GetSimulation2()->GetEntitiesWithInterface(IID_Ownership); 1111 for (CSimulation2::InterfaceList::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit) 1111 1112 { 1112 1113 if (static_cast<ICmpOwnership*>(eit->second)->GetOwner() == playerID) 1113 1114 {