Scripting WIP
authorPerttu Ahola <celeron55@gmail.com>
Fri, 11 Nov 2011 17:33:17 +0000 (19:33 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:38 +0000 (19:13 +0200)
22 files changed:
src/CMakeLists.txt
src/common_irrlicht.h
src/content_cao.cpp
src/content_cao.h
src/content_inventory.cpp
src/content_inventory.h
src/content_object.h
src/content_sao.cpp
src/content_sao.h
src/environment.cpp
src/environment.h
src/inventory.cpp
src/irrlichttypes.h [new file with mode: 0644]
src/porting.cpp
src/script.cpp [new file with mode: 0644]
src/script.h [new file with mode: 0644]
src/scriptapi.cpp [new file with mode: 0644]
src/scriptapi.h [new file with mode: 0644]
src/server.cpp
src/server.h
src/serverobject.cpp
src/serverobject.h

index f75c182bd0850476cd3e92ceb1139c1baa42ef2e..b41fc4a6cb5814cd42a534bd671081edda4d1160 100644 (file)
@@ -94,6 +94,8 @@ configure_file(
 )
 
 set(common_SRCS
+       scriptapi.cpp
+       script.cpp
        log.cpp
        content_sao.cpp
        mapgen.cpp
index f4c2f76ecec26ab4257e5d925fb17a22266c2632..379c2d15a6fb101279402c390bf0bcdd9ea4e204 100644 (file)
@@ -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 <irrTypes.h>
-#include <vector2d.h>
-#include <vector3d.h>
-#include <irrMap.h>
-#include <irrList.h>
-#include <irrArray.h>
-#include <aabbox3d.h>
+#include "irrlichttypes.h"
+
 #ifndef SERVER
 #include <SColor.h>
 #include <IMesh.h>
@@ -43,26 +38,6 @@ video::SColor(255,30,30,30));d->endScene();}
 #include <IGUIElement.h>
 #include <IGUIEnvironment.h>
 #endif
-using namespace irr;
-typedef core::vector3df v3f;
-typedef core::vector3d<s16> v3s16;
-typedef core::vector3d<s32> v3s32;
-
-typedef core::vector2d<f32> v2f;
-typedef core::vector2d<s16> v2s16;
-typedef core::vector2d<s32> v2s32;
-typedef core::vector2d<u32> v2u32;
-typedef core::vector2d<f32> v2f32;
-
-#ifdef _MSC_VER
-       // Windows
-       typedef unsigned long long u64;
-#else
-       // Posix
-       #include <stdint.h>
-       typedef uint64_t u64;
-       //typedef unsigned long long u64;
-#endif
 
 #endif
 
index 6cb2cee385f53b2112656f826c3ea5d0963af91a..157a51886493ba952c65f8f20146f717bee835fa 100644 (file)
@@ -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"<<std::endl;
+       std::istringstream is(data, std::ios::binary);
+       // command
+       u8 cmd = readU8(is);
+       if(cmd == 0)
+       {
+               // pos
+               m_position = readV3F1000(is);
+               updateNodePos();
+       }
+}
+
+void LuaEntityCAO::initialize(const std::string &data)
+{
+       infostream<<"LuaEntityCAO: Got init data"<<std::endl;
+       
+       {
+               std::istringstream is(data, std::ios::binary);
+               // version
+               u8 version = readU8(is);
+               // check version
+               if(version != 0)
+                       return;
+               // pos
+               m_position = readV3F1000(is);
+       }
+       
+       updateNodePos();
+}
+
+
index 963e1a4889aef425dd302546f5b81caa9a38453f..c8554e737cb0cc370823e37eee370eed7545091b 100644 (file)
@@ -376,6 +376,46 @@ private:
        Settings *m_properties;
 };
 
+/*
+       LuaEntityCAO
+*/
+
+class LuaEntityCAO : public ClientActiveObject
+{
+public:
+       LuaEntityCAO();
+       virtual ~LuaEntityCAO();
+       
+       u8 getType() const
+       {
+               return ACTIVEOBJECT_TYPE_LUAENTITY;
+       }
+       
+       static ClientActiveObject* create();
+
+       void addToScene(scene::ISceneManager *smgr);
+       void removeFromScene();
+       void updateLight(u8 light_at_pos);
+       v3s16 getLightPosition();
+       void updateNodePos();
+
+       void step(float dtime, ClientEnvironment *env);
+
+       void processMessage(const std::string &data);
+
+       void initialize(const std::string &data);
+       
+       core::aabbox3d<f32>* getSelectionBox()
+               {return &m_selection_box;}
+       v3f getPosition()
+               {return m_position;}
+
+private:
+       core::aabbox3d<f32> m_selection_box;
+       scene::IMeshSceneNode *m_node;
+       v3f m_position;
+};
+
 
 #endif
 
