关于芒果魔兽的同步算法及同步容器设计

芒果魔兽的AOI算法 跟其他AOI算法差不多 也是通过九宫格计算需要同步的范围 然后使用自定义的一个TypeMapContainer 结构  key 值是下列结构 

struct ContainerMapList
{
    GridRefManager<OBJECT> _element;
};

芒果魔兽 设置的key 值 是针对的每个地图  所以下列代码可以看到 只有地图类继承了这个格子索引管理类


class Map : public GridRefManager<NGridType>
{
        friend class MapReference;
        friend class ObjectGridLoader;
        friend class ObjectWorldLoader;

    protected:
        Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
}

这个Key是一种特殊的数据类型  芒果魔兽重写了一个双向链表 这个key的值 是双向链表的head 类型 具体代码如下

1.双向链表 及链表头

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _LINKEDLIST
#define _LINKEDLIST

#include <cstddef>

//============================================
class LinkedListHead;

class LinkedListElement
{
    private:

        friend class LinkedListHead;

        LinkedListElement* iNext;
        LinkedListElement* iPrev;

    public:

        LinkedListElement()  { iNext = nullptr; iPrev = nullptr; }
        ~LinkedListElement() { delink(); }

        bool hasNext() const  { return (iNext->iNext != nullptr); }
        bool hasPrev() const  { return (iPrev->iPrev != nullptr); }
        bool isInList() const { return (iNext != nullptr && iPrev != nullptr); }

        LinkedListElement*       next()       { return hasNext() ? iNext : nullptr; }
        LinkedListElement const* next() const { return hasNext() ? iNext : nullptr; }
        LinkedListElement*       prev()       { return hasPrev() ? iPrev : nullptr; }
        LinkedListElement const* prev() const { return hasPrev() ? iPrev : nullptr; }

        LinkedListElement*       nocheck_next()       { return iNext; }
        LinkedListElement const* nocheck_next() const { return iNext; }
        LinkedListElement*       nocheck_prev()       { return iPrev; }
        LinkedListElement const* nocheck_prev() const { return iPrev; }

        void delink()
        {
            if (isInList())
            {
                iNext->iPrev = iPrev;
                iPrev->iNext = iNext;
                iNext = nullptr;
                iPrev = nullptr;
            }
        }

        void insertBefore(LinkedListElement* pElem)
        {
            pElem->iNext = this;
            pElem->iPrev = iPrev;
            iPrev->iNext = pElem;
            iPrev = pElem;
        }

        void insertAfter(LinkedListElement* pElem)
        {
            pElem->iPrev = this;
            pElem->iNext = iNext;
            iNext->iPrev = pElem;
            iNext = pElem;
        }
};

//============================================

class LinkedListHead
{
    private:

        LinkedListElement iFirst;
        LinkedListElement iLast;
        uint32 iSize;

    public:

        LinkedListHead()
        {
            // create empty list

            iFirst.iNext = &iLast;
            iLast.iPrev = &iFirst;
            iSize = 0;
        }

        bool isEmpty() const { return (!iFirst.iNext->isInList()); }

        LinkedListElement*       getFirst()       { return (isEmpty() ? nullptr : iFirst.iNext); }
        LinkedListElement const* getFirst() const { return (isEmpty() ? nullptr : iFirst.iNext); }

        LinkedListElement*       getLast()        { return (isEmpty() ? nullptr : iLast.iPrev); }
        LinkedListElement const* getLast() const  { return (isEmpty() ? nullptr : iLast.iPrev); }

        void insertFirst(LinkedListElement* pElem)
        {
            iFirst.insertAfter(pElem);
        }

        void insertLast(LinkedListElement* pElem)
        {
            iLast.insertBefore(pElem);
        }

        uint32 getSize() const
        {
            if (!iSize)
            {
                uint32 result = 0;
                LinkedListElement const* e = getFirst();

                while (e)
                {
                    ++result;
                    e = e->next();
                }

                return result;
            }
            return iSize;
        }

        void incSize() { ++iSize; }
        void decSize() { --iSize; }

        template<class _Ty>
        class Iterator
        {
            public:

                typedef std::bidirectional_iterator_tag iterator_category;
                typedef _Ty value_type;
                typedef ptrdiff_t difference_type;
                typedef ptrdiff_t distance_type;
                typedef _Ty* pointer;
                typedef _Ty const* const_pointer;
                typedef _Ty& reference;
                typedef _Ty const& const_reference;

                Iterator()
                    : _Ptr(nullptr)
                {
                    // construct with null node pointer
                }

                Iterator(pointer _Pnode)
                    : _Ptr(_Pnode)
                {
                    // construct with node pointer _Pnode
                }

                Iterator& operator=(Iterator const& _Right)
                {
                    return (*this) = _Right._Ptr;
                }

                Iterator& operator=(const_pointer const& _Right)
                {
                    _Ptr = (pointer)_Right;
                    return (*this);
                }

                reference operator*()
                {
                    // return designated value
                    return *_Ptr;
                }

                pointer operator->()
                {
                    // return pointer to class object
                    return _Ptr;
                }

                Iterator& operator++()
                {
                    // preincrement
                    _Ptr = _Ptr->next();
                    return (*this);
                }

                Iterator operator++(int)
                {
                    // postincrement
                    iterator _Tmp = *this;
                    ++*this;
                    return (_Tmp);
                }

                Iterator& operator--()
                {
                    // predecrement
                    _Ptr = _Ptr->prev();
                    return (*this);
                }

