l_client.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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 "client/clientevent.h"
  21. #include "client/sound.h"
  22. #include "clientenvironment.h"
  23. #include "common/c_content.h"
  24. #include "common/c_converter.h"
  25. #include "cpp_api/s_base.h"
  26. #include "gettext.h"
  27. #include "l_internal.h"
  28. #include "lua_api/l_item.h"
  29. #include "lua_api/l_nodemeta.h"
  30. #include "gui/mainmenumanager.h"
  31. #include "map.h"
  32. #include "util/string.h"
  33. #include "nodedef.h"
  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_last_run_mod()
  40. int ModApiClient::l_get_last_run_mod(lua_State *L)
  41. {
  42. lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
  43. const char *current_mod = lua_tostring(L, -1);
  44. if (current_mod == NULL || current_mod[0] == '\0') {
  45. lua_pop(L, 1);
  46. lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
  47. }
  48. return 1;
  49. }
  50. // set_last_run_mod(modname)
  51. int ModApiClient::l_set_last_run_mod(lua_State *L)
  52. {
  53. if (!lua_isstring(L, 1))
  54. return 0;
  55. const char *mod = lua_tostring(L, 1);
  56. getScriptApiBase(L)->setOriginDirect(mod);
  57. lua_pushboolean(L, true);
  58. return 1;
  59. }
  60. // print(text)
  61. int ModApiClient::l_print(lua_State *L)
  62. {
  63. NO_MAP_LOCK_REQUIRED;
  64. std::string text = luaL_checkstring(L, 1);
  65. rawstream << text << std::endl;
  66. return 0;
  67. }
  68. // display_chat_message(message)
  69. int ModApiClient::l_display_chat_message(lua_State *L)
  70. {
  71. if (!lua_isstring(L, 1))
  72. return 0;
  73. std::string message = luaL_checkstring(L, 1);
  74. getClient(L)->pushToChatQueue(new ChatMessage(utf8_to_wide(message)));
  75. lua_pushboolean(L, true);
  76. return 1;
  77. }
  78. // send_chat_message(message)
  79. int ModApiClient::l_send_chat_message(lua_State *L)
  80. {
  81. if (!lua_isstring(L, 1))
  82. return 0;
  83. // If server disabled this API, discard
  84. if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_CHAT_MESSAGES))
  85. return 0;
  86. std::string message = luaL_checkstring(L, 1);
  87. getClient(L)->sendChatMessage(utf8_to_wide(message));
  88. return 0;
  89. }
  90. // clear_out_chat_queue()
  91. int ModApiClient::l_clear_out_chat_queue(lua_State *L)
  92. {
  93. getClient(L)->clearOutChatQueue();
  94. return 0;
  95. }
  96. // get_player_names()
  97. int ModApiClient::l_get_player_names(lua_State *L)
  98. {
  99. const std::list<std::string> &plist = getClient(L)->getConnectedPlayerNames();
  100. lua_createtable(L, plist.size(), 0);
  101. int newTable = lua_gettop(L);
  102. int index = 1;
  103. std::list<std::string>::const_iterator iter;
  104. for (iter = plist.begin(); iter != plist.end(); ++iter) {
  105. lua_pushstring(L, (*iter).c_str());
  106. lua_rawseti(L, newTable, index);
  107. index++;
  108. }
  109. return 1;
  110. }
  111. // show_formspec(formspec)
  112. int ModApiClient::l_show_formspec(lua_State *L)
  113. {
  114. if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
  115. return 0;
  116. ClientEvent *event = new ClientEvent();
  117. event->type = CE_SHOW_LOCAL_FORMSPEC;
  118. event->show_formspec.formname = new std::string(luaL_checkstring(L, 1));
  119. event->show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
  120. getClient(L)->pushToEventQueue(event);
  121. lua_pushboolean(L, true);
  122. return 1;
  123. }
  124. // send_respawn()
  125. int ModApiClient::l_send_respawn(lua_State *L)
  126. {
  127. getClient(L)->sendRespawn();
  128. return 0;
  129. }
  130. // disconnect()
  131. int ModApiClient::l_disconnect(lua_State *L)
  132. {
  133. // Stops badly written Lua code form causing boot loops
  134. if (getClient(L)->isShutdown()) {
  135. lua_pushboolean(L, false);
  136. return 1;
  137. }
  138. g_gamecallback->disconnect();
  139. lua_pushboolean(L, true);
  140. return 1;
  141. }
  142. // gettext(text)
  143. int ModApiClient::l_gettext(lua_State *L)
  144. {
  145. std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
  146. lua_pushstring(L, text.c_str());
  147. return 1;
  148. }
  149. // get_node(pos)
  150. // pos = {x=num, y=num, z=num}
  151. int ModApiClient::l_get_node_or_nil(lua_State *L)
  152. {
  153. // pos
  154. v3s16 pos = read_v3s16(L, 1);
  155. // Do it
  156. bool pos_ok;
  157. MapNode n = getClient(L)->getNode(pos, &pos_ok);
  158. if (pos_ok) {
  159. // Return node
  160. pushnode(L, n, getClient(L)->ndef());
  161. } else {
  162. lua_pushnil(L);
  163. }
  164. return 1;
  165. }
  166. int ModApiClient::l_get_language(lua_State *L)
  167. {
  168. char *locale = setlocale(LC_ALL, "");
  169. lua_pushstring(L, locale);
  170. return 1;
  171. }
  172. int ModApiClient::l_get_wielded_item(lua_State *L)
  173. {
  174. Client *client = getClient(L);
  175. Inventory local_inventory(client->idef());
  176. client->getLocalInventory(local_inventory);
  177. InventoryList *mlist = local_inventory.getList("main");
  178. if (mlist && client->getPlayerItem() < mlist->getSize()) {
  179. LuaItemStack::create(L, mlist->getItem(client->getPlayerItem()));
  180. } else {
  181. LuaItemStack::create(L, ItemStack());
  182. }
  183. return 1;
  184. }
  185. // get_meta(pos)
  186. int ModApiClient::l_get_meta(lua_State *L)
  187. {
  188. v3s16 p = read_v3s16(L, 1);
  189. NodeMetadata *meta = getClient(L)->getEnv().getMap().getNodeMetadata(p);
  190. NodeMetaRef::createClient(L, meta);
  191. return 1;
  192. }
  193. int ModApiClient::l_sound_play(lua_State *L)
  194. {
  195. ISoundManager *sound = getClient(L)->getSoundManager();
  196. SimpleSoundSpec spec;
  197. read_soundspec(L, 1, spec);
  198. float gain = 1.0f;
  199. float pitch = 1.0f;
  200. bool looped = false;
  201. s32 handle;
  202. if (lua_istable(L, 2)) {
  203. getfloatfield(L, 2, "gain", gain);
  204. getfloatfield(L, 2, "pitch", pitch);
  205. getboolfield(L, 2, "loop", looped);
  206. lua_getfield(L, 2, "pos");
  207. if (!lua_isnil(L, -1)) {
  208. v3f pos = read_v3f(L, -1) * BS;
  209. lua_pop(L, 1);
  210. handle = sound->playSoundAt(
  211. spec.name, looped, gain * spec.gain, pos, pitch);
  212. lua_pushinteger(L, handle);
  213. return 1;
  214. }
  215. }
  216. handle = sound->playSound(spec.name, looped, gain * spec.gain, 0.0f, pitch);
  217. lua_pushinteger(L, handle);
  218. return 1;
  219. }
  220. int ModApiClient::l_sound_stop(lua_State *L)
  221. {
  222. u32 handle = luaL_checkinteger(L, 1);
  223. getClient(L)->getSoundManager()->stopSound(handle);
  224. return 0;
  225. }
  226. // get_server_info()
  227. int ModApiClient::l_get_server_info(lua_State *L)
  228. {
  229. Client *client = getClient(L);
  230. Address serverAddress = client->getServerAddress();
  231. lua_newtable(L);
  232. lua_pushstring(L, client->getAddressName().c_str());
  233. lua_setfield(L, -2, "address");
  234. lua_pushstring(L, serverAddress.serializeString().c_str());
  235. lua_setfield(L, -2, "ip");
  236. lua_pushinteger(L, serverAddress.getPort());
  237. lua_setfield(L, -2, "port");
  238. lua_pushinteger(L, client->getProtoVersion());
  239. lua_setfield(L, -2, "protocol_version");
  240. return 1;
  241. }
  242. // get_item_def(itemstring)
  243. int ModApiClient::l_get_item_def(lua_State *L)
  244. {
  245. IGameDef *gdef = getGameDef(L);
  246. assert(gdef);
  247. IItemDefManager *idef = gdef->idef();
  248. assert(idef);
  249. if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_READ_ITEMDEFS))
  250. return 0;
  251. if (!lua_isstring(L, 1))
  252. return 0;
  253. const std::string &name(lua_tostring(L, 1));
  254. if (!idef->isKnown(name))
  255. return 0;
  256. const ItemDefinition &def = idef->get(name);
  257. push_item_definition_full(L, def);
  258. return 1;
  259. }
  260. // get_node_def(nodename)
  261. int ModApiClient::l_get_node_def(lua_State *L)
  262. {
  263. IGameDef *gdef = getGameDef(L);
  264. assert(gdef);
  265. const NodeDefManager *ndef = gdef->ndef();
  266. assert(ndef);
  267. if (!lua_isstring(L, 1))
  268. return 0;
  269. if (getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_READ_NODEDEFS))
  270. return 0;
  271. const std::string &name = lua_tostring(L, 1);
  272. const ContentFeatures &cf = ndef->get(ndef->getId(name));
  273. if (cf.name != name) // Unknown node. | name = <whatever>, cf.name = ignore
  274. return 0;
  275. push_content_features(L, cf);
  276. return 1;
  277. }
  278. int ModApiClient::l_get_privilege_list(lua_State *L)
  279. {
  280. const Client *client = getClient(L);
  281. lua_newtable(L);
  282. for (const std::string &priv : client->getPrivilegeList()) {
  283. lua_pushboolean(L, true);
  284. lua_setfield(L, -2, priv.c_str());
  285. }
  286. return 1;
  287. }
  288. // get_builtin_path()
  289. int ModApiClient::l_get_builtin_path(lua_State *L)
  290. {
  291. lua_pushstring(L, BUILTIN_MOD_NAME ":");
  292. return 1;
  293. }
  294. void ModApiClient::Initialize(lua_State *L, int top)
  295. {
  296. API_FCT(get_current_modname);
  297. API_FCT(print);
  298. API_FCT(display_chat_message);
  299. API_FCT(send_chat_message);
  300. API_FCT(clear_out_chat_queue);
  301. API_FCT(get_player_names);
  302. API_FCT(set_last_run_mod);
  303. API_FCT(get_last_run_mod);
  304. API_FCT(show_formspec);
  305. API_FCT(send_respawn);
  306. API_FCT(gettext);
  307. API_FCT(get_node_or_nil);
  308. API_FCT(get_wielded_item);
  309. API_FCT(disconnect);
  310. API_FCT(get_meta);
  311. API_FCT(sound_play);
  312. API_FCT(sound_stop);
  313. API_FCT(get_server_info);
  314. API_FCT(get_item_def);
  315. API_FCT(get_node_def);
  316. API_FCT(get_privilege_list);
  317. API_FCT(get_builtin_path);
  318. API_FCT(get_language);
  319. }