3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU 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.
20 #include "serverobject.h"
22 #include "environment.h"
24 ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos):
33 ServerActiveObject::~ServerActiveObject()
41 TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
42 ServerActiveObject(env, id, pos),
48 void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
57 m_base_position.Y += dtime * BS * 2;
58 if(m_base_position.Y > 8*BS)
59 m_base_position.Y = 2*BS;
65 //dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
69 data += itos(0); // 0 = position
71 data += itos(m_base_position.X);
73 data += itos(m_base_position.Y);
75 data += itos(m_base_position.Z);
77 ActiveObjectMessage aom(getId(), false, data);
78 messages.push_back(aom);
94 on_get_client_init_data(self)
95 on_get_server_init_data(self)
96 on_initialize(self, data)
102 static int lf_object_remove(lua_State *L)
105 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
110 self->m_removed = true;
116 ServerEnvironment object_get_environment(self)
118 static int lf_object_get_environment(lua_State *L)
121 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
126 lua_pushlightuserdata(L, self->getEnv());
131 object_set_base_position(self, {X=,Y=,Z=})
133 static int lf_object_set_base_position(lua_State *L)
136 assert(lua_istable(L, -1));
137 lua_pushstring(L, "X");
139 lua_Number x = lua_tonumber(L, -1);
141 lua_pushstring(L, "Y");
143 lua_Number y = lua_tonumber(L, -1);
145 lua_pushstring(L, "Z");
147 lua_Number z = lua_tonumber(L, -1);
151 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
156 self->setBasePosition(v3f(x*BS,y*BS,z*BS));
158 return 0; // Number of return values
162 {X=,Y=,Z=} object_get_base_position(self)
164 static int lf_object_get_base_position(lua_State *L)
167 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
172 v3f pos = self->getBasePosition();
176 lua_pushstring(L, "X");
177 lua_pushnumber(L, pos.X/BS);
180 lua_pushstring(L, "Y");
181 lua_pushnumber(L, pos.Y/BS);
184 lua_pushstring(L, "Z");
185 lua_pushnumber(L, pos.Z/BS);
188 return 1; // Number of return values
192 object_add_message(self, string data)
195 static int lf_object_add_message(lua_State *L)
199 const char *data_c = lua_tolstring(L, -1, &datalen);
202 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
208 std::string data(data_c, datalen);
209 //dstream<<"object_add_message: data="<<data<<std::endl;
211 // Create message and add to queue
212 ActiveObjectMessage aom(self->getId());
214 aom.datastring = data;
215 self->m_message_queue.push_back(aom);
217 return 0; // Number of return values
221 env_get_node(env, {X=,Y=,Z=})
223 static int lf_env_get_node(lua_State *L)
226 assert(lua_istable(L, -1));
227 lua_pushstring(L, "X");
229 lua_Number x = lua_tonumber(L, -1);
231 lua_pushstring(L, "Y");
233 lua_Number y = lua_tonumber(L, -1);
235 lua_pushstring(L, "Z");
237 lua_Number z = lua_tonumber(L, -1);
241 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
246 v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
248 /*dstream<<"Checking node from pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z
252 MapNode n(CONTENT_IGNORE);
253 n = env->getMap().getNodeNoEx(pos);
255 // Create a table with some data about the node
257 lua_pushstring(L, "content");
258 lua_pushinteger(L, n.d);
260 lua_pushstring(L, "param1");
261 lua_pushinteger(L, n.param);
263 lua_pushstring(L, "param2");
264 lua_pushinteger(L, n.param2);
272 get_content_features(content)
274 static int lf_get_content_features(lua_State *L)
279 n.d = lua_tointeger(L, -1);
282 // Get and return information
283 ContentFeatures &f = content_features(n.d);
286 lua_pushstring(L, "walkable");
287 lua_pushboolean(L, f.walkable);
289 lua_pushstring(L, "diggable");
290 lua_pushboolean(L, f.diggable);
292 lua_pushstring(L, "buildable_to");
293 lua_pushboolean(L, f.buildable_to);
300 bool env_dig_node(env, {X=,Y=,Z=})
301 Return true on success
303 static int lf_env_dig_node(lua_State *L)
306 assert(lua_istable(L, -1));
307 lua_pushstring(L, "X");
309 lua_Number x = lua_tonumber(L, -1);
311 lua_pushstring(L, "Y");
313 lua_Number y = lua_tonumber(L, -1);
315 lua_pushstring(L, "Z");
317 lua_Number z = lua_tonumber(L, -1);
321 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
325 v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
329 This gets sent to the server by the map through the edit
332 bool succeeded = env->getMap().removeNodeWithEvent(pos);
334 lua_pushboolean(L, succeeded);
339 bool env_place_node(env, {X=,Y=,Z=}, node)
340 node={content=,param1=,param2=}
341 param1 and param2 are optional
342 Return true on success
344 static int lf_env_place_node(lua_State *L)
347 MapNode n(CONTENT_STONE);
348 assert(lua_istable(L, -1));
350 lua_pushstring(L, "content");
352 if(lua_isnumber(L, -1))
353 n.d = lua_tonumber(L, -1);
355 lua_pushstring(L, "param1");
357 if(lua_isnumber(L, -1))
358 n.param = lua_tonumber(L, -1);
360 lua_pushstring(L, "param2");
362 if(lua_isnumber(L, -1))
363 n.param2 = lua_tonumber(L, -1);
368 assert(lua_istable(L, -1));
369 lua_pushstring(L, "X");
371 lua_Number x = lua_tonumber(L, -1);
373 lua_pushstring(L, "Y");
375 lua_Number y = lua_tonumber(L, -1);
377 lua_pushstring(L, "Z");
379 lua_Number z = lua_tonumber(L, -1);
383 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
387 v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
391 This gets sent to the server by the map through the edit
394 bool succeeded = env->getMap().addNodeWithEvent(pos, n);
396 lua_pushboolean(L, succeeded);
401 string env_get_nearest_player_name(env, {X=,Y=,Z=})
403 static int lf_env_get_nearest_player_name(lua_State *L)
406 assert(lua_istable(L, -1));
407 lua_pushstring(L, "X");
409 lua_Number x = lua_tonumber(L, -1);
411 lua_pushstring(L, "Y");
413 lua_Number y = lua_tonumber(L, -1);
415 lua_pushstring(L, "Z");
417 lua_Number z = lua_tonumber(L, -1);
421 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
425 v3f pos_f = v3f(x,y,z)*BS;
427 Player *player = env->getNearestConnectedPlayer(pos_f);
430 lua_pushstring(L, player->getName());
432 lua_pushstring(L, "");
434 return 1; // Number of return values
438 {exists=, pos={X=,Y=,Z=}, connected=} env_get_player_info(env, name)
440 static int lf_env_get_player_info(lua_State *L)
443 const char *name = lua_tostring(L, -1);
446 ServerEnvironment *env = (ServerEnvironment*)lua_touserdata(L, -1);
450 Player *player = env->getPlayer(name);
453 pos = player->getPosition();
457 lua_pushstring(L, "exists");
458 lua_pushboolean(L, (player != NULL));
463 lua_pushstring(L, "pos");
467 lua_pushstring(L, "X");
468 lua_pushnumber(L, pos.X/BS);
471 lua_pushstring(L, "Y");
472 lua_pushnumber(L, pos.Y/BS);
475 lua_pushstring(L, "Z");
476 lua_pushnumber(L, pos.Z/BS);
481 lua_pushstring(L, "connected");
482 lua_pushboolean(L, (player->peer_id != 0));
486 return 1; // Number of return values
489 LuaSAO::LuaSAO(ServerEnvironment *env, u16 id, v3f pos):
490 ServerActiveObject(env, id, pos),
493 dstream<<"LuaSAO::LuaSAO(): id="<<id<<std::endl;
504 //lua_pushlightuserdata(L, this);
505 //lua_setglobal(L, "self");
507 // Register functions
508 #define LUA_REGISTER_FUNC(L, x) lua_register(L, #x, lf_ ## x)
509 LUA_REGISTER_FUNC(L, object_remove);
510 LUA_REGISTER_FUNC(L, object_get_environment);
511 LUA_REGISTER_FUNC(L, object_set_base_position);
512 LUA_REGISTER_FUNC(L, object_get_base_position);
513 LUA_REGISTER_FUNC(L, object_add_message);
514 LUA_REGISTER_FUNC(L, env_get_node);
515 LUA_REGISTER_FUNC(L, get_content_features);
516 LUA_REGISTER_FUNC(L, env_dig_node);
517 LUA_REGISTER_FUNC(L, env_place_node);
518 LUA_REGISTER_FUNC(L, env_get_nearest_player_name);
519 LUA_REGISTER_FUNC(L, env_get_player_info);
527 std::string LuaSAO::getClientInitializationData()
530 Read client-side script from file
533 std::string relative_path;
534 relative_path += "scripts/objects/";
535 relative_path += m_script_name;
536 relative_path += "/client.lua";
537 std::string full_path = porting::getDataPath(relative_path.c_str());
539 std::ifstream file(full_path.c_str(), std::ios::binary | std::ios::ate);
540 int size = file.tellg();
541 SharedBuffer<char> buf(size);
542 file.seekg(0, std::ios::beg);
543 file.read(&buf[0], size);
552 std::string script_string(&buf[0], buf.getSize());
553 data += serializeLongString(script_string);
556 Get data from server-side script for inclusion
558 std::string other_data;
562 const char *funcname = "on_get_client_init_data";
563 lua_getglobal(L, funcname);
564 if(!lua_isfunction(L,-1))
567 dstream<<"WARNING: LuaSAO: Function not found: "
568 <<funcname<<std::endl;
574 lua_pushlightuserdata(L, this);
576 // Call (1 parameters, 1 result)
577 if(lua_pcall(L, 1, 1, 0))
579 dstream<<"WARNING: LuaSAO: Error running function "
581 <<lua_tostring(L,-1)<<std::endl;
586 if(!lua_isstring(L,-1))
588 dstream<<"WARNING: LuaSAO: Function "<<funcname
589 <<" didn't return a string"<<std::endl;
594 const char *cs = lua_tolstring(L, -1, &cs_len);
597 other_data = std::string(cs, cs_len);
601 data += serializeLongString(other_data);
606 std::string LuaSAO::getServerInitializationData()
611 data.append(serializeString(m_script_name));
614 Get data from server-side script for inclusion
616 std::string other_data;
620 const char *funcname = "on_get_server_init_data";
621 lua_getglobal(L, funcname);
622 if(!lua_isfunction(L,-1))
625 dstream<<"WARNING: LuaSAO: Function not found: "
626 <<funcname<<std::endl;
632 lua_pushlightuserdata(L, this);
634 // Call (1 parameters, 1 result)
635 if(lua_pcall(L, 1, 1, 0))
637 dstream<<"WARNING: LuaSAO: Error running function "
639 <<lua_tostring(L,-1)<<std::endl;
644 if(!lua_isstring(L,-1))
646 dstream<<"WARNING: LuaSAO: Function "<<funcname
647 <<" didn't return a string"<<std::endl;
652 const char *cs = lua_tolstring(L, -1, &cs_len);
655 other_data = std::string(cs, cs_len);
659 data += serializeLongString(other_data);
664 void LuaSAO::initializeFromNothing(const std::string &script_name)
666 loadScripts(script_name);
669 Call on_initialize(self, data) in the script
672 const char *funcname = "on_initialize";
673 lua_getglobal(L, funcname);
674 if(!lua_isfunction(L,-1))
677 dstream<<"WARNING: LuaSAO: Function not found: "
678 <<funcname<<std::endl;
684 lua_pushlightuserdata(L, this);
686 lua_pushstring(L, "");
688 // Call (2 parameters, 0 result)
689 if(lua_pcall(L, 2, 0, 0))
691 dstream<<"WARNING: LuaSAO: Error running function "
693 <<lua_tostring(L,-1)<<std::endl;
698 void LuaSAO::initializeFromSave(const std::string &data)
700 std::istringstream is(data, std::ios::binary);
701 std::string script_name = deSerializeString(is);
702 std::string other = deSerializeLongString(is);
704 loadScripts(script_name);
707 Call on_initialize(self, data) in the script
710 const char *funcname = "on_initialize";
711 lua_getglobal(L, funcname);
712 if(!lua_isfunction(L,-1))
715 dstream<<"WARNING: LuaSAO: Function not found: "
716 <<funcname<<std::endl;
722 lua_pushlightuserdata(L, this);
724 lua_pushlstring(L, other.c_str(), other.size());
726 // Call (2 parameters, 0 result)
727 if(lua_pcall(L, 2, 0, 0))
729 dstream<<"WARNING: LuaSAO: Error running function "
731 <<lua_tostring(L,-1)<<std::endl;
736 void LuaSAO::loadScripts(const std::string &script_name)
738 m_script_name = script_name;
740 std::string relative_path;
741 relative_path += "scripts/objects/";
742 relative_path += script_name;
743 std::string server_file = relative_path + "/server.lua";
744 std::string server_path = porting::getDataPath(server_file.c_str());
748 ret = luaL_loadfile(L, server_path.c_str());
751 const char *message = lua_tostring(L, -1);
753 dstream<<"LuaSAO::loadScript(): lua_loadfile failed: "
754 <<message<<std::endl;
758 ret = lua_pcall(L, 0, 0, 0);
761 const char *message = lua_tostring(L, -1);
763 dstream<<"LuaSAO::loadScript(): lua_pcall failed: "
764 <<message<<std::endl;
770 void LuaSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
772 const char *funcname = "on_step";
773 lua_getglobal(L, funcname);
774 if(!lua_isfunction(L,-1))
777 dstream<<"WARNING: LuaSAO::step(): Function not found: "
778 <<funcname<<std::endl;
784 lua_pushlightuserdata(L, this);
786 lua_pushnumber(L, dtime);
788 // Call (2 parameters, 0 result)
789 if(lua_pcall(L, 2, 0, 0))
791 dstream<<"WARNING: LuaSAO::step(): Error running function "
793 <<lua_tostring(L,-1)<<std::endl;
798 while(m_message_queue.size() != 0)
800 messages.push_back(m_message_queue.pop_front());