Server should use the same eye position as the client
[oweals/minetest.git] / src / mapblock.cpp
index 2f6a4b850116522e8bd98c855f91819425ae8ec4..44ca75ff0b794ab66393c8329ab70ffd9b153de3 100644 (file)
@@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        MapBlock
 */
 
-MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
+MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
                m_parent(parent),
                m_pos(pos),
                m_modified(MOD_STATE_WRITE_NEEDED),
@@ -38,7 +38,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
                m_generated(false),
                m_objects(this),
                m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
-               m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED)
+               m_usage_timer(0)
 {
        data = NULL;
        if(dummy == false)
@@ -242,7 +242,12 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
                        // Check if node above block has sunlight
                        try{
                                MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
-                               if(n.d == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
+                               if(n.getContent() == CONTENT_IGNORE)
+                               {
+                                       // Trust heuristics
+                                       no_sunlight = is_underground;
+                               }
+                               else if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
                                {
                                        no_sunlight = true;
                                }
@@ -260,8 +265,8 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
                                else
                                {
                                        MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z));
-                                       //if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE)
-                                       if(content_features(n.d).sunlight_propagates == false)
+                                       //if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
+                                       if(content_features(n).sunlight_propagates == false)
                                        {
                                                no_sunlight = true;
                                        }
@@ -322,14 +327,14 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
                                                bool upper_is_air = false;
                                                try
                                                {
-                                                       if(getNodeParent(pos+v3s16(0,1,0)).d == CONTENT_AIR)
+                                                       if(getNodeParent(pos+v3s16(0,1,0)).getContent() == CONTENT_AIR)
                                                                upper_is_air = true;
                                                }
                                                catch(InvalidPositionException &e)
                                                {
                                                }
                                                // Turn mud into grass
-                                               if(upper_is_air && n.d == CONTENT_MUD
+                                               if(upper_is_air && n.getContent() == CONTENT_MUD
                                                                && current_light == LIGHT_SUN)
                                                {
                                                        n.d = CONTENT_GRASS;
@@ -473,7 +478,7 @@ void MapBlock::updateDayNightDiff()
                for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
                {
                        MapNode &n = data[i];
-                       if(n.d != CONTENT_AIR)
+                       if(n.getContent() != CONTENT_AIR)
                        {
                                only_air = false;
                                break;
@@ -496,8 +501,8 @@ s16 MapBlock::getGroundLevel(v2s16 p2d)
                s16 y = MAP_BLOCKSIZE-1;
                for(; y>=0; y--)
                {
-                       //if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d))
-                       if(content_features(getNodeRef(p2d.X, y, p2d.Y).d).walkable)
+                       MapNode n = getNodeRef(p2d.X, y, p2d.Y);
+                       if(content_features(n).walkable)
                        {
                                if(y == MAP_BLOCKSIZE-1)
                                        return -2;
@@ -560,7 +565,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
                SharedBuffer<u8> materialdata(nodecount);
                for(u32 i=0; i<nodecount; i++)
                {
-                       materialdata[i] = data[i].d;
+                       materialdata[i] = data[i].param0;
                }
                compress(materialdata, os, version);
 
@@ -568,7 +573,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
                SharedBuffer<u8> lightdata(nodecount);
                for(u32 i=0; i<nodecount; i++)
                {
-                       lightdata[i] = data[i].param;
+                       lightdata[i] = data[i].param1;
                }
                compress(lightdata, os, version);
                
@@ -607,24 +612,20 @@ void MapBlock::serialize(std::ostream &os, u8 version)
                        Get data
                */
 
-               SharedBuffer<u8> databuf(nodecount*3);
-
-               // Get contents
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       databuf[i] = data[i].d;
-               }
-
-               // Get params
+               // Serialize nodes
+               SharedBuffer<u8> databuf_nodelist(nodecount*3);
                for(u32 i=0; i<nodecount; i++)
                {
-                       databuf[i+nodecount] = data[i].param;
+                       data[i].serialize(&databuf_nodelist[i*3], version);
                }
-
-               // Get param2
+               
+               // Create buffer with different parameters sorted
+               SharedBuffer<u8> databuf(nodecount*3);
                for(u32 i=0; i<nodecount; i++)
                {
-                       databuf[i+nodecount*2] = data[i].param2;
+                       databuf[i] = databuf_nodelist[i*3];
+                       databuf[i+nodecount] = databuf_nodelist[i*3+1];
+                       databuf[i+nodecount*2] = databuf_nodelist[i*3+2];
                }
 
                /*
@@ -719,7 +720,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                                                ("MapBlock::deSerialize: invalid format");
                        for(u32 i=0; i<s.size(); i++)
                        {
-                               data[i].d = s[i];
+                               data[i].param0 = s[i];
                        }
                }
                {
@@ -732,7 +733,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                                                ("MapBlock::deSerialize: invalid format");
                        for(u32 i=0; i<s.size(); i++)
                        {
-                               data[i].param = s[i];
+                               data[i].param1 = s[i];
                        }
                }
        
@@ -773,20 +774,14 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                                        ("MapBlock::deSerialize: decompress resulted in size"
                                        " other than nodecount*3");
 
-               // Set contents
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       data[i].d = s[i];
-               }
-               // Set params
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       data[i].param = s[i+nodecount];
-               }
-               // Set param2
+               // deserialize nodes from buffer
                for(u32 i=0; i<nodecount; i++)
                {
-                       data[i].param2 = s[i+nodecount*2];
+                       u8 buf[3];
+                       buf[0] = s[i];
+                       buf[1] = s[i+nodecount];
+                       buf[2] = s[i+nodecount*2];
+                       data[i].deSerialize(buf, version);
                }
                
                /*
@@ -818,25 +813,6 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                        }
                }
        }
-       
-       /*
-               Translate nodes as specified in the translate_to fields of
-               node features
-
-               NOTE: This isn't really used. Should it be removed?
-       */
-       for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
-       {
-               MapNode &n = data[i];
-
-               MapNode *translate_to = content_features(n.d).translate_to;
-               if(translate_to)
-               {
-                       dstream<<"MapBlock: WARNING: Translating node "<<n.d<<" to "
-                                       <<translate_to->d<<std::endl;
-                       n = *translate_to;
-               }
-       }
 }
 
 void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
@@ -891,5 +867,130 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
        }
 }
 
+/*
+       Get a quick string to describe what a block actually contains
+*/
+std::string analyze_block(MapBlock *block)
+{
+       if(block == NULL)
+       {
+               return "NULL";
+       }
+
+       std::ostringstream desc;
+       
+       v3s16 p = block->getPos();
+       char spos[20];
+       snprintf(spos, 20, "(%2d,%2d,%2d), ", p.X, p.Y, p.Z);
+       desc<<spos;
+       
+       switch(block->getModified())
+       {
+       case MOD_STATE_CLEAN:
+               desc<<"CLEAN,           ";
+               break;
+       case MOD_STATE_WRITE_AT_UNLOAD:
+               desc<<"WRITE_AT_UNLOAD, ";
+               break;
+       case MOD_STATE_WRITE_NEEDED:
+               desc<<"WRITE_NEEDED,    ";
+               break;
+       default:
+               desc<<"unknown getModified()="+itos(block->getModified())+", ";
+       }
+
+       if(block->isGenerated())
+               desc<<"is_gen [X], ";
+       else
+               desc<<"is_gen [ ], ";
+
+       if(block->getIsUnderground())
+               desc<<"is_ug [X], ";
+       else
+               desc<<"is_ug [ ], ";
+
+#ifndef SERVER
+       if(block->getMeshExpired())
+               desc<<"mesh_exp [X], ";
+       else
+               desc<<"mesh_exp [ ], ";
+#endif
+
+       if(block->getLightingExpired())
+               desc<<"lighting_exp [X], ";
+       else
+               desc<<"lighting_exp [ ], ";
+
+       if(block->isDummy())
+       {
+               desc<<"Dummy, ";
+       }
+       else
+       {
+               // We'll just define the numbers here, don't want to include
+               // content_mapnode.h
+               const content_t content_water = 2;
+               const content_t content_watersource = 9;
+               const content_t content_tree = 0x801;
+               const content_t content_leaves = 0x802;
+               const content_t content_jungletree = 0x815;
+
+               bool full_ignore = true;
+               bool some_ignore = false;
+               bool full_air = true;
+               bool some_air = false;
+               bool trees = false;
+               bool water = false;
+               for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+               for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+               for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+               {
+                       v3s16 p(x0,y0,z0);
+                       MapNode n = block->getNode(p);
+                       content_t c = n.getContent();
+                       if(c == CONTENT_IGNORE)
+                               some_ignore = true;
+                       else
+                               full_ignore = false;
+                       if(c == CONTENT_AIR)
+                               some_air = true;
+                       else
+                               full_air = false;
+                       if(c == content_tree || c == content_jungletree
+                                       || c == content_leaves)
+                               trees = true;
+                       if(c == content_water
+                                       || c == content_watersource)
+                               water = true;
+               }
+               
+               desc<<"content {";
+               
+               std::ostringstream ss;
+               
+               if(full_ignore)
+                       ss<<"IGNORE (full), ";
+               else if(some_ignore)
+                       ss<<"IGNORE, ";
+               
+               if(full_air)
+                       ss<<"AIR (full), ";
+               else if(some_air)
+                       ss<<"AIR, ";
+
+               if(trees)
+                       ss<<"trees, ";
+               if(water)
+                       ss<<"water, ";
+               
+               if(ss.str().size()>=2)
+                       desc<<ss.str().substr(0, ss.str().size()-2);
+
+               desc<<"}, ";
+       }
+
+       return desc.str().substr(0, desc.str().size()-2);
+}
+
 
 //END