55 #include <SDL2/SDL_timer.h>
67 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
68 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
69 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
70 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
73 static const char *
Gen =
"name generator";
76 static const char *
Interp =
"lua interpreter";
85 template<VERSION_COMP_OP vop>
91 lua_pushboolean(L, result);
101 if(lua_isinteger(L, 2)) {
102 int n = lua_tointeger(L, 2) - 1;
104 if(
n >= 0 &&
size_t(
n) < components.size()) {
111 char const *m = luaL_checkstring(L, 2);
119 }
else if(strcmp(m,
"sep") == 0) {
128 static const std::vector<std::string> fields{
"major",
"minor",
"revision",
"is_canonical",
"special",
"sep"};
139 vers->~version_info();
159 if(luaL_testudata(L, 1,
Version)) {
165 if(lua_type(L, 1) == LUA_TSTRING) {
168 int major = luaL_checkinteger(L, 1), minor = luaL_optinteger(L, 2, 0), rev = luaL_optinteger(L, 3, 0);
169 std::string sep, special;
170 if(lua_type(L, -1) == LUA_TSTRING) {
171 special = lua_tostring(L, -1);
172 if(!special.empty() && std::isalpha(special[0])) {
175 sep.push_back(special[0]);
176 special = special.substr(1);
181 new(L)
version_info(major, minor, rev, sep[0], special);
183 if(luaL_newmetatable(L,
Version)) {
184 static const luaL_Reg metafuncs[] {
188 {
"__lt", &impl_version_compare<VERSION_COMP_OP::OP_LESS> },
189 {
"__le", &impl_version_compare<VERSION_COMP_OP::OP_LESS_OR_EQUAL> },
190 {
"__eq", &impl_version_compare<VERSION_COMP_OP::OP_EQUAL> },
194 luaL_setfuncs(L, metafuncs, 0);
195 luaW_table_set<std::string>(L, -1,
"__metatable",
Version);
197 lua_setmetatable(L, -2);
217 DBG_LUA <<
"intf_print called:";
218 std::size_t nargs = lua_gettop(L);
220 lua_getglobal(L,
"tostring");
221 for (std::size_t
i = 1;
i <= nargs; ++
i) {
222 lua_pushvalue(L, -1);
225 const char * str = lua_tostring(L, -1);
227 LOG_LUA <<
"'tostring' must return a value to 'print'";
246 static const char*
const prefix =
"Warning:\n ";
247 static std::ostringstream warning(prefix);
248 warning.seekp(0, std::ios::end);
249 warning <<
msg <<
' ';
251 auto L =
reinterpret_cast<lua_State*
>(
p);
254 lua_pushinteger(L, 2);
256 auto& lk = lua_kernel_base::get_lua_kernel<lua_kernel_base>(L);
257 lk.add_log_to_console(luaL_checkstring(L, -1));
273 std::string chunk = luaL_checkstring(L, 1);
274 const char* name = luaL_optstring(L, 2, chunk.c_str());
275 std::string mode = luaL_optstring(L, 3,
"t");
276 bool override_env = !lua_isnone(L, 4);
279 return luaL_argerror(L, 3,
"binary chunks are not allowed for security reasons");
282 int result = luaL_loadbufferx(L, chunk.data(), chunk.length(), name,
"t");
283 if(result != LUA_OK) {
295 const char* upvalue_name = lua_setupvalue(L, -2, 1);
296 if(upvalue_name ==
nullptr) {
310 lua_CFunction function = lua_tocfunction(L, lua_upvalueindex(1));
313 int nRets =
function(L);
325 std::string message =
"There is already an external logger attached to this lua kernel, you cannot open the lua console right now.";
337 lua_pushstring(L, gen->
generate().c_str());
350 std::string
type = luaL_checkstring(L, 1);
353 if(
type ==
"markov" ||
type ==
"markov_chain") {
354 std::vector<std::string> input;
355 if(lua_istable(L, 2)) {
356 input = lua_check<std::vector<std::string>>(L, 2);
360 int chain_sz = luaL_optinteger(L, 3, 2);
361 int max_len = luaL_optinteger(L, 4, 12);
365 }
else if(
type ==
"context_free" ||
type ==
"cfg" ||
type ==
"CFG") {
366 if(lua_istable(L, 2)) {
367 std::map<std::string, std::vector<std::string>>
data;
368 for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
369 if(lua_type(L, -2) != LUA_TSTRING) {
370 lua_pushstring(L,
"CFG generator: invalid nonterminal name (must be a string)");
373 if(lua_isstring(L, -1)) {
375 if(productions.size() > 1) {
376 deprecated_message(
"wesnoth.name_generator('cfg', {nonterminal = 'a|b'})",
DEP_LEVEL::INDEFINITE,
"1.17",
"Non-terminals should now be assigned an array of productions instead of a single string containing productions separated by | - but a single string is fine if it's only one production");
378 }
else if(lua_istable(L, -1)) {
379 const auto&
split = lua_check<std::vector<t_string>>(L, -1);
380 auto& productions =
data[lua_tostring(L,-2)];
383 lua_pushstring(L,
"CFG generator: invalid nonterminal value (must be a string or list of strings)");
397 return luaL_argerror(L, 1,
"should be either 'markov_chain' or 'context_free'");
401 lua_pushstring(L, ex.
what());
407 luaL_getmetatable(L,
Gen);
408 lua_setmetatable(L, -2);
419 const std::string& logger = lua_isstring(L, 2) ? luaL_checkstring(L, 1) :
"";
420 std::string
msg = lua_isstring(L, 2) ? luaL_checkstring(L, 2) : luaL_checkstring(L, 1);
421 if(
msg.empty() ||
msg.back() !=
'\n') {
425 if(logger ==
"err" || logger ==
"error") {
427 }
else if(logger ==
"warn" || logger ==
"wrn" || logger ==
"warning") {
429 }
else if((logger ==
"debug" || logger ==
"dbg")) {
445 const std::string elem = luaL_checkstring(L, 1);
448 const std::string ver_str = lua_isnoneornil(L, 3) ?
"" : luaL_checkstring(L, 3);
457 lua_warning(L,
msg.c_str(),
false);
472 if(!lua_istable(L, 1)) {
475 auto names = lua_check<std::vector<std::string>>(L, 2);
477 int len = luaL_checkinteger(L, -1);
479 for(
int i = 1; i <= std::max<int>(len,
names.size());
i++) {
490 temp.
read(luaL_checkstring(L, 1));
491 std::set<map_location> locs;
492 for(
int x = 1; x <= temp.
width(); x++) {
493 for(
int y = 1; y <= temp.
height(); y++) {
494 if(!temp.
value(x, y)) {
508 for(
const auto&
loc : locs) {
520 lua_pushinteger(L, SDL_GetTicks());
532 switch(luaL_getmetafield(L, -1,
"__dir")) {
536 if(lua_pcall(L, 2, 1, 0) == LUA_OK) {
537 keys = lua_check<std::vector<std::string>>(L, -1);
539 lua_warning(L,
"wesnoth.print_attributes: __dir metamethod raised an error",
false);
543 auto dir_keys = lua_check<std::vector<std::string>>(L, -1);
544 std::copy(dir_keys.begin(), dir_keys.end(), std::back_inserter(
keys));
553 auto key = luaL_checkstring(L, 2);
554 auto type = lua_getfield(L, 1, key);
555 if(
type == LUA_TTABLE) {
556 lua_pushliteral(L,
"__deprecated");
557 if(lua_rawget(L, -2) == LUA_TBOOLEAN) {
559 lua_pushboolean(L, deprecated);
564 lua_pushboolean(L,
false);
571 auto key = luaL_checkstring(L, 2);
572 std::string suffix =
" ";
573 auto type = lua_getfield(L, 1, key);
574 if(
type == LUA_TTABLE) {
576 }
else if(
type == LUA_TFUNCTION) {
578 }
else if(
type == LUA_TUSERDATA) {
579 lua_getglobal(L,
"getmetatable");
580 lua_pushvalue(L, -2);
582 if(lua_type(L, -1) == LUA_TSTRING) {
583 auto meta = lua_check<std::string>(L, -1);
584 if(meta ==
"function") {
589 if(suffix.size() == 1) {
591 if(
auto t = luaL_getmetafield(L, -1,
"__dir_tablelike");
t == LUA_TBOOLEAN) {
596 }
else if(
t != LUA_TNIL) {
601 suffix =
" " + suffix;
602 lua_pushlstring(L, suffix.c_str(), suffix.size());
612 if(idx < 0 && idx >= -lua_gettop(L)) {
613 idx = lua_absindex(L, idx);
615 std::vector<std::string>
keys;
616 if(lua_istable(L, idx)) {
619 int save_top = lua_gettop(L);
620 lua_pushvalue(L, idx);
622 lua_settop(L, save_top);
625 int table_idx = lua_absindex(L, -1);
626 for(lua_pushnil(L); lua_next(L, table_idx); lua_pop(L, 1)) {
627 if(lua_type(L, -2) == LUA_TSTRING) {
628 keys.push_back(lua_tostring(L,-2));
636 if(luaL_getmetafield(L, table_idx,
"__index") == LUA_TNIL)
break;
637 }
while(lua_istable(L, -1));
638 if(lua_isfunction(L, -1)) {
642 }
else if(lua_isuserdata(L, idx) && !lua_islightuserdata(L, idx)) {
643 lua_pushvalue(L, idx);
648 std::sort(
keys.begin(),
keys.end());
649 auto new_end = std::unique(
keys.begin(),
keys.end());
650 new_end = std::remove_if(
keys.begin(), new_end, [L, idx](
const std::string& key) {
651 if(key.compare(0, 2,
"__") == 0) {
654 int save_top = lua_gettop(L);
656 lua_settop(L, save_top);
663 lua_pushvalue(L, idx);
665 if(lua_pcall(L, 2, 1, 0) == LUA_OK) {
688 if(lua_isnil(L, 1))
return luaL_argerror(L, 1,
"Can't dir() nil");
689 if(!lua_isfunction(L, 2)) {
692 int fcn_idx = lua_gettop(L);
694 size_t max_len = std::accumulate(
keys.begin(),
keys.end(), 0, [](
size_t max,
const std::string& next) {
695 return std::max(max, next.size());
698 static const size_t MAX_WIDTH = 80, COL_PADDING = 3, SUFFIX_PADDING = 2;
699 size_t col_width = max_len + COL_PADDING + SUFFIX_PADDING;
700 size_t n_cols = (MAX_WIDTH + COL_PADDING) / col_width;
701 size_t n_rows = ceil(
keys.size() /
double(n_cols));
702 for(
size_t i = 0;
i < n_rows;
i++) {
703 std::ostringstream
line;
705 line.setf(std::ios::left);
706 for(
size_t j = 0; j < n_cols && j + (
i * n_cols) <
keys.size(); j++) {
707 int save_top = lua_gettop(L);
709 lua_settop(L, save_top);
713 const auto& key =
keys[j +
i * n_cols];
714 lua_pushlstring(L, key.c_str(), key.size());
715 std::string suffix =
" !";
716 if(lua_pcall(L, 2, 1, 0) == LUA_OK) {
717 suffix = luaL_checkstring(L, -1);
721 line.width(col_width - SUFFIX_PADDING + suffix.size());
725 lua_pushvalue(L, fcn_idx);
737 template <member_callback method>
739 return ((lua_kernel_base::get_lua_kernel<lua_kernel_base>(L)).*method)(L);
744 : mState(luaL_newstate())
754 cmd_log_ <<
"Adding boost function proxy...\n";
760 cmd_log_ <<
"Adding standard libs...\n";
762 static const luaL_Reg safe_libs[] {
763 {
"", luaopen_base },
764 {
"table", luaopen_table },
765 {
"string", luaopen_string },
766 {
"math", luaopen_math },
767 {
"coroutine", luaopen_coroutine },
768 {
"debug", luaopen_debug },
769 {
"os", luaopen_os },
770 {
"utf8", luaopen_utf8 },
779 for (luaL_Reg
const *lib = safe_libs; lib->func; ++lib)
781 luaL_requiref(L, lib->name, lib->func, strlen(lib->name));
786 lua_getglobal(L,
"os");
788 while(lua_next(L, -2) != 0) {
790 char const*
function = lua_tostring(L, -1);
791 if(strcmp(
function,
"clock") == 0 || strcmp(
function,
"date") == 0
792 || strcmp(
function,
"time") == 0 || strcmp(
function,
"difftime") == 0)
continue;
794 lua_setfield(L, -3,
function);
800 lua_setglobal(L,
"dofile");
802 lua_setglobal(L,
"loadfile");
805 cmd_log_ <<
"Adding error handler...\n";
812 cmd_log_ <<
"Registering basic wesnoth API...\n";
814 static luaL_Reg
const callbacks[] {
817 {
"dofile", &dispatch<&lua_kernel_base::intf_dofile> },
818 {
"require", &dispatch<&lua_kernel_base::intf_require> },
819 {
"kernel_type", &dispatch<&lua_kernel_base::intf_kernel_type> },
833 lua_getglobal(L,
"wesnoth");
834 if (!lua_istable(L,-1)) {
837 luaL_setfuncs(L, callbacks, 0);
839 lua_setglobal(L,
"wesnoth");
849 cmd_log_ <<
"Redirecting print function...\n";
851 lua_getglobal(L,
"print");
852 lua_setglobal(L,
"std_print");
856 lua_pushcfunction(L, &dispatch<&lua_kernel_base::intf_print>);
857 lua_setglobal(L,
"print");
860 lua_setglobal(L,
"load");
862 lua_setglobal(L,
"loadstring");
865 cmd_log_ <<
"Wrapping pcall and xpcall functions...\n";
866 lua_getglobal(L,
"pcall");
868 lua_setglobal(L,
"pcall");
869 lua_getglobal(L,
"xpcall");
871 lua_setglobal(L,
"xpcall");
873 cmd_log_ <<
"Initializing package repository...\n";
875 lua_getglobal(L,
"wesnoth");
877 lua_setfield(L, -2,
"package");
880 lua_pushstring(L,
"lua/package.lua");
883 cmd_log_ <<
"Error: Failed to initialize package repository. Falling back to less flexible C++ implementation.\n";
887 cmd_log_ <<
"Adding map table...\n";
889 static luaL_Reg
const map_callbacks[] {
910 lua_getglobal(L,
"wesnoth");
912 luaL_setfuncs(L, map_callbacks, 0);
913 lua_setfield(L, -2,
"map");
917 cmd_log_ <<
"Adding game_config table...\n";
919 lua_getglobal(L,
"wesnoth");
920 lua_newuserdatauv(L, 0, 0);
921 lua_createtable(L, 0, 3);
922 lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_get>);
923 lua_setfield(L, -2,
"__index");
924 lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_set>);
925 lua_setfield(L, -2,
"__newindex");
926 lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_dir>);
927 lua_setfield(L, -2,
"__dir");
928 lua_pushboolean(L,
true);
929 lua_setfield(L, -2,
"__dir_tablelike");
930 lua_pushstring(L,
"game config");
931 lua_setfield(L, -2,
"__metatable");
932 lua_setmetatable(L, -2);
933 lua_setfield(L, -2,
"game_config");
937 cmd_log_ <<
"Adding rng tables...\n";
940 cmd_log_ <<
"Adding name generator metatable...\n";
941 luaL_newmetatable(L,
Gen);
955 cmd_log_ <<
"Sandboxing Lua interpreter...\nTo make variables visible outside the interpreter, assign to _G.variable.\n";
956 cmd_log_ <<
"The special variable _ holds the result of the last expression (if any).\n";
958 lua_createtable(L, 0, 1);
959 lua_getglobal(L,
"_G");
960 lua_setfield(L, -2,
"__index");
961 lua_setmetatable(L, -2);
963 lua_setfield(L, -2,
"dir");
964 lua_setfield(L, LUA_REGISTRYINDEX,
Interp);
971 lua_pushstring(L,
"lua/ilua.lua");
974 lua_pushstring(L,
"set_strict");
977 cmd_log_ <<
"Failed to activate strict mode.\n";
979 cmd_log_ <<
"Activated strict mode.\n";
982 lua_setglobal(L,
"ilua");
984 cmd_log_ <<
"Error: failed to load ilua.\n";
990 lua_getglobal(L,
"debug");
992 while(lua_next(L, -2) != 0) {
994 char const*
function = lua_tostring(L, -1);
995 if(strcmp(
function,
"traceback") == 0 || strcmp(
function,
"getinfo") == 0)
continue;
997 lua_setfield(L, -3,
function);
1041 if (errcode != LUA_OK) {
1042 char const *
msg = lua_tostring(L, -1);
1044 std::string context =
"When executing, ";
1045 if (errcode == LUA_ERRRUN) {
1046 context +=
"Lua runtime error: ";
1047 }
else if (errcode == LUA_ERRERR) {
1048 context +=
"Lua error in attached debugger: ";
1049 }
else if (errcode == LUA_ERRMEM) {
1050 context +=
"Lua out of memory error: ";
1052 context +=
"unknown lua error: ";
1054 if(lua_isstring(L, -1)) {
1055 context +=
msg ?
msg :
"null string";
1057 context += lua_typename(L, lua_type(L, -1));
1062 e_h(context.c_str(),
"Lua Error");
1073 int errcode = luaL_loadbufferx(
mState, prog.c_str(), prog.size(), name.empty() ? prog.c_str() : name.c_str(), allow_unsafe ?
"tb" :
"t");
1074 if (errcode != LUA_OK) {
1075 char const *
msg = lua_tostring(
mState, -1);
1076 std::string message =
msg ?
msg :
"null string";
1078 std::string context =
"When parsing a string to lua, ";
1080 if (errcode == LUA_ERRSYNTAX) {
1081 context +=
" a syntax error";
1082 }
else if(errcode == LUA_ERRMEM){
1083 context +=
" a memory error";
1085 context +=
" an unknown error";
1090 e_h(message.c_str(), context.c_str());
1104 this->
run(cfg[
"code"].str().c_str(), cfg[
"name"].str(), nArgs);
1109 if(lua_iscfunction(L, func)) {
1112 if(!lua_isfunction(L, func)) {
1117 lua_pushvalue(L, func);
1118 lua_getinfo(L,
">u", &
info);
1121 lua_pushvalue(L, func);
1123 data[
"code"] = lua_check<std::string>(L, -1);
1126 for(
int i = 1;
i <=
info.nups;
i++, lua_pop(L, 1)) {
1127 std::string_view name = lua_getupvalue(L, func,
i);
1128 if(name ==
"_ENV") {
1129 upvalues.
add_child(name)[
"upvalue_type"] =
"_ENV";
1132 int idx = lua_absindex(L, -1);
1133 switch(lua_type(L, idx)) {
1134 case LUA_TBOOLEAN:
case LUA_TNUMBER:
case LUA_TSTRING:
1145 for(
size_t i = 1;
i <= lua_rawlen(L, -1);
i++, lua_pop(L, 1)) {
1146 lua_rawgeti(L, idx,
i);
1149 cfg[
"name"] =
names[0];
1150 cfg[
"upvalue_type"] =
"named tuple";
1155 std::vector<std::string>
names;
1156 int save_top = lua_gettop(L);
1157 if(luaL_getmetafield(L, idx,
"__name") && lua_check<std::string>(L, -1) ==
"named tuple") {
1158 luaL_getmetafield(L, -2,
"__names");
1159 names = lua_check<std::vector<std::string>>(L, -1);
1161 lua_settop(L, save_top);
1162 upvalues.
add_child(name, cfg)[
"upvalue_type"] =
names.empty() ?
"config" :
"named tuple";
1165 for(
size_t i = 1;
i <= lua_rawlen(L, -1);
i++, lua_pop(L, 1)) {
1166 lua_rawgeti(L, idx,
i);
1169 cfg[
"upvalue_type"] =
"array";
1171 bool found_non_array =
false;
1172 for(lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) {
1173 if(lua_type(L, -2) != LUA_TNUMBER) {
1174 found_non_array =
true;
1178 if(!found_non_array)
break;
1182 std::ostringstream os;
1183 os <<
"cannot serialize function with upvalue " << name <<
" = ";
1185 lua_pushvalue(L, idx);
1187 os << luaL_checkstring(L, -1);
1188 lua_pushboolean(L,
false);
1192 if(!upvalues.
empty())
data.add_child(
"upvalues", upvalues);
1198 if(!
load_string(cfg[
"code"].str(), cfg[
"name"], eh,
true))
return false;
1200 lua_pushvalue(
mState, -1);
1203 int funcindex = lua_absindex(
mState, -1);
1204 for(
int i = 1;
i <=
info.nups;
i++) {
1205 std::string_view name = lua_getupvalue(
mState, funcindex,
i);
1207 if(name ==
"_ENV") {
1208 lua_pushglobaltable(
mState);
1209 }
else if(upvalues->has_attribute(name)) {
1211 }
else if(upvalues->has_child(name)) {
1212 const auto& child = upvalues->mandatory_child(name);
1213 if(child[
"upvalue_type"] ==
"array") {
1214 auto children = upvalues->child_range(name);
1215 lua_createtable(
mState, children.size(), 0);
1216 for(
const auto& cfg : children) {
1220 }
else if(child[
"upvalue_type"] ==
"config") {
1222 }
else if(child[
"upvalue_type"] ==
"function") {
1224 }
else if(child[
"upvalue_type"] ==
"nil") {
1228 lua_setupvalue(
mState, funcindex,
i);
1236 int top = lua_gettop(
mState);
1240 lua_pushvalue(
mState, -1);
1247 error[
"name"] =
"execute_error";
1248 error[
"error"] =
e.what();
1252 result[
"ref"] = cfg[
"ref"];
1254 lua_remove(
mState, top + 1);
1255 result[
"name"] =
"execute_result";
1256 for(
int i = top + 1;
i < lua_gettop(
mState);
i++) {
1257 std::string
index = std::to_string(
i - top);
1259 case LUA_TNUMBER:
case LUA_TBOOLEAN:
case LUA_TSTRING:
1276 if(in_interpreter) {
1278 if(lua_setupvalue(
mState, -2, 1) ==
nullptr)
1281 lua_insert(
mState, -nArgs - 1);
1282 this->
protected_call(nArgs, in_interpreter ? LUA_MULTRET : 0, eh);
1298 std::string experiment =
"return ";
1300 int top = lua_gettop(
mState);
1307 this->
load_string(experiment.c_str(),
"interactive", eh);
1309 if(lua_setupvalue(
mState, -2, 1) ==
nullptr)
1313 if(lua_gettop(
mState) == top + 1) {
1323 int nRets = lua_gettop(
mState) - top - 1;
1327 int env_idx = lua_gettop(
mState);
1328 lua_pushvalue(
mState, top + 2);
1329 lua_setfield(
mState, -2,
"_");
1332 for(
int i = top + 2;
i < env_idx;
i++)
1335 lua_setfield(
mState, -2,
"_all");
1348 luaL_checkstring(L, 1);
1349 lua_rotate(L, 1, -1);
1352 lua_rotate(L, 1, 1);
1356 lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
1357 return lua_gettop(L);
1368 const char * m = luaL_checkstring(L, 1);
1370 return luaL_argerror(L, 1,
"found a null string argument to wesnoth require");
1375 lua_getglobal(L,
"wesnoth");
1376 lua_pushstring(L,
"package");
1378 lua_pushvalue(L, 1);
1384 lua_pushvalue(L, 1);
1392 DBG_LUA <<
"require: loaded a file, now calling it";
1400 lua_pushvalue(L, 1);
1401 lua_pushvalue(L, -2);
1405 lua_settable(L, -4);
1415 lua_createtable(L,
palette.size(), 1);
1416 lua_rotate(L, -2, 1);
1417 lua_setfield(L, -2,
"name");
1421 lua_rawseti(L, -2, 1);
1423 lua_rawseti(L, -2, 2);
1425 lua_rawseti(L, -2, 3);
1427 lua_rawseti(L, -2, 4);
1428 lua_rawseti(L, -2,
i);
1433 char const *m = luaL_checkstring(L, 2);
1434 lua_pushvalue(L, 2);
1447 #define GAME_CONFIG_SIMPLE_GETTER(name) \
1448 GAME_CONFIG_GETTER(#name, decltype(game_config::name), lua_kernel_base) { \
1450 return game_config::name; \
1470 if(luaL_newmetatable(L,
"color palettes")) {
1472 lua_setfield(L, -2,
"__index");
1474 lua_setmetatable(L, -2);
1480 lua_pushstring(L,
"red_green_scale");
1487 lua_pushstring(L,
"red_green_scale_text");
1494 lua_pushstring(L,
"blue_white_scale");
1501 lua_pushstring(L,
"blue_white_scale_text");
1543 lua_pushcfunction(L, luaopen_package);
1544 lua_pushstring(L,
"package");
1554 lua_pushstring(L,
"lua/core");
1556 cmd_log_ <<
"Error: Failed to load core.\n";
1566 std::vector<std::string> ret;
1570 int idx = lua_gettop(L);
1571 lua_getglobal(L,
"_G");
1574 while (lua_next(L, idx+1) != 0) {
1575 if (lua_isstring(L, -2)) {
1576 ret.push_back(lua_tostring(L,-2));
1589 std::vector<std::string> ret;
1590 std::string base_path = input;
1591 std::size_t last_dot = base_path.find_last_of(
'.');
1592 std::string partial_name = base_path.substr(last_dot + 1);
1593 base_path.erase(last_dot);
1594 std::string
load =
"return " + base_path;
1597 int save_stack = lua_gettop(L);
1598 int result = luaL_loadstring(L,
load.c_str());
1599 if(result != LUA_OK) {
1601 LOG_LUA <<
"Error when attempting tab completion:";
1602 LOG_LUA << luaL_checkstring(L, -1);
1604 lua_settop(L, save_stack);
1609 if(lua_istable(L, -1) || lua_isuserdata(L, -1)) {
1610 int top = lua_gettop(L);
1611 int obj = lua_absindex(L, -1);
1612 if(luaL_getmetafield(L, obj,
"__tab_enum") == LUA_TFUNCTION) {
1613 lua_pushvalue(L, obj);
1614 lua_pushlstring(L, partial_name.c_str(), partial_name.size());
1616 ret = lua_check<std::vector<std::string>>(L, -1);
1617 }
else if(lua_type(L, -1) != LUA_TTABLE) {
1618 LOG_LUA <<
"Userdata missing __tab_enum meta-function for tab completion";
1619 lua_settop(L, save_stack);
1624 for(lua_pushnil(L); lua_next(L, obj); lua_pop(L, 1)) {
1625 if(lua_type(L, -2) == LUA_TSTRING) {
1626 std::string attr = lua_tostring(L, -2);
1630 if(!isalpha(attr[0]) && attr[0] !=
'_') {
1633 if(std::any_of(attr.begin(), attr.end(), [](
char c){
1634 return !isalpha(c) && !isdigit(c) && c !=
'_';
1638 if(attr.substr(0, partial_name.size()) == partial_name) {
1639 ret.push_back(base_path +
"." + attr);
1645 lua_settop(L, save_stack);
1652 #pragma GCC diagnostic push
1653 #pragma GCC diagnostic ignored "-Wold-style-cast"
1657 #pragma GCC diagnostic pop
std::vector< std::string > names
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.
config & add_child(config_key_type key)
static void rethrow()
Rethrows the stored exception.
void load_core()
Loads the "core" library into the Lua environment.
void run(char const *prog, const std::string &name, int nArgs=0)
Runs a plain script.
virtual void log_error(char const *msg, char const *context="Lua error")
Error reporting mechanisms, used by virtual methods protected_call and load_string.
int intf_dofile(lua_State *L)
Loads and executes a Lua file.
int impl_game_config_get(lua_State *L)
Gets some game_config data (__index metamethod).
int intf_require(lua_State *L)
Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
void throwing_run(char const *prog, const std::string &name, int nArgs, bool in_interpreter=false)
Runs a plain script, but reports errors by throwing lua_error.
int intf_kernel_type(lua_State *L)
int impl_game_config_set(lua_State *L)
Sets some game_config data (__newindex metamethod).
void load_package()
Loads the package library into lua environment.
bool protected_call(int nArgs, int nRets, const error_handler &)
void add_log_to_console(const std::string &msg)
int impl_game_config_dir(lua_State *L)
Gets a list of game_config data (__dir metamethod).
int intf_show_lua_console(lua_State *L)
bool load_string(const std::string &prog, const std::string &name, const error_handler &, bool allow_unsafe=false)
std::vector< std::tuple< std::string, std::string > > registered_widget_definitions_
static lua_kernel_base *& get_lua_kernel_base_ptr(lua_State *L)
std::vector< std::string > get_global_var_names()
Get tab completion strings.
std::function< void(char const *, char const *)> error_handler
void run_lua_tag(const config &cfg)
Runs a [lua] tag.
bool load_binary(const config &func, const error_handler &)
virtual ~lua_kernel_base()
int intf_print(lua_State *L)
Replacement print function – instead of printing to std::cout, print to the command log.
void interactive_run(char const *prog)
Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it nor...
std::vector< std::string > get_attribute_names(const std::string &var_path)
Gets all attribute names of an extended variable name.
config run_binary_lua_tag(const config &cfg)
Runs a binary [lua] tag.
virtual uint32_t get_random_seed()
virtual void throw_exception(char const *msg, char const *context="Lua error")
virtual std::string my_name()
User-visible name of the lua kernel that they are talking to.
const char * what() const noexcept
std::string generate(const std::map< std::string, std::string > &variables) const
virtual ~name_generator()
void read(const std::string &shroud_data)
void set_enabled(bool enabled)
bool value(int x, int y) const
std::string write() const
const std::string & str() const
Represents version numbers.
std::string str() const
Serializes the version number into string form.
unsigned int revision_level() const
Retrieves the revision level (x3 in "x1.x2.x3").
char special_version_separator() const
Retrieves the special version separator (e.g.
const std::string & special_version() const
Retrieves the special version suffix (e.g.
unsigned int minor_version() const
Retrieves the minor version number (x2 in "x1.x2.x3").
unsigned int major_version() const
Retrieves the major version number (x1 in "x1.x2.x3").
const std::vector< unsigned int > & components() const
Read-only access to all numeric components.
bool is_canonical() const
Whether the version number is considered canonical for mainline Wesnoth.
std::vector< color_t > palette(const color_range &cr)
Creates a reference color palette from a color range.
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
DEP_LEVEL
See https://wiki.wesnoth.org/CompatibilityStandards for more info.
int(* lua_CFunction)(lua_State *L)
bool do_version_check(const version_info &a, VERSION_COMP_OP op, const version_info &b)
Interfaces for manipulating version numbers of engine, add-ons, etc.
const language_def & get_language()
Standard logging facilities (interface).
#define LOG_STREAM(level, domain)
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
void push_error_handler(lua_State *L)
void luaW_push_namedtuple(lua_State *L, const std::vector< std::string > &names)
Push an empty "named tuple" onto the stack.
std::set< map_location > luaW_check_locationset(lua_State *L, int idx)
Converts a table of integer pairs to a set of map location objects.
bool luaW_toboolean(lua_State *L, int n)
int luaW_type_error(lua_State *L, int narg, const char *tname)
bool luaW_toscalar(lua_State *L, int index, config::attribute_value &v)
Converts the value at the top of the stack to an attribute value.
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.
std::vector< std::string > luaW_to_namedtuple(lua_State *L, int idx)
Get the keys of a "named tuple" from the stack.
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
Calls a Lua function stored below its nArgs arguments at the top of the stack.
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
int luaW_push_locationset(lua_State *L, const std::set< map_location > &locs)
Converts a set of map locations to a Lua table pushed at the top of the stack.
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.
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
#define return_string_attrib(name, accessor)
#define return_int_attrib(name, accessor)
#define return_bool_attrib(name, accessor)
static int intf_make_shroud_bitmap(lua_State *L)
static int impl_version_finalize(lua_State *L)
Destroy a version.
int dispatch(lua_State *L)
static int intf_name_generator(lua_State *L)
static lg::log_domain log_user("scripting/lua/user")
static int intf_current_version(lua_State *L)
Returns the current Wesnoth version.
static lg::log_domain log_scripting_lua("scripting/lua")
static int intf_parse_shroud_bitmap(lua_State *L)
static int intf_make_version(lua_State *L)
Builds a version from its component parts, or parses it from a string.
static int impl_version_dir(lua_State *L)
static int impl_version_get(lua_State *L)
Decomposes a version into its component parts.
static int impl_get_dir_suffix(lua_State *L)
static int impl_version_tostring(lua_State *L)
Convert a version to string form.
luaW_Registry & gameConfigReg()
static int intf_deprecated_message(lua_State *L)
Logs a deprecation message.
static int intf_pcall(lua_State *L)
Wrapper for pcall and xpcall functions to rethrow jailbreak exceptions.
static int intf_named_tuple(lua_State *L)
Converts a Lua array to a named tuple.
static void impl_warn(void *p, const char *msg, int tocont)
int(lua_kernel_base::* member_callback)(lua_State *L)
static const char * Version
static int intf_log(lua_State *L)
Logs a message Arg 1: (optional) Logger Arg 2: Message.
static int impl_palette_get(lua_State *L)
static int impl_is_deprecated(lua_State *L)
static const char * Interp
std::vector< std::string > luaW_get_attributes(lua_State *L, int idx)
This function does the actual work of grabbing all the attribute names.
static void push_color_palette(lua_State *L, const std::vector< color_t > &palette)
static int intf_load(lua_State *L)
Replacement load function.
static int intf_ms_since_init(lua_State *L)
Returns the time stamp, exactly as [set_variable] time=stamp does.
static int intf_get_language(lua_State *L)
static int impl_name_generator_call(lua_State *L)
static void dir_meta_helper(lua_State *L, std::vector< std::string > &keys)
static int intf_object_dir(lua_State *L)
Prints out a list of keys available in an object.
#define GAME_CONFIG_SIMPLE_GETTER(name)
config luaW_serialize_function(lua_State *L, int func)
static int impl_name_generator_collect(lua_State *L)
static int impl_version_compare(lua_State *L)
Compares two versions.
#define GAME_CONFIG_GETTER(name, type, kernel_type)
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
std::vector< color_t > red_green_scale_text
const version_info wesnoth_version(VERSION)
const std::vector< color_t > & tc_info(std::string_view name)
std::vector< color_t > blue_white_scale
std::vector< color_t > red_green_scale
std::vector< color_t > blue_white_scale_text
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
void remove_single_widget_definition(const std::string &widget_type, const std::string &definition_id)
Removes a widget definition from the default GUI.
std::string register_metatables(lua_State *L)
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
void register_metatable(lua_State *L)
int luaW_open(lua_State *L)
int load_file(lua_State *L)
Loads a Lua file and pushes the contents on the stack.
int luaW_open(lua_State *L)
int show_lua_console(lua_State *, lua_kernel_base *lk)
int intf_get_relative_dir(lua_State *L)
Expose map_location get_relative_dir.
int intf_vector_negation(lua_State *L)
Expose map_location::vector_negation to lua.
int intf_distance_between(lua_State *L)
Expose map_location distance_between.
int intf_get_in_cubic(lua_State *L)
Expose map_location to_cubic.
int intf_tiles_adjacent(lua_State *L)
Expose map_location tiles_adjacent.
int intf_vector_diff(lua_State *L)
Expose map_location::vector_difference to lua.
int intf_get_from_cubic(lua_State *L)
Expose map_location from_cubic.
int intf_vector_sum(lua_State *L)
Expose map_location::vector_sum to lua.
int intf_get_tile_ring(lua_State *L)
Expose map_location get_tile_ring.
int intf_rotate_right_around_center(lua_State *L)
Expose map_location::rotate_right_around_center to lua.
int intf_get_tiles_in_radius(lua_State *L)
Expose map_location get_tiles_in_radius.
int intf_get_adjacent_tiles(lua_State *L)
Expose map_location get_adjacent_tiles.
int intf_get_direction(lua_State *L)
Expose map_location::get_direction function to lua Arg 1: a location Arg 2: a direction Arg 3: (optio...
int luaW_open(lua_State *L)
void load_tables(lua_State *L)
Creates the metatable for RNG objects, and adds the Rng table which contains the constructor.
int luaW_open(lua_State *L)
int luaW_open(lua_State *L)
rng * generator
This generator is automatically synced during synced context.
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::vector< std::string > parenthetical_split(std::string_view val, const char separator, std::string_view left, std::string_view right, const int flags)
Splits a string based either on a separator, except then the text appears within specified parenthesi...
std::vector< std::string > split(const config_attribute_value &val)
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
void lua_push(lua_State *L, const T &val)
static std::string flush(std::ostringstream &s)
#define ON_SCOPE_EXIT(...)
Run some arbitrary code (a lambda) when the current scope exits The lambda body follows this header,...
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.
int dir(lua_State *L)
Implement __dir metamethod.
int set(lua_State *L)
Implement __newindex metamethod.
int get(lua_State *L)
Implement __index metamethod.
external_log_type external_log_
static map_location::direction n