index 413ae8505276e349ae3f334b9bc6ce533cfb05da..1d5c6b35594214f483c5bbc981ec40eb8dc627a1 100644 (file)
@@ -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;
        }
 
index 91550bb9a42c0e46881337024bbf8b4d08be5351..9fd4cb03bd7114b21c4c01a82f4b162491a069eb 100644 (file)
@@ -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);
index a5fea716351de6b7667d7a6dc76f26273e1be485..f092b2789139f043c957860c31af13d640d3c453 100644 (file)
@@ -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
 
index f226371852c5ff22c2250e1fce75663487b06b68..d51e92a8c50738bafb9e6a83a8325df8f39c50e1 100644 (file)
@@ -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 \""
                        <<inventorystring<<"\""<<std::endl;
-       return new ItemSAO(env, id, pos, inventorystring);
+       return new ItemSAO(env, pos, inventorystring);
 }
 
 void ItemSAO::step(float dtime, bool send_recommended)
@@ -260,10 +260,10 @@ void ItemSAO::rightClick(Player *player)
 */
 
 // Prototype
-RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
+RatSAO proto_RatSAO(NULL, v3f(0,0,0));
 
-RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
-       ServerActiveObject(env, id, pos),
+RatSAO::RatSAO(ServerEnvironment *env, v3f pos):
+       ServerActiveObject(env, pos),
        m_is_active(false),
        m_speed_f(0,0,0)
 {
@@ -278,7 +278,7 @@ RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
        m_touching_ground = false;
 }
 
-ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
+ServerActiveObject* RatSAO::create(ServerEnvironment *env, v3f pos,
                const std::string &data)
 {
        std::istringstream is(data, std::ios::binary);
@@ -289,7 +289,7 @@ ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
        // check if version is supported
        if(version != 0)
                return NULL;
-       return new RatSAO(env, id, pos);
+       return new RatSAO(env, pos);
 }
 
 void RatSAO::step(float dtime, bool send_recommended)
@@ -447,10 +447,10 @@ InventoryItem* RatSAO::createPickedUpItem()
 */
 
 // Prototype
-Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
+Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0));
 
-Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
-       ServerActiveObject(env, id, pos),
+Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos):
+       ServerActiveObject(env, pos),
        m_is_active(false),
        m_speed_f(0,0,0)
 {
@@ -467,7 +467,7 @@ Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
        m_after_jump_timer = 0;
 }
 
-ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
+ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, v3f pos,
                const std::string &data)
 {
        std::istringstream is(data, std::ios::binary);
@@ -478,7 +478,7 @@ ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
        // check if version is supported
        if(version != 0)
                return NULL;
-       Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
+       Oerkki1SAO *o = new Oerkki1SAO(env, pos);
        o->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=\""<<name<<"\" state=\""
+                       <<state<<"\")"<<std::endl;
+       return new LuaEntitySAO(env, pos, name, state);
+}
+
+void LuaEntitySAO::step(float dtime, bool send_recommended)
+{
+       if(m_registered){
+               lua_State *L = m_env->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<<std::endl;
+       std::ostringstream os(std::ios::binary);
+       // version
+       writeU8(os, 0);
+       // name
+       os<<serializeString(m_init_name);
+       // state
+       std::string state = scriptapi_luaentity_get_state(L, m_id);
+       os<<serializeString(state);
+       return os.str();
+}
+
+
index f0ebf4f6fbe3b02822ba35d3e74f08b785835b84..44c0b7172c77d7c274bea18bb087d2e5db97cce4 100644 (file)
@@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class TestSAO : public ServerActiveObject
 {
 public:
-       TestSAO(ServerEnvironment *env, u16 id, v3f pos);
+       TestSAO(ServerEnvironment *env, v3f pos);
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_TEST;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        void step(float dtime, bool send_recommended);
 private:
@@ -40,11 +40,11 @@ private:
 class ItemSAO : public ServerActiveObject
 {
 public:
-       ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
+       ItemSAO(ServerEnvironment *env, v3f pos,
                        const std::string inventorystring);
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_ITEM;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData();
@@ -62,10 +62,10 @@ private:
 class RatSAO : public ServerActiveObject
 {
 public:
-       RatSAO(ServerEnvironment *env, u16 id, v3f pos);
+       RatSAO(ServerEnvironment *env, v3f pos);
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_RAT;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData();
@@ -87,10 +87,10 @@ private:
 class Oerkki1SAO : public ServerActiveObject
 {
 public:
-       Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
+       Oerkki1SAO(ServerEnvironment *env, v3f pos);
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_OERKKI1;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData();
@@ -119,10 +119,10 @@ private:
 class FireflySAO : public ServerActiveObject
 {
 public:
-       FireflySAO(ServerEnvironment *env, u16 id, v3f pos);
+       FireflySAO(ServerEnvironment *env, v3f pos);
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_FIREFLY;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        void step(float dtime, bool send_recommended);
        std::string getClientInitializationData();
@@ -146,12 +146,12 @@ class Settings;
 class MobV2SAO : public ServerActiveObject
 {
 public:
-       MobV2SAO(ServerEnvironment *env, u16 id, v3f pos,
+       MobV2SAO(ServerEnvironment *env, v3f pos,
                        Settings *init_properties);
        virtual ~MobV2SAO();
        u8 getType() const
                {return ACTIVEOBJECT_TYPE_MOBV2;}
-       static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
                        const std::string &data);
        std::string getStaticData();
        std::string getClientInitializationData();
@@ -195,5 +195,27 @@ private:
        Settings *m_properties;
 };
 
+struct LuaState;
+
+class LuaEntitySAO : public ServerActiveObject
+{
+public:
+       LuaEntitySAO(ServerEnvironment *env, v3f pos,
+                       const std::string &name, const std::string &state);
+       ~LuaEntitySAO();
+       u8 getType() const
+               {return ACTIVEOBJECT_TYPE_LUAENTITY;}
+       virtual void addedToEnvironment(u16 id);
+       static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
+                       const std::string &data);
+       void step(float dtime, bool send_recommended);
+       std::string getClientInitializationData();
+       std::string getStaticData();
+private:
+       std::string m_init_name;
+       std::string m_init_state;
+       bool m_registered;
+};
+
 #endif
 
index 80e9d5c78bc3eeadf3affabf6f57ff7a05588a77..d7a647ac841e927e10d1516a9d71592d617889ae 100644 (file)
@@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "log.h"
 #include "profiler.h"
+#include "scriptapi.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -267,9 +268,9 @@ void ActiveBlockList::update(core::list<v3s16> &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 "
                                                                                        <<PP(p1)<<std::endl;
                                                                        for(int j=0; j<3; j++){
                                                                                ServerActiveObject *obj = new RatSAO(
-                                                                                               this, 0, pos);
+                                                                                               this, pos);
                                                                                addActiveObject(obj);
                                                                        }
                                                                } else {
                                                                        actionstream<<"An oerkki spawns at "
                                                                                        <<PP(p1)<<std::endl;
                                                                        ServerActiveObject *obj = new Oerkki1SAO(
-                                                                                       this, 0, pos);
+                                                                                       this, pos);
                                                                        addActiveObject(obj);
                                                                }
                                                        }
@@ -1228,18 +1231,18 @@ void ServerEnvironment::step(float dtime)
                        Create a ServerActiveObject
                */
 
-               //TestSAO *obj = new TestSAO(this, 0, pos);
-               //ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
-               //ServerActiveObject *obj = new RatSAO(this, 0, pos);
-               //ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
-               //ServerActiveObject *obj = new FireflySAO(this, 0, pos);
+               //TestSAO *obj = new TestSAO(this, pos);
+               //ServerActiveObject *obj = new ItemSAO(this, pos, "CraftItem Stick 1");
+               //ServerActiveObject *obj = new RatSAO(this, pos);
+               //ServerActiveObject *obj = new Oerkki1SAO(this, pos);
+               //ServerActiveObject *obj = new FireflySAO(this, pos);
 
                infostream<<"Server: Spawning MobV2SAO at "
                                <<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl;
                
                Settings properties;
                getMob_dungeon_master(properties);
-               ServerActiveObject *obj = new MobV2SAO(this, 0, pos, &properties);
+               ServerActiveObject *obj = new MobV2SAO(this, pos, &properties);
                addActiveObject(obj);
        }
 #endif
