├── .gitmodules ├── Makefile ├── README.md ├── aoi.lua ├── lua-aoi.c └── service_aoi.c /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "aoi"] 2 | path = aoi 3 | url = https://github.com/cloudwu/aoi.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | SKYNET_ROOT ?= ../../skynet/ 3 | include $(SKYNET_ROOT)platform.mk 4 | 5 | LUA_CLIB_PATH ?= $(SKYNET_ROOT)/../luaclib/ 6 | 7 | SKYNET_SRC ?= $(SKYNET_ROOT)skynet-src/ 8 | SKYNET_LUA_INC ?= $(SKYNET_ROOT)3rd/lua 9 | SKYNET_LUA_LIB ?= $(SKYNET_ROOT)3rd/lua/ 10 | 11 | 12 | CAOI_SO = $(LUA_CLIB_PATH)/caoi.so 13 | # LAOI_SO = $(LUA_CLIB_PATH)/laoi.so 14 | 15 | LFLAGS = $(SHARED) -I$(SKYNET_LUA_INC) -llua -L$(SKYNET_LUA_LIB) 16 | 17 | all: $(CAOI_SO) #$(LAOI_SO) 18 | 19 | $(CAOI_SO): service_aoi.c $< 20 | $(CC) $(LFLAGS) -o $@ $(CFLAGS) $< -I$(SKYNET_SRC) 21 | 22 | # $(LAOI_SO): lua-aoi.c 23 | # gcc -O2 -Wall $^ -fPIC --shared -o $@ -llua -I$(SKYNET_SRC) -I$(SKYNET_LUA_INC) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # skynet_aoi 2 | 3 | 请移步 [aoi](https://github.com/cloudfreexiao/pluto/tree/main/pluto/luaclib/lua-aoi) 4 | -------------------------------------------------------------------------------- /aoi.lua: -------------------------------------------------------------------------------- 1 | local skynet = require "skynet" 2 | local queue = require "skynet.queue" 3 | require "skynet.manager" 4 | 5 | local enumtype = 6 | { 7 | CHAR_TYPE_PLAYER = 1, 8 | CHAR_TYPE_MONSTER = 2, 9 | } 10 | 11 | local CMD = {} 12 | local OBJ = {} 13 | local playerview = {} 14 | local monsterview = {} 15 | local aoi 16 | local update_thread 17 | local need_update 18 | local map_name = ... 19 | local mapagent 20 | local luaqueue = queue() 21 | 22 | local AOI_RADIS = 200 23 | local AOI_RADIS2 = AOI_RADIS * AOI_RADIS 24 | local LEAVE_AOI_RADIS2 = AOI_RADIS2 * 4 25 | 26 | local function DIST2(p1,p2) 27 | return ((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z)) 28 | end 29 | 30 | skynet.register_protocol { 31 | name = "text", 32 | id = skynet.PTYPE_TEXT, 33 | pack = function(text) return text end, 34 | unpack = function(buf, sz) return skynet.tostring(buf,sz) end, 35 | } 36 | 37 | --怪物移动的时候通知玩家信息 38 | local function updateviewmonster(monstertempid) 39 | if monsterview[monstertempid] == nil then return end 40 | local myobj = OBJ[monstertempid] 41 | local mypos = myobj.movement.pos 42 | --离开他人视野 43 | local leavelist = {} 44 | --进入他人视野 45 | local enterlist = {} 46 | --通知他人自己移动 47 | local movelist = {} 48 | 49 | local othertempid 50 | local otherpos 51 | local otheragent 52 | local otherobj 53 | for k,v in pairs(monsterview[monstertempid]) do 54 | othertempid = OBJ[k].tempid 55 | otherpos = OBJ[k].movement.pos 56 | otheragent = OBJ[k].agent 57 | otherobj = { 58 | tempid = othertempid, 59 | agent = OBJ[k].agent, 60 | } 61 | local distance = DIST2(mypos,otherpos) 62 | if distance <= AOI_RADIS2 then 63 | if not v then 64 | monsterview[monstertempid][k] = true 65 | playerview[k][monstertempid] = true 66 | table.insert(enterlist,OBJ[k]) 67 | else 68 | table.insert(movelist,otheragent) 69 | end 70 | elseif distance > AOI_RADIS2 and distance <= LEAVE_AOI_RADIS2 then 71 | if v then 72 | monsterview[monstertempid][k] = false 73 | playerview[k][monstertempid] = false 74 | table.insert(leavelist,otherobj) 75 | end 76 | else 77 | if v then 78 | table.insert(leavelist,otherobj) 79 | end 80 | monsterview[monstertempid][k] = nil 81 | playerview[k][monstertempid] = nil 82 | end 83 | end 84 | 85 | --离开他人视野 86 | for _,v in pairs(leavelist) do 87 | skynet.send(v.agent,"lua","delaoiobj",myobj.tempid) 88 | end 89 | 90 | --重新进入视野 91 | for _,v in pairs(enterlist) do 92 | skynet.send(v.agent,"lua","addaoiobj",myobj) 93 | end 94 | 95 | --视野范围内移动 96 | for _,v in pairs(movelist) do 97 | skynet.send(v,"lua","updateaoiobj",myobj) 98 | end 99 | 100 | skynet.send(myobj.agent,"lua","updateaoilist",myobj.tempid,enterlist,leavelist) 101 | end 102 | 103 | --根据对象类型插入table 104 | local function inserttotablebytype(t,v,type) 105 | if type ~= enumtype.CHAR_TYPE_PLAYER then 106 | table.insert(t.monsterlist,v) 107 | else 108 | table.insert(t.playerlist,v) 109 | end 110 | end 111 | 112 | --观看者坐标更新的时候 113 | --根据距离情况通知他人自己的信息 114 | local function updateviewplayer(viewertempid) 115 | if playerview[viewertempid] == nil then return end 116 | local myobj = OBJ[viewertempid] 117 | local mypos = myobj.movement.pos 118 | 119 | --离开他人视野 120 | local leavelist = { 121 | playerlist = {}, 122 | monsterlist = {}, 123 | } 124 | --进入他人视野 125 | local enterlist = { 126 | playerlist = {}, 127 | monsterlist = {}, 128 | } 129 | --通知他人自己移动 130 | local movelist = { 131 | playerlist = {}, 132 | monsterlist = {}, 133 | } 134 | 135 | local othertempid 136 | local otherpos 137 | local othertype 138 | local otherobj 139 | for k,v in pairs(playerview[viewertempid]) do 140 | othertempid = OBJ[k].tempid 141 | otherpos = OBJ[k].movement.pos 142 | othertype = OBJ[k].type 143 | otherobj = { 144 | tempid = othertempid, 145 | agent = OBJ[k].agent, 146 | } 147 | local distance = DIST2(mypos,otherpos) 148 | if distance <= AOI_RADIS2 then 149 | if not v then 150 | playerview[viewertempid][k] = true 151 | if othertype ~= enumtype.CHAR_TYPE_PLAYER then 152 | monsterview[k][viewertempid] = true 153 | table.insert(enterlist.monsterlist,OBJ[k]) 154 | else 155 | playerview[k][viewertempid] = true 156 | table.insert(enterlist.playerlist,OBJ[k]) 157 | end 158 | else 159 | inserttotablebytype(movelist,otherobj,othertype) 160 | end 161 | elseif distance > AOI_RADIS2 and distance <= LEAVE_AOI_RADIS2 then 162 | if v then 163 | playerview[viewertempid][k] = false 164 | if othertype ~= enumtype.CHAR_TYPE_PLAYER then 165 | monsterview[k][viewertempid] = false 166 | table.insert(leavelist.monsterlist,otherobj) 167 | else 168 | playerview[k][viewertempid] = false 169 | table.insert(leavelist.playerlist,otherobj) 170 | end 171 | end 172 | else 173 | if v then 174 | inserttotablebytype(leavelist,otherobj,othertype) 175 | end 176 | playerview[viewertempid][k] = nil 177 | if othertype ~= enumtype.CHAR_TYPE_PLAYER then 178 | monsterview[k][viewertempid] = nil 179 | else 180 | playerview[k][viewertempid] = nil 181 | end 182 | end 183 | end 184 | 185 | --离开他人视野 186 | for _,v in pairs(leavelist.playerlist) do 187 | skynet.send(v.agent,"lua","delaoiobj",viewertempid) 188 | end 189 | 190 | --重新进入视野 191 | for _,v in pairs(enterlist.playerlist) do 192 | skynet.send(v.agent,"lua","addaoiobj",myobj) 193 | end 194 | 195 | --视野范围内移动 196 | for _,v in pairs(movelist.playerlist) do 197 | skynet.send(v.agent,"lua","updateaoiobj",myobj) 198 | end 199 | 200 | --怪物的更新合并一起发送 201 | if not table.empty(leavelist.monsterlist) or 202 | not table.empty(enterlist.monsterlist) or 203 | not table.empty(movelist.monsterlist) then 204 | local monsterenterlist = { 205 | obj = myobj, 206 | monsterlist = enterlist.monsterlist, 207 | } 208 | local monsterleavelist = { 209 | tempid = viewertempid, 210 | monsterlist = leavelist.monsterlist, 211 | } 212 | local monstermovelist = { 213 | obj = myobj, 214 | monsterlist = movelist.monsterlist, 215 | } 216 | skynet.send(mapagent,"lua","updateaoiinfo",monsterenterlist,monsterleavelist,monstermovelist) 217 | end 218 | 219 | --通知自己 220 | skynet.send(myobj.agent,"lua","updateaoilist",enterlist,leavelist) 221 | end 222 | 223 | --aoi回调 224 | function CMD.aoicallback(w,m) 225 | assert(OBJ[w],w) 226 | assert(OBJ[m],m) 227 | 228 | if playerview[OBJ[w].tempid] == nil then 229 | playerview[OBJ[w].tempid] = {} 230 | end 231 | playerview[OBJ[w].tempid][OBJ[m].tempid] = true 232 | 233 | --怪物视野内的玩家 234 | if OBJ[m].type ~= enumtype.CHAR_TYPE_PLAYER then 235 | if monsterview[OBJ[m].tempid] == nil then 236 | monsterview[OBJ[m].tempid] = {} 237 | end 238 | monsterview[OBJ[m].tempid][OBJ[w].tempid] = true 239 | end 240 | 241 | --通知agent 242 | skynet.send(OBJ[w].agent,"lua","addaoiobj",OBJ[m]) 243 | if OBJ[m].type ~= enumtype.CHAR_TYPE_PLAYER then 244 | skynet.send(OBJ[m].agent,"lua","addaoiobj",OBJ[m].tempid,OBJ[w]) 245 | end 246 | end 247 | 248 | --添加到aoi 249 | function CMD.characterenter(obj) 250 | assert(obj) 251 | assert(obj.agent) 252 | assert(obj.movement) 253 | assert(obj.movement.mode) 254 | assert(obj.movement.pos.x) 255 | assert(obj.movement.pos.y) 256 | assert(obj.movement.pos.z) 257 | --log.debug("AOI ENTER %d %s %d %d %d",obj.tempid,obj.movement.mode,obj.movement.pos.x,obj.movement.pos.y,obj.movement.pos.z) 258 | OBJ[obj.tempid] = obj 259 | if obj.type ~= enumtype.CHAR_TYPE_PLAYER then 260 | updateviewmonster(obj.tempid) 261 | else 262 | updateviewplayer(obj.tempid) 263 | end 264 | assert(pcall(skynet.send,aoi, "text", "update "..obj.tempid.." "..obj.movement.mode.." "..obj.movement.pos.x.." "..obj.movement.pos.y.." "..obj.movement.pos.z)) 265 | need_update = true 266 | end 267 | 268 | --从aoi中移除 269 | --TODO 怪物的离开 270 | function CMD.characterleave(obj) 271 | assert(obj) 272 | skynet.error(obj.tempid, " leave aoi") 273 | assert(pcall(skynet.send, aoi, "text", "update "..obj.tempid.." d "..obj.movement.pos.x.." "..obj.movement.pos.y.." "..obj.movement.pos.z)) 274 | OBJ[obj.tempid] = nil 275 | if playerview[obj.tempid] then 276 | local monsterleavelist = { 277 | tempid = obj.tempid, 278 | monsterlist = {}, 279 | } 280 | for k,_ in pairs(playerview[obj.tempid]) do 281 | if playerview[k] then 282 | if playerview[k][obj.tempid] then 283 | --视野内需要通知 284 | skynet.send(OBJ[k].agent,"lua","delaoiobj",obj.tempid) 285 | end 286 | playerview[k][obj.tempid] = nil 287 | elseif monsterview[k] then 288 | if monsterview[k][obj.tempid] then 289 | --视野内需要通知 290 | table.insert(monsterleavelist.monsterlist,{tempid = k}) 291 | end 292 | monsterview[k][obj.tempid] = nil 293 | end 294 | end 295 | 296 | if not table.empty(monsterleavelist.monsterlist) then 297 | skynet.send(mapagent,"lua","updateaoiinfo",{monsterlist = {}},monsterleavelist,{monsterlist = {}}) 298 | end 299 | playerview[obj.tempid] = nil 300 | end 301 | need_update = true 302 | end 303 | 304 | --0.1秒更新一次 305 | local function message_update () 306 | if need_update then 307 | need_update = false 308 | assert(pcall(skynet.send,aoi, "text", "message ")) 309 | end 310 | update_thread = skynet.timeout(10, message_update) 311 | end 312 | 313 | function CMD.open() 314 | aoi = assert(skynet.launch("caoi", map_name)) 315 | assert(aoi == (skynet.self() + 1)) 316 | mapagent = skynet.self() - 1 317 | message_update() 318 | end 319 | 320 | function CMD.close(name) 321 | skynet.error("close aoi(%s)...",name) 322 | update_thread() 323 | end 324 | 325 | skynet.start(function() 326 | skynet.dispatch("text", function (_, _, cmd) 327 | local t = cmd:split(" ") 328 | local f = CMD[t[1]] 329 | if f then 330 | luaqueue(f,tonumber(t[2]),tonumber(t[3])) 331 | else 332 | skynet.error("Unknown command : [%s]", cmd) 333 | end 334 | end) 335 | 336 | skynet.dispatch("lua", function (_,_, cmd, ...) 337 | local f = CMD[cmd] 338 | if f then 339 | skynet.ret(skynet.pack(luaqueue(f, ...))) 340 | else 341 | skynet.error("Unknown command : [%s]", cmd) 342 | skynet.response()(false) 343 | end 344 | end) 345 | end) 346 | -------------------------------------------------------------------------------- /lua-aoi.c: -------------------------------------------------------------------------------- 1 | #define LUA_LIB 2 | 3 | #include "aoi/aoi.h" 4 | #include "skynet.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // https://blog.codingnow.com/2012/03/dev_note_13.html 11 | // https://blog.codingnow.com/2008/07/aoi.html 12 | 13 | struct laoi_cookie 14 | { 15 | int count; 16 | int max; 17 | int current; 18 | }; 19 | 20 | struct laoi_space 21 | { 22 | struct lua_State *L; 23 | struct aoi_space *space; 24 | struct laoi_cookie cookie; 25 | }; 26 | 27 | static void 28 | message(void *ud, uint32_t watcher, uint32_t marker) 29 | { 30 | // printf("%u => %u\n", watcher, marker); 31 | struct laoi_space *aux = (struct laoi_space *)(ud); 32 | struct lua_State *L = aux->L; 33 | if (L == NULL) 34 | { 35 | printf("%s\n", "L is empty."); 36 | return; 37 | } 38 | lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); 39 | lua_getfield(L, -1, "aoi_callback"); // function 40 | lua_pushinteger(L, watcher); 41 | lua_pushinteger(L, marker); 42 | lua_pcall(L, 2, 0, 0); 43 | return; 44 | } 45 | 46 | static void * 47 | my_alloc(void *ud, void *ptr, size_t sz) 48 | { 49 | struct laoi_space *aux = ud; 50 | struct laoi_cookie *cookie = &aux->cookie; 51 | if (ptr == NULL) 52 | { 53 | void *p = skynet_malloc(sz); 54 | ++cookie->count; 55 | cookie->current += sz; 56 | if (cookie->max < cookie->current) 57 | { 58 | cookie->max = cookie->current; 59 | } 60 | 61 | return p; 62 | } 63 | --cookie->count; 64 | cookie->current -= sz; 65 | 66 | skynet_free(ptr); 67 | return NULL; 68 | } 69 | 70 | static int 71 | lnew(lua_State *L) 72 | { 73 | struct laoi_space *aux = (struct laoi_space *)lua_newuserdata(L, sizeof(*aux)); 74 | if (aux == NULL) 75 | { 76 | luaL_error(L, "malloc failture.\n"); 77 | return 0; 78 | } 79 | else 80 | { 81 | lua_pushvalue(L, lua_upvalueindex(1)); 82 | lua_setmetatable(L, -2); 83 | 84 | aux->L = L; 85 | lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); 86 | lua_newtable(L); 87 | lua_rawsetp(L, -2, aux); 88 | lua_pop(L, 1); 89 | 90 | struct laoi_cookie cookie = {0, 0, 0}; 91 | aux->cookie = cookie; 92 | struct aoi_space *space = aoi_create(my_alloc, aux); 93 | aux->space = space; 94 | 95 | return 1; 96 | } 97 | } 98 | 99 | static int 100 | lrelease(lua_State *L) 101 | { 102 | if (lua_gettop(L) >= 1) 103 | { 104 | struct laoi_space *aux = (struct laoi_space *)lua_touserdata(L, 1); 105 | struct aoi_space *space = aux->space; 106 | aoi_release(space); 107 | return 0; 108 | } 109 | else 110 | { 111 | luaL_error(L, "must be."); 112 | return 0; 113 | } 114 | } 115 | 116 | static int 117 | lupdate(lua_State *L) 118 | { 119 | luaL_checktype(L, 1, LUA_TUSERDATA); 120 | struct laoi_space *aux = (struct laoi_space *)lua_touserdata(L, 1); 121 | struct aoi_space *space = aux->space; 122 | lua_Integer id = luaL_checkinteger(L, 2); 123 | const char *m = luaL_checkstring(L, 3); 124 | lua_Number x = luaL_checknumber(L, 4); 125 | lua_Number y = luaL_checknumber(L, 5); 126 | lua_Number z = luaL_checknumber(L, 6); 127 | float pos[3] = {x, y, z}; 128 | aoi_update(space, id, m, pos); 129 | return 0; 130 | } 131 | 132 | static int 133 | lmessage(lua_State *L) 134 | { 135 | luaL_checktype(L, 1, LUA_TUSERDATA); 136 | luaL_checktype(L, 2, LUA_TFUNCTION); 137 | struct laoi_space *aux = (struct laoi_space *)lua_touserdata(L, 1); 138 | aux->L = L; 139 | struct aoi_space *space = aux->space; 140 | 141 | lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); 142 | lua_pushvalue(L, 2); 143 | lua_setfield(L, -2, "aoi_callback"); 144 | aoi_message(space, message, aux); 145 | return 0; 146 | } 147 | 148 | static int 149 | ldump(lua_State *L) 150 | { 151 | struct laoi_space *aux = (struct laoi_space *)lua_touserdata(L, 1); 152 | printf("max memory = %d, current memory = %d\n", aux->cookie.max, aux->cookie.current); 153 | return 0; 154 | } 155 | 156 | LUAMOD_API int 157 | luaopen_aoi_core(lua_State *L) 158 | { 159 | luaL_checkversion(L); 160 | lua_newtable(L); // met 161 | luaL_Reg l[] = { 162 | {"update", lupdate}, 163 | {"message", lmessage}, 164 | {"dump", ldump}, 165 | {NULL, NULL}, 166 | }; 167 | luaL_newlib(L, l); 168 | lua_setfield(L, -2, "__index"); 169 | lua_pushcclosure(L, lrelease, 0); 170 | lua_setfield(L, -2, "__gc"); 171 | lua_pushcclosure(L, lnew, 1); 172 | return 1; 173 | } 174 | -------------------------------------------------------------------------------- /service_aoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "skynet.h" 6 | #include "./aoi/aoi.h" 7 | 8 | 9 | struct alloc_cookie { 10 | int count; 11 | int max; 12 | int current; 13 | }; 14 | 15 | struct aoi_space_plus { 16 | struct alloc_cookie* cookie; 17 | struct aoi_space* space; 18 | }; 19 | 20 | static void * 21 | my_alloc(void *ud, void *ptr, size_t sz) { 22 | struct alloc_cookie *cookie = ud; 23 | if (ptr == NULL) { 24 | void *p = skynet_malloc(sz); 25 | ++cookie->count; 26 | cookie->current += sz; 27 | if (cookie->max < cookie->current) { 28 | cookie->max = cookie->current; 29 | } 30 | return p; 31 | } 32 | --cookie->count; 33 | cookie->current -= sz; 34 | skynet_free(ptr); 35 | return NULL; 36 | } 37 | 38 | static int 39 | getnumbercount(uint32_t n) { 40 | int count = 0; 41 | while (n != 0) { 42 | n = n / 10; 43 | ++count; 44 | } 45 | return count; 46 | } 47 | 48 | static void 49 | callbackmessage(void *ud, uint32_t watcher, uint32_t marker) { 50 | struct skynet_context *ctx = ud; 51 | size_t sz = getnumbercount(watcher) + getnumbercount(marker) + strlen("aoicallback") + 2; 52 | char *msg = skynet_malloc(sz); 53 | memset(msg, 0, sz); 54 | sprintf(msg, "aoicallback %d %d", watcher, marker); 55 | //caoi server的启动在laoi启动之后,handle理论是caoi = laoi + 1 56 | //如果失败,就需要换方式了 57 | skynet_send(ctx, 0, skynet_current_handle() - 1, PTYPE_TEXT | PTYPE_TAG_DONTCOPY, 0, (void *)msg, sz); 58 | } 59 | 60 | static void 61 | _parm(char *msg, int sz, int command_sz) { 62 | while (command_sz < sz) { 63 | if (msg[command_sz] != ' ') 64 | break; 65 | ++command_sz; 66 | } 67 | int i; 68 | for (i = command_sz; i < sz; i++) { 69 | msg[i - command_sz] = msg[i]; 70 | } 71 | msg[i - command_sz] = '\0'; 72 | } 73 | 74 | static void 75 | _ctrl(struct skynet_context *ctx, struct aoi_space *space, const void *msg, int sz) { 76 | char tmp[sz + 1]; 77 | memcpy(tmp, msg, sz); 78 | tmp[sz] = '\0'; 79 | char *command = tmp; 80 | int i; 81 | if (sz == 0) 82 | return; 83 | for (i = 0; i < sz; i++) { 84 | if (command[i] == ' ') { 85 | break; 86 | } 87 | } 88 | if (memcmp(command, "update", i) == 0) { 89 | _parm(tmp, sz, i); 90 | char *text = tmp; 91 | char *idstr = strsep(&text, " "); 92 | if (text == NULL) { 93 | return; 94 | } 95 | int id = strtol(idstr, NULL, 10); 96 | char *mode = strsep(&text, " "); 97 | if (text == NULL) { 98 | return; 99 | } 100 | float pos[3] = {0}; 101 | char *posstr = strsep(&text, " "); 102 | if (text == NULL) { 103 | return; 104 | } 105 | pos[0] = strtof(posstr, NULL); 106 | posstr = strsep(&text, " "); 107 | if (text == NULL) { 108 | return; 109 | } 110 | pos[1] = strtof(posstr, NULL); 111 | posstr = strsep(&text, " "); 112 | pos[2] = strtof(posstr, NULL); 113 | 114 | aoi_update(space, id, mode, pos); 115 | return; 116 | } 117 | if (memcmp(command, "message", i) == 0) 118 | { 119 | aoi_message(space, callbackmessage, ctx); 120 | return; 121 | } 122 | skynet_error(ctx, "[aoi] Unkown command : %s", command); 123 | } 124 | 125 | struct aoi_space_plus * 126 | caoi_create(void) { 127 | struct aoi_space_plus *space_plus = skynet_malloc(sizeof(struct aoi_space_plus)); 128 | memset(space_plus, 0, sizeof(*space_plus)); 129 | 130 | space_plus->cookie = skynet_malloc(sizeof(struct alloc_cookie)); 131 | memset(space_plus->cookie, 0, sizeof(*(space_plus->cookie))); 132 | 133 | space_plus->space = aoi_create(my_alloc, space_plus->cookie); 134 | return space_plus; 135 | } 136 | 137 | void caoi_release(struct aoi_space_plus *space_plus) { 138 | aoi_release(space_plus->space); 139 | skynet_free(space_plus->cookie); 140 | skynet_free(space_plus); 141 | } 142 | 143 | static int 144 | caoi_cb(struct skynet_context *context, void *ud, int type, int session, uint32_t source, const void *msg, size_t sz) { 145 | struct aoi_space *space = ud; 146 | switch (type) { 147 | case PTYPE_TEXT: 148 | _ctrl(context, space, msg, (int)sz); 149 | break; 150 | } 151 | 152 | return 0; 153 | } 154 | 155 | int caoi_init(struct aoi_space_plus *space_plus, struct skynet_context *ctx) { 156 | skynet_callback(ctx, space_plus->space, caoi_cb); 157 | return 0; 158 | } 159 | --------------------------------------------------------------------------------