Author: silene
Date: Mon Apr 13 13:49:10 2009
New Revision: 34853
URL: http://svn.gna.org/viewcvs/wesnoth?rev=34853&view=rev
Log:
Added wesnoth.register_wml_action for Lua scripts to register new WML tags.
Modified:
trunk/src/scripting/lua.cpp
Modified: trunk/src/scripting/lua.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/scripting/lua.cpp?rev=34853&r1=34852&r2=34853&view=diff
==============================================================================
--- trunk/src/scripting/lua.cpp (original)
+++ trunk/src/scripting/lua.cpp Mon Apr 13 13:49:10 2009
@@ -61,6 +61,7 @@
static char const getunitKey = 0;
static char const handlerKey = 0;
static char const tstringKey = 0;
+static char const uactionKey = 0;
/**
* Converts a string into a Lua object pushed at the top of the stack.
@@ -516,6 +517,88 @@
goto continue_call_destructor;
}
+/**
+ * Proxy class for calling WML action handlers defined in Lua.
+ */
+struct lua_action_handler : game_events::action_handler
+{
+ lua_State *L;
+ unit_map *units;
+ int num;
+
+ lua_action_handler(lua_State *l, int n, unit_map *u)
+ : L(l), units(u), num(n) {}
+ void handle(game_events::event_handler &,
+ const game_events::queued_event &, const vconfig &);
+};
+
+void lua_action_handler::handle(game_events::event_handler &handler,
+ const game_events::queued_event &, const vconfig &cfg)
+{
+ // Store the event data in the registry.
+ lua_pushlightuserdata(L, (void *)&handlerKey);
+ event_handler_data *eh = static_cast<event_handler_data *>
+ (lua_newuserdata(L, sizeof(event_handler_data)));
+ eh->handler = &handler;
+ eh->units = units;
+ lua_settable(L, LUA_REGISTRYINDEX);
+
+ // Load the error handler from the registry.
+ lua_pushlightuserdata(L, (void *)&executeKey);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+
+ // Load the user function from the registry.
+ lua_pushlightuserdata(L, (void *)&uactionKey);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ lua_rawgeti(L, -1, num);
+ lua_remove(L, -2);
+
+ // Push the WML table argument.
+ lua_newtable(L);
+ table_of_wml_config(L, cfg.get_parsed_config());
+
+ int res = lua_pcall(L, 1, 0, -3);
+ if (res)
+ {
+ LOG_STREAM(err, lua)
+ << "Failure while running Lua action handler: "
+ << lua_tostring(L, -1) << '\n';
+ lua_pop(L, 2);
+ return;
+ }
+
+ lua_pop(L, 1);
+}
+
+/**
+ * Registers a function as WML action handler.
+ * - Arg 1: string containing the WML tag.
+ * - Arg 2: function taking a WML table as argument.
+ */
+static int lua_register_wml_action(lua_State *L)
+{
+ char const *m = luaL_checkstring(L, 1);
+
+ // Retrieve the unit map from the registry.
+ lua_pushlightuserdata(L, (void *)&handlerKey);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ event_handler_data *eh = static_cast<event_handler_data
*>(lua_touserdata(L, -1));
+
+ // Retrieve the user action table from the registry.
+ lua_pushlightuserdata(L, (void *)&uactionKey);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ size_t length = lua_objlen(L, -1);
+
+ // Push the function on it so that it is not collected.
+ lua_pushvalue(L, 2);
+ lua_rawseti(L, -2, length + 1);
+
+ // Create the proxy C++ action handler.
+ game_events::register_action_handler(m,
+ new lua_action_handler(L, length + 1, eh->units));
+ return 0;
+}
+
static int lua_message(lua_State *L)
{
char const *m = luaL_checkstring(L, 1);
@@ -546,14 +629,15 @@
// Put some callback functions in the scripting environment.
static luaL_reg const callbacks[] = {
- { "fire", &lua_fire },
- { "fire_event", &lua_fire_event },
- { "get_units", &lua_get_units },
- { "get_variable", &lua_get_variable },
- { "message", &lua_message },
- { "dofile", &lua_dofile },
- { "set_variable", &lua_set_variable },
- { "textdomain", &lua_textdomain },
+ { "fire", &lua_fire },
+ { "fire_event", &lua_fire_event },
+ { "get_units", &lua_get_units },
+ { "get_variable", &lua_get_variable },
+ { "message", &lua_message },
+ { "dofile", &lua_dofile },
+ { "set_variable", &lua_set_variable },
+ { "textdomain", &lua_textdomain },
+ { "register_wml_action", &lua_register_wml_action },
{ NULL, NULL }
};
luaL_register(L, "wesnoth", callbacks);
@@ -593,6 +677,11 @@
lua_pushnil(L);
lua_setglobal(L, "loadfile");
+ // Create the user action table.
+ lua_pushlightuserdata(L, (void *)&uactionKey);
+ lua_newtable(L);
+ lua_settable(L, LUA_REGISTRYINDEX);
+
// Store the error handler, then close debug.
lua_pushlightuserdata(L, (void *)&executeKey);
lua_getglobal(L, "debug");
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits