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)
100 object_set_base_position(self, {X=,Y=,Z=})
102 static int lf_object_set_base_position(lua_State *L)
105 assert(lua_istable(L, -1));
106 lua_pushstring(L, "X");
108 lua_Number x = lua_tonumber(L, -1);
110 lua_pushstring(L, "Y");
112 lua_Number y = lua_tonumber(L, -1);
114 lua_pushstring(L, "Z");
116 lua_Number z = lua_tonumber(L, -1);
120 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
125 self->setBasePosition(v3f(x*BS,y*BS,z*BS));
127 return 0; // Number of return values
131 {X=,Y=,Z=} object_get_base_position(self)
133 static int lf_object_get_base_position(lua_State *L)
136 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
141 v3f pos = self->getBasePosition();
145 lua_pushstring(L, "X");
146 lua_pushnumber(L, pos.X/BS);
149 lua_pushstring(L, "Y");
150 lua_pushnumber(L, pos.Y/BS);
153 lua_pushstring(L, "Z");
154 lua_pushnumber(L, pos.Z/BS);
157 return 1; // Number of return values
161 object_add_message(self, string data)
164 static int lf_object_add_message(lua_State *L)
168 const char *data_c = lua_tolstring(L, -1, &datalen);
171 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
177 std::string data(data_c, datalen);
178 //dstream<<"object_add_message: data="<<data<<std::endl;
180 // Create message and add to queue
181 ActiveObjectMessage aom(self->getId());
183 aom.datastring = data;
184 self->m_message_queue.push_back(aom);
186 return 0; // Number of return values
190 object_get_node(self, {X=,Y=,Z=})
192 static int lf_object_get_node(lua_State *L)
195 assert(lua_istable(L, -1));
196 lua_pushstring(L, "X");
198 lua_Number x = lua_tonumber(L, -1);
200 lua_pushstring(L, "Y");
202 lua_Number y = lua_tonumber(L, -1);
204 lua_pushstring(L, "Z");
206 lua_Number z = lua_tonumber(L, -1);
210 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
215 v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
217 /*dstream<<"Checking node from pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z
221 MapNode n(CONTENT_IGNORE);
222 n = self->getEnv()->getMap().getNodeNoEx(pos);
224 // Create a table with some data about the node
226 lua_pushstring(L, "content");
227 lua_pushinteger(L, n.d);
229 lua_pushstring(L, "param1");
230 lua_pushinteger(L, n.param);
232 lua_pushstring(L, "param2");
233 lua_pushinteger(L, n.param2);
242 get_node_features(node)
243 node = {content=,param1=,param2=}
245 static int lf_get_node_features(lua_State *L)
250 assert(lua_istable(L, -1));
251 lua_pushstring(L, "content");
253 n.d = lua_tointeger(L, -1);
255 lua_pushstring(L, "param1");
257 n.param = lua_tointeger(L, -1);
259 lua_pushstring(L, "param2");
261 n.param2 = lua_tointeger(L, -1);
265 ContentFeatures &f = content_features(n.d);
271 get_content_features(content)
273 static int lf_get_content_features(lua_State *L)
278 n.d = lua_tointeger(L, -1);
281 // Get and return information
282 ContentFeatures &f = content_features(n.d);
285 lua_pushstring(L, "walkable");
286 lua_pushboolean(L, f.walkable);
288 lua_pushstring(L, "diggable");
289 lua_pushboolean(L, f.diggable);
291 lua_pushstring(L, "buildable_to");
292 lua_pushboolean(L, f.buildable_to);
299 bool object_dig_node(self, {X=,Y=,Z=})
300 Return true on success
302 static int lf_object_dig_node(lua_State *L)
305 assert(lua_istable(L, -1));
306 lua_pushstring(L, "X");
308 lua_Number x = lua_tonumber(L, -1);
310 lua_pushstring(L, "Y");
312 lua_Number y = lua_tonumber(L, -1);
314 lua_pushstring(L, "Z");
316 lua_Number z = lua_tonumber(L, -1);
320 LuaSAO *self = (LuaSAO*)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 = self->getEnv()->getMap().removeNodeWithEvent(pos);
334 lua_pushboolean(L, succeeded);
339 bool object_place_node(self, {X=,Y=,Z=}, node)
340 node={content=,param1=,param2=}
341 param1 and param2 are optional
342 Return true on success
344 static int lf_object_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 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
388 v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
392 This gets sent to the server by the map through the edit
395 bool succeeded = self->getEnv()->getMap().addNodeWithEvent(pos, n);
397 lua_pushboolean(L, succeeded);
404 static int lf_object_remove(lua_State *L)
407 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
412 self->m_removed = true;
418 {X=,Y=,Z=} object_get_nearest_player_position(self)
420 /*static int lf_object_get_nearest_player_position(lua_State *L)
423 LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
428 ServerEnvironment *env = self->getEnv();
434 lua_pushstring(L, "X");
435 lua_pushnumber(L, pos.X/BS);
438 lua_pushstring(L, "Y");
439 lua_pushnumber(L, pos.Y/BS);
442 lua_pushstring(L, "Z");
443 lua_pushnumber(L, pos.Z/BS);
446 return 1; // Number of return values
449 LuaSAO::LuaSAO(ServerEnvironment *env, u16 id, v3f pos):
450 ServerActiveObject(env, id, pos),
453 dstream<<"LuaSAO::LuaSAO(): id="<<id<<std::endl;
464 //lua_pushlightuserdata(L, this);
465 //lua_setglobal(L, "self");
467 // Register functions
468 lua_register(L, "object_set_base_position", lf_object_set_base_position);
469 lua_register(L, "object_get_base_position", lf_object_get_base_position);
470 lua_register(L, "object_add_message", lf_object_add_message);
471 lua_register(L, "object_get_node", lf_object_get_node);
472 lua_register(L, "get_content_features", lf_get_content_features);
473 lua_register(L, "object_dig_node", lf_object_dig_node);
474 lua_register(L, "object_place_node", lf_object_place_node);
475 lua_register(L, "object_remove", lf_object_remove);
483 std::string LuaSAO::getClientInitializationData()
486 Read client-side script from file
489 std::string relative_path;
490 relative_path += "luaobjects/";
491 relative_path += m_script_name;
492 relative_path += "/client.lua";
493 std::string full_path = porting::getDataPath(relative_path.c_str());
495 std::ifstream file(full_path.c_str(), std::ios::binary | std::ios::ate);
496 int size = file.tellg();
497 SharedBuffer<char> buf(size);
498 file.seekg(0, std::ios::beg);
499 file.read(&buf[0], size);
508 std::string script_string(&buf[0], buf.getSize());
509 data += serializeLongString(script_string);
512 Get data from server-side script for inclusion
514 std::string other_data;
518 const char *funcname = "on_get_client_init_data";
519 lua_getglobal(L, funcname);
520 if(!lua_isfunction(L,-1))
523 dstream<<"WARNING: LuaSAO: Function not found: "
524 <<funcname<<std::endl;
530 lua_pushlightuserdata(L, this);
532 // Call (1 parameters, 1 result)
533 if(lua_pcall(L, 1, 1, 0))
535 dstream<<"WARNING: LuaSAO: Error running function "
537 <<lua_tostring(L,-1)<<std::endl;
542 if(!lua_isstring(L,-1))
544 dstream<<"WARNING: LuaSAO: Function "<<funcname
545 <<" didn't return a string"<<std::endl;
550 const char *cs = lua_tolstring(L, -1, &cs_len);
553 other_data = std::string(cs, cs_len);
557 data += serializeLongString(other_data);
562 std::string LuaSAO::getServerInitializationData()
567 data.append(serializeString(m_script_name));
570 Get data from server-side script for inclusion
572 std::string other_data;
576 const char *funcname = "on_get_server_init_data";
577 lua_getglobal(L, funcname);
578 if(!lua_isfunction(L,-1))
581 dstream<<"WARNING: LuaSAO: Function not found: "
582 <<funcname<<std::endl;
588 lua_pushlightuserdata(L, this);
590 // Call (1 parameters, 1 result)
591 if(lua_pcall(L, 1, 1, 0))
593 dstream<<"WARNING: LuaSAO: Error running function "
595 <<lua_tostring(L,-1)<<std::endl;
600 if(!lua_isstring(L,-1))
602 dstream<<"WARNING: LuaSAO: Function "<<funcname
603 <<" didn't return a string"<<std::endl;
608 const char *cs = lua_tolstring(L, -1, &cs_len);
611 other_data = std::string(cs, cs_len);
615 data += serializeLongString(other_data);
620 void LuaSAO::initializeFromNothing(const std::string &script_name)
622 loadScripts(script_name);
625 Call on_initialize(self, data) in the script
628 const char *funcname = "on_initialize";
629 lua_getglobal(L, funcname);
630 if(!lua_isfunction(L,-1))
633 dstream<<"WARNING: LuaSAO: Function not found: "
634 <<funcname<<std::endl;
640 lua_pushlightuserdata(L, this);
642 lua_pushstring(L, "");
644 // Call (2 parameters, 0 result)
645 if(lua_pcall(L, 2, 0, 0))
647 dstream<<"WARNING: LuaSAO: Error running function "
649 <<lua_tostring(L,-1)<<std::endl;
654 void LuaSAO::initializeFromSave(const std::string &data)
656 std::istringstream is(data, std::ios::binary);
657 std::string script_name = deSerializeString(is);
658 std::string other = deSerializeLongString(is);
660 loadScripts(script_name);
663 Call on_initialize(self, data) in the script
666 const char *funcname = "on_initialize";
667 lua_getglobal(L, funcname);
668 if(!lua_isfunction(L,-1))
671 dstream<<"WARNING: LuaSAO: Function not found: "
672 <<funcname<<std::endl;
678 lua_pushlightuserdata(L, this);
680 lua_pushlstring(L, other.c_str(), other.size());
682 // Call (2 parameters, 0 result)
683 if(lua_pcall(L, 2, 0, 0))
685 dstream<<"WARNING: LuaSAO: Error running function "
687 <<lua_tostring(L,-1)<<std::endl;
692 void LuaSAO::loadScripts(const std::string &script_name)
694 m_script_name = script_name;
696 std::string relative_path;
697 relative_path += "luaobjects/";
698 relative_path += script_name;
699 std::string server_file = relative_path + "/server.lua";
700 std::string server_path = porting::getDataPath(server_file.c_str());
704 ret = luaL_loadfile(L, server_path.c_str());
707 const char *message = lua_tostring(L, -1);
709 dstream<<"LuaSAO::loadScript(): lua_loadfile failed: "
710 <<message<<std::endl;
714 ret = lua_pcall(L, 0, 0, 0);
717 const char *message = lua_tostring(L, -1);
719 dstream<<"LuaSAO::loadScript(): lua_pcall failed: "
720 <<message<<std::endl;
726 void LuaSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
728 const char *funcname = "on_step";
729 lua_getglobal(L, funcname);
730 if(!lua_isfunction(L,-1))
733 dstream<<"WARNING: LuaSAO::step(): Function not found: "
734 <<funcname<<std::endl;
740 lua_pushlightuserdata(L, this);
742 lua_pushnumber(L, dtime);
744 // Call (2 parameters, 0 result)
745 if(lua_pcall(L, 2, 0, 0))
747 dstream<<"WARNING: LuaSAO::step(): Error running function "
749 <<lua_tostring(L,-1)<<std::endl;
754 while(m_message_queue.size() != 0)
756 messages.push_back(m_message_queue.pop_front());