]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/map.cpp
Prevent world creation if the world already exists
[dragonfireclient.git] / src / map.cpp
index 275b260290bda95e9f93a4a5b0c299d067999e9f..39c6d292b3248569a0ffe382220250e24b01a440 100644 (file)
@@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapblock.h"
 #include "main.h"
 #include "filesys.h"
-#include "utility.h"
 #include "voxel.h"
 #include "porting.h"
 #include "mapgen.h"
@@ -32,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "profiler.h"
 #include "nodedef.h"
 #include "gamedef.h"
+#include "util/directiontables.h"
+#include "rollback_interface.h"
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -932,12 +933,12 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
 void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                core::map<v3s16, MapBlock*> &modified_blocks)
 {
-       INodeDefManager *nodemgr = m_gamedef->ndef();
+       INodeDefManager *ndef = m_gamedef->ndef();
 
        /*PrintInfo(m_dout);
        m_dout<<DTIME<<"Map::addNodeAndUpdate(): p=("
                        <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
-
+       
        /*
                From this node to nodes underneath:
                If lighting is sunlight (1.0), unlight neighbours and
@@ -950,6 +951,11 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
 
        bool node_under_sunlight = true;
        core::map<v3s16, bool> light_sources;
+       
+       /*
+               Collect old node for rollback
+       */
+       RollbackNode rollback_oldnode(this, p, m_gamedef);
 
        /*
                If there is a node at top and it doesn't have sunlight,
@@ -960,7 +966,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
        try{
                MapNode topnode = getNode(toppos);
 
-               if(topnode.getLight(LIGHTBANK_DAY, nodemgr) != LIGHT_SUN)
+               if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
                        node_under_sunlight = false;
        }
        catch(InvalidPositionException &e)
@@ -980,7 +986,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
        {
                enum LightBank bank = banks[i];
 
-               u8 lightwas = getNode(p).getLight(bank, nodemgr);
+               u8 lightwas = getNode(p).getLight(bank, ndef);
 
                // Add the block of the added node to modified_blocks
                v3s16 blockpos = getNodeBlockPos(p);
@@ -997,16 +1003,16 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                // light again into this.
                unLightNeighbors(bank, p, lightwas, light_sources, modified_blocks);
 
-               n.setLight(bank, 0, nodemgr);
+               n.setLight(bank, 0, ndef);
        }
 
        /*
                If node lets sunlight through and is under sunlight, it has
                sunlight too.
        */
-       if(node_under_sunlight && nodemgr->get(n).sunlight_propagates)
+       if(node_under_sunlight && ndef->get(n).sunlight_propagates)
        {
-               n.setLight(LIGHTBANK_DAY, LIGHT_SUN, nodemgr);
+               n.setLight(LIGHTBANK_DAY, LIGHT_SUN, ndef);
        }
 
        /*
@@ -1028,7 +1034,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                TODO: This could be optimized by mass-unlighting instead
                          of looping
        */
-       if(node_under_sunlight && !nodemgr->get(n).sunlight_propagates)
+       if(node_under_sunlight && !ndef->get(n).sunlight_propagates)
        {
                s16 y = p.Y - 1;
                for(;; y--){
@@ -1044,12 +1050,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                                break;
                        }
 
-                       if(n2.getLight(LIGHTBANK_DAY, nodemgr) == LIGHT_SUN)
+                       if(n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN)
                        {
                                unLightNeighbors(LIGHTBANK_DAY,
-                                               n2pos, n2.getLight(LIGHTBANK_DAY, nodemgr),
+                                               n2pos, n2.getLight(LIGHTBANK_DAY, ndef),
                                                light_sources, modified_blocks);
-                               n2.setLight(LIGHTBANK_DAY, 0, nodemgr);
+                               n2.setLight(LIGHTBANK_DAY, 0, ndef);
                                setNode(n2pos, n2);
                        }
                        else
@@ -1078,6 +1084,17 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                block->expireDayNightDiff();
        }
 
+       /*
+               Report for rollback
+       */
+       if(m_gamedef->rollback())
+       {
+               RollbackNode rollback_newnode(this, p, m_gamedef);
+               RollbackAction action;
+               action.setSetNode(p, rollback_oldnode, rollback_newnode);
+               m_gamedef->rollback()->reportAction(action);
+       }
+
        /*
                Add neighboring liquid nodes and the node itself if it is
                liquid (=water node was added) to transform queue.
@@ -1099,7 +1116,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
                v3s16 p2 = p + dirs[i];
 
                MapNode n2 = getNode(p2);
-               if(nodemgr->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
+               if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
                {
                        m_transforming_liquid.push_back(p2);
                }
@@ -1115,7 +1132,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
 void Map::removeNodeAndUpdate(v3s16 p,
                core::map<v3s16, MapBlock*> &modified_blocks)
 {
-       INodeDefManager *nodemgr = m_gamedef->ndef();
+       INodeDefManager *ndef = m_gamedef->ndef();
 
        /*PrintInfo(m_dout);
        m_dout<<DTIME<<"Map::removeNodeAndUpdate(): p=("
@@ -1128,6 +1145,11 @@ void Map::removeNodeAndUpdate(v3s16 p,
        // Node will be replaced with this
        content_t replace_material = CONTENT_AIR;
 
+       /*
+               Collect old node for rollback
+       */
+       RollbackNode rollback_oldnode(this, p, m_gamedef);
+
        /*
                If there is a node at top and it doesn't have sunlight,
                there will be no sunlight going down.
@@ -1135,7 +1157,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
        try{
                MapNode topnode = getNode(toppos);
 
-               if(topnode.getLight(LIGHTBANK_DAY, nodemgr) != LIGHT_SUN)
+               if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
                        node_under_sunlight = false;
        }
        catch(InvalidPositionException &e)
@@ -1157,7 +1179,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
                        Unlight neighbors (in case the node is a light source)
                */
                unLightNeighbors(bank, p,
-                               getNode(p).getLight(bank, nodemgr),
+                               getNode(p).getLight(bank, ndef),
                                light_sources, modified_blocks);
        }
 
