Lua struct obj improvements
If the core frees the obj struct referred by lua, don't free it, just mark it as OBJ_LUAFREE - lua will free it in gc once all the references to it are gone.
This commit is contained in:
+2
-1
@@ -66,7 +66,8 @@ struct obj {
|
|||||||
#define OBJ_MIGRATING 5 /* object sent off to another level */
|
#define OBJ_MIGRATING 5 /* object sent off to another level */
|
||||||
#define OBJ_BURIED 6 /* object buried */
|
#define OBJ_BURIED 6 /* object buried */
|
||||||
#define OBJ_ONBILL 7 /* object on shk bill */
|
#define OBJ_ONBILL 7 /* object on shk bill */
|
||||||
#define NOBJ_STATES 8
|
#define OBJ_LUAFREE 8 /* object has been dealloc'd, but is ref'd by lua */
|
||||||
|
#define NOBJ_STATES 9
|
||||||
xchar timed; /* # of fuses (timers) attached to this obj */
|
xchar timed; /* # of fuses (timers) attached to this obj */
|
||||||
|
|
||||||
Bitfield(cursed, 1);
|
Bitfield(cursed, 1);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||||
* and save files.
|
* and save files.
|
||||||
*/
|
*/
|
||||||
#define EDITLEVEL 7
|
#define EDITLEVEL 8
|
||||||
|
|
||||||
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2019"
|
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2019"
|
||||||
#define COPYRIGHT_BANNER_B \
|
#define COPYRIGHT_BANNER_B \
|
||||||
|
|||||||
+10
-4
@@ -1969,6 +1969,7 @@ struct monst *mtmp;
|
|||||||
* OBJ_MIGRATING migrating chain
|
* OBJ_MIGRATING migrating chain
|
||||||
* OBJ_BURIED level.buriedobjs chain
|
* OBJ_BURIED level.buriedobjs chain
|
||||||
* OBJ_ONBILL on g.billobjs chain
|
* OBJ_ONBILL on g.billobjs chain
|
||||||
|
* OBJ_LUAFREE obj is dealloc'd from core, but still used by lua
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
obj_extract_self(obj)
|
obj_extract_self(obj)
|
||||||
@@ -1976,6 +1977,7 @@ struct obj *obj;
|
|||||||
{
|
{
|
||||||
switch (obj->where) {
|
switch (obj->where) {
|
||||||
case OBJ_FREE:
|
case OBJ_FREE:
|
||||||
|
case OBJ_LUAFREE:
|
||||||
break;
|
break;
|
||||||
case OBJ_FLOOR:
|
case OBJ_FLOOR:
|
||||||
remove_object(obj);
|
remove_object(obj);
|
||||||
@@ -2161,7 +2163,7 @@ void
|
|||||||
dealloc_obj(obj)
|
dealloc_obj(obj)
|
||||||
struct obj *obj;
|
struct obj *obj;
|
||||||
{
|
{
|
||||||
if (obj->where != OBJ_FREE)
|
if (obj->where != OBJ_FREE && obj->where != OBJ_LUAFREE)
|
||||||
panic("dealloc_obj: obj not free");
|
panic("dealloc_obj: obj not free");
|
||||||
if (obj->nobj)
|
if (obj->nobj)
|
||||||
panic("dealloc_obj with nobj");
|
panic("dealloc_obj with nobj");
|
||||||
@@ -2192,8 +2194,11 @@ struct obj *obj;
|
|||||||
|
|
||||||
if (obj->oextra)
|
if (obj->oextra)
|
||||||
dealloc_oextra(obj);
|
dealloc_oextra(obj);
|
||||||
if (obj->lua_ref_cnt)
|
if (obj->lua_ref_cnt) {
|
||||||
return; /* obj is referenced from a lua script, let lua gc free it */
|
/* obj is referenced from a lua script, let lua gc free it */
|
||||||
|
obj->where = OBJ_LUAFREE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
free((genericptr_t) obj);
|
free((genericptr_t) obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2430,7 +2435,8 @@ const char *mesg;
|
|||||||
static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
|
static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
|
||||||
"contained", "invent",
|
"contained", "invent",
|
||||||
"minvent", "migrating",
|
"minvent", "migrating",
|
||||||
"buried", "onbill" };
|
"buried", "onbill",
|
||||||
|
"luafree" };
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
where_name(obj)
|
where_name(obj)
|
||||||
|
|||||||
+27
-24
@@ -22,6 +22,8 @@ struct _lua_obj {
|
|||||||
struct obj *obj;
|
struct obj *obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define lobj_is_ok(lo) ((lo) && (lo)->obj && (lo)->obj->where != OBJ_LUAFREE)
|
||||||
|
|
||||||
struct _lua_obj *
|
struct _lua_obj *
|
||||||
l_obj_check(L, index)
|
l_obj_check(L, index)
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -46,7 +48,8 @@ lua_State *L;
|
|||||||
if (lo->obj->lua_ref_cnt > 0)
|
if (lo->obj->lua_ref_cnt > 0)
|
||||||
lo->obj->lua_ref_cnt--;
|
lo->obj->lua_ref_cnt--;
|
||||||
/* free-floating objects with no other refs are deallocated. */
|
/* free-floating objects with no other refs are deallocated. */
|
||||||
if (lo->obj->where == OBJ_FREE && !lo->obj->lua_ref_cnt) {
|
if (!lo->obj->lua_ref_cnt
|
||||||
|
&& (lo->obj->where == OBJ_FREE || lo->obj->where == OBJ_LUAFREE)) {
|
||||||
if (Has_contents(lo->obj)) {
|
if (Has_contents(lo->obj)) {
|
||||||
struct obj *otmp;
|
struct obj *otmp;
|
||||||
while ((otmp = lo->obj->cobj) != 0) {
|
while ((otmp = lo->obj->cobj) != 0) {
|
||||||
@@ -98,13 +101,12 @@ lua_State *L;
|
|||||||
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
nhl_error(L, "l_obj_getcontents: no obj");
|
nhl_error(L, "l_obj_getcontents: no obj");
|
||||||
if (!obj->cobj)
|
|
||||||
nhl_error(L, "l_obj_getcontents: no cobj");
|
|
||||||
|
|
||||||
(void) l_obj_push(L, obj->cobj);
|
(void) l_obj_push(L, obj->cobj);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Puts object inside another object. */
|
||||||
/* local box = obj.new("large chest");
|
/* local box = obj.new("large chest");
|
||||||
box.addcontent(obj.new("rock"));
|
box.addcontent(obj.new("rock"));
|
||||||
*/
|
*/
|
||||||
@@ -115,19 +117,21 @@ lua_State *L;
|
|||||||
struct _lua_obj *lobox = l_obj_check(L, 1);
|
struct _lua_obj *lobox = l_obj_check(L, 1);
|
||||||
struct _lua_obj *lo = l_obj_check(L, 2);
|
struct _lua_obj *lo = l_obj_check(L, 2);
|
||||||
struct obj *otmp;
|
struct obj *otmp;
|
||||||
|
int refs;
|
||||||
|
|
||||||
if (!lo->obj || !lobox->obj)
|
if (!lobj_is_ok(lo) || !lobj_is_ok(lobox))
|
||||||
nhl_error(L, "l_obj_add_to_container: no obj");
|
return 0;
|
||||||
|
|
||||||
if (!Is_container(lobox->obj))
|
refs = lo->obj->lua_ref_cnt;
|
||||||
nhl_error(L, "l_obj_add_to_container: not a container");
|
|
||||||
|
|
||||||
|
obj_extract_self(lo->obj);
|
||||||
otmp = add_to_container(lobox->obj, lo->obj);
|
otmp = add_to_container(lobox->obj, lo->obj);
|
||||||
|
|
||||||
/* was lo->obj merged? FIXME: causes problems if both lo->obj and
|
/* was lo->obj merged? */
|
||||||
the one it merged with are handled by lua. Use lo->state? */
|
if (otmp != lo->obj) {
|
||||||
if (otmp != lo->obj)
|
lo->obj->lua_ref_cnt += refs;
|
||||||
lo->obj = otmp;
|
lo->obj = otmp;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -135,6 +139,7 @@ lua_State *L;
|
|||||||
/* Get a table of object class data. */
|
/* Get a table of object class data. */
|
||||||
/* local odata = obj.class(otbl.otyp); */
|
/* local odata = obj.class(otbl.otyp); */
|
||||||
/* local odata = obj.class(obj.new("rock")); */
|
/* local odata = obj.class(obj.new("rock")); */
|
||||||
|
/* local odata = o:class(); */
|
||||||
static int
|
static int
|
||||||
l_obj_objects_to_table(L)
|
l_obj_objects_to_table(L)
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -217,7 +222,7 @@ lua_State *L;
|
|||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj || obj->where == OBJ_LUAFREE) {
|
||||||
nhl_add_table_entry_int(L, "NO_OBJ", 1);
|
nhl_add_table_entry_int(L, "NO_OBJ", 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -352,20 +357,19 @@ lua_State *L;
|
|||||||
{
|
{
|
||||||
int argc = lua_gettop(L);
|
int argc = lua_gettop(L);
|
||||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||||
|
int x, y;
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
nhl_error(L, "l_obj_placeobj: Wrong args");
|
nhl_error(L, "l_obj_placeobj: Wrong args");
|
||||||
|
|
||||||
if (lo && lo->obj) {
|
x = (int) luaL_checkinteger(L, 2);
|
||||||
int x, y;
|
y = (int) luaL_checkinteger(L, 3);
|
||||||
|
lua_pop(L, 3);
|
||||||
x = (int) luaL_checkinteger(L, 2);
|
|
||||||
y = (int) luaL_checkinteger(L, 3);
|
|
||||||
lua_pop(L, 3);
|
|
||||||
|
|
||||||
|
if (lobj_is_ok(lo)) {
|
||||||
|
obj_extract_self(lo->obj);
|
||||||
place_object(lo->obj, x, y);
|
place_object(lo->obj, x, y);
|
||||||
} else
|
}
|
||||||
nhl_error(L, "l_obj_placeobj: Wrong args");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -393,11 +397,10 @@ lua_State *L;
|
|||||||
{
|
{
|
||||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||||
|
|
||||||
if (lo && lo->obj && lo->obj->where == OBJ_CONTAINED) {
|
if (lo && lo->obj && lo->obj->where == OBJ_CONTAINED)
|
||||||
(void) l_obj_push(L, lo->obj->ocontainer);
|
(void) l_obj_push(L, lo->obj->ocontainer);
|
||||||
return 1;
|
else
|
||||||
}
|
(void) l_obj_push(L, NULL);
|
||||||
(void) l_obj_push(L, NULL);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +412,7 @@ lua_State *L;
|
|||||||
{
|
{
|
||||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||||
|
|
||||||
lua_pushboolean(L, lo && lo->obj);
|
lua_pushboolean(L, lobj_is_ok(lo));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,3 +64,21 @@ end
|
|||||||
if (oc3.class ~= "*") then
|
if (oc3.class ~= "*") then
|
||||||
error("object class is not *, part 3");
|
error("object class is not *, part 3");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local oc4 = o:class();
|
||||||
|
if (oc4.name ~= "rock") then
|
||||||
|
error("object class is not rock, part 4");
|
||||||
|
end
|
||||||
|
if (oc4.class ~= "*") then
|
||||||
|
error("object class is not *, part 4");
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- placing obj into container even when obj is somewhere else already
|
||||||
|
local o5 = obj.new("dagger");
|
||||||
|
o5:placeobj(u.ux, u.uy);
|
||||||
|
box:addcontent(o5);
|
||||||
|
|
||||||
|
|
||||||
|
local o6 = obj.new("statue");
|
||||||
|
o6:addcontent(obj.new("spellbook"));
|
||||||
|
|||||||
Reference in New Issue
Block a user