From: Perttu Ahola Date: Fri, 11 Nov 2011 17:33:17 +0000 (+0200) Subject: Scripting WIP X-Git-Tag: 0.4.dev-20111201-0~207 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=bfc68d31510bbd40732c19ada51d4683cb050de2;p=oweals%2Fminetest.git Scripting WIP --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f75c182bd..b41fc4a6c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,6 +94,8 @@ configure_file( ) set(common_SRCS + scriptapi.cpp + script.cpp log.cpp content_sao.cpp mapgen.cpp diff --git a/src/common_irrlicht.h b/src/common_irrlicht.h index f4c2f76ec..379c2d15a 100644 --- a/src/common_irrlicht.h +++ b/src/common_irrlicht.h @@ -23,13 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define endSceneX(d){d->draw2DLine(v2s32(0,0),v2s32(1,0),\ video::SColor(255,30,30,30));d->endScene();} -#include -#include -#include -#include -#include -#include -#include +#include "irrlichttypes.h" + #ifndef SERVER #include #include @@ -43,26 +38,6 @@ video::SColor(255,30,30,30));d->endScene();} #include #include #endif -using namespace irr; -typedef core::vector3df v3f; -typedef core::vector3d v3s16; -typedef core::vector3d v3s32; - -typedef core::vector2d v2f; -typedef core::vector2d v2s16; -typedef core::vector2d v2s32; -typedef core::vector2d v2u32; -typedef core::vector2d v2f32; - -#ifdef _MSC_VER - // Windows - typedef unsigned long long u64; -#else - // Posix - #include - typedef uint64_t u64; - //typedef unsigned long long u64; -#endif #endif diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 6cb2cee38..157a51886 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1264,3 +1264,152 @@ void MobV2CAO::setLooks(const std::string &looks) selection_size.X); } +/* + LuaEntityCAO +*/ + +// Prototype +LuaEntityCAO proto_LuaEntityCAO; + +LuaEntityCAO::LuaEntityCAO(): + ClientActiveObject(0), + m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), + m_node(NULL), + m_position(v3f(0,10*BS,0)) +{ + ClientActiveObject::registerType(getType(), create); +} + +LuaEntityCAO::~LuaEntityCAO() +{ +} + +ClientActiveObject* LuaEntityCAO::create() +{ + return new LuaEntityCAO(); +} + +void LuaEntityCAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + video::IVideoDriver* driver = smgr->getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/ + video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1), + video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1), + video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0), + video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); + //buf->getMaterial().setTexture(0, NULL); + // Initialize with the stick texture + buf->getMaterial().setTexture + (0, driver->getTexture(getTexturePath("mese.png").c_str())); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + m_node = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + // Set it to use the materials of the meshbuffers directly. + // This is needed for changing the texture in the future + m_node->setReadOnlyMaterials(true); + updateNodePos(); +} + +void LuaEntityCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void LuaEntityCAO::updateLight(u8 light_at_pos) +{ + if(m_node == NULL) + return; + + u8 li = decode_light(light_at_pos); + video::SColor color(255,li,li,li); + setMeshVerticesColor(m_node->getMesh(), color); +} + +v3s16 LuaEntityCAO::getLightPosition() +{ + return floatToInt(m_position, BS); +} + +void LuaEntityCAO::updateNodePos() +{ + if(m_node == NULL) + return; + + m_node->setPosition(m_position); +} + +void LuaEntityCAO::step(float dtime, ClientEnvironment *env) +{ + if(m_node) + { + /*v3f rot = m_node->getRotation(); + rot.Y += dtime * 120; + m_node->setRotation(rot);*/ + LocalPlayer *player = env->getLocalPlayer(); + assert(player); + v3f rot = m_node->getRotation(); + rot.Y = 180.0 - (player->getYaw()); + m_node->setRotation(rot); + } +} + +void LuaEntityCAO::processMessage(const std::string &data) +{ + infostream<<"LuaEntityCAO: Got message"<* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return m_position;} + +private: + core::aabbox3d m_selection_box; + scene::IMeshSceneNode *m_node; + v3f m_position; +}; + #endif diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp index 413ae8505..1d5c6b355 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -80,16 +80,16 @@ std::string item_craft_get_image_name(const std::string &subname) } ServerActiveObject* item_craft_create_object(const std::string &subname, - ServerEnvironment *env, u16 id, v3f pos) + ServerEnvironment *env, v3f pos) { if(subname == "rat") { - ServerActiveObject *obj = new RatSAO(env, id, pos); + ServerActiveObject *obj = new RatSAO(env, pos); return obj; } else if(subname == "firefly") { - ServerActiveObject *obj = new FireflySAO(env, id, pos); + ServerActiveObject *obj = new FireflySAO(env, pos); return obj; } diff --git a/src/content_inventory.h b/src/content_inventory.h index 91550bb9a..9fd4cb03b 100644 --- a/src/content_inventory.h +++ b/src/content_inventory.h @@ -33,7 +33,7 @@ InventoryItem* item_material_create_cook_result(content_t content); std::string item_craft_get_image_name(const std::string &subname); ServerActiveObject* item_craft_create_object(const std::string &subname, - ServerEnvironment *env, u16 id, v3f pos); + ServerEnvironment *env, v3f pos); s16 item_craft_get_drop_count(const std::string &subname); bool item_craft_is_cookable(const std::string &subname); InventoryItem* item_craft_create_cook_result(const std::string &subname); diff --git a/src/content_object.h b/src/content_object.h index a5fea7163..f092b2789 100644 --- a/src/content_object.h +++ b/src/content_object.h @@ -27,5 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define ACTIVEOBJECT_TYPE_FIREFLY 5 #define ACTIVEOBJECT_TYPE_MOBV2 6 +#define ACTIVEOBJECT_TYPE_LUAENTITY 7 + #endif diff --git a/src/content_sao.cpp b/src/content_sao.cpp index f22637185..d51e92a8c 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -49,20 +49,20 @@ void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase) */ // Prototype -TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); +TestSAO proto_TestSAO(NULL, v3f(0,0,0)); -TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +TestSAO::TestSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_timer1(0), m_age(0) { ServerActiveObject::registerType(getType(), create); } -ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { - return new TestSAO(env, id, pos); + return new TestSAO(env, pos); } void TestSAO::step(float dtime, bool send_recommended) @@ -107,11 +107,11 @@ void TestSAO::step(float dtime, bool send_recommended) */ // Prototype -ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), ""); +ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); -ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, +ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos, const std::string inventorystring): - ServerActiveObject(env, id, pos), + ServerActiveObject(env, pos), m_inventorystring(inventorystring), m_speed_f(0,0,0), m_last_sent_position(0,0,0) @@ -119,7 +119,7 @@ ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, ServerActiveObject::registerType(getType(), create); } -ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -133,7 +133,7 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos, std::string inventorystring = deSerializeString(is); infostream<<"ItemSAO::create(): Creating item \"" <m_hp = hp; return o; } @@ -739,10 +739,10 @@ void Oerkki1SAO::doDamage(u16 d) */ // Prototype -FireflySAO proto_FireflySAO(NULL, 0, v3f(0,0,0)); +FireflySAO proto_FireflySAO(NULL, v3f(0,0,0)); -FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), +FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), m_is_active(false), m_speed_f(0,0,0) { @@ -757,7 +757,7 @@ FireflySAO::FireflySAO(ServerEnvironment *env, u16 id, v3f pos): m_touching_ground = false; } -ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* FireflySAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); @@ -768,7 +768,7 @@ ServerActiveObject* FireflySAO::create(ServerEnvironment *env, u16 id, v3f pos, // check if version is supported if(version != 0) return NULL; - return new FireflySAO(env, id, pos); + return new FireflySAO(env, pos); } void FireflySAO::step(float dtime, bool send_recommended) @@ -918,11 +918,11 @@ InventoryItem* FireflySAO::createPickedUpItem() */ // Prototype -MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL); +MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL); -MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos, +MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos, Settings *init_properties): - ServerActiveObject(env, id, pos), + ServerActiveObject(env, pos), m_move_type("ground_nodes"), m_speed(0,0,0), m_last_sent_position(0,0,0), @@ -961,13 +961,13 @@ MobV2SAO::~MobV2SAO() delete m_properties; } -ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos, +ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::istringstream is(data, std::ios::binary); Settings properties; properties.parseConfigLines(is, "MobArgsEnd"); - MobV2SAO *o = new MobV2SAO(env, id, pos, &properties); + MobV2SAO *o = new MobV2SAO(env, pos, &properties); return o; } @@ -1174,7 +1174,7 @@ void MobV2SAO::step(float dtime, bool send_recommended) properties.set("player_hit_damage", "9"); properties.set("player_hit_distance", "2"); properties.set("player_hit_interval", "1"); - ServerActiveObject *obj = new MobV2SAO(m_env, 0, + ServerActiveObject *obj = new MobV2SAO(m_env, pos, &properties); //m_env->addActiveObjectAsStatic(obj); m_env->addActiveObject(obj); @@ -1490,3 +1490,95 @@ void MobV2SAO::doDamage(u16 d) } +/* + LuaEntitySAO +*/ + +#include "scriptapi.h" + +// Prototype +LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", ""); + +LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, + const std::string &name, const std::string &state): + ServerActiveObject(env, pos), + m_init_name(name), + m_init_state(state), + m_registered(false) +{ + if(env == NULL){ + ServerActiveObject::registerType(getType(), create); + return; + } +} + +LuaEntitySAO::~LuaEntitySAO() +{ + if(m_registered){ + lua_State *L = m_env->getLua(); + scriptapi_luaentity_deregister(L, m_id); + } +} + +void LuaEntitySAO::addedToEnvironment(u16 id) +{ + ServerActiveObject::addedToEnvironment(id); + + // Create entity by name and state + m_registered = true; + lua_State *L = m_env->getLua(); + scriptapi_luaentity_register(L, id, m_init_name.c_str(), m_init_state.c_str()); +} + +ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, + const std::string &data) +{ + std::istringstream is(data, std::ios::binary); + // read version + u8 version = readU8(is); + // check if version is supported + if(version != 0) + return NULL; + // read name + std::string name = deSerializeString(is); + // read state + std::string state = deSerializeLongString(is); + // create object + infostream<<"LuaEntitySAO::create(name=\""<getLua(); + scriptapi_luaentity_step(L, m_id, dtime, send_recommended); + } +} + +std::string LuaEntitySAO::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + return os.str(); +} + +std::string LuaEntitySAO::getStaticData() +{ + infostream<<__FUNCTION_NAME< &active_positions, ServerEnvironment */ -ServerEnvironment::ServerEnvironment(ServerMap *map, Server *server): +ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L): m_map(map), - m_server(server), + m_lua(L), m_random_spawn_timer(3), m_send_recommended_timer(0), m_game_time(0), @@ -674,6 +675,8 @@ void ServerEnvironment::clearAllObjects() obj->m_removed = true; continue; } + // Deregister in scripting api + scriptapi_rm_object_reference(m_lua, obj); // Delete active object delete obj; // Id to be removed from m_active_objects @@ -1043,7 +1046,7 @@ void ServerEnvironment::step(float dtime) n1.getContent() == CONTENT_AIR) { v3f pos = intToFloat(p1, BS); - ServerActiveObject *obj = new RatSAO(this, 0, pos); + ServerActiveObject *obj = new RatSAO(this, pos); addActiveObject(obj); } } @@ -1071,21 +1074,21 @@ void ServerEnvironment::step(float dtime) Settings properties; getMob_dungeon_master(properties); ServerActiveObject *obj = new MobV2SAO( - this, 0, pos, &properties); + this, pos, &properties); addActiveObject(obj); } else if(i == 2 || i == 3){ actionstream<<"Rats spawn at " <addedToEnvironment(object->getId()); + // Register reference in scripting api + scriptapi_add_object_reference(m_lua, object); return object->getId(); } @@ -1544,6 +1552,9 @@ void ServerEnvironment::removeRemovedObjects() if(obj->m_known_by_count > 0) continue; + // Deregister in scripting api + scriptapi_rm_object_reference(m_lua, obj); + // Delete delete obj; // Id to be removed from m_active_objects @@ -1815,6 +1826,10 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) verbosestream<<"ServerEnvironment::deactivateFarObjects(): " <<"object id="< m_active_objects; // Outgoing network message buffer for active objects diff --git a/src/inventory.cpp b/src/inventory.cpp index 92ef3b011..5d4a6e408 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -136,7 +136,7 @@ ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f Create an ItemSAO */ // Create object - ServerActiveObject *obj = new ItemSAO(env, 0, pos, getItemString()); + ServerActiveObject *obj = new ItemSAO(env, pos, getItemString()); return obj; } @@ -174,7 +174,7 @@ video::ITexture * CraftItem::getImage() const ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos) { // Special cases - ServerActiveObject *obj = item_craft_create_object(m_subname, env, id, pos); + ServerActiveObject *obj = item_craft_create_object(m_subname, env, pos); if(obj) return obj; // Default diff --git a/src/irrlichttypes.h b/src/irrlichttypes.h new file mode 100644 index 000000000..7ab83bb7d --- /dev/null +++ b/src/irrlichttypes.h @@ -0,0 +1,52 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef IRRLICHTTYPES_HEADER +#define IRRLICHTTYPES_HEADER + +#include +#include +#include +#include +#include +#include +#include +using namespace irr; +typedef core::vector3df v3f; +typedef core::vector3d v3s16; +typedef core::vector3d v3s32; + +typedef core::vector2d v2f; +typedef core::vector2d v2s16; +typedef core::vector2d v2s32; +typedef core::vector2d v2u32; +typedef core::vector2d v2f32; + +#ifdef _MSC_VER + // Windows + typedef unsigned long long u64; +#else + // Posix + #include + typedef uint64_t u64; + //typedef unsigned long long u64; +#endif + +#endif + diff --git a/src/porting.cpp b/src/porting.cpp index 00595b06c..0adc955a9 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -56,9 +56,10 @@ void sigint_handler(int sig) dstream< + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "script.h" +#include +#include +#include +#include +#include "log.h" +#include + +extern "C" { +#include +#include +#include +} + +void script_error(lua_State *L, const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + lua_close(L); + exit(EXIT_FAILURE); +} + +void script_call_va(lua_State *L, const char *func, const char *sig, ...) +{ + va_list vl; + int narg, nres; /* number of arguments and results */ + + va_start(vl, sig); + lua_getglobal(L, func); /* push function */ + + for (narg = 0; *sig; narg++) { + /* repeat for each argument */ + /* check stack space */ + luaL_checkstack(L, 1, "too many arguments"); + switch (*sig++) { + case 'd': /* double argument */ + lua_pushnumber(L, va_arg(vl, double)); + break; + case 'i': /* int argument */ + lua_pushinteger(L, va_arg(vl, int)); + break; + case 's': /* string argument */ + lua_pushstring(L, va_arg(vl, char *)); + break; + case '>': /* end of arguments */ + goto endargs; + default: + script_error(L, "invalid option (%c)", *(sig - 1)); + } + } +endargs: + + nres = strlen(sig); /* number of expected results */ + + if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */ + script_error(L, "error calling '%s': %s", func, lua_tostring(L, -1)); + + nres = -nres; /* stack index of first result */ + while (*sig) { /* repeat for each result */ + switch (*sig++) { + case 'd': /* double result */ + if (!lua_isnumber(L, nres)) + script_error(L, "wrong result type"); + *va_arg(vl, double *) = lua_tonumber(L, nres); + break; + case 'i': /* int result */ + if (!lua_isnumber(L, nres)) + script_error(L, "wrong result type"); + *va_arg(vl, int *) = lua_tointeger(L, nres); + break; + case 's': /* string result */ + if (!lua_isstring(L, nres)) + script_error(L, "wrong result type"); + *va_arg(vl, const char **) = lua_tostring(L, nres); + break; + default: + script_error(L, "invalid option (%c)", *(sig - 1)); + } + nres++; + } + + va_end(vl); +} + +bool script_load(lua_State *L, const char *path) +{ + infostream<<"Loading and running script from "< + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef SCRIPT_HEADER +#define SCRIPT_HEADER + +typedef struct lua_State lua_State; +//#include + +lua_State* script_init(); +lua_State* script_deinit(lua_State *L); +void script_error(lua_State *L, const char *fmt, ...); +void script_call_va(lua_State *L, const char *func, const char *sig, ...); +bool script_load(lua_State *L, const char *path); + +#endif + diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp new file mode 100644 index 000000000..fbe383075 --- /dev/null +++ b/src/scriptapi.cpp @@ -0,0 +1,422 @@ +/* +Minetest-c55 +Copyright (C) 2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "scriptapi.h" + +#include +extern "C" { +#include +#include +#include +} + +#include "log.h" +#include "server.h" +#include "porting.h" +#include "filesys.h" +#include "serverobject.h" +#include "script.h" +//#include "luna.h" + +static void stackDump(lua_State *L, std::ostream &o) +{ + int i; + int top = lua_gettop(L); + for (i = 1; i <= top; i++) { /* repeat for each level */ + int t = lua_type(L, i); + switch (t) { + + case LUA_TSTRING: /* strings */ + o<<"\""<= 30){ + dstream<<"Stack is over 30:"<m_object; + if(co == NULL) return 0; + infostream<<"ObjectRef::l_remove(): id="<getId()<m_removed = true; + return 0; + } + + static int gc_object(lua_State *L) { + //ObjectRef *o = checkobject(L, 1); + ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); + //infostream<<"ObjectRef::gc_object: o="<getId()); // Push id + lua_gettable(L, objectstable); + // Object is at stack top + lua_pop(L, 1); // pop object*/ + + // Set luaentities[id] = nil + lua_pushnumber(L, cobj->getId()); // Push id + lua_pushnil(L); + lua_settable(L, objectstable); + + lua_pop(L, 2); // pop luaentities, minetest +} + +void scriptapi_luaentity_step(lua_State *L, u16 id, + float dtime, bool send_recommended) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + infostream<<"scriptapi_luaentity_step: id="<getId()); // Push id + lua_gettable(L, objectstable); + + // TODO: Call step function + + lua_pop(L, 1); // pop object + lua_pop(L, 2); // pop luaentities, minetest +} + +std::string scriptapi_luaentity_get_state(lua_State *L, u16 id) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + infostream<<"scriptapi_luaentity_get_state: id="<getId()); // Push id + lua_pushvalue(L, object); // Copy object to top of stack + lua_settable(L, objectstable); + + // pop object_refs, minetest and the object + lua_pop(L, 3); +} + +void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) +{ + realitycheck(L); + assert(lua_checkstack(L, 20)); + infostream<<"scriptapi_rm_object_reference: id="<getId()<getId()); // Push id + lua_gettable(L, objectstable); + // Set object reference to NULL + ObjectRef::set_null(L); + lua_pop(L, 1); // pop object + + // Set object_refs[id] = nil + lua_pushnumber(L, cobj->getId()); // Push id + lua_pushnil(L); + lua_settable(L, objectstable); + + // pop object_refs, minetest + lua_pop(L, 2); +} + diff --git a/src/scriptapi.h b/src/scriptapi.h new file mode 100644 index 000000000..a97d707a8 --- /dev/null +++ b/src/scriptapi.h @@ -0,0 +1,43 @@ +/* +Minetest-c55 +Copyright (C) 2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef SCRIPTAPI_HEADER +#define SCRIPTAPI_HEADER + +#include "irrlichttypes.h" +#include + +class Server; +class ServerActiveObject; +typedef struct lua_State lua_State; + +void scriptapi_export(lua_State *L, Server *server); + +void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj); +void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj); + +void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name, + const char *init_state); +void scriptapi_luaentity_deregister(lua_State *L, u16 id); +void scriptapi_luaentity_step(lua_State *L, u16 id, + float dtime, bool send_recommended); +std::string scriptapi_luaentity_get_state(lua_State *L, u16 id); + +#endif + diff --git a/src/server.cpp b/src/server.cpp index e7cfc9afc..1c5d8d937 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -39,6 +39,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "profiler.h" #include "log.h" +#include "script.h" +#include "scriptapi.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -185,7 +187,7 @@ void * EmergeThread::Thread() <<"("<m_env.getPlayer(peer_id); + Player *player = server->m_env->getPlayer(peer_id); assert(player != NULL); @@ -572,7 +574,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, MAP_BLOCKSIZE*p.Z); // Get ground height in nodes - s16 gh = server->m_env.getServerMap().findGroundLevel( + s16 gh = server->m_env->getServerMap().findGroundLevel( p2d_nodes_center); // If differs a lot, don't generate @@ -611,7 +613,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, /* Check if map has this block */ - MapBlock *block = server->m_env.getMap().getBlockNoCreateNoEx(p); + MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p); bool surely_not_found_on_disk = false; bool block_is_invalid = false; @@ -640,7 +642,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, #if 0 v2s16 p2d(p.X, p.Z); - ServerMap *map = (ServerMap*)(&server->m_env.getMap()); + ServerMap *map = (ServerMap*)(&server->m_env->getMap()); v2s16 chunkpos = map->sector_to_chunk(p2d); if(map->chunkNonVolatile(chunkpos) == false) block_is_invalid = true; @@ -802,7 +804,7 @@ void RemoteClient::SendObjectData( */ // Get connected players - core::list players = server->m_env.getPlayers(true); + core::list players = server->m_env->getPlayers(true); // Write player count u16 playercount = players.size(); @@ -948,10 +950,12 @@ Server::Server( std::string mapsavedir, std::string configpath ): - m_env(new ServerMap(mapsavedir), this), + m_env(NULL), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_authmanager(mapsavedir+DIR_DELIM+"auth.txt"), m_banmanager(mapsavedir+DIR_DELIM+"ipban.txt"), + m_lua(NULL), + //m_scriptapi(NULL), m_thread(this), m_emergethread(this), m_time_counter(0), @@ -973,20 +977,38 @@ Server::Server( m_con_mutex.Init(); m_step_dtime_mutex.Init(); m_step_dtime = 0.0; + + JMutexAutoLock envlock(m_env_mutex); + JMutexAutoLock conlock(m_con_mutex); + + // Initialize scripting + + infostream<<"Server: Initializing scripting"<getMap().addEventReceiver(this); // If file exists, load environment metadata if(fs::PathExists(m_mapsavedir+DIR_DELIM+"env_meta.txt")) { infostream<<"Server: Loading environment metadata"<loadMeta(m_mapsavedir); } // Load players infostream<<"Server: Loading players"<deSerializePlayers(m_mapsavedir); } Server::~Server() @@ -1029,13 +1051,13 @@ Server::~Server() Save players */ infostream<<"Server: Saving players"<serializePlayers(m_mapsavedir); /* Save environment metadata */ infostream<<"Server: Saving environment metadata"<saveMeta(m_mapsavedir); } /* @@ -1058,13 +1080,20 @@ Server::~Server() { u16 peer_id = i.getNode()->getKey(); JMutexAutoLock envlock(m_env_mutex); - m_env.removePlayer(peer_id); + m_env->removePlayer(peer_id); }*/ // Delete client delete i.getNode()->getValue(); } } + + // Delete Environment + delete m_env; + + // Deinitialize scripting + infostream<<"Server: Deinitializing scripting"<setTimeOfDay((m_env->getTimeOfDay() + units) % 24000); //infostream<<"Server: m_time_of_day = "<getValue(); - //Player *player = m_env.getPlayer(client->peer_id); + //Player *player = m_env->getPlayer(client->peer_id); SharedBuffer data = makePacket_TOCLIENT_TIME_OF_DAY( - m_env.getTimeOfDay()); + m_env->getTimeOfDay()); // Send as reliable m_con.Send(client->peer_id, 0, data, true); } @@ -1209,7 +1238,7 @@ void Server::AsyncRunStep() // Step environment ScopeProfiler sp(g_profiler, "SEnv step"); ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG); - m_env.step(dtime); + m_env->step(dtime); } const float map_timer_and_unload_dtime = 5.15; @@ -1218,7 +1247,7 @@ void Server::AsyncRunStep() JMutexAutoLock lock(m_env_mutex); // Run Map's timers and unload unused data ScopeProfiler sp(g_profiler, "Server: map timer and unload"); - m_env.getMap().timerUpdate(map_timer_and_unload_dtime, + m_env->getMap().timerUpdate(map_timer_and_unload_dtime, g_settings->getFloat("server_unload_unused_data_timeout")); } @@ -1239,13 +1268,13 @@ void Server::AsyncRunStep() ScopeProfiler sp(g_profiler, "Server: liquid transform"); core::map modified_blocks; - m_env.getMap().transformLiquids(modified_blocks); + m_env->getMap().transformLiquids(modified_blocks); #if 0 /* Update lighting */ core::map lighting_modified_blocks; - ServerMap &map = ((ServerMap&)m_env.getMap()); + ServerMap &map = ((ServerMap&)m_env->getMap()); map.updateLighting(modified_blocks, lighting_modified_blocks); // Add blocks modified by lighting to modified_blocks @@ -1295,7 +1324,7 @@ void Server::AsyncRunStep() { //u16 peer_id = i.getNode()->getKey(); RemoteClient *client = i.getNode()->getValue(); - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player==NULL) continue; infostream<<"* "<getName()<<"\t"; @@ -1326,7 +1355,7 @@ void Server::AsyncRunStep() i.atEnd() == false; i++) { RemoteClient *client = i.getNode()->getValue(); - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player==NULL) { // This can happen if the client timeouts somehow @@ -1339,9 +1368,9 @@ void Server::AsyncRunStep() core::map removed_objects; core::map added_objects; - m_env.getRemovedActiveObjects(pos, radius, + m_env->getRemovedActiveObjects(pos, radius, client->m_known_objects, removed_objects); - m_env.getAddedActiveObjects(pos, radius, + m_env->getAddedActiveObjects(pos, radius, client->m_known_objects, added_objects); // Ignore if nothing happened @@ -1364,7 +1393,7 @@ void Server::AsyncRunStep() { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); // Add to data buffer for sending writeU16((u8*)buf, i.getNode()->getKey()); @@ -1386,7 +1415,7 @@ void Server::AsyncRunStep() { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); // Get object type u8 type = ACTIVEOBJECT_TYPE_INVALID; @@ -1452,7 +1481,7 @@ void Server::AsyncRunStep() } } - m_env.setKnownActiveObjects(whatever); + m_env->setKnownActiveObjects(whatever); #endif } @@ -1473,7 +1502,7 @@ void Server::AsyncRunStep() // Get active object messages from environment for(;;) { - ActiveObjectMessage aom = m_env.getActiveObjectMessage(); + ActiveObjectMessage aom = m_env->getActiveObjectMessage(); if(aom.id == 0) break; @@ -1662,7 +1691,7 @@ void Server::AsyncRunStep() { v3s16 p = i.getNode()->getKey(); modified_blocks2.insert(p, - m_env.getMap().getBlockNoCreateNoEx(p)); + m_env->getMap().getBlockNoCreateNoEx(p)); } // Set blocks not sent for(core::list::Iterator @@ -1749,15 +1778,15 @@ void Server::AsyncRunStep() JMutexAutoLock lock(m_env_mutex); /*// Unload unused data (delete from memory) - m_env.getMap().unloadUnusedData( + m_env->getMap().unloadUnusedData( g_settings->getFloat("server_unload_unused_sectors_timeout")); */ - /*u32 deleted_count = m_env.getMap().unloadUnusedData( + /*u32 deleted_count = m_env->getMap().unloadUnusedData( g_settings->getFloat("server_unload_unused_sectors_timeout")); */ // Save only changed parts - m_env.getMap().save(true); + m_env->getMap().save(true); /*if(deleted_count > 0) { @@ -1766,10 +1795,10 @@ void Server::AsyncRunStep() }*/ // Save players - m_env.serializePlayers(m_mapsavedir); + m_env->serializePlayers(m_mapsavedir); // Save environment metadata - m_env.saveMeta(m_mapsavedir); + m_env->saveMeta(m_mapsavedir); } } } @@ -1811,7 +1840,7 @@ void Server::Receive() <<" has apparently closed connection. " <<"Removing player."<removePlayer(peer_id);*/ } } @@ -2026,7 +2055,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) writeU16(&reply[0], TOCLIENT_INIT); writeU8(&reply[2], deployed); writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS)); - writeU64(&reply[2+1+6], m_env.getServerMap().getSeed()); + writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); // Send as reliable m_con.Send(peer_id, 0, reply, true); @@ -2063,7 +2092,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send player items to all players SendPlayerItems(); - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); // Send HP SendPlayerHP(player); @@ -2071,7 +2100,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send time of day { SharedBuffer data = makePacket_TOCLIENT_TIME_OF_DAY( - m_env.getTimeOfDay()); + m_env->getTimeOfDay()); m_con.Send(peer_id, 0, data, true); } @@ -2081,7 +2110,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send information about joining in chat { std::wstring name = L"unknown"; - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player != NULL) name = narrow_to_wide(player->getName()); @@ -2117,7 +2146,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(client->serialization_version == SER_FMT_VER_INVALID) continue; // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(!player) continue; // Get name of player @@ -2139,7 +2168,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player == NULL){ infostream<<"Server::ProcessData(): Cancelling: " @@ -2247,7 +2276,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) u16 id = readS16(&data[3]); u16 item_i = readU16(&data[5]); - ServerActiveObject *obj = m_env.getActiveObject(id); + ServerActiveObject *obj = m_env->getActiveObject(id); if(obj == NULL) { @@ -2421,7 +2450,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) try { - MapNode n = m_env.getMap().getNode(p_under); + MapNode n = m_env->getMap().getNode(p_under); // Get mineral mineral = n.getMineral(); // Get material at position @@ -2442,7 +2471,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(cannot_remove_node == false) { // Get node metadata - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p_under); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p_under); if(meta && meta->nodeRemovalDisabled() == true) { infostream<<"Server: Not finishing digging: " @@ -2608,7 +2637,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { MapEditEventIgnorer ign(&m_ignore_map_edit_events); - m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks); + m_env->getMap().removeNodeAndUpdate(p_under, modified_blocks); } /* Set blocks not sent to far players @@ -2649,7 +2678,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { try{ // Don't add a node if this is not a free space - MapNode n2 = m_env.getMap().getNode(p_over); + MapNode n2 = m_env->getMap().getNode(p_over); bool no_enough_privs = ((getPlayerPrivs(player) & PRIV_BUILD)==0); if(no_enough_privs) @@ -2750,7 +2779,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) MapEditEventIgnorer ign(&m_ignore_map_edit_events); std::string p_name = std::string(player->getName()); - m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); + m_env->getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); } /* Set blocks not sent to far players @@ -2792,7 +2821,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) Check that the block is loaded so that the item can properly be added to the static list too */ - MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos); + MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); if(block==NULL) { infostream<<"Error while placing object: " @@ -2823,7 +2852,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) /* Create the object */ - ServerActiveObject *obj = item->createSAO(&m_env, 0, pos); + ServerActiveObject *obj = item->createSAO(m_env, 0, pos); if(obj == NULL) { @@ -2837,7 +2866,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" at "<addActiveObject(obj); infostream<<"Placed object"<getMap().getNodeMetadata(p); if(!meta) return; if(meta->typeId() != CONTENT_SIGN_WALL) @@ -2936,7 +2965,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" at "<getMap().getBlockNoCreateNoEx(blockpos); if(block) { block->setChangedFlag(); @@ -3052,7 +3081,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) p.X = stoi(fn.next(",")); p.Y = stoi(fn.next(",")); p.Z = stoi(fn.next(",")); - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) @@ -3070,7 +3099,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) p.X = stoi(fn.next(",")); p.Y = stoi(fn.next(",")); p.Z = stoi(fn.next(",")); - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) @@ -3153,7 +3182,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) str_split(message, L' '), paramstring, this, - &m_env, + m_env, player, privs); @@ -3356,7 +3385,7 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id) p.X = stoi(fn.next(",")); p.Y = stoi(fn.next(",")); p.Z = stoi(fn.next(",")); - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); if(meta) return meta->getInventory(); infostream<<"nodemeta at ("<getMap().getNodeMetadata(p); if(meta) meta->inventoryModified(); @@ -3415,7 +3444,7 @@ core::list Server::getPlayerInfo() core::list list; - core::list players = m_env.getPlayers(); + core::list players = m_env->getPlayers(); core::list::Iterator i; for(i = players.begin(); @@ -3559,7 +3588,7 @@ void Server::SendPlayerInfos() //JMutexAutoLock envlock(m_env_mutex); // Get connected players - core::list players = m_env.getPlayers(true); + core::list players = m_env->getPlayers(true); u32 player_count = players.getSize(); u32 datasize = 2+(2+PLAYERNAME_SIZE)*player_count; @@ -3593,7 +3622,7 @@ void Server::SendInventory(u16 peer_id) { DSTACK(__FUNCTION_NAME); - Player* player = m_env.getPlayer(peer_id); + Player* player = m_env->getPlayer(peer_id); assert(player); /* @@ -3650,7 +3679,7 @@ void Server::SendPlayerItems() DSTACK(__FUNCTION_NAME); std::ostringstream os(std::ios_base::binary); - core::list players = m_env.getPlayers(true); + core::list players = m_env->getPlayers(true); writeU16(os, TOCLIENT_PLAYERITEM); writeU16(os, players.size()); @@ -3779,7 +3808,7 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id, if(far_players) { // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player) { // If player is far away, only set modified blocks not sent @@ -3820,7 +3849,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, if(far_players) { // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player) { // If player is far away, only set modified blocks not sent @@ -3960,7 +3989,7 @@ void Server::SendBlocks(float dtime) MapBlock *block = NULL; try { - block = m_env.getMap().getBlockNoCreate(q.pos); + block = m_env->getMap().getBlockNoCreate(q.pos); } catch(InvalidPositionException &e) { @@ -4019,7 +4048,7 @@ void Server::HandlePlayerHP(Player *player, s16 damage) void Server::RespawnPlayer(Player *player) { - v3f pos = findSpawnPos(m_env.getServerMap()); + v3f pos = findSpawnPos(m_env->getServerMap()); player->setPosition(pos); player->hp = 20; SendMovePlayer(player); @@ -4030,7 +4059,7 @@ void Server::UpdateCrafting(u16 peer_id) { DSTACK(__FUNCTION_NAME); - Player* player = m_env.getPlayer(peer_id); + Player* player = m_env->getPlayer(peer_id); assert(player); /* @@ -4096,7 +4125,7 @@ std::wstring Server::getStatusString() if(client->serialization_version == SER_FMT_VER_INVALID) continue; // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); // Get name of player std::wstring name = L"unknown"; if(player != NULL) @@ -4105,7 +4134,7 @@ std::wstring Server::getStatusString() os<isSavingEnabled() == false) + if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false) os<get("motd") != "") os<get("motd")); @@ -4121,7 +4150,7 @@ void Server::saveConfig() void Server::notifyPlayer(const char *name, const std::wstring msg) { - Player *player = m_env.getPlayer(name); + Player *player = m_env->getPlayer(name); if(!player) return; SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg); @@ -4200,7 +4229,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id /* Try to get an existing player */ - Player *player = m_env.getPlayer(name); + Player *player = m_env->getPlayer(name); if(player != NULL) { // If player is already connected, cancel @@ -4230,7 +4259,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id /* If player with the wanted peer_id already exists, cancel. */ - if(m_env.getPlayer(peer_id) != NULL) + if(m_env->getPlayer(peer_id) != NULL) { infostream<<"emergePlayer(): Player with wrong name but same" " peer_id already exists"<getName()<<"\""<getServerMap()); player->setPosition(pos); @@ -4266,7 +4295,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id Add player to environment */ - m_env.addPlayer(player); + m_env->addPlayer(player); /* Add stuff to inventory @@ -4337,7 +4366,7 @@ void Server::handlePeerChange(PeerChange &c) { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); if(obj && obj->m_known_by_count > 0) obj->m_known_by_count--; @@ -4346,7 +4375,7 @@ void Server::handlePeerChange(PeerChange &c) // Collect information about leaving in chat std::wstring message; { - Player *player = m_env.getPlayer(c.peer_id); + Player *player = m_env->getPlayer(c.peer_id); if(player != NULL) { std::wstring name = narrow_to_wide(player->getName()); @@ -4360,12 +4389,12 @@ void Server::handlePeerChange(PeerChange &c) /*// Delete player { - m_env.removePlayer(c.peer_id); + m_env->removePlayer(c.peer_id); }*/ // Set player client disconnected { - Player *player = m_env.getPlayer(c.peer_id); + Player *player = m_env->getPlayer(c.peer_id); if(player != NULL) player->peer_id = 0; @@ -4384,7 +4413,7 @@ void Server::handlePeerChange(PeerChange &c) if(client->serialization_version == SER_FMT_VER_INVALID) continue; // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(!player) continue; // Get name of player diff --git a/src/server.h b/src/server.h index b238bec26..ab8c31a00 100644 --- a/src/server.h +++ b/src/server.h @@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "inventory.h" #include "auth.h" #include "ban.h" +struct LuaState; +typedef struct lua_State lua_State; /* Some random functions @@ -391,7 +393,7 @@ public: // Environment must be locked when called void setTimeOfDay(u32 time) { - m_env.setTimeOfDay(time); + m_env->setTimeOfDay(time); m_time_of_day_send_timer = 0; } @@ -476,6 +478,9 @@ public: // Envlock and conlock should be locked when calling this void notifyPlayer(const char *name, const std::wstring msg); void notifyPlayers(const std::wstring msg); + + // Envlock and conlock should be locked when using Lua + lua_State *getLua(){ return m_lua; } private: @@ -543,7 +548,7 @@ private: // When called, environment mutex should be locked std::string getPlayerName(u16 peer_id) { - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player == NULL) return "[id="+itos(peer_id); return player->getName(); @@ -582,7 +587,7 @@ private: // environment shall be locked first. // Environment - ServerEnvironment m_env; + ServerEnvironment *m_env; JMutex m_env_mutex; // Connection @@ -596,6 +601,10 @@ private: // Bann checking BanManager m_banmanager; + + // Scripting + // Envlock and conlock should be locked when using Lua + lua_State *m_lua; /* Threads diff --git a/src/serverobject.cpp b/src/serverobject.cpp index ce19ea34f..2a007bda5 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "inventory.h" -ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos): - ActiveObject(id), +ServerActiveObject::ServerActiveObject(ServerEnvironment *env, v3f pos): + ActiveObject(0), m_known_by_count(0), m_removed(false), m_pending_deactivation(false), @@ -37,6 +37,11 @@ ServerActiveObject::~ServerActiveObject() { } +void ServerActiveObject::addedToEnvironment(u16 id) +{ + setId(id); +} + ServerActiveObject* ServerActiveObject::create(u8 type, ServerEnvironment *env, u16 id, v3f pos, const std::string &data) @@ -53,7 +58,7 @@ ServerActiveObject* ServerActiveObject::create(u8 type, } Factory f = n->getValue(); - ServerActiveObject *object = (*f)(env, id, pos, data); + ServerActiveObject *object = (*f)(env, pos, data); return object; } diff --git a/src/serverobject.h b/src/serverobject.h index cbb50949c..8d6bfd6e8 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -51,9 +51,11 @@ public: NOTE: m_env can be NULL, but step() isn't called if it is. Prototypes are used that way. */ - ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos); + ServerActiveObject(ServerEnvironment *env, v3f pos); virtual ~ServerActiveObject(); + virtual void addedToEnvironment(u16 id); + // Create a certain type of ServerActiveObject static ServerActiveObject* create(u8 type, ServerEnvironment *env, u16 id, v3f pos, @@ -160,7 +162,7 @@ public: protected: // Used for creating objects based on type typedef ServerActiveObject* (*Factory) - (ServerEnvironment *env, u16 id, v3f pos, + (ServerEnvironment *env, v3f pos, const std::string &data); static void registerType(u16 type, Factory f);