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

 

posted @ 2022-03-13 00:44  zzyoucan  阅读(388)  评论(0编辑  收藏  举报