[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: a few lua api questions:imbedding, object methods and object properties
- From: "Littlefield, Tyler" <tyler@...>
- Date: Tue, 23 Oct 2012 14:32:17 -0600
Hello all:
I've been working on a mud for a while, and my scripting engine is
rather primative. basically a mud is just a multi-user text-based game,
so it can be considered along the same lines as a game engine.
I'd really like to revamp my scripting system before it gets more
complicated than it is already. I'm not really sure how to do a couple
of things though.
First, triggers are obviously important. Currently I have events in game
that just fire when an action is performed, so I can extend these to hit
Lua.
I'm thinking each object will just do something like:
AddTrigger("give", onGive)
This will just bind the onGive function/callback into an event that will
be triggered when this happens. is that a decent idea? Every object that
is loaded gets it's code executed in a virtual table of sorts. It looks
something like this:
void Script::Execute(Entity* obj, const std::string &code)
{
lua_State* state = Script::GetState();
int ret = 0;
World* world = World::GetPtr();
if (!luaL_loadbuffer(state, code.c_str(), code.length(),
"execution")) // chunk is at -1
{
//we need to create the metatable and store it in the registry:
lua_pushinteger(state, obj->GetOnum());
lua_newtable(state); // create shadow environment table at -1
lua_settable(state, LUA_REGISTRYINDEX);
//now we get the table back again:
lua_pushinteger(state, obj->GetOnum());
lua_gettable(state, LUA_REGISTRYINDEX);
ObjectToStack(state, obj);
lua_setfield(state, -2, "this");
lua_getfield(state, LUA_REGISTRYINDEX, "meta"); //our metatable
is at -1
lua_setmetatable(state, -2); //set table and pop
lua_setfenv(state, -2); //sets the environment
ret = lua_pcall(state, 0, 0, 0);
if (ret)
{
world->WriteLog(lua_tostring(state, -1), SCRIPT, "script");
lua_pop(state, 1);
}
}
}
Is this recommended? The idea was to keep objects from having naming
collisions. For example if I had a function named foo on a sword and a
player. Would this also be something to use when loading global scripts?
Second, I'd really like to objify everything. For example in order to
send a message to a player currently, I have to do:
player.send(mob, "hello world!")
How hard would it be to attach ehese in classes somehow, so I just call
self:send("hello world!" or whatever?
Right now my registration is done in a table:
BOOL InitPlayerScript(Script* s)
{
lua_State* lstate = s->GetState();
luaL_newmetatable(lstate, "player");
lua_pushstring(lstate, "__index");
lua_pushvalue(lstate, -2);
lua_settable(lstate, -3);
luaL_openlib(lstate, "player", player_table, 0);
...
}
static const struct luaL_reg player_table [] =
{"GetTitle", SCR_GetTitle},
{"SetTitle", SCR_SetTitle},
...
{NULL, NULL}
};
int SCR_GetTitle(lua_State* l)
{
UserData* udata = NULL;
if (lua_gettop(l) != 1)
{
SCR_Error(l, "Invalid number of arguments to \'GetTitle\'.");
return 0;
}
udata = (UserData*)lua_touserdata(l, -1);
if (!IsPlayer(l, udata))
{
return 0;
}
lua_pushlstring(l, ((Player*)udata->ptr)->GetTitle().c_str(),
((Player*)udata->ptr)->GetTitle().length());
return 1;
}
int SCR_SetTitle(lua_State* l)
{
const char* title = NULL;
UserData* udata = NULL;
if (lua_gettop(l) != 2)
{
SCR_Error(l, "Invalid number of arguments to \'SetTitle\'.");
return 0;
}
title = lua_tostring(l, -1);
if (!title)
{
SCR_Error(l, "Argument 2 to \'SetTitle\' must be a string.");
return 0;
}
udata = (UserData*)lua_touserdata(l, -2);
if (!IsPlayer(l, udata))
{
return 0;
}
((Player*)udata->ptr)->SetTitle(title);
return 0;
}
Can something like this be more OO like?
Finally, I'm curious how to go about setting up object properties. a lot
of muds that have used lua (I was just looking at the Aard page) sets
stuff up
like ch for the calling player, self for the current object, then they
allow for like ch.gold, ch.int etc. I'm curious how this works. I know
about setting values on a table, but it seems that the table would have
to call it's underlying c++ object's GetGold method to retrieve it.
Thanks in advance, and sorry for all the questions.
--
Take care,
Ty
http://tds-solutions.net
The aspen project: a barebones light-weight mud engine:
http://code.google.com/p/aspenmud
He that will not reason is a bigot; he that cannot reason is a fool; he that dares not reason is a slave.