]> granicus.if.org Git - nethack/commitdiff
Add lua object references
authorPasi Kallinen <paxed@alt.org>
Thu, 26 Dec 2019 16:43:39 +0000 (18:43 +0200)
committerPasi Kallinen <paxed@alt.org>
Thu, 26 Dec 2019 17:15:24 +0000 (19:15 +0200)
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
include/obj.h
include/patchlevel.h
src/mkobj.c
src/nhlobj.c
src/nhlua.c
src/restore.c

index 2d7947e6284a6bfce6fa451a773733f961bfb1c3..75463909b3c2615660394e6e6ede780c5c668234 100644 (file)
@@ -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
 
index 1a1a5b418e3e0de1b7591a02af4b79d41911db78..3f8784309cdf937be173cbf45199e674effc531c 100644 (file)
@@ -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 */
 };
 
index 8fd411eb1291c1818ac116c0d9183b61448f51d9..e69cf51f816f92a468a7aecf399da30540e2c38a 100644 (file)
@@ -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 \
index 54416100e87ccc411bb4fb326bd0097021aa34e2..dbbd9c974d2cf0641cc0c4854553ba92dfff9b76 100644 (file)
@@ -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);
 }
 
index f7c9b56370f75f5c48a421c7c02c5a4a86df900d..1223603b8d630944119de1acfdf3bad3c8289b38 100644 (file)
@@ -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
index b6afc2e59e8e1ad275246c036c75c99bb5782dc6..a4c7e0473bbe45a9c7faf3097061f75ec5b16910 100644 (file)
@@ -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;
 }
index 7217718f197316be32f861119bdb193a6a6ea3f5..297080abca0e70129e3b13c8fa5c96d3ef8723ad 100644 (file)
@@ -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;