@@ -1219,7 +1241,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
                // TODO: Is this needed? Lighting is cleared up there already.
                try{
                        MapNode n = getNode(p);
-                       n.setLight(LIGHTBANK_DAY, 0, nodemgr);
+                       n.setLight(LIGHTBANK_DAY, 0, ndef);
                        setNode(p, n);
                }
                catch(InvalidPositionException &e)
@@ -1254,6 +1276,17 @@ void Map::removeNodeAndUpdate(v3s16 p,
                block->expireDayNightDiff();
        }
 
+       /*
+               Report for rollback
+       */
+       if(m_gamedef->rollback())
+       {
+               RollbackNode rollback_newnode(this, p, m_gamedef);
+               RollbackAction action;
+               action.setSetNode(p, rollback_oldnode, rollback_newnode);
+               m_gamedef->rollback()->reportAction(action);
+       }
+
        /*
                Add neighboring liquid nodes and this node to transform queue.
                (it's vital for the node itself to get updated last.)
@@ -1275,7 +1308,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
                v3s16 p2 = p + dirs[i];
 
                MapNode n2 = getNode(p2);
-               if(nodemgr->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
+               if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
                {
                        m_transforming_liquid.push_back(p2);
                }
@@ -1435,8 +1468,8 @@ void Map::timerUpdate(float dtime, float unload_timeout,
                        MapBlock *block = (*i);
                        
                        block->incrementUsageTimer(dtime);
-                       
-                       if(block->getUsageTimer() > unload_timeout)
+
+                       if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout)
                        {
                                v3s16 p = block->getPos();
 
@@ -1603,7 +1636,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
        while(m_transforming_liquid.size() != 0)
        {
                // This should be done here so that it is done when continue is used
-               if(loopcount >= initial_size * 3)
+               if(loopcount >= initial_size || loopcount >= 10000)
                        break;
                loopcount++;
 
@@ -1791,7 +1824,30 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
                        n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
                }
                n0.setContent(new_node_content);
-               setNode(p0, n0);
+               
+               // Find out whether there is a suspect for this action
+               std::string suspect;
+               if(m_gamedef->rollback()){
+                       suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
+               }
+
+               if(!suspect.empty()){
+                       // Blame suspect
+                       RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
+                       // Get old node for rollback
+                       RollbackNode rollback_oldnode(this, p0, m_gamedef);
+                       // Set node
+                       setNode(p0, n0);
+                       // Report
+                       RollbackNode rollback_newnode(this, p0, m_gamedef);
+                       RollbackAction action;
+                       action.setSetNode(p0, rollback_oldnode, rollback_newnode);
+                       m_gamedef->rollback()->reportAction(action);
+               } else {
+                       // Set node
+                       setNode(p0, n0);
+               }
+
                v3s16 blockpos = getNodeBlockPos(p0);
                MapBlock *block = getBlockNoCreateNoEx(blockpos);
                if(block != NULL) {
@@ -1881,6 +1937,59 @@ void Map::removeNodeMetadata(v3s16 p)
        block->m_node_metadata.remove(p_rel);
 }
 
+NodeTimer Map::getNodeTimer(v3s16 p)
+{
+       v3s16 blockpos = getNodeBlockPos(p);
+       v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
+       MapBlock *block = getBlockNoCreateNoEx(blockpos);
+       if(!block){
+               infostream<<"Map::getNodeTimer(): Need to emerge "
+                               <<PP(blockpos)<<std::endl;
+               block = emergeBlock(blockpos, false);
+       }
+       if(!block)
+       {
+               infostream<<"WARNING: Map::getNodeTimer(): Block not found"
+                               <<std::endl;
+               return NodeTimer();
+       }
+       NodeTimer t = block->m_node_timers.get(p_rel);
+       return t;
+}
+
+void Map::setNodeTimer(v3s16 p, NodeTimer t)
+{
+       v3s16 blockpos = getNodeBlockPos(p);
+       v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
+       MapBlock *block = getBlockNoCreateNoEx(blockpos);
+       if(!block){
+               infostream<<"Map::setNodeTimer(): Need to emerge "
+                               <<PP(blockpos)<<std::endl;
+               block = emergeBlock(blockpos, false);
+       }
+       if(!block)
+       {
+               infostream<<"WARNING: Map::setNodeTimer(): Block not found"
+                               <<std::endl;
+               return;
+       }
+       block->m_node_timers.set(p_rel, t);
+}
+
+void Map::removeNodeTimer(v3s16 p)
+{
+       v3s16 blockpos = getNodeBlockPos(p);
+       v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
+       MapBlock *block = getBlockNoCreateNoEx(blockpos);
+       if(block == NULL)
+       {
+               infostream<<"WARNING: Map::removeNodeTimer(): Block not found"
+                               <<std::endl;
+               return;
+       }
+       block->m_node_timers.remove(p_rel);
+}
+
 /*
        ServerMap
 */