@@ -1493,6 +1496,11 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
                                <<"could not find block for storing id="<<object->getId()
                                <<" statically"<<std::endl;
        }
+       
+       // Post-initialize object
+       object->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="<<id<<" is not known by clients"
                                <<"; deleting"<<std::endl;
+
+               // Deregister in scripting api
+               scriptapi_rm_object_reference(m_lua, obj);
+
                // Delete active object
                delete obj;
                // Id to be removed from m_active_objects
index 5d2fe55515d785e83399199f49b624f2686c09fa..0e0a5510e960120d12fe5f8b6f9a33964fc6ba4f 100644 (file)
@@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class Server;
 class ActiveBlockModifier;
 class ServerActiveObject;
+typedef struct lua_State lua_State;
 
 class Environment
 {
@@ -126,7 +127,7 @@ private:
 class ServerEnvironment : public Environment
 {
 public:
-       ServerEnvironment(ServerMap *map, Server *server);
+       ServerEnvironment(ServerMap *map, lua_State *L);
        ~ServerEnvironment();
 
        Map & getMap()
@@ -139,13 +140,11 @@ public:
                return *m_map;
        }
 
-       Server * getServer()
+       lua_State* getLua()
        {
-               return m_server;
+               return m_lua;
        }
 
-       void step(f32 dtime);
-       
        /*
                Save players
        */
@@ -222,7 +221,9 @@ public:
        
        // Clear all objects, loading and going through every MapBlock
        void clearAllObjects();
-
+       
+       void step(f32 dtime);
+       
 private:
 
        /*
@@ -269,8 +270,8 @@ private:
        
        // The map
        ServerMap *m_map;
-       // Pointer to server (which is handling this environment)
-       Server *m_server;
+       // Lua state
+       lua_State *m_lua;
        // Active object list
        core::map<u16, ServerActiveObject*> m_active_objects;
        // Outgoing network message buffer for active objects
index 92ef3b011f708c5fbb744d90355b3172093c9919..5d4a6e4089e09f967025e637c36ae5dcfe18960d 100644 (file)
@@ -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 (file)
index 0000000..7ab83bb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <irrTypes.h>
+#include <vector2d.h>
+#include <vector3d.h>
+#include <irrMap.h>
+#include <irrList.h>
+#include <irrArray.h>
+#include <aabbox3d.h>
+using namespace irr;
+typedef core::vector3df v3f;
+typedef core::vector3d<s16> v3s16;
+typedef core::vector3d<s32> v3s32;
+
+typedef core::vector2d<f32> v2f;
+typedef core::vector2d<s16> v2s16;
+typedef core::vector2d<s32> v2s32;
+typedef core::vector2d<u32> v2u32;
+typedef core::vector2d<f32> v2f32;
+
+#ifdef _MSC_VER
+       // Windows
+       typedef unsigned long long u64;
+#else
+       // Posix
+       #include <stdint.h>
+       typedef uint64_t u64;
+       //typedef unsigned long long u64;
+#endif
+
+#endif
+
index 00595b06ca0c8ce0dd922c8f0283fbbb37f47cde..0adc955a94f77b28861a5bd8b4c00e118feeab09 100644 (file)
@@ -56,9 +56,10 @@ void sigint_handler(int sig)
                dstream<<DTIME<<"INFO: sigint_handler(): "
                                <<"Ctrl-C pressed, shutting down."<<std::endl;
                
-               dstream<<DTIME<<"INFO: sigint_handler(): "
+               // Comment out for less clutter when testing scripts
+               /*dstream<<DTIME<<"INFO: sigint_handler(): "
                                <<"Printing debug stacks"<<std::endl;
-               debug_stacks_print();
+               debug_stacks_print();*/
 
                g_killed = true;
        }
@@ -91,9 +92,10 @@ void signal_handler_init(void)
                        {
                                dstream<<DTIME<<"INFO: event_handler(): "
                                                <<"Ctrl+C, Close Event, Logoff Event or Shutdown Event, shutting down."<<std::endl;
-                               dstream<<DTIME<<"INFO: event_handler(): "
+                               // Comment out for less clutter when testing scripts
+                               /*dstream<<DTIME<<"INFO: event_handler(): "
                                                <<"Printing debug stacks"<<std::endl;
-                               debug_stacks_print();
+                               debug_stacks_print();*/
 
                                g_killed = true;
                        }
