59 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
60 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
61 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
62 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
67 lua_getglobal(L,
"print");
71 std::stringstream
line;
81 lua_pushstring(L,
line.str().c_str());
85 lua_pushstring(L,
"No plugins available.\n");
93 std::this_thread::sleep_for(std::chrono::milliseconds{luaL_checkinteger(L, 1)});
102 lua_getglobal(
mState,
"wesnoth");
104 lua_setfield(
mState, -2,
"delay");
109 lua_setglobal(
mState,
"describe_plugins");
119 lua_setfield(
mState, -2,
"execute");
120 lua_setfield(
mState, -2,
"plugin");
129 if (lua_status(T_) == LUA_OK) {
130 return "not started";
135 switch (lua_status(T_)) {
146 return started_ ? (lua_status(T_) == LUA_YIELD) : (lua_status(T_) == LUA_OK);
158 lua_rawget(L, LUA_REGISTRYINDEX);
159 if (!lua_istable(L,-1)) {
164 lua_pushinteger(L, lua_rawlen(L, -1) + 1);
166 lua_State * T = lua_newthread(L);
170 lua_rawset(L, LUA_REGISTRYINDEX);
180 DBG_LUA <<
"created thread: status = " << lua_status(T) << (lua_status(T) == LUA_OK ?
" == OK" :
" == ?");
181 DBG_LUA <<
"loading script from string:\n<<\n" << prog <<
"\n>>";
184 int errcode = luaL_loadstring(T, prog.c_str());
185 if (errcode != LUA_OK) {
186 const char * err_str = lua_tostring(T, -1);
187 std::string
msg = err_str ? err_str :
"null string";
189 std::string context =
"When parsing a string to a lua thread, ";
191 if (errcode == LUA_ERRSYNTAX) {
192 context +=
" a syntax error";
193 }
else if(errcode == LUA_ERRMEM){
194 context +=
" a memory error";
196 context +=
" an unknown error";
202 throw game::lua_error(
"Error when executing a script to make a lua thread.");
204 if (!lua_isfunction(T, -1)) {
205 throw game::lua_error(std::string(
"Error when executing a script to make a lua thread -- function was not produced, found a ") + lua_typename(T, lua_type(T, -1)) );
216 lua_pushstring(T, file.c_str());
219 throw game::lua_error(
"Error when executing a file to make a lua thread.");
221 if (!lua_isfunction(T, -1)) {
222 throw game::lua_error(std::string(
"Error when executing a file to make a lua thread -- function was not produced, found a ") + lua_typename(T, lua_type(T, -1)) );
239 static int impl_context_backend(lua_State * L,
const std::shared_ptr<lua_context_backend>& backend, std::string req_name)
241 if (!backend->valid) {
242 luaL_error(L ,
"Error, you tried to use an invalid context object in a lua thread");
246 evt.
name = std::move(req_name);
249 backend->requests.push_back(evt);
255 if (!backend->valid) {
256 luaL_error(L ,
"Error, you tried to use an invalid context object in a lua thread");
262 luaL_argerror(L, 1,
"Error, tried to parse a config but some fields were invalid");
282 static const int CTX = 1, FUNC = 2, EVT = 3, EXEC = 4;
283 if(lua_gettop(L) == 2) lua_pushnil(L);
285 lua_pushboolean(L,
false);
286 lua_pushstring(L,
"context not valid");
290 lua_pushboolean(L,
false);
291 lua_pushstring(L,
"context cannot execute");
294 if(!lua_islightuserdata(L, EXEC)) {
295 lua_pushboolean(L,
false);
296 lua_pushstring(L,
"execute is not a thread");
301 if(
data[
"params"] != 0) {
302 lua_pushboolean(L,
false);
303 lua_pushstring(L,
"cannot execute function with parameters");
306 if(!lua_isnil(L, EVT))
data[
"name"] = luaL_checkstring(L, EVT);
307 lua_pushvalue(L, FUNC);
308 data[
"ref"] = luaL_ref(L, LUA_REGISTRYINDEX);
309 std::shared_ptr<lua_context_backend>* context =
static_cast<std::shared_ptr<lua_context_backend>*
>(lua_touserdata(L, EXEC));
313 lua_pushboolean(L,
false);
314 lua_pushstring(L,
e.what());
317 lua_pushboolean(L,
true);
329 for(
const auto& event : queue) {
330 events.add_child(event.name, event.data);
335 auto this_context_backend = std::make_shared<lua_context_backend>();
337 lua_pushstring(T_,
"valid");
338 lua_pushboolean(T_,
true);
339 lua_settable(T_, -3);
341 lua_pushstring(T_, key.c_str());
343 lua_settable(T_, -3);
346 lua_pushstring(T_,
"execute");
347 lua_pushlightuserdata(T_, &this_context_backend);
348 lua_settable(T_, -3);
353 lua_pushstring(T_,
"name");
354 lua_pushstring(T_, ctxt.
name_.c_str());
355 lua_settable(T_, -3);
356 lua_pushstring(T_,
"valid");
357 lua_pushboolean(T_,
true);
358 lua_settable(T_, -3);
359 for (
const plugins_context::accessor_list::value_type & v : ctxt.
accessors_) {
360 const std::string & key = v.first;
362 lua_pushstring(T_, key.c_str());
364 lua_settable(T_, -3);
368 lua_pushvalue(T_, -2);
369 lua_pushvalue(T_, -2);
372 lua_xmove(T_, owner_.get_state(), 2);
376 lua_resume(T_,
nullptr, 3, &numres);
380 this_context_backend->valid =
false;
382 if (lua_status(T_) != LUA_YIELD) {
383 LOG_LUA <<
"Thread status = '" << lua_status(T_) <<
"'";
384 if (lua_status(T_) != LUA_OK) {
385 std::stringstream ss;
386 ss <<
"encountered a";
387 switch(lua_status(T_)) {
395 ss <<
" error-handler ";
401 ss <<
"error:\n" << lua_tostring(T_, -1) <<
"\n";
409 lua_pushstring(owner_.get_state(),
"valid");
410 lua_pushboolean(owner_.get_state(),
false);
411 lua_settable(owner_.get_state(), -3);
412 lua_pushstring(owner_.get_state(),
"valid");
413 lua_pushboolean(owner_.get_state(),
false);
414 lua_settable(owner_.get_state(), -4);
415 lua_pop(owner_.get_state(), 2);
422 auto result = lk->run_binary_lua_tag(data);
423 int ref = result[
"ref"].to_int();
424 if(auto func = result.optional_child(
"executed")) {
425 lua_rawgeti(T_, LUA_REGISTRYINDEX, ref);
426 luaW_copy_upvalues(T_, *func);
427 luaL_unref(T_, LUA_REGISTRYINDEX, ref);
430 result.remove_children(
"executed");
431 result.remove_attribute(
"ref");
446 lua_pushvalue(L, -1);
448 lua_getinfo(L,
">u", &
info);
449 int funcindex = lua_absindex(L, -1);
450 for(
int i = 1;
i <=
info.nups;
i++, lua_pop(L, 1)) {
451 std::string_view name = lua_getupvalue(L, funcindex,
i);
453 lua_pushglobaltable(L);
454 }
else if(upvalues->has_attribute(name)) {
456 }
else if(upvalues->has_child(name)) {
457 const auto& child = upvalues->mandatory_child(name);
458 if(child[
"upvalue_type"] ==
"array") {
459 auto children = upvalues->child_range(name);
460 lua_createtable(L, children.size(), 0);
461 for(
const auto& cfg : children) {
463 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
465 }
else if(child[
"upvalue_type"] ==
"named tuple") {
466 auto children = upvalues->child_range(name);
467 std::vector<std::string>
names;
468 for(
const auto& cfg : children) {
469 names.push_back(cfg[
"name"]);
472 for(
const auto& cfg : children) {
474 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
476 }
else if(child[
"upvalue_type"] ==
"config") {
478 }
else if(child[
"upvalue_type"] ==
"function") {
480 lua_pushvalue(L, -1);
483 lua_setupvalue(L, funcindex,
i);
GAME_CONFIG_SETTER("debug", bool, application_lua_kernel)
static lua_State * get_new_thread(lua_State *L)
static lg::log_domain log_scripting_lua("scripting/lua")
static int impl_context_accessor(lua_State *L, const std::shared_ptr< lua_context_backend > &backend, const plugins_context::accessor_function &func)
static int intf_describe_plugins(lua_State *L)
static int impl_context_backend(lua_State *L, const std::shared_ptr< lua_context_backend > &backend, std::string req_name)
static int intf_execute(lua_State *L)
bool luaW_copy_upvalues(lua_State *L, const config &cfg)
static char * v_threadtableKey
static void *const threadtableKey
static int intf_delay(lua_State *L)
luaW_Registry & gameConfigReg()
std::vector< std::string > names
request_list run_script(const plugins_context &ctxt, const std::vector< plugins_manager::event > &queue)
thread(const thread &)=delete
thread * load_script_from_string(const std::string &)
std::vector< std::function< bool(void)> > request_list
thread * load_script_from_file(const std::string &)
A config object defines a single node in a WML file, with access to child nodes.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
virtual void log_error(char const *msg, char const *context="Lua error")
Error reporting mechanisms, used by virtual methods protected_call and load_string.
bool protected_call(int nArgs, int nRets, const error_handler &)
lua_kernel_base * execute_kernel_
std::function< config(config)> accessor_function
void notify_event(const std::string &name, const config &data)
std::string get_name(std::size_t idx)
static plugins_manager * get()
Definitions for the interface to Wesnoth Markup Language (WML).
Standard logging facilities (interface).
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
void luaW_push_namedtuple(lua_State *L, const std::vector< std::string > &names)
Push an empty "named tuple" onto the stack.
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
void luaW_pushscalar(lua_State *L, const config::attribute_value &v)
Converts an attribute value into a Lua object pushed at the top of the stack.
bool luaW_tableget(lua_State *L, int index, const char *key)
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
config luaW_serialize_function(lua_State *L, int func)
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Handling of system events.
void set_debug(bool new_debug)
void push_function(lua_State *L, const lua_function &f)
Pushes a std::function wrapper object onto the stack.
int load_file(lua_State *L)
Loads a Lua file and pushes the contents on the stack.
std::string register_table(lua_State *L)
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
std::decay_t< T > luaW_table_get_def(lua_State *L, int index, std::string_view k, const T &def)
returns t[k] where k is the table at index index and k is k or def if it is not convertible to the co...
Error used to report an error in a lua script or in the lua interpreter.
Holds a lookup table for members of one type of object.
std::vector< plugins_manager::event > requests
lua_kernel_base * execute
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.