                Iterator operator--(int)
                {
                    // postdecrement
                    iterator _Tmp = *this;
                    --*this;
                    return (_Tmp);
                }

                bool operator==(Iterator const& _Right) const
                {
                    // test for iterator equality
                    return (_Ptr == _Right._Ptr);
                }

                bool operator!=(Iterator const& _Right) const
                {
                    // test for iterator inequality
                    return (!(*this == _Right));
                }

                bool operator==(pointer const& _Right) const
                {
                    // test for pointer equality
                    return (_Ptr != _Right);
                }

                bool operator!=(pointer const& _Right) const
                {
                    // test for pointer equality
                    return (!(*this == _Right));
                }

                bool operator==(const_reference _Right) const
                {
                    // test for reference equality
                    return (_Ptr == &_Right);
                }

                bool operator!=(const_reference _Right) const
                {
                    // test for reference equality
                    return (_Ptr != &_Right);
                }

                pointer _Mynode()
                {
                    // return node pointer
                    return (_Ptr);
                }

            protected:

                pointer _Ptr;                               // pointer to node
        };

        typedef Iterator<LinkedListElement> iterator;
};

//============================================

#endif

2.RefManager管理链表头


#include "Utilities/LinkedList.h"
#include "Utilities/LinkedReference/Reference.h"

template <class TO, class FROM>
class RefManager : public LinkedListHead
{
    public:

        typedef LinkedListHead::Iterator<Reference<TO, FROM> > iterator;
        typedef LinkedListHead::Iterator<Reference<TO, FROM> const > const_iterator;
        RefManager() {}
        virtual ~RefManager() { clearReferences(); }

        Reference<TO, FROM>*       getFirst()       { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); }
        Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); }
        Reference<TO, FROM>*       getLast()       { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); }
        Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); }

        iterator begin() { return iterator(getFirst()); }
        iterator end() { return iterator(nullptr); }
        iterator rbegin() { return iterator(getLast()); }
        iterator rend() { return iterator(nullptr); }
        const_iterator begin() const { return const_iterator(getFirst()); }
        const_iterator end() const { return const_iterator(nullptr); }

        void clearReferences()
        {
            LinkedListElement* ref;
            while ((ref = getFirst()) != nullptr)
            {
                ((Reference<TO, FROM>*) ref)->invalidate();
                ref->delink();                              // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list
            }
        }
};

3.双向链表子节点GridReference 类

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _GRIDREFERENCE_H
#define _GRIDREFERENCE_H

#include "Utilities/LinkedReference/Reference.h"

template<class OBJECT> class GridRefManager;

template<class OBJECT>
class GridReference : public Reference<GridRefManager<OBJECT>, OBJECT>
{
    protected:

        void targetObjectBuildLink() override
        {
            // called from link()
            this->getTarget()->insertFirst(this);
            this->getTarget()->incSize();
        }

        void targetObjectDestroyLink() override
        {
            // called from unlink()
            if (this->isValid())
                this->getTarget()->decSize();
        }

        void sourceObjectDestroyLink() override
        {
            // called from invalidate()
            this->getTarget()->decSize();
        }

    public:

        GridReference()
            : Reference<GridRefManager<OBJECT>, OBJECT>()
        {
        }

        ~GridReference()
        {
            this->unlink();
        }

        GridReference* next()
        {
            return (GridReference*)Reference<GridRefManager<OBJECT>, OBJECT>::next();
        }
};

#endif

4.容器类型类 自定义了几种数据结构 TypeUnorderedMapContainer  以及 TypeMapContaine

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef MANGOS_TYPECONTAINER_H
#define MANGOS_TYPECONTAINER_H

/*
 * Here, you'll find a series of containers that allow you to hold multiple
 * types of object at the same time.
 */

#include <cassert>
#include <map>
#include <vector>
#include "Common.h"
#include "Utilities/TypeList.h"
#include "GameSystem/GridRefManager.h"

template<class OBJECT, class KEY_TYPE>
struct ContainerUnorderedMap
{
    std::unordered_map<KEY_TYPE, OBJECT*> _element;
};

template<class KEY_TYPE>
struct ContainerUnorderedMap<TypeNull, KEY_TYPE>
{
};

template<class H, class T, class KEY_TYPE>
struct ContainerUnorderedMap< TypeList<H, T>, KEY_TYPE >
{
    ContainerUnorderedMap<H, KEY_TYPE> _elements;
    ContainerUnorderedMap<T, KEY_TYPE> _TailElements;
};

template<class OBJECT_TYPES, class KEY_TYPE = OBJECT_HANDLE>
class TypeUnorderedMapContainer
{
    public:

        template<class SPECIFIC_TYPE>
        bool insert(KEY_TYPE handle, SPECIFIC_TYPE* obj)
        {
            return TypeUnorderedMapContainer::insert(i_elements, handle, obj);
        }

        template<class SPECIFIC_TYPE>
        bool erase(KEY_TYPE handle, SPECIFIC_TYPE* /*obj*/)
        {
            return TypeUnorderedMapContainer::erase(i_elements, handle, (SPECIFIC_TYPE*)nullptr);
        }

        template<class SPECIFIC_TYPE>
        SPECIFIC_TYPE* find(KEY_TYPE hdl, SPECIFIC_TYPE* /*obj*/)
        {
            return TypeUnorderedMapContainer::find(i_elements, hdl, (SPECIFIC_TYPE*)nullptr);
        }

        template<class SPECIFIC_TYPE>
        typename std::unordered_map<KEY_TYPE, SPECIFIC_TYPE*>::iterator begin()
        {
            return i_elements._elements._element.begin();
        }

        template<class SPECIFIC_TYPE>
        typename std::unordered_map<KEY_TYPE, SPECIFIC_TYPE*>::iterator end()
        {
            return i_elements._elements._element.end();
        }

    private:

        ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE> i_elements;

        // Helpers
        // Insert helpers
        template<class SPECIFIC_TYPE>
        static bool insert(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE handle, SPECIFIC_TYPE* obj)
        {
            typename std::unordered_map<KEY_TYPE, SPECIFIC_TYPE*>::iterator i = elements._element.find(handle);
            if (i == elements._element.end())
            {
                elements._element[handle] = obj;
                return true;
            }
            assert(i->second == obj && "Object with certain key already in but objects are different!");
            return false;
        }

        template<class SPECIFIC_TYPE>
        static bool insert(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE /*handle*/, SPECIFIC_TYPE* /*obj*/)
        {
            return false;
        }

        template<class SPECIFIC_TYPE, class T>
        static bool insert(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE /*handle*/, SPECIFIC_TYPE* /*obj*/)
        {
            return false;
        }

        template<class SPECIFIC_TYPE, class H, class T>
        static bool insert(ContainerUnorderedMap< TypeList<H, T>, KEY_TYPE >& elements, KEY_TYPE handle, SPECIFIC_TYPE* obj)
        {
            bool ret = TypeUnorderedMapContainer::insert(elements._elements, handle, obj);
            return ret ? ret : TypeUnorderedMapContainer::insert(elements._TailElements, handle, obj);
        }

        // Find helpers
        template<class SPECIFIC_TYPE>
        static SPECIFIC_TYPE* find(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE hdl, SPECIFIC_TYPE* /*obj*/)
        {
            typename std::unordered_map<KEY_TYPE, SPECIFIC_TYPE*>::iterator i = elements._element.find(hdl);
            if (i == elements._element.end())
                return nullptr;
            return i->second;
        }

        template<class SPECIFIC_TYPE>
        static SPECIFIC_TYPE* find(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE /*hdl*/, SPECIFIC_TYPE* /*obj*/)
        {
            return nullptr;
        }

        template<class SPECIFIC_TYPE, class T>
        static SPECIFIC_TYPE* find(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE /*hdl*/, SPECIFIC_TYPE* /*obj*/)
        {
            return nullptr;
        }

        template<class SPECIFIC_TYPE, class H, class T>
        static SPECIFIC_TYPE* find(ContainerUnorderedMap< TypeList<H, T>, KEY_TYPE >& elements, KEY_TYPE hdl, SPECIFIC_TYPE* /*obj*/)
        {
            SPECIFIC_TYPE* ret = TypeUnorderedMapContainer::find(elements._elements, hdl, (SPECIFIC_TYPE*)nullptr);
            return ret ? ret : TypeUnorderedMapContainer::find(elements._TailElements, hdl, (SPECIFIC_TYPE*)nullptr);
        }

        // Erase helpers
        template<class SPECIFIC_TYPE>
        static bool erase(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE handle, SPECIFIC_TYPE* /*obj*/)
        {
            elements._element.erase(handle);

            return true;
        }

        template<class SPECIFIC_TYPE>
        static bool erase(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE /*handle*/, SPECIFIC_TYPE* /*obj*/)
        {
            return false;
        }

        template<class SPECIFIC_TYPE, class T>
        static bool erase(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE /*handle*/, SPECIFIC_TYPE* /*obj*/)
        {
            return false;
        }

        template<class SPECIFIC_TYPE, class H, class T>
        static bool erase(ContainerUnorderedMap< TypeList<H, T>, KEY_TYPE >& elements, KEY_TYPE handle, SPECIFIC_TYPE* /*obj*/)
        {
            bool ret = TypeUnorderedMapContainer::erase(elements._elements, handle, (SPECIFIC_TYPE*)nullptr);
            return ret ? ret : TypeUnorderedMapContainer::erase(elements._TailElements, handle, (SPECIFIC_TYPE*)nullptr);
        }
};

/*
 * @class ContainerMapList is a multi-type container for map elements
 * By itself it's meaningless but collaborating with TypeContainers,
 * it becomes the most powerful container in the whole system.
 */
template<class OBJECT>
struct ContainerMapList
{
    GridRefManager<OBJECT> _element;
};

template<>
struct ContainerMapList<TypeNull>                           /* nothing is in type null */
{
};

template<class H, class T>
struct ContainerMapList<TypeList<H, T> >
{
    ContainerMapList<H> _elements;
    ContainerMapList<T> _TailElements;
};

#include "TypeContainerFunctions.h"

/*
 * @class TypeMapContainer contains a fixed number of types and is
 * determined at compile time.  This is probably the most complicated
 * class and do its simplest thing, that is, holds objects
 * of different types.
 */

template<class OBJECT_TYPES>
class TypeMapContainer
{
    public:

        template<class SPECIFIC_TYPE>
        size_t Count() const { return MaNGOS::Count(i_elements, (SPECIFIC_TYPE*)nullptr); }

        /// inserts a specific object into the container
        template<class SPECIFIC_TYPE>
        bool insert(SPECIFIC_TYPE* obj)
        {
            SPECIFIC_TYPE* t = MaNGOS::Insert(i_elements, obj);
            return (t != nullptr);
        }

