🐳 chore(库): 更新 lua ecs

develop
xiaojin 5 years ago
parent 1616446211
commit 6a8673d95d

@ -40,6 +40,7 @@ init_component_pool(struct entity_world *w, int index, int stride, int opt_size)
c->n = 0;
c->stride = stride;
c->id = NULL;
c->last_lookup = 0;
if (stride > 0) {
c->buffer = NULL;
} else {
@ -282,18 +283,23 @@ lookup_component(struct component_pool *pool, unsigned int eid, int guess_index)
int n = pool->n;
if (n == 0)
return -1;
if (guess_index + GUESS_RANGE >= n)
if (guess_index < 0 || guess_index >= pool->n)
return binary_search(pool->id, 0, pool->n, eid);
unsigned int *a = pool->id;
int lower = a[guess_index];
if (eid <= lower) {
if (eid == lower)
return guess_index;
return binary_search(a, 0, guess_index, eid);
}
if (guess_index + GUESS_RANGE*2 >= pool->n) {
return binary_search(a, guess_index + 1, pool->n, eid);
}
int higher = a[guess_index + GUESS_RANGE];
if (eid > higher) {
return binary_search(a, guess_index + GUESS_RANGE + 1, pool->n, eid);
}
int lower = a[guess_index];
if (eid < lower) {
return binary_search(a, 0, guess_index, eid);
}
return binary_search(a, guess_index, guess_index + GUESS_RANGE, eid);
return binary_search(a, guess_index + 1, guess_index + GUESS_RANGE + 1, eid);
}
static inline void
@ -1629,122 +1635,6 @@ 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);
int sorted_id = check_cid(L, w, 2);
int value_id = check_cid(L, w, 3);
int value = luaL_checkinteger(L, 4);
struct component_pool *c = &w->c[sorted_id];
int begin = 0, end = c->n;
if (sorted_id == value_id) {
while (begin < end) {
int mid = (begin + end)/2;
int * v = entity_iter_(w, value_id, mid);
if (*v == value) {
// found
lua_createtable(L, 2, 0);
lua_pushinteger(L, mid + 1);
lua_seti(L, -2, 1);
lua_pushinteger(L, sorted_id);
lua_seti(L, -2, 2);
return 1;
}
if (*v < value) {
begin = mid + 1;
} else {
end = mid;
}
}
} else {
while (begin < end) {
int mid = (begin + end)/2;
int index = entity_sibling_index_(w, sorted_id, mid, value_id);
if (index == 0) {
return luaL_error(L, "Invalid value component");
}
int * v = entity_iter_(w, value_id, index - 1);
if (*v == value) {
// found
lua_createtable(L, 2, 0);
lua_pushinteger(L, index);
lua_seti(L, -2, 1);
lua_pushinteger(L, sorted_id);
lua_seti(L, -2, 2);
return 1;
}
if (*v < value) {
begin = mid + 1;
} else {
end = mid;
}
}
}
return 0;
}
static int
lobject(lua_State *L) {
struct group_iter *iter = luaL_checkudata(L, 1, "ENTITY_GROUPITER");
@ -1866,6 +1756,26 @@ next_removed_index(int removed_index, struct component_pool *removed, unsigned i
return removed_index;
}
// remove reference object where id == 0
static void
remove_unused_reference(lua_State *L, struct component_pool *c, int from) {
int i;
int to = from;
for (i=from; i < c->n; i++) {
if (c->id[i]) {
c->id[to] = c->id[i];
lua_geti(L, -1, i+1);
lua_seti(L, -2, to+1);
++to;
}
}
for (i=to;i<=c->n;i++) {
lua_pushnil(L);
lua_seti(L, -2, i+1);
}
c->n = to;
}
static int
lupdate_reference(lua_State *L) {
struct entity_world *w = getW(L);
@ -1874,7 +1784,7 @@ lupdate_reference(lua_State *L) {
return 0;
int cid = check_cid(L, w, 2);
struct component_pool *reference = &w->c[cid];
if (reference == 0)
if (reference->n == 0)
return 0; // no reference
if (lua_getiuservalue(L, 1, cid * 2 + 2) != LUA_TTABLE) {
return luaL_error(L, "Invalid reference component %d", cid);
@ -1884,8 +1794,11 @@ lupdate_reference(lua_State *L) {
unsigned int removed_eid = removed->id[removed_index];
int index = find_boundary(0, reference->n, reference->id, removed_eid);
int reference_index = index + 1;
int removed_reference = 0;
for (i=index; i< reference->n; i++) {
if (lua_geti(L, -1, i+1) != LUA_TTABLE) {
int rtype = lua_geti(L, -1, i+1);
if (rtype != LUA_TBOOLEAN && rtype != LUA_TTABLE) {
// false means removed reference
return luaL_error(L, "Invalid reference object");
}
if (removed_eid) {
@ -1902,12 +1815,39 @@ lupdate_reference(lua_State *L) {
lua_pushinteger(L, reference_index);
++reference_index;
}
if (rtype == LUA_TBOOLEAN) {
// set id = 0, so removed_reference() can remove them
--reference_index;
reference->id[i] = 0;
if (removed_reference == 0) {
removed_reference = i + 1;
}
lua_pop(L, 2);
} else {
lua_seti(L, -2, 1);
lua_pop(L, 1);
}
}
if (removed_reference) {
remove_unused_reference(L, reference, removed_reference - 1);
}
return 0;
}
static int
ldumpid(lua_State *L) {
struct entity_world *w = getW(L);
int cid = check_cid(L, w, 2);
struct component_pool *c = &w->c[cid];
lua_createtable(L, c->n, 0);
int i;
for (i=0;i<c->n;i++) {
lua_pushinteger(L, c->id[i]);
lua_rawseti(L, -2, i+1);
}
return 1;
}
LUAMOD_API int
luaopen_ecs_core(lua_State *L) {
luaL_checkversion(L);
@ -1936,10 +1876,9 @@ luaopen_ecs_core(lua_State *L) {
{ "_object", lobject },
{ "_sync", lsync },
{ "_release", lrelease },
{ "_bsearch", lbsearch },
{ "_reuse", lreuse },
{ "_fetch", lfetch },
{ "_update_reference", lupdate_reference },
{ "_dumpid", ldumpid },
{ NULL, NULL },
};
luaL_setfuncs(L,l,0);

@ -11,9 +11,10 @@ w:register {
local r = {}
for i=1, 42 do
r[i] = w:new {
r[i] = {}
w:new {
value = i,
reference = true,
reference = r[i],
}
w:new {
value = -i,
@ -32,11 +33,15 @@ local function read(i)
return v.value
end
w:update()
w:remove(r[1])
w:remove(r[10])
w:remove(r[20])
w:remove(r[30])
w:remove_reference(r[40])
w:update()
for i=1,42 do

@ -35,10 +35,6 @@ for v in w:select "sort data:in index:in" do
print(v.data, v.index)
end
local iter = w:bsearch("sort", "index", 5)
w:sync("data:in", iter)
print("Found", iter.data)
w:register {
name = "sorted_index",
type = "int",
@ -52,7 +48,4 @@ for v in w:select "sorted_index:in data?in" do
print(v.sorted_index, "=>", v.data)
end
local iter = w:bsearch("sorted_index", "sorted_index", 4)
w:sync("data:in", iter)
print("Found", iter.data)
--w:remove(iter)

@ -16,10 +16,13 @@ w:new {
}
local function print_v()
local v = w:singleton("t", "t:in")
print(".a = ",v.t.a)
print(".b = ",v.t.b)
local v = w:singleton "t"
print(".a = ",v.a)
print(".b = ",v.b)
w:sync("t:in", v)
print(".a = ", v.t.a)
print(".a = ", v.t.b)
end
local ctx = w:context { "t" }

@ -26,6 +26,12 @@ w:new {
vector = { x = 1, y = 2 },
text = "Hello World",
mark = true,
index = 2,
}
w:new {
text = "Hello World 2",
mark = true,
index = 1,
}
@ -38,6 +44,11 @@ for v in w:select "mark" do
end
end
local ids = w:dumpid "sort"
for idx, id in ipairs(ids) do
print(idx, id)
end

@ -279,7 +279,6 @@ function M:new(obj)
local typenames = context[self].typenames
local reference = obj.reference
if reference then
reference = {}
obj.reference = nil
end
for k,v in pairs(obj) do
@ -295,6 +294,7 @@ function M:new(obj)
reference[1] = id
reference[2] = REFERENCE_ID
self:object("reference", id, reference)
obj.reference = reference
return reference
end
end
@ -401,27 +401,9 @@ function M:order(sorted, refname, order_array)
self:_orderkey(sid, rid, order_array)
end
function M:bsearch(sorted, name, value)
function M:dumpid(name)
local typenames = context[self].typenames
local sorted_id = typenames[sorted].id
local value_id = typenames[name].id
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
return self:_dumpid(typenames[name].id)
end
function M:update()
@ -429,6 +411,12 @@ function M:update()
self:_update()
end
function M:remove_reference(ref)
ref.reference = false
self:sync("reference:out", ref)
ref[1] = nil
end
do
local _object = M._object
function M:object(name, refid, v)
@ -436,9 +424,22 @@ do
return _object(pat, v, refid)
end
function M:singleton(name, v)
local pat = context[self].ref[name]
return _object(pat, v, 1)
function M:singleton(name, pattern, iter)
local typenames = context[self].typenames
if iter == nil then
iter = { 1, typenames[name].id }
if pattern then
local p = context[self].select[pattern]
self:_sync(p, iter)
end
return iter
else
iter[1] = 1
iter[2] = typenames[name].id
local p = context[self].select[pattern]
self:_sync(p, iter)
end
return iter
end
end

Loading…
Cancel
Save