>By the sound of it, your decision to use metatables has got
> around the major sticking point I could see with fully
> integrating Lua with Smaug, that is the difficulty of
> keeping two copies of the data (like level). You mention
> using __index in the metatable, presumably you would use
> __newindex if you wanted to change something (like the
> level).
Exactly as you said. For example, ch and room are initialized with:
static const luaL_reg luaCHGetset[] = {
{ "__index", luaCHGet },
{ "__newindex", luaCHSet },
{ NULL, NULL }
};
static const luaL_reg luaRoomGetset[] = {
{ "__index", luaRoomGet },
{ "__newindex", luaRoomSet },
{ NULL, NULL }
};
I vaguely remember looking at __CALL (or similar) but didn't want to use anything not documented in the reference manual just in case. I don't remember what the need for that was now, so it can't have been that important.
The get/set functions are basically:
...
GETSTACKCH(C,1,"Expected CH","property access");
propName = luaL_checkstring(l,2);
if (ISNULL(propName)) return 0;
for (prop = chProps; prop->name != NULL; prop++) {
if (compares(prop->name,propName)) break;
}
...
Propnames is a simple table of property name, the variable type to return to Lua, a get function and a set function if set is allowed on that property. A friend of mine came up with this approach and I was skeptical about speed, but it really does work.
We never did go C++, but converting the property tables to a simple 27 way (alpha+other) hash would be trivial and bring down access time further. I have the tables ordered with the most commonly used properties at the beginning so we haven't really seen a need.
The fixed types for obj, ch, room, exit and mud make chaining commands very powerful too, for example:
-- give item academy-3 to razor, anywhere in game.
-- give is give(OBJ,CH,opts)
give(oload("academy-3"), getmob("razor",WORLD+PLRONLY))
Obviously checking each for nil would be cleaner, but this would fail gracefully with an error log if the object did not exist or the player was not around. Or:
-- load a copy of self in random room in zone.
-- used at death to make sure this mob always exists
-- somewhere without making it unkillable.
mload(self.key, getroom("aylor-"..math.random(1,100)))
The 'zonekey-number' is what we use instead of vnums. Vnum ranges would make it even easier.
Can't recommend strongly enough taking the leap and converting to Lua. We havent even touched on the potential of lua sockets for web/forum integration, social network
widgets etc yet.
|