        ///  Removes the object from the container, and returns the removed object
        template<class SPECIFIC_TYPE>
        bool remove(SPECIFIC_TYPE* obj)
        {
            SPECIFIC_TYPE* t = MaNGOS::Remove(i_elements, obj);
            return (t != nullptr);
        }

        ContainerMapList<OBJECT_TYPES>& GetElements() { return i_elements; }
        const ContainerMapList<OBJECT_TYPES>& GetElements() const { return i_elements;}

    private:

        ContainerMapList<OBJECT_TYPES> i_elements;
};

#endif

6.上面容器类使用了一些命名空间的函数 方便实现功能  下面是函数的代码

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef TYPECONTAINER_FUNCTIONS_H
#define TYPECONTAINER_FUNCTIONS_H

/*
 * Here you'll find a list of helper functions to make
 * the TypeContainer usefull.  Without it, its hard
 * to access or mutate the container.
 */

#include "Platform/Define.h"
#include "Utilities/TypeList.h"
#include <map>

namespace MaNGOS
{
    /* ContainerMapList Helpers */
    // count functions
    template<class SPECIFIC_TYPE>
    size_t Count(const ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* /*fake*/)
    {
        return elements._element.getSize();
    }

    template<class SPECIFIC_TYPE>
    size_t Count(const ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
    {
        return 0;
    }

    template<class SPECIFIC_TYPE, class T>
    size_t Count(const ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
    {
        return 0;
    }

    template<class SPECIFIC_TYPE, class T>
    size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >& elements, SPECIFIC_TYPE* fake)
    {
        return Count(elements._elements, fake);
    }

    template<class SPECIFIC_TYPE, class H, class T>
    size_t Count(const ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* fake)
    {
        return Count(elements._TailElements, fake);
    }

    // non-const insert functions
    template<class SPECIFIC_TYPE>
    SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* obj)
    {
        // elements._element[hdl] = obj;
        obj->GetGridRef().link(&elements._element, obj);
        return obj;
    }

    template<class SPECIFIC_TYPE>
    SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
    {
        return nullptr;
    }

    // this is a missed
    template<class SPECIFIC_TYPE, class T>
    SPECIFIC_TYPE* Insert(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
    {
        return nullptr;                                        // a missed
    }

    // Recursion
    template<class SPECIFIC_TYPE, class H, class T>
    SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* obj)
    {
        SPECIFIC_TYPE* t = Insert(elements._elements, obj);
        return (t != nullptr ? t : Insert(elements._TailElements, obj));
    }

    // non-const remove method
    template<class SPECIFIC_TYPE>
    SPECIFIC_TYPE* Remove(ContainerMapList<SPECIFIC_TYPE>& /*elements*/, SPECIFIC_TYPE* obj)
    {
        obj->GetGridRef().unlink();
        return obj;
    }

