]> git.lizzy.rs Git - minetest.git/blob - src/serverobject.cpp
2fd3a1bfb16e52a7e28239807749264b95dd7bde
[minetest.git] / src / serverobject.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 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.
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 General Public License for more details.
14
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.
18 */
19
20 #include "serverobject.h"
21 #include <fstream>
22 #include "environment.h"
23
24 ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos):
25         ActiveObject(id),
26         m_known_by_count(0),
27         m_removed(false),
28         m_env(env),
29         m_base_position(pos)
30 {
31 }
32
33 ServerActiveObject::~ServerActiveObject()
34 {
35 }
36
37 /*
38         TestSAO
39 */
40
41 TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
42         ServerActiveObject(env, id, pos),
43         m_timer1(0),
44         m_age(0)
45 {
46 }
47
48 void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
49 {
50         m_age += dtime;
51         if(m_age > 10)
52         {
53                 m_removed = true;
54                 return;
55         }
56
57         m_base_position.Y += dtime * BS * 2;
58         if(m_base_position.Y > 8*BS)
59                 m_base_position.Y = 2*BS;
60
61         m_timer1 -= dtime;
62         if(m_timer1 < 0.0)
63         {
64                 m_timer1 += 0.125;
65                 //dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
66
67                 std::string data;
68
69                 data += itos(0); // 0 = position
70                 data += " ";
71                 data += itos(m_base_position.X);
72                 data += " ";
73                 data += itos(m_base_position.Y);
74                 data += " ";
75                 data += itos(m_base_position.Z);
76
77                 ActiveObjectMessage aom(getId(), false, data);
78                 messages.push_back(aom);
79         }
80 }
81
82 /*
83         LuaSAO
84 */
85
86 extern "C"{
87 #include "lstring.h"
88 }
89
90 /*
91         object_set_base_position(self, x,y,z)
92         x,y,z = object_get_base_position(self)
93         object_add_message(self, data)
94         object_remove(self)
95 */
96
97 /*
98         object_set_base_position(self, x, y, z)
99 */
100 static int lf_object_set_base_position(lua_State *L)
101 {
102         // 4: z
103         lua_Number z = lua_tonumber(L, -1);
104         lua_pop(L, 1);
105         // 3: y
106         lua_Number y = lua_tonumber(L, -1);
107         lua_pop(L, 1);
108         // 2: x
109         lua_Number x = lua_tonumber(L, -1);
110         lua_pop(L, 1);
111         // 1: self
112         LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
113         lua_pop(L, 1);
114         
115         assert(self);
116         
117         self->setBasePosition(v3f(x*BS,y*BS,z*BS));
118         
119         return 0; // Number of return values
120 }
121
122 /*
123         object_get_base_position(self)
124 */
125 static int lf_object_get_base_position(lua_State *L)
126 {
127         // 1: self
128         LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
129         lua_pop(L, 1);
130         
131         assert(self);
132         
133         v3f pos = self->getBasePosition();
134
135         lua_pushnumber(L, pos.X/BS);
136         lua_pushnumber(L, pos.Y/BS);
137         lua_pushnumber(L, pos.Z/BS);
138         return 3; // Number of return values
139 }
140
141 /*
142         object_add_message(self, string data)
143         lf = luafunc
144 */
145 static int lf_object_add_message(lua_State *L)
146 {
147         // 2: data
148         size_t datalen = 0;
149         const char *data_c = lua_tolstring(L, -1, &datalen);
150         lua_pop(L, 1);
151         // 1: self
152         LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
153         lua_pop(L, 1);
154         
155         assert(self);
156         assert(data_c);
157         
158         std::string data(data_c, datalen);
159         //dstream<<"object_add_message: data="<<data<<std::endl;
160         
161         // Create message and add to queue
162         ActiveObjectMessage aom(self->getId());
163         aom.reliable = true;
164         aom.datastring = data;
165         self->m_message_queue.push_back(aom);
166
167         return 0; // Number of return values
168 }
169
170 /*
171         object_get_node(x,y,z)
172 */
173 static int lf_object_get_node(lua_State *L)
174 {
175         // 4: z
176         lua_Number z = lua_tonumber(L, -1);
177         lua_pop(L, 1);
178         // 3: y
179         lua_Number y = lua_tonumber(L, -1);
180         lua_pop(L, 1);
181         // 2: x
182         lua_Number x = lua_tonumber(L, -1);
183         lua_pop(L, 1);
184         // 1: self
185         LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
186         lua_pop(L, 1);
187         
188         assert(self);
189
190         v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
191
192         /*dstream<<"Checking node from pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z
193                         <<")"<<std::endl;*/
194         
195         // Get the node
196         MapNode n(CONTENT_IGNORE);
197         n = self->getEnv()->getMap().getNodeNoEx(pos);
198
199         // Create a table with some data about the node
200         lua_newtable(L);
201         lua_pushstring(L, "content");
202         lua_pushinteger(L, n.d);
203         lua_settable(L, -3);
204         lua_pushstring(L, "walkable");
205         lua_pushboolean(L, content_features(n.d).walkable);
206         lua_settable(L, -3);
207         
208         // Return the table
209         return 1;
210 }
211
212 /*
213         object_remove(x,y,z)
214 */
215 static int lf_object_remove(lua_State *L)
216 {
217         // 1: self
218         LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
219         lua_pop(L, 1);
220         
221         assert(self);
222
223         self->m_removed = true;
224
225         return 0;
226 }
227
228 LuaSAO::LuaSAO(ServerEnvironment *env, u16 id, v3f pos):
229         ServerActiveObject(env, id, pos),
230         L(NULL)
231 {
232         dstream<<"LuaSAO::LuaSAO(): id="<<id<<std::endl;
233         L = lua_open();
234         assert(L);
235         
236         // Load libraries
237         luaopen_base(L);
238         luaopen_table(L);
239         luaopen_string(L);
240         luaopen_math(L);
241         
242         // Add globals
243         //lua_pushlightuserdata(L, this);
244         //lua_setglobal(L, "self");
245         
246         // Register functions
247         lua_register(L, "object_set_base_position", lf_object_set_base_position);
248         lua_register(L, "object_get_base_position", lf_object_get_base_position);
249         lua_register(L, "object_add_message", lf_object_add_message);
250         lua_register(L, "object_get_node", lf_object_get_node);
251         lua_register(L, "object_remove", lf_object_remove);
252 }
253
254 LuaSAO::~LuaSAO()
255 {
256         lua_close(L);
257 }
258
259 std::string LuaSAO::getClientInitializationData()
260 {
261         /*
262                 Read client-side script from file
263         */
264         
265         std::string relative_path;
266         relative_path += "luaobjects/";
267         relative_path += m_script_name;
268         relative_path += "/client.lua";
269         std::string full_path = porting::getDataPath(relative_path.c_str());
270         std::string script;
271         std::ifstream file(full_path.c_str(), std::ios::binary | std::ios::ate);
272         int size = file.tellg();
273         SharedBuffer<char> buf(size);
274         file.seekg(0, std::ios::beg);
275         file.read(&buf[0], size);
276         file.close();
277         
278         /*
279                 Create data string
280         */
281         std::string data;
282
283         // Append script
284         std::string script_string(&buf[0], buf.getSize());
285         data += serializeLongString(script_string);
286
287         /*
288                 Get data from server-side script for inclusion
289         */
290         std::string other_data;
291         
292         do{
293
294                 const char *funcname = "get_client_init_data";
295                 lua_getglobal(L, funcname);
296                 if(!lua_isfunction(L,-1))
297                 {
298                         lua_pop(L,1);
299                         dstream<<"WARNING: LuaSAO: Function not found: "
300                                         <<funcname<<std::endl;
301                         break;
302                 }
303                 
304                 // Parameters:
305                 // 1: self
306                 lua_pushlightuserdata(L, this);
307                 
308                 // Call (1 parameters, 1 result)
309                 if(lua_pcall(L, 1, 1, 0))
310                 {
311                         dstream<<"WARNING: LuaSAO: Error running function "
312                                         <<funcname<<": "
313                                         <<lua_tostring(L,-1)<<std::endl;
314                         break;
315                 }
316
317                 // Retrieve result
318                 if(!lua_isstring(L,-1))
319                 {
320                         dstream<<"WARNING: LuaSAO: Function "<<funcname
321                                         <<" didn't return a string"<<std::endl;
322                         break;
323                 }
324                 
325                 size_t cs_len = 0;
326                 const char *cs = lua_tolstring(L, -1, &cs_len);
327                 lua_pop(L,1);
328
329                 other_data = std::string(cs, cs_len);
330
331         }while(0);
332         
333         data += serializeLongString(other_data);
334
335         return data;
336 }
337
338 std::string LuaSAO::getServerInitializationData()
339 {
340         std::string data;
341         
342         // Script name
343         data.append(serializeString(m_script_name));
344
345         /*
346                 Get data from server-side script for inclusion
347         */
348         std::string other_data;
349         
350         do{
351
352                 const char *funcname = "get_server_init_data";
353                 lua_getglobal(L, funcname);
354                 if(!lua_isfunction(L,-1))
355                 {
356                         lua_pop(L,1);
357                         dstream<<"WARNING: LuaSAO: Function not found: "
358                                         <<funcname<<std::endl;
359                         break;
360                 }
361                 
362                 // Parameters:
363                 // 1: self
364                 lua_pushlightuserdata(L, this);
365                 
366                 // Call (1 parameters, 1 result)
367                 if(lua_pcall(L, 1, 1, 0))
368                 {
369                         dstream<<"WARNING: LuaSAO: Error running function "
370                                         <<funcname<<": "
371                                         <<lua_tostring(L,-1)<<std::endl;
372                         break;
373                 }
374
375                 // Retrieve result
376                 if(!lua_isstring(L,-1))
377                 {
378                         dstream<<"WARNING: LuaSAO: Function "<<funcname
379                                         <<" didn't return a string"<<std::endl;
380                         break;
381                 }
382                 
383                 size_t cs_len = 0;
384                 const char *cs = lua_tolstring(L, -1, &cs_len);
385                 lua_pop(L,1);
386
387                 other_data = std::string(cs, cs_len);
388
389         }while(0);
390         
391         data += serializeLongString(other_data);
392
393         return data;
394 }
395
396 void LuaSAO::initialize(const std::string &data)
397 {
398         std::istringstream is(data, std::ios::binary);
399         std::string script_name = deSerializeString(is);
400         std::string other = deSerializeLongString(is);
401
402         loadScripts(script_name);
403
404         /*
405                 Call initialize(self, data) in the script
406         */
407         
408         const char *funcname = "initialize";
409         lua_getglobal(L, funcname);
410         if(!lua_isfunction(L,-1))
411         {
412                 lua_pop(L,1);
413                 dstream<<"WARNING: LuaSAO: Function not found: "
414                                 <<funcname<<std::endl;
415                 return;
416         }
417         
418         // Parameters:
419         // 1: self
420         lua_pushlightuserdata(L, this);
421         // 2: data (other)
422         lua_pushlstring(L, other.c_str(), other.size());
423         
424         // Call (2 parameters, 0 result)
425         if(lua_pcall(L, 2, 0, 0))
426         {
427                 dstream<<"WARNING: LuaSAO: Error running function "
428                                 <<funcname<<": "
429                                 <<lua_tostring(L,-1)<<std::endl;
430                 return;
431         }
432 }
433
434 void LuaSAO::loadScripts(const std::string &script_name)
435 {
436         m_script_name = script_name;
437         
438         std::string relative_path;
439         relative_path += "luaobjects/";
440         relative_path += script_name;
441         std::string server_file = relative_path + "/server.lua";
442         std::string server_path = porting::getDataPath(server_file.c_str());
443
444         // Load the file
445         int ret;
446         ret = luaL_loadfile(L, server_path.c_str());
447         if(ret)
448         {
449                 const char *message = lua_tostring(L, -1);
450                 lua_pop(L, 1);
451                 dstream<<"LuaSAO::loadScript(): lua_loadfile failed: "
452                                 <<message<<std::endl;
453                 assert(0);
454                 return;
455         }
456         ret = lua_pcall(L, 0, 0, 0);
457         if(ret)
458         {
459                 const char *message = lua_tostring(L, -1);
460                 lua_pop(L, 1);
461                 dstream<<"LuaSAO::loadScript(): lua_pcall failed: "
462                                 <<message<<std::endl;
463                 assert(0);
464                 return;
465         }
466 }
467
468 void LuaSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
469 {
470         lua_getglobal(L, "step");
471         if(!lua_isfunction(L,-1))
472         {
473                 lua_pop(L,1);
474                 dstream<<"WARNING: LuaSAO::step(): step function not found"<<std::endl;
475                 return;
476         }
477         
478         // Parameters:
479         // 1: self
480         lua_pushlightuserdata(L, this);
481         // 2: dtime
482         lua_pushnumber(L, dtime);
483         
484         // Call (2 parameters, 0 result)
485         if(lua_pcall(L, 2, 0, 0))
486         {
487                 dstream<<"WARNING: LuaSAO::step(): Error running function step(): "
488                                 <<lua_tostring(L,-1)<<std::endl;
489                 return;
490         }
491
492         // Move messages
493         while(m_message_queue.size() != 0)
494         {
495                 messages.push_back(m_message_queue.pop_front());
496         }
497 }
498
499
500