You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

389 lines
9.8 KiB

  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include "l_client.h"
  18. #include "chatmessage.h"
  19. #include "client.h"
  20. #include "clientenvironment.h"
  21. #include "common/c_content.h"
  22. #include "common/c_converter.h"
  23. #include "cpp_api/s_base.h"
  24. #include "gettext.h"
  25. #include "l_internal.h"
  26. #include "lua_api/l_item.h"
  27. #include "lua_api/l_nodemeta.h"
  28. #include "mainmenumanager.h"
  29. #include "map.h"
  30. #include "util/string.h"
  31. #include "nodedef.h"
  32. extern MainGameCallback *g_gamecallback;
  33. // get_current_modname()
  34. int ModApiClient::l_get_current_modname(lua_State *L)
  35. {
  36. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  37. return 1;
  38. }
  39. // get_modpath(modname)
  40. int ModApiClient::l_get_modpath(lua_State *L)
  41. {
  42. std::string modname = readParam<std::string>(L, 1);
  43. // Client mods use a virtual filesystem, see Client::scanModSubfolder()
  44. std::string path = modname + ":";
  45. lua_pushstring(L, path.c_str());
  46. return 1;
  47. }
  48. // get_last_run_mod()
  49. int ModApiClient::l_get_last_run_mod(lua_State *L)
  50. {
  51. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  52. std::string current_mod = readParam<std::string>(L, -1, "");
  53. if (current_mod.empty()) {
  54. lua_pop(L, 1);
  55. lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
  56. }
  57. return 1;
  58. }
  59. // set_last_run_mod(modname)
  60. int ModApiClient::l_set_last_run_mod(lua_State *L)
  61. {
  62. if (!lua_isstring(L, 1))
  63. return 0;
  64. const char *mod = lua_tostring(L, 1);
  65. getScriptApiBase(L)->setOriginDirect(mod);
  66. lua_pushboolean(L, true);
  67. return 1;
  68. }
  69. // print(text)
  70. int ModApiClient::l_print(lua_State *L)
  71. {
  72. NO_MAP_LOCK_REQUIRED;
  73. std::string text = luaL_checkstring(L, 1);
  74. rawstream << text << std::endl;
  75. return 0;
  76. }
  77. // display_chat_message(message)
  78. int ModApiClient::l_display_chat_message(lua_State *L)
  79. {
  80. if (!lua_isstring(L, 1))
  81. return 0;
  82. std::string message = luaL_checkstring(L, 1);
  83. getClient(L)->pushToChatQueue(new ChatMessage(utf8_to_wide(message)));
  84. lua_pushboolean(L, true);
  85. return 1;
  86. }
  87. // send_chat_message(message)
  88. int ModApiClient::l_send_chat_message(lua_State *L)
  89. {
  90. if (!lua_isstring (L, 1)) return 0;
  91. std::string message = luaL_checkstring (L, 1);
  92. getClient (L)->sendChatMessage (utf8_to_wide (message));
  93. return 0;
  94. }
  95. // clear_out_chat_queue()
  96. int ModApiClient::l_clear_out_chat_queue(lua_State *L)
  97. {
  98. getClient(L)->clearOutChatQueue();
  99. return 0;
  100. }
  101. // get_player_names()
  102. int ModApiClient::l_get_player_names(lua_State *L)
  103. {
  104. const std::list<std::string> &plist = getClient(L)->getConnectedPlayerNames();
  105. lua_createtable(L, plist.size(), 0);
  106. int newTable = lua_gettop(L);
  107. int index = 1;
  108. std::list<std::string>::const_iterator iter;
  109. for (iter = plist.begin(); iter != plist.end(); ++iter) {
  110. lua_pushstring(L, (*iter).c_str());
  111. lua_rawseti(L, newTable, index);
  112. index++;
  113. }
  114. return 1;
  115. }
  116. // show_formspec(formspec)
  117. int ModApiClient::l_show_formspec(lua_State *L)
  118. {
  119. if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
  120. return 0;
  121. ClientEvent event;
  122. event.type = CE_SHOW_LOCAL_FORMSPEC;
  123. event.show_formspec.formname = new std::string(luaL_checkstring(L, 1));
  124. event.show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
  125. getClient(L)->pushToEventQueue(event);
  126. lua_pushboolean(L, true);
  127. return 1;
  128. }
  129. // send_respawn()
  130. int ModApiClient::l_send_respawn(lua_State *L)
  131. {
  132. getClient(L)->sendRespawn();
  133. return 0;
  134. }
  135. // disconnect()
  136. int ModApiClient::l_disconnect(lua_State *L)
  137. {
  138. // Stops badly written Lua code form causing boot loops
  139. if (getClient(L)->isShutdown()) {
  140. lua_pushboolean(L, false);
  141. return 1;
  142. }
  143. g_gamecallback->disconnect();
  144. lua_pushboolean(L, true);
  145. return 1;
  146. }
  147. // gettext(text)
  148. int ModApiClient::l_gettext(lua_State *L)
  149. {
  150. std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
  151. lua_pushstring(L, text.c_str());
  152. return 1;
  153. }
  154. // get_node(pos)
  155. // pos = {x=num, y=num, z=num}
  156. int ModApiClient::l_get_node_or_nil(lua_State *L)
  157. {
  158. // pos
  159. v3s16 pos = read_v3s16(L, 1);
  160. // Do it
  161. bool pos_ok;
  162. MapNode n = getClient(L)->getNode(pos, &pos_ok);
  163. if (pos_ok) {
  164. // Return node
  165. pushnode(L, n, getClient(L)->ndef());
  166. } else {
  167. lua_pushnil(L);
  168. }
  169. return 1;
  170. }
  171. int ModApiClient::l_get_language(lua_State *L)
  172. {
  173. char *locale = setlocale(LC_MESSAGES, NULL);
  174. std::string lang = gettext("LANG_CODE");
  175. if (lang == "LANG_CODE")
  176. lang = "";
  177. lua_pushstring(L, locale);
  178. lua_pushstring(L, lang.c_str());
  179. return 2;
  180. }
  181. int ModApiClient::l_get_wielded_item(lua_State *L)
  182. {
  183. Client *client = getClient(L);
  184. Inventory local_inventory(client->idef());
  185. client->getLocalInventory(local_inventory);
  186. InventoryList *mlist = local_inventory.getList("main");
  187. if (mlist && client->getPlayerItem() < mlist->getSize()) {
  188. LuaItemStack::create(L, mlist->getItem(client->getPlayerItem()));
  189. } else {
  190. LuaItemStack::create(L, ItemStack());
  191. }
  192. return 1;
  193. }
  194. // get_meta(pos)
  195. int ModApiClient::l_get_meta(lua_State *L)
  196. {
  197. v3s16 p = read_v3s16(L, 1);
  198. NodeMetadata *meta = getClient(L)->getEnv().getMap().getNodeMetadata(p);
  199. NodeMetaRef::createClient(L, meta);
  200. return 1;
  201. }
  202. int ModApiClient::l_sound_play(lua_State *L)
  203. {
  204. ISoundManager *sound = getClient(L)->getSoundManager();
  205. SimpleSoundSpec spec;
  206. read_soundspec(L, 1, spec);
  207. float gain = 1.0f;
  208. float pitch = 1.0f;
  209. bool looped = false;
  210. s32 handle;
  211. if (lua_istable(L, 2)) {
  212. getfloatfield(L, 2, "gain", gain);
  213. getfloatfield(L, 2, "pitch", pitch);
  214. getboolfield(L, 2, "loop", looped);
  215. lua_getfield(L, 2, "pos");
  216. if (!lua_isnil(L, -1)) {
  217. v3f pos = read_v3f(L, -1) * BS;
  218. lua_pop(L, 1);
  219. handle = sound->playSoundAt(
  220. spec.name, looped, gain * spec.gain, pos, pitch);
  221. lua_pushinteger(L, handle);
  222. return 1;
  223. }
  224. }
  225. handle = sound->playSound(spec.name, looped, gain * spec.gain, 0.0f, pitch);
  226. lua_pushinteger(L, handle);
  227. return 1;
  228. }
  229. int ModApiClient::l_sound_stop(lua_State *L)
  230. {
  231. u32 handle = luaL_checkinteger(L, 1);
  232. getClient(L)->getSoundManager()->stopSound(handle);
  233. return 0;
  234. }
  235. // get_server_info()
  236. int ModApiClient::l_get_server_info(lua_State *L)
  237. {
  238. Client *client = getClient(L);
  239. Address serverAddress = client->getServerAddress();
  240. lua_newtable(L);
  241. lua_pushstring(L, client->getAddressName().c_str());
  242. lua_setfield(L, -2, "address");
  243. lua_pushstring(L, serverAddress.serializeString().c_str());
  244. lua_setfield(L, -2, "ip");
  245. lua_pushinteger(L, serverAddress.getPort());
  246. lua_setfield(L, -2, "port");
  247. lua_pushinteger(L, client->getProtoVersion());
  248. lua_setfield(L, -2, "protocol_version");
  249. return 1;
  250. }
  251. // get_item_def(itemstring)
  252. int ModApiClient::l_get_item_def(lua_State *L)
  253. {
  254. IGameDef *gdef = getGameDef(L);
  255. assert(gdef);
  256. IItemDefManager *idef = gdef->idef();
  257. assert(idef);
  258. if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_READ_ITEMDEFS))
  259. return 0;
  260. if (!lua_isstring(L, 1))
  261. return 0;
  262. std::string name = readParam<std::string>(L, 1);
  263. if (!idef->isKnown(name))
  264. return 0;
  265. const ItemDefinition &def = idef->get(name);
  266. push_item_definition_full(L, def);
  267. return 1;
  268. }
  269. // get_node_def(nodename)
  270. int ModApiClient::l_get_node_def(lua_State *L)
  271. {
  272. IGameDef *gdef = getGameDef(L);
  273. assert(gdef);
  274. INodeDefManager *ndef = gdef->ndef();
  275. assert(ndef);
  276. if (!lua_isstring(L, 1))
  277. return 0;
  278. if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_READ_NODEDEFS))
  279. return 0;
  280. std::string name = readParam<std::string>(L, 1);
  281. const ContentFeatures &cf = ndef->get(ndef->getId(name));
  282. if (cf.name != name) // Unknown node. | name = <whatever>, cf.name = ignore
  283. return 0;
  284. push_content_features(L, cf);
  285. return 1;
  286. }
  287. int ModApiClient::l_get_privilege_list(lua_State *L)
  288. {
  289. const Client *client = getClient(L);
  290. lua_newtable(L);
  291. for (const std::string &priv : client->getPrivilegeList()) {
  292. lua_pushboolean(L, true);
  293. lua_setfield(L, -2, priv.c_str());
  294. }
  295. return 1;
  296. }
  297. // get_builtin_path()
  298. int ModApiClient::l_get_builtin_path(lua_State *L)
  299. {
  300. lua_pushstring(L, BUILTIN_MOD_NAME ":");
  301. return 1;
  302. }
  303. void ModApiClient::Initialize(lua_State *L, int top)
  304. {
  305. API_FCT(get_current_modname);
  306. API_FCT(get_modpath);
  307. API_FCT(print);
  308. API_FCT(display_chat_message);
  309. API_FCT(send_chat_message);
  310. API_FCT(clear_out_chat_queue);
  311. API_FCT(get_player_names);
  312. API_FCT(set_last_run_mod);
  313. API_FCT(get_last_run_mod);
  314. API_FCT(show_formspec);
  315. API_FCT(send_respawn);
  316. API_FCT(gettext);
  317. API_FCT(get_node_or_nil);
  318. API_FCT(get_wielded_item);
  319. API_FCT(disconnect);
  320. API_FCT(get_meta);
  321. API_FCT(sound_play);
  322. API_FCT(sound_stop);
  323. API_FCT(get_server_info);
  324. API_FCT(get_item_def);
  325. API_FCT(get_node_def);
  326. API_FCT(get_privilege_list);
  327. API_FCT(get_builtin_path);
  328. API_FCT(get_language);
  329. }