    template<class SPECIFIC_TYPE>
    SPECIFIC_TYPE* Remove(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
    {
        return nullptr;
    }

    // this is a missed
    template<class SPECIFIC_TYPE, class T>
    SPECIFIC_TYPE* Remove(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
    {
        return nullptr;                                        // a missed
    }

    template<class SPECIFIC_TYPE, class T, class H>
    SPECIFIC_TYPE* Remove(ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* obj)
    {
        // The head element is bad
        SPECIFIC_TYPE* t = Remove(elements._elements, obj);
        return (t != nullptr ? t : Remove(elements._TailElements, obj));
    }
}

#endif

上面代码 我们看到了一些功能 函数  但是特别需要注意的是 下面这个代码

  obj->GetGridRef().link(&elements._element, obj);
//以及
  obj->GetGridRef().unlink();

这两个用到的link函数是最终添加对象到双向链表的子节点 所以需要你的需要添加到双向链表的类 都要实现GetGridRef()方法 代码如下

//摄像机类需要实现以下方法

        GridReference<Camera>& GetGridRef() { return m_gridRef; }
        bool isActiveObject() const { return false; }
    
        GridReference<Camera> m_gridRef;
// 在线玩家类需要实现以下方法
       GridReference<Player>& GetGridRef() { return m_gridRef; }
       GridReference<Player> m_gridRef;
//尸体类需要实现以下方法
      GridReference<Corpse>& GetGridRef() { return m_gridRef; }
      GridReference<Corpse> m_gridRef;
//生物类需要实现以下方法
      GridReference<Creature>& GetGridRef() { return m_gridRef; }
      GridReference<Creature> m_gridRef;
      

上面就已经完成了 AOI算法的容器类 下面需要实现一个 访问容器类  后续同步数据的时候会使用到

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef MANGOS_TYPECONTAINERVISITOR_H
#define MANGOS_TYPECONTAINERVISITOR_H

/*
 * @class TypeContainerVisitor is implemented as a visitor pattern.  It is
 * a visitor to the TypeMapContainer or ContainerMapList.  The visitor has
 * to overload its types as a visit method is called.
 */

#include "Platform/Define.h"
#include "TypeContainer.h"

// forward declaration
template<class T, class Y> class TypeContainerVisitor;

// visitor helper
template<class VISITOR, class TYPE_CONTAINER>
void VisitorHelper(VISITOR& v, TYPE_CONTAINER& c)
{
    v.Visit(c);
}

// terminate condition container map list
template<class VISITOR>
void VisitorHelper(VISITOR& /*v*/, ContainerMapList<TypeNull>& /*c*/)
{
}

template<class VISITOR, class T>
void VisitorHelper(VISITOR& v, ContainerMapList<T>& c)
{
    v.Visit(c._element);
}

// recursion container map list
template<class VISITOR, class H, class T>
void VisitorHelper(VISITOR& v, ContainerMapList<TypeList<H, T> >& c)
{
    VisitorHelper(v, c._elements);
    VisitorHelper(v, c._TailElements);
}

// for TypeMapContainer
template<class VISITOR, class OBJECT_TYPES>
void VisitorHelper(VISITOR& v, TypeMapContainer<OBJECT_TYPES>& c)
{
    VisitorHelper(v, c.GetElements());
}

template<class VISITOR, class TYPE_CONTAINER>
class TypeContainerVisitor
{
    public:

        TypeContainerVisitor(VISITOR& v)
            : i_visitor(v)
        {
        }

        void Visit(TYPE_CONTAINER& c)
        {
            VisitorHelper(i_visitor, c);
        }

        void Visit(const TYPE_CONTAINER& c) const
        {
            VisitorHelper(i_visitor, c);
        }

    private:

        VISITOR& i_visitor;
};

#endif

上面所有容器的函数准备工作已经完成  这时候可以创建每个格子的容器了

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef MANGOS_GRID_H
#define MANGOS_GRID_H

/*
  @class Grid
  Grid is a logical segment of the game world represented inside MaNGOS.
  Grid is bind at compile time to a particular type of object which
  we call it the object of interested.  There are many types of loader,
  specially, dynamic loader, static loader, or on-demand loader.  There's
  a subtle difference between dynamic loader and on-demand loader but
  this is implementation specific to the loader class.  From the
  Grid's perspective, the loader meets its API requirement is suffice.
*/

#include "Platform/Define.h"
#include "Policies/ThreadingModel.h"
#include "TypeContainer.h"
#include "TypeContainerVisitor.h"

// forward declaration
template<class A, class T, class O> class GridLoader;

template
<
    class ACTIVE_OBJECT,
    class WORLD_OBJECT_TYPES,
    class GRID_OBJECT_TYPES
    >
class Grid
{
        // allows the GridLoader to access its internals
        template<class A, class T, class O> friend class GridLoader;

    public:

        /** destructor to clean up its resources. This includes unloading the
        grid if it has not been unload.
        */
        ~Grid() {}

        /** an object of interested enters the grid
         */
        template<class SPECIFIC_OBJECT>
        bool AddWorldObject(SPECIFIC_OBJECT* obj)
        {
            return i_objects.template insert<SPECIFIC_OBJECT>(obj);
        }

        /** an object of interested exits the grid
         */
        template<class SPECIFIC_OBJECT>
        bool RemoveWorldObject(SPECIFIC_OBJECT* obj)
        {
            return i_objects.template remove<SPECIFIC_OBJECT>(obj);
        }

        /** Grid visitor for grid objects
         */
        template<class T>
        void Visit(TypeContainerVisitor<T, TypeMapContainer<GRID_OBJECT_TYPES> >& visitor)
        {
            visitor.Visit(i_container);
        }

        /** Grid visitor for world objects
         */
        template<class T>
        void Visit(TypeContainerVisitor<T, TypeMapContainer<WORLD_OBJECT_TYPES> >& visitor)
        {
            visitor.Visit(i_objects);
        }

        /** Returns the number of object within the grid.
         */
        uint32 ActiveObjectsInGrid() const
        {
            return m_activeGridObjects.size() + i_objects.template Count<ACTIVE_OBJECT>();
        }

        /** Inserts a container type object into the grid.
         */
        template<class SPECIFIC_OBJECT>
        bool AddGridObject(SPECIFIC_OBJECT* obj)
        {
            if (obj->isActiveObject())
                m_activeGridObjects.insert(obj);

            return i_container.template insert<SPECIFIC_OBJECT>(obj);
        }

        /** Removes a containter type object from the grid
         */
        template<class SPECIFIC_OBJECT>
        bool RemoveGridObject(SPECIFIC_OBJECT* obj)
        {
            if (obj->isActiveObject())
                m_activeGridObjects.erase(obj);

            return i_container.template remove<SPECIFIC_OBJECT>(obj);
        }

    private:

        TypeMapContainer<GRID_OBJECT_TYPES> i_container;
        TypeMapContainer<WORLD_OBJECT_TYPES> i_objects;
        typedef std::set<void*> ActiveGridObjects;
        ActiveGridObjects m_activeGridObjects;
};

#endif

上面类就是每个格子会保存的对象 类 其中有加添 移除函数 下面需要创建一个每个的格子的管理类

下面是代码 其中还有格子信息类 魔兽世界地图数据是 1个格子的同步cell 为16 *16 所以下面 代码中的uint32 N, 后续会传递16 数据过来过来

/*
 * This file is part of the CMaNGOS Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef MANGOS_NGRID_H
#define MANGOS_NGRID_H

/** NGrid is nothing more than a wrapper of the Grid with an NxN cells
 */

#include "GameSystem/Grid.h"
#include "GameSystem/GridReference.h"
#include "Util/Timer.h"

#include <cassert>

class GridInfo
{
    public:

        GridInfo()
            : i_timer(0), i_unloadActiveLockCount(0), i_unloadExplicitLock(false)
        {
        }

        GridInfo(time_t expiry, bool unload = true)
            : i_timer(expiry), i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload)
        {
        }

        const TimeTracker& getTimeTracker() const { return i_timer; }

        bool getUnloadLock() const
        {
            return i_unloadActiveLockCount || i_unloadExplicitLock;
        }

        void setUnloadExplicitLock(bool on) { i_unloadExplicitLock = on; }
        void incUnloadActiveLock() { ++i_unloadActiveLockCount; }
        void decUnloadActiveLock() { if (i_unloadActiveLockCount) --i_unloadActiveLockCount; }

        void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; }
        void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); }
        void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); }

    private:

        TimeTracker i_timer;
        uint16 i_unloadActiveLockCount : 16;                // lock from active object spawn points (prevent clone loading)
        bool i_unloadExplicitLock      : 1;                 // explicit manual lock or config setting
};

