summaryrefslogtreecommitdiff
path: root/src/serverobject.cpp
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-02-21 16:10:36 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-02-21 16:10:36 +0200
commit69dbc046eb5a82b38c6d5c3302e9b3b0b3c1bcf1 (patch)
treee892b50187ba7343cb75f359ccbb55bdde19afd5 /src/serverobject.cpp
parentc57637b4c39319e0c0d5d80d0ae2884aec66d691 (diff)
downloadminetest-69dbc046eb5a82b38c6d5c3302e9b3b0b3c1bcf1.tar.gz
minetest-69dbc046eb5a82b38c6d5c3302e9b3b0b3c1bcf1.tar.bz2
minetest-69dbc046eb5a82b38c6d5c3302e9b3b0b3c1bcf1.zip
preliminary lua scripting framework for objects
Diffstat (limited to 'src/serverobject.cpp')
-rw-r--r--src/serverobject.cpp433
1 files changed, 429 insertions, 4 deletions
diff --git a/src/serverobject.cpp b/src/serverobject.cpp
index ffb6059dc..2fd3a1bfb 100644
--- a/src/serverobject.cpp
+++ b/src/serverobject.cpp
@@ -18,11 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "serverobject.h"
+#include <fstream>
+#include "environment.h"
-ServerActiveObject::ServerActiveObject(u16 id, v3f pos):
+ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos):
ActiveObject(id),
m_known_by_count(0),
m_removed(false),
+ m_env(env),
m_base_position(pos)
{
}
@@ -31,8 +34,12 @@ ServerActiveObject::~ServerActiveObject()
{
}
-TestSAO::TestSAO(u16 id, v3f pos):
- ServerActiveObject(id, pos),
+/*
+ TestSAO
+*/
+
+TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
+ ServerActiveObject(env, id, pos),
m_timer1(0),
m_age(0)
{
@@ -67,9 +74,427 @@ void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
data += " ";
data += itos(m_base_position.Z);
- //ActiveObjectMessage aom(getId(), true, data);
ActiveObjectMessage aom(getId(), false, data);
messages.push_back(aom);
}
}
+/*
+ LuaSAO
+*/
+
+extern "C"{
+#include "lstring.h"
+}
+
+/*
+ object_set_base_position(self, x,y,z)
+ x,y,z = object_get_base_position(self)
+ object_add_message(self, data)
+ object_remove(self)
+*/
+
+/*
+ object_set_base_position(self, x, y, z)
+*/
+static int lf_object_set_base_position(lua_State *L)
+{
+ // 4: z
+ lua_Number z = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 3: y
+ lua_Number y = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 2: x
+ lua_Number x = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 1: self
+ LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ assert(self);
+
+ self->setBasePosition(v3f(x*BS,y*BS,z*BS));
+
+ return 0; // Number of return values
+}
+
+/*
+ object_get_base_position(self)
+*/
+static int lf_object_get_base_position(lua_State *L)
+{
+ // 1: self
+ LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ assert(self);
+
+ v3f pos = self->getBasePosition();
+
+ lua_pushnumber(L, pos.X/BS);
+ lua_pushnumber(L, pos.Y/BS);
+ lua_pushnumber(L, pos.Z/BS);
+ return 3; // Number of return values
+}
+
+/*
+ object_add_message(self, string data)
+ lf = luafunc
+*/
+static int lf_object_add_message(lua_State *L)
+{
+ // 2: data
+ size_t datalen = 0;
+ const char *data_c = lua_tolstring(L, -1, &datalen);
+ lua_pop(L, 1);
+ // 1: self
+ LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ assert(self);
+ assert(data_c);
+
+ std::string data(data_c, datalen);
+ //dstream<<"object_add_message: data="<<data<<std::endl;
+
+ // Create message and add to queue
+ ActiveObjectMessage aom(self->getId());
+ aom.reliable = true;
+ aom.datastring = data;
+ self->m_message_queue.push_back(aom);
+
+ return 0; // Number of return values
+}
+
+/*
+ object_get_node(x,y,z)
+*/
+static int lf_object_get_node(lua_State *L)
+{
+ // 4: z
+ lua_Number z = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 3: y
+ lua_Number y = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 2: x
+ lua_Number x = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ // 1: self
+ LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ assert(self);
+
+ v3s16 pos = floatToInt(v3f(x,y,z), 1.0);
+
+ /*dstream<<"Checking node from pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z
+ <<")"<<std::endl;*/
+
+ // Get the node
+ MapNode n(CONTENT_IGNORE);
+ n = self->getEnv()->getMap().getNodeNoEx(pos);
+
+ // Create a table with some data about the node
+ lua_newtable(L);
+ lua_pushstring(L, "content");
+ lua_pushinteger(L, n.d);
+ lua_settable(L, -3);
+ lua_pushstring(L, "walkable");
+ lua_pushboolean(L, content_features(n.d).walkable);
+ lua_settable(L, -3);
+
+ // Return the table
+ return 1;
+}
+
+/*
+ object_remove(x,y,z)
+*/
+static int lf_object_remove(lua_State *L)
+{
+ // 1: self
+ LuaSAO *self = (LuaSAO*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ assert(self);
+
+ self->m_removed = true;
+
+ return 0;
+}
+
+LuaSAO::LuaSAO(ServerEnvironment *env, u16 id, v3f pos):
+ ServerActiveObject(env, id, pos),
+ L(NULL)
+{
+ dstream<<"LuaSAO::LuaSAO(): id="<<id<<std::endl;
+ L = lua_open();
+ assert(L);
+
+ // Load libraries
+ luaopen_base(L);
+ luaopen_table(L);
+ luaopen_string(L);
+ luaopen_math(L);
+
+ // Add globals
+ //lua_pushlightuserdata(L, this);
+ //lua_setglobal(L, "self");
+
+ // Register functions
+ lua_register(L, "object_set_base_position", lf_object_set_base_position);
+ lua_register(L, "object_get_base_position", lf_object_get_base_position);
+ lua_register(L, "object_add_message", lf_object_add_message);
+ lua_register(L, "object_get_node", lf_object_get_node);
+ lua_register(L, "object_remove", lf_object_remove);
+}
+
+LuaSAO::~LuaSAO()
+{
+ lua_close(L);
+}
+
+std::string LuaSAO::getClientInitializationData()
+{
+ /*
+ Read client-side script from file
+ */
+
+ std::string relative_path;
+ relative_path += "luaobjects/";
+ relative_path += m_script_name;
+ relative_path += "/client.lua";
+ std::string full_path = porting::getDataPath(relative_path.c_str());
+ std::string script;
+ std::ifstream file(full_path.c_str(), std::ios::binary | std::ios::ate);
+ int size = file.tellg();
+ SharedBuffer<char> buf(size);
+ file.seekg(0, std::ios::beg);
+ file.read(&buf[0], size);
+ file.close();
+
+ /*
+ Create data string
+ */
+ std::string data;
+
+ // Append script
+ std::string script_string(&buf[0], buf.getSize());
+ data += serializeLongString(script_string);
+
+ /*
+ Get data from server-side script for inclusion
+ */
+ std::string other_data;
+
+ do{
+
+ const char *funcname = "get_client_init_data";
+ lua_getglobal(L, funcname);
+ if(!lua_isfunction(L,-1))
+ {
+ lua_pop(L,1);
+ dstream<<"WARNING: LuaSAO: Function not found: "
+ <<funcname<<std::endl;
+ break;
+ }
+
+ // Parameters:
+ // 1: self
+ lua_pushlightuserdata(L, this);
+
+ // Call (1 parameters, 1 result)
+ if(lua_pcall(L, 1, 1, 0))
+ {
+ dstream<<"WARNING: LuaSAO: Error running function "
+ <<funcname<<": "
+ <<lua_tostring(L,-1)<<std::endl;
+ break;
+ }
+
+ // Retrieve result
+ if(!lua_isstring(L,-1))
+ {
+ dstream<<"WARNING: LuaSAO: Function "<<funcname
+ <<" didn't return a string"<<std::endl;
+ break;
+ }
+
+ size_t cs_len = 0;
+ const char *cs = lua_tolstring(L, -1, &cs_len);
+ lua_pop(L,1);
+
+ other_data = std::string(cs, cs_len);
+
+ }while(0);
+
+ data += serializeLongString(other_data);
+
+ return data;
+}
+
+std::string LuaSAO::getServerInitializationData()
+{
+ std::string data;
+
+ // Script name
+ data.append(serializeString(m_script_name));
+
+ /*
+ Get data from server-side script for inclusion
+ */
+ std::string other_data;
+
+ do{
+
+ const char *funcname = "get_server_init_data";
+ lua_getglobal(L, funcname);
+ if(!lua_isfunction(L,-1))
+ {
+ lua_pop(L,1);
+ dstream<<"WARNING: LuaSAO: Function not found: "
+ <<funcname<<std::endl;
+ break;
+ }
+
+ // Parameters:
+ // 1: self
+ lua_pushlightuserdata(L, this);
+
+ // Call (1 parameters, 1 result)
+ if(lua_pcall(L, 1, 1, 0))
+ {
+ dstream<<"WARNING: LuaSAO: Error running function "
+ <<funcname<<": "
+ <<lua_tostring(L,-1)<<std::endl;
+ break;
+ }
+
+ // Retrieve result
+ if(!lua_isstring(L,-1))
+ {
+ dstream<<"WARNING: LuaSAO: Function "<<funcname
+ <<" didn't return a string"<<std::endl;
+ break;
+ }
+
+ size_t cs_len = 0;
+ const char *cs = lua_tolstring(L, -1, &cs_len);
+ lua_pop(L,1);
+
+ other_data = std::string(cs, cs_len);
+
+ }while(0);
+
+ data += serializeLongString(other_data);
+
+ return data;
+}
+
+void LuaSAO::initialize(const std::string &data)
+{
+ std::istringstream is(data, std::ios::binary);
+ std::string script_name = deSerializeString(is);
+ std::string other = deSerializeLongString(is);
+
+ loadScripts(script_name);
+
+ /*
+ Call initialize(self, data) in the script
+ */
+
+ const char *funcname = "initialize";
+ lua_getglobal(L, funcname);
+ if(!lua_isfunction(L,-1))
+ {
+ lua_pop(L,1);
+ dstream<<"WARNING: LuaSAO: Function not found: "
+ <<funcname<<std::endl;
+ return;
+ }
+
+ // Parameters:
+ // 1: self
+ lua_pushlightuserdata(L, this);
+ // 2: data (other)
+ lua_pushlstring(L, other.c_str(), other.size());
+
+ // Call (2 parameters, 0 result)
+ if(lua_pcall(L, 2, 0, 0))
+ {
+ dstream<<"WARNING: LuaSAO: Error running function "
+ <<funcname<<": "
+ <<lua_tostring(L,-1)<<std::endl;
+ return;
+ }
+}
+
+void LuaSAO::loadScripts(const std::string &script_name)
+{
+ m_script_name = script_name;
+
+ std::string relative_path;
+ relative_path += "luaobjects/";
+ relative_path += script_name;
+ std::string server_file = relative_path + "/server.lua";
+ std::string server_path = porting::getDataPath(server_file.c_str());
+
+ // Load the file
+ int ret;
+ ret = luaL_loadfile(L, server_path.c_str());
+ if(ret)
+ {
+ const char *message = lua_tostring(L, -1);
+ lua_pop(L, 1);
+ dstream<<"LuaSAO::loadScript(): lua_loadfile failed: "
+ <<message<<std::endl;
+ assert(0);
+ return;
+ }
+ ret = lua_pcall(L, 0, 0, 0);
+ if(ret)
+ {
+ const char *message = lua_tostring(L, -1);
+ lua_pop(L, 1);
+ dstream<<"LuaSAO::loadScript(): lua_pcall failed: "
+ <<message<<std::endl;
+ assert(0);
+ return;
+ }
+}
+
+void LuaSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
+{
+ lua_getglobal(L, "step");
+ if(!lua_isfunction(L,-1))
+ {
+ lua_pop(L,1);
+ dstream<<"WARNING: LuaSAO::step(): step function not found"<<std::endl;
+ return;
+ }
+
+ // Parameters:
+ // 1: self
+ lua_pushlightuserdata(L, this);
+ // 2: dtime
+ lua_pushnumber(L, dtime);
+
+ // Call (2 parameters, 0 result)
+ if(lua_pcall(L, 2, 0, 0))
+ {
+ dstream<<"WARNING: LuaSAO::step(): Error running function step(): "
+ <<lua_tostring(L,-1)<<std::endl;
+ return;
+ }
+
+ // Move messages
+ while(m_message_queue.size() != 0)
+ {
+ messages.push_back(m_message_queue.pop_front());
+ }
+}
+
+
+