Line data Source code
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 "lua_api/l_object.h"
21 : #include "lua_api/l_internal.h"
22 : #include "lua_api/l_inventory.h"
23 : #include "lua_api/l_item.h"
24 : #include "common/c_converter.h"
25 : #include "common/c_content.h"
26 : #include "log.h"
27 : #include "tool.h"
28 : #include "serverobject.h"
29 : #include "content_sao.h"
30 : #include "server.h"
31 : #include "hud.h"
32 : #include "scripting_game.h"
33 :
34 : #define GET_ENV_PTR ServerEnvironment* env = \
35 : dynamic_cast<ServerEnvironment*>(getEnv(L)); \
36 : if (env == NULL) return 0
37 :
38 : struct EnumString es_HudElementType[] =
39 : {
40 : {HUD_ELEM_IMAGE, "image"},
41 : {HUD_ELEM_TEXT, "text"},
42 : {HUD_ELEM_STATBAR, "statbar"},
43 : {HUD_ELEM_INVENTORY, "inventory"},
44 : {HUD_ELEM_WAYPOINT, "waypoint"},
45 : {0, NULL},
46 : };
47 :
48 : struct EnumString es_HudElementStat[] =
49 : {
50 : {HUD_STAT_POS, "position"},
51 : {HUD_STAT_POS, "pos"}, /* Deprecated, only for compatibility's sake */
52 : {HUD_STAT_NAME, "name"},
53 : {HUD_STAT_SCALE, "scale"},
54 : {HUD_STAT_TEXT, "text"},
55 : {HUD_STAT_NUMBER, "number"},
56 : {HUD_STAT_ITEM, "item"},
57 : {HUD_STAT_DIR, "direction"},
58 : {HUD_STAT_ALIGN, "alignment"},
59 : {HUD_STAT_OFFSET, "offset"},
60 : {HUD_STAT_WORLD_POS, "world_pos"},
61 : {0, NULL},
62 : };
63 :
64 : struct EnumString es_HudBuiltinElement[] =
65 : {
66 : {HUD_FLAG_HOTBAR_VISIBLE, "hotbar"},
67 : {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"},
68 : {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
69 : {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
70 : {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
71 : {0, NULL},
72 : };
73 :
74 : /*
75 : ObjectRef
76 : */
77 :
78 :
79 0 : ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
80 : {
81 0 : luaL_checktype(L, narg, LUA_TUSERDATA);
82 0 : void *ud = luaL_checkudata(L, narg, className);
83 0 : if(!ud) luaL_typerror(L, narg, className);
84 0 : return *(ObjectRef**)ud; // unbox pointer
85 : }
86 :
87 0 : ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
88 : {
89 0 : ServerActiveObject *co = ref->m_object;
90 0 : return co;
91 : }
92 :
93 0 : LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
94 : {
95 0 : ServerActiveObject *obj = getobject(ref);
96 0 : if(obj == NULL)
97 0 : return NULL;
98 0 : if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
99 0 : return NULL;
100 0 : return (LuaEntitySAO*)obj;
101 : }
102 :
103 0 : PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
104 : {
105 0 : ServerActiveObject *obj = getobject(ref);
106 0 : if(obj == NULL)
107 0 : return NULL;
108 0 : if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
109 0 : return NULL;
110 0 : return (PlayerSAO*)obj;
111 : }
112 :
113 0 : Player* ObjectRef::getplayer(ObjectRef *ref)
114 : {
115 0 : PlayerSAO *playersao = getplayersao(ref);
116 0 : if(playersao == NULL)
117 0 : return NULL;
118 0 : return playersao->getPlayer();
119 : }
120 :
121 : // Exported functions
122 :
123 : // garbage collector
124 0 : int ObjectRef::gc_object(lua_State *L) {
125 0 : ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
126 : //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
127 0 : delete o;
128 0 : return 0;
129 : }
130 :
131 : // remove(self)
132 0 : int ObjectRef::l_remove(lua_State *L)
133 : {
134 0 : NO_MAP_LOCK_REQUIRED;
135 0 : ObjectRef *ref = checkobject(L, 1);
136 0 : ServerActiveObject *co = getobject(ref);
137 0 : if(co == NULL) return 0;
138 0 : if(co->getType() == ACTIVEOBJECT_TYPE_PLAYER) return 0;
139 0 : verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
140 0 : co->m_removed = true;
141 0 : return 0;
142 : }
143 :
144 : // getpos(self)
145 : // returns: {x=num, y=num, z=num}
146 0 : int ObjectRef::l_getpos(lua_State *L)
147 : {
148 0 : NO_MAP_LOCK_REQUIRED;
149 0 : ObjectRef *ref = checkobject(L, 1);
150 0 : ServerActiveObject *co = getobject(ref);
151 0 : if(co == NULL) return 0;
152 0 : v3f pos = co->getBasePosition() / BS;
153 0 : lua_newtable(L);
154 0 : lua_pushnumber(L, pos.X);
155 0 : lua_setfield(L, -2, "x");
156 0 : lua_pushnumber(L, pos.Y);
157 0 : lua_setfield(L, -2, "y");
158 0 : lua_pushnumber(L, pos.Z);
159 0 : lua_setfield(L, -2, "z");
160 0 : return 1;
161 : }
162 :
163 : // setpos(self, pos)
164 0 : int ObjectRef::l_setpos(lua_State *L)
165 : {
166 0 : NO_MAP_LOCK_REQUIRED;
167 0 : ObjectRef *ref = checkobject(L, 1);
168 : //LuaEntitySAO *co = getluaobject(ref);
169 0 : ServerActiveObject *co = getobject(ref);
170 0 : if(co == NULL) return 0;
171 : // pos
172 0 : v3f pos = checkFloatPos(L, 2);
173 : // Do it
174 0 : co->setPos(pos);
175 0 : return 0;
176 : }
177 :
178 : // moveto(self, pos, continuous=false)
179 0 : int ObjectRef::l_moveto(lua_State *L)
180 : {
181 0 : NO_MAP_LOCK_REQUIRED;
182 0 : ObjectRef *ref = checkobject(L, 1);
183 : //LuaEntitySAO *co = getluaobject(ref);
184 0 : ServerActiveObject *co = getobject(ref);
185 0 : if(co == NULL) return 0;
186 : // pos
187 0 : v3f pos = checkFloatPos(L, 2);
188 : // continuous
189 0 : bool continuous = lua_toboolean(L, 3);
190 : // Do it
191 0 : co->moveTo(pos, continuous);
192 0 : return 0;
193 : }
194 :
195 : // punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
196 0 : int ObjectRef::l_punch(lua_State *L)
197 : {
198 0 : NO_MAP_LOCK_REQUIRED;
199 0 : ObjectRef *ref = checkobject(L, 1);
200 0 : ObjectRef *puncher_ref = checkobject(L, 2);
201 0 : ServerActiveObject *co = getobject(ref);
202 0 : ServerActiveObject *puncher = getobject(puncher_ref);
203 0 : if(co == NULL) return 0;
204 0 : if(puncher == NULL) return 0;
205 0 : v3f dir;
206 0 : if(lua_type(L, 5) != LUA_TTABLE)
207 0 : dir = co->getBasePosition() - puncher->getBasePosition();
208 : else
209 0 : dir = read_v3f(L, 5);
210 0 : float time_from_last_punch = 1000000;
211 0 : if(lua_isnumber(L, 3))
212 0 : time_from_last_punch = lua_tonumber(L, 3);
213 0 : ToolCapabilities toolcap = read_tool_capabilities(L, 4);
214 0 : dir.normalize();
215 :
216 0 : s16 src_original_hp = co->getHP();
217 0 : s16 dst_origin_hp = puncher->getHP();
218 :
219 : // Do it
220 0 : co->punch(dir, &toolcap, puncher, time_from_last_punch);
221 :
222 : // If the punched is a player, and its HP changed
223 0 : if (src_original_hp != co->getHP() &&
224 0 : co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
225 0 : getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(),
226 0 : co->getHP() == 0);
227 : }
228 :
229 : // If the puncher is a player, and its HP changed
230 0 : if (dst_origin_hp != puncher->getHP() &&
231 0 : puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
232 0 : getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)puncher)->getPeerID(),
233 0 : puncher->getHP() == 0);
234 : }
235 0 : return 0;
236 : }
237 :
238 : // right_click(self, clicker); clicker = an another ObjectRef
239 0 : int ObjectRef::l_right_click(lua_State *L)
240 : {
241 0 : NO_MAP_LOCK_REQUIRED;
242 0 : ObjectRef *ref = checkobject(L, 1);
243 0 : ObjectRef *ref2 = checkobject(L, 2);
244 0 : ServerActiveObject *co = getobject(ref);
245 0 : ServerActiveObject *co2 = getobject(ref2);
246 0 : if(co == NULL) return 0;
247 0 : if(co2 == NULL) return 0;
248 : // Do it
249 0 : co->rightClick(co2);
250 0 : return 0;
251 : }
252 :
253 : // set_hp(self, hp)
254 : // hp = number of hitpoints (2 * number of hearts)
255 : // returns: nil
256 0 : int ObjectRef::l_set_hp(lua_State *L)
257 : {
258 0 : NO_MAP_LOCK_REQUIRED;
259 0 : ObjectRef *ref = checkobject(L, 1);
260 0 : luaL_checknumber(L, 2);
261 0 : ServerActiveObject *co = getobject(ref);
262 0 : if(co == NULL) return 0;
263 0 : int hp = lua_tonumber(L, 2);
264 : /*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
265 : <<" hp="<<hp<<std::endl;*/
266 : // Do it
267 0 : co->setHP(hp);
268 0 : if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
269 0 : getServer(L)->SendPlayerHPOrDie(((PlayerSAO*)co)->getPeerID(), co->getHP() == 0);
270 : }
271 : // Return
272 0 : return 0;
273 : }
274 :
275 : // get_hp(self)
276 : // returns: number of hitpoints (2 * number of hearts)
277 : // 0 if not applicable to this type of object
278 0 : int ObjectRef::l_get_hp(lua_State *L)
279 : {
280 0 : NO_MAP_LOCK_REQUIRED;
281 0 : ObjectRef *ref = checkobject(L, 1);
282 0 : ServerActiveObject *co = getobject(ref);
283 0 : if(co == NULL){
284 : // Default hp is 1
285 0 : lua_pushnumber(L, 1);
286 0 : return 1;
287 : }
288 0 : int hp = co->getHP();
289 : /*infostream<<"ObjectRef::l_get_hp(): id="<<co->getId()
290 : <<" hp="<<hp<<std::endl;*/
291 : // Return
292 0 : lua_pushnumber(L, hp);
293 0 : return 1;
294 : }
295 :
296 : // get_inventory(self)
297 0 : int ObjectRef::l_get_inventory(lua_State *L)
298 : {
299 0 : NO_MAP_LOCK_REQUIRED;
300 0 : ObjectRef *ref = checkobject(L, 1);
301 0 : ServerActiveObject *co = getobject(ref);
302 0 : if(co == NULL) return 0;
303 : // Do it
304 0 : InventoryLocation loc = co->getInventoryLocation();
305 0 : if(getServer(L)->getInventory(loc) != NULL)
306 0 : InvRef::create(L, loc);
307 : else
308 0 : lua_pushnil(L); // An object may have no inventory (nil)
309 0 : return 1;
310 : }
311 :
312 : // get_wield_list(self)
313 0 : int ObjectRef::l_get_wield_list(lua_State *L)
314 : {
315 0 : NO_MAP_LOCK_REQUIRED;
316 0 : ObjectRef *ref = checkobject(L, 1);
317 0 : ServerActiveObject *co = getobject(ref);
318 0 : if(co == NULL) return 0;
319 : // Do it
320 0 : lua_pushstring(L, co->getWieldList().c_str());
321 0 : return 1;
322 : }
323 :
324 : // get_wield_index(self)
325 0 : int ObjectRef::l_get_wield_index(lua_State *L)
326 : {
327 0 : NO_MAP_LOCK_REQUIRED;
328 0 : ObjectRef *ref = checkobject(L, 1);
329 0 : ServerActiveObject *co = getobject(ref);
330 0 : if(co == NULL) return 0;
331 : // Do it
332 0 : lua_pushinteger(L, co->getWieldIndex() + 1);
333 0 : return 1;
334 : }
335 :
336 : // get_wielded_item(self)
337 0 : int ObjectRef::l_get_wielded_item(lua_State *L)
338 : {
339 0 : NO_MAP_LOCK_REQUIRED;
340 0 : ObjectRef *ref = checkobject(L, 1);
341 0 : ServerActiveObject *co = getobject(ref);
342 0 : if(co == NULL){
343 : // Empty ItemStack
344 0 : LuaItemStack::create(L, ItemStack());
345 0 : return 1;
346 : }
347 : // Do it
348 0 : LuaItemStack::create(L, co->getWieldedItem());
349 0 : return 1;
350 : }
351 :
352 : // set_wielded_item(self, itemstack or itemstring or table or nil)
353 0 : int ObjectRef::l_set_wielded_item(lua_State *L)
354 : {
355 0 : NO_MAP_LOCK_REQUIRED;
356 0 : ObjectRef *ref = checkobject(L, 1);
357 0 : ServerActiveObject *co = getobject(ref);
358 0 : if(co == NULL) return 0;
359 : // Do it
360 0 : ItemStack item = read_item(L, 2, getServer(L));
361 0 : bool success = co->setWieldedItem(item);
362 0 : if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
363 0 : getServer(L)->SendInventory(((PlayerSAO*)co));
364 : }
365 0 : lua_pushboolean(L, success);
366 0 : return 1;
367 : }
368 :
369 : // set_armor_groups(self, groups)
370 0 : int ObjectRef::l_set_armor_groups(lua_State *L)
371 : {
372 0 : NO_MAP_LOCK_REQUIRED;
373 0 : ObjectRef *ref = checkobject(L, 1);
374 0 : ServerActiveObject *co = getobject(ref);
375 0 : if(co == NULL) return 0;
376 : // Do it
377 0 : ItemGroupList groups;
378 0 : read_groups(L, 2, groups);
379 0 : co->setArmorGroups(groups);
380 0 : return 0;
381 : }
382 :
383 : // get_armor_groups(self)
384 0 : int ObjectRef::l_get_armor_groups(lua_State *L)
385 : {
386 0 : NO_MAP_LOCK_REQUIRED;
387 0 : ObjectRef *ref = checkobject(L, 1);
388 0 : ServerActiveObject *co = getobject(ref);
389 0 : if (co == NULL)
390 0 : return 0;
391 : // Do it
392 0 : ItemGroupList groups = co->getArmorGroups();
393 0 : push_groups(L, groups);
394 0 : return 1;
395 : }
396 :
397 : // set_physics_override(self, physics_override_speed, physics_override_jump,
398 : // physics_override_gravity, sneak, sneak_glitch)
399 0 : int ObjectRef::l_set_physics_override(lua_State *L)
400 : {
401 0 : ObjectRef *ref = checkobject(L, 1);
402 0 : PlayerSAO *co = (PlayerSAO *) getobject(ref);
403 0 : if(co == NULL) return 0;
404 : // Do it
405 0 : if (lua_istable(L, 2)) {
406 0 : co->m_physics_override_speed = getfloatfield_default(L, 2, "speed", co->m_physics_override_speed);
407 0 : co->m_physics_override_jump = getfloatfield_default(L, 2, "jump", co->m_physics_override_jump);
408 0 : co->m_physics_override_gravity = getfloatfield_default(L, 2, "gravity", co->m_physics_override_gravity);
409 0 : co->m_physics_override_sneak = getboolfield_default(L, 2, "sneak", co->m_physics_override_sneak);
410 0 : co->m_physics_override_sneak_glitch = getboolfield_default(L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch);
411 0 : co->m_physics_override_sent = false;
412 : } else {
413 : // old, non-table format
414 0 : if(!lua_isnil(L, 2)){
415 0 : co->m_physics_override_speed = lua_tonumber(L, 2);
416 0 : co->m_physics_override_sent = false;
417 : }
418 0 : if(!lua_isnil(L, 3)){
419 0 : co->m_physics_override_jump = lua_tonumber(L, 3);
420 0 : co->m_physics_override_sent = false;
421 : }
422 0 : if(!lua_isnil(L, 4)){
423 0 : co->m_physics_override_gravity = lua_tonumber(L, 4);
424 0 : co->m_physics_override_sent = false;
425 : }
426 : }
427 0 : return 0;
428 : }
429 :
430 : // get_physics_override(self)
431 0 : int ObjectRef::l_get_physics_override(lua_State *L)
432 : {
433 0 : ObjectRef *ref = checkobject(L, 1);
434 0 : PlayerSAO *co = (PlayerSAO *)getobject(ref);
435 0 : if (co == NULL)
436 0 : return 0;
437 : // Do it
438 0 : lua_newtable(L);
439 0 : lua_pushnumber(L, co->m_physics_override_speed);
440 0 : lua_setfield(L, -2, "speed");
441 0 : lua_pushnumber(L, co->m_physics_override_jump);
442 0 : lua_setfield(L, -2, "jump");
443 0 : lua_pushnumber(L, co->m_physics_override_gravity);
444 0 : lua_setfield(L, -2, "gravity");
445 0 : lua_pushboolean(L, co->m_physics_override_sneak);
446 0 : lua_setfield(L, -2, "sneak");
447 0 : lua_pushboolean(L, co->m_physics_override_sneak_glitch);
448 0 : lua_setfield(L, -2, "sneak_glitch");
449 0 : return 1;
450 : }
451 :
452 : // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
453 0 : int ObjectRef::l_set_animation(lua_State *L)
454 : {
455 0 : NO_MAP_LOCK_REQUIRED;
456 0 : ObjectRef *ref = checkobject(L, 1);
457 0 : ServerActiveObject *co = getobject(ref);
458 0 : if(co == NULL) return 0;
459 : // Do it
460 0 : v2f frames = v2f(1, 1);
461 0 : if(!lua_isnil(L, 2))
462 0 : frames = read_v2f(L, 2);
463 0 : float frame_speed = 15;
464 0 : if(!lua_isnil(L, 3))
465 0 : frame_speed = lua_tonumber(L, 3);
466 0 : float frame_blend = 0;
467 0 : if(!lua_isnil(L, 4))
468 0 : frame_blend = lua_tonumber(L, 4);
469 0 : bool frame_loop = true;
470 0 : if(lua_isboolean(L, 5))
471 0 : frame_loop = lua_toboolean(L, 5);
472 0 : co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
473 0 : return 0;
474 : }
475 :
476 : // get_animation(self)
477 0 : int ObjectRef::l_get_animation(lua_State *L)
478 : {
479 0 : NO_MAP_LOCK_REQUIRED;
480 0 : ObjectRef *ref = checkobject(L, 1);
481 0 : ServerActiveObject *co = getobject(ref);
482 0 : if (co == NULL)
483 0 : return 0;
484 : // Do it
485 0 : v2f frames = v2f(1,1);
486 0 : float frame_speed = 15;
487 0 : float frame_blend = 0;
488 0 : bool frame_loop = true;
489 0 : co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
490 :
491 0 : push_v2f(L, frames);
492 0 : lua_pushnumber(L, frame_speed);
493 0 : lua_pushnumber(L, frame_blend);
494 0 : lua_pushboolean(L, frame_loop);
495 0 : return 4;
496 : }
497 :
498 : // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
499 0 : int ObjectRef::l_set_local_animation(lua_State *L)
500 : {
501 : //NO_MAP_LOCK_REQUIRED;
502 0 : ObjectRef *ref = checkobject(L, 1);
503 0 : Player *player = getplayer(ref);
504 0 : if (player == NULL)
505 0 : return 0;
506 : // Do it
507 0 : v2s32 frames[4];
508 0 : for (int i=0;i<4;i++) {
509 0 : if(!lua_isnil(L, 2+1))
510 0 : frames[i] = read_v2s32(L, 2+i);
511 : }
512 0 : float frame_speed = 30;
513 0 : if(!lua_isnil(L, 6))
514 0 : frame_speed = lua_tonumber(L, 6);
515 :
516 0 : if (!getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed))
517 0 : return 0;
518 :
519 0 : lua_pushboolean(L, true);
520 0 : return 0;
521 : }
522 :
523 : // get_local_animation(self)
524 0 : int ObjectRef::l_get_local_animation(lua_State *L)
525 : {
526 : //NO_MAP_LOCK_REQUIRED
527 0 : ObjectRef *ref = checkobject(L, 1);
528 0 : Player *player = getplayer(ref);
529 0 : if (player == NULL)
530 0 : return 0;
531 :
532 0 : v2s32 frames[4];
533 : float frame_speed;
534 0 : player->getLocalAnimations(frames, &frame_speed);
535 :
536 0 : for (int i = 0; i < 4; i++) {
537 0 : push_v2s32(L, frames[i]);
538 : }
539 :
540 0 : lua_pushnumber(L, frame_speed);
541 0 : return 5;
542 : }
543 :
544 : // set_eye_offset(self, v3f first pv, v3f third pv)
545 0 : int ObjectRef::l_set_eye_offset(lua_State *L)
546 : {
547 : //NO_MAP_LOCK_REQUIRED;
548 0 : ObjectRef *ref = checkobject(L, 1);
549 0 : Player *player = getplayer(ref);
550 0 : if (player == NULL)
551 0 : return 0;
552 : // Do it
553 0 : v3f offset_first = v3f(0, 0, 0);
554 0 : v3f offset_third = v3f(0, 0, 0);
555 :
556 0 : if(!lua_isnil(L, 2))
557 0 : offset_first = read_v3f(L, 2);
558 0 : if(!lua_isnil(L, 3))
559 0 : offset_third = read_v3f(L, 3);
560 :
561 : // Prevent abuse of offset values (keep player always visible)
562 0 : offset_third.X = rangelim(offset_third.X,-10,10);
563 0 : offset_third.Z = rangelim(offset_third.Z,-5,5);
564 : /* TODO: if possible: improve the camera colision detetion to allow Y <= -1.5) */
565 0 : offset_third.Y = rangelim(offset_third.Y,-10,15); //1.5*BS
566 :
567 0 : if (!getServer(L)->setPlayerEyeOffset(player, offset_first, offset_third))
568 0 : return 0;
569 :
570 0 : lua_pushboolean(L, true);
571 0 : return 0;
572 : }
573 :
574 : // get_eye_offset(self)
575 0 : int ObjectRef::l_get_eye_offset(lua_State *L)
576 : {
577 : //NO_MAP_LOCK_REQUIRED;
578 0 : ObjectRef *ref = checkobject(L, 1);
579 0 : Player *player = getplayer(ref);
580 0 : if (player == NULL)
581 0 : return 0;
582 : // Do it
583 0 : push_v3f(L, player->eye_offset_first);
584 0 : push_v3f(L, player->eye_offset_third);
585 0 : return 2;
586 : }
587 :
588 : // set_bone_position(self, std::string bone, v3f position, v3f rotation)
589 0 : int ObjectRef::l_set_bone_position(lua_State *L)
590 : {
591 0 : NO_MAP_LOCK_REQUIRED;
592 0 : ObjectRef *ref = checkobject(L, 1);
593 0 : ServerActiveObject *co = getobject(ref);
594 0 : if(co == NULL) return 0;
595 : // Do it
596 0 : std::string bone = "";
597 0 : if(!lua_isnil(L, 2))
598 0 : bone = lua_tostring(L, 2);
599 0 : v3f position = v3f(0, 0, 0);
600 0 : if(!lua_isnil(L, 3))
601 0 : position = read_v3f(L, 3);
602 0 : v3f rotation = v3f(0, 0, 0);
603 0 : if(!lua_isnil(L, 4))
604 0 : rotation = read_v3f(L, 4);
605 0 : co->setBonePosition(bone, position, rotation);
606 0 : return 0;
607 : }
608 :
609 : // get_bone_position(self, bone)
610 0 : int ObjectRef::l_get_bone_position(lua_State *L)
611 : {
612 0 : NO_MAP_LOCK_REQUIRED;
613 0 : ObjectRef *ref = checkobject(L, 1);
614 0 : ServerActiveObject *co = getobject(ref);
615 0 : if (co == NULL)
616 0 : return 0;
617 : // Do it
618 0 : std::string bone = "";
619 0 : if(!lua_isnil(L, 2))
620 0 : bone = lua_tostring(L, 2);
621 :
622 0 : v3f position = v3f(0, 0, 0);
623 0 : v3f rotation = v3f(0, 0, 0);
624 0 : co->getBonePosition(bone, &position, &rotation);
625 :
626 0 : push_v3f(L, position);
627 0 : push_v3f(L, rotation);
628 0 : return 2;
629 : }
630 :
631 : // set_attach(self, parent, bone, position, rotation)
632 0 : int ObjectRef::l_set_attach(lua_State *L)
633 : {
634 0 : NO_MAP_LOCK_REQUIRED;
635 0 : ObjectRef *ref = checkobject(L, 1);
636 0 : ObjectRef *parent_ref = checkobject(L, 2);
637 0 : ServerActiveObject *co = getobject(ref);
638 0 : ServerActiveObject *parent = getobject(parent_ref);
639 0 : if(co == NULL) return 0;
640 0 : if(parent == NULL) return 0;
641 : // Do it
642 0 : std::string bone = "";
643 0 : if(!lua_isnil(L, 3))
644 0 : bone = lua_tostring(L, 3);
645 0 : v3f position = v3f(0, 0, 0);
646 0 : if(!lua_isnil(L, 4))
647 0 : position = read_v3f(L, 4);
648 0 : v3f rotation = v3f(0, 0, 0);
649 0 : if(!lua_isnil(L, 5))
650 0 : rotation = read_v3f(L, 5);
651 0 : co->setAttachment(parent->getId(), bone, position, rotation);
652 0 : return 0;
653 : }
654 :
655 : // get_attach(self)
656 0 : int ObjectRef::l_get_attach(lua_State *L)
657 : {
658 0 : NO_MAP_LOCK_REQUIRED;
659 0 : GET_ENV_PTR;
660 :
661 0 : ObjectRef *ref = checkobject(L, 1);
662 0 : ServerActiveObject *co = getobject(ref);
663 0 : if (co == NULL)
664 0 : return 0;
665 :
666 : // Do it
667 0 : int parent_id = 0;
668 0 : std::string bone = "";
669 0 : v3f position = v3f(0, 0, 0);
670 0 : v3f rotation = v3f(0, 0, 0);
671 0 : co->getAttachment(&parent_id, &bone, &position, &rotation);
672 0 : if (!parent_id)
673 0 : return 0;
674 0 : ServerActiveObject *parent = env->getActiveObject(parent_id);
675 :
676 0 : getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
677 0 : lua_pushlstring(L, bone.c_str(), bone.size());
678 0 : push_v3f(L, position);
679 0 : push_v3f(L, rotation);
680 0 : return 4;
681 : }
682 :
683 : // set_detach(self)
684 0 : int ObjectRef::l_set_detach(lua_State *L)
685 : {
686 0 : NO_MAP_LOCK_REQUIRED;
687 0 : ObjectRef *ref = checkobject(L, 1);
688 0 : ServerActiveObject *co = getobject(ref);
689 0 : if(co == NULL) return 0;
690 : // Do it
691 0 : co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
692 0 : return 0;
693 : }
694 :
695 : // set_properties(self, properties)
696 0 : int ObjectRef::l_set_properties(lua_State *L)
697 : {
698 0 : NO_MAP_LOCK_REQUIRED;
699 0 : ObjectRef *ref = checkobject(L, 1);
700 0 : ServerActiveObject *co = getobject(ref);
701 0 : if(co == NULL) return 0;
702 0 : ObjectProperties *prop = co->accessObjectProperties();
703 0 : if(!prop)
704 0 : return 0;
705 0 : read_object_properties(L, 2, prop);
706 0 : co->notifyObjectPropertiesModified();
707 0 : return 0;
708 : }
709 :
710 : // get_properties(self)
711 0 : int ObjectRef::l_get_properties(lua_State *L)
712 : {
713 0 : NO_MAP_LOCK_REQUIRED;
714 0 : ObjectRef *ref = checkobject(L, 1);
715 0 : ServerActiveObject *co = getobject(ref);
716 0 : if (co == NULL)
717 0 : return 0;
718 0 : ObjectProperties *prop = co->accessObjectProperties();
719 0 : if (!prop)
720 0 : return 0;
721 0 : push_object_properties(L, prop);
722 0 : return 1;
723 : }
724 :
725 : // is_player(self)
726 0 : int ObjectRef::l_is_player(lua_State *L)
727 : {
728 0 : NO_MAP_LOCK_REQUIRED;
729 0 : ObjectRef *ref = checkobject(L, 1);
730 0 : Player *player = getplayer(ref);
731 0 : lua_pushboolean(L, (player != NULL));
732 0 : return 1;
733 : }
734 :
735 : /* LuaEntitySAO-only */
736 :
737 : // setvelocity(self, {x=num, y=num, z=num})
738 0 : int ObjectRef::l_setvelocity(lua_State *L)
739 : {
740 0 : NO_MAP_LOCK_REQUIRED;
741 0 : ObjectRef *ref = checkobject(L, 1);
742 0 : LuaEntitySAO *co = getluaobject(ref);
743 0 : if(co == NULL) return 0;
744 0 : v3f pos = checkFloatPos(L, 2);
745 : // Do it
746 0 : co->setVelocity(pos);
747 0 : return 0;
748 : }
749 :
750 : // getvelocity(self)
751 0 : int ObjectRef::l_getvelocity(lua_State *L)
752 : {
753 0 : NO_MAP_LOCK_REQUIRED;
754 0 : ObjectRef *ref = checkobject(L, 1);
755 0 : LuaEntitySAO *co = getluaobject(ref);
756 0 : if(co == NULL) return 0;
757 : // Do it
758 0 : v3f v = co->getVelocity();
759 0 : pushFloatPos(L, v);
760 0 : return 1;
761 : }
762 :
763 : // setacceleration(self, {x=num, y=num, z=num})
764 0 : int ObjectRef::l_setacceleration(lua_State *L)
765 : {
766 0 : NO_MAP_LOCK_REQUIRED;
767 0 : ObjectRef *ref = checkobject(L, 1);
768 0 : LuaEntitySAO *co = getluaobject(ref);
769 0 : if(co == NULL) return 0;
770 : // pos
771 0 : v3f pos = checkFloatPos(L, 2);
772 : // Do it
773 0 : co->setAcceleration(pos);
774 0 : return 0;
775 : }
776 :
777 : // getacceleration(self)
778 0 : int ObjectRef::l_getacceleration(lua_State *L)
779 : {
780 0 : NO_MAP_LOCK_REQUIRED;
781 0 : ObjectRef *ref = checkobject(L, 1);
782 0 : LuaEntitySAO *co = getluaobject(ref);
783 0 : if(co == NULL) return 0;
784 : // Do it
785 0 : v3f v = co->getAcceleration();
786 0 : pushFloatPos(L, v);
787 0 : return 1;
788 : }
789 :
790 : // setyaw(self, radians)
791 0 : int ObjectRef::l_setyaw(lua_State *L)
792 : {
793 0 : NO_MAP_LOCK_REQUIRED;
794 0 : ObjectRef *ref = checkobject(L, 1);
795 0 : LuaEntitySAO *co = getluaobject(ref);
796 0 : if(co == NULL) return 0;
797 0 : float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
798 : // Do it
799 0 : co->setYaw(yaw);
800 0 : return 0;
801 : }
802 :
803 : // getyaw(self)
804 0 : int ObjectRef::l_getyaw(lua_State *L)
805 : {
806 0 : NO_MAP_LOCK_REQUIRED;
807 0 : ObjectRef *ref = checkobject(L, 1);
808 0 : LuaEntitySAO *co = getluaobject(ref);
809 0 : if(co == NULL) return 0;
810 : // Do it
811 0 : float yaw = co->getYaw() * core::DEGTORAD;
812 0 : lua_pushnumber(L, yaw);
813 0 : return 1;
814 : }
815 :
816 : // settexturemod(self, mod)
817 0 : int ObjectRef::l_settexturemod(lua_State *L)
818 : {
819 0 : NO_MAP_LOCK_REQUIRED;
820 0 : ObjectRef *ref = checkobject(L, 1);
821 0 : LuaEntitySAO *co = getluaobject(ref);
822 0 : if(co == NULL) return 0;
823 : // Do it
824 0 : std::string mod = luaL_checkstring(L, 2);
825 0 : co->setTextureMod(mod);
826 0 : return 0;
827 : }
828 :
829 : // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
830 : // select_horiz_by_yawpitch=false)
831 0 : int ObjectRef::l_setsprite(lua_State *L)
832 : {
833 0 : NO_MAP_LOCK_REQUIRED;
834 0 : ObjectRef *ref = checkobject(L, 1);
835 0 : LuaEntitySAO *co = getluaobject(ref);
836 0 : if(co == NULL) return 0;
837 : // Do it
838 0 : v2s16 p(0,0);
839 0 : if(!lua_isnil(L, 2))
840 0 : p = read_v2s16(L, 2);
841 0 : int num_frames = 1;
842 0 : if(!lua_isnil(L, 3))
843 0 : num_frames = lua_tonumber(L, 3);
844 0 : float framelength = 0.2;
845 0 : if(!lua_isnil(L, 4))
846 0 : framelength = lua_tonumber(L, 4);
847 0 : bool select_horiz_by_yawpitch = false;
848 0 : if(!lua_isnil(L, 5))
849 0 : select_horiz_by_yawpitch = lua_toboolean(L, 5);
850 0 : co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
851 0 : return 0;
852 : }
853 :
854 : // DEPRECATED
855 : // get_entity_name(self)
856 0 : int ObjectRef::l_get_entity_name(lua_State *L)
857 : {
858 0 : NO_MAP_LOCK_REQUIRED;
859 0 : ObjectRef *ref = checkobject(L, 1);
860 0 : LuaEntitySAO *co = getluaobject(ref);
861 0 : log_deprecated(L,"Deprecated call to \"get_entity_name");
862 0 : if(co == NULL) return 0;
863 : // Do it
864 0 : std::string name = co->getName();
865 0 : lua_pushstring(L, name.c_str());
866 0 : return 1;
867 : }
868 :
869 : // get_luaentity(self)
870 0 : int ObjectRef::l_get_luaentity(lua_State *L)
871 : {
872 0 : NO_MAP_LOCK_REQUIRED;
873 0 : ObjectRef *ref = checkobject(L, 1);
874 0 : LuaEntitySAO *co = getluaobject(ref);
875 0 : if(co == NULL) return 0;
876 : // Do it
877 0 : luaentity_get(L, co->getId());
878 0 : return 1;
879 : }
880 :
881 : /* Player-only */
882 :
883 : // is_player_connected(self)
884 0 : int ObjectRef::l_is_player_connected(lua_State *L)
885 : {
886 0 : NO_MAP_LOCK_REQUIRED;
887 0 : ObjectRef *ref = checkobject(L, 1);
888 0 : Player *player = getplayer(ref);
889 0 : lua_pushboolean(L, (player != NULL && player->peer_id != 0));
890 0 : return 1;
891 : }
892 :
893 : // get_player_name(self)
894 0 : int ObjectRef::l_get_player_name(lua_State *L)
895 : {
896 0 : NO_MAP_LOCK_REQUIRED;
897 0 : ObjectRef *ref = checkobject(L, 1);
898 0 : Player *player = getplayer(ref);
899 0 : if(player == NULL){
900 0 : lua_pushlstring(L, "", 0);
901 0 : return 1;
902 : }
903 : // Do it
904 0 : lua_pushstring(L, player->getName());
905 0 : return 1;
906 : }
907 :
908 : // get_look_dir(self)
909 0 : int ObjectRef::l_get_look_dir(lua_State *L)
910 : {
911 0 : NO_MAP_LOCK_REQUIRED;
912 0 : ObjectRef *ref = checkobject(L, 1);
913 0 : Player *player = getplayer(ref);
914 0 : if(player == NULL) return 0;
915 : // Do it
916 0 : float pitch = player->getRadPitch();
917 0 : float yaw = player->getRadYaw();
918 0 : v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw));
919 0 : push_v3f(L, v);
920 0 : return 1;
921 : }
922 :
923 : // get_look_pitch(self)
924 0 : int ObjectRef::l_get_look_pitch(lua_State *L)
925 : {
926 0 : NO_MAP_LOCK_REQUIRED;
927 0 : ObjectRef *ref = checkobject(L, 1);
928 0 : Player *player = getplayer(ref);
929 0 : if(player == NULL) return 0;
930 : // Do it
931 0 : lua_pushnumber(L, player->getRadPitch());
932 0 : return 1;
933 : }
934 :
935 : // get_look_yaw(self)
936 0 : int ObjectRef::l_get_look_yaw(lua_State *L)
937 : {
938 0 : NO_MAP_LOCK_REQUIRED;
939 0 : ObjectRef *ref = checkobject(L, 1);
940 0 : Player *player = getplayer(ref);
941 0 : if(player == NULL) return 0;
942 : // Do it
943 0 : lua_pushnumber(L, player->getRadYaw());
944 0 : return 1;
945 : }
946 :
947 : // set_look_pitch(self, radians)
948 0 : int ObjectRef::l_set_look_pitch(lua_State *L)
949 : {
950 0 : NO_MAP_LOCK_REQUIRED;
951 0 : ObjectRef *ref = checkobject(L, 1);
952 0 : PlayerSAO* co = getplayersao(ref);
953 0 : if(co == NULL) return 0;
954 0 : float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
955 : // Do it
956 0 : co->setPitch(pitch);
957 0 : return 1;
958 : }
959 :
960 : // set_look_yaw(self, radians)
961 0 : int ObjectRef::l_set_look_yaw(lua_State *L)
962 : {
963 0 : NO_MAP_LOCK_REQUIRED;
964 0 : ObjectRef *ref = checkobject(L, 1);
965 0 : PlayerSAO* co = getplayersao(ref);
966 0 : if(co == NULL) return 0;
967 0 : float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
968 : // Do it
969 0 : co->setYaw(yaw);
970 0 : return 1;
971 : }
972 :
973 : // set_breath(self, breath)
974 0 : int ObjectRef::l_set_breath(lua_State *L)
975 : {
976 0 : NO_MAP_LOCK_REQUIRED;
977 0 : ObjectRef *ref = checkobject(L, 1);
978 0 : PlayerSAO* co = getplayersao(ref);
979 0 : if(co == NULL) return 0;
980 0 : u16 breath = luaL_checknumber(L, 2);
981 : // Do it
982 0 : co->setBreath(breath);
983 :
984 : // If the object is a player sent the breath to client
985 0 : if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
986 0 : getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
987 :
988 0 : return 0;
989 : }
990 :
991 : // get_breath(self)
992 0 : int ObjectRef::l_get_breath(lua_State *L)
993 : {
994 0 : NO_MAP_LOCK_REQUIRED;
995 0 : ObjectRef *ref = checkobject(L, 1);
996 0 : PlayerSAO* co = getplayersao(ref);
997 0 : if(co == NULL) return 0;
998 : // Do it
999 0 : u16 breath = co->getBreath();
1000 0 : lua_pushinteger (L, breath);
1001 0 : return 1;
1002 : }
1003 :
1004 : // set_inventory_formspec(self, formspec)
1005 0 : int ObjectRef::l_set_inventory_formspec(lua_State *L)
1006 : {
1007 0 : NO_MAP_LOCK_REQUIRED;
1008 0 : ObjectRef *ref = checkobject(L, 1);
1009 0 : Player *player = getplayer(ref);
1010 0 : if(player == NULL) return 0;
1011 0 : std::string formspec = luaL_checkstring(L, 2);
1012 :
1013 0 : player->inventory_formspec = formspec;
1014 0 : getServer(L)->reportInventoryFormspecModified(player->getName());
1015 0 : lua_pushboolean(L, true);
1016 0 : return 1;
1017 : }
1018 :
1019 : // get_inventory_formspec(self) -> formspec
1020 0 : int ObjectRef::l_get_inventory_formspec(lua_State *L)
1021 : {
1022 0 : NO_MAP_LOCK_REQUIRED;
1023 0 : ObjectRef *ref = checkobject(L, 1);
1024 0 : Player *player = getplayer(ref);
1025 0 : if(player == NULL) return 0;
1026 :
1027 0 : std::string formspec = player->inventory_formspec;
1028 0 : lua_pushlstring(L, formspec.c_str(), formspec.size());
1029 0 : return 1;
1030 : }
1031 :
1032 : // get_player_control(self)
1033 0 : int ObjectRef::l_get_player_control(lua_State *L)
1034 : {
1035 0 : NO_MAP_LOCK_REQUIRED;
1036 0 : ObjectRef *ref = checkobject(L, 1);
1037 0 : Player *player = getplayer(ref);
1038 0 : if(player == NULL){
1039 0 : lua_pushlstring(L, "", 0);
1040 0 : return 1;
1041 : }
1042 : // Do it
1043 0 : PlayerControl control = player->getPlayerControl();
1044 0 : lua_newtable(L);
1045 0 : lua_pushboolean(L, control.up);
1046 0 : lua_setfield(L, -2, "up");
1047 0 : lua_pushboolean(L, control.down);
1048 0 : lua_setfield(L, -2, "down");
1049 0 : lua_pushboolean(L, control.left);
1050 0 : lua_setfield(L, -2, "left");
1051 0 : lua_pushboolean(L, control.right);
1052 0 : lua_setfield(L, -2, "right");
1053 0 : lua_pushboolean(L, control.jump);
1054 0 : lua_setfield(L, -2, "jump");
1055 0 : lua_pushboolean(L, control.aux1);
1056 0 : lua_setfield(L, -2, "aux1");
1057 0 : lua_pushboolean(L, control.sneak);
1058 0 : lua_setfield(L, -2, "sneak");
1059 0 : lua_pushboolean(L, control.LMB);
1060 0 : lua_setfield(L, -2, "LMB");
1061 0 : lua_pushboolean(L, control.RMB);
1062 0 : lua_setfield(L, -2, "RMB");
1063 0 : return 1;
1064 : }
1065 :
1066 : // get_player_control_bits(self)
1067 0 : int ObjectRef::l_get_player_control_bits(lua_State *L)
1068 : {
1069 0 : NO_MAP_LOCK_REQUIRED;
1070 0 : ObjectRef *ref = checkobject(L, 1);
1071 0 : Player *player = getplayer(ref);
1072 0 : if(player == NULL){
1073 0 : lua_pushlstring(L, "", 0);
1074 0 : return 1;
1075 : }
1076 : // Do it
1077 0 : lua_pushnumber(L, player->keyPressed);
1078 0 : return 1;
1079 : }
1080 :
1081 : // hud_add(self, form)
1082 0 : int ObjectRef::l_hud_add(lua_State *L)
1083 : {
1084 0 : ObjectRef *ref = checkobject(L, 1);
1085 0 : Player *player = getplayer(ref);
1086 0 : if (player == NULL)
1087 0 : return 0;
1088 :
1089 0 : HudElement *elem = new HudElement;
1090 :
1091 0 : elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
1092 0 : es_HudElementType, HUD_ELEM_TEXT);
1093 :
1094 0 : lua_getfield(L, 2, "position");
1095 0 : elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1096 0 : lua_pop(L, 1);
1097 :
1098 0 : lua_getfield(L, 2, "scale");
1099 0 : elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1100 0 : lua_pop(L, 1);
1101 :
1102 0 : lua_getfield(L, 2, "size");
1103 0 : elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
1104 0 : lua_pop(L, 1);
1105 :
1106 0 : elem->name = getstringfield_default(L, 2, "name", "");
1107 0 : elem->text = getstringfield_default(L, 2, "text", "");
1108 0 : elem->number = getintfield_default(L, 2, "number", 0);
1109 0 : elem->item = getintfield_default(L, 2, "item", 0);
1110 0 : elem->dir = getintfield_default(L, 2, "direction", 0);
1111 :
1112 : // Deprecated, only for compatibility's sake
1113 0 : if (elem->dir == 0)
1114 0 : elem->dir = getintfield_default(L, 2, "dir", 0);
1115 :
1116 0 : lua_getfield(L, 2, "alignment");
1117 0 : elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1118 0 : lua_pop(L, 1);
1119 :
1120 0 : lua_getfield(L, 2, "offset");
1121 0 : elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
1122 0 : lua_pop(L, 1);
1123 :
1124 0 : lua_getfield(L, 2, "world_pos");
1125 0 : elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
1126 0 : lua_pop(L, 1);
1127 :
1128 : /* check for known deprecated element usage */
1129 0 : if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32())) {
1130 0 : log_deprecated(L,"Deprecated usage of statbar without size!");
1131 : }
1132 :
1133 0 : u32 id = getServer(L)->hudAdd(player, elem);
1134 0 : if (id == (u32)-1) {
1135 0 : delete elem;
1136 0 : return 0;
1137 : }
1138 :
1139 0 : lua_pushnumber(L, id);
1140 0 : return 1;
1141 : }
1142 :
1143 : // hud_remove(self, id)
1144 0 : int ObjectRef::l_hud_remove(lua_State *L)
1145 : {
1146 0 : ObjectRef *ref = checkobject(L, 1);
1147 0 : Player *player = getplayer(ref);
1148 0 : if (player == NULL)
1149 0 : return 0;
1150 :
1151 0 : u32 id = -1;
1152 0 : if (!lua_isnil(L, 2))
1153 0 : id = lua_tonumber(L, 2);
1154 :
1155 0 : if (!getServer(L)->hudRemove(player, id))
1156 0 : return 0;
1157 :
1158 0 : lua_pushboolean(L, true);
1159 0 : return 1;
1160 : }
1161 :
1162 : // hud_change(self, id, stat, data)
1163 0 : int ObjectRef::l_hud_change(lua_State *L)
1164 : {
1165 0 : ObjectRef *ref = checkobject(L, 1);
1166 0 : Player *player = getplayer(ref);
1167 0 : if (player == NULL)
1168 0 : return 0;
1169 :
1170 0 : u32 id = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : -1;
1171 :
1172 0 : HudElement *e = player->getHud(id);
1173 0 : if (!e)
1174 0 : return 0;
1175 :
1176 0 : HudElementStat stat = HUD_STAT_NUMBER;
1177 0 : if (lua_isstring(L, 3)) {
1178 : int statint;
1179 0 : std::string statstr = lua_tostring(L, 3);
1180 0 : stat = string_to_enum(es_HudElementStat, statint, statstr) ?
1181 0 : (HudElementStat)statint : HUD_STAT_NUMBER;
1182 : }
1183 :
1184 0 : void *value = NULL;
1185 0 : switch (stat) {
1186 : case HUD_STAT_POS:
1187 0 : e->pos = read_v2f(L, 4);
1188 0 : value = &e->pos;
1189 0 : break;
1190 : case HUD_STAT_NAME:
1191 0 : e->name = luaL_checkstring(L, 4);
1192 0 : value = &e->name;
1193 0 : break;
1194 : case HUD_STAT_SCALE:
1195 0 : e->scale = read_v2f(L, 4);
1196 0 : value = &e->scale;
1197 0 : break;
1198 : case HUD_STAT_TEXT:
1199 0 : e->text = luaL_checkstring(L, 4);
1200 0 : value = &e->text;
1201 0 : break;
1202 : case HUD_STAT_NUMBER:
1203 0 : e->number = luaL_checknumber(L, 4);
1204 0 : value = &e->number;
1205 0 : break;
1206 : case HUD_STAT_ITEM:
1207 0 : e->item = luaL_checknumber(L, 4);
1208 0 : value = &e->item;
1209 0 : break;
1210 : case HUD_STAT_DIR:
1211 0 : e->dir = luaL_checknumber(L, 4);
1212 0 : value = &e->dir;
1213 0 : break;
1214 : case HUD_STAT_ALIGN:
1215 0 : e->align = read_v2f(L, 4);
1216 0 : value = &e->align;
1217 0 : break;
1218 : case HUD_STAT_OFFSET:
1219 0 : e->offset = read_v2f(L, 4);
1220 0 : value = &e->offset;
1221 0 : break;
1222 : case HUD_STAT_WORLD_POS:
1223 0 : e->world_pos = read_v3f(L, 4);
1224 0 : value = &e->world_pos;
1225 0 : break;
1226 : case HUD_STAT_SIZE:
1227 0 : e->size = read_v2s32(L, 4);
1228 0 : value = &e->size;
1229 0 : break;
1230 : }
1231 :
1232 0 : getServer(L)->hudChange(player, id, stat, value);
1233 :
1234 0 : lua_pushboolean(L, true);
1235 0 : return 1;
1236 : }
1237 :
1238 : // hud_get(self, id)
1239 0 : int ObjectRef::l_hud_get(lua_State *L)
1240 : {
1241 0 : ObjectRef *ref = checkobject(L, 1);
1242 0 : Player *player = getplayer(ref);
1243 0 : if (player == NULL)
1244 0 : return 0;
1245 :
1246 0 : u32 id = lua_tonumber(L, -1);
1247 :
1248 0 : HudElement *e = player->getHud(id);
1249 0 : if (!e)
1250 0 : return 0;
1251 :
1252 0 : lua_newtable(L);
1253 :
1254 0 : lua_pushstring(L, es_HudElementType[(u8)e->type].str);
1255 0 : lua_setfield(L, -2, "type");
1256 :
1257 0 : push_v2f(L, e->pos);
1258 0 : lua_setfield(L, -2, "position");
1259 :
1260 0 : lua_pushstring(L, e->name.c_str());
1261 0 : lua_setfield(L, -2, "name");
1262 :
1263 0 : push_v2f(L, e->scale);
1264 0 : lua_setfield(L, -2, "scale");
1265 :
1266 0 : lua_pushstring(L, e->text.c_str());
1267 0 : lua_setfield(L, -2, "text");
1268 :
1269 0 : lua_pushnumber(L, e->number);
1270 0 : lua_setfield(L, -2, "number");
1271 :
1272 0 : lua_pushnumber(L, e->item);
1273 0 : lua_setfield(L, -2, "item");
1274 :
1275 0 : lua_pushnumber(L, e->dir);
1276 0 : lua_setfield(L, -2, "direction");
1277 :
1278 : // Deprecated, only for compatibility's sake
1279 0 : lua_pushnumber(L, e->dir);
1280 0 : lua_setfield(L, -2, "dir");
1281 :
1282 0 : push_v3f(L, e->world_pos);
1283 0 : lua_setfield(L, -2, "world_pos");
1284 :
1285 0 : return 1;
1286 : }
1287 :
1288 : // hud_set_flags(self, flags)
1289 0 : int ObjectRef::l_hud_set_flags(lua_State *L)
1290 : {
1291 0 : ObjectRef *ref = checkobject(L, 1);
1292 0 : Player *player = getplayer(ref);
1293 0 : if (player == NULL)
1294 0 : return 0;
1295 :
1296 0 : u32 flags = 0;
1297 0 : u32 mask = 0;
1298 : bool flag;
1299 :
1300 0 : const EnumString *esp = es_HudBuiltinElement;
1301 0 : for (int i = 0; esp[i].str; i++) {
1302 0 : if (getboolfield(L, 2, esp[i].str, flag)) {
1303 0 : flags |= esp[i].num * flag;
1304 0 : mask |= esp[i].num;
1305 : }
1306 : }
1307 0 : if (!getServer(L)->hudSetFlags(player, flags, mask))
1308 0 : return 0;
1309 :
1310 0 : lua_pushboolean(L, true);
1311 0 : return 1;
1312 : }
1313 :
1314 0 : int ObjectRef::l_hud_get_flags(lua_State *L)
1315 : {
1316 0 : ObjectRef *ref = checkobject(L, 1);
1317 0 : Player *player = getplayer(ref);
1318 0 : if (player == NULL)
1319 0 : return 0;
1320 :
1321 0 : lua_newtable(L);
1322 0 : lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE);
1323 0 : lua_setfield(L, -2, "hotbar");
1324 0 : lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE);
1325 0 : lua_setfield(L, -2, "healthbar");
1326 0 : lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE);
1327 0 : lua_setfield(L, -2, "crosshair");
1328 0 : lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE);
1329 0 : lua_setfield(L, -2, "wielditem");
1330 0 : lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
1331 0 : lua_setfield(L, -2, "breathbar");
1332 :
1333 0 : return 1;
1334 : }
1335 :
1336 : // hud_set_hotbar_itemcount(self, hotbar_itemcount)
1337 0 : int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
1338 : {
1339 0 : ObjectRef *ref = checkobject(L, 1);
1340 0 : Player *player = getplayer(ref);
1341 0 : if (player == NULL)
1342 0 : return 0;
1343 :
1344 0 : s32 hotbar_itemcount = lua_tonumber(L, 2);
1345 :
1346 0 : if (!getServer(L)->hudSetHotbarItemcount(player, hotbar_itemcount))
1347 0 : return 0;
1348 :
1349 0 : lua_pushboolean(L, true);
1350 0 : return 1;
1351 : }
1352 :
1353 : // hud_get_hotbar_itemcount(self)
1354 0 : int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
1355 : {
1356 0 : ObjectRef *ref = checkobject(L, 1);
1357 0 : Player *player = getplayer(ref);
1358 0 : if (player == NULL)
1359 0 : return 0;
1360 :
1361 0 : s32 hotbar_itemcount = getServer(L)->hudGetHotbarItemcount(player);
1362 :
1363 0 : lua_pushnumber(L, hotbar_itemcount);
1364 0 : return 1;
1365 : }
1366 :
1367 : // hud_set_hotbar_image(self, name)
1368 0 : int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
1369 : {
1370 0 : ObjectRef *ref = checkobject(L, 1);
1371 0 : Player *player = getplayer(ref);
1372 0 : if (player == NULL)
1373 0 : return 0;
1374 :
1375 0 : std::string name = lua_tostring(L, 2);
1376 :
1377 0 : getServer(L)->hudSetHotbarImage(player, name);
1378 0 : return 1;
1379 : }
1380 :
1381 : // hud_get_hotbar_image(self)
1382 0 : int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
1383 : {
1384 0 : ObjectRef *ref = checkobject(L, 1);
1385 0 : Player *player = getplayer(ref);
1386 0 : if (player == NULL)
1387 0 : return 0;
1388 :
1389 0 : std::string name = getServer(L)->hudGetHotbarImage(player);
1390 0 : lua_pushlstring(L, name.c_str(), name.size());
1391 0 : return 1;
1392 : }
1393 :
1394 : // hud_set_hotbar_selected_image(self, name)
1395 0 : int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
1396 : {
1397 0 : ObjectRef *ref = checkobject(L, 1);
1398 0 : Player *player = getplayer(ref);
1399 0 : if (player == NULL)
1400 0 : return 0;
1401 :
1402 0 : std::string name = lua_tostring(L, 2);
1403 :
1404 0 : getServer(L)->hudSetHotbarSelectedImage(player, name);
1405 0 : return 1;
1406 : }
1407 :
1408 : // hud_get_hotbar_selected_image(self)
1409 0 : int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
1410 : {
1411 0 : ObjectRef *ref = checkobject(L, 1);
1412 0 : Player *player = getplayer(ref);
1413 0 : if (player == NULL)
1414 0 : return 0;
1415 :
1416 0 : std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
1417 0 : lua_pushlstring(L, name.c_str(), name.size());
1418 0 : return 1;
1419 : }
1420 :
1421 : // set_sky(self, bgcolor, type, list)
1422 0 : int ObjectRef::l_set_sky(lua_State *L)
1423 : {
1424 0 : ObjectRef *ref = checkobject(L, 1);
1425 0 : Player *player = getplayer(ref);
1426 0 : if (player == NULL)
1427 0 : return 0;
1428 :
1429 0 : video::SColor bgcolor(255,255,255,255);
1430 0 : read_color(L, 2, &bgcolor);
1431 :
1432 0 : std::string type = luaL_checkstring(L, 3);
1433 :
1434 0 : std::vector<std::string> params;
1435 0 : if (lua_istable(L, 4)) {
1436 0 : int table = lua_gettop(L);
1437 0 : lua_pushnil(L);
1438 0 : while (lua_next(L, table) != 0) {
1439 : // key at index -2 and value at index -1
1440 0 : if (lua_isstring(L, -1))
1441 0 : params.push_back(lua_tostring(L, -1));
1442 : else
1443 0 : params.push_back("");
1444 : // removes value, keeps key for next iteration
1445 0 : lua_pop(L, 1);
1446 : }
1447 : }
1448 :
1449 0 : if (type == "skybox" && params.size() != 6)
1450 0 : throw LuaError("skybox expects 6 textures");
1451 :
1452 0 : if (!getServer(L)->setSky(player, bgcolor, type, params))
1453 0 : return 0;
1454 :
1455 0 : lua_pushboolean(L, true);
1456 0 : return 1;
1457 : }
1458 :
1459 : // get_sky(self)
1460 0 : int ObjectRef::l_get_sky(lua_State *L)
1461 : {
1462 0 : ObjectRef *ref = checkobject(L, 1);
1463 0 : Player *player = getplayer(ref);
1464 0 : if (player == NULL)
1465 0 : return 0;
1466 0 : video::SColor bgcolor(255, 255, 255, 255);
1467 0 : std::string type;
1468 0 : std::vector<std::string> params;
1469 :
1470 0 : player->getSky(&bgcolor, &type, ¶ms);
1471 0 : type = type == "" ? "regular" : type;
1472 :
1473 0 : push_ARGB8(L, bgcolor);
1474 0 : lua_pushlstring(L, type.c_str(), type.size());
1475 0 : lua_newtable(L);
1476 0 : s16 i = 1;
1477 0 : for (std::vector<std::string>::iterator it = params.begin();
1478 0 : it != params.end(); ++it) {
1479 0 : lua_pushlstring(L, it->c_str(), it->size());
1480 0 : lua_rawseti(L, -2, i);
1481 0 : i++;
1482 : }
1483 0 : return 3;
1484 : }
1485 :
1486 : // override_day_night_ratio(self, brightness=0...1)
1487 0 : int ObjectRef::l_override_day_night_ratio(lua_State *L)
1488 : {
1489 0 : ObjectRef *ref = checkobject(L, 1);
1490 0 : Player *player = getplayer(ref);
1491 0 : if (player == NULL)
1492 0 : return 0;
1493 :
1494 0 : bool do_override = false;
1495 0 : float ratio = 0.0f;
1496 0 : if (!lua_isnil(L, 2)){
1497 0 : do_override = true;
1498 0 : ratio = luaL_checknumber(L, 2);
1499 : }
1500 :
1501 0 : if (!getServer(L)->overrideDayNightRatio(player, do_override, ratio))
1502 0 : return 0;
1503 :
1504 0 : lua_pushboolean(L, true);
1505 0 : return 1;
1506 : }
1507 :
1508 : // get_day_night_ratio(self)
1509 0 : int ObjectRef::l_get_day_night_ratio(lua_State *L)
1510 : {
1511 0 : ObjectRef *ref = checkobject(L, 1);
1512 0 : Player *player = getplayer(ref);
1513 0 : if (player == NULL)
1514 0 : return 0;
1515 :
1516 : bool do_override;
1517 : float ratio;
1518 0 : player->getDayNightRatio(&do_override, &ratio);
1519 :
1520 0 : if (do_override)
1521 0 : lua_pushnumber(L, ratio);
1522 : else
1523 0 : lua_pushnil(L);
1524 :
1525 0 : return 1;
1526 : }
1527 :
1528 : // set_nametag_attributes(self, attributes)
1529 0 : int ObjectRef::l_set_nametag_attributes(lua_State *L)
1530 : {
1531 0 : NO_MAP_LOCK_REQUIRED;
1532 0 : ObjectRef *ref = checkobject(L, 1);
1533 0 : PlayerSAO *playersao = getplayersao(ref);
1534 0 : if (playersao == NULL)
1535 0 : return 0;
1536 :
1537 0 : lua_getfield(L, 2, "color");
1538 0 : if (!lua_isnil(L, -1)) {
1539 0 : video::SColor color = playersao->getNametagColor();
1540 0 : if (!read_color(L, -1, &color))
1541 0 : return 0;
1542 0 : playersao->setNametagColor(color);
1543 : }
1544 :
1545 0 : lua_pushboolean(L, true);
1546 0 : return 1;
1547 : }
1548 :
1549 : // get_nametag_attributes(self)
1550 0 : int ObjectRef::l_get_nametag_attributes(lua_State *L)
1551 : {
1552 0 : NO_MAP_LOCK_REQUIRED;
1553 0 : ObjectRef *ref = checkobject(L, 1);
1554 0 : PlayerSAO *playersao = getplayersao(ref);
1555 0 : if (playersao == NULL)
1556 0 : return 0;
1557 :
1558 0 : video::SColor color = playersao->getNametagColor();
1559 :
1560 0 : lua_newtable(L);
1561 0 : push_ARGB8(L, color);
1562 0 : lua_setfield(L, -2, "color");
1563 :
1564 0 : return 1;
1565 : }
1566 :
1567 0 : ObjectRef::ObjectRef(ServerActiveObject *object):
1568 0 : m_object(object)
1569 : {
1570 : //infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
1571 0 : }
1572 :
1573 0 : ObjectRef::~ObjectRef()
1574 : {
1575 : /*if(m_object)
1576 : infostream<<"ObjectRef destructing for id="
1577 : <<m_object->getId()<<std::endl;
1578 : else
1579 : infostream<<"ObjectRef destructing for id=unknown"<<std::endl;*/
1580 0 : }
1581 :
1582 : // Creates an ObjectRef and leaves it on top of stack
1583 : // Not callable from Lua; all references are created on the C side.
1584 0 : void ObjectRef::create(lua_State *L, ServerActiveObject *object)
1585 : {
1586 0 : ObjectRef *o = new ObjectRef(object);
1587 : //infostream<<"ObjectRef::create: o="<<o<<std::endl;
1588 0 : *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
1589 0 : luaL_getmetatable(L, className);
1590 0 : lua_setmetatable(L, -2);
1591 0 : }
1592 :
1593 0 : void ObjectRef::set_null(lua_State *L)
1594 : {
1595 0 : ObjectRef *o = checkobject(L, -1);
1596 0 : o->m_object = NULL;
1597 0 : }
1598 :
1599 0 : void ObjectRef::Register(lua_State *L)
1600 : {
1601 0 : lua_newtable(L);
1602 0 : int methodtable = lua_gettop(L);
1603 0 : luaL_newmetatable(L, className);
1604 0 : int metatable = lua_gettop(L);
1605 :
1606 0 : lua_pushliteral(L, "__metatable");
1607 0 : lua_pushvalue(L, methodtable);
1608 0 : lua_settable(L, metatable); // hide metatable from Lua getmetatable()
1609 :
1610 0 : lua_pushliteral(L, "__index");
1611 0 : lua_pushvalue(L, methodtable);
1612 0 : lua_settable(L, metatable);
1613 :
1614 0 : lua_pushliteral(L, "__gc");
1615 0 : lua_pushcfunction(L, gc_object);
1616 0 : lua_settable(L, metatable);
1617 :
1618 0 : lua_pop(L, 1); // drop metatable
1619 :
1620 0 : luaL_openlib(L, 0, methods, 0); // fill methodtable
1621 0 : lua_pop(L, 1); // drop methodtable
1622 :
1623 : // Cannot be created from Lua
1624 : //lua_register(L, className, create_object);
1625 0 : }
1626 :
1627 : const char ObjectRef::className[] = "ObjectRef";
1628 : const luaL_reg ObjectRef::methods[] = {
1629 : // ServerActiveObject
1630 : luamethod(ObjectRef, remove),
1631 : luamethod(ObjectRef, getpos),
1632 : luamethod(ObjectRef, setpos),
1633 : luamethod(ObjectRef, moveto),
1634 : luamethod(ObjectRef, punch),
1635 : luamethod(ObjectRef, right_click),
1636 : luamethod(ObjectRef, set_hp),
1637 : luamethod(ObjectRef, get_hp),
1638 : luamethod(ObjectRef, get_inventory),
1639 : luamethod(ObjectRef, get_wield_list),
1640 : luamethod(ObjectRef, get_wield_index),
1641 : luamethod(ObjectRef, get_wielded_item),
1642 : luamethod(ObjectRef, set_wielded_item),
1643 : luamethod(ObjectRef, set_armor_groups),
1644 : luamethod(ObjectRef, get_armor_groups),
1645 : luamethod(ObjectRef, set_animation),
1646 : luamethod(ObjectRef, get_animation),
1647 : luamethod(ObjectRef, set_bone_position),
1648 : luamethod(ObjectRef, get_bone_position),
1649 : luamethod(ObjectRef, set_attach),
1650 : luamethod(ObjectRef, get_attach),
1651 : luamethod(ObjectRef, set_detach),
1652 : luamethod(ObjectRef, set_properties),
1653 : luamethod(ObjectRef, get_properties),
1654 : // LuaEntitySAO-only
1655 : luamethod(ObjectRef, setvelocity),
1656 : luamethod(ObjectRef, getvelocity),
1657 : luamethod(ObjectRef, setacceleration),
1658 : luamethod(ObjectRef, getacceleration),
1659 : luamethod(ObjectRef, setyaw),
1660 : luamethod(ObjectRef, getyaw),
1661 : luamethod(ObjectRef, settexturemod),
1662 : luamethod(ObjectRef, setsprite),
1663 : luamethod(ObjectRef, get_entity_name),
1664 : luamethod(ObjectRef, get_luaentity),
1665 : // Player-only
1666 : luamethod(ObjectRef, is_player),
1667 : luamethod(ObjectRef, is_player_connected),
1668 : luamethod(ObjectRef, get_player_name),
1669 : luamethod(ObjectRef, get_look_dir),
1670 : luamethod(ObjectRef, get_look_pitch),
1671 : luamethod(ObjectRef, get_look_yaw),
1672 : luamethod(ObjectRef, set_look_yaw),
1673 : luamethod(ObjectRef, set_look_pitch),
1674 : luamethod(ObjectRef, get_breath),
1675 : luamethod(ObjectRef, set_breath),
1676 : luamethod(ObjectRef, set_inventory_formspec),
1677 : luamethod(ObjectRef, get_inventory_formspec),
1678 : luamethod(ObjectRef, get_player_control),
1679 : luamethod(ObjectRef, get_player_control_bits),
1680 : luamethod(ObjectRef, set_physics_override),
1681 : luamethod(ObjectRef, get_physics_override),
1682 : luamethod(ObjectRef, hud_add),
1683 : luamethod(ObjectRef, hud_remove),
1684 : luamethod(ObjectRef, hud_change),
1685 : luamethod(ObjectRef, hud_get),
1686 : luamethod(ObjectRef, hud_set_flags),
1687 : luamethod(ObjectRef, hud_get_flags),
1688 : luamethod(ObjectRef, hud_set_hotbar_itemcount),
1689 : luamethod(ObjectRef, hud_get_hotbar_itemcount),
1690 : luamethod(ObjectRef, hud_set_hotbar_image),
1691 : luamethod(ObjectRef, hud_get_hotbar_image),
1692 : luamethod(ObjectRef, hud_set_hotbar_selected_image),
1693 : luamethod(ObjectRef, hud_get_hotbar_selected_image),
1694 : luamethod(ObjectRef, set_sky),
1695 : luamethod(ObjectRef, get_sky),
1696 : luamethod(ObjectRef, override_day_night_ratio),
1697 : luamethod(ObjectRef, get_day_night_ratio),
1698 : luamethod(ObjectRef, set_local_animation),
1699 : luamethod(ObjectRef, get_local_animation),
1700 : luamethod(ObjectRef, set_eye_offset),
1701 : luamethod(ObjectRef, get_eye_offset),
1702 : luamethod(ObjectRef, set_nametag_attributes),
1703 : luamethod(ObjectRef, get_nametag_attributes),
1704 : {0,0}
1705 3 : };
|