typedef enum
{
    GRID_STATE_INVALID = 0,
    GRID_STATE_ACTIVE = 1,
    GRID_STATE_IDLE = 2,
    GRID_STATE_REMOVAL = 3,
    MAX_GRID_STATE = 4
} grid_state_t;

template
<
    uint32 N,
    class ACTIVE_OBJECT,
    class WORLD_OBJECT_TYPES,
    class GRID_OBJECT_TYPES
    >
class NGrid
{
    public:

        typedef Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridType;

        NGrid(uint32 id, uint32 x, uint32 y, time_t expiry, bool unload = true)
            : i_gridId(id), i_x(x), i_y(y), i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false)
        {
            i_GridInfo = GridInfo(expiry, unload);
        }

        const GridType& operator()(uint32 x, uint32 y) const
        {
            assert(x < N);
            assert(y < N);
            return i_cells[x][y];
        }

        GridType& operator()(uint32 x, uint32 y)
        {
            assert(x < N);
            assert(y < N);
            return i_cells[x][y];
        }

        const uint32& GetGridId() const { return i_gridId; }
        grid_state_t GetGridState() const { return i_cellstate; }
        void SetGridState(grid_state_t s) { i_cellstate = s; }
        uint32 getX() const { return i_x; }
        uint32 getY() const { return i_y; }

        void link(GridRefManager<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> >* pTo)
        {
            i_Reference.link(pTo, this);
        }

        bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; }
        void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; }

        GridInfo* getGridInfoRef() { return &i_GridInfo; }
        const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); }
        bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); }
        void setUnloadExplicitLock(bool on) { i_GridInfo.setUnloadExplicitLock(on); }
        void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); }
        void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); }
        void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); }
        void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); }

        template<class SPECIFIC_OBJECT>
        void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT* obj)
        {
            getGridType(x, y).AddWorldObject(obj);
        }

        template<class SPECIFIC_OBJECT>
        void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT* obj)
        {
            getGridType(x, y).RemoveWorldObject(obj);
        }

        template<class T, class TT>
        void Visit(TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
        {
            for (uint32 x = 0; x < N; ++x)
                for (uint32 y = 0; y < N; ++y)
                    i_cells[x][y].Visit(visitor);
        }

        template<class T, class TT>
        void Visit(const uint32& x, const uint32& y, TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
        {
            getGridType(x, y).Visit(visitor);
        }

        uint32 ActiveObjectsInGrid() const
        {
            uint32 count = 0;
            for (uint32 x = 0; x < N; ++x)
                for (uint32 y = 0; y < N; ++y)
                    count += i_cells[x][y].ActiveObjectsInGrid();

            return count;
        }

        template<class SPECIFIC_OBJECT>
        bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT* obj)
        {
            return getGridType(x, y).AddGridObject(obj);
        }

        template<class SPECIFIC_OBJECT>
        bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT* obj)
        {
            return getGridType(x, y).RemoveGridObject(obj);
        }

    private:

        GridType& getGridType(const uint32& x, const uint32& y)
        {
            assert(x < N);
            assert(y < N);
            return i_cells[x][y];
        }

        uint32 i_gridId;
        GridInfo i_GridInfo;
        GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference;
        uint32 i_x;
        uint32 i_y;
        grid_state_t i_cellstate;
        GridType i_cells[N][N];
        bool i_GridObjectDataLoaded;
};

#endif

到此 容器算法基础框架搭建完毕  下面开始使用 使用的时候需要参考一个模板编程  这个宏定义代码实现的是可以把不同的类型数据 串联起来  实现元编程

class TypeNull;

template<typename HEAD, typename TAIL>
struct TypeList
{
    typedef HEAD Head;
    typedef TAIL Tail;
};

// enough for now.. can be expand at any point in time as needed
#define TYPELIST_1(T1)                 TypeList<T1, TypeNull>
#define TYPELIST_2(T1, T2)             TypeList<T1, TYPELIST_1(T2) >
#define TYPELIST_3(T1, T2, T3)         TypeList<T1, TYPELIST_2(T2, T3) >
#define TYPELIST_4(T1, T2, T3, T4)     TypeList<T1, TYPELIST_3(T2, T3, T4) >
#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList<T1, TYPELIST_4(T2, T3, T4, T5) >

#endif

typedef 串连上面的类

typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, Camera)           AllWorldObjectTypes;
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
typedef TYPELIST_4(Creature, Pet, GameObject, DynamicObject)                            AllMapStoredObjectTypes;

typedef GridRefManager<Camera>          CameraMapType;
typedef GridRefManager<Corpse>          CorpseMapType;
typedef GridRefManager<Creature>        CreatureMapType;
typedef GridRefManager<DynamicObject>   DynamicObjectMapType;
typedef GridRefManager<GameObject>      GameObjectMapType;
typedef GridRefManager<Player>          PlayerMapType;

typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;

typedef TypeMapContainer<AllGridObjectTypes> GridTypeMapContainer;
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;

MAX_NUMBER_OF_CELLS 是16 这样所有的类就串连起来  开始使用 地图类中创建格子容器管理类  魔兽世界的一个地图是无缝地图  一个无缝地图数据是64*64 

//在MAP类里面 定义格子对象
    private:
        time_t i_gridExpiry;
        time_t m_curTime;
        tm m_curTimeTm;

        NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];

在地图初始化的时候 会初始化指针

void Map::Initialize(bool loadInstanceData /*= true*/)
{
    m_CreatureGuids.Set(sObjectMgr.GetFirstTemporaryCreatureLowGuid());
    m_GameObjectGuids.Set(sObjectMgr.GetFirstTemporaryGameObjectLowGuid());

    for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
    {
        for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
        {
            // z code
            m_bLoadedGrids[idx][j] = false;
            setNGrid(nullptr, idx, j);
        }
    }
}

并且在玩家 或者一些特殊对象进入到地图的某个Cell的时候 生成对应的对象格子容器对象 下面代码需要的注意的是         buildNGridLinkage(getNGrid(p.x_coord, p.y_coord)); 函数 这个是把地图跟NGRIDTYPE做第一次链接  地图是所以双向链表的头 所以继承 GridRefManager<NGridType> 这个函数就把地图跟每个NGridtype关联起来了

class Map : public GridRefManager<NGridType>
void Map::EnsureGridCreated(const GridPair& p)
{
    if (!getNGrid(p.x_coord, p.y_coord))
    {
        setNGrid(new NGridType(p.x_coord * MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_BOOL_GRID_UNLOAD)),
                 p.x_coord, p.y_coord);

        // build a linkage between this map and NGridType
        buildNGridLinkage(getNGrid(p.x_coord, p.y_coord));

        getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE);

        // z coord
        int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
        int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;

        if (!m_bLoadedGrids[gx][gy])
            LoadMapAndVMap(gx, gy);
    }
}
bool Map::EnsureGridLoaded(const Cell& cell)
{
    EnsureGridCreated(GridPair(cell.GridX(), cell.GridY()));
    NGridType* grid = getNGrid(cell.GridX(), cell.GridY());

    MANGOS_ASSERT(grid != nullptr);
    if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY()))
    {
        // it's important to set it loaded before loading!
        // otherwise there is a possibility of infinity chain (grid loading will be called many times for the same grid)
        // possible scenario:
        // active object A(loaded with loader.LoadN call and added to the  map)
        // summons some active object B, while B added to map grid loading called again and so on..
        setGridObjectDataLoaded(true, cell.GridX(), cell.GridY());
        ObjectGridLoader loader(*grid, this, cell);
        loader.LoadN();

        // Add resurrectable corpses to world object list in grid
        sObjectAccessor.AddCorpsesToGrid(GridPair(cell.GridX(), cell.GridY()), (*grid)(cell.CellX(), cell.CellY()), this);
        return true;
    }

    return false;
}

玩家 或者任何生物进入到该地图后 就会通过AddToGrid()函数 把对象添加进对应格子容器cell里 

template<class T>
void Map::AddToGrid(T* obj, NGridType* grid, Cell const& cell)
{
    (*grid)(cell.CellX(), cell.CellY()).AddGridObject<T>(obj);
}

上面完成了添加 下面开始AOI同步算法 当需要同步数据时候  具体同步函数都在GridNotifiers.h里面  我们拿其中的一个举例  需要同步不同逻辑的时候需要先 写一个结构体


    struct ObjectMessageDistDeliverer
    {
        WorldObject const& i_object;
        WorldPacket const& i_message;
        float i_dist;
        ObjectMessageDistDeliverer(WorldObject const& obj, WorldPacket const& msg, float dist) : i_object(obj), i_message(msg), i_dist(dist) {}
        void Visit(CameraMapType& m);
        template<class SKIP> void Visit(GridRefManager<SKIP>&) {}
    };
void ObjectMessageDistDeliverer::Visit(CameraMapType& m)
{
    for (auto& iter : m)
    {
        if (!i_dist || iter.getSource()->GetBody()->IsWithinDist(&i_object, i_dist))
        {
            if (WorldSession* session = iter.getSource()->GetOwner()->GetSession())
                session->SendPacket(i_message);
        }
    }
}

上面代码需要注意的两点  第一是你需要同步的对象类型  例如这个例子 需要同步的是拥有CameraMapType的类 所以单独实现了        void Visit(CameraMapType& m);方法  而其他需要同步的对象 就直接跳过了        template<class SKIP> void Visit(GridRefManager<SKIP>&) {}

下面开始

void Map::MessageDistBroadcast(WorldObject const* obj, WorldPacket const& msg, float dist)
{
    CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());

    if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
    {
        sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
        return;
    }

    Cell cell(p);
    cell.SetNoCreate();

    if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)))
        return;

    MaNGOS::ObjectMessageDistDeliverer post_man(*obj, msg, dist);
    TypeContainerVisitor<MaNGOS::ObjectMessageDistDeliverer, WorldTypeMapContainer > message(post_man);
    cell.Visit(p, message, *this, *obj, dist);
}

