Add lua object references
Whenever a lua script references a core struct obj, increment a counter in the obj struct. Core code will not free the obj, if there are any lua references pointing to it, just makes it free-floating. When lua script ends, the lua gc will free the free-floating objects. Also exposes u.inventory to lua. Breaks save and bones compat.
This commit is contained in:
@@ -1675,6 +1675,7 @@ E int FDECL(l_selection_register, (lua_State *));
|
||||
|
||||
/* ### nhlobj.c ### */
|
||||
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
|
||||
E void FDECL(nhl_push_obj, (lua_State *, struct obj *));
|
||||
E int FDECL(l_obj_register, (lua_State *));
|
||||
#endif
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ struct obj {
|
||||
unsigned oeaten; /* nutrition left in food, if partly eaten */
|
||||
long age; /* creation date */
|
||||
long owornmask;
|
||||
unsigned lua_ref_cnt; /* # of lua script references for this object */
|
||||
struct oextra *oextra; /* pointer to oextra struct */
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 5
|
||||
#define EDITLEVEL 6
|
||||
|
||||
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2019"
|
||||
#define COPYRIGHT_BANNER_B \
|
||||
|
||||
@@ -444,6 +444,7 @@ long num;
|
||||
obj->owt = weight(obj);
|
||||
otmp->quan = num;
|
||||
otmp->owt = weight(otmp); /* -= obj->owt ? */
|
||||
otmp->lua_ref_cnt = 0;
|
||||
|
||||
g.context.objsplit.parent_oid = obj->o_id;
|
||||
g.context.objsplit.child_oid = otmp->o_id;
|
||||
@@ -797,6 +798,7 @@ boolean artif;
|
||||
otmp->lknown = 0;
|
||||
otmp->cknown = 0;
|
||||
otmp->corpsenm = NON_PM;
|
||||
otmp->lua_ref_cnt = 0;
|
||||
|
||||
if (init) {
|
||||
switch (let) {
|
||||
@@ -2178,8 +2180,10 @@ struct obj *obj;
|
||||
* list must track all objects that can have a light source
|
||||
* attached to it (and also requires lamplit to be set).
|
||||
*/
|
||||
if (obj_sheds_light(obj))
|
||||
if (obj_sheds_light(obj)) {
|
||||
del_light_source(LS_OBJECT, obj_to_any(obj));
|
||||
obj->lamplit = 0;
|
||||
}
|
||||
|
||||
if (obj == g.thrownobj)
|
||||
g.thrownobj = 0;
|
||||
@@ -2188,6 +2192,8 @@ struct obj *obj;
|
||||
|
||||
if (obj->oextra)
|
||||
dealloc_oextra(obj);
|
||||
if (obj->lua_ref_cnt)
|
||||
return; /* obj is referenced from a lua script, let lua gc free it */
|
||||
free((genericptr_t) obj);
|
||||
}
|
||||
|
||||
|
||||
16
src/nhlobj.c
16
src/nhlobj.c
@@ -43,8 +43,10 @@ lua_State *L;
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
if (lo && lo->obj) {
|
||||
/* free-floating objects are deallocated */
|
||||
if (lo->obj->where == OBJ_FREE) {
|
||||
if (lo->obj->lua_ref_cnt > 0)
|
||||
lo->obj->lua_ref_cnt--;
|
||||
/* free-floating objects with no other refs are deallocated. */
|
||||
if (lo->obj->where == OBJ_FREE && !lo->obj->lua_ref_cnt) {
|
||||
if (Has_contents(lo->obj)) {
|
||||
struct obj *otmp;
|
||||
while ((otmp = lo->obj->cobj) != 0) {
|
||||
@@ -71,10 +73,20 @@ struct obj *otmp;
|
||||
|
||||
lo->state = 0;
|
||||
lo->obj = otmp;
|
||||
if (otmp)
|
||||
otmp->lua_ref_cnt++;
|
||||
|
||||
return lo;
|
||||
}
|
||||
|
||||
void
|
||||
nhl_push_obj(L, otmp)
|
||||
lua_State *L;
|
||||
struct obj *otmp;
|
||||
{
|
||||
(void) l_obj_push(L, otmp);
|
||||
}
|
||||
|
||||
/* local o = obj.new("large chest");
|
||||
local cobj = o:contents(); */
|
||||
static int
|
||||
|
||||
@@ -839,6 +839,11 @@ lua_State *L;
|
||||
return nhl_push_anything(L, ustruct[i].type, ustruct[i].ptr);
|
||||
}
|
||||
|
||||
if (!strcmp(tkey, "inventory")) {
|
||||
nhl_push_obj(L, g.invent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nhl_error(L, "Unknown u table index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ struct obj *otmp;
|
||||
if (nhfp->structlevel)
|
||||
mread(nhfp->fd, (genericptr_t) otmp, sizeof(struct obj));
|
||||
|
||||
otmp->lua_ref_cnt = 0;
|
||||
/* next object pointers are invalid; otmp->cobj needs to be left
|
||||
as is--being non-null is key to restoring container contents */
|
||||
otmp->nobj = otmp->nexthere = (struct obj *) 0;
|
||||
|
||||
Reference in New Issue
Block a user