• aoi十字链表


    #include <stdio.h>
    #include <string.h>
    extern "C" {
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
    }
    //#pragma comment(lib,"lua.lib") 
    
    
    #define LUA_LIB
    #include "skynet.h"
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    #include <assert.h>
    #include <stdlib.h>
    #include <time.h>
    
    #include <lua.h>
    #include <lauxlib.h>
    #include <iostream>
    
    
    #define INVALID_ID (~0)
    #define PRE_ALLOC 30000
    #define AOI_RADIS 25
    #define MAX_POSITION  1200
    #define MODE_WATCHER 1
    #define MODE_MARKER 2
    #define MODE_MOVE 4
    #define MODE_DROP 8
    #define MAX_PATROL_POINTS 10
    
    #define \
        CHECK_MINMAX(x, min, max) \
    if ((x) < (min)) \
        return; \
    if ((x) >= (max)) \
        return; \
    
    //hash
    struct element {
        int64_t key;
        int64_t value;
    };
    
    struct hashtable {
        struct element **elm;
        int64_t count;
        int64_t size;        // PRE_ALLOC
    };
    
    int64_t hashcode(struct hashtable* t, int64_t key) {
        return key%t->size;
    }
    
    struct hashtable* hash_init() {
        struct hashtable *t = (struct hashtable*)malloc(sizeof(struct hashtable));
        t->size = PRE_ALLOC;
        t->count = 0;
        t->elm = (struct element **)malloc(t->size * sizeof(struct element*));
        for (int64_t i = 0; i < t->size; i++) {
            t->elm[i] = (struct element*)malloc(sizeof(struct element));
            t->elm[i]->key = -1;
            t->elm[i]->value = -1;
        }
        return t;
    }
    
    void hash_release(struct hashtable* t) {
        if (NULL == t) return;
        for (int64_t i = 0; i < t->size; i++)
        {
            free(t->elm[i]);
        }
        free(t->elm);
        free(t);
    }
    
    void hash_reset(struct hashtable* t) {
        t->count = 0;
        for (int64_t i = 0; i < t->size; i++) {
            t->elm[i]->key = -1;
            t->elm[i]->value = -1;
        }
    }
    
    void hash_copy(struct hashtable* t, struct hashtable* s) {
    
        if (s&&t) {
            for (int64_t i = 0; i < t->size; i++) {
                t->elm[i]->key = -1;
                t->elm[i]->value = -1;
            }
            for (int64_t i = 0; i < s->size; i++) {
                t->elm[i]->key = s->elm[i]->key;
                t->elm[i]->value = s->elm[i]->value;
            }
            t->count = s->count;
            t->size = s->size;
        }
    }
    
    
    void hash_set(struct hashtable* t, int64_t key, int64_t value) {
        if (NULL == t) return;
        int64_t position = hashcode(t, key);
        for (int64_t i = 1; t->elm[position]->key >= 0 && i < t->size; i++) {
            position = (hashcode(t, position) + i) % t->size;
        }
    
        t->elm[position]->key = key;
        t->elm[position]->value = value;
    
        t->count += 1;
    }
    
    int64_t hash_get(struct hashtable* t, int64_t key) {
        if (NULL == t) return -1;
        int64_t position = hashcode(t, key);
        while (t->elm[position]->key != key) {
            position = hashcode(t, position + 1);
            if (t->elm[position]->key == -1 || position == hashcode(t, key)) {
                return -1;
            }
        }
        return position;
    }
    //hash
    
    
    
    
    
    //可见对象集合
    struct watchset {
        int64_t* idset;
        uint32_t  last;
        struct hashtable* htable;
    };
    
    //坐标节点
    struct dnode {
        int64_t id;
        int x;
        int y;
        int mode;
        struct dnode * xPrev;
        struct dnode * xNext;
        struct dnode * yPrev;
        struct dnode * yNext;
    };
    
    
    //data from lua
    struct objectdata {
        int64_t id;
        int x;
        int y;
        int iswatcher;
        int ismarker;
        int patrols[MAX_PATROL_POINTS][2];
        uint32_t patrolNum;
        uint32_t aoirange;
    };
    
    
    struct object {
        int ref;
        int64_t id;
        int version;
        int mode;
        int last[2];
        int position[2];
    
        ///被观察者(地图上对象),观察者也会存进来
        struct dnode**   patrolnodes;            //第一个节点为当前移动节点
        int patrols[MAX_PATROL_POINTS][2];      //行军路点
        uint32_t patrolNum;
    
        //观察者(玩家)
        struct watchset* watchedset;             //可见列表
        uint32_t aoirange;                        //视野范围
    };
    
    
    //objhash
    struct objelement {
        int64_t key;
        struct object* value;
    };
    
    struct objhashtable {
        struct objelement **elm;
        int64_t count;
        int64_t size;        // PRE_ALLOC
    };
    
    int64_t objhashcode(struct objhashtable* t, int64_t key) {
        return key%t->size;
    }
    
    struct objhashtable* objhash_init() {
        struct objhashtable *t = (struct objhashtable*)malloc(sizeof(struct objhashtable));
        t->size = PRE_ALLOC;
        t->count = 0;
        t->elm = (struct objelement **)malloc(t->size * sizeof(struct objelement*));
        for (int64_t i = 0; i < t->size; i++) {
            t->elm[i] = (struct objelement*)malloc(sizeof(struct objelement));
            t->elm[i]->key = -1;
            t->elm[i]->value = NULL;
        }
        return t;
    }
    
    void objhash_release(struct objhashtable* t) {
        if (NULL == t) return;
        for (int64_t i = 0; i < t->size; i++)
        {
            free(t->elm[i]);
        }
        free(t->elm);
        free(t);
    }
    
    static void
    objhash_foreach(struct objhashtable* t, void(*func)(void *ud, struct object *obj), void *ud) {
        for (int64_t i = 0; i < t->size; i++) {
            if (t->elm[i]->value) {
                func(ud, t->elm[i]->value);
            }
        }
    }
    
    void objhash_reset(struct objhashtable* t) {
        t->count = 0;
        for (int64_t i = 0; i < t->size; i++) {
            t->elm[i]->key = -1;
            t->elm[i]->value = NULL;
        }
    }
    
    void objhash_copy(struct objhashtable* t, struct objhashtable* s) {
    
        if (s&&t) {
            for (int64_t i = 0; i < t->size; i++) {
                t->elm[i]->key = -1;
                t->elm[i]->value = NULL;
            }
            for (int64_t i = 0; i < s->size; i++) {
                t->elm[i]->key = s->elm[i]->key;
                t->elm[i]->value = s->elm[i]->value;
            }
            t->count = s->count;
            t->size = s->size;
        }
    }
    
    
    void objhash_set(struct objhashtable* t, int64_t key, struct object* value) {
        if (NULL == t) return;
        int64_t position = objhashcode(t, key);
        for (int64_t i = 1; t->elm[position]->key >= 0 && i < t->size; i++) {
            position = (objhashcode(t, position) + i) % t->size;
        }
    
        t->elm[position]->key = key;
        t->elm[position]->value = value;
    
        t->count += 1;
    }
    
    int64_t objhash_get(struct objhashtable* t, int64_t key) {
        if (NULL == t) return -1;
        int64_t position = objhashcode(t, key);
        while (t->elm[position]->key != key) {
            position = objhashcode(t, position + 1);
            if (t->elm[position]->key == -1 || position == objhashcode(t, key)) {
                return -1;
            }
        }
        return position;
    }
    
    struct object* objhash_getobject(struct objhashtable* t, int64_t key) {
        if (NULL == t) return NULL;
        int64_t position = objhashcode(t, key);
        while (t->elm[position]->key != key) {
            position = objhashcode(t, position + 1);
            if (t->elm[position]->key == -1 || position == objhashcode(t, key)) {
                return NULL;
            }
        }
        return t->elm[position]->value;
    }
    //hash
    
    
    
    struct map_slot {
        int64_t id;
        struct object * obj;
        int64_t next;
    };
    
    struct map {
        int64_t size;
        int64_t lastfree;
        struct map_slot * slot;
    };
    
    struct aoispace {
        struct skynet_context *ctx;
    
        //struct map * object;
        struct objhashtable* object;
    
    
        struct dnode*** dnodearray;        //[1200][1200]用于快速查找
        struct dnode** dlinks;
    
        struct watchset* lastSet;
        int64_t newidset[PRE_ALLOC];
        uint32_t newid;
        int64_t delidset[PRE_ALLOC];
        uint32_t delid;
        int64_t updateidset[PRE_ALLOC];
        uint32_t updateid;
    }*space;
    
    struct watchset*
        new_watchset() {
    
            struct watchset * wset = (struct watchset *)malloc(sizeof(*wset));
            wset->idset = (int64_t*)malloc(PRE_ALLOC * sizeof(int64_t));
            wset->last = 0;
            wset->htable = hash_init();
            return wset;
        };
    
    void
    delete_watchset(struct aoispace * space, struct watchset * wset) {
    
        free(wset->idset);
        hash_release(wset->htable);
        free(wset);
    }
    
    void
    copy_watchset(struct watchset* dest, struct watchset* src) {
        dest->last = src->last;
        memcpy(dest->idset, src->idset, PRE_ALLOC * sizeof(int64_t));
        hash_copy(dest->htable, src->htable);
    }
    
    void
    compare_watchset(struct aoispace * space, struct watchset*  newSet, struct watchset*  oldSet) {
        space->newid = 0;
        space->delid = 0;
        space->updateid = 0;
        memset(space->newidset, 0, sizeof(space->newidset));
        memset(space->delidset, 0, sizeof(space->delidset));
        memset(space->updateidset, 0, sizeof(space->updateidset));
    
        for (uint32_t i = 0; i < newSet->last; ++i) {
            int64_t id = newSet->idset[i];
            if (hash_get(oldSet->htable, id) >= 0) {
                space->updateidset[space->updateid++] = id;
            }
            else {
                space->newidset[space->newid++] = id;
            }
        }
    
        for (uint32_t i = 0; i < oldSet->last; ++i) {
            int64_t id = oldSet->idset[i];
            if (hash_get(newSet->htable, id) < 0) {
                space->delidset[space->delid++] = id;
            }
        }
    }
    
    
    void
    add_dnode(struct aoispace * space, struct dnode * node) {
        int slot = node->x;
        CHECK_MINMAX(slot, 0, MAX_POSITION);
        struct dnode* curnode = space->dlinks[slot];
        struct dnode* cur = curnode;
        struct dnode* pre = cur->yPrev;
        while (cur != NULL) {
            if (cur->y > node->y) {
                node->yNext = cur;
                node->yPrev = cur->yPrev;
                cur->yPrev->yNext = node;
                cur->yPrev = node;
                int yslot = node->y;
                CHECK_MINMAX(yslot, 0, MAX_POSITION);
                if (space->dnodearray[slot][yslot] == NULL) {
                    space->dnodearray[slot][yslot] = node;
                }
                else {
                    node->xNext = space->dnodearray[slot][yslot];
                    space->dnodearray[slot][yslot] = node;
                }
                return;
            }
            pre = cur;
            cur = cur->yNext;
        }
    
        pre->yNext = node;
        node->yPrev = pre;
    
        int yslot = node->y;
        CHECK_MINMAX(yslot, 0, MAX_POSITION);
        if (space->dnodearray[slot][yslot] == NULL) {
            space->dnodearray[slot][yslot] = node;
        }
        else {
            node->xNext = space->dnodearray[slot][yslot];
            space->dnodearray[slot][yslot] = node;
        }
    }
    
    //获取[x,y]aoirange内的对象集合 watcher 0: marker  1:watcher  (0:观察者得到被观察者,1:被观察者得到观察者)
    void getwatch(struct aoispace * space, uint32_t x, uint32_t y, uint32_t aoirange, char watcher, struct watchset* watchedset) {
        //reset
        watchedset->last = 0;
        hash_reset(watchedset->htable);
    
        if (aoirange == 0) {
            aoirange = AOI_RADIS;
        }
    
        int curslot = x;
        int startslot = curslot - aoirange;
        if (startslot < 0) startslot = 0;
        int endslot = curslot + aoirange;
        if (endslot >= MAX_POSITION) endslot = MAX_POSITION - 1;
    
        int startsloty = y - aoirange;
        if (startsloty < 0) startsloty = 0;
        int endsloty = y + aoirange;
        if (endsloty >= MAX_POSITION) endsloty = MAX_POSITION - 1;
    
        for (int i = startslot; i <= endslot; ++i) {
            struct dnode* first = NULL;
            for (int j = startsloty; j <= endsloty; ++j) {
                if (space->dnodearray[i][j] != NULL) {
                    first = space->dnodearray[i][j];//[1][1]
                    break;
                }
            }
            if (first == NULL) {
                continue;
    
            }
            struct dnode* curnode = first;
            while (curnode != NULL) {
                if (hash_get(watchedset->htable, curnode->id) >= 0) {
                    curnode = curnode->xNext;
                    std::cout << "dup" << std::endl;
                    continue;
                }
    
                if (watcher == 0 && (curnode->mode&MODE_WATCHER)) {
                    curnode = curnode->xNext;
                    continue;
                }
    
                if (watcher == 1 && (curnode->mode&MODE_MARKER)) {
                    curnode = curnode->xNext;
                    continue;
                }
    
                if (watcher == 1) {
                    //检查观察者视野
                    struct object* watcher = objhash_getobject(space->object, curnode->id);
                    if (watcher) {
                        if (watcher->position[0] + watcher->aoirange < x) {
                            curnode = curnode->xNext;
                            continue;
                        }
                        if (watcher->position[0] > watcher->aoirange + x) {
                            curnode = curnode->xNext;
                            continue;
                        }
                        if (watcher->position[1] + watcher->aoirange < y) {
                            curnode = curnode->xNext;
                            continue;
                        }
                        if (watcher->position[1] > watcher->aoirange + y) {
                            curnode = curnode->xNext;
                            continue;
                        }
                    }
                }
    
                watchedset->idset[watchedset->last++] = curnode->id;
                std::cout << "111add id:" << curnode->id << " x:" << curnode->x << " y" << curnode->y << std::endl;
                hash_set(watchedset->htable, curnode->id, 1);
                curnode = curnode->xNext;
            }
            curnode = first->yNext;//[1][2]
            while (curnode != NULL) {
                if (hash_get(watchedset->htable, curnode->id) >= 0) {
                    curnode = curnode->yNext;
                    std::cout << "dup" << std::endl;
                    continue;
                }
    
                if (watcher == 0 && (curnode->mode&MODE_WATCHER)) {
                    curnode = curnode->yNext;
                    continue;
                }
    
                if (watcher == 1 && (curnode->mode&MODE_MARKER)) {
                    curnode = curnode->yNext;
                    continue;
                }
    
                if (watcher == 1) {
                    //检查观察者视野
                    struct object* watcher = objhash_getobject(space->object, curnode->id);
                    if (watcher) {
                        if (watcher->position[0] + watcher->aoirange < x) {
                            curnode = curnode->yNext;
                            continue;
                        }
                        if (watcher->position[0] > watcher->aoirange + x) {
                            curnode = curnode->yNext;
                            continue;
                        }
                        if (watcher->position[1] + watcher->aoirange < y) {
                            curnode = curnode->yNext;
                            continue;
                        }
                        if (watcher->position[1] > watcher->aoirange + y) {
                            curnode = curnode->yNext;
                            continue;
                        }
                    }
                }
    
                if (curnode->y + aoirange < y) {
                    curnode = curnode->yNext;
                    continue;
                }
    
                if (curnode->y > aoirange + y) {
                    break;
                }
                watchedset->idset[watchedset->last++] = curnode->id;
                std::cout << "222add id:" << curnode->id << " x:" << curnode->x << " y" << curnode->y << std::endl;
                hash_set(watchedset->htable, curnode->id, 1);
                curnode = curnode->yNext;
            }
        }
    }
    
    //
    void
    getmarkers(struct aoispace * space, struct object * obj) {
        copy_watchset(space->lastSet, obj->watchedset);
        getwatch(space, obj->position[0], obj->position[1], obj->aoirange, 0, obj->watchedset);
        compare_watchset(space, obj->watchedset, space->lastSet);
        //printf("obj %d watch total = %d,lasttotal = %d,new = %d , del = %d, update = %d\n",obj->id,obj->watchedset->last,space->lastSet->last,space->newid,space->delid,space->updateid);
    };
    
    //一个对象的观察者集合
    void
    getwatchers(struct aoispace * space, struct object * obj) {
        getwatch(space, obj->position[0], obj->position[1], obj->aoirange, 1, space->lastSet);
    };
    
    struct dnode*
        new_objdnode(struct aoispace * space, int64_t id, int x, int y, int mode) {
            struct dnode* node = (struct dnode*)malloc(sizeof(*node));
            node->id = id;
            node->x = x;
            node->y = y;
            node->mode = mode;
            node->xPrev = NULL;
            node->xNext = NULL;
            node->yPrev = NULL;
            node->yNext = NULL;
            add_dnode(space, node);
            return node;
        };
    
    void
    update_objdnode(struct aoispace * space, struct dnode* node, int x, int y, int mode) {
        node->x = x;
        node->y = y;
        node->mode = mode;
        node->xPrev = NULL;
        node->xNext = NULL;
        node->yPrev = NULL;
        node->yNext = NULL;
        add_dnode(space, node);
    };
    
    void
    delete_objdnode(struct aoispace * space, struct dnode* node) {
        if (node) {
            free(node);
            node = NULL;
        }
    }
    
    void
    dnode_leave(struct aoispace * space, struct dnode * node) {
    
        if (!node) {
            return;
        }
    
        if (node->xPrev) {
            node->xPrev->xNext = node->xNext;
        }
    
        if (node->xNext) {
            node->xNext->xPrev = node->xPrev;
        }
    
        if (node->yPrev) {
            node->yPrev->yNext = node->yNext;
        }
        if (node->yNext) {
            node->yNext->yPrev = node->yPrev;
        }
    
        CHECK_MINMAX(node->x, 0, MAX_POSITION);
        CHECK_MINMAX(node->y, 0, MAX_POSITION);
        //dnodearray
        struct dnode* cur = space->dnodearray[node->x][node->y];
        struct dnode* pre = NULL;
        while (cur != NULL)
        {
            if (cur == node) {
                if (pre) {
                    pre->xNext = cur->xNext;
                }
                if (cur == space->dnodearray[node->x][node->y]) {
                    space->dnodearray[node->x][node->y] = cur->xNext;
                }
                cur->xNext = NULL;
            }
            pre = cur;
            cur = cur->xNext;
        }
    
        node->xPrev = NULL;
        node->xNext = NULL;
        node->yPrev = NULL;
        node->yNext = NULL;
    };
    
    
    
    static struct object *
    new_object(struct aoispace * space, struct objectdata* data) {
        struct object * obj = (struct object *)malloc(sizeof(*obj));
        obj->ref = 1;
        obj->id = data->id;
        obj->version = 0;
        obj->mode = 0;
        obj->aoirange = data->aoirange;
    
        obj->position[0] = data->x;
        obj->position[1] = data->y;
    
        if (data->iswatcher) {
            obj->mode |= MODE_WATCHER;
            obj->watchedset = new_watchset();
    
            //观察者也加入链表(只是保存)
            obj->patrolNum = 1;
            obj->patrolnodes = (struct dnode**)malloc(sizeof(struct dnode*));
            struct dnode* objdnode = new_objdnode(space, obj->id, data->x, data->y, obj->mode);
            obj->patrolnodes[0] = objdnode;
        }
    
        if (data->ismarker) {
    
            obj->mode |= MODE_MARKER;
    
            obj->patrols[0][0] = data->x;
            obj->patrols[0][1] = data->y;
            obj->patrolNum = data->patrolNum + 1;
    
            for (int i = 0; i < data->patrolNum; ++i) {
                obj->patrols[i + 1][0] = data->patrols[i][0];
                obj->patrols[i + 1][1] = data->patrols[i][1];
            }
    
            obj->patrolnodes = (struct dnode**)malloc(obj->patrolNum * sizeof(struct dnode*));
            for (int i = 0; i < obj->patrolNum; i++) {
                struct dnode* objdnode = new_objdnode(space, obj->id, obj->patrols[i][0], obj->patrols[i][1], obj->mode);
                obj->patrolnodes[i] = objdnode;
            }
        }
    
        return obj;
    }
    static void
    update_object(void *s, struct object * obj, struct objectdata* data) {
        struct aoispace * space = (struct aoispace *)s;
    
        if (obj->mode&MODE_WATCHER) {
            dnode_leave(space, obj->patrolnodes[0]);
            update_objdnode(space, obj->patrolnodes[0], data->x, data->y, obj->mode);
        }
    
        if (obj->mode&MODE_MARKER) {
    
            for (int i = 0; i < obj->patrolNum; i++) {
                dnode_leave(space, obj->patrolnodes[i]);
            }
    
            obj->patrols[0][0] = data->x;
            obj->patrols[0][1] = data->y;
    
            obj->patrolNum = data->patrolNum + 1;
    
            for (int i = 0; i < data->patrolNum; ++i) {
                obj->patrols[i + 1][0] = data->patrols[i][0];
                obj->patrols[i + 1][1] = data->patrols[i][1];
            }
    
            for (int i = 0; i < obj->patrolNum; i++) {
                if (obj->patrolnodes[i] != NULL) {
                    update_objdnode(space, obj->patrolnodes[i], obj->patrols[i][0], obj->patrols[i][1], obj->mode);
                }
                else
                {
                    struct dnode* objdnode = new_objdnode(space, obj->id, obj->patrols[i][0], obj->patrols[i][1], obj->mode);
                    obj->patrolnodes[i] = objdnode;
                }
            }
        }
    
        obj->position[0] = data->x;
        obj->position[1] = data->y;
    
        obj->aoirange = data->aoirange;
    }
    static void
    delete_object(void *s, struct object * obj) {
        //printf("delete_object...%d\n",obj->id);
        struct aoispace * space = (struct aoispace *)s;
    
        for (int i = 0; i < obj->patrolNum; i++) {
            delete_objdnode(space, obj->patrolnodes[i]);
        }
        free(obj->patrolnodes);
    
        if (obj->mode&MODE_WATCHER) {
            delete_watchset(space, obj->watchedset);
        }
        free(obj);
    }
    
    inline static void
    grab_object(struct object *obj) {
        ++obj->ref;
    }
    
    //objmgr
    inline static void
    drop_object(struct aoispace * space, struct object *obj) {
        --obj->ref;
        if (obj->ref <= 0) {
            for (int i = 0; i < obj->patrolNum; ++i) {
                dnode_leave(space, obj->patrolnodes[i]);
            }
    
            int64_t position = objhash_get(space->object, obj->id);
            if (position >= 0) {
                space->object->elm[position]->key = -1;
                space->object->elm[position]->value = NULL;
            }
    
            //objhash_set(space->object, obj->id);
    
            delete_object(space, obj);
        }
    }
    
    struct aoispace *
        aoispace_create(void) {
            struct aoispace *space = (struct aoispace *)malloc(sizeof(*space));
            space->object = objhash_init();
            space->dnodearray = (struct dnode***)malloc(MAX_POSITION * sizeof(struct dnode**));
            space->dlinks = (struct dnode**)malloc(MAX_POSITION * sizeof(struct dnode*));
            for (int i = 0; i < MAX_POSITION; i++) {
    
                space->dnodearray[i] = (struct dnode**)malloc(MAX_POSITION * sizeof(struct dnode*));
                for (int j = 0; j < MAX_POSITION; j++) {
                    space->dnodearray[i][j] = NULL;
                }
    
                space->dlinks[i] = (struct dnode*)malloc(sizeof(struct dnode));
                space->dlinks[i]->id = -1;
                space->dlinks[i]->x = 0;
                space->dlinks[i]->y = 0;
                space->dlinks[i]->mode = 0;
                space->dlinks[i]->yPrev = space->dlinks[i];
                space->dlinks[i]->yNext = NULL;
                space->dlinks[i]->xPrev = NULL;
                space->dlinks[i]->xNext = NULL;
            }
            space->lastSet = new_watchset();
            return space;
        }
    
    void
    aoispace_release(struct aoispace *space) {
    
        objhash_foreach(space->object, delete_object, space);
    
        objhash_release(space->object);
    
        for (int i = 0; i < MAX_POSITION; i++) {
            free(space->dnodearray[i]);
            free(space->dlinks[i]);
        }
        free(space->dnodearray);
        free(space->dlinks);
        delete_watchset(space, space->lastSet);
        free(space);
    }
    
    ///debug
    void
    dumpspacedlinks(struct aoispace *space) {
        //dump
        for (int i = 0; i < MAX_POSITION; ++i) {
            struct dnode* curnode = space->dlinks[i]->yNext;
            while (curnode != NULL)
            {
                printf("i=%d id=%ld,x=%d,y=%d\n", i, curnode->id, curnode->x, curnode->y);
                curnode = curnode->yNext;
            }
        }
    }
    
    //lua export func
    int
    linit(lua_State *L) {
        space = aoispace_create();
        //printf("aoispace_create..%p\n",space);    
        return 0;
    }
    
    int
    lexit(lua_State *L)
    {
        //printf("aoispace_release..%p\n",space);
        aoispace_release(space);
        return 0;
    }
    
    bool
    printluatable(lua_State *L, int index) {
        int level = 0;
        lua_pushnil(L);
        while (lua_next(L, -2) != 0) {
            int keyType = lua_type(L, -2);
            if (keyType == LUA_TNUMBER) {
                double value = lua_tonumber(L, -2);
                printf("\n%d--Key:%f ", level, value);
            }
            else if (keyType == LUA_TSTRING) {
                const char*  value = lua_tostring(L, -2);
                printf("\n%d--Key:%s ", level, value);
            }
            else {
                return false;
            }
    
            int valueType = lua_type(L, -1);
            switch (valueType) {
            case LUA_TNIL:
            {
                             break;
            }
            case LUA_TBOOLEAN:
            {
                                 int value = lua_toboolean(L, -1);
                                 printf("%d\n", value);
                                 break;
            }
            case LUA_TNUMBER:
            {
                                printf("%f\n", lua_tonumber(L, -1));
                                break;
            }
            case LUA_TSTRING:
            {
                                printf("%s\n", lua_tostring(L, -1));
                                break;
            }
            case LUA_TTABLE:
            {
                               level++;
                               int index = lua_gettop(L);
                               if (!printluatable(L, index)) {
                                   printf("popTable error in  popTable,error occured\n");
                                   return false;
                               }
                               break;
            }
            default:
            {
                       return false;
            }
            }
            lua_pop(L, 1);
        }
        return true;
    }
    
    bool
    parse_objectdata(lua_State *L, int index, struct objectdata* objdata) {
        lua_pushnil(L);
        while (lua_next(L, -2) != 0) {
    
            int keyType = lua_type(L, -2);
            int valueType = lua_type(L, -1);
    
            if (keyType == LUA_TSTRING) {
                const char*  key = lua_tostring(L, -2);
                if (!strcmp(key, "id")) {
                    objdata->id = lua_tonumber(L, -1);
                    //printf("level=%d, id=%d \n",level,objdata->id);
                }
                else if (!strcmp(key, "x")) {
                    objdata->x = lua_tonumber(L, -1);
                    //printf("level=%d, x=%d \n",level,objdata->x);
                }
                else if (!strcmp(key, "y")) {
                    objdata->y = lua_tonumber(L, -1);
                    //printf("level=%d, y=%d \n",level,objdata->y);
                }
                else if (!strcmp(key, "iswatcher")) {
                    objdata->iswatcher = lua_tonumber(L, -1);
                    //printf("level=%d, iswatcher=%d \n",level,objdata->iswatcher);
                }
                else if (!strcmp(key, "ismarker")) {
                    objdata->ismarker = lua_tonumber(L, -1);
                    //printf("level=%d, ismarker=%d \n",level,objdata->ismarker);
                }
                else if (!strcmp(key, "aoirange")) {
                    objdata->aoirange = lua_tonumber(L, -1);
                }
                else if (!strcmp(key, "patrols")) {
                }
                else if (!strcmp(key, "px")) {
                    objdata->patrols[objdata->patrolNum - 1][0] = lua_tonumber(L, -1);
                    //printf("level=%d, px=%d \n",level,objdata->patrols[objdata->patrolNum][0]);
                }
                else if (!strcmp(key, "py")) {
                    objdata->patrols[objdata->patrolNum - 1][1] = lua_tonumber(L, -1);
                    //printf("level=%d, py=%d \n",level,objdata->patrols[objdata->patrolNum][1]);
                }
                else {
                    printf("parse_objectdata error key = %s\n", key);
                    return false;
                }
            }
            else if (keyType == LUA_TNUMBER) {
                objdata->patrolNum = lua_tointeger(L, -2);
            }
    
            if (LUA_TTABLE == valueType) {
                int subindex = lua_gettop(L);
                parse_objectdata(L, subindex, objdata);
            }
    
            lua_pop(L, 1);
        }
        return true;
    }
    
    int
    laddobj(lua_State *L)
    {
        struct objectdata data;
        memset(&data, 0, sizeof(data));
        bool ret = parse_objectdata(L, 1, &data);
    
    
    
        if (ret) {
            lua_pushinteger(L, 1);
            for (int k = 0; k < 2; ++k)
            {
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        data.id = k * 100 + i * 10 + j;
                        data.x = i;
                        data.y = j;
    
                        data.iswatcher = 0;
                        data.ismarker = 1;
                        if (data.id == 0)
                        {
                            data.iswatcher = 1;
                            data.ismarker = 0;
                        }
    
    
    
                        data.aoirange = 300;
                        struct object* obj = objhash_getobject(space->object, data.id);
                        if (obj != NULL) {
                            printf("laddobj.. obj!=NULL  id = %ld", data.id);
                            lua_pushinteger(L, 0);
                            return 1;
                        }
    
                        struct object* newobj = new_object(space, &data);
    
                        objhash_set(space->object, data.id, newobj);
    
                        printf("laddobj..%p,%p\n", space, newobj);
                    }
                }
            }
    
        }
        else
        {
            lua_pushinteger(L, 0);
        }
        return 1;
    }
    
    int
    lupdateobj(lua_State *L)
    {
        struct objectdata data;
        memset(&data, 0, sizeof(data));
        bool ret = parse_objectdata(L, 1, &data);
        if (ret) {
            struct object* obj = objhash_getobject(space->object, data.id);
            if (obj == NULL) {
                printf("lupdateobj.. obj==NULL  id = %ld", data.id);
                lua_pushinteger(L, 0);
                return 0;
    
            }
            update_object(space, obj, &data);
            lua_pushinteger(L, 1);
        }
        else {
            lua_pushinteger(L, 0);
        }
        return 1;
    }
    
    int
    ldelobj(lua_State *L)
    {
        int64_t id = lua_tointeger(L, 1);
        struct object* obj = objhash_getobject(space->object, id);
        if (obj == NULL) {
            printf("ldelobj.. obj==NULL  id = %ld", id);
            return 0;
        }
        drop_object(space, obj);
        printf("ldelobj..%p,%p\n", space, obj);
        return 0;
    }
    
    //得到被观察对象集合
    int
    lgetmarkers(lua_State *L)
    {
        int64_t id = lua_tointeger(L, 1);
        struct object* obj = objhash_getobject(space->object, id);
        if (obj == NULL) {
            printf("lgetmakers.. obj==NULL  id = %ld\n", id);
            return 0;
        }
        if ((obj->mode & MODE_WATCHER) == 0) {
            printf("lgetmakers.. obj is not watcher  id = %ld\n", id);
            return 0;
        }
    
        printf("lgetmarkers..%p,%p\n", space, obj);
    
        getmarkers(space, obj);
    
        lua_newtable(L);
        lua_pushinteger(L, id);
        lua_setfield(L, -2, "id");//{["id"] = id}
        lua_newtable(L);
        for (uint32_t i = 0; i < space->newid; i++) {
            lua_pushinteger(L, space->newidset[i]);
            lua_rawseti(L, -2, i + 1);
        }
        lua_setfield(L, -2, "new"); //{["new"] = {11,22,33}}
    
        lua_newtable(L);
        for (uint32_t i = 0; i < space->updateid; i++) {
            lua_pushinteger(L, space->updateidset[i]);
            lua_rawseti(L, -2, i + 1);
        }
        lua_setfield(L, -2, "update"); //{["update"] = {22,33,44}}
    
        lua_newtable(L);
        for (uint32_t i = 0; i < space->delid; i++) {
            lua_pushinteger(L, space->delidset[i]);
            lua_rawseti(L, -2, i + 1);
        }
        lua_setfield(L, -2, "del");//{["del"] = {33,44,55}}
    
        //printf("stack size = %d\n", lua_gettop(L));
        return 1;
    }
    
    //得到观察对象集合
    int
    lgetwatchers(lua_State *L)
    {
        int64_t id = lua_tointeger(L, 1);
        printf("lgetwatchers..%p,%ld\n", space, id);
        struct object* obj = objhash_getobject(space->object, id);
        printf("lgetwatchers..%p,%p\n", space, obj);
        if (obj == NULL) {
            printf("lgetwatchers.. obj==NULL  id = %ld\n", id);
            return 0;
        }
        if ((obj->mode & MODE_MARKER) == 0) {
            printf("lgetwatchers.. obj is not watcher  id = %ld\n", id);
            return 0;
        }
    
        getwatchers(space, obj);
    
        lua_newtable(L);
        lua_pushinteger(L, id);
        lua_setfield(L, -2, "id");
    
        lua_newtable(L);
        for (uint32_t i = 0; i < space->lastSet->last; i++) {
            lua_pushinteger(L, space->lastSet->idset[i]);
            lua_rawseti(L, -2, i + 1);
        }
        lua_setfield(L, -2, "watchers");
    
        return 1;
    }
    
    //根据坐标算出视野内所有对象 
    int
    lgetwatch(lua_State *L)
    {
        int x = lua_tointeger(L, 1);
        int y = lua_tointeger(L, 2);
        int range = lua_tointeger(L, 3);
        int watcher = lua_tointeger(L, 4);
    
        getwatch(space, x, y, range, watcher, space->lastSet);
    
        lua_newtable(L);
        lua_newtable(L);
        for (uint32_t i = 0; i < space->lastSet->last; i++) {
            lua_pushinteger(L, space->lastSet->idset[i]);
            lua_rawseti(L, -2, i + 1);
        }
        lua_setfield(L, -2, "watch");
        return 1;
    }
    ///////lua
    int luaopen_aoispace(lua_State *L) {
    
        luaL_Reg l[] = {
            { "init", linit },
            { "exit", lexit },
            { "addobj", laddobj },
            { "updateobj", lupdateobj },
            { "delobj", ldelobj },
            { "getmarkers", lgetmarkers },
            { "getwatchers", lgetwatchers },
            { "getwatch", lgetwatch },
            { NULL, NULL }
        };
    
        //luaL_newlib(L, l);
        return 1;
    }
    
    
    
    int main()
    {
        lua_State* L = luaL_newstate();
        luaL_dofile(L, "Test.lua"); //执行"Test.lua"文件中的代码
        /* table is in the stack at index 't' */
        //lua_pushnil(L);  /* first key */
        //stackDump(L);
        //while (lua_next(L, 2) != 0) {
        //    /* uses 'key' (at index -2) and 'value' (at index -1) */
        //    printf("%s - %s\n",
        //        lua_typename(L, lua_type(L, -2)),
        //        lua_typename(L, lua_type(L, -1)));
        //    /* removes 'value'; keeps 'key' for next iteration */
        //    lua_pop(L, 1);
        //}
    
    
        linit(L);
        laddobj(L);
        lua_settop(L, 0);
        lua_pushnumber(L, 0);
        lgetmarkers(L);
    
        //lua_getglobal(L, "background");
        //if (!lua_istable(L, -1))
        //{
        //    return;
        //}
    
        //int red = getfield("r");
        //int green = getfield("g");
        //int blue = getfield("b");
        //dumpspacedlinks(space);
    
        getchar();
        return 0;
    }

     

    2022.3.16

    目前用的格子的方式。我觉得是九宫格的思维,把地图对象放到格子中
    之前aoi,是个链表,可以看成只有Y轴一条链,十字链表可以实现动态的视野范围,获取aoi时,只需要根据视野的x轴,遍历y轴链表
    我觉得对于大地图更节省内存,效率更好些,可以实现动态视野,但实现更复杂,九宫格实现简单些,不容易出bug

    ROK这种类型的游戏,视野变化很大,最大视野可能是最小视野的2倍以上,动态视野收益很大,视图同步包体积会减少很多在最小视野的时候,符合十字链表的使用场景。
    十字链表也有格子的概念,只是格子比较小,比如你们地图大小是1000x1000,一个坐标单位实际上是10

  • 相关阅读:
    代码审查如何做
    使用 Gitbook 打造你的电子书
    Ztree的简单使用和后台交互的写法(一)
    ORACLE 错误:oralce record is locked by another user
    easyUI增加视图分组的办法
    jquery 解析数据库中的json日期为正常的格式
    Bootstrap基本类和组件学习二
    bootstrap的学习-基础样式和排版一
    easyUI中tree的简单使用
    orancle的安装和配置
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/15999336.html
Copyright © 2020-2023  润新知