diff --git a/src/script.cpp b/src/script.cpp
new file mode 100644 (file)
index 0000000..edfc596
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <cstdarg>
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include "log.h"
+#include <iostream>
+
+extern "C" {
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+}
+
+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 "<<path<<std::endl;
+       int ret = luaL_loadfile(L, path) || lua_pcall(L, 0, 0, 0);
+       if(ret){
+               errorstream<<"Failed to load and run script from "<<path<<": "<<lua_tostring(L, -1)<<std::endl;
+               lua_pop(L, 1); // Pop error message from stack
+               return false;
+       }
+       return true;
+}
+
+lua_State* script_init()
+{
+       lua_State *L = luaL_newstate();
+       luaL_openlibs(L);
+       return L;
+}
+
+lua_State* script_deinit(lua_State *L)
+{
+       lua_close(L);
+}
+
+
diff --git a/src/script.h b/src/script.h
new file mode 100644 (file)
index 0000000..8225474
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <string>
+
+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 (file)
index 0000000..fbe3830
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <iostream>
+extern "C" {
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+}
+
+#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<<"\""<<lua_tostring(L, i)<<"\"";
+               break;
+
+         case LUA_TBOOLEAN:  /* booleans */
+               o<<(lua_toboolean(L, i) ? "true" : "false");
+               break;
+
+         case LUA_TNUMBER:  /* numbers */ {
+               char buf[10];
+               snprintf(buf, 10, "%g", lua_tonumber(L, i));
+               o<<buf;
+               break; }
+
+         default:  /* other values */
+               o<<lua_typename(L, t);
+               break;
+
+       }
+       o<<" ";
+  }
+  o<<std::endl;
+}
+
+static void realitycheck(lua_State *L)
+{
+       int top = lua_gettop(L);
+       if(top >= 30){
+               dstream<<"Stack is over 30:"<<std::endl;
+               stackDump(L, dstream);
+               script_error(L, "Stack is over 30 (reality check)");
+       }
+}
+
+// Register new object prototype (must be based on entity)
+static int l_register_object(lua_State *L)
+{
+       const char *name = luaL_checkstring(L, 1);
+       luaL_checkany(L, 2);
+       infostream<<"register_object: "<<name<<std::endl;
+       // Get the minetest table
+       lua_getglobal(L, "minetest");
+       // Get field "registered_objects"
+       lua_getfield(L, -1, "registered_objects");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       // Object is in param 2
+       lua_pushvalue(L, 2); // Copy object to top of stack
+       lua_setfield(L, objectstable, name); // registered_objects[name] = object
+
+       return 0; /* number of results */
+}
+
+static int l_new_entity(lua_State *L)
+{
+       /* o = o or {}
+          setmetatable(o, self)
+          self.__index = self
+          return o */
+       if(lua_isnil(L, -1))
+               lua_newtable(L);
+       luaL_checktype(L, -1, LUA_TTABLE);
+       luaL_getmetatable(L, "minetest.entity");
+       lua_pushvalue(L, -1); // duplicate metatable
+       lua_setfield(L, -2, "__index");
+       lua_setmetatable(L, -2);
+       // return table
+       return 1;
+}
+
+static const struct luaL_Reg minetest_f [] = {
+       {"register_object", l_register_object},
+       {"new_entity", l_new_entity},
+       {NULL, NULL}
+};
+
+static int l_entity_set_deleted(lua_State *L)
+{
+       return 0;
+}
+
+static const struct luaL_Reg minetest_entity_m [] = {
+       {"set_deleted", l_entity_set_deleted},
+       {NULL, NULL}
+};
+
+class ObjectRef
+{
+private:
+       ServerActiveObject *m_object;
+
+       static const char className[];
+       static const luaL_reg methods[];
+
+       static ObjectRef *checkobject(lua_State *L, int narg)
+       {
+               luaL_checktype(L, narg, LUA_TUSERDATA);
+               void *ud = luaL_checkudata(L, narg, className);
+               if(!ud) luaL_typerror(L, narg, className);
+               return *(ObjectRef**)ud;  // unbox pointer
+       }
+       
+       // Exported functions
+
+       static int l_remove(lua_State *L)
+       {
+               ObjectRef *o = checkobject(L, 1);
+               ServerActiveObject *co = o->m_object;
+               if(co == NULL) return 0;
+               infostream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
+               co->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="<<o<<std::endl;
+               delete o;
+               return 0;
+       }
+
+public:
+       ObjectRef(ServerActiveObject *object):
+               m_object(object)
+       {
+               infostream<<"ObjectRef created for id="<<m_object->getId()<<std::endl;
+       }
+
+       ~ObjectRef()
+       {
+               if(m_object)
+                       infostream<<"ObjectRef destructing for id="<<m_object->getId()<<std::endl;
+               else
+                       infostream<<"ObjectRef destructing for id=unknown"<<std::endl;
+       }
+
+       // Creates an ObjectRef and leaves it on top of stack
+       // Not callable from Lua; all references are created on the C side.
+       static void create(lua_State *L, ServerActiveObject *object)
+       {
+               ObjectRef *o = new ObjectRef(object);
+               //infostream<<"ObjectRef::create: o="<<o<<std::endl;
+               *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+               luaL_getmetatable(L, className);
+               lua_setmetatable(L, -2);
+       }
+
+       static void set_null(lua_State *L)
+       {
+               ObjectRef *o = checkobject(L, -1);
+               ServerActiveObject *co = o->m_object;
+               if(co == NULL)
+                       return;
+               o->m_object = NULL;
+       }
+       
+       static void Register(lua_State *L)
+       {
+               lua_newtable(L);
+               int methodtable = lua_gettop(L);
+               luaL_newmetatable(L, className);
+               int metatable = lua_gettop(L);
+
+               lua_pushliteral(L, "__metatable");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
+
+               lua_pushliteral(L, "__index");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);
+
+               lua_pushliteral(L, "__gc");
+               lua_pushcfunction(L, gc_object);
+               lua_settable(L, metatable);
+
+               lua_pop(L, 1);  // drop metatable
+
+               luaL_openlib(L, 0, methods, 0);  // fill methodtable
+               lua_pop(L, 1);  // drop methodtable
+
+               // Cannot be created from Lua
+               //lua_register(L, className, create_object);
+       }
+};
+
+const char ObjectRef::className[] = "ObjectRef";
+
+#define method(class, name) {#name, class::l_##name}
+
+const luaL_reg ObjectRef::methods[] = {
+       method(ObjectRef, remove),
+       {0,0}
+};
+
+void scriptapi_export(lua_State *L, Server *server)
+{
+       realitycheck(L);
+       assert(lua_checkstack(L, 20));
+       infostream<<"scriptapi_export"<<std::endl;
+       
+       // Register global functions in table minetest
+       lua_newtable(L);
+       luaL_register(L, NULL, minetest_f);
+       lua_setglobal(L, "minetest");
+       
+       // Get the main minetest table
+       lua_getglobal(L, "minetest");
+
+       // Add registered_objects table in minetest
+       lua_newtable(L);
+       lua_setfield(L, -2, "registered_objects");
+
+       // Add object_refs table in minetest
+       lua_newtable(L);
+       lua_setfield(L, -2, "object_refs");
+
+       // Add luaentities table in minetest
+       lua_newtable(L);
+       lua_setfield(L, -2, "luaentities");
+
+       // Load and run some base Lua stuff
+       /*script_load(L, (porting::path_data + DIR_DELIM + "scripts"
+                       + DIR_DELIM + "base.lua").c_str());*/
+       
+       // Create entity reference metatable
+       luaL_newmetatable(L, "minetest.entity_reference");
+       lua_pop(L, 1);
+       
+       // Create entity prototype
+       luaL_newmetatable(L, "minetest.entity");
+       // metatable.__index = metatable
+       lua_pushvalue(L, -1); // Duplicate metatable
+       lua_setfield(L, -2, "__index");
+       // Put functions in metatable
+       luaL_register(L, NULL, minetest_entity_m);
+       // Put other stuff in metatable
+
+       // Entity C reference
+       ObjectRef::Register(L);
+}
+
+void scriptapi_luaentity_register(lua_State *L, u16 id, const char *name,
+               const char *init_state)
+{
+       realitycheck(L);
+       assert(lua_checkstack(L, 20));
+       infostream<<"scriptapi_luaentity_register: id="<<id<<std::endl;
+       
+       // Create object as a dummy string (TODO: Create properly)
+       lua_pushstring(L, "dummy object string");
+       int object = lua_gettop(L);
+
+       // Get minetest.luaentities table
+       lua_getglobal(L, "minetest");
+       lua_getfield(L, -1, "luaentities");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       
+       // luaentities[id] = object
+       lua_pushnumber(L, id); // Push id
+       lua_pushvalue(L, object); // Copy object to top of stack
+       lua_settable(L, objectstable);
+       
+       lua_pop(L, 3); // pop luaentities, minetest and the object
+}
+
+void scriptapi_luaentity_deregister(lua_State *L, u16 id)
+{
+       realitycheck(L);
+       assert(lua_checkstack(L, 20));
+       infostream<<"scriptapi_luaentity_deregister: id="<<id<<std::endl;
+
+       // Get minetest.luaentities table
+       lua_getglobal(L, "minetest");
+       lua_getfield(L, -1, "luaentities");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       
+       /*// Get luaentities[id]
+       lua_pushnumber(L, cobj->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="<<id<<std::endl;
+
+       // Get minetest.luaentities table
+       lua_getglobal(L, "minetest");
+       lua_getfield(L, -1, "luaentities");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       
+       // Get luaentities[id]
+       lua_pushnumber(L, cobj->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="<<id<<std::endl;
+       
+       return "";
+}
+
+void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
+{
+       realitycheck(L);
+       assert(lua_checkstack(L, 20));
+       infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
+
+       // Create object on stack
+       ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
+       int object = lua_gettop(L);
+
+       // Get minetest.object_refs table
+       lua_getglobal(L, "minetest");
+       lua_getfield(L, -1, "object_refs");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       
+       // object_refs[id] = object
+       lua_pushnumber(L, cobj->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="<<cobj->getId()<<std::endl;
+
+       // Get minetest.object_refs table
+       lua_getglobal(L, "minetest");
+       lua_getfield(L, -1, "object_refs");
+       luaL_checktype(L, -1, LUA_TTABLE);
+       int objectstable = lua_gettop(L);
+       
+       // Get object_refs[id]
+       lua_pushnumber(L, cobj->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 (file)
index 0000000..a97d707
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+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 <string>
+
+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
+
index e7cfc9afcfd363ede0e57db66d75e6ded7ef6df5..1c5d8d937b070c5943abf23e311cb7e9fc146106 100644 (file)
@@ -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()
                                        <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
                                        <<"only_from_disk="<<only_from_disk<<std::endl;
                
-               ServerMap &map = ((ServerMap&)m_server->m_env.getMap());
+               ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
                        
                //core::map<v3s16, MapBlock*> changed_blocks;
                //core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
@@ -250,7 +252,7 @@ void * EmergeThread::Thread()
                                        MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
                                        
                                        // Activate objects and stuff
-                                       m_server->m_env.activateBlock(block, 3600);
+                                       m_server->m_env->activateBlock(block, 3600);
                                }
                        }
                        else
@@ -371,7 +373,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
        //TimeTaker timer("RemoteClient::GetNextBlocks");
        
-       Player *player = server->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<Player*> players = server->m_env.getPlayers(true);
+       core::list<Player*> 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"<<std::endl;
+       m_lua = script_init();
+       assert(m_lua);
+       // Export API
+       scriptapi_export(m_lua, this);
+       // Load and run scripts
+       script_load(m_lua, (porting::path_data + DIR_DELIM + "scripts"
+                       + DIR_DELIM + "default.lua").c_str());
+       
+       // Initialize Environment
+       
+       m_env = new ServerEnvironment(new ServerMap(mapsavedir), m_lua);
        
        // Register us to receive map edit events
-       m_env.getMap().addEventReceiver(this);
+       m_env->getMap().addEventReceiver(this);
 
        // If file exists, load environment metadata
        if(fs::PathExists(m_mapsavedir+DIR_DELIM+"env_meta.txt"))
        {
                infostream<<"Server: Loading environment metadata"<<std::endl;
-               m_env.loadMeta(m_mapsavedir);
+               m_env->loadMeta(m_mapsavedir);
        }
 
        // Load players
        infostream<<"Server: Loading players"<<std::endl;
-       m_env.deSerializePlayers(m_mapsavedir);
+       m_env->deSerializePlayers(m_mapsavedir);
 }
 
 Server::~Server()
@@ -1029,13 +1051,13 @@ Server::~Server()
                        Save players
                */
                infostream<<"Server: Saving players"<<std::endl;
-               m_env.serializePlayers(m_mapsavedir);
+               m_env->serializePlayers(m_mapsavedir);
 
                /*
                        Save environment metadata
                */
                infostream<<"Server: Saving environment metadata"<<std::endl;
-               m_env.saveMeta(m_mapsavedir);
+               m_env->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"<<std::endl;
+       script_deinit(m_lua);
 }
 
 void Server::start(unsigned short port)
