]> git.lizzy.rs Git - minetest.git/blob - src/script/cpp_api/s_server.cpp
Add keybind to swap items between hands
[minetest.git] / src / script / cpp_api / s_server.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "cpp_api/s_server.h"
21 #include "cpp_api/s_internal.h"
22 #include "common/c_converter.h"
23 #include "util/numeric.h" // myrand
24
25 bool ScriptApiServer::getAuth(const std::string &playername,
26                 std::string *dst_password,
27                 std::set<std::string> *dst_privs,
28                 s64 *dst_last_login)
29 {
30         SCRIPTAPI_PRECHECKHEADER
31
32         int error_handler = PUSH_ERROR_HANDLER(L);
33         getAuthHandler();
34         lua_getfield(L, -1, "get_auth");
35         if (lua_type(L, -1) != LUA_TFUNCTION)
36                 throw LuaError("Authentication handler missing get_auth");
37         lua_pushstring(L, playername.c_str());
38         PCALL_RES(lua_pcall(L, 1, 1, error_handler));
39         lua_remove(L, -2); // Remove auth handler
40         lua_remove(L, error_handler);
41
42         // nil = login not allowed
43         if (lua_isnil(L, -1))
44                 return false;
45         luaL_checktype(L, -1, LUA_TTABLE);
46
47         std::string password;
48         if (!getstringfield(L, -1, "password", password))
49                 throw LuaError("Authentication handler didn't return password");
50         if (dst_password)
51                 *dst_password = password;
52
53         lua_getfield(L, -1, "privileges");
54         if (!lua_istable(L, -1))
55                 throw LuaError("Authentication handler didn't return privilege table");
56         if (dst_privs)
57                 readPrivileges(-1, *dst_privs);
58         lua_pop(L, 1);  // Remove key from privs table
59
60         s64 last_login;
61         if(!getintfield(L, -1, "last_login", last_login))
62                 throw LuaError("Authentication handler didn't return last_login");
63         if (dst_last_login)
64                 *dst_last_login = (s64)last_login;
65
66         return true;
67 }
68
69 void ScriptApiServer::getAuthHandler()
70 {
71         lua_State *L = getStack();
72
73         lua_getglobal(L, "core");
74         lua_getfield(L, -1, "registered_auth_handler");
75         if (lua_isnil(L, -1)){
76                 lua_pop(L, 1);
77                 lua_getfield(L, -1, "builtin_auth_handler");
78         }
79
80         setOriginFromTable(-1);
81
82         lua_remove(L, -2); // Remove core
83         if (lua_type(L, -1) != LUA_TTABLE)
84                 throw LuaError("Authentication handler table not valid");
85 }
86
87 void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result)
88 {
89         lua_State *L = getStack();
90
91         result.clear();
92         lua_pushnil(L);
93         if (index < 0)
94                 index -= 1;
95         while (lua_next(L, index) != 0) {
96                 // key at index -2 and value at index -1
97                 std::string key = luaL_checkstring(L, -2);
98                 bool value = readParam<bool>(L, -1);
99                 if (value)
100                         result.insert(key);
101                 // removes value, keeps key for next iteration
102                 lua_pop(L, 1);
103         }
104 }
105
106 void ScriptApiServer::createAuth(const std::string &playername,
107                 const std::string &password)
108 {
109         SCRIPTAPI_PRECHECKHEADER
110
111         int error_handler = PUSH_ERROR_HANDLER(L);
112         getAuthHandler();
113         lua_getfield(L, -1, "create_auth");
114         lua_remove(L, -2); // Remove auth handler
115         if (lua_type(L, -1) != LUA_TFUNCTION)
116                 throw LuaError("Authentication handler missing create_auth");
117         lua_pushstring(L, playername.c_str());
118         lua_pushstring(L, password.c_str());
119         PCALL_RES(lua_pcall(L, 2, 0, error_handler));
120         lua_pop(L, 1); // Pop error handler
121 }
122
123 bool ScriptApiServer::setPassword(const std::string &playername,
124                 const std::string &password)
125 {
126         SCRIPTAPI_PRECHECKHEADER
127
128         int error_handler = PUSH_ERROR_HANDLER(L);
129         getAuthHandler();
130         lua_getfield(L, -1, "set_password");
131         lua_remove(L, -2); // Remove auth handler
132         if (lua_type(L, -1) != LUA_TFUNCTION)
133                 throw LuaError("Authentication handler missing set_password");
134         lua_pushstring(L, playername.c_str());
135         lua_pushstring(L, password.c_str());
136         PCALL_RES(lua_pcall(L, 2, 1, error_handler));
137         lua_remove(L, error_handler);
138         return lua_toboolean(L, -1);
139 }
140
141 bool ScriptApiServer::on_chat_message(const std::string &name,
142                 const std::string &message)
143 {
144         SCRIPTAPI_PRECHECKHEADER
145
146         // Get core.registered_on_chat_messages
147         lua_getglobal(L, "core");
148         lua_getfield(L, -1, "registered_on_chat_messages");
149         // Call callbacks
150         lua_pushstring(L, name.c_str());
151         lua_pushstring(L, message.c_str());
152         runCallbacks(2, RUN_CALLBACKS_MODE_OR_SC);
153         return readParam<bool>(L, -1);
154 }
155
156 void ScriptApiServer::on_mods_loaded()
157 {
158         SCRIPTAPI_PRECHECKHEADER
159
160         // Get registered shutdown hooks
161         lua_getglobal(L, "core");
162         lua_getfield(L, -1, "registered_on_mods_loaded");
163         // Call callbacks
164         runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
165 }
166
167 void ScriptApiServer::on_shutdown()
168 {
169         SCRIPTAPI_PRECHECKHEADER
170
171         // Get registered shutdown hooks
172         lua_getglobal(L, "core");
173         lua_getfield(L, -1, "registered_on_shutdown");
174         // Call callbacks
175         runCallbacks(0, RUN_CALLBACKS_MODE_FIRST);
176 }
177
178 std::string ScriptApiServer::formatChatMessage(const std::string &name,
179         const std::string &message)
180 {
181         SCRIPTAPI_PRECHECKHEADER
182
183         // Push function onto stack
184         lua_getglobal(L, "core");
185         lua_getfield(L, -1, "format_chat_message");
186
187         // Push arguments onto stack
188         lua_pushstring(L, name.c_str());
189         lua_pushstring(L, message.c_str());
190
191         // Actually call the function
192         lua_call(L, 2, 1);
193
194         // Fetch return value
195         std::string ret = lua_tostring(L, -1);
196         lua_pop(L, 1);
197
198         return ret;
199 }
200
201 u32 ScriptApiServer::allocateDynamicMediaCallback(lua_State *L, int f_idx)
202 {
203         if (f_idx < 0)
204                 f_idx = lua_gettop(L) + f_idx + 1;
205
206         lua_getglobal(L, "core");
207         lua_getfield(L, -1, "dynamic_media_callbacks");
208         luaL_checktype(L, -1, LUA_TTABLE);
209
210         // Find a randomly generated token that doesn't exist yet
211         int tries = 100;
212         u32 token;
213         while (1) {
214                 token = myrand();
215                 lua_rawgeti(L, -2, token);
216                 bool is_free = lua_isnil(L, -1);
217                 lua_pop(L, 1);
218                 if (is_free)
219                         break;
220                 if (--tries < 0)
221                         FATAL_ERROR("Ran out of callbacks IDs?!");
222         }
223
224         // core.dynamic_media_callbacks[token] = callback_func
225         lua_pushvalue(L, f_idx);
226         lua_rawseti(L, -2, token);
227
228         lua_pop(L, 2);
229
230         verbosestream << "allocateDynamicMediaCallback() = " << token << std::endl;
231         return token;
232 }
233
234 void ScriptApiServer::freeDynamicMediaCallback(u32 token)
235 {
236         SCRIPTAPI_PRECHECKHEADER
237
238         verbosestream << "freeDynamicMediaCallback(" << token << ")" << std::endl;
239
240         // core.dynamic_media_callbacks[token] = nil
241         lua_getglobal(L, "core");
242         lua_getfield(L, -1, "dynamic_media_callbacks");
243         luaL_checktype(L, -1, LUA_TTABLE);
244         lua_pushnil(L);
245         lua_rawseti(L, -2, token);
246         lua_pop(L, 2);
247 }
248
249 void ScriptApiServer::on_dynamic_media_added(u32 token, const char *playername)
250 {
251         SCRIPTAPI_PRECHECKHEADER
252
253         int error_handler = PUSH_ERROR_HANDLER(L);
254         lua_getglobal(L, "core");
255         lua_getfield(L, -1, "dynamic_media_callbacks");
256         luaL_checktype(L, -1, LUA_TTABLE);
257         lua_rawgeti(L, -1, token);
258         luaL_checktype(L, -1, LUA_TFUNCTION);
259
260         lua_pushstring(L, playername);
261         PCALL_RES(lua_pcall(L, 1, 0, error_handler));
262 }