From 6d8d3a9557ab9de89b200a7ff1bded083ab5f33d Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Thu, 26 Dec 2019 18:43:39 +0200 Subject: [PATCH] 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. --- include/extern.h | 1 + include/obj.h | 1 + include/patchlevel.h | 2 +- src/mkobj.c | 8 +++++++- src/nhlobj.c | 16 ++++++++++++++-- src/nhlua.c | 5 +++++ src/restore.c | 1 + 7 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/extern.h b/include/extern.h index 2d7947e62..75463909b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 diff --git a/include/obj.h b/include/obj.h index 1a1a5b418..3f8784309 100644 --- a/include/obj.h +++ b/include/obj.h @@ -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 */ }; diff --git a/include/patchlevel.h b/include/patchlevel.h index 8fd411eb1..e69cf51f8 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -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 \ diff --git a/src/mkobj.c b/src/mkobj.c index 54416100e..dbbd9c974 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -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); } diff --git a/src/nhlobj.c b/src/nhlobj.c index f7c9b5637..1223603b8 100644 --- a/src/nhlobj.c +++ b/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 diff --git a/src/nhlua.c b/src/nhlua.c index b6afc2e59..a4c7e0473 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -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; } diff --git a/src/restore.c b/src/restore.c index 7217718f1..297080abc 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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; -- 2.49.0