@@ -1173,7 +1202,7 @@ void Server::AsyncRunStep()
                u32 units = (u32)(m_time_counter*speed);
                m_time_counter -= (f32)units / speed;
                
-               m_env.setTimeOfDay((m_env.getTimeOfDay() + units) % 24000);
+               m_env->setTimeOfDay((m_env->getTimeOfDay() + units) % 24000);
                
                //infostream<<"Server: m_time_of_day = "<<m_time_of_day.get()<<std::endl;
 
@@ -1194,10 +1223,10 @@ 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);
                                
                                SharedBuffer<u8> 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<v3s16, MapBlock*> modified_blocks;
-               m_env.getMap().transformLiquids(modified_blocks);
+               m_env->getMap().transformLiquids(modified_blocks);
 #if 0          
                /*
                        Update lighting
                */
                core::map<v3s16, MapBlock*> 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<<"* "<<player->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<u16, bool> removed_objects;
                        core::map<u16, bool> 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<u16>::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."<<std::endl;
 
-               m_env.removePlayer(peer_id);*/
+               m_env->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<u8> 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 "<<PP(p_over)<<std::endl;
                                
                                        // Add the object to the environment
-                                       m_env.addActiveObject(obj);
+                                       m_env->addActiveObject(obj);
                                        
                                        infostream<<"Placed object"<<std::endl;
 
@@ -2924,7 +2953,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        text += (char)buf[0];
                }
 
-               NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+               NodeMetadata *meta = m_env->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 "<<PP(p)<<std::endl;
                                
                v3s16 blockpos = getNodeBlockPos(p);
-               MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos);
+               MapBlock *block = m_env->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 ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
@@ -3389,7 +3418,7 @@ void Server::inventoryModified(InventoryContext *c, std::string id)
                p.Z = stoi(fn.next(","));
                v3s16 blockpos = getNodeBlockPos(p);
 
-               NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+               NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
                if(meta)
                        meta->inventoryModified();
 
@@ -3415,7 +3444,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
        
        core::list<PlayerInfo> list;
 
-       core::list<Player*> players = m_env.getPlayers();
+       core::list<Player*> players = m_env->getPlayers();
        
        core::list<Player*>::Iterator i;
        for(i = players.begin();
@@ -3559,7 +3588,7 @@ void Server::SendPlayerInfos()
        //JMutexAutoLock envlock(m_env_mutex);
        
        // Get connected players
-       core::list<Player*> players = m_env.getPlayers(true);
+       core::list<Player*> 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<Player *> players = m_env.getPlayers(true);
+       core::list<Player *> 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<<name<<L",";
        }
        os<<L"}";
-       if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
+       if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
                os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
        if(g_settings->get("motd") != "")
                os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->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"<<std::endl;
@@ -4258,7 +4287,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id
                infostream<<"Server: Finding spawn place for player \""
                                <<player->getName()<<"\""<<std::endl;
 
-               v3f pos = findSpawnPos(m_env.getServerMap());
+               v3f pos = findSpawnPos(m_env->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
index b238bec26e86029b191c03101ce776808d4fb6f0..ab8c31a00a0a57186692d91eba573269d64874c1 100644 (file)
@@ -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
index ce19ea34f10a85d7b46aa1a8038e0dde24b7d777..2a007bda5a7d8e0795cae4524cba6fbbacd01d6a 100644 (file)
@@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <fstream>
 #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;
 }
 
index cbb50949cf8a4ff0064098fd03cbed5d98d47245..8d6bfd6e8b5982264e0056b200c9c758fd10c273 100644 (file)
@@ -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);