Ticket #1707: entitymap.diff

File entitymap.diff, 10.8 KB (added by mrf, 9 years ago)
  • components/CCmpRangeManager.cpp

     
    2626#include "simulation2/components/ICmpVision.h"
    2727#include "simulation2/helpers/Render.h"
    2828#include "simulation2/helpers/Spatial.h"
     29#include "simulation2/helpers/EntityMap.h"
    2930
    3031#include "graphics/Overlay.h"
    3132#include "graphics/Terrain.h"
     
    149150 */
    150151struct EntityDistanceOrdering
    151152{
    152     EntityDistanceOrdering(const std::map<entity_id_t, EntityData>& entities, const CFixedVector2D& source) :
     153    EntityDistanceOrdering(const EntityMap<EntityData>& entities, const CFixedVector2D& source) :
    153154        m_EntityData(entities), m_Source(source)
    154155    {
    155156    }
     
    163164        return (vecA.CompareLength(vecB) < 0);
    164165    }
    165166
    166     const std::map<entity_id_t, EntityData>& m_EntityData;
     167    const EntityMap<EntityData>& m_EntityData;
    167168    CFixedVector2D m_Source;
    168169
    169170private:
     
    210211    // Range query state:
    211212    tag_t m_QueryNext; // next allocated id
    212213    std::map<tag_t, Query> m_Queries;
    213     std::map<entity_id_t, EntityData> m_EntityData;
     214    EntityMap<EntityData> m_EntityData;
    214215    SpatialSubdivision<entity_id_t> m_Subdivision; // spatial index of m_EntityData
    215216
    216217    // LOS state:
     
    284285
    285286        serialize.NumberU32_Unbounded("query next", m_QueryNext);
    286287        SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries);
    287         SerializeMap<SerializeU32_Unbounded, SerializeEntityData>()(serialize, "entity data", m_EntityData);
     288        SerializeEntityMap<SerializeEntityData>()(serialize, "entity data", m_EntityData);
    288289
    289290        SerializeMap<SerializeI32_Unbounded, SerializeBool>()(serialize, "los reveal all", m_LosRevealAll);
    290291        serialize.Bool("los circular", m_LosCircular);
     
    355356            const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg);
    356357            entity_id_t ent = msgData.entity;
    357358
    358             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     359            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    359360
    360361            // Ignore if we're not already tracking this entity
    361362            if (it == m_EntityData.end())
     
    402403            const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    403404            entity_id_t ent = msgData.entity;
    404405
    405             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     406            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    406407
    407408            // Ignore if we're not already tracking this entity
    408409            if (it == m_EntityData.end())
     
    425426            const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg);
    426427            entity_id_t ent = msgData.entity;
    427428
    428             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     429            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    429430
    430431            // Ignore if we're not already tracking this entity
    431432            if (it == m_EntityData.end())
     
    447448            const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg);
    448449            entity_id_t ent = msgData.entity;
    449450
    450             std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     451            EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    451452
    452453            // Ignore if we're not already tracking this entity
    453454            if (it == m_EntityData.end())
     
    555556        m_LosStateRevealed.clear();
    556557        m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide);
    557558
    558         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     559        for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
    559560        {
    560561            if (it->second.inWorld)
    561562                LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z));
     
    572573        // (TODO: find the optimal number instead of blindly guessing)
    573574        m_Subdivision.Reset(x1, z1, entity_pos_t::FromInt(8*TERRAIN_TILE_SIZE));
    574575
    575         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     576        for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
    576577        {
    577578            if (it->second.inWorld)
    578579                m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z));
     
    693694
    694695        u32 ownerMask = CalcOwnerMask(player);
    695696
    696         for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     697        for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
    697698        {
    698699            // Check owner and add to list if it matches
    699700            if (CalcOwnerMask(it->second.owner) & ownerMask)
     
    804805        // Special case: range -1.0 means check all entities ignoring distance
    805806        if (q.maxRange == entity_pos_t::FromInt(-1))
    806807        {
    807             for (std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
     808            for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
    808809            {
    809810                if (!TestEntityQuery(q, it->first, it->second))
    810811                    continue;
     
    819820
    820821            for (size_t i = 0; i < ents.size(); ++i)
    821822            {
    822                 std::map<entity_id_t, EntityData>::const_iterator it = m_EntityData.find(ents[i]);
     823                EntityMap<EntityData>::const_iterator it = m_EntityData.find(ents[i]);
    823824                ENSURE(it != m_EntityData.end());
    824825
    825826                if (!TestEntityQuery(q, it->first, it->second))
     
    945946   
    946947    virtual void SetEntityFlag(entity_id_t ent, std::string identifier, bool value)
    947948    {
    948         std::map<entity_id_t, EntityData>::iterator it = m_EntityData.find(ent);
     949        EntityMap<EntityData>::iterator it = m_EntityData.find(ent);
    949950
    950951        // We don't have this entity
    951952        if (it == m_EntityData.end())
  • helpers/EntityMap.h

     
     1#ifndef INCLUDED_ENTITYMAP
     2#define INCLUDED_ENTITYMAP
     3
     4#ifndef NDEBUG
     5#define ENTITYMAP_INSERTION_CHECK
     6#endif
     7
     8/**
     9 * A fast replacement for map<entity_id_t, T>.
     10 * We make the following assumptions:
     11 *  - entity id's (keys) are unique and are inserted in increasing order
     12 *  - an entity id that was removed is never added again
     13 *  - modifications (add / delete) are far less frequent then look-ups
     14 *  - preformance for iteration is important
     15 */
     16template<typename T>
     17class EntityMap
     18{
     19
     20public:
     21    EntityMap() : m_Data(), m_Lookup()
     22    {
     23    }
     24
     25    EntityMap(const EntityMap& m) : m_Data(m.m_Data), m_Lookup(m.m_Lookup)
     26    {
     27    }
     28
     29    // Map interface:
     30    // Member types
     31    typedef entity_id_t key_type;
     32    typedef T mapped_type;
     33    typedef std::pair<entity_id_t, T> value_type;
     34
     35    typedef typename std::vector<value_type>::difference_type difference_type;
     36    typedef typename std::vector<value_type>::size_type size_type;
     37
     38    typedef typename std::vector<value_type>::iterator iterator;
     39    typedef typename std::vector<value_type>::const_iterator const_iterator;
     40    typedef typename std::vector<value_type>::reverse_iterator reverse_iterator;
     41    typedef typename std::vector<value_type>::const_reverse_iterator const_reverse_iterator;
     42
     43    // Iterators
     44    iterator begin()
     45    { return m_Data.begin(); }
     46   
     47    const_iterator begin() const
     48    { return m_Data.begin(); }
     49
     50    iterator end()
     51    { return m_Data.end(); }
     52   
     53    const_iterator end() const
     54    { return m_Data.end(); }
     55
     56    reverse_iterator rbegin()
     57    { return m_Data.rbegin(); }
     58
     59    const_reverse_iterator rbegin() const
     60    { return m_Data.rbegin(); }
     61
     62    reverse_iterator rend()
     63    { return m_Data.rend(); }
     64   
     65    const_reverse_iterator rend() const
     66    { return m_Data.rend(); }
     67
     68    // Capacity
     69    bool empty() const
     70    { return m_Data.empty(); }
     71   
     72    size_type size() const
     73    { return m_Data.size(); }
     74   
     75    size_type max_size() const
     76    { return std::min<size_type>(m_Data.max_size(), std::numeric_limits<difference_type>::max()); }
     77
     78    // Modification
     79    std::pair<iterator, bool> insert(const value_type& val)
     80    {
     81#ifdef ENTITYMAP_INSERTION_CHECK
     82        ENSURE(val.first >= size());
     83        ENSURE(val.first <= std::numeric_limits<difference_type>::max());
     84#endif
     85        m_Data.push_back(val);
     86        difference_type pos = m_Data.size() - 1;
     87        m_Lookup.resize(val.first + 1, -1);
     88        m_Lookup[val.first] = pos;
     89        return std::make_pair(m_Data.begin() + pos, true);
     90    }
     91   
     92    void erase(iterator it)
     93    {
     94        // update all lookup indices
     95        m_Lookup[it->first] = -1;
     96        for(entity_id_t ent = it->first + 1; ent < m_Lookup.size(); ent++)
     97        {
     98            if (m_Lookup[ent] >= 0) m_Lookup[ent]--;
     99        }
     100        m_Data.erase(it);
     101    }
     102   
     103    size_type erase(const key_type& key)
     104    {
     105        size_type count = 0;
     106        iterator it = find(key);
     107        if (it != end())
     108        {
     109            erase(it);
     110            count = 1;
     111        }
     112        return count;
     113    }
     114   
     115    void swap(EntityMap &map)
     116    {
     117        m_Data.swap(map.m_Data);
     118        m_Lookup.swap(map.m_Lookup);
     119    }
     120
     121    void clear()
     122    {
     123        m_Data.clear();
     124        m_Lookup.clear();
     125    }
     126
     127    // Operations
     128    iterator find(const key_type& key)
     129    {
     130        if (key < m_Lookup.size())
     131        {
     132            difference_type pos = m_Lookup[key];
     133            if (pos >= 0)
     134            {
     135                return m_Data.begin() + pos;
     136            }
     137        }
     138        return m_Data.end();
     139    }
     140
     141    const_iterator find(const key_type& key) const
     142    {
     143        if (key < m_Lookup.size())
     144        {
     145            difference_type pos = m_Lookup[key];
     146            if (pos >= 0)
     147            {
     148                return m_Data.begin() + pos;
     149            }
     150        }
     151        return m_Data.end();
     152    }
     153
     154    size_type count(const key_type& key) const
     155    {
     156        return find(key) == end() ? 0 : 1;
     157    }
     158   
     159private:
     160    std::vector<value_type> m_Data;
     161    std::vector<difference_type> m_Lookup;
     162};
     163#endif
  • serialization/SerializeTemplates.h

     
    2424 */
    2525
    2626#include "simulation2/components/ICmpPathfinder.h"
     27#include "simulation2/helpers/EntityMap.h"
    2728
    2829template<typename ELEM>
    2930struct SerializeVector
     
    8788    }
    8889};
    8990
     91template<typename VS>
     92struct SerializeEntityMap
     93{
     94    template<typename V>
     95    void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<V>& value)
     96    {
     97        size_t len = value.size();
     98        serialize.NumberU32_Unbounded("length", (u32)len);
     99        for (typename EntityMap<V>::iterator it = value.begin(); it != value.end(); ++it)
     100        {
     101            serialize.NumberU32_Unbounded("key", it->first);
     102            VS()(serialize, "value", it->second);
     103        }
     104    }
     105
     106    template<typename V>
     107    void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<V>& value)
     108    {
     109        value.clear();
     110        u32 len;
     111        deserialize.NumberU32_Unbounded("length", len);
     112        for (size_t i = 0; i < len; ++i)
     113        {
     114            entity_id_t k;
     115            deserialize.NumberU32_Unbounded("key", k);
     116            V v;
     117            VS()(deserialize, "value", v);
     118            value.insert(std::make_pair(k, v));
     119        }
     120    }
     121};
     122
    90123// We have to order the map before serializing to make things consistent
    91124template<typename KS, typename VS>
    92125struct SerializeUnorderedMap