Ticket #4046: EntityMapForComponents.4.patch

File EntityMapForComponents.4.patch, 44.3 KB (added by wraitii, 8 years ago)

RC

  • source/graphics/MapWriter.cpp

     
    326326
    327327            // This will probably need to be changed in the future, but for now we'll
    328328            // just save all entities that have a position
    329             CSimulation2::InterfaceList ents = sim.GetEntitiesWithInterface(IID_Position);
     329            const CSimulation2::InterfaceList& ents = sim.GetEntitiesWithInterface(IID_Position);
    330330            for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
    331331            {
    332332                entity_id_t ent = it->first;
  • source/graphics/ObjectManager.cpp

     
    2929#include "simulation2/Simulation2.h"
    3030#include "simulation2/components/ICmpTerrain.h"
    3131#include "simulation2/components/ICmpVisual.h"
     32#include "simulation2/system/EntityMap.h"
    3233
    3334
    3435bool CObjectManager::ObjectKey::operator< (const CObjectManager::ObjectKey& a) const
     
    197198            // object with all correct variations, and we don't want to waste space storing it just for the
    198199            // rare occurrence of hotloading, so we'll tell the component (which does preserve the information)
    199200            // to do the reloading itself
    200             const CSimulation2::InterfaceListUnordered& cmps = m_Simulation.GetEntitiesWithInterfaceUnordered(IID_Visual);
    201             for (CSimulation2::InterfaceListUnordered::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)
    202203                static_cast<ICmpVisual*>(eit->second)->Hotload(it->first);
    203204        }
    204205    }
  • source/gui/MiniMap.cpp

     
    506506    const float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
    507507    const float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
    508508
    509     CSimulation2::InterfaceList ents = sim->GetEntitiesWithInterface(IID_Minimap);
     509    const CSimulation2::InterfaceList& ents = sim->GetEntitiesWithInterface(IID_Minimap);
    510510
    511511    if (doUpdate)
    512512    {
  • source/simulation2/components/CCmpTerritoryManager.cpp

     
    408408        count = 0;
    409409
    410410    // Find all territory influence entities
    411     CComponentManager::InterfaceList influences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence);
     411    const CComponentManager::InterfaceList& influences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence);
    412412
    413413    // Split influence entities into per-player lists, ignoring any with invalid properties
    414414    std::map<player_id_t, std::vector<entity_id_t> > influenceEntities;
  • source/simulation2/helpers/Selection.cpp

     
    151151    }
    152152    else // owner == INVALID_PLAYER; Used when selecting units in Atlas or other mods that allow all kinds of selectables to be selected.
    153153    {
    154         const CSimulation2::InterfaceListUnordered& selectableEnts = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
    155         for (CSimulation2::InterfaceListUnordered::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)
    156156        {
    157157            if (CheckEntityVisibleAndInRect(it->second->GetEntityHandle(), cmpRangeManager, camera, sx0, sy0, sx1, sy1, owner, allowEditorSelectables))
    158158                hitEnts.push_back(it->first);
     
    172172
    173173    std::vector<entity_id_t> hitEnts;
    174174
    175     const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
    176     for (CSimulation2::InterfaceListUnordered::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)
    177177    {
    178178        entity_id_t ent = it->first;
    179179        CEntityHandle handle = it->second->GetEntityHandle();
  • source/simulation2/serialization/SerializeTemplates.h

     
    164164    }
    165165};
    166166
    167 // We have to order the map before serializing to make things consistent
    168 template<typename KS, typename VS>
    169 struct SerializeUnorderedMap
    170 {
    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 
    185167template<typename T, T max>
    186168struct SerializeU8_Enum
    187169{
  • source/simulation2/Simulation2.cpp

     
    647647    m->m_ComponentManager.BroadcastMessage(msg);
    648648}
    649649
    650 CSimulation2::InterfaceList CSimulation2::GetEntitiesWithInterface(int iid)
     650const CSimulation2::InterfaceList& CSimulation2::GetEntitiesWithInterface(int iid)
    651651{
    652652    return m->m_ComponentManager.GetEntitiesWithInterface(iid);
    653653}
    654654
    655 const CSimulation2::InterfaceListUnordered& CSimulation2::GetEntitiesWithInterfaceUnordered(int iid)
    656 {
    657     return m->m_ComponentManager.GetEntitiesWithInterfaceUnordered(iid);
    658 }
    659 
    660655const CSimContext& CSimulation2::GetSimContext() const
    661656{
    662657    return m->m_SimContext;
  • source/simulation2/Simulation2.h

     
    2020
    2121#include "simulation2/system/CmpPtr.h"
    2222#include "simulation2/system/Components.h"
     23#include "simulation2/system/EntityMap.h"
    2324#include "simulation2/helpers/SimulationCommand.h"
    2425#include "scriptinterface/ScriptVal.h"
    2526
    2627#include "lib/file/vfs/vfs_path.h"
    2728
    28 #include <boost/unordered_map.hpp>
    29 
    3029#include <map>
    3130
    3231class CSimulation2Impl;
     
    202201    void PostMessage(entity_id_t ent, const CMessage& msg) const;
    203202    void BroadcastMessage(const CMessage& msg) const;
    204203
    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;
    207205
    208206    /**
    209207     * Returns a list of components implementing the given interface, and their
    210      * associated entities, sorted by entity ID.
     208     * associated entities.
    211209     */
    212     InterfaceList GetEntitiesWithInterface(int iid);
     210    const InterfaceList& GetEntitiesWithInterface(int iid);
    213211
    214     /**
    215      * Returns a list of components implementing the given interface, and their
    216      * associated entities, as an unordered map.
    217      */
    218     const InterfaceListUnordered& GetEntitiesWithInterfaceUnordered(int iid);
    219 
    220212    const CSimContext& GetSimContext() const;
    221213    ScriptInterface& GetScriptInterface() const;
    222214
  • source/simulation2/system/ComponentManager.cpp

     
    305305    {
    306306        // For every script component with this cid, we need to switch its
    307307        // 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();
    310310        for (; eit != comps.end(); ++eit)
    311311        {
    312312            JS::RootedValue instance(cx, eit->second->GetJSInstance());
     
    405405    CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
    406406
    407407    std::vector<int> ret;
    408     const InterfaceListUnordered& ents = componentManager->GetEntitiesWithInterfaceUnordered(iid);
    409     for (InterfaceListUnordered::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)
    410410        if (!ENTITY_IS_LOCAL(it->first))
    411411            ret.push_back(it->first);
    412412    std::sort(ret.begin(), ret.end());
     
    418418    CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
    419419
    420420    std::vector<IComponent*> ret;
    421     InterfaceList ents = componentManager->GetEntitiesWithInterface(iid);
     421    const InterfaceList& ents = componentManager->GetEntitiesWithInterface(iid);
    422422    for (InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
    423423        ret.push_back(it->second); // TODO: maybe we should exclude local entities
    424424    return ret;
     
    509509    m_DynamicMessageSubscriptionsNonsyncByComponent.clear();
    510510
    511511    // 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();
    513513    for (; iit != m_ComponentsByTypeId.end(); ++iit)
    514514    {
    515         std::map<entity_id_t, IComponent*>::iterator eit = iit->second.begin();
     515        GlobalEntityMap<IComponent*>::iterator eit = iit->second.begin();
    516516        for (; eit != iit->second.end(); ++eit)
    517517        {
    518518            eit->second->Deinit();
     
    520520        }
    521521    }
    522522
    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();
    524524    for (; ifcit != m_ComponentsByInterface.end(); ++ifcit)
    525525        ifcit->clear();
    526526
     
    527527    m_ComponentsByTypeId.clear();
    528528
    529529    // Delete all SEntityComponentCaches
    530     std::map<entity_id_t, SEntityComponentCache*>::iterator ccit = m_ComponentCaches.begin();
     530    GlobalEntityMap<SEntityComponentCache*>::iterator ccit = m_ComponentCaches.begin();
    531531    for (; ccit != m_ComponentCaches.end(); ++ccit)
    532532        free(ccit->second);
    533533    m_ComponentCaches.clear();
     
    750750
    751751    ENSURE((size_t)ct.iid < m_ComponentsByInterface.size());
    752752
    753     boost::unordered_map<entity_id_t, IComponent*>& emap1 = m_ComponentsByInterface[ct.iid];
     753    GlobalEntityMap<IComponent*>& emap1 = m_ComponentsByInterface[ct.iid];
    754754    if (emap1.find(ent.GetId()) != emap1.end())
    755755    {
    756756        LOGERROR("Multiple components for interface %d", ct.iid);
     
    757757        return NULL;
    758758    }
    759759
    760     std::map<entity_id_t, IComponent*>& emap2 = m_ComponentsByTypeId[cid];
     760    GlobalEntityMap<IComponent*>& emap2 = m_ComponentsByTypeId[cid];
    761761
    762762    // If this is a scripted component, construct the appropriate JS object first
    763763    JS::RootedValue obj(cx);
     
    779779    component->SetSimContext(m_SimContext);
    780780
    781781    // 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);
    784784    // TODO: We need to more careful about this - if an entity is constructed by a component
    785785    // while we're iterating over all components, this will invalidate the iterators and everything
    786786    // will break.
     
    799799    // Just add it into the by-interface map, not the by-component-type map,
    800800    // so it won't be considered for messages or deletion etc
    801801
    802     boost::unordered_map<entity_id_t, IComponent*>& emap1 = m_ComponentsByInterface.at(iid);
     802    GlobalEntityMap<IComponent*>& emap1 = m_ComponentsByInterface.at(iid);
    803803    if (emap1.find(ent.GetId()) != emap1.end())
    804804        debug_warn(L"Multiple components for interface");
    805     emap1.insert(std::make_pair(ent.GetId(), &component));
     805    emap1.insert(ent.GetId(), &component);
    806806
    807807    SEntityComponentCache* cache = ent.GetComponentCache();
    808808    ENSURE(cache != NULL && iid < (int)cache->numInterfaces && cache->interfaces[iid] == NULL);
     
    819819    cache->numInterfaces = m_InterfaceIdsByName.size() + 1;
    820820
    821821    ENSURE(m_ComponentCaches.find(ent) == m_ComponentCaches.end());
    822     m_ComponentCaches[ent] = cache;
     822    m_ComponentCaches.insert(ent, cache);
    823823
    824824    return CEntityHandle(ent, cache);
    825825}
     
    826826
    827827CEntityHandle CComponentManager::LookupEntityHandle(entity_id_t ent, bool allowCreate)
    828828{
    829     std::map<entity_id_t, SEntityComponentCache*>::iterator it;
    830     it = m_ComponentCaches.find(ent);
     829    GlobalEntityMap<SEntityComponentCache*>::iterator it = m_ComponentCaches.find(ent);
    831830    if (it == m_ComponentCaches.end())
    832831    {
    833832        if (allowCreate)
     
    918917            PostMessage(ent, msg);
    919918
    920919            // 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();
    922921            for (; iit != m_ComponentsByTypeId.end(); ++iit)
    923922            {
    924                 std::map<entity_id_t, IComponent*>::iterator eit = iit->second.find(ent);
     923                GlobalEntityMap<IComponent*>::iterator eit = iit->second.find(ent);
    925924                if (eit != iit->second.end())
    926925                {
    927926                    eit->second->Deinit();
     
    936935            m_ComponentCaches.erase(ent);
    937936
    938937            // 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();
    940939            for (; ifcit != m_ComponentsByInterface.end(); ++ifcit)
    941940            {
    942941                ifcit->erase(ent);
     
    953952        return NULL;
    954953    }
    955954
    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);
    957956    if (eit == m_ComponentsByInterface[iid].end())
    958957    {
    959958        // This entity doesn't implement this interface
     
    963962    return eit->second;
    964963}
    965964
    966 CComponentManager::InterfaceList CComponentManager::GetEntitiesWithInterface(InterfaceId iid) const
     965static CComponentManager::InterfaceList g_EmptyEntityMap;
     966const CComponentManager::InterfaceList& CComponentManager::GetEntitiesWithInterface(InterfaceId iid) const
    967967{
    968     std::vector<std::pair<entity_id_t, IComponent*> > ret;
    969 
    970968    if ((size_t)iid >= m_ComponentsByInterface.size())
    971969    {
    972970        // 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 ID
    983 
    984     return ret;
    985 }
    986 
    987 static CComponentManager::InterfaceListUnordered g_EmptyEntityMap;
    988 const CComponentManager::InterfaceListUnordered& CComponentManager::GetEntitiesWithInterfaceUnordered(InterfaceId iid) const
    989 {
    990     if ((size_t)iid >= m_ComponentsByInterface.size())
    991     {
    992         // Invalid iid
    993971        return g_EmptyEntityMap;
    994972    }
    995973
     
    1007985        for (; ctit != it->second.end(); ++ctit)
    1008986        {
    1009987            // 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);
    1011989            if (emap == m_ComponentsByTypeId.end())
    1012990                continue;
    1013991
    1014992            // 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);
    1016994            if (eit != emap->second.end())
    1017995                eit->second->HandleMessage(msg, false);
    1018996        }
     
    10321010        for (; ctit != it->second.end(); ++ctit)
    10331011        {
    10341012            // 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);
    10361014            if (emap == m_ComponentsByTypeId.end())
    10371015                continue;
    10381016
    10391017            // 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();
    10411019            for (; eit != emap->second.end(); ++eit)
    10421020                eit->second->HandleMessage(msg, false);
    10431021        }
     
    10691047            }
    10701048
    10711049            // 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);
    10731051            if (emap == m_ComponentsByTypeId.end())
    10741052                continue;
    10751053
    10761054            // 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();
    10781056            for (; eit != emap->second.end(); ++eit)
    10791057                eit->second->HandleMessage(msg, true);
    10801058        }
  • source/simulation2/system/ComponentManager.h

     
    1919#define INCLUDED_COMPONENTMANAGER
    2020
    2121#include "Entity.h"
     22#include "EntityMap.h"
    2223#include "Components.h"
    2324#include "scriptinterface/ScriptInterface.h"
    2425#include "simulation2/helpers/Player.h"
     
    2526#include "ps/Filesystem.h"
    2627
    2728#include <boost/random/linear_congruential.hpp>
    28 #include <boost/unordered_map.hpp>
    2929
    3030#include <map>
    3131
     
    270270    IComponent* QueryInterface(entity_id_t ent, InterfaceId iid) const;
    271271
    272272    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;
    275274
    276     InterfaceList GetEntitiesWithInterface(InterfaceId iid) const;
    277     const InterfaceListUnordered& GetEntitiesWithInterfaceUnordered(InterfaceId iid) const;
     275    const InterfaceList& GetEntitiesWithInterface(InterfaceId iid) const;
    278276
    279277    /**
    280278     * Send a message, targeted at a particular entity. The message will be received by any
     
    354352    // TODO: some of these should be vectors
    355353    std::map<ComponentTypeId, ComponentType> m_ComponentTypesById;
    356354    std::vector<CComponentManager::ComponentTypeId> m_ScriptedSystemComponents;
    357     std::vector<boost::unordered_map<entity_id_t, IComponent*> > m_ComponentsByInterface; // indexed by InterfaceId
    358     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;
    359357    std::map<MessageTypeId, std::vector<ComponentTypeId> > m_LocalMessageSubscriptions;
    360358    std::map<MessageTypeId, std::vector<ComponentTypeId> > m_GlobalMessageSubscriptions;
    361359    std::map<std::string, ComponentTypeId> m_ComponentTypeIdsByName;
     
    366364    std::map<MessageTypeId, CDynamicSubscription> m_DynamicMessageSubscriptionsNonsync;
    367365    std::map<IComponent*, std::set<MessageTypeId> > m_DynamicMessageSubscriptionsNonsyncByComponent;
    368366
    369     std::map<entity_id_t, SEntityComponentCache*> m_ComponentCaches;
     367    GlobalEntityMap<SEntityComponentCache*> m_ComponentCaches;
    370368
    371369    // TODO: maintaining both ComponentsBy* is nasty; can we get rid of one,
    372370    // while keeping QueryInterface and PostMessage sufficiently efficient?
  • source/simulation2/system/ComponentManagerSerialization.cpp

     
    1818#include "precompiled.h"
    1919
    2020#include "ComponentManager.h"
     21#include "EntityMap.h"
    2122#include "IComponent.h"
    2223#include "ParamNode.h"
    2324
     
    5859    std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> > components;
    5960    //std::map<ComponentTypeId, std::string> names;
    6061
    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();
    6263    for (; ctit != m_ComponentsByTypeId.end(); ++ctit)
    6364    {
    64         std::map<entity_id_t, IComponent*>::const_iterator eit = ctit->second.begin();
     65        GlobalEntityMap<IComponent*>::const_iterator eit = ctit->second.begin();
    6566        for (; eit != ctit->second.end(); ++eit)
    6667        {
    6768            components[eit->first][ctit->first] = eit->second;
     
    109110    serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
    110111    serializer.NumberU32_Unbounded("next entity id", m_NextEntityId);
    111112
    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();
    113114    for (; cit != m_ComponentsByTypeId.end(); ++cit)
    114115    {
    115116        // In quick mode, only check unit positions
     
    118119
    119120        // Only emit component types if they have a component that will be serialized
    120121        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)
    122123        {
    123124            // Don't serialize local entities
    124125            if (ENTITY_IS_LOCAL(eit->first))
     
    133134
    134135        serializer.NumberI32_Unbounded("component type id", cit->first);
    135136
    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)
    137138        {
    138139            // Don't serialize local entities
    139140            if (ENTITY_IS_LOCAL(eit->first))
     
    188189    serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
    189190    serializer.NumberU32_Unbounded("next entity id", m_NextEntityId);
    190191
    191     std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit;
     192    std::map<ComponentTypeId, GlobalEntityMap<IComponent*> >::const_iterator cit;
    192193   
    193194    uint32_t numSystemComponentTypes = 0;
    194195    uint32_t numComponentTypes = 0;
     
    199200    {
    200201        // Only emit component types if they have a component that will be serialized
    201202        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)
    203204        {
    204205            // Don't serialize local entities, and handle SYSTEM_ENTITY separately
    205206            if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
     
    238239
    239240        serializer.StringASCII("name", ctit->second.name, 0, 255);
    240241
    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);
    242243        if (eit == cit->second.end())
    243244        {
    244245            debug_warn(L"Invalid eit"); // this should never happen
     
    265266
    266267        // Count the components before serializing any of them
    267268        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)
    269270        {
    270271            // Don't serialize local entities or SYSTEM_ENTITY
    271272            if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
     
    278279        serializer.NumberU32_Unbounded("num components", numComponents);
    279280
    280281        // 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)
    282283        {
    283284            // Don't serialize local entities or SYSTEM_ENTITY
    284285            if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
  • source/simulation2/system/EntityMap.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    1818#define INCLUDED_ENTITYMAP
    1919
    2020#include "Entity.h"
     21#include "simulation2/serialization/ISerializer.h"
     22#include "simulation2/serialization/IDeserializer.h"
    2123
    2224/**
    2325 * A fast replacement for map<entity_id_t, T>.
     
    2830 */
    2931template<class T> class EntityMap
    3032{
    31 private:
    32     EntityMap(const EntityMap&);            // non-copyable
    33     EntityMap& operator=(const EntityMap&); // non-copyable
     33public:
     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);
    3451
    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    }
    3662    typedef entity_id_t key_type;
    3763    typedef T mapped_type;
    3864    template<class K, class V> struct key_val {
     
    4066        typedef V second_type;
    4167        K first;
    4268        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); };
    4376    };
    4477    typedef key_val<entity_id_t, T> value_type;
    4578
     
    4881    size_t m_BufferCapacity;    // capacity of the buffer
    4982    value_type* m_Buffer;       // vector with all the mapped key-value pairs
    5083
     84    size_t m_FirstEntityID;     // real ID of the [0] in the buffer, so we can offset.
    5185    size_t m_Count;             // number of 'valid' entity id's
    5286
    5387public:
    5488
    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)
    5690    {
    5791        // for entitymap we allocate the buffer right away
    5892        // with first element in buffer being the Invalid Entity
    5993        m_Buffer = (value_type*)malloc(sizeof(value_type) * (m_BufferCapacity + 1));
    6094
    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
    6496    }
     97    inline EntityMap(size_t ID) : EntityMap()
     98    {
     99        m_FirstEntityID = ID;
     100    }
     101
    65102    inline ~EntityMap()
    66103    {
    67104        free(m_Buffer);
     
    97134
    98135    inline iterator begin()
    99136    {
    100         value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
     137        value_type* ptr = m_Buffer;
    101138        while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
    102139        return ptr;
    103140    }
     
    107144    }
    108145    inline const_iterator begin() const
    109146    {
    110         value_type* ptr = m_Buffer + 1; // skip the first INVALID_ENTITY
     147        value_type* ptr = m_Buffer;
    111148        while (ptr->first == INVALID_ENTITY) ++ptr; // skip any other invalid entities
    112149        return ptr;
    113150    }
     
    121158    inline size_t size() const { return m_Count; }
    122159
    123160    // Modification
    124     void insert(const key_type key, const mapped_type& value)
     161    void insert(const key_type actual_key, const mapped_type& value)
    125162    {
     163        key_type key = actual_key - m_FirstEntityID;
    126164        if (key >= m_BufferCapacity) // do we need to resize buffer?
    127165        {
    128166            size_t newCapacity = m_BufferCapacity + 4096;
     
    143181fill_gaps:
    144182            // set all entity id's to INVALID_ENTITY inside the new range
    145183            for (size_t i = m_BufferSize; i <= key; ++i)
     184            {
    146185                m_Buffer[i].first = INVALID_ENTITY;
     186                new (&m_Buffer[i].second) mapped_type();
     187            }
    147188            m_BufferSize = key; // extend the new size
    148189        }
    149190
    150191        value_type& item = m_Buffer[key];
    151192        key_type oldKey = item.first;
    152         item.first = key;
     193        item.first = actual_key;
    153194        if (key == m_BufferSize) // push_back
    154195        {
    155196            ++m_BufferSize; // expand
     
    157198            new (&item.second) mapped_type(value); // copy ctor to init
    158199            m_Buffer[m_BufferSize].first = 0xFFFFFFFF; // ensure end() always has 0xFFFFFFFF
    159200        }
    160         else if(!item.first) // insert new to middle
    161         {
    162             ++m_Count;
    163             new (&item.second) mapped_type(value); // copy ctor to init
    164         }
    165201        else // set existing value
    166202        {
    167203            if (oldKey == INVALID_ENTITY)
    168204                m_Count++;
    169             item.second = value; // overwrite existing
     205            item.second = value;
    170206        }
    171207    }
    172208   
     
    182218    }
    183219    void erase(const entity_id_t key)
    184220    {
    185         if (key < m_BufferSize)
     221        if (key - m_FirstEntityID < m_BufferSize)
    186222        {
    187             value_type* ptr = m_Buffer + key;
     223            value_type* ptr = m_Buffer + key - m_FirstEntityID;
    188224            if (ptr->first != INVALID_ENTITY)
    189225            {
    190226                ptr->first = INVALID_ENTITY;
     
    210246    }
    211247
    212248    // 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    };
    213257    inline iterator find(const entity_id_t key)
    214258    {
    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?
    216260        {
    217             value_type* ptr = m_Buffer + key;
     261            value_type* ptr = m_Buffer + key - m_FirstEntityID;
    218262            if (ptr->first != INVALID_ENTITY)
    219263                return ptr;
    220264        }
     
    222266    }
    223267    inline const_iterator find(const entity_id_t key) const
    224268    {
    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?
    226270        {
    227             const value_type* ptr = m_Buffer + key;
     271            const value_type* ptr = m_Buffer + key - m_FirstEntityID;
    228272            if (ptr->first != INVALID_ENTITY)
    229273                return ptr;
    230274        }
     
    232276    }
    233277    inline size_t count(const entity_id_t key) const
    234278    {
    235         if (key < m_BufferSize)
     279        if (key - m_FirstEntityID >= 0 && key - m_FirstEntityID < m_BufferSize)
    236280        {
    237             if (m_Buffer[key].first != INVALID_ENTITY)
     281            if (m_Buffer[key - m_FirstEntityID].first != INVALID_ENTITY)
    238282                return 1;
    239283        }
    240284        return 0;
     
    278322    }
    279323};
    280324
     325//Implements the same interface as EntityMap but uses two internally to separate local entities
     326template<class T>
     327class GlobalEntityMap
     328{
     329public:
     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;
    281346
     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
    282495#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.
     26class 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    }
     36public:
     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

     
    1818#ifndef INCLUDED_DELTAARRAY
    1919#define INCLUDED_DELTAARRAY
    2020
     21#include <boost/unordered_map.hpp>
     22
    2123template<typename T> class DeltaArray2D
    2224{
    2325public:
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

     
    5050#include "simulation2/components/ICmpTemplateManager.h"
    5151#include "simulation2/components/ICmpVisual.h"
    5252#include "simulation2/helpers/Selection.h"
     53#include "simulation2/system/EntityMap.h"
    5354#include "ps/XML/XMLWriter.h"
    5455
    5556namespace AtlasMessage {
     
    11061107    std::vector<entity_id_t> ids;
    11071108    player_id_t playerID = msg->player;
    11081109
    1109     const CSimulation2::InterfaceListUnordered& cmps = g_Game->GetSimulation2()->GetEntitiesWithInterfaceUnordered(IID_Ownership);
    1110     for (CSimulation2::InterfaceListUnordered::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)
    11111112    {
    11121113        if (static_cast<ICmpOwnership*>(eit->second)->GetOwner() == playerID)
    11131114        {