51 #include <boost/range/adaptors.hpp>
57 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
58 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
59 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
60 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
65 lua_getglobal(L,
"print");
69 std::stringstream
line;
79 lua_pushstring(L,
line.str().c_str());
83 lua_pushstring(L,
"No plugins available.\n");
91 std::this_thread::sleep_for(std::chrono::milliseconds{luaL_checkinteger(L, 1)});
98 lua_getglobal(
mState,
"wesnoth");
100 lua_setfield(
mState, -2,
"delay");
105 lua_setglobal(
mState,
"describe_plugins");
117 if (lua_status(T_) == LUA_OK) {
118 return "not started";
123 switch (lua_status(T_)) {
134 return started_ ? (lua_status(T_) == LUA_YIELD) : (lua_status(T_) == LUA_OK);
146 lua_rawget(L, LUA_REGISTRYINDEX);
147 if (!lua_istable(L,-1)) {
152 lua_pushinteger(L, lua_rawlen(L, -1) + 1);
154 lua_State * T = lua_newthread(L);
158 lua_rawset(L, LUA_REGISTRYINDEX);
168 DBG_LUA <<
"created thread: status = " << lua_status(T) << (lua_status(T) == LUA_OK ?
" == OK" :
" == ?");
169 DBG_LUA <<
"loading script from string:\n<<\n" << prog <<
"\n>>";
172 int errcode = luaL_loadstring(T, prog.c_str());
173 if (errcode != LUA_OK) {
174 const char * err_str = lua_tostring(T, -1);
175 std::string
msg = err_str ? err_str :
"null string";
177 std::string context =
"When parsing a string to a lua thread, ";
179 if (errcode == LUA_ERRSYNTAX) {
180 context +=
" a syntax error";
181 }
else if(errcode == LUA_ERRMEM){
182 context +=
" a memory error";
184 context +=
" an unknown error";
190 throw game::lua_error(
"Error when executing a script to make a lua thread.");
192 if (!lua_isfunction(T, -1)) {
193 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)) );
204 lua_pushstring(T, file.c_str());
207 throw game::lua_error(
"Error when executing a file to make a lua thread.");
209 if (!lua_isfunction(T, -1)) {
210 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)) );
226 static int impl_context_backend(lua_State * L, std::shared_ptr<lua_context_backend> backend, std::string req_name)
228 if (!backend->valid) {
229 luaL_error(L ,
"Error, you tried to use an invalid context object in a lua thread");
236 backend->requests.push_back(evt);
242 if (!backend->valid) {
243 luaL_error(L ,
"Error, you tried to use an invalid context object in a lua thread");
249 luaL_argerror(L, 1,
"Error, tried to parse a config but some fields were invalid");
267 for (std::size_t
i = 0;
i < queue.size(); ++
i) {
269 lua_pushstring(T_, queue[
i].name.c_str());
270 lua_rawseti(T_, -2, 1);
272 lua_rawseti(T_, -2, 2);
273 lua_rawseti(T_, -2,
i+1);
277 auto this_context_backend = std::make_shared<lua_context_backend>();
279 for (
const std::string & key : ctxt.
callbacks_ | boost::adaptors::map_keys ) {
280 lua_pushstring(T_, key.c_str());
282 lua_settable(T_, -3);
287 lua_pushstring(T_,
"name");
288 lua_pushstring(T_, ctxt.
name_.c_str());
289 lua_settable(T_, -3);
290 for (
const plugins_context::accessor_list::value_type & v : ctxt.
accessors_) {
291 const std::string & key = v.first;
293 lua_pushstring(T_, key.c_str());
295 lua_settable(T_, -3);
300 lua_resume(T_,
nullptr, 3, &numres);
304 this_context_backend->valid =
false;
306 if (lua_status(T_) != LUA_YIELD) {
307 LOG_LUA <<
"Thread status = '" << lua_status(T_) <<
"'";
308 if (lua_status(T_) != LUA_OK) {
309 std::stringstream ss;
310 ss <<
"encountered a";
311 switch(lua_status(T_)) {
319 ss <<
" error-handler ";
325 ss <<
"error:\n" << lua_tostring(T_, -1) <<
"\n";
static lua_State * get_new_thread(lua_State *L)
static lg::log_domain log_scripting_lua("scripting/lua")
static int intf_describe_plugins(lua_State *L)
static int impl_context_accessor(lua_State *L, std::shared_ptr< lua_context_backend > backend, plugins_context::accessor_function func)
static char * v_threadtableKey
static void *const threadtableKey
static int intf_delay(lua_State *L)
static int impl_context_backend(lua_State *L, std::shared_ptr< lua_context_backend > backend, std::string req_name)
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.
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, error_handler)
std::function< config(config)> accessor_function
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.
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
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(const std::string &str)
Length in characters of a UTF-8 string.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Error used to report an error in a lua script or in the lua interpreter.
std::vector< plugins_manager::event > requests
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.