]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/mapblockobject.cpp
comments
[dragonfireclient.git] / src / mapblockobject.cpp
index 3a28e2250eef5c602de77f51706262e8627be15a..ab12afc8e12a75aad035c6524668ea843551167c 100644 (file)
@@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock.h"
 // Only for ::getNodeBox, TODO: Get rid of this
 #include "map.h"
+#include "inventory.h"
+#include "irrlichtwrapper.h"
 
 /*
        MapBlockObject
@@ -46,6 +48,17 @@ void MapBlockObject::setBlockChanged()
 /*
        MovingObject
 */
+
+v3f MovingObject::getAbsoluteShowPos()
+{
+       if(m_block == NULL)
+               return m_pos;
+       
+       // getPosRelative gets nodepos relative to map origin
+       v3f blockpos = intToFloat(m_block->getPosRelative());
+       return blockpos + m_showpos;
+}
+
 void MovingObject::move(float dtime, v3f acceleration)
 {
        DSTACK("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
@@ -97,7 +110,7 @@ void MovingObject::move(float dtime, v3f acceleration)
        float speedlength = m_speed.getLength();
        f32 dtime_max_increment;
        if(fabs(speedlength) > 0.001)
-               dtime_max_increment = 0.1*BS / speedlength;
+               dtime_max_increment = 0.05*BS / speedlength;
        else
                dtime_max_increment = 0.5;
        
@@ -145,20 +158,20 @@ void MovingObject::move(float dtime, v3f acceleration)
                for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
                {
                        try{
-                               if(material_walkable(m_block->getNodeParent(v3s16(x,y,z)).d)
+                               if(content_walkable(m_block->getNodeParent(v3s16(x,y,z)).d)
                                                == false)
                                        continue;
                        }
                        catch(InvalidPositionException &e)
                        {
-                               // Doing nothing here will block the player from
+                               // Doing nothing here will block the object from
                                // walking over map borders
                        }
 
                        core::aabbox3d<f32> nodebox = Map::getNodeBox(
                                        v3s16(x,y,z));
                        
-                       // See if the player is touching ground
+                       // See if the object is touching ground
                        if(
                                        fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d
                                        && nodebox.MaxEdge.X-d > objectbox.MinEdge.X
@@ -227,6 +240,219 @@ void MovingObject::move(float dtime, v3f acceleration)
        m_pos = position;
 }
 
+void MovingObject::simpleMove(float dtime)
+{
+       m_pos_animation_time_counter += dtime;
+       m_pos_animation_counter += dtime;
+       v3f movevector = m_pos - m_oldpos;
+       f32 moveratio;
+       if(m_pos_animation_time < 0.001)
+               moveratio = 1.0;
+       else
+               moveratio = m_pos_animation_counter / m_pos_animation_time;
+       if(moveratio > 1.5)
+               moveratio = 1.5;
+       m_showpos = m_oldpos + movevector * moveratio;
+}
+
+#ifndef SERVER
+/*
+       RatObject
+*/
+void RatObject::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),
+       };
+       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, driver->getTexture(porting::getDataPath("rat.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();
+       updateNodePos();
+}
+#endif
+
+/*
+       ItemObject
+*/
+#ifndef SERVER
+void ItemObject::addToScene(scene::ISceneManager *smgr)
+{
+       if(m_node != NULL)
+               return;
+       
+       //video::IVideoDriver* driver = smgr->getVideoDriver();
+       
+       // Get image of item for showing
+       video::ITexture *texture = getItemImage();
+
+       /*
+               Create a mesh
+       */
+
+       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/2,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
+               video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
+               video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
+               video::S3DVertex(BS/3,-BS/2+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, texture);
+       buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+       buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+       buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       m_node = smgr->addMeshSceneNode(mesh, NULL);
+       // Set it to use the materials of the meshbuffers directly.
+       // This is needed for changing the texture in the future
+       ((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
+       mesh->drop();
+
+       updateSceneNode();
+}
+
+video::ITexture * ItemObject::getItemImage()
+{
+       /*
+               Create an inventory item to see what is its image
+       */
+       video::ITexture *texture = NULL;
+       InventoryItem *item = createInventoryItem();
+       if(item)
+               texture = item->getImage();
+       /*else
+               texture = g_irrlicht->getTexture(porting::getDataPath("cloud.png").c_str());*/
+       if(item)
+               delete item;
+       return texture;
+}
+
+#endif
+
+InventoryItem * ItemObject::createInventoryItem()
+{
+       try{
+               std::istringstream is(m_itemstring, std::ios_base::binary);
+               InventoryItem *item = InventoryItem::deSerialize(is);
+               dstream<<__FUNCTION_NAME<<": m_itemstring=\""
+                               <<m_itemstring<<"\" -> item="<<item
+                               <<std::endl;
+               return item;
+       }
+       catch(SerializationError &e)
+       {
+               dstream<<__FUNCTION_NAME<<": serialization error: "
+                               <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
+               return NULL;
+       }
+}
+
+/*
+       PlayerObject
+*/
+#ifndef SERVER
+void PlayerObject::addToScene(scene::ISceneManager *smgr)
+{
+       if(m_node != NULL)
+               return;
+       
+       video::IVideoDriver* driver = smgr->getVideoDriver();
+
+       // Attach a simple mesh to the player for showing an image
+       scene::SMesh *mesh = new scene::SMesh();
+       { // Front
+       scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+       video::SColor c(255,255,255,255);
+       video::S3DVertex vertices[4] =
+       {
+               video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
+               video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
+               video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
+               video::S3DVertex(-BS/2,BS*2,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, driver->getTexture(porting::getDataPath("player.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;
+       buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       { // Back
+       scene::IMeshBuffer *buf = new scene::SMeshBuffer();
+       video::SColor c(255,255,255,255);
+       video::S3DVertex vertices[4] =
+       {
+               video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
+               video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
+               video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
+               video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,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, driver->getTexture(porting::getDataPath("player_back.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_REF;
+       // Add to mesh
+       mesh->addMeshBuffer(buf);
+       buf->drop();
+       }
+       
+       m_node = smgr->addMeshSceneNode(mesh, NULL);
+       mesh->drop();
+       updateNodePos();
+}
+#endif
+
 /*
        MapBlockObjectList
 */
@@ -265,7 +491,7 @@ void MapBlockObjectList::serialize(std::ostream &os, u8 version)
 }
 
 void MapBlockObjectList::update(std::istream &is, u8 version,
-               scene::ISceneManager *smgr)
+               scene::ISceneManager *smgr, u32 daynight_ratio)
 {
        JMutexAutoLock lock(m_mutex);
 
@@ -339,17 +565,7 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                                        " id="<<id
                                        <<std::endl;*/
 
-                       if(type_id == MAPBLOCKOBJECT_TYPE_TEST)
-                       {
-                               // The constructors of objects shouldn't need
-                               // any more parameters than this.
-                               obj = new TestObject(m_block, id, pos);
-                       }
-                       else if(type_id == MAPBLOCKOBJECT_TYPE_TEST2)
-                       {
-                               obj = new Test2Object(m_block, id, pos);
-                       }
-                       else if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
+                       if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
                        {
                                obj = new SignObject(m_block, id, pos);
                        }
@@ -357,13 +573,20 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                        {
                                obj = new RatObject(m_block, id, pos);
                        }
+                       else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
+                       {
+                               obj = new ItemObject(m_block, id, pos);
+                       }
                        else
                        {
+                               // This is fatal because we cannot know the length
+                               // of the object's data
                                throw SerializationError
                                ("MapBlockObjectList::update(): Unknown MapBlockObject type");
                        }
 
                        if(smgr != NULL)
+                               //obj->addToScene(smgr, daynight_ratio);
                                obj->addToScene(smgr);
 
                        n->setValue(obj);
@@ -372,6 +595,11 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                {
                        obj = n->getValue();
                        obj->updatePos(pos);
+                       /*if(daynight_ratio != m_last_update_daynight_ratio)
+                       {
+                               obj->removeFromScene();
+                               obj->addToScene(smgr, daynight_ratio);
+                       }*/
                }
 
                // Now there is an object in obj.
@@ -379,6 +607,21 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                
                obj->update(is, version);
                
+               /*
+                       Update light on client
+               */
+               if(smgr != NULL)
+               {
+                       u8 light = LIGHT_MAX;
+                       try{
+                               v3s16 relpos_i = floatToInt(obj->m_pos);
+                               MapNode n = m_block->getNodeParent(relpos_i);
+                               light = n.getLightBlend(daynight_ratio);
+                       }
+                       catch(InvalidPositionException &e) {}
+                       obj->updateLight(light);
+               }
+               
                // Remove from deletion list
                if(ids_to_delete.find(id) != NULL)
                        ids_to_delete.remove(id);
@@ -400,6 +643,8 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
                delete obj;
                m_objects.remove(id);
        }
+
+       m_last_update_daynight_ratio = daynight_ratio;
 }
 
 s16 MapBlockObjectList::getFreeId() throw(ContainerFullException)
@@ -502,7 +747,7 @@ MapBlockObject * MapBlockObjectList::get(s16 id)
                return n->getValue();
 }
 
-void MapBlockObjectList::step(float dtime, bool server)
+void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
 {
        DSTACK(__FUNCTION_NAME);
        
@@ -524,7 +769,17 @@ void MapBlockObjectList::step(float dtime, bool server)
 
                        if(server)
                        {
-                               bool to_delete = obj->serverStep(dtime);
+                               // Update light
+                               u8 light = LIGHT_MAX;
+                               try{
+                                       v3s16 relpos_i = floatToInt(obj->m_pos);
+                                       MapNode n = m_block->getNodeParent(relpos_i);
+                                       light = n.getLightBlend(daynight_ratio);
+                               }
+                               catch(InvalidPositionException &e) {}
+                               obj->updateLight(light);
+                               
+                               bool to_delete = obj->serverStep(dtime, daynight_ratio);
 
                                if(to_delete)
                                        ids_to_delete.insert(obj->m_id, true);
@@ -679,7 +934,7 @@ void MapBlockObjectList::getObjects(v3f origin, f32 max_d,
        {
                MapBlockObject *obj = i.getNode()->getValue();
 
-               f32 d = (obj->m_pos - origin).getLength();
+               f32 d = (obj->getRelativeShowPos() - origin).getLength();
 
                if(d > max_d)
                        continue;