上面代码其实是范围广播消息 先根据坐标计算出玩家具体的cell 生成了一个ObjectMessageDistDeliverer 对象 这个对象其实是类似回调函数 然后还生成了一个访问容器TypeContainerVisitor 具体代码参考上面     cell.Visit(p, message, *this, *obj, dist);开始执行计算 dist参数是同步的范围 obj是一个世界物品  

template<class T, class CONTAINER>
inline void
Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& m, const WorldObject& obj, float radius) const
{
    Cell::Visit(standing_cell, visitor, m, obj.GetPositionX(), obj.GetPositionY(), radius + obj.GetObjectBoundingRadius());
}
template<class T, class CONTAINER>
inline void
Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& m, float x, float y, float radius) const
{
    if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
        return;

    //如果范围小于等于0  就只需要同步给当前cell里面的对象
    if (radius <= 0.0f)
    {
        m.Visit(*this, visitor);
        return;
    }
    // 修正范围
    if (radius > MAX_VISIBILITY_DISTANCE)
        radius = MAX_VISIBILITY_DISTANCE;

    // 计算同步区域 
    CellArea area = Cell::CalculateCellArea(x, y, radius);
    // 检测是不是区域是不是同一区域 
    if (!area)
    {
        m.Visit(*this, visitor);
        return;
    }

    CellPair& begin_cell = area.low_bound;
    CellPair& end_cell = area.high_bound;
    //上面据算出需要更新的区域边界
    //如果超过4 就需要同步圆形范围
    if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4))
    {
        VisitCircle(visitor, m, begin_cell, end_cell);
        return;
    }
    //这里是先给当前cell的数据不同
    m.Visit(*this, visitor);

    // 同步周边
    for (uint32 i = begin_cell.x_coord; i <= end_cell.x_coord; ++i)
    {
        for (uint32 j = begin_cell.y_coord; j <= end_cell.y_coord; ++j)
        {
            CellPair cell_pair(i, j);
            // lets skip standing cell since we already visited it
            if (cell_pair != standing_cell)
            {
                Cell r_zone(cell_pair);
                r_zone.data.Part.nocreate = data.Part.nocreate;
                m.Visit(r_zone, visitor);
            }
        }
    }
}

具体看注释

template<class T, class CONTAINER>
inline void
Map::Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor)
{
    const uint32 x = cell.GridX();
    const uint32 y = cell.GridY();
    const uint32 cell_x = cell.CellX();
    const uint32 cell_y = cell.CellY();

    if (!cell.NoCreate() || loaded(GridPair(x, y)))
    {
        EnsureGridLoaded(cell);
        getNGrid(x, y)->Visit(cell_x, cell_y, visitor);
    }
}

找到具体的格子容器 执行同步

    template<class T, class TT>
        void Visit(const uint32& x, const uint32& y, TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
        {
            getGridType(x, y).Visit(visitor);
        }
        GridType& getGridType(const uint32& x, const uint32& y)
        {
            assert(x < N);
            assert(y < N);
            return i_cells[x][y];
        }
        template<class T, class TT>
        void Visit(TypeContainerVisitor<T, TypeMapContainer<TT> >& visitor)
        {
            for (uint32 x = 0; x < N; ++x)
                for (uint32 y = 0; y < N; ++y)
                    i_cells[x][y].Visit(visitor);
        }
      template<class T>
        void Visit(TypeContainerVisitor<T, TypeMapContainer<WORLD_OBJECT_TYPES> >& visitor)
        {
            visitor.Visit(i_objects);
        }

上面就是数据在GIRD传递的过程 下面 开始数据开始调用  之前创建的ObjectMessageDistDeliverer结构体  是封装到了TypeContainerVisitor容器内的 下面代码是调用过程

template<class VISITOR, class TYPE_CONTAINER>
class TypeContainerVisitor
{
    public:

        TypeContainerVisitor(VISITOR& v)
            : i_visitor(v)
        {
        }

        void Visit(TYPE_CONTAINER& c)
        {
            VisitorHelper(i_visitor, c);
        }

        void Visit(const TYPE_CONTAINER& c) const
        {
            VisitorHelper(i_visitor, c);
        }

    private:

        VISITOR& i_visitor;
};
template<class VISITOR, class OBJECT_TYPES>
void VisitorHelper(VISITOR& v, TypeMapContainer<OBJECT_TYPES>& c)
{
    VisitorHelper(v, c.GetElements());
}

前面我们说过 我们使用过

typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, Camera)           AllWorldObjectTypes;
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;

所以

    TypeContainerVisitor<MaNGOS::ObjectMessageDistDeliverer, WorldTypeMapContainer > message(post_man);

这个第二个参数  就代表了TYPE_CONTAINER 的类型是 ContainerMapList<TypeList<H, T> >&

所以这里最后调用的函数是下面的  并且使用了递归访问了结构体内的visit函数

template<class VISITOR, class H, class T>
void VisitorHelper(VISITOR& v, ContainerMapList<TypeList<H, T> >& c)
{
    VisitorHelper(v, c._elements);
    VisitorHelper(v, c._TailElements);
}

因为其他类型都skip了  最后访问的到了到了ObjectMessageDistDeliverer的void Visit(CameraMapType& m);函数  就把需要同步的物体信息转发给了有摄像机的连线玩家

PS 上面代码展示的只是AOI算法同步数据   玩家或者物体移动进入新的cell需要重新定位 从旧的cell里面移除  并且添加到新的cell里面去 芒果魔兽源码可以参考RemoveFromGrid 调用的地方

文章中有不理解的地方 进群交流讨论服务器技术 可以加Q群397926909

  • 39
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值