From b5659bc39b9dffa62a3181874d8bf148c464bdb5 Mon Sep 17 00:00:00 2001 From: xiaojin Date: Thu, 5 Aug 2021 17:03:43 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B3=20chore(=E5=BA=93):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/lualib-src/lua-ecs/luaecs.c | 140 +++++++++++++++++- framework/lualib-src/lua-ecs/test11.lua | 30 ++++ framework/lualib-src/lua-ecs/test12.lua | 48 ++++++ framework/lualib-src/lua-ecs/test9.lua | 8 + framework/lualib/3rd/misc/dump.lua | 1 + framework/lualib/3rd/misc/ecs.lua | 65 ++++++-- framework/lualib/3rd/misc/ltdiff.lua | 84 +++++++++++ .../lualib/zeus/skynet/{cs.lua => lock.lua} | 7 +- framework/simulation/simulation.lua | 4 +- framework/skynet | 2 +- 10 files changed, 371 insertions(+), 18 deletions(-) create mode 100644 framework/lualib-src/lua-ecs/test11.lua create mode 100644 framework/lualib-src/lua-ecs/test12.lua create mode 100644 framework/lualib/3rd/misc/dump.lua create mode 100644 framework/lualib/3rd/misc/ltdiff.lua rename framework/lualib/zeus/skynet/{cs.lua => lock.lua} (88%) diff --git a/framework/lualib-src/lua-ecs/luaecs.c b/framework/lualib-src/lua-ecs/luaecs.c index f716fa2..9cdb1cb 100644 --- a/framework/lualib-src/lua-ecs/luaecs.c +++ b/framework/lualib-src/lua-ecs/luaecs.c @@ -245,7 +245,8 @@ insert_id(lua_State *L, int world_index, struct entity_world *w, int cid, unsign } } } - add_component_id_(L, world_index, w, cid, eid); + // 0xffffffff max uint avoid check + add_component_id_(L, world_index, w, cid, 0xffffffff); memmove(c->id + from + 1, c->id + from, sizeof(unsigned int) * (c->n - from - 1)); c->id[from] = eid; } @@ -1628,6 +1629,65 @@ lorderkey(lua_State *L) { return 0; } +static int +search_id(lua_State *L, int begin, int end, struct entity_world *w, int cid, int64_t value) { + while (begin < end) { + int mid = (begin + end)/2; + int64_t * v = entity_iter_(w, cid, mid); + if (*v == value) { + // found + lua_pushinteger(L, mid + 1); + lua_seti(L, -2, 1); + return 1; + } + if (*v < value) { + begin = mid + 1; + } else { + end = mid; + } + } + return 0; +} + +static int +lfetch(lua_State *L) { + struct entity_world *w = getW(L); + int cid = check_cid(L, w, 2); + lua_Integer value = luaL_checkinteger(L, 3); + struct component_pool *c = &w->c[cid]; + if (c->stride != sizeof(int64_t)) { + return luaL_error(L, "Id component is not int64"); + } + if (lua_istable(L, 4)) { + // cache iter + lua_settop(L, 4); + lua_geti(L, 4, 1); + int mid = lua_tointeger(L, -1) - 1; + lua_pop(L, 1); + if (mid >=0 && mid < c->n) { + int64_t * v = entity_iter_(w, cid, mid); + if (*v == value) + return 1; + if (*v < value) { + return search_id(L, mid+1, c->n, w, cid, value); + } else { + if (mid > GUESS_RANGE) { + return search_id(L, mid - GUESS_RANGE, mid, w, cid, value) || + search_id(L, 0, mid - GUESS_RANGE, w, cid, value); + } + return search_id(L, 0, mid, w, cid, value); + } + } + return 0; + } else { + // new iter + lua_createtable(L, 2, 0); + lua_pushinteger(L, cid); + lua_seti(L, -2, 2); + return search_id(L, 0, c->n, w, cid, value); + } +} + static int lbsearch(lua_State *L) { struct entity_world *w = getW(L); @@ -1774,6 +1834,80 @@ lreuse(lua_State *L) { return 1; } +static int +find_boundary(int from, int to, unsigned int *a, unsigned int eid) { + while(from < to) { + int mid = (from + to)/2; + unsigned int aa = a[mid]; + if (aa == eid) + return mid; + else if (aa < eid) { + from = mid + 1; + } else { + to = mid; + } + } + return to; +} + +static inline int +next_removed_index(int removed_index, struct component_pool *removed, unsigned int *removed_eid) { + for (;;) { + ++removed_index; + if (removed_index >= removed->n) { + *removed_eid = 0; + break; + } + unsigned int last_eid = *removed_eid; + *removed_eid = removed->id[removed_index]; + if (*removed_eid != last_eid) + break; + } + return removed_index; +} + +static int +lupdate_reference(lua_State *L) { + struct entity_world *w = getW(L); + struct component_pool *removed = &w->c[ENTITY_REMOVED]; + if (removed->n == 0) // no removed entity + return 0; + int cid = check_cid(L, w, 2); + struct component_pool *reference = &w->c[cid]; + if (reference == 0) + return 0; // no reference + if (lua_getiuservalue(L, 1, cid * 2 + 2) != LUA_TTABLE) { + return luaL_error(L, "Invalid reference component %d", cid); + } + int i; + int removed_index = 0; + unsigned int removed_eid = removed->id[removed_index]; + int index = find_boundary(0, reference->n, reference->id, removed_eid); + int reference_index = index + 1; + for (i=index; i< reference->n; i++) { + if (lua_geti(L, -1, i+1) != LUA_TTABLE) { + return luaL_error(L, "Invalid reference object"); + } + if (removed_eid) { + while (removed_eid < reference->id[i]) { + removed_index = next_removed_index(removed_index, removed, &removed_eid); + } + } + if (removed_eid == reference->id[i]) { + // removed reference, clear reference id + lua_pushnil(L); + removed_index = next_removed_index(removed_index, removed, &removed_eid); + } else { + // update reference id + lua_pushinteger(L, reference_index); + ++reference_index; + } + lua_seti(L, -2, 1); + lua_pop(L, 1); + } + return 0; +} + LUAMOD_API int luaopen_ecs_core(lua_State *L) { luaL_checkversion(L); @@ -1792,7 +1926,7 @@ luaopen_ecs_core(lua_State *L) { { "_newtype",lnew_type }, { "_newentity", lnew_entity }, { "_addcomponent", ladd_component }, - { "update", lupdate }, + { "_update", lupdate }, { "_clear", lclear_type }, { "_context", lcontext }, { "_groupiter", lgroupiter }, @@ -1804,6 +1938,8 @@ luaopen_ecs_core(lua_State *L) { { "_release", lrelease }, { "_bsearch", lbsearch }, { "_reuse", lreuse }, + { "_fetch", lfetch }, + { "_update_reference", lupdate_reference }, { NULL, NULL }, }; luaL_setfuncs(L,l,0); diff --git a/framework/lualib-src/lua-ecs/test11.lua b/framework/lualib-src/lua-ecs/test11.lua new file mode 100644 index 0000000..6e3ece1 --- /dev/null +++ b/framework/lualib-src/lua-ecs/test11.lua @@ -0,0 +1,30 @@ +local ecs = require "ecs" + +local w = ecs.world() + +w:register { + name = "id", + type = "int64", +} + +w:register { + name = "data", + type = "lua", +} + +for i = 1 , 10 do + w:new { + id = i, + data = "Hello " .. i, + } +end + +local function fetch(id) + local v = w:sync("data:in", w:fetch("id", id)) + return v.data +end + +for i = 1, 10 do + print(fetch(i)) +end + diff --git a/framework/lualib-src/lua-ecs/test12.lua b/framework/lualib-src/lua-ecs/test12.lua new file mode 100644 index 0000000..d629fbc --- /dev/null +++ b/framework/lualib-src/lua-ecs/test12.lua @@ -0,0 +1,48 @@ +local ecs = require "ecs" + +local w = ecs.world() + +w:register { + name = "value", + type = "int", +} + + +local r = {} + +for i=1, 42 do + r[i] = w:new { + value = i, + reference = true, + } + w:new { + value = -i, + } +end + +for v in w:select("value:in") do + print(v.value) + if v.value < 0 then + w:remove(v) + end +end + +local function read(i) + local v = w:sync("value:in", r[i]) + return v.value +end + +w:remove(r[1]) +w:remove(r[10]) +w:remove(r[20]) +w:remove(r[30]) + +w:update() + +for i=1,42 do + print(pcall(read,i)) +end + +for v in w:select("value:in") do + print(v.value) +end diff --git a/framework/lualib-src/lua-ecs/test9.lua b/framework/lualib-src/lua-ecs/test9.lua index e618540..2e8e27c 100644 --- a/framework/lualib-src/lua-ecs/test9.lua +++ b/framework/lualib-src/lua-ecs/test9.lua @@ -17,12 +17,20 @@ w:register { name = "mark" } +w:register { + name = "index", + type = "int", +} + w:new { vector = { x = 1, y = 2 }, text = "Hello World", mark = true, + index = 1, } +w:sort("sort", "index") + for v in w:select "mark" do w:readall(v) for k,v in pairs(v) do diff --git a/framework/lualib/3rd/misc/dump.lua b/framework/lualib/3rd/misc/dump.lua new file mode 100644 index 0000000..317c71f --- /dev/null +++ b/framework/lualib/3rd/misc/dump.lua @@ -0,0 +1 @@ +return "mm" \ No newline at end of file diff --git a/framework/lualib/3rd/misc/ecs.lua b/framework/lualib/3rd/misc/ecs.lua index 93bf6b5..8b9b1e0 100644 --- a/framework/lualib/3rd/misc/ecs.lua +++ b/framework/lualib/3rd/misc/ecs.lua @@ -1,5 +1,7 @@ local ecs = require "ecs.core" +local REFERENCE_ID = 1 + local function get_attrib(opt, inout) if opt == nil then return { exist = true } @@ -12,7 +14,7 @@ local function get_attrib(opt, inout) end if inout == "in" then desc.r = true - elseif inout == "out" or inout == "new" then + elseif inout == "out" then desc.w = true elseif inout == "update" then desc.r = true @@ -61,17 +63,20 @@ local function cache_world(obj, k) local function gen_all_pat() local desc = {} local i = 1 + local _ORDERKEY = ecs._ORDERKEY for name,t in pairs(c.typenames) do - local a = { - name = t.name, - id = t.id, - type = t.type, - opt = true, - r = true, - } - table.move(t, 1, #t, 1, a) - desc[i] = a - i = i + 1 + if t.size ~= _ORDERKEY then + local a = { + name = t.name, + id = t.id, + type = t.type, + opt = true, + r = true, + } + table.move(t, 1, #t, 1, a) + desc[i] = a + i = i + 1 + end end return desc end @@ -272,6 +277,11 @@ function M:new(obj) -- dump(obj) local eid = self:_newentity() local typenames = context[self].typenames + local reference = obj.reference + if reference then + reference = {} + obj.reference = nil + end for k,v in pairs(obj) do local tc = typenames[k] if not tc then @@ -280,6 +290,13 @@ function M:new(obj) local id = self:_addcomponent(eid, tc.id) self:object(k, id, v) end + if reference then + local id = self:_addcomponent(eid, REFERENCE_ID) + reference[1] = id + reference[2] = REFERENCE_ID + self:object("reference", id, reference) + return reference + end end function M:ref(name, refobj) @@ -391,6 +408,27 @@ function M:bsearch(sorted, name, value) return self:_bsearch(sorted_id, value_id, value) end +function M:fetch(idtype, id) + local c = context[self].typenames[idtype] + local f = c.fetch + if not f then + f = setmetatable({}, { __mode = "kv" }) + c.fetch = f + end + local cid = c.id + local iter = f[id] + local ret = self:_fetch(cid, id, iter) + if not iter then + f[id] = ret + end + return ret +end + +function M:update() + self:_update_reference(REFERENCE_ID) + self:_update() +end + do local _object = M._object function M:object(name, refid, v) @@ -412,6 +450,11 @@ function ecs.world() size = 0, tag = true, } + w:register { + name = "reference", + type = "lua", + } + assert(context[w].typenames.reference.id == REFERENCE_ID) return w end diff --git a/framework/lualib/3rd/misc/ltdiff.lua b/framework/lualib/3rd/misc/ltdiff.lua new file mode 100644 index 0000000..b2181b8 --- /dev/null +++ b/framework/lualib/3rd/misc/ltdiff.lua @@ -0,0 +1,84 @@ +-- https://github.com/LuaDist-testing/ltdiff + +local ltdiff = {} + +local function table_diff(A, B) + local diff = { + del = {}, + mod = {}, + sub = {}, + } + + for k, v in pairs(A) do + if type(A[k]) == "function" or type(A[k]) == "userdata" then + error("table_diff only supports diffs of tables!") + elseif B[k] ~= nil and type(A[k]) == "table" and type(B[k]) == "table" then + diff.sub[k] = table_diff(A[k], B[k]) + + if next(diff.sub[k]) == nil then + diff.sub[k] = nil + end + elseif B[k] == nil then + diff.del[#(diff.del) + 1] = k + elseif B[k] ~= v then + diff.mod[k] = B[k] + end + end + + for k, v in pairs(B) do + if type(B[k]) == "function" or type(B[k]) == "userdata" then + error("table_diff only supports diffs of tables!") + elseif diff.sub[k] ~= nil then + -- skip + elseif A[k] ~= nil and type(A[k]) == "table" and type(B[k]) == "table" then + diff.sub[k] = table_diff(B[k], A[k]) + + if next(diff.sub[k]) == nil then + diff.sub[k] = nil + end + elseif B[k] ~= A[k] then + diff.mod[k] = v + end + end + + if next(diff.sub) == nil then + diff.sub = nil + end + + if next(diff.mod) == nil then + diff.mod = nil + end + + if next(diff.del) == nil then + diff.del = nil + end + + return diff +end + +local function table_patch(A, diff) + if diff.sub ~= nil then + for k, v in pairs(diff.sub) do + A[k] = table_patch(A[k], v) + end + end + + if diff.del ~= nil then + for _, v in pairs(diff.del) do + A[v] = nil + end + end + + if diff.mod ~= nil then + for k, v in pairs(diff.mod) do + A[k] = v + end + end + + return A +end + +ltdiff.diff = table_diff +ltdiff.patch = table_patch + +return ltdiff diff --git a/framework/lualib/zeus/skynet/cs.lua b/framework/lualib/zeus/skynet/lock.lua similarity index 88% rename from framework/lualib/zeus/skynet/cs.lua rename to framework/lualib/zeus/skynet/lock.lua index 66c5354..d7a1af5 100644 --- a/framework/lualib/zeus/skynet/cs.lua +++ b/framework/lualib/zeus/skynet/lock.lua @@ -1,3 +1,4 @@ +-- https://github.com/cloudwu/skynet/pull/1419 local skynet = require "skynet" local coroutine = coroutine @@ -6,7 +7,9 @@ local tinsert = table.insert local tremove = table.remove local setmetatable = setmetatable -function skynet.cs() +-- local scope_lock = lock() + +function skynet.lock() local current_thread local ref = 0 local thread_queue = {} @@ -37,4 +40,4 @@ function skynet.cs() end end -return skynet.cs +return skynet.lock diff --git a/framework/simulation/simulation.lua b/framework/simulation/simulation.lua index 938f95d..8ede01a 100644 --- a/framework/simulation/simulation.lua +++ b/framework/simulation/simulation.lua @@ -10,6 +10,7 @@ if not ok then return end +local dump = require "dump" local termfx = require "termfx" local ui = require "simpleui" @@ -43,7 +44,6 @@ local function main(token) termfx.present() - local evt = termfx.pollevent(100) if evt then if evt.type == 'key' then @@ -67,7 +67,7 @@ local function main(token) local r, msgid, msg = recv_msg() if r == true then - table.insert(msg_list, {MN[msgid] or msgid, inspect(msg)}) + table.insert(msg_list, {MN[msgid] or msgid, dump(msg)}) elseif r == false then p('网络断开,结束客户端', msgid) break diff --git a/framework/skynet b/framework/skynet index bc298e4..0d56381 160000 --- a/framework/skynet +++ b/framework/skynet @@ -1 +1 @@ -Subproject commit bc298e4a91d016df653e9a48f118672d209a3a05 +Subproject commit 0d5638125b8f7fcab8bbe93343ca36a57820a717