|
|
|
|
@ -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);
|
|
|
|
|
|