]> git.lizzy.rs Git - minetest.git/blob - src/script/cpp_api/s_entity.cpp
Hardware coloring for itemstacks
[minetest.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         objectrefGet(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                 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         /* Read stuff */
173
174         prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
175
176         getboolfield(L, -1, "physical", prop->physical);
177         getboolfield(L, -1, "collide_with_objects", prop->collideWithObjects);
178
179         getfloatfield(L, -1, "weight", prop->weight);
180
181         lua_getfield(L, -1, "collisionbox");
182         if (lua_istable(L, -1))
183                 prop->collisionbox = read_aabb3f(L, -1, 1.0);
184         lua_pop(L, 1);
185
186         getstringfield(L, -1, "visual", prop->visual);
187
188         getstringfield(L, -1, "mesh", prop->mesh);
189
190         // Deprecated: read object properties directly
191         read_object_properties(L, -1, prop, getServer()->idef());
192
193         // Read initial_properties
194         lua_getfield(L, -1, "initial_properties");
195         read_object_properties(L, -1, prop, getServer()->idef());
196         lua_pop(L, 1);
197 }
198
199 void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
200 {
201         SCRIPTAPI_PRECHECKHEADER
202
203         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
204
205         int error_handler = PUSH_ERROR_HANDLER(L);
206
207         // Get core.luaentities[id]
208         luaentity_get(L, id);
209         int object = lua_gettop(L);
210         // State: object is at top of stack
211         // Get step function
212         lua_getfield(L, -1, "on_step");
213         if (lua_isnil(L, -1)) {
214                 lua_pop(L, 2); // Pop on_step and entity
215                 return;
216         }
217         luaL_checktype(L, -1, LUA_TFUNCTION);
218         lua_pushvalue(L, object); // self
219         lua_pushnumber(L, dtime); // dtime
220
221         setOriginFromTable(object);
222         PCALL_RES(lua_pcall(L, 2, 0, error_handler));
223
224         lua_pop(L, 2); // Pop object and error handler
225 }
226
227 // Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
228 //                       tool_capabilities, direction, damage)
229 bool ScriptApiEntity::luaentity_Punch(u16 id,
230                 ServerActiveObject *puncher, float time_from_last_punch,
231                 const ToolCapabilities *toolcap, v3f dir, s16 damage)
232 {
233         SCRIPTAPI_PRECHECKHEADER
234
235         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
236
237         int error_handler = PUSH_ERROR_HANDLER(L);
238
239         // Get core.luaentities[id]
240         luaentity_get(L,id);
241         int object = lua_gettop(L);
242         // State: object is at top of stack
243         // Get function
244         lua_getfield(L, -1, "on_punch");
245         if (lua_isnil(L, -1)) {
246                 lua_pop(L, 2); // Pop on_punch and entity
247                 return false;
248         }
249         luaL_checktype(L, -1, LUA_TFUNCTION);
250         lua_pushvalue(L, object);  // self
251         objectrefGetOrCreate(L, puncher);  // Clicker reference
252         lua_pushnumber(L, time_from_last_punch);
253         push_tool_capabilities(L, *toolcap);
254         push_v3f(L, dir);
255         lua_pushnumber(L, damage);
256
257         setOriginFromTable(object);
258         PCALL_RES(lua_pcall(L, 6, 1, error_handler));
259
260         bool retval = lua_toboolean(L, -1);
261         lua_pop(L, 2); // Pop object and error handler
262         return retval;
263 }
264
265 // Calls entity:on_rightclick(ObjectRef clicker)
266 void ScriptApiEntity::luaentity_Rightclick(u16 id,
267                 ServerActiveObject *clicker)
268 {
269         SCRIPTAPI_PRECHECKHEADER
270
271         //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
272
273         int error_handler = PUSH_ERROR_HANDLER(L);
274
275         // Get core.luaentities[id]
276         luaentity_get(L, id);
277         int object = lua_gettop(L);
278         // State: object is at top of stack
279         // Get function
280         lua_getfield(L, -1, "on_rightclick");
281         if (lua_isnil(L, -1)) {
282                 lua_pop(L, 2); // Pop on_rightclick and entity
283                 return;
284         }
285         luaL_checktype(L, -1, LUA_TFUNCTION);
286         lua_pushvalue(L, object); // self
287         objectrefGetOrCreate(L, clicker); // Clicker reference
288
289         setOriginFromTable(object);
290         PCALL_RES(lua_pcall(L, 2, 0, error_handler));
291
292         lua_pop(L, 2); // Pop object and error handler
293 }
294