Fix mouse events sent to wrong GUI elements when dragging
[oweals/minetest.git] / src / map.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "map.h"
21 #include "mapsector.h"
22 #include "mapblock.h"
23 #include "filesys.h"
24 #include "voxel.h"
25 #include "voxelalgorithms.h"
26 #include "porting.h"
27 #include "serialization.h"
28 #include "nodemetadata.h"
29 #include "settings.h"
30 #include "log.h"
31 #include "profiler.h"
32 #include "nodedef.h"
33 #include "gamedef.h"
34 #include "util/directiontables.h"
35 #include "util/basic_macros.h"
36 #include "rollback_interface.h"
37 #include "environment.h"
38 #include "reflowscan.h"
39 #include "emerge.h"
40 #include "mapgen/mapgen_v6.h"
41 #include "mapgen/mg_biome.h"
42 #include "config.h"
43 #include "server.h"
44 #include "database/database.h"
45 #include "database/database-dummy.h"
46 #include "database/database-sqlite3.h"
47 #include "script/scripting_server.h"
48 #include <deque>
49 #include <queue>
50 #if USE_LEVELDB
51 #include "database/database-leveldb.h"
52 #endif
53 #if USE_REDIS
54 #include "database/database-redis.h"
55 #endif
56 #if USE_POSTGRESQL
57 #include "database/database-postgresql.h"
58 #endif
59
60
61 /*
62         Map
63 */
64
65 Map::Map(std::ostream &dout, IGameDef *gamedef):
66         m_dout(dout),
67         m_gamedef(gamedef),
68         m_nodedef(gamedef->ndef())
69 {
70 }
71
72 Map::~Map()
73 {
74         /*
75                 Free all MapSectors
76         */
77         for (auto &sector : m_sectors) {
78                 delete sector.second;
79         }
80 }
81
82 void Map::addEventReceiver(MapEventReceiver *event_receiver)
83 {
84         m_event_receivers.insert(event_receiver);
85 }
86
87 void Map::removeEventReceiver(MapEventReceiver *event_receiver)
88 {
89         m_event_receivers.erase(event_receiver);
90 }
91
92 void Map::dispatchEvent(const MapEditEvent &event)
93 {
94         for (MapEventReceiver *event_receiver : m_event_receivers) {
95                 event_receiver->onMapEditEvent(event);
96         }
97 }
98
99 MapSector * Map::getSectorNoGenerateNoLock(v2s16 p)
100 {
101         if(m_sector_cache != NULL && p == m_sector_cache_p){
102                 MapSector * sector = m_sector_cache;
103                 return sector;
104         }
105
106         std::map<v2s16, MapSector*>::iterator n = m_sectors.find(p);
107
108         if (n == m_sectors.end())
109                 return NULL;
110
111         MapSector *sector = n->second;
112
113         // Cache the last result
114         m_sector_cache_p = p;
115         m_sector_cache = sector;
116
117         return sector;
118 }
119
120 MapSector * Map::getSectorNoGenerate(v2s16 p)
121 {
122         return getSectorNoGenerateNoLock(p);
123 }
124
125 MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d)
126 {
127         v2s16 p2d(p3d.X, p3d.Z);
128         MapSector * sector = getSectorNoGenerate(p2d);
129         if(sector == NULL)
130                 return NULL;
131         MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y);
132         return block;
133 }
134
135 MapBlock * Map::getBlockNoCreate(v3s16 p3d)
136 {
137         MapBlock *block = getBlockNoCreateNoEx(p3d);
138         if(block == NULL)
139                 throw InvalidPositionException();
140         return block;
141 }
142
143 bool Map::isNodeUnderground(v3s16 p)
144 {
145         v3s16 blockpos = getNodeBlockPos(p);
146         MapBlock *block = getBlockNoCreateNoEx(blockpos);
147         return block && block->getIsUnderground(); 
148 }
149
150 bool Map::isValidPosition(v3s16 p)
151 {
152         v3s16 blockpos = getNodeBlockPos(p);
153         MapBlock *block = getBlockNoCreateNoEx(blockpos);
154         return (block != NULL);
155 }
156
157 // Returns a CONTENT_IGNORE node if not found
158 MapNode Map::getNode(v3s16 p, bool *is_valid_position)
159 {
160         v3s16 blockpos = getNodeBlockPos(p);
161         MapBlock *block = getBlockNoCreateNoEx(blockpos);
162         if (block == NULL) {
163                 if (is_valid_position != NULL)
164                         *is_valid_position = false;
165                 return {CONTENT_IGNORE};
166         }
167
168         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
169         bool is_valid_p;
170         MapNode node = block->getNodeNoCheck(relpos, &is_valid_p);
171         if (is_valid_position != NULL)
172                 *is_valid_position = is_valid_p;
173         return node;
174 }
175
176 // throws InvalidPositionException if not found
177 void Map::setNode(v3s16 p, MapNode & n)
178 {
179         v3s16 blockpos = getNodeBlockPos(p);
180         MapBlock *block = getBlockNoCreate(blockpos);
181         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
182         // Never allow placing CONTENT_IGNORE, it causes problems
183         if(n.getContent() == CONTENT_IGNORE){
184                 bool temp_bool;
185                 errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE"
186                                 <<" while trying to replace \""
187                                 <<m_nodedef->get(block->getNodeNoCheck(relpos, &temp_bool)).name
188                                 <<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl;
189                 return;
190         }
191         block->setNodeNoCheck(relpos, n);
192 }
193
194 void Map::addNodeAndUpdate(v3s16 p, MapNode n,
195                 std::map<v3s16, MapBlock*> &modified_blocks,
196                 bool remove_metadata)
197 {
198         // Collect old node for rollback
199         RollbackNode rollback_oldnode(this, p, m_gamedef);
200
201         // This is needed for updating the lighting
202         MapNode oldnode = getNode(p);
203
204         // Remove node metadata
205         if (remove_metadata) {
206                 removeNodeMetadata(p);
207         }
208
209         // Set the node on the map
210         // Ignore light (because calling voxalgo::update_lighting_nodes)
211         n.setLight(LIGHTBANK_DAY, 0, m_nodedef);
212         n.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
213         setNode(p, n);
214
215         // Update lighting
216         std::vector<std::pair<v3s16, MapNode> > oldnodes;
217         oldnodes.emplace_back(p, oldnode);
218         voxalgo::update_lighting_nodes(this, oldnodes, modified_blocks);
219
220         for (auto &modified_block : modified_blocks) {
221                 modified_block.second->expireDayNightDiff();
222         }
223
224         // Report for rollback
225         if(m_gamedef->rollback())
226         {
227                 RollbackNode rollback_newnode(this, p, m_gamedef);
228                 RollbackAction action;
229                 action.setSetNode(p, rollback_oldnode, rollback_newnode);
230                 m_gamedef->rollback()->reportAction(action);
231         }
232
233         /*
234                 Add neighboring liquid nodes and this node to transform queue.
235                 (it's vital for the node itself to get updated last, if it was removed.)
236          */
237
238         for (const v3s16 &dir : g_7dirs) {
239                 v3s16 p2 = p + dir;
240
241                 bool is_valid_position;
242                 MapNode n2 = getNode(p2, &is_valid_position);
243                 if(is_valid_position &&
244                                 (m_nodedef->get(n2).isLiquid() ||
245                                 n2.getContent() == CONTENT_AIR))
246                         m_transforming_liquid.push_back(p2);
247         }
248 }
249
250 void Map::removeNodeAndUpdate(v3s16 p,
251                 std::map<v3s16, MapBlock*> &modified_blocks)
252 {
253         addNodeAndUpdate(p, MapNode(CONTENT_AIR), modified_blocks, true);
254 }
255
256 bool Map::addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata)
257 {
258         MapEditEvent event;
259         event.type = remove_metadata ? MEET_ADDNODE : MEET_SWAPNODE;
260         event.p = p;
261         event.n = n;
262
263         bool succeeded = true;
264         try{
265                 std::map<v3s16, MapBlock*> modified_blocks;
266                 addNodeAndUpdate(p, n, modified_blocks, remove_metadata);
267
268                 // Copy modified_blocks to event
269                 for (auto &modified_block : modified_blocks) {
270                         event.modified_blocks.insert(modified_block.first);
271                 }
272         }
273         catch(InvalidPositionException &e){
274                 succeeded = false;
275         }
276
277         dispatchEvent(event);
278
279         return succeeded;
280 }
281
282 bool Map::removeNodeWithEvent(v3s16 p)
283 {
284         MapEditEvent event;
285         event.type = MEET_REMOVENODE;
286         event.p = p;
287
288         bool succeeded = true;
289         try{
290                 std::map<v3s16, MapBlock*> modified_blocks;
291                 removeNodeAndUpdate(p, modified_blocks);
292
293                 // Copy modified_blocks to event
294                 for (auto &modified_block : modified_blocks) {
295                         event.modified_blocks.insert(modified_block.first);
296                 }
297         }
298         catch(InvalidPositionException &e){
299                 succeeded = false;
300         }
301
302         dispatchEvent(event);
303
304         return succeeded;
305 }
306
307 struct TimeOrderedMapBlock {
308         MapSector *sect;
309         MapBlock *block;
310
311         TimeOrderedMapBlock(MapSector *sect, MapBlock *block) :
312                 sect(sect),
313                 block(block)
314         {}
315
316         bool operator<(const TimeOrderedMapBlock &b) const
317         {
318                 return block->getUsageTimer() < b.block->getUsageTimer();
319         };
320 };
321
322 /*
323         Updates usage timers
324 */
325 void Map::timerUpdate(float dtime, float unload_timeout, u32 max_loaded_blocks,
326                 std::vector<v3s16> *unloaded_blocks)
327 {
328         bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
329
330         // Profile modified reasons
331         Profiler modprofiler;
332
333         std::vector<v2s16> sector_deletion_queue;
334         u32 deleted_blocks_count = 0;
335         u32 saved_blocks_count = 0;
336         u32 block_count_all = 0;
337
338         beginSave();
339
340         // If there is no practical limit, we spare creation of mapblock_queue
341         if (max_loaded_blocks == U32_MAX) {
342                 for (auto &sector_it : m_sectors) {
343                         MapSector *sector = sector_it.second;
344
345                         bool all_blocks_deleted = true;
346
347                         MapBlockVect blocks;
348                         sector->getBlocks(blocks);
349
350                         for (MapBlock *block : blocks) {
351                                 block->incrementUsageTimer(dtime);
352
353                                 if (block->refGet() == 0
354                                                 && block->getUsageTimer() > unload_timeout) {
355                                         v3s16 p = block->getPos();
356
357                                         // Save if modified
358                                         if (block->getModified() != MOD_STATE_CLEAN
359                                                         && save_before_unloading) {
360                                                 modprofiler.add(block->getModifiedReasonString(), 1);
361                                                 if (!saveBlock(block))
362                                                         continue;
363                                                 saved_blocks_count++;
364                                         }
365
366                                         // Delete from memory
367                                         sector->deleteBlock(block);
368
369                                         if (unloaded_blocks)
370                                                 unloaded_blocks->push_back(p);
371
372                                         deleted_blocks_count++;
373                                 } else {
374                                         all_blocks_deleted = false;
375                                         block_count_all++;
376                                 }
377                         }
378
379                         if (all_blocks_deleted) {
380                                 sector_deletion_queue.push_back(sector_it.first);
381                         }
382                 }
383         } else {
384                 std::priority_queue<TimeOrderedMapBlock> mapblock_queue;
385                 for (auto &sector_it : m_sectors) {
386                         MapSector *sector = sector_it.second;
387
388                         MapBlockVect blocks;
389                         sector->getBlocks(blocks);
390
391                         for (MapBlock *block : blocks) {
392                                 block->incrementUsageTimer(dtime);
393                                 mapblock_queue.push(TimeOrderedMapBlock(sector, block));
394                         }
395                 }
396                 block_count_all = mapblock_queue.size();
397                 // Delete old blocks, and blocks over the limit from the memory
398                 while (!mapblock_queue.empty() && (mapblock_queue.size() > max_loaded_blocks
399                                 || mapblock_queue.top().block->getUsageTimer() > unload_timeout)) {
400                         TimeOrderedMapBlock b = mapblock_queue.top();
401                         mapblock_queue.pop();
402
403                         MapBlock *block = b.block;
404
405                         if (block->refGet() != 0)
406                                 continue;
407
408                         v3s16 p = block->getPos();
409
410                         // Save if modified
411                         if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) {
412                                 modprofiler.add(block->getModifiedReasonString(), 1);
413                                 if (!saveBlock(block))
414                                         continue;
415                                 saved_blocks_count++;
416                         }
417
418                         // Delete from memory
419                         b.sect->deleteBlock(block);
420
421                         if (unloaded_blocks)
422                                 unloaded_blocks->push_back(p);
423
424                         deleted_blocks_count++;
425                         block_count_all--;
426                 }
427                 // Delete empty sectors
428                 for (auto &sector_it : m_sectors) {
429                         if (sector_it.second->empty()) {
430                                 sector_deletion_queue.push_back(sector_it.first);
431                         }
432                 }
433         }
434         endSave();
435
436         // Finally delete the empty sectors
437         deleteSectors(sector_deletion_queue);
438
439         if(deleted_blocks_count != 0)
440         {
441                 PrintInfo(infostream); // ServerMap/ClientMap:
442                 infostream<<"Unloaded "<<deleted_blocks_count
443                                 <<" blocks from memory";
444                 if(save_before_unloading)
445                         infostream<<", of which "<<saved_blocks_count<<" were written";
446                 infostream<<", "<<block_count_all<<" blocks in memory";
447                 infostream<<"."<<std::endl;
448                 if(saved_blocks_count != 0){
449                         PrintInfo(infostream); // ServerMap/ClientMap:
450                         infostream<<"Blocks modified by: "<<std::endl;
451                         modprofiler.print(infostream);
452                 }
453         }
454 }
455
456 void Map::unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks)
457 {
458         timerUpdate(0.0, -1.0, 0, unloaded_blocks);
459 }
460
461 void Map::deleteSectors(std::vector<v2s16> &sectorList)
462 {
463         for (v2s16 j : sectorList) {
464                 MapSector *sector = m_sectors[j];
465                 // If sector is in sector cache, remove it from there
466                 if(m_sector_cache == sector)
467                         m_sector_cache = NULL;
468                 // Remove from map and delete
469                 m_sectors.erase(j);
470                 delete sector;
471         }
472 }
473
474 void Map::PrintInfo(std::ostream &out)
475 {
476         out<<"Map: ";
477 }
478
479 #define WATER_DROP_BOOST 4
480
481 enum NeighborType : u8 {
482         NEIGHBOR_UPPER,
483         NEIGHBOR_SAME_LEVEL,
484         NEIGHBOR_LOWER
485 };
486
487 struct NodeNeighbor {
488         MapNode n;
489         NeighborType t;
490         v3s16 p;
491
492         NodeNeighbor()
493                 : n(CONTENT_AIR), t(NEIGHBOR_SAME_LEVEL)
494         { }
495
496         NodeNeighbor(const MapNode &node, NeighborType n_type, const v3s16 &pos)
497                 : n(node),
498                   t(n_type),
499                   p(pos)
500         { }
501 };
502
503 void Map::transforming_liquid_add(v3s16 p) {
504         m_transforming_liquid.push_back(p);
505 }
506
507 void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
508                 ServerEnvironment *env)
509 {
510         u32 loopcount = 0;
511         u32 initial_size = m_transforming_liquid.size();
512
513         /*if(initial_size != 0)
514                 infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
515
516         // list of nodes that due to viscosity have not reached their max level height
517         std::deque<v3s16> must_reflow;
518
519         std::vector<std::pair<v3s16, MapNode> > changed_nodes;
520
521         u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
522         u32 loop_max = liquid_loop_max;
523
524 #if 0
525
526         /* If liquid_loop_max is not keeping up with the queue size increase
527          * loop_max up to a maximum of liquid_loop_max * dedicated_server_step.
528          */
529         if (m_transforming_liquid.size() > loop_max * 2) {
530                 // "Burst" mode
531                 float server_step = g_settings->getFloat("dedicated_server_step");
532                 if (m_transforming_liquid_loop_count_multiplier - 1.0 < server_step)
533                         m_transforming_liquid_loop_count_multiplier *= 1.0 + server_step / 10;
534         } else {
535                 m_transforming_liquid_loop_count_multiplier = 1.0;
536         }
537
538         loop_max *= m_transforming_liquid_loop_count_multiplier;
539 #endif
540
541         while (m_transforming_liquid.size() != 0)
542         {
543                 // This should be done here so that it is done when continue is used
544                 if (loopcount >= initial_size || loopcount >= loop_max)
545                         break;
546                 loopcount++;
547
548                 /*
549                         Get a queued transforming liquid node
550                 */
551                 v3s16 p0 = m_transforming_liquid.front();
552                 m_transforming_liquid.pop_front();
553
554                 MapNode n0 = getNode(p0);
555
556                 /*
557                         Collect information about current node
558                  */
559                 s8 liquid_level = -1;
560                 // The liquid node which will be placed there if
561                 // the liquid flows into this node.
562                 content_t liquid_kind = CONTENT_IGNORE;
563                 // The node which will be placed there if liquid
564                 // can't flow into this node.
565                 content_t floodable_node = CONTENT_AIR;
566                 const ContentFeatures &cf = m_nodedef->get(n0);
567                 LiquidType liquid_type = cf.liquid_type;
568                 switch (liquid_type) {
569                         case LIQUID_SOURCE:
570                                 liquid_level = LIQUID_LEVEL_SOURCE;
571                                 liquid_kind = m_nodedef->getId(cf.liquid_alternative_flowing);
572                                 break;
573                         case LIQUID_FLOWING:
574                                 liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
575                                 liquid_kind = n0.getContent();
576                                 break;
577                         case LIQUID_NONE:
578                                 // if this node is 'floodable', it *could* be transformed
579                                 // into a liquid, otherwise, continue with the next node.
580                                 if (!cf.floodable)
581                                         continue;
582                                 floodable_node = n0.getContent();
583                                 liquid_kind = CONTENT_AIR;
584                                 break;
585                 }
586
587                 /*
588                         Collect information about the environment
589                  */
590                 const v3s16 *dirs = g_6dirs;
591                 NodeNeighbor sources[6]; // surrounding sources
592                 int num_sources = 0;
593                 NodeNeighbor flows[6]; // surrounding flowing liquid nodes
594                 int num_flows = 0;
595                 NodeNeighbor airs[6]; // surrounding air
596                 int num_airs = 0;
597                 NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
598                 int num_neutrals = 0;
599                 bool flowing_down = false;
600                 bool ignored_sources = false;
601                 for (u16 i = 0; i < 6; i++) {
602                         NeighborType nt = NEIGHBOR_SAME_LEVEL;
603                         switch (i) {
604                                 case 1:
605                                         nt = NEIGHBOR_UPPER;
606                                         break;
607                                 case 4:
608                                         nt = NEIGHBOR_LOWER;
609                                         break;
610                                 default:
611                                         break;
612                         }
613                         v3s16 npos = p0 + dirs[i];
614                         NodeNeighbor nb(getNode(npos), nt, npos);
615                         const ContentFeatures &cfnb = m_nodedef->get(nb.n);
616                         switch (m_nodedef->get(nb.n.getContent()).liquid_type) {
617                                 case LIQUID_NONE:
618                                         if (cfnb.floodable) {
619                                                 airs[num_airs++] = nb;
620                                                 // if the current node is a water source the neighbor
621                                                 // should be enqueded for transformation regardless of whether the
622                                                 // current node changes or not.
623                                                 if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
624                                                         m_transforming_liquid.push_back(npos);
625                                                 // if the current node happens to be a flowing node, it will start to flow down here.
626                                                 if (nb.t == NEIGHBOR_LOWER)
627                                                         flowing_down = true;
628                                         } else {
629                                                 neutrals[num_neutrals++] = nb;
630                                                 if (nb.n.getContent() == CONTENT_IGNORE) {
631                                                         // If node below is ignore prevent water from
632                                                         // spreading outwards and otherwise prevent from
633                                                         // flowing away as ignore node might be the source
634                                                         if (nb.t == NEIGHBOR_LOWER)
635                                                                 flowing_down = true;
636                                                         else
637                                                                 ignored_sources = true;
638                                                 }
639                                         }
640                                         break;
641                                 case LIQUID_SOURCE:
642                                         // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
643                                         if (liquid_kind == CONTENT_AIR)
644                                                 liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
645                                         if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
646                                                 neutrals[num_neutrals++] = nb;
647                                         } else {
648                                                 // Do not count bottom source, it will screw things up
649                                                 if(dirs[i].Y != -1)
650                                                         sources[num_sources++] = nb;
651                                         }
652                                         break;
653                                 case LIQUID_FLOWING:
654                                         // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
655                                         if (liquid_kind == CONTENT_AIR)
656                                                 liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing);
657                                         if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
658                                                 neutrals[num_neutrals++] = nb;
659                                         } else {
660                                                 flows[num_flows++] = nb;
661                                                 if (nb.t == NEIGHBOR_LOWER)
662                                                         flowing_down = true;
663                                         }
664                                         break;
665                         }
666                 }
667
668                 /*
669                         decide on the type (and possibly level) of the current node
670                  */
671                 content_t new_node_content;
672                 s8 new_node_level = -1;
673                 s8 max_node_level = -1;
674
675                 u8 range = m_nodedef->get(liquid_kind).liquid_range;
676                 if (range > LIQUID_LEVEL_MAX + 1)
677                         range = LIQUID_LEVEL_MAX + 1;
678
679                 if ((num_sources >= 2 && m_nodedef->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
680                         // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
681                         // or the flowing alternative of the first of the surrounding sources (if it's air), so
682                         // it's perfectly safe to use liquid_kind here to determine the new node content.
683                         new_node_content = m_nodedef->getId(m_nodedef->get(liquid_kind).liquid_alternative_source);
684                 } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
685                         // liquid_kind is set properly, see above
686                         max_node_level = new_node_level = LIQUID_LEVEL_MAX;
687                         if (new_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
688                                 new_node_content = liquid_kind;
689                         else
690                                 new_node_content = floodable_node;
691                 } else if (ignored_sources && liquid_level >= 0) {
692                         // Maybe there are neighbouring sources that aren't loaded yet
693                         // so prevent flowing away.
694                         new_node_level = liquid_level;
695                         new_node_content = liquid_kind;
696                 } else {
697                         // no surrounding sources, so get the maximum level that can flow into this node
698                         for (u16 i = 0; i < num_flows; i++) {
699                                 u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
700                                 switch (flows[i].t) {
701                                         case NEIGHBOR_UPPER:
702                                                 if (nb_liquid_level + WATER_DROP_BOOST > max_node_level) {
703                                                         max_node_level = LIQUID_LEVEL_MAX;
704                                                         if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
705                                                                 max_node_level = nb_liquid_level + WATER_DROP_BOOST;
706                                                 } else if (nb_liquid_level > max_node_level) {
707                                                         max_node_level = nb_liquid_level;
708                                                 }
709                                                 break;
710                                         case NEIGHBOR_LOWER:
711                                                 break;
712                                         case NEIGHBOR_SAME_LEVEL:
713                                                 if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
714                                                                 nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level)
715                                                         max_node_level = nb_liquid_level - 1;
716                                                 break;
717                                 }
718                         }
719
720                         u8 viscosity = m_nodedef->get(liquid_kind).liquid_viscosity;
721                         if (viscosity > 1 && max_node_level != liquid_level) {
722                                 // amount to gain, limited by viscosity
723                                 // must be at least 1 in absolute value
724                                 s8 level_inc = max_node_level - liquid_level;
725                                 if (level_inc < -viscosity || level_inc > viscosity)
726                                         new_node_level = liquid_level + level_inc/viscosity;
727                                 else if (level_inc < 0)
728                                         new_node_level = liquid_level - 1;
729                                 else if (level_inc > 0)
730                                         new_node_level = liquid_level + 1;
731                                 if (new_node_level != max_node_level)
732                                         must_reflow.push_back(p0);
733                         } else {
734                                 new_node_level = max_node_level;
735                         }
736
737                         if (max_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
738                                 new_node_content = liquid_kind;
739                         else
740                                 new_node_content = floodable_node;
741
742                 }
743
744                 /*
745                         check if anything has changed. if not, just continue with the next node.
746                  */
747                 if (new_node_content == n0.getContent() &&
748                                 (m_nodedef->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
749                                 ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
750                                 ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
751                                 == flowing_down)))
752                         continue;
753
754
755                 /*
756                         update the current node
757                  */
758                 MapNode n00 = n0;
759                 //bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
760                 if (m_nodedef->get(new_node_content).liquid_type == LIQUID_FLOWING) {
761                         // set level to last 3 bits, flowing down bit to 4th bit
762                         n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
763                 } else {
764                         // set the liquid level and flow bits to 0
765                         n0.param2 &= ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
766                 }
767
768                 // change the node.
769                 n0.setContent(new_node_content);
770
771                 // on_flood() the node
772                 if (floodable_node != CONTENT_AIR) {
773                         if (env->getScriptIface()->node_on_flood(p0, n00, n0))
774                                 continue;
775                 }
776
777                 // Ignore light (because calling voxalgo::update_lighting_nodes)
778                 n0.setLight(LIGHTBANK_DAY, 0, m_nodedef);
779                 n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
780
781                 // Find out whether there is a suspect for this action
782                 std::string suspect;
783                 if (m_gamedef->rollback())
784                         suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
785
786                 if (m_gamedef->rollback() && !suspect.empty()) {
787                         // Blame suspect
788                         RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
789                         // Get old node for rollback
790                         RollbackNode rollback_oldnode(this, p0, m_gamedef);
791                         // Set node
792                         setNode(p0, n0);
793                         // Report
794                         RollbackNode rollback_newnode(this, p0, m_gamedef);
795                         RollbackAction action;
796                         action.setSetNode(p0, rollback_oldnode, rollback_newnode);
797                         m_gamedef->rollback()->reportAction(action);
798                 } else {
799                         // Set node
800                         setNode(p0, n0);
801                 }
802
803                 v3s16 blockpos = getNodeBlockPos(p0);
804                 MapBlock *block = getBlockNoCreateNoEx(blockpos);
805                 if (block != NULL) {
806                         modified_blocks[blockpos] =  block;
807                         changed_nodes.emplace_back(p0, n00);
808                 }
809
810                 /*
811                         enqueue neighbors for update if neccessary
812                  */
813                 switch (m_nodedef->get(n0.getContent()).liquid_type) {
814                         case LIQUID_SOURCE:
815                         case LIQUID_FLOWING:
816                                 // make sure source flows into all neighboring nodes
817                                 for (u16 i = 0; i < num_flows; i++)
818                                         if (flows[i].t != NEIGHBOR_UPPER)
819                                                 m_transforming_liquid.push_back(flows[i].p);
820                                 for (u16 i = 0; i < num_airs; i++)
821                                         if (airs[i].t != NEIGHBOR_UPPER)
822                                                 m_transforming_liquid.push_back(airs[i].p);
823                                 break;
824                         case LIQUID_NONE:
825                                 // this flow has turned to air; neighboring flows might need to do the same
826                                 for (u16 i = 0; i < num_flows; i++)
827                                         m_transforming_liquid.push_back(flows[i].p);
828                                 break;
829                 }
830         }
831         //infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
832
833         for (auto &iter : must_reflow)
834                 m_transforming_liquid.push_back(iter);
835
836         voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks);
837
838
839         /* ----------------------------------------------------------------------
840          * Manage the queue so that it does not grow indefinately
841          */
842         u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
843
844         if (time_until_purge == 0)
845                 return; // Feature disabled
846
847         time_until_purge *= 1000;       // seconds -> milliseconds
848
849         u64 curr_time = porting::getTimeMs();
850         u32 prev_unprocessed = m_unprocessed_count;
851         m_unprocessed_count = m_transforming_liquid.size();
852
853         // if unprocessed block count is decreasing or stable
854         if (m_unprocessed_count <= prev_unprocessed) {
855                 m_queue_size_timer_started = false;
856         } else {
857                 if (!m_queue_size_timer_started)
858                         m_inc_trending_up_start_time = curr_time;
859                 m_queue_size_timer_started = true;
860         }
861
862         // Account for curr_time overflowing
863         if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
864                 m_queue_size_timer_started = false;
865
866         /* If the queue has been growing for more than liquid_queue_purge_time seconds
867          * and the number of unprocessed blocks is still > liquid_loop_max then we
868          * cannot keep up; dump the oldest blocks from the queue so that the queue
869          * has liquid_loop_max items in it
870          */
871         if (m_queue_size_timer_started
872                         && curr_time - m_inc_trending_up_start_time > time_until_purge
873                         && m_unprocessed_count > liquid_loop_max) {
874
875                 size_t dump_qty = m_unprocessed_count - liquid_loop_max;
876
877                 infostream << "transformLiquids(): DUMPING " << dump_qty
878                            << " blocks from the queue" << std::endl;
879
880                 while (dump_qty--)
881                         m_transforming_liquid.pop_front();
882
883                 m_queue_size_timer_started = false; // optimistically assume we can keep up now
884                 m_unprocessed_count = m_transforming_liquid.size();
885         }
886 }
887
888 std::vector<v3s16> Map::findNodesWithMetadata(v3s16 p1, v3s16 p2)
889 {
890         std::vector<v3s16> positions_with_meta;
891
892         sortBoxVerticies(p1, p2);
893         v3s16 bpmin = getNodeBlockPos(p1);
894         v3s16 bpmax = getNodeBlockPos(p2);
895
896         VoxelArea area(p1, p2);
897
898         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
899         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
900         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
901                 v3s16 blockpos(x, y, z);
902
903                 MapBlock *block = getBlockNoCreateNoEx(blockpos);
904                 if (!block) {
905                         verbosestream << "Map::getNodeMetadata(): Need to emerge "
906                                 << PP(blockpos) << std::endl;
907                         block = emergeBlock(blockpos, false);
908                 }
909                 if (!block) {
910                         infostream << "WARNING: Map::getNodeMetadata(): Block not found"
911                                 << std::endl;
912                         continue;
913                 }
914
915                 v3s16 p_base = blockpos * MAP_BLOCKSIZE;
916                 std::vector<v3s16> keys = block->m_node_metadata.getAllKeys();
917                 for (size_t i = 0; i != keys.size(); i++) {
918                         v3s16 p(keys[i] + p_base);
919                         if (!area.contains(p))
920                                 continue;
921
922                         positions_with_meta.push_back(p);
923                 }
924         }
925
926         return positions_with_meta;
927 }
928
929 NodeMetadata *Map::getNodeMetadata(v3s16 p)
930 {
931         v3s16 blockpos = getNodeBlockPos(p);
932         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
933         MapBlock *block = getBlockNoCreateNoEx(blockpos);
934         if(!block){
935                 infostream<<"Map::getNodeMetadata(): Need to emerge "
936                                 <<PP(blockpos)<<std::endl;
937                 block = emergeBlock(blockpos, false);
938         }
939         if(!block){
940                 warningstream<<"Map::getNodeMetadata(): Block not found"
941                                 <<std::endl;
942                 return NULL;
943         }
944         NodeMetadata *meta = block->m_node_metadata.get(p_rel);
945         return meta;
946 }
947
948 bool Map::setNodeMetadata(v3s16 p, NodeMetadata *meta)
949 {
950         v3s16 blockpos = getNodeBlockPos(p);
951         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
952         MapBlock *block = getBlockNoCreateNoEx(blockpos);
953         if(!block){
954                 infostream<<"Map::setNodeMetadata(): Need to emerge "
955                                 <<PP(blockpos)<<std::endl;
956                 block = emergeBlock(blockpos, false);
957         }
958         if(!block){
959                 warningstream<<"Map::setNodeMetadata(): Block not found"
960                                 <<std::endl;
961                 return false;
962         }
963         block->m_node_metadata.set(p_rel, meta);
964         return true;
965 }
966
967 void Map::removeNodeMetadata(v3s16 p)
968 {
969         v3s16 blockpos = getNodeBlockPos(p);
970         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
971         MapBlock *block = getBlockNoCreateNoEx(blockpos);
972         if(block == NULL)
973         {
974                 warningstream<<"Map::removeNodeMetadata(): Block not found"
975                                 <<std::endl;
976                 return;
977         }
978         block->m_node_metadata.remove(p_rel);
979 }
980
981 NodeTimer Map::getNodeTimer(v3s16 p)
982 {
983         v3s16 blockpos = getNodeBlockPos(p);
984         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
985         MapBlock *block = getBlockNoCreateNoEx(blockpos);
986         if(!block){
987                 infostream<<"Map::getNodeTimer(): Need to emerge "
988                                 <<PP(blockpos)<<std::endl;
989                 block = emergeBlock(blockpos, false);
990         }
991         if(!block){
992                 warningstream<<"Map::getNodeTimer(): Block not found"
993                                 <<std::endl;
994                 return NodeTimer();
995         }
996         NodeTimer t = block->m_node_timers.get(p_rel);
997         NodeTimer nt(t.timeout, t.elapsed, p);
998         return nt;
999 }
1000
1001 void Map::setNodeTimer(const NodeTimer &t)
1002 {
1003         v3s16 p = t.position;
1004         v3s16 blockpos = getNodeBlockPos(p);
1005         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
1006         MapBlock *block = getBlockNoCreateNoEx(blockpos);
1007         if(!block){
1008                 infostream<<"Map::setNodeTimer(): Need to emerge "
1009                                 <<PP(blockpos)<<std::endl;
1010                 block = emergeBlock(blockpos, false);
1011         }
1012         if(!block){
1013                 warningstream<<"Map::setNodeTimer(): Block not found"
1014                                 <<std::endl;
1015                 return;
1016         }
1017         NodeTimer nt(t.timeout, t.elapsed, p_rel);
1018         block->m_node_timers.set(nt);
1019 }
1020
1021 void Map::removeNodeTimer(v3s16 p)
1022 {
1023         v3s16 blockpos = getNodeBlockPos(p);
1024         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
1025         MapBlock *block = getBlockNoCreateNoEx(blockpos);
1026         if(block == NULL)
1027         {
1028                 warningstream<<"Map::removeNodeTimer(): Block not found"
1029                                 <<std::endl;
1030                 return;
1031         }
1032         block->m_node_timers.remove(p_rel);
1033 }
1034
1035 bool Map::determineAdditionalOcclusionCheck(const v3s16 &pos_camera,
1036         const core::aabbox3d<s16> &block_bounds, v3s16 &check)
1037 {
1038         /*
1039                 This functions determines the node inside the target block that is
1040                 closest to the camera position. This increases the occlusion culling
1041                 accuracy in straight and diagonal corridors.
1042                 The returned position will be occlusion checked first in addition to the
1043                 others (8 corners + center).
1044                 No position is returned if
1045                 - the closest node is a corner, corners are checked anyway.
1046                 - the camera is inside the target block, it will never be occluded.
1047         */
1048 #define CLOSEST_EDGE(pos, bounds, axis) \
1049         ((pos).axis <= (bounds).MinEdge.axis) ? (bounds).MinEdge.axis : \
1050         (bounds).MaxEdge.axis
1051
1052         bool x_inside = (block_bounds.MinEdge.X <= pos_camera.X) &&
1053                         (pos_camera.X <= block_bounds.MaxEdge.X);
1054         bool y_inside = (block_bounds.MinEdge.Y <= pos_camera.Y) &&
1055                         (pos_camera.Y <= block_bounds.MaxEdge.Y);
1056         bool z_inside = (block_bounds.MinEdge.Z <= pos_camera.Z) &&
1057                         (pos_camera.Z <= block_bounds.MaxEdge.Z);
1058
1059         if (x_inside && y_inside && z_inside)
1060                 return false; // Camera inside target mapblock
1061
1062         // straight
1063         if (x_inside && y_inside) {
1064                 check = v3s16(pos_camera.X, pos_camera.Y, 0);
1065                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1066                 return true;
1067         } else if (y_inside && z_inside) {
1068                 check = v3s16(0, pos_camera.Y, pos_camera.Z);
1069                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1070                 return true;
1071         } else if (x_inside && z_inside) {
1072                 check = v3s16(pos_camera.X, 0, pos_camera.Z);
1073                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1074                 return true;
1075         }
1076
1077         // diagonal
1078         if (x_inside) {
1079                 check = v3s16(pos_camera.X, 0, 0);
1080                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1081                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1082                 return true;
1083         } else if (y_inside) {
1084                 check = v3s16(0, pos_camera.Y, 0);
1085                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1086                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1087                 return true;
1088         } else if (z_inside) {
1089                 check = v3s16(0, 0, pos_camera.Z);
1090                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1091                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1092                 return true;
1093         }
1094
1095         // Closest node would be a corner, none returned
1096         return false;
1097 }
1098
1099 bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
1100         float step, float stepfac, float offset, float end_offset, u32 needed_count)
1101 {
1102         v3f direction = intToFloat(pos_target - pos_camera, BS);
1103         float distance = direction.getLength();
1104
1105         // Normalize direction vector
1106         if (distance > 0.0f)
1107                 direction /= distance;
1108
1109         v3f pos_origin_f = intToFloat(pos_camera, BS);
1110         u32 count = 0;
1111         bool is_valid_position;
1112
1113         for (; offset < distance + end_offset; offset += step) {
1114                 v3f pos_node_f = pos_origin_f + direction * offset;
1115                 v3s16 pos_node = floatToInt(pos_node_f, BS);
1116
1117                 MapNode node = getNode(pos_node, &is_valid_position);
1118
1119                 if (is_valid_position &&
1120                                 !m_nodedef->get(node).light_propagates) {
1121                         // Cannot see through light-blocking nodes --> occluded
1122                         count++;
1123                         if (count >= needed_count)
1124                                 return true;
1125                 }
1126                 step *= stepfac;
1127         }
1128         return false;
1129 }
1130
1131 bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
1132 {
1133         // Check occlusion for center and all 8 corners of the mapblock
1134         // Overshoot a little for less flickering
1135         static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
1136         static const v3s16 dir9[9] = {
1137                 v3s16( 0,  0,  0),
1138                 v3s16( 1,  1,  1) * bs2,
1139                 v3s16( 1,  1, -1) * bs2,
1140                 v3s16( 1, -1,  1) * bs2,
1141                 v3s16( 1, -1, -1) * bs2,
1142                 v3s16(-1,  1,  1) * bs2,
1143                 v3s16(-1,  1, -1) * bs2,
1144                 v3s16(-1, -1,  1) * bs2,
1145                 v3s16(-1, -1, -1) * bs2,
1146         };
1147
1148         v3s16 pos_blockcenter = block->getPosRelative() + (MAP_BLOCKSIZE / 2);
1149
1150         // Starting step size, value between 1m and sqrt(3)m
1151         float step = BS * 1.2f;
1152         // Multiply step by each iteraction by 'stepfac' to reduce checks in distance
1153         float stepfac = 1.05f;
1154
1155         float start_offset = BS * 1.0f;
1156
1157         // The occlusion search of 'isOccluded()' must stop short of the target
1158         // point by distance 'end_offset' to not enter the target mapblock.
1159         // For the 8 mapblock corners 'end_offset' must therefore be the maximum
1160         // diagonal of a mapblock, because we must consider all view angles.
1161         // sqrt(1^2 + 1^2 + 1^2) = 1.732
1162         float end_offset = -BS * MAP_BLOCKSIZE * 1.732f;
1163
1164         // to reduce the likelihood of falsely occluded blocks
1165         // require at least two solid blocks
1166         // this is a HACK, we should think of a more precise algorithm
1167         u32 needed_count = 2;
1168
1169         // Additional occlusion check, see comments in that function
1170         v3s16 check;
1171         if (determineAdditionalOcclusionCheck(cam_pos_nodes, block->getBox(), check)) {
1172                 // node is always on a side facing the camera, end_offset can be lower
1173                 if (!isOccluded(cam_pos_nodes, check, step, stepfac, start_offset,
1174                                 -1.0f, needed_count))
1175                         return false;
1176         }
1177
1178         for (const v3s16 &dir : dir9) {
1179                 if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir, step, stepfac,
1180                                 start_offset, end_offset, needed_count))
1181                         return false;
1182         }
1183         return true;
1184 }
1185
1186 /*
1187         ServerMap
1188 */
1189 ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
1190                 EmergeManager *emerge):
1191         Map(dout_server, gamedef),
1192         settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
1193         m_emerge(emerge)
1194 {
1195         verbosestream<<FUNCTION_NAME<<std::endl;
1196
1197         // Tell the EmergeManager about our MapSettingsManager
1198         emerge->map_settings_mgr = &settings_mgr;
1199
1200         /*
1201                 Try to load map; if not found, create a new one.
1202         */
1203
1204         // Determine which database backend to use
1205         std::string conf_path = savedir + DIR_DELIM + "world.mt";
1206         Settings conf;
1207         bool succeeded = conf.readConfigFile(conf_path.c_str());
1208         if (!succeeded || !conf.exists("backend")) {
1209                 // fall back to sqlite3
1210                 conf.set("backend", "sqlite3");
1211         }
1212         std::string backend = conf.get("backend");
1213         dbase = createDatabase(backend, savedir, conf);
1214         if (conf.exists("readonly_backend")) {
1215                 std::string readonly_dir = savedir + DIR_DELIM + "readonly";
1216                 dbase_ro = createDatabase(conf.get("readonly_backend"), readonly_dir, conf);
1217         }
1218         if (!conf.updateConfigFile(conf_path.c_str()))
1219                 errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl;
1220
1221         m_savedir = savedir;
1222         m_map_saving_enabled = false;
1223
1224         try {
1225                 // If directory exists, check contents and load if possible
1226                 if (fs::PathExists(m_savedir)) {
1227                         // If directory is empty, it is safe to save into it.
1228                         if (fs::GetDirListing(m_savedir).empty()) {
1229                                 infostream<<"ServerMap: Empty save directory is valid."
1230                                                 <<std::endl;
1231                                 m_map_saving_enabled = true;
1232                         }
1233                         else
1234                         {
1235
1236                                 if (settings_mgr.loadMapMeta()) {
1237                                         infostream << "ServerMap: Metadata loaded from "
1238                                                 << savedir << std::endl;
1239                                 } else {
1240                                         infostream << "ServerMap: Metadata could not be loaded "
1241                                                 "from " << savedir << ", assuming valid save "
1242                                                 "directory." << std::endl;
1243                                 }
1244
1245                                 m_map_saving_enabled = true;
1246                                 // Map loaded, not creating new one
1247                                 return;
1248                         }
1249                 }
1250                 // If directory doesn't exist, it is safe to save to it
1251                 else{
1252                         m_map_saving_enabled = true;
1253                 }
1254         }
1255         catch(std::exception &e)
1256         {
1257                 warningstream<<"ServerMap: Failed to load map from "<<savedir
1258                                 <<", exception: "<<e.what()<<std::endl;
1259                 infostream<<"Please remove the map or fix it."<<std::endl;
1260                 warningstream<<"Map saving will be disabled."<<std::endl;
1261         }
1262 }
1263
1264 ServerMap::~ServerMap()
1265 {
1266         verbosestream<<FUNCTION_NAME<<std::endl;
1267
1268         try
1269         {
1270                 if (m_map_saving_enabled) {
1271                         // Save only changed parts
1272                         save(MOD_STATE_WRITE_AT_UNLOAD);
1273                         infostream << "ServerMap: Saved map to " << m_savedir << std::endl;
1274                 } else {
1275                         infostream << "ServerMap: Map not saved" << std::endl;
1276                 }
1277         }
1278         catch(std::exception &e)
1279         {
1280                 infostream<<"ServerMap: Failed to save map to "<<m_savedir
1281                                 <<", exception: "<<e.what()<<std::endl;
1282         }
1283
1284         /*
1285                 Close database if it was opened
1286         */
1287         delete dbase;
1288         delete dbase_ro;
1289
1290 #if 0
1291         /*
1292                 Free all MapChunks
1293         */
1294         core::map<v2s16, MapChunk*>::Iterator i = m_chunks.getIterator();
1295         for(; i.atEnd() == false; i++)
1296         {
1297                 MapChunk *chunk = i.getNode()->getValue();
1298                 delete chunk;
1299         }
1300 #endif
1301 }
1302
1303 MapgenParams *ServerMap::getMapgenParams()
1304 {
1305         // getMapgenParams() should only ever be called after Server is initialized
1306         assert(settings_mgr.mapgen_params != NULL);
1307         return settings_mgr.mapgen_params;
1308 }
1309
1310 u64 ServerMap::getSeed()
1311 {
1312         return getMapgenParams()->seed;
1313 }
1314
1315 s16 ServerMap::getWaterLevel()
1316 {
1317         return getMapgenParams()->water_level;
1318 }
1319
1320 bool ServerMap::blockpos_over_mapgen_limit(v3s16 p)
1321 {
1322         const s16 mapgen_limit_bp = rangelim(
1323                 getMapgenParams()->mapgen_limit, 0, MAX_MAP_GENERATION_LIMIT) /
1324                 MAP_BLOCKSIZE;
1325         return p.X < -mapgen_limit_bp ||
1326                 p.X >  mapgen_limit_bp ||
1327                 p.Y < -mapgen_limit_bp ||
1328                 p.Y >  mapgen_limit_bp ||
1329                 p.Z < -mapgen_limit_bp ||
1330                 p.Z >  mapgen_limit_bp;
1331 }
1332
1333 bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
1334 {
1335         s16 csize = getMapgenParams()->chunksize;
1336         v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize);
1337         v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1);
1338
1339         bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
1340         EMERGE_DBG_OUT("initBlockMake(): " PP(bpmin) " - " PP(bpmax));
1341
1342         v3s16 extra_borders(1, 1, 1);
1343         v3s16 full_bpmin = bpmin - extra_borders;
1344         v3s16 full_bpmax = bpmax + extra_borders;
1345
1346         // Do nothing if not inside mapgen limits (+-1 because of neighbors)
1347         if (blockpos_over_mapgen_limit(full_bpmin) ||
1348                         blockpos_over_mapgen_limit(full_bpmax))
1349                 return false;
1350
1351         data->seed = getSeed();
1352         data->blockpos_min = bpmin;
1353         data->blockpos_max = bpmax;
1354         data->blockpos_requested = blockpos;
1355         data->nodedef = m_nodedef;
1356
1357         /*
1358                 Create the whole area of this and the neighboring blocks
1359         */
1360         for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
1361         for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++) {
1362                 v2s16 sectorpos(x, z);
1363                 // Sector metadata is loaded from disk if not already loaded.
1364                 MapSector *sector = createSector(sectorpos);
1365                 FATAL_ERROR_IF(sector == NULL, "createSector() failed");
1366
1367                 for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
1368                         v3s16 p(x, y, z);
1369
1370                         MapBlock *block = emergeBlock(p, false);
1371                         if (block == NULL) {
1372                                 block = createBlock(p);
1373
1374                                 // Block gets sunlight if this is true.
1375                                 // Refer to the map generator heuristics.
1376                                 bool ug = m_emerge->isBlockUnderground(p);
1377                                 block->setIsUnderground(ug);
1378                         }
1379                 }
1380         }
1381
1382         /*
1383                 Now we have a big empty area.
1384
1385                 Make a ManualMapVoxelManipulator that contains this and the
1386                 neighboring blocks
1387         */
1388
1389         data->vmanip = new MMVManip(this);
1390         data->vmanip->initialEmerge(full_bpmin, full_bpmax);
1391
1392         // Note: we may need this again at some point.
1393 #if 0
1394         // Ensure none of the blocks to be generated were marked as
1395         // containing CONTENT_IGNORE
1396         for (s16 z = blockpos_min.Z; z <= blockpos_max.Z; z++) {
1397                 for (s16 y = blockpos_min.Y; y <= blockpos_max.Y; y++) {
1398                         for (s16 x = blockpos_min.X; x <= blockpos_max.X; x++) {
1399                                 core::map<v3s16, u8>::Node *n;
1400                                 n = data->vmanip->m_loaded_blocks.find(v3s16(x, y, z));
1401                                 if (n == NULL)
1402                                         continue;
1403                                 u8 flags = n->getValue();
1404                                 flags &= ~VMANIP_BLOCK_CONTAINS_CIGNORE;
1405                                 n->setValue(flags);
1406                         }
1407                 }
1408         }
1409 #endif
1410
1411         // Data is ready now.
1412         return true;
1413 }
1414
1415 void ServerMap::finishBlockMake(BlockMakeData *data,
1416         std::map<v3s16, MapBlock*> *changed_blocks)
1417 {
1418         v3s16 bpmin = data->blockpos_min;
1419         v3s16 bpmax = data->blockpos_max;
1420
1421         v3s16 extra_borders(1, 1, 1);
1422
1423         bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
1424         EMERGE_DBG_OUT("finishBlockMake(): " PP(bpmin) " - " PP(bpmax));
1425
1426         /*
1427                 Blit generated stuff to map
1428                 NOTE: blitBackAll adds nearly everything to changed_blocks
1429         */
1430         data->vmanip->blitBackAll(changed_blocks);
1431
1432         EMERGE_DBG_OUT("finishBlockMake: changed_blocks.size()="
1433                 << changed_blocks->size());
1434
1435         /*
1436                 Copy transforming liquid information
1437         */
1438         while (data->transforming_liquid.size()) {
1439                 m_transforming_liquid.push_back(data->transforming_liquid.front());
1440                 data->transforming_liquid.pop_front();
1441         }
1442
1443         for (auto &changed_block : *changed_blocks) {
1444                 MapBlock *block = changed_block.second;
1445                 if (!block)
1446                         continue;
1447                 /*
1448                         Update day/night difference cache of the MapBlocks
1449                 */
1450                 block->expireDayNightDiff();
1451                 /*
1452                         Set block as modified
1453                 */
1454                 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1455                         MOD_REASON_EXPIRE_DAYNIGHTDIFF);
1456         }
1457
1458         /*
1459                 Set central blocks as generated
1460         */
1461         for (s16 x = bpmin.X; x <= bpmax.X; x++)
1462         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1463         for (s16 y = bpmin.Y; y <= bpmax.Y; y++) {
1464                 MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
1465                 if (!block)
1466                         continue;
1467
1468                 block->setGenerated(true);
1469         }
1470
1471         /*
1472                 Save changed parts of map
1473                 NOTE: Will be saved later.
1474         */
1475         //save(MOD_STATE_WRITE_AT_UNLOAD);
1476 }
1477
1478 MapSector *ServerMap::createSector(v2s16 p2d)
1479 {
1480         /*
1481                 Check if it exists already in memory
1482         */
1483         MapSector *sector = getSectorNoGenerate(p2d);
1484         if (sector)
1485                 return sector;
1486
1487         /*
1488                 Do not create over max mapgen limit
1489         */
1490         const s16 max_limit_bp = MAX_MAP_GENERATION_LIMIT / MAP_BLOCKSIZE;
1491         if (p2d.X < -max_limit_bp ||
1492                         p2d.X >  max_limit_bp ||
1493                         p2d.Y < -max_limit_bp ||
1494                         p2d.Y >  max_limit_bp)
1495                 throw InvalidPositionException("createSector(): pos. over max mapgen limit");
1496
1497         /*
1498                 Generate blank sector
1499         */
1500
1501         sector = new MapSector(this, p2d, m_gamedef);
1502
1503         // Sector position on map in nodes
1504         //v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
1505
1506         /*
1507                 Insert to container
1508         */
1509         m_sectors[p2d] = sector;
1510
1511         return sector;
1512 }
1513
1514 #if 0
1515 /*
1516         This is a quick-hand function for calling makeBlock().
1517 */
1518 MapBlock * ServerMap::generateBlock(
1519                 v3s16 p,
1520                 std::map<v3s16, MapBlock*> &modified_blocks
1521 )
1522 {
1523         bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
1524
1525         TimeTaker timer("generateBlock");
1526
1527         //MapBlock *block = original_dummy;
1528
1529         v2s16 p2d(p.X, p.Z);
1530         v2s16 p2d_nodes = p2d * MAP_BLOCKSIZE;
1531
1532         /*
1533                 Do not generate over-limit
1534         */
1535         if(blockpos_over_limit(p))
1536         {
1537                 infostream<<FUNCTION_NAME<<": Block position over limit"<<std::endl;
1538                 throw InvalidPositionException("generateBlock(): pos. over limit");
1539         }
1540
1541         /*
1542                 Create block make data
1543         */
1544         BlockMakeData data;
1545         initBlockMake(&data, p);
1546
1547         /*
1548                 Generate block
1549         */
1550         {
1551                 TimeTaker t("mapgen::make_block()");
1552                 mapgen->makeChunk(&data);
1553                 //mapgen::make_block(&data);
1554
1555                 if(enable_mapgen_debug_info == false)
1556                         t.stop(true); // Hide output
1557         }
1558
1559         /*
1560                 Blit data back on map, update lighting, add mobs and whatever this does
1561         */
1562         finishBlockMake(&data, modified_blocks);
1563
1564         /*
1565                 Get central block
1566         */
1567         MapBlock *block = getBlockNoCreateNoEx(p);
1568
1569 #if 0
1570         /*
1571                 Check result
1572         */
1573         if(block)
1574         {
1575                 bool erroneus_content = false;
1576                 for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
1577                 for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
1578                 for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
1579                 {
1580                         v3s16 p(x0,y0,z0);
1581                         MapNode n = block->getNode(p);
1582                         if(n.getContent() == CONTENT_IGNORE)
1583                         {
1584                                 infostream<<"CONTENT_IGNORE at "
1585                                                 <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
1586                                                 <<std::endl;
1587                                 erroneus_content = true;
1588                                 assert(0);
1589                         }
1590                 }
1591                 if(erroneus_content)
1592                 {
1593                         assert(0);
1594                 }
1595         }
1596 #endif
1597
1598 #if 0
1599         /*
1600                 Generate a completely empty block
1601         */
1602         if(block)
1603         {
1604                 for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
1605                 for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
1606                 {
1607                         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
1608                         {
1609                                 MapNode n;
1610                                 n.setContent(CONTENT_AIR);
1611                                 block->setNode(v3s16(x0,y0,z0), n);
1612                         }
1613                 }
1614         }
1615 #endif
1616
1617         if(enable_mapgen_debug_info == false)
1618                 timer.stop(true); // Hide output
1619
1620         return block;
1621 }
1622 #endif
1623
1624 MapBlock * ServerMap::createBlock(v3s16 p)
1625 {
1626         /*
1627                 Do not create over max mapgen limit
1628         */
1629         if (blockpos_over_max_limit(p))
1630                 throw InvalidPositionException("createBlock(): pos. over max mapgen limit");
1631
1632         v2s16 p2d(p.X, p.Z);
1633         s16 block_y = p.Y;
1634         /*
1635                 This will create or load a sector if not found in memory.
1636                 If block exists on disk, it will be loaded.
1637
1638                 NOTE: On old save formats, this will be slow, as it generates
1639                       lighting on blocks for them.
1640         */
1641         MapSector *sector;
1642         try {
1643                 sector = createSector(p2d);
1644         } catch (InvalidPositionException &e) {
1645                 infostream<<"createBlock: createSector() failed"<<std::endl;
1646                 throw e;
1647         }
1648
1649         /*
1650                 Try to get a block from the sector
1651         */
1652
1653         MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
1654         if (block) {
1655                 if(block->isDummy())
1656                         block->unDummify();
1657                 return block;
1658         }
1659         // Create blank
1660         block = sector->createBlankBlock(block_y);
1661
1662         return block;
1663 }
1664
1665 MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
1666 {
1667         {
1668                 MapBlock *block = getBlockNoCreateNoEx(p);
1669                 if (block && !block->isDummy())
1670                         return block;
1671         }
1672
1673         {
1674                 MapBlock *block = loadBlock(p);
1675                 if(block)
1676                         return block;
1677         }
1678
1679         if (create_blank) {
1680                 MapSector *sector = createSector(v2s16(p.X, p.Z));
1681                 MapBlock *block = sector->createBlankBlock(p.Y);
1682
1683                 return block;
1684         }
1685
1686         return NULL;
1687 }
1688
1689 MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d)
1690 {
1691         MapBlock *block = getBlockNoCreateNoEx(p3d);
1692         if (block == NULL)
1693                 m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, p3d, false);
1694
1695         return block;
1696 }
1697
1698 // N.B.  This requires no synchronization, since data will not be modified unless
1699 // the VoxelManipulator being updated belongs to the same thread.
1700 void ServerMap::updateVManip(v3s16 pos)
1701 {
1702         Mapgen *mg = m_emerge->getCurrentMapgen();
1703         if (!mg)
1704                 return;
1705
1706         MMVManip *vm = mg->vm;
1707         if (!vm)
1708                 return;
1709
1710         if (!vm->m_area.contains(pos))
1711                 return;
1712
1713         s32 idx = vm->m_area.index(pos);
1714         vm->m_data[idx] = getNode(pos);
1715         vm->m_flags[idx] &= ~VOXELFLAG_NO_DATA;
1716
1717         vm->m_is_dirty = true;
1718 }
1719
1720 s16 ServerMap::findGroundLevel(v2s16 p2d)
1721 {
1722 #if 0
1723         /*
1724                 Uh, just do something random...
1725         */
1726         // Find existing map from top to down
1727         s16 max=63;
1728         s16 min=-64;
1729         v3s16 p(p2d.X, max, p2d.Y);
1730         for(; p.Y>min; p.Y--)
1731         {
1732                 MapNode n = getNodeNoEx(p);
1733                 if(n.getContent() != CONTENT_IGNORE)
1734                         break;
1735         }
1736         if(p.Y == min)
1737                 goto plan_b;
1738         // If this node is not air, go to plan b
1739         if(getNodeNoEx(p).getContent() != CONTENT_AIR)
1740                 goto plan_b;
1741         // Search existing walkable and return it
1742         for(; p.Y>min; p.Y--)
1743         {
1744                 MapNode n = getNodeNoEx(p);
1745                 if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE)
1746                         return p.Y;
1747         }
1748
1749         // Move to plan b
1750 plan_b:
1751 #endif
1752
1753         /*
1754                 Determine from map generator noise functions
1755         */
1756
1757         s16 level = m_emerge->getGroundLevelAtPoint(p2d);
1758         return level;
1759
1760         //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
1761         //return (s16)level;
1762 }
1763
1764 void ServerMap::createDirs(const std::string &path)
1765 {
1766         if (!fs::CreateAllDirs(path)) {
1767                 m_dout<<"ServerMap: Failed to create directory "
1768                                 <<"\""<<path<<"\""<<std::endl;
1769                 throw BaseException("ServerMap failed to create directory");
1770         }
1771 }
1772
1773 void ServerMap::save(ModifiedState save_level)
1774 {
1775         if (!m_map_saving_enabled) {
1776                 warningstream<<"Not saving map, saving disabled."<<std::endl;
1777                 return;
1778         }
1779
1780         if(save_level == MOD_STATE_CLEAN)
1781                 infostream<<"ServerMap: Saving whole map, this can take time."
1782                                 <<std::endl;
1783
1784         if (m_map_metadata_changed || save_level == MOD_STATE_CLEAN) {
1785                 if (settings_mgr.saveMapMeta())
1786                         m_map_metadata_changed = false;
1787         }
1788
1789         // Profile modified reasons
1790         Profiler modprofiler;
1791
1792         u32 block_count = 0;
1793         u32 block_count_all = 0; // Number of blocks in memory
1794
1795         // Don't do anything with sqlite unless something is really saved
1796         bool save_started = false;
1797
1798         for (auto &sector_it : m_sectors) {
1799                 MapSector *sector = sector_it.second;
1800
1801                 MapBlockVect blocks;
1802                 sector->getBlocks(blocks);
1803
1804                 for (MapBlock *block : blocks) {
1805                         block_count_all++;
1806
1807                         if(block->getModified() >= (u32)save_level) {
1808                                 // Lazy beginSave()
1809                                 if(!save_started) {
1810                                         beginSave();
1811                                         save_started = true;
1812                                 }
1813
1814                                 modprofiler.add(block->getModifiedReasonString(), 1);
1815
1816                                 saveBlock(block);
1817                                 block_count++;
1818                         }
1819                 }
1820         }
1821
1822         if(save_started)
1823                 endSave();
1824
1825         /*
1826                 Only print if something happened or saved whole map
1827         */
1828         if(save_level == MOD_STATE_CLEAN
1829                         || block_count != 0) {
1830                 infostream<<"ServerMap: Written: "
1831                                 <<block_count<<" block files"
1832                                 <<", "<<block_count_all<<" blocks in memory."
1833                                 <<std::endl;
1834                 PrintInfo(infostream); // ServerMap/ClientMap:
1835                 infostream<<"Blocks modified by: "<<std::endl;
1836                 modprofiler.print(infostream);
1837         }
1838 }
1839
1840 void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
1841 {
1842         dbase->listAllLoadableBlocks(dst);
1843         if (dbase_ro)
1844                 dbase_ro->listAllLoadableBlocks(dst);
1845 }
1846
1847 void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
1848 {
1849         for (auto &sector_it : m_sectors) {
1850                 MapSector *sector = sector_it.second;
1851
1852                 MapBlockVect blocks;
1853                 sector->getBlocks(blocks);
1854
1855                 for (MapBlock *block : blocks) {
1856                         v3s16 p = block->getPos();
1857                         dst.push_back(p);
1858                 }
1859         }
1860 }
1861
1862 MapDatabase *ServerMap::createDatabase(
1863         const std::string &name,
1864         const std::string &savedir,
1865         Settings &conf)
1866 {
1867         if (name == "sqlite3")
1868                 return new MapDatabaseSQLite3(savedir);
1869         if (name == "dummy")
1870                 return new Database_Dummy();
1871         #if USE_LEVELDB
1872         if (name == "leveldb")
1873                 return new Database_LevelDB(savedir);
1874         #endif
1875         #if USE_REDIS
1876         if (name == "redis")
1877                 return new Database_Redis(conf);
1878         #endif
1879         #if USE_POSTGRESQL
1880         if (name == "postgresql") {
1881                 std::string connect_string;
1882                 conf.getNoEx("pgsql_connection", connect_string);
1883                 return new MapDatabasePostgreSQL(connect_string);
1884         }
1885         #endif
1886
1887         throw BaseException(std::string("Database backend ") + name + " not supported.");
1888 }
1889
1890 void ServerMap::beginSave()
1891 {
1892         dbase->beginSave();
1893 }
1894
1895 void ServerMap::endSave()
1896 {
1897         dbase->endSave();
1898 }
1899
1900 bool ServerMap::saveBlock(MapBlock *block)
1901 {
1902         return saveBlock(block, dbase);
1903 }
1904
1905 bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db)
1906 {
1907         v3s16 p3d = block->getPos();
1908
1909         // Dummy blocks are not written
1910         if (block->isDummy()) {
1911                 warningstream << "saveBlock: Not writing dummy block "
1912                         << PP(p3d) << std::endl;
1913                 return true;
1914         }
1915
1916         // Format used for writing
1917         u8 version = SER_FMT_VER_HIGHEST_WRITE;
1918
1919         /*
1920                 [0] u8 serialization version
1921                 [1] data
1922         */
1923         std::ostringstream o(std::ios_base::binary);
1924         o.write((char*) &version, 1);
1925         block->serialize(o, version, true);
1926
1927         bool ret = db->saveBlock(p3d, o.str());
1928         if (ret) {
1929                 // We just wrote it to the disk so clear modified flag
1930                 block->resetModified();
1931         }
1932         return ret;
1933 }
1934
1935 void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load)
1936 {
1937         try {
1938                 std::istringstream is(*blob, std::ios_base::binary);
1939
1940                 u8 version = SER_FMT_VER_INVALID;
1941                 is.read((char*)&version, 1);
1942
1943                 if(is.fail())
1944                         throw SerializationError("ServerMap::loadBlock(): Failed"
1945                                         " to read MapBlock version");
1946
1947                 MapBlock *block = NULL;
1948                 bool created_new = false;
1949                 block = sector->getBlockNoCreateNoEx(p3d.Y);
1950                 if(block == NULL)
1951                 {
1952                         block = sector->createBlankBlockNoInsert(p3d.Y);
1953                         created_new = true;
1954                 }
1955
1956                 // Read basic data
1957                 block->deSerialize(is, version, true);
1958
1959                 // If it's a new block, insert it to the map
1960                 if (created_new) {
1961                         sector->insertBlock(block);
1962                         ReflowScan scanner(this, m_emerge->ndef);
1963                         scanner.scan(block, &m_transforming_liquid);
1964                 }
1965
1966                 /*
1967                         Save blocks loaded in old format in new format
1968                 */
1969
1970                 //if(version < SER_FMT_VER_HIGHEST_READ || save_after_load)
1971                 // Only save if asked to; no need to update version
1972                 if(save_after_load)
1973                         saveBlock(block);
1974
1975                 // We just loaded it from, so it's up-to-date.
1976                 block->resetModified();
1977         }
1978         catch(SerializationError &e)
1979         {
1980                 errorstream<<"Invalid block data in database"
1981                                 <<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
1982                                 <<" (SerializationError): "<<e.what()<<std::endl;
1983
1984                 // TODO: Block should be marked as invalid in memory so that it is
1985                 // not touched but the game can run
1986
1987                 if(g_settings->getBool("ignore_world_load_errors")){
1988                         errorstream<<"Ignoring block load error. Duck and cover! "
1989                                         <<"(ignore_world_load_errors)"<<std::endl;
1990                 } else {
1991                         throw SerializationError("Invalid block data in database");
1992                 }
1993         }
1994 }
1995
1996 MapBlock* ServerMap::loadBlock(v3s16 blockpos)
1997 {
1998         bool created_new = (getBlockNoCreateNoEx(blockpos) == NULL);
1999
2000         v2s16 p2d(blockpos.X, blockpos.Z);
2001
2002         std::string ret;
2003         dbase->loadBlock(blockpos, &ret);
2004         if (!ret.empty()) {
2005                 loadBlock(&ret, blockpos, createSector(p2d), false);
2006         } else if (dbase_ro) {
2007                 dbase_ro->loadBlock(blockpos, &ret);
2008                 if (!ret.empty()) {
2009                         loadBlock(&ret, blockpos, createSector(p2d), false);
2010                 }
2011         } else {
2012                 return NULL;
2013         }
2014
2015         MapBlock *block = getBlockNoCreateNoEx(blockpos);
2016         if (created_new && (block != NULL)) {
2017                 std::map<v3s16, MapBlock*> modified_blocks;
2018                 // Fix lighting if necessary
2019                 voxalgo::update_block_border_lighting(this, block, modified_blocks);
2020                 if (!modified_blocks.empty()) {
2021                         //Modified lighting, send event
2022                         MapEditEvent event;
2023                         event.type = MEET_OTHER;
2024                         std::map<v3s16, MapBlock *>::iterator it;
2025                         for (it = modified_blocks.begin();
2026                                         it != modified_blocks.end(); ++it)
2027                                 event.modified_blocks.insert(it->first);
2028                         dispatchEvent(event);
2029                 }
2030         }
2031         return block;
2032 }
2033
2034 bool ServerMap::deleteBlock(v3s16 blockpos)
2035 {
2036         if (!dbase->deleteBlock(blockpos))
2037                 return false;
2038
2039         MapBlock *block = getBlockNoCreateNoEx(blockpos);
2040         if (block) {
2041                 v2s16 p2d(blockpos.X, blockpos.Z);
2042                 MapSector *sector = getSectorNoGenerate(p2d);
2043                 if (!sector)
2044                         return false;
2045                 sector->deleteBlock(block);
2046         }
2047
2048         return true;
2049 }
2050
2051 void ServerMap::PrintInfo(std::ostream &out)
2052 {
2053         out<<"ServerMap: ";
2054 }
2055
2056 bool ServerMap::repairBlockLight(v3s16 blockpos,
2057         std::map<v3s16, MapBlock *> *modified_blocks)
2058 {
2059         MapBlock *block = emergeBlock(blockpos, false);
2060         if (!block || !block->isGenerated())
2061                 return false;
2062         voxalgo::repair_block_light(this, block, modified_blocks);
2063         return true;
2064 }
2065
2066 MMVManip::MMVManip(Map *map):
2067                 VoxelManipulator(),
2068                 m_map(map)
2069 {
2070 }
2071
2072 void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
2073         bool load_if_inexistent)
2074 {
2075         TimeTaker timer1("initialEmerge", &emerge_time);
2076
2077         // Units of these are MapBlocks
2078         v3s16 p_min = blockpos_min;
2079         v3s16 p_max = blockpos_max;
2080
2081         VoxelArea block_area_nodes
2082                         (p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
2083
2084         u32 size_MB = block_area_nodes.getVolume()*4/1000000;
2085         if(size_MB >= 1)
2086         {
2087                 infostream<<"initialEmerge: area: ";
2088                 block_area_nodes.print(infostream);
2089                 infostream<<" ("<<size_MB<<"MB)";
2090                 infostream<<std::endl;
2091         }
2092
2093         addArea(block_area_nodes);
2094
2095         for(s32 z=p_min.Z; z<=p_max.Z; z++)
2096         for(s32 y=p_min.Y; y<=p_max.Y; y++)
2097         for(s32 x=p_min.X; x<=p_max.X; x++)
2098         {
2099                 u8 flags = 0;
2100                 MapBlock *block;
2101                 v3s16 p(x,y,z);
2102                 std::map<v3s16, u8>::iterator n;
2103                 n = m_loaded_blocks.find(p);
2104                 if(n != m_loaded_blocks.end())
2105                         continue;
2106
2107                 bool block_data_inexistent = false;
2108                 {
2109                         TimeTaker timer2("emerge load", &emerge_load_time);
2110
2111                         block = m_map->getBlockNoCreateNoEx(p);
2112                         if (!block || block->isDummy())
2113                                 block_data_inexistent = true;
2114                         else
2115                                 block->copyTo(*this);
2116                 }
2117
2118                 if(block_data_inexistent)
2119                 {
2120
2121                         if (load_if_inexistent && !blockpos_over_max_limit(p)) {
2122                                 ServerMap *svrmap = (ServerMap *)m_map;
2123                                 block = svrmap->emergeBlock(p, false);
2124                                 if (block == NULL)
2125                                         block = svrmap->createBlock(p);
2126                                 block->copyTo(*this);
2127                         } else {
2128                                 flags |= VMANIP_BLOCK_DATA_INEXIST;
2129
2130                                 /*
2131                                         Mark area inexistent
2132                                 */
2133                                 VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
2134                                 // Fill with VOXELFLAG_NO_DATA
2135                                 for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
2136                                 for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
2137                                 {
2138                                         s32 i = m_area.index(a.MinEdge.X,y,z);
2139                                         memset(&m_flags[i], VOXELFLAG_NO_DATA, MAP_BLOCKSIZE);
2140                                 }
2141                         }
2142                 }
2143                 /*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE)
2144                 {
2145                         // Mark that block was loaded as blank
2146                         flags |= VMANIP_BLOCK_CONTAINS_CIGNORE;
2147                 }*/
2148
2149                 m_loaded_blocks[p] = flags;
2150         }
2151
2152         m_is_dirty = false;
2153 }
2154
2155 void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
2156         bool overwrite_generated)
2157 {
2158         if(m_area.getExtent() == v3s16(0,0,0))
2159                 return;
2160
2161         /*
2162                 Copy data of all blocks
2163         */
2164         for (auto &loaded_block : m_loaded_blocks) {
2165                 v3s16 p = loaded_block.first;
2166                 MapBlock *block = m_map->getBlockNoCreateNoEx(p);
2167                 bool existed = !(loaded_block.second & VMANIP_BLOCK_DATA_INEXIST);
2168                 if (!existed || (block == NULL) ||
2169                         (!overwrite_generated && block->isGenerated()))
2170                         continue;
2171
2172                 block->copyFrom(*this);
2173                 block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP);
2174
2175                 if(modified_blocks)
2176                         (*modified_blocks)[p] = block;
2177         }
2178 }
2179
2180 //END