]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/cpp_api/s_entity.cpp
Revert "Make Lint Happy"
[dragonfireclient.git] / src / script / cpp_api / s_entity.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_entity.h"
21 #include "cpp_api/s_internal.h"
22 #include "log.h"
23 #include "object_properties.h"
24 #include "common/c_converter.h"
25 #include "common/c_content.h"
26 #include "server.h"
27
28 bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
29 {
30         SCRIPTAPI_PRECHECKHEADER
31
32         verbosestream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
33                         <<name<<"\""<<std::endl;
34
35         // Get core.registered_entities[name]
36         lua_getglobal(L, "core");
37         lua_getfield(L, -1, "registered_entities");
38         luaL_checktype(L, -1, LUA_TTABLE);
39         lua_pushstring(L, name);
40         lua_gettable(L, -2);
41         // Should be a table, which we will use as a prototype
42         //luaL_checktype(L, -1, LUA_TTABLE);
43         if (lua_type(L, -1) != LUA_TTABLE){
44                 errorstream<<"LuaEntity name \""<<name<<"\" not defined"<<std::endl;
45                 return false;
46         }
47         int prototype_table = lua_gettop(L);
48         //dump2(L, "prototype_table");
49
50         // Create entity object
51         lua_newtable(L);
52         int object = lua_gettop(L);
53
54         // Set object metatable
55         lua_pushvalue(L, prototype_table);
56         lua_setmetatable(L, -2);
57
58         // Add object reference
59         // This should be userdata with metatable ObjectRef
60         push_objectRef(L, id);
61         luaL_checktype(L, -1, LUA_TUSERDATA);
62         if (!luaL_checkudata(L, -1, "ObjectRef"))
63                 luaL_typerror(L, -1, "ObjectRef");
64         lua_setfield(L, -2, "object");
65
66         // core.luaentities[id] = object
67         lua_getglobal(L, "core");
68         lua_getfield(L, -1, "luaentities");
69         luaL_checktype(L, -1, LUA_TTABLE);
70         lua_pushnumber(L, id); // Push id
71         lua_pushvalue(L, object); // Copy object to top of stack
72         lua_settable(L, -3);
73
74         return true;
75 }
76
77 void ScriptApiEntity::luaentity_Activate(u16 id,
78                 const std::string &staticdata, u32 dtime_s)
79 {
80         SCRIPTAPI_PRECHECKHEADER
81
82         verbosestream << "scriptapi_luaentity_activate: id=" << id << std::endl;
83
84         int error_handler = PUSH_ERROR_HANDLER(L);
85
86         // Get core.luaentities[id]
87         luaentity_get(L, id);
88         int object = lua_gettop(L);
89
90         // Get on_activate function
91         lua_getfield(L, -1, "on_activate");
92         if (!lua_isnil(L, -1)) {
93                 luaL_checktype(L, -1, LUA_TFUNCTION);
94                 lua_pushvalue(L, object); // self
95                 lua_pushlstring(L, staticdata.c_str(), staticdata.size());
96                 lua_pushinteger(L, dtime_s);
97
98                 setOriginFromTable(object);
99                 PCALL_RES(lua_pcall(L, 3, 0, error_handler));
100         } else {
101                 lua_pop(L, 1);
102         }
103         lua_pop(L, 2); // Pop object and error handler
104 }
105
106 void ScriptApiEntity::luaentity_Remove(u16 id)
107 {
108         SCRIPTAPI_PRECHECKHEADER
109
110         verbosestream << "scriptapi_luaentity_rm: id=" << id << std::endl;
111
112         // Get core.luaentities table
113         lua_getglobal(L, "core");
114         lua_getfield(L, -1, "luaentities");
115         luaL_checktype(L, -1, LUA_TTABLE);
116         int objectstable = lua_gettop(L);
117
118         // Set luaentities[id] = nil
119         lua_pushnumber(L, id); // Push id
120         lua_pushnil(L);
121         lua_settable(L, objectstable);
122
123         lua_pop(L, 2); // pop luaentities, core
124 }
125
126 std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
127 {
128         SCRIPTAPI_PRECHECKHEADER
129
130         //infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
131
132         int error_handler = PUSH_ERROR_HANDLER(L);
133
134         // Get core.luaentities[id]
135         luaentity_get(L, id);
136         int object = lua_gettop(L);
137
138         // Get get_staticdata function
139         lua_getfield(L, -1, "get_staticdata");
140         if (lua_isnil(L, -1)) {
141                 lua_pop(L, 2); // Pop entity and  get_staticdata
142                 return "";
143         }
144         luaL_checktype(L, -1, LUA_TFUNCTION);
145         lua_pushvalue(L, object); // self
146
147         setOriginFromTable(object);
148         PCALL_RES(lua_pcall(L, 1, 1, error_handler));
149
150         lua_remove(L, object);
151         lua_remove(L, error_handler);
152
153         size_t len = 0;
154         const char *s = lua_tolstring(L, -1, &len);
155         lua_pop(L, 1); // Pop static data
156         return std::string(s, len);
157 }
158
159 void ScriptApiEntity::luaentity_GetProperties(u16 id,
160                 ServerActiveObject *self, ObjectProperties *prop)
161 {
162         SCRIPTAPI_PRECHECKHEADER
163
164         //infostream<<"scriptapi_luaentity_get_properties: id="<<id<<std::endl;
165
166         // Get core.luaentities[id]
167         luaentity_get(L, id);
168
169         // Set default values that differ from ObjectProperties defaults
170         prop->hp_max = 10;
171
172         // Deprecated: read object properties directly
173         read_object_properties(L, -1, self, prop, getServer()->idef());
174
175         // Read initial_properties
176         lua_getfield(L, -1, "initial_properties");
177         read_object_properties(L, -1, self, prop, getServer()->idef());
178         lua_pop(L, 1);
179 }
180
181 void ScriptApiEntity::luaentity_Step(u16 id, float dtime,
182         const collisionMoveResult *moveresult)
183 {
184         SCRIPTAPI_PRECHECKHEADER
185
186         int error_handler = PUSH_ERROR_HANDLER(L);
187
188         // Get core.luaentities[id]
189         luaentity_get(L, id);
190         int object = lua_gettop(L);
191         // State: object is at top of stack
192         // Get step function
193         lua_getfield(L, -1, "on_step");
194         if (lua_isnil(L, -1)) {
195                 lua_pop(L, 2); // Pop on_step and entity
196                 return;
197         }
198         luaL_checktype(L, -1, LUA_TFUNCTION);
199         lua_pushvalue(L, object); // self
200         lua_pushnumber(L, dtime); // dtime
201         /* moveresult */
202         if (moveresult)
203                 push_collision_move_result(L, *moveresult);
204         else
205                 lua_pushnil(L);
206
207         setOriginFromTable(object);
208         PCALL_RES(lua_pcall(L, 3, 0, error_handler));
209
210         lua_pop(L, 2); // Pop object and error handler
211 }
212
213 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
214 //                       tool_capabilities, direction, damage)
215 bool ScriptApiEntity::luaentity_Punch(u16 id,
216                 ServerActiveObject *puncher, float time_from_last_punch,
217                 const ToolCapabilities *toolcap, v3f dir, s16 damage)
218 {
219         SCRIPTAPI_PRECHECKHEADER
220
221         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
222
223         int error_handler = PUSH_ERROR_HANDLER(L);
224
225         // Get core.luaentities[id]
226         luaentity_get(L,id);
227         int object = lua_gettop(L);
228         // State: object is at top of stack
229         // Get function
230         lua_getfield(L, -1, "on_punch");
231         if (lua_isnil(L, -1)) {
232                 lua_pop(L, 2); // Pop on_punch and entity
233                 return false;
234         }
235         luaL_checktype(L, -1, LUA_TFUNCTION);
236         lua_pushvalue(L, object);  // self
237         objectrefGetOrCreate(L, puncher);  // Clicker reference
238         lua_pushnumber(L, time_from_last_punch);
239         push_tool_capabilities(L, *toolcap);
240         push_v3f(L, dir);
241         lua_pushnumber(L, damage);
242
243         setOriginFromTable(object);
244         PCALL_RES(lua_pcall(L, 6, 1, error_handler));
245
246         bool retval = readParam<bool>(L, -1);
247         lua_pop(L, 2); // Pop object and error handler
248         return retval;
249 }
250
251 // Calls entity[field](ObjectRef self, ObjectRef sao)
252 bool ScriptApiEntity::luaentity_run_simple_callback(u16 id,
253         ServerActiveObject *sao, const char *field)
254 {
255         SCRIPTAPI_PRECHECKHEADER
256
257         int error_handler = PUSH_ERROR_HANDLER(L);
258
259         // Get core.luaentities[id]
260         luaentity_get(L, id);
261         int object = lua_gettop(L);
262         // State: object is at top of stack
263         // Get function
264         lua_getfield(L, -1, field);
265         if (lua_isnil(L, -1)) {
266                 lua_pop(L, 2); // Pop callback field and entity
267                 return false;
268         }
269         luaL_checktype(L, -1, LUA_TFUNCTION);
270         lua_pushvalue(L, object);  // self
271         objectrefGetOrCreate(L, sao);  // killer reference
272
273         setOriginFromTable(object);
274         PCALL_RES(lua_pcall(L, 2, 1, error_handler));
275
276         bool retval = readParam<bool>(L, -1);
277         lua_pop(L, 2); // Pop object and error handler
278         return retval;
279 }
280
281 bool ScriptApiEntity::luaentity_on_death(u16 id, ServerActiveObject *killer)
282 {
283         return luaentity_run_simple_callback(id, killer, "on_death");
284 }
285
286 // Calls entity:on_rightclick(ObjectRef clicker)
287 void ScriptApiEntity::luaentity_Rightclick(u16 id, ServerActiveObject *clicker)
288 {
289         luaentity_run_simple_callback(id, clicker, "on_rightclick");
290 }
291
292 void ScriptApiEntity::luaentity_on_attach_child(u16 id, ServerActiveObject *child)
293 {
294         luaentity_run_simple_callback(id, child, "on_attach_child");
295 }
296
297 void ScriptApiEntity::luaentity_on_detach_child(u16 id, ServerActiveObject *child)
298 {
299         luaentity_run_simple_callback(id, child, "on_detach_child");
300 }
301
302 void ScriptApiEntity::luaentity_on_detach(u16 id, ServerActiveObject *parent)
303 {
304         luaentity_run_simple_callback(id, parent, "on_detach");
305 }