Fix bone-attached entities (#10015)
[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 const static v3s16 liquid_6dirs[6] = {
482         // order: upper before same level before lower
483         v3s16( 0, 1, 0),
484         v3s16( 0, 0, 1),
485         v3s16( 1, 0, 0),
486         v3s16( 0, 0,-1),
487         v3s16(-1, 0, 0),
488         v3s16( 0,-1, 0)
489 };
490
491 enum NeighborType : u8 {
492         NEIGHBOR_UPPER,
493         NEIGHBOR_SAME_LEVEL,
494         NEIGHBOR_LOWER
495 };
496
497 struct NodeNeighbor {
498         MapNode n;
499         NeighborType t;
500         v3s16 p;
501
502         NodeNeighbor()
503                 : n(CONTENT_AIR), t(NEIGHBOR_SAME_LEVEL)
504         { }
505
506         NodeNeighbor(const MapNode &node, NeighborType n_type, const v3s16 &pos)
507                 : n(node),
508                   t(n_type),
509                   p(pos)
510         { }
511 };
512
513 void Map::transforming_liquid_add(v3s16 p) {
514         m_transforming_liquid.push_back(p);
515 }
516
517 void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
518                 ServerEnvironment *env)
519 {
520         u32 loopcount = 0;
521         u32 initial_size = m_transforming_liquid.size();
522
523         /*if(initial_size != 0)
524                 infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
525
526         // list of nodes that due to viscosity have not reached their max level height
527         std::deque<v3s16> must_reflow;
528
529         std::vector<std::pair<v3s16, MapNode> > changed_nodes;
530
531         u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
532         u32 loop_max = liquid_loop_max;
533
534 #if 0
535
536         /* If liquid_loop_max is not keeping up with the queue size increase
537          * loop_max up to a maximum of liquid_loop_max * dedicated_server_step.
538          */
539         if (m_transforming_liquid.size() > loop_max * 2) {
540                 // "Burst" mode
541                 float server_step = g_settings->getFloat("dedicated_server_step");
542                 if (m_transforming_liquid_loop_count_multiplier - 1.0 < server_step)
543                         m_transforming_liquid_loop_count_multiplier *= 1.0 + server_step / 10;
544         } else {
545                 m_transforming_liquid_loop_count_multiplier = 1.0;
546         }
547
548         loop_max *= m_transforming_liquid_loop_count_multiplier;
549 #endif
550
551         while (m_transforming_liquid.size() != 0)
552         {
553                 // This should be done here so that it is done when continue is used
554                 if (loopcount >= initial_size || loopcount >= loop_max)
555                         break;
556                 loopcount++;
557
558                 /*
559                         Get a queued transforming liquid node
560                 */
561                 v3s16 p0 = m_transforming_liquid.front();
562                 m_transforming_liquid.pop_front();
563
564                 MapNode n0 = getNode(p0);
565
566                 /*
567                         Collect information about current node
568                  */
569                 s8 liquid_level = -1;
570                 // The liquid node which will be placed there if
571                 // the liquid flows into this node.
572                 content_t liquid_kind = CONTENT_IGNORE;
573                 // The node which will be placed there if liquid
574                 // can't flow into this node.
575                 content_t floodable_node = CONTENT_AIR;
576                 const ContentFeatures &cf = m_nodedef->get(n0);
577                 LiquidType liquid_type = cf.liquid_type;
578                 switch (liquid_type) {
579                         case LIQUID_SOURCE:
580                                 liquid_level = LIQUID_LEVEL_SOURCE;
581                                 liquid_kind = cf.liquid_alternative_flowing_id;
582                                 break;
583                         case LIQUID_FLOWING:
584                                 liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
585                                 liquid_kind = n0.getContent();
586                                 break;
587                         case LIQUID_NONE:
588                                 // if this node is 'floodable', it *could* be transformed
589                                 // into a liquid, otherwise, continue with the next node.
590                                 if (!cf.floodable)
591                                         continue;
592                                 floodable_node = n0.getContent();
593                                 liquid_kind = CONTENT_AIR;
594                                 break;
595                 }
596
597                 /*
598                         Collect information about the environment
599                  */
600                 NodeNeighbor sources[6]; // surrounding sources
601                 int num_sources = 0;
602                 NodeNeighbor flows[6]; // surrounding flowing liquid nodes
603                 int num_flows = 0;
604                 NodeNeighbor airs[6]; // surrounding air
605                 int num_airs = 0;
606                 NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
607                 int num_neutrals = 0;
608                 bool flowing_down = false;
609                 bool ignored_sources = false;
610                 for (u16 i = 0; i < 6; i++) {
611                         NeighborType nt = NEIGHBOR_SAME_LEVEL;
612                         switch (i) {
613                                 case 0:
614                                         nt = NEIGHBOR_UPPER;
615                                         break;
616                                 case 5:
617                                         nt = NEIGHBOR_LOWER;
618                                         break;
619                                 default:
620                                         break;
621                         }
622                         v3s16 npos = p0 + liquid_6dirs[i];
623                         NodeNeighbor nb(getNode(npos), nt, npos);
624                         const ContentFeatures &cfnb = m_nodedef->get(nb.n);
625                         switch (m_nodedef->get(nb.n.getContent()).liquid_type) {
626                                 case LIQUID_NONE:
627                                         if (cfnb.floodable) {
628                                                 airs[num_airs++] = nb;
629                                                 // if the current node is a water source the neighbor
630                                                 // should be enqueded for transformation regardless of whether the
631                                                 // current node changes or not.
632                                                 if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
633                                                         m_transforming_liquid.push_back(npos);
634                                                 // if the current node happens to be a flowing node, it will start to flow down here.
635                                                 if (nb.t == NEIGHBOR_LOWER)
636                                                         flowing_down = true;
637                                         } else {
638                                                 neutrals[num_neutrals++] = nb;
639                                                 if (nb.n.getContent() == CONTENT_IGNORE) {
640                                                         // If node below is ignore prevent water from
641                                                         // spreading outwards and otherwise prevent from
642                                                         // flowing away as ignore node might be the source
643                                                         if (nb.t == NEIGHBOR_LOWER)
644                                                                 flowing_down = true;
645                                                         else
646                                                                 ignored_sources = true;
647                                                 }
648                                         }
649                                         break;
650                                 case LIQUID_SOURCE:
651                                         // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
652                                         if (liquid_kind == CONTENT_AIR)
653                                                 liquid_kind = cfnb.liquid_alternative_flowing_id;
654                                         if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
655                                                 neutrals[num_neutrals++] = nb;
656                                         } else {
657                                                 // Do not count bottom source, it will screw things up
658                                                 if(nt != NEIGHBOR_LOWER)
659                                                         sources[num_sources++] = nb;
660                                         }
661                                         break;
662                                 case LIQUID_FLOWING:
663                                         if (nb.t != NEIGHBOR_SAME_LEVEL ||
664                                                 (nb.n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK) {
665                                                 // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
666                                                 // but exclude falling liquids on the same level, they cannot flow here anyway
667                                                 if (liquid_kind == CONTENT_AIR)
668                                                         liquid_kind = cfnb.liquid_alternative_flowing_id;
669                                         }
670                                         if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
671                                                 neutrals[num_neutrals++] = nb;
672                                         } else {
673                                                 flows[num_flows++] = nb;
674                                                 if (nb.t == NEIGHBOR_LOWER)
675                                                         flowing_down = true;
676                                         }
677                                         break;
678                         }
679                 }
680
681                 /*
682                         decide on the type (and possibly level) of the current node
683                  */
684                 content_t new_node_content;
685                 s8 new_node_level = -1;
686                 s8 max_node_level = -1;
687
688                 u8 range = m_nodedef->get(liquid_kind).liquid_range;
689                 if (range > LIQUID_LEVEL_MAX + 1)
690                         range = LIQUID_LEVEL_MAX + 1;
691
692                 if ((num_sources >= 2 && m_nodedef->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
693                         // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
694                         // or the flowing alternative of the first of the surrounding sources (if it's air), so
695                         // it's perfectly safe to use liquid_kind here to determine the new node content.
696                         new_node_content = m_nodedef->get(liquid_kind).liquid_alternative_source_id;
697                 } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
698                         // liquid_kind is set properly, see above
699                         max_node_level = new_node_level = LIQUID_LEVEL_MAX;
700                         if (new_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
701                                 new_node_content = liquid_kind;
702                         else
703                                 new_node_content = floodable_node;
704                 } else if (ignored_sources && liquid_level >= 0) {
705                         // Maybe there are neighbouring sources that aren't loaded yet
706                         // so prevent flowing away.
707                         new_node_level = liquid_level;
708                         new_node_content = liquid_kind;
709                 } else {
710                         // no surrounding sources, so get the maximum level that can flow into this node
711                         for (u16 i = 0; i < num_flows; i++) {
712                                 u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
713                                 switch (flows[i].t) {
714                                         case NEIGHBOR_UPPER:
715                                                 if (nb_liquid_level + WATER_DROP_BOOST > max_node_level) {
716                                                         max_node_level = LIQUID_LEVEL_MAX;
717                                                         if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
718                                                                 max_node_level = nb_liquid_level + WATER_DROP_BOOST;
719                                                 } else if (nb_liquid_level > max_node_level) {
720                                                         max_node_level = nb_liquid_level;
721                                                 }
722                                                 break;
723                                         case NEIGHBOR_LOWER:
724                                                 break;
725                                         case NEIGHBOR_SAME_LEVEL:
726                                                 if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
727                                                                 nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level)
728                                                         max_node_level = nb_liquid_level - 1;
729                                                 break;
730                                 }
731                         }
732
733                         u8 viscosity = m_nodedef->get(liquid_kind).liquid_viscosity;
734                         if (viscosity > 1 && max_node_level != liquid_level) {
735                                 // amount to gain, limited by viscosity
736                                 // must be at least 1 in absolute value
737                                 s8 level_inc = max_node_level - liquid_level;
738                                 if (level_inc < -viscosity || level_inc > viscosity)
739                                         new_node_level = liquid_level + level_inc/viscosity;
740                                 else if (level_inc < 0)
741                                         new_node_level = liquid_level - 1;
742                                 else if (level_inc > 0)
743                                         new_node_level = liquid_level + 1;
744                                 if (new_node_level != max_node_level)
745                                         must_reflow.push_back(p0);
746                         } else {
747                                 new_node_level = max_node_level;
748                         }
749
750                         if (max_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
751                                 new_node_content = liquid_kind;
752                         else
753                                 new_node_content = floodable_node;
754
755                 }
756
757                 /*
758                         check if anything has changed. if not, just continue with the next node.
759                  */
760                 if (new_node_content == n0.getContent() &&
761                                 (m_nodedef->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
762                                 ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
763                                 ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
764                                 == flowing_down)))
765                         continue;
766
767
768                 /*
769                         update the current node
770                  */
771                 MapNode n00 = n0;
772                 //bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
773                 if (m_nodedef->get(new_node_content).liquid_type == LIQUID_FLOWING) {
774                         // set level to last 3 bits, flowing down bit to 4th bit
775                         n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
776                 } else {
777                         // set the liquid level and flow bits to 0
778                         n0.param2 &= ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
779                 }
780
781                 // change the node.
782                 n0.setContent(new_node_content);
783
784                 // on_flood() the node
785                 if (floodable_node != CONTENT_AIR) {
786                         if (env->getScriptIface()->node_on_flood(p0, n00, n0))
787                                 continue;
788                 }
789
790                 // Ignore light (because calling voxalgo::update_lighting_nodes)
791                 n0.setLight(LIGHTBANK_DAY, 0, m_nodedef);
792                 n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
793
794                 // Find out whether there is a suspect for this action
795                 std::string suspect;
796                 if (m_gamedef->rollback())
797                         suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
798
799                 if (m_gamedef->rollback() && !suspect.empty()) {
800                         // Blame suspect
801                         RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
802                         // Get old node for rollback
803                         RollbackNode rollback_oldnode(this, p0, m_gamedef);
804                         // Set node
805                         setNode(p0, n0);
806                         // Report
807                         RollbackNode rollback_newnode(this, p0, m_gamedef);
808                         RollbackAction action;
809                         action.setSetNode(p0, rollback_oldnode, rollback_newnode);
810                         m_gamedef->rollback()->reportAction(action);
811                 } else {
812                         // Set node
813                         setNode(p0, n0);
814                 }
815
816                 v3s16 blockpos = getNodeBlockPos(p0);
817                 MapBlock *block = getBlockNoCreateNoEx(blockpos);
818                 if (block != NULL) {
819                         modified_blocks[blockpos] =  block;
820                         changed_nodes.emplace_back(p0, n00);
821                 }
822
823                 /*
824                         enqueue neighbors for update if neccessary
825                  */
826                 switch (m_nodedef->get(n0.getContent()).liquid_type) {
827                         case LIQUID_SOURCE:
828                         case LIQUID_FLOWING:
829                                 // make sure source flows into all neighboring nodes
830                                 for (u16 i = 0; i < num_flows; i++)
831                                         if (flows[i].t != NEIGHBOR_UPPER)
832                                                 m_transforming_liquid.push_back(flows[i].p);
833                                 for (u16 i = 0; i < num_airs; i++)
834                                         if (airs[i].t != NEIGHBOR_UPPER)
835                                                 m_transforming_liquid.push_back(airs[i].p);
836                                 break;
837                         case LIQUID_NONE:
838                                 // this flow has turned to air; neighboring flows might need to do the same
839                                 for (u16 i = 0; i < num_flows; i++)
840                                         m_transforming_liquid.push_back(flows[i].p);
841                                 break;
842                 }
843         }
844         //infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
845
846         for (auto &iter : must_reflow)
847                 m_transforming_liquid.push_back(iter);
848
849         voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks);
850
851
852         /* ----------------------------------------------------------------------
853          * Manage the queue so that it does not grow indefinately
854          */
855         u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
856
857         if (time_until_purge == 0)
858                 return; // Feature disabled
859
860         time_until_purge *= 1000;       // seconds -> milliseconds
861
862         u64 curr_time = porting::getTimeMs();
863         u32 prev_unprocessed = m_unprocessed_count;
864         m_unprocessed_count = m_transforming_liquid.size();
865
866         // if unprocessed block count is decreasing or stable
867         if (m_unprocessed_count <= prev_unprocessed) {
868                 m_queue_size_timer_started = false;
869         } else {
870                 if (!m_queue_size_timer_started)
871                         m_inc_trending_up_start_time = curr_time;
872                 m_queue_size_timer_started = true;
873         }
874
875         // Account for curr_time overflowing
876         if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
877                 m_queue_size_timer_started = false;
878
879         /* If the queue has been growing for more than liquid_queue_purge_time seconds
880          * and the number of unprocessed blocks is still > liquid_loop_max then we
881          * cannot keep up; dump the oldest blocks from the queue so that the queue
882          * has liquid_loop_max items in it
883          */
884         if (m_queue_size_timer_started
885                         && curr_time - m_inc_trending_up_start_time > time_until_purge
886                         && m_unprocessed_count > liquid_loop_max) {
887
888                 size_t dump_qty = m_unprocessed_count - liquid_loop_max;
889
890                 infostream << "transformLiquids(): DUMPING " << dump_qty
891                            << " blocks from the queue" << std::endl;
892
893                 while (dump_qty--)
894                         m_transforming_liquid.pop_front();
895
896                 m_queue_size_timer_started = false; // optimistically assume we can keep up now
897                 m_unprocessed_count = m_transforming_liquid.size();
898         }
899 }
900
901 std::vector<v3s16> Map::findNodesWithMetadata(v3s16 p1, v3s16 p2)
902 {
903         std::vector<v3s16> positions_with_meta;
904
905         sortBoxVerticies(p1, p2);
906         v3s16 bpmin = getNodeBlockPos(p1);
907         v3s16 bpmax = getNodeBlockPos(p2);
908
909         VoxelArea area(p1, p2);
910
911         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
912         for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
913         for (s16 x = bpmin.X; x <= bpmax.X; x++) {
914                 v3s16 blockpos(x, y, z);
915
916                 MapBlock *block = getBlockNoCreateNoEx(blockpos);
917                 if (!block) {
918                         verbosestream << "Map::getNodeMetadata(): Need to emerge "
919                                 << PP(blockpos) << std::endl;
920                         block = emergeBlock(blockpos, false);
921                 }
922                 if (!block) {
923                         infostream << "WARNING: Map::getNodeMetadata(): Block not found"
924                                 << std::endl;
925                         continue;
926                 }
927
928                 v3s16 p_base = blockpos * MAP_BLOCKSIZE;
929                 std::vector<v3s16> keys = block->m_node_metadata.getAllKeys();
930                 for (size_t i = 0; i != keys.size(); i++) {
931                         v3s16 p(keys[i] + p_base);
932                         if (!area.contains(p))
933                                 continue;
934
935                         positions_with_meta.push_back(p);
936                 }
937         }
938
939         return positions_with_meta;
940 }
941
942 NodeMetadata *Map::getNodeMetadata(v3s16 p)
943 {
944         v3s16 blockpos = getNodeBlockPos(p);
945         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
946         MapBlock *block = getBlockNoCreateNoEx(blockpos);
947         if(!block){
948                 infostream<<"Map::getNodeMetadata(): Need to emerge "
949                                 <<PP(blockpos)<<std::endl;
950                 block = emergeBlock(blockpos, false);
951         }
952         if(!block){
953                 warningstream<<"Map::getNodeMetadata(): Block not found"
954                                 <<std::endl;
955                 return NULL;
956         }
957         NodeMetadata *meta = block->m_node_metadata.get(p_rel);
958         return meta;
959 }
960
961 bool Map::setNodeMetadata(v3s16 p, NodeMetadata *meta)
962 {
963         v3s16 blockpos = getNodeBlockPos(p);
964         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
965         MapBlock *block = getBlockNoCreateNoEx(blockpos);
966         if(!block){
967                 infostream<<"Map::setNodeMetadata(): Need to emerge "
968                                 <<PP(blockpos)<<std::endl;
969                 block = emergeBlock(blockpos, false);
970         }
971         if(!block){
972                 warningstream<<"Map::setNodeMetadata(): Block not found"
973                                 <<std::endl;
974                 return false;
975         }
976         block->m_node_metadata.set(p_rel, meta);
977         return true;
978 }
979
980 void Map::removeNodeMetadata(v3s16 p)
981 {
982         v3s16 blockpos = getNodeBlockPos(p);
983         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
984         MapBlock *block = getBlockNoCreateNoEx(blockpos);
985         if(block == NULL)
986         {
987                 warningstream<<"Map::removeNodeMetadata(): Block not found"
988                                 <<std::endl;
989                 return;
990         }
991         block->m_node_metadata.remove(p_rel);
992 }
993
994 NodeTimer Map::getNodeTimer(v3s16 p)
995 {
996         v3s16 blockpos = getNodeBlockPos(p);
997         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
998         MapBlock *block = getBlockNoCreateNoEx(blockpos);
999         if(!block){
1000                 infostream<<"Map::getNodeTimer(): Need to emerge "
1001                                 <<PP(blockpos)<<std::endl;
1002                 block = emergeBlock(blockpos, false);
1003         }
1004         if(!block){
1005                 warningstream<<"Map::getNodeTimer(): Block not found"
1006                                 <<std::endl;
1007                 return NodeTimer();
1008         }
1009         NodeTimer t = block->m_node_timers.get(p_rel);
1010         NodeTimer nt(t.timeout, t.elapsed, p);
1011         return nt;
1012 }
1013
1014 void Map::setNodeTimer(const NodeTimer &t)
1015 {
1016         v3s16 p = t.position;
1017         v3s16 blockpos = getNodeBlockPos(p);
1018         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
1019         MapBlock *block = getBlockNoCreateNoEx(blockpos);
1020         if(!block){
1021                 infostream<<"Map::setNodeTimer(): Need to emerge "
1022                                 <<PP(blockpos)<<std::endl;
1023                 block = emergeBlock(blockpos, false);
1024         }
1025         if(!block){
1026                 warningstream<<"Map::setNodeTimer(): Block not found"
1027                                 <<std::endl;
1028                 return;
1029         }
1030         NodeTimer nt(t.timeout, t.elapsed, p_rel);
1031         block->m_node_timers.set(nt);
1032 }
1033
1034 void Map::removeNodeTimer(v3s16 p)
1035 {
1036         v3s16 blockpos = getNodeBlockPos(p);
1037         v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
1038         MapBlock *block = getBlockNoCreateNoEx(blockpos);
1039         if(block == NULL)
1040         {
1041                 warningstream<<"Map::removeNodeTimer(): Block not found"
1042                                 <<std::endl;
1043                 return;
1044         }
1045         block->m_node_timers.remove(p_rel);
1046 }
1047
1048 bool Map::determineAdditionalOcclusionCheck(const v3s16 &pos_camera,
1049         const core::aabbox3d<s16> &block_bounds, v3s16 &check)
1050 {
1051         /*
1052                 This functions determines the node inside the target block that is
1053                 closest to the camera position. This increases the occlusion culling
1054                 accuracy in straight and diagonal corridors.
1055                 The returned position will be occlusion checked first in addition to the
1056                 others (8 corners + center).
1057                 No position is returned if
1058                 - the closest node is a corner, corners are checked anyway.
1059                 - the camera is inside the target block, it will never be occluded.
1060         */
1061 #define CLOSEST_EDGE(pos, bounds, axis) \
1062         ((pos).axis <= (bounds).MinEdge.axis) ? (bounds).MinEdge.axis : \
1063         (bounds).MaxEdge.axis
1064
1065         bool x_inside = (block_bounds.MinEdge.X <= pos_camera.X) &&
1066                         (pos_camera.X <= block_bounds.MaxEdge.X);
1067         bool y_inside = (block_bounds.MinEdge.Y <= pos_camera.Y) &&
1068                         (pos_camera.Y <= block_bounds.MaxEdge.Y);
1069         bool z_inside = (block_bounds.MinEdge.Z <= pos_camera.Z) &&
1070                         (pos_camera.Z <= block_bounds.MaxEdge.Z);
1071
1072         if (x_inside && y_inside && z_inside)
1073                 return false; // Camera inside target mapblock
1074
1075         // straight
1076         if (x_inside && y_inside) {
1077                 check = v3s16(pos_camera.X, pos_camera.Y, 0);
1078                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1079                 return true;
1080         } else if (y_inside && z_inside) {
1081                 check = v3s16(0, pos_camera.Y, pos_camera.Z);
1082                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1083                 return true;
1084         } else if (x_inside && z_inside) {
1085                 check = v3s16(pos_camera.X, 0, pos_camera.Z);
1086                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1087                 return true;
1088         }
1089
1090         // diagonal
1091         if (x_inside) {
1092                 check = v3s16(pos_camera.X, 0, 0);
1093                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1094                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1095                 return true;
1096         } else if (y_inside) {
1097                 check = v3s16(0, pos_camera.Y, 0);
1098                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1099                 check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z);
1100                 return true;
1101         } else if (z_inside) {
1102                 check = v3s16(0, 0, pos_camera.Z);
1103                 check.X = CLOSEST_EDGE(pos_camera, block_bounds, X);
1104                 check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y);
1105                 return true;
1106         }
1107
1108         // Closest node would be a corner, none returned
1109         return false;
1110 }
1111
1112 bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
1113         float step, float stepfac, float offset, float end_offset, u32 needed_count)
1114 {
1115         v3f direction = intToFloat(pos_target - pos_camera, BS);
1116         float distance = direction.getLength();
1117
1118         // Normalize direction vector
1119         if (distance > 0.0f)
1120                 direction /= distance;
1121
1122         v3f pos_origin_f = intToFloat(pos_camera, BS);
1123         u32 count = 0;
1124         bool is_valid_position;
1125
1126         for (; offset < distance + end_offset; offset += step) {
1127                 v3f pos_node_f = pos_origin_f + direction * offset;
1128                 v3s16 pos_node = floatToInt(pos_node_f, BS);
1129
1130                 MapNode node = getNode(pos_node, &is_valid_position);
1131
1132                 if (is_valid_position &&
1133                                 !m_nodedef->get(node).light_propagates) {
1134                         // Cannot see through light-blocking nodes --> occluded
1135                         count++;
1136                         if (count >= needed_count)
1137                                 return true;
1138                 }
1139                 step *= stepfac;
1140         }
1141         return false;
1142 }
1143
1144 bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes)
1145 {
1146         // Check occlusion for center and all 8 corners of the mapblock
1147         // Overshoot a little for less flickering
1148         static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1;
1149         static const v3s16 dir9[9] = {
1150                 v3s16( 0,  0,  0),
1151                 v3s16( 1,  1,  1) * bs2,
1152                 v3s16( 1,  1, -1) * bs2,
1153                 v3s16( 1, -1,  1) * bs2,
1154                 v3s16( 1, -1, -1) * bs2,
1155                 v3s16(-1,  1,  1) * bs2,
1156                 v3s16(-1,  1, -1) * bs2,
1157                 v3s16(-1, -1,  1) * bs2,
1158                 v3s16(-1, -1, -1) * bs2,
1159         };
1160
1161         v3s16 pos_blockcenter = block->getPosRelative() + (MAP_BLOCKSIZE / 2);
1162
1163         // Starting step size, value between 1m and sqrt(3)m
1164         float step = BS * 1.2f;
1165         // Multiply step by each iteraction by 'stepfac' to reduce checks in distance
1166         float stepfac = 1.05f;
1167
1168         float start_offset = BS * 1.0f;
1169
1170         // The occlusion search of 'isOccluded()' must stop short of the target
1171         // point by distance 'end_offset' to not enter the target mapblock.
1172         // For the 8 mapblock corners 'end_offset' must therefore be the maximum
1173         // diagonal of a mapblock, because we must consider all view angles.
1174         // sqrt(1^2 + 1^2 + 1^2) = 1.732
1175         float end_offset = -BS * MAP_BLOCKSIZE * 1.732f;
1176
1177         // to reduce the likelihood of falsely occluded blocks
1178         // require at least two solid blocks
1179         // this is a HACK, we should think of a more precise algorithm
1180         u32 needed_count = 2;
1181
1182         // Additional occlusion check, see comments in that function
1183         v3s16 check;
1184         if (determineAdditionalOcclusionCheck(cam_pos_nodes, block->getBox(), check)) {
1185                 // node is always on a side facing the camera, end_offset can be lower
1186                 if (!isOccluded(cam_pos_nodes, check, step, stepfac, start_offset,
1187                                 -1.0f, needed_count))
1188                         return false;
1189         }
1190
1191         for (const v3s16 &dir : dir9) {
1192                 if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir, step, stepfac,
1193                                 start_offset, end_offset, needed_count))
1194                         return false;
1195         }
1196         return true;
1197 }
1198
1199 /*
1200         ServerMap
1201 */
1202 ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
1203                 EmergeManager *emerge, MetricsBackend *mb):
1204         Map(dout_server, gamedef),
1205         settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"),
1206         m_emerge(emerge)
1207 {
1208         verbosestream<<FUNCTION_NAME<<std::endl;
1209
1210         // Tell the EmergeManager about our MapSettingsManager
1211         emerge->map_settings_mgr = &settings_mgr;
1212
1213         /*
1214                 Try to load map; if not found, create a new one.
1215         */
1216
1217         // Determine which database backend to use
1218         std::string conf_path = savedir + DIR_DELIM + "world.mt";
1219         Settings conf;
1220         bool succeeded = conf.readConfigFile(conf_path.c_str());
1221         if (!succeeded || !conf.exists("backend")) {
1222                 // fall back to sqlite3
1223                 conf.set("backend", "sqlite3");
1224         }
1225         std::string backend = conf.get("backend");
1226         dbase = createDatabase(backend, savedir, conf);
1227         if (conf.exists("readonly_backend")) {
1228                 std::string readonly_dir = savedir + DIR_DELIM + "readonly";
1229                 dbase_ro = createDatabase(conf.get("readonly_backend"), readonly_dir, conf);
1230         }
1231         if (!conf.updateConfigFile(conf_path.c_str()))
1232                 errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl;
1233
1234         m_savedir = savedir;
1235         m_map_saving_enabled = false;
1236
1237         m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)");
1238
1239         try {
1240                 // If directory exists, check contents and load if possible
1241                 if (fs::PathExists(m_savedir)) {
1242                         // If directory is empty, it is safe to save into it.
1243                         if (fs::GetDirListing(m_savedir).empty()) {
1244                                 infostream<<"ServerMap: Empty save directory is valid."
1245                                                 <<std::endl;
1246                                 m_map_saving_enabled = true;
1247                         }
1248                         else
1249                         {
1250
1251                                 if (settings_mgr.loadMapMeta()) {
1252                                         infostream << "ServerMap: Metadata loaded from "
1253                                                 << savedir << std::endl;
1254                                 } else {
1255                                         infostream << "ServerMap: Metadata could not be loaded "
1256                                                 "from " << savedir << ", assuming valid save "
1257                                                 "directory." << std::endl;
1258                                 }
1259
1260                                 m_map_saving_enabled = true;
1261                                 // Map loaded, not creating new one
1262                                 return;
1263                         }
1264                 }
1265                 // If directory doesn't exist, it is safe to save to it
1266                 else{
1267                         m_map_saving_enabled = true;
1268                 }
1269         }
1270         catch(std::exception &e)
1271         {
1272                 warningstream<<"ServerMap: Failed to load map from "<<savedir
1273                                 <<", exception: "<<e.what()<<std::endl;
1274                 infostream<<"Please remove the map or fix it."<<std::endl;
1275                 warningstream<<"Map saving will be disabled."<<std::endl;
1276         }
1277 }
1278
1279 ServerMap::~ServerMap()
1280 {
1281         verbosestream<<FUNCTION_NAME<<std::endl;
1282
1283         try
1284         {
1285                 if (m_map_saving_enabled) {
1286                         // Save only changed parts
1287                         save(MOD_STATE_WRITE_AT_UNLOAD);
1288                         infostream << "ServerMap: Saved map to " << m_savedir << std::endl;
1289                 } else {
1290                         infostream << "ServerMap: Map not saved" << std::endl;
1291                 }
1292         }
1293         catch(std::exception &e)
1294         {
1295                 infostream<<"ServerMap: Failed to save map to "<<m_savedir
1296                                 <<", exception: "<<e.what()<<std::endl;
1297         }
1298
1299         /*
1300                 Close database if it was opened
1301         */
1302         delete dbase;
1303         delete dbase_ro;
1304
1305 #if 0
1306         /*
1307                 Free all MapChunks
1308         */
1309         core::map<v2s16, MapChunk*>::Iterator i = m_chunks.getIterator();
1310         for(; i.atEnd() == false; i++)
1311         {
1312                 MapChunk *chunk = i.getNode()->getValue();
1313                 delete chunk;
1314         }
1315 #endif
1316 }
1317
1318 MapgenParams *ServerMap::getMapgenParams()
1319 {
1320         // getMapgenParams() should only ever be called after Server is initialized
1321         assert(settings_mgr.mapgen_params != NULL);
1322         return settings_mgr.mapgen_params;
1323 }
1324
1325 u64 ServerMap::getSeed()
1326 {
1327         return getMapgenParams()->seed;
1328 }
1329
1330 s16 ServerMap::getWaterLevel()
1331 {
1332         return getMapgenParams()->water_level;
1333 }
1334
1335 bool ServerMap::blockpos_over_mapgen_limit(v3s16 p)
1336 {
1337         const s16 mapgen_limit_bp = rangelim(
1338                 getMapgenParams()->mapgen_limit, 0, MAX_MAP_GENERATION_LIMIT) /
1339                 MAP_BLOCKSIZE;
1340         return p.X < -mapgen_limit_bp ||
1341                 p.X >  mapgen_limit_bp ||
1342                 p.Y < -mapgen_limit_bp ||
1343                 p.Y >  mapgen_limit_bp ||
1344                 p.Z < -mapgen_limit_bp ||
1345                 p.Z >  mapgen_limit_bp;
1346 }
1347
1348 bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
1349 {
1350         s16 csize = getMapgenParams()->chunksize;
1351         v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize);
1352         v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1);
1353
1354         bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
1355         EMERGE_DBG_OUT("initBlockMake(): " PP(bpmin) " - " PP(bpmax));
1356
1357         v3s16 extra_borders(1, 1, 1);
1358         v3s16 full_bpmin = bpmin - extra_borders;
1359         v3s16 full_bpmax = bpmax + extra_borders;
1360
1361         // Do nothing if not inside mapgen limits (+-1 because of neighbors)
1362         if (blockpos_over_mapgen_limit(full_bpmin) ||
1363                         blockpos_over_mapgen_limit(full_bpmax))
1364                 return false;
1365
1366         data->seed = getSeed();
1367         data->blockpos_min = bpmin;
1368         data->blockpos_max = bpmax;
1369         data->blockpos_requested = blockpos;
1370         data->nodedef = m_nodedef;
1371
1372         /*
1373                 Create the whole area of this and the neighboring blocks
1374         */
1375         for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
1376         for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++) {
1377                 v2s16 sectorpos(x, z);
1378                 // Sector metadata is loaded from disk if not already loaded.
1379                 MapSector *sector = createSector(sectorpos);
1380                 FATAL_ERROR_IF(sector == NULL, "createSector() failed");
1381
1382                 for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
1383                         v3s16 p(x, y, z);
1384
1385                         MapBlock *block = emergeBlock(p, false);
1386                         if (block == NULL) {
1387                                 block = createBlock(p);
1388
1389                                 // Block gets sunlight if this is true.
1390                                 // Refer to the map generator heuristics.
1391                                 bool ug = m_emerge->isBlockUnderground(p);
1392                                 block->setIsUnderground(ug);
1393                         }
1394                 }
1395         }
1396
1397         /*
1398                 Now we have a big empty area.
1399
1400                 Make a ManualMapVoxelManipulator that contains this and the
1401                 neighboring blocks
1402         */
1403
1404         data->vmanip = new MMVManip(this);
1405         data->vmanip->initialEmerge(full_bpmin, full_bpmax);
1406
1407         // Note: we may need this again at some point.
1408 #if 0
1409         // Ensure none of the blocks to be generated were marked as
1410         // containing CONTENT_IGNORE
1411         for (s16 z = blockpos_min.Z; z <= blockpos_max.Z; z++) {
1412                 for (s16 y = blockpos_min.Y; y <= blockpos_max.Y; y++) {
1413                         for (s16 x = blockpos_min.X; x <= blockpos_max.X; x++) {
1414                                 core::map<v3s16, u8>::Node *n;
1415                                 n = data->vmanip->m_loaded_blocks.find(v3s16(x, y, z));
1416                                 if (n == NULL)
1417                                         continue;
1418                                 u8 flags = n->getValue();
1419                                 flags &= ~VMANIP_BLOCK_CONTAINS_CIGNORE;
1420                                 n->setValue(flags);
1421                         }
1422                 }
1423         }
1424 #endif
1425
1426         // Data is ready now.
1427         return true;
1428 }
1429
1430 void ServerMap::finishBlockMake(BlockMakeData *data,
1431         std::map<v3s16, MapBlock*> *changed_blocks)
1432 {
1433         v3s16 bpmin = data->blockpos_min;
1434         v3s16 bpmax = data->blockpos_max;
1435
1436         v3s16 extra_borders(1, 1, 1);
1437
1438         bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
1439         EMERGE_DBG_OUT("finishBlockMake(): " PP(bpmin) " - " PP(bpmax));
1440
1441         /*
1442                 Blit generated stuff to map
1443                 NOTE: blitBackAll adds nearly everything to changed_blocks
1444         */
1445         data->vmanip->blitBackAll(changed_blocks);
1446
1447         EMERGE_DBG_OUT("finishBlockMake: changed_blocks.size()="
1448                 << changed_blocks->size());
1449
1450         /*
1451                 Copy transforming liquid information
1452         */
1453         while (data->transforming_liquid.size()) {
1454                 m_transforming_liquid.push_back(data->transforming_liquid.front());
1455                 data->transforming_liquid.pop_front();
1456         }
1457
1458         for (auto &changed_block : *changed_blocks) {
1459                 MapBlock *block = changed_block.second;
1460                 if (!block)
1461                         continue;
1462                 /*
1463                         Update day/night difference cache of the MapBlocks
1464                 */
1465                 block->expireDayNightDiff();
1466                 /*
1467                         Set block as modified
1468                 */
1469                 block->raiseModified(MOD_STATE_WRITE_NEEDED,
1470                         MOD_REASON_EXPIRE_DAYNIGHTDIFF);
1471         }
1472
1473         /*
1474                 Set central blocks as generated
1475         */
1476         for (s16 x = bpmin.X; x <= bpmax.X; x++)
1477         for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
1478         for (s16 y = bpmin.Y; y <= bpmax.Y; y++) {
1479                 MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
1480                 if (!block)
1481                         continue;
1482
1483                 block->setGenerated(true);
1484         }
1485
1486         /*
1487                 Save changed parts of map
1488                 NOTE: Will be saved later.
1489         */
1490         //save(MOD_STATE_WRITE_AT_UNLOAD);
1491 }
1492
1493 MapSector *ServerMap::createSector(v2s16 p2d)
1494 {
1495         /*
1496                 Check if it exists already in memory
1497         */
1498         MapSector *sector = getSectorNoGenerate(p2d);
1499         if (sector)
1500                 return sector;
1501
1502         /*
1503                 Do not create over max mapgen limit
1504         */
1505         const s16 max_limit_bp = MAX_MAP_GENERATION_LIMIT / MAP_BLOCKSIZE;
1506         if (p2d.X < -max_limit_bp ||
1507                         p2d.X >  max_limit_bp ||
1508                         p2d.Y < -max_limit_bp ||
1509                         p2d.Y >  max_limit_bp)
1510                 throw InvalidPositionException("createSector(): pos. over max mapgen limit");
1511
1512         /*
1513                 Generate blank sector
1514         */
1515
1516         sector = new MapSector(this, p2d, m_gamedef);
1517
1518         // Sector position on map in nodes
1519         //v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
1520
1521         /*
1522                 Insert to container
1523         */
1524         m_sectors[p2d] = sector;
1525
1526         return sector;
1527 }
1528
1529 #if 0
1530 /*
1531         This is a quick-hand function for calling makeBlock().
1532 */
1533 MapBlock * ServerMap::generateBlock(
1534                 v3s16 p,
1535                 std::map<v3s16, MapBlock*> &modified_blocks
1536 )
1537 {
1538         bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
1539
1540         TimeTaker timer("generateBlock");
1541
1542         //MapBlock *block = original_dummy;
1543
1544         v2s16 p2d(p.X, p.Z);
1545         v2s16 p2d_nodes = p2d * MAP_BLOCKSIZE;
1546
1547         /*
1548                 Do not generate over-limit
1549         */
1550         if(blockpos_over_limit(p))
1551         {
1552                 infostream<<FUNCTION_NAME<<": Block position over limit"<<std::endl;
1553                 throw InvalidPositionException("generateBlock(): pos. over limit");
1554         }
1555
1556         /*
1557                 Create block make data
1558         */
1559         BlockMakeData data;
1560         initBlockMake(&data, p);
1561
1562         /*
1563                 Generate block
1564         */
1565         {
1566                 TimeTaker t("mapgen::make_block()");
1567                 mapgen->makeChunk(&data);
1568                 //mapgen::make_block(&data);
1569
1570                 if(enable_mapgen_debug_info == false)
1571                         t.stop(true); // Hide output
1572         }
1573
1574         /*
1575                 Blit data back on map, update lighting, add mobs and whatever this does
1576         */
1577         finishBlockMake(&data, modified_blocks);
1578
1579         /*
1580                 Get central block
1581         */
1582         MapBlock *block = getBlockNoCreateNoEx(p);
1583
1584 #if 0
1585         /*
1586                 Check result
1587         */
1588         if(block)
1589         {
1590                 bool erroneus_content = false;
1591                 for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
1592                 for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
1593                 for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
1594                 {
1595                         v3s16 p(x0,y0,z0);
1596                         MapNode n = block->getNode(p);
1597                         if(n.getContent() == CONTENT_IGNORE)
1598                         {
1599                                 infostream<<"CONTENT_IGNORE at "
1600                                                 <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
1601                                                 <<std::endl;
1602                                 erroneus_content = true;
1603                                 assert(0);
1604                         }
1605                 }
1606                 if(erroneus_content)
1607                 {
1608                         assert(0);
1609                 }
1610         }
1611 #endif
1612
1613 #if 0
1614         /*
1615                 Generate a completely empty block
1616         */
1617         if(block)
1618         {
1619                 for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
1620                 for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
1621                 {
1622                         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
1623                         {
1624                                 MapNode n;
1625                                 n.setContent(CONTENT_AIR);
1626                                 block->setNode(v3s16(x0,y0,z0), n);
1627                         }
1628                 }
1629         }
1630 #endif
1631
1632         if(enable_mapgen_debug_info == false)
1633                 timer.stop(true); // Hide output
1634
1635         return block;
1636 }
1637 #endif
1638
1639 MapBlock * ServerMap::createBlock(v3s16 p)
1640 {
1641         /*
1642                 Do not create over max mapgen limit
1643         */
1644         if (blockpos_over_max_limit(p))
1645                 throw InvalidPositionException("createBlock(): pos. over max mapgen limit");
1646
1647         v2s16 p2d(p.X, p.Z);
1648         s16 block_y = p.Y;
1649         /*
1650                 This will create or load a sector if not found in memory.
1651                 If block exists on disk, it will be loaded.
1652
1653                 NOTE: On old save formats, this will be slow, as it generates
1654                       lighting on blocks for them.
1655         */
1656         MapSector *sector;
1657         try {
1658                 sector = createSector(p2d);
1659         } catch (InvalidPositionException &e) {
1660                 infostream<<"createBlock: createSector() failed"<<std::endl;
1661                 throw e;
1662         }
1663
1664         /*
1665                 Try to get a block from the sector
1666         */
1667
1668         MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
1669         if (block) {
1670                 if(block->isDummy())
1671                         block->unDummify();
1672                 return block;
1673         }
1674         // Create blank
1675         block = sector->createBlankBlock(block_y);
1676
1677         return block;
1678 }
1679
1680 MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
1681 {
1682         {
1683                 MapBlock *block = getBlockNoCreateNoEx(p);
1684                 if (block && !block->isDummy())
1685                         return block;
1686         }
1687
1688         {
1689                 MapBlock *block = loadBlock(p);
1690                 if(block)
1691                         return block;
1692         }
1693
1694         if (create_blank) {
1695                 MapSector *sector = createSector(v2s16(p.X, p.Z));
1696                 MapBlock *block = sector->createBlankBlock(p.Y);
1697
1698                 return block;
1699         }
1700
1701         return NULL;
1702 }
1703
1704 MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d)
1705 {
1706         MapBlock *block = getBlockNoCreateNoEx(p3d);
1707         if (block == NULL)
1708                 m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, p3d, false);
1709
1710         return block;
1711 }
1712
1713 // N.B.  This requires no synchronization, since data will not be modified unless
1714 // the VoxelManipulator being updated belongs to the same thread.
1715 void ServerMap::updateVManip(v3s16 pos)
1716 {
1717         Mapgen *mg = m_emerge->getCurrentMapgen();
1718         if (!mg)
1719                 return;
1720
1721         MMVManip *vm = mg->vm;
1722         if (!vm)
1723                 return;
1724
1725         if (!vm->m_area.contains(pos))
1726                 return;
1727
1728         s32 idx = vm->m_area.index(pos);
1729         vm->m_data[idx] = getNode(pos);
1730         vm->m_flags[idx] &= ~VOXELFLAG_NO_DATA;
1731
1732         vm->m_is_dirty = true;
1733 }
1734
1735 s16 ServerMap::findGroundLevel(v2s16 p2d)
1736 {
1737 #if 0
1738         /*
1739                 Uh, just do something random...
1740         */
1741         // Find existing map from top to down
1742         s16 max=63;
1743         s16 min=-64;
1744         v3s16 p(p2d.X, max, p2d.Y);
1745         for(; p.Y>min; p.Y--)
1746         {
1747                 MapNode n = getNodeNoEx(p);
1748                 if(n.getContent() != CONTENT_IGNORE)
1749                         break;
1750         }
1751         if(p.Y == min)
1752                 goto plan_b;
1753         // If this node is not air, go to plan b
1754         if(getNodeNoEx(p).getContent() != CONTENT_AIR)
1755                 goto plan_b;
1756         // Search existing walkable and return it
1757         for(; p.Y>min; p.Y--)
1758         {
1759                 MapNode n = getNodeNoEx(p);
1760                 if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE)
1761                         return p.Y;
1762         }
1763
1764         // Move to plan b
1765 plan_b:
1766 #endif
1767
1768         /*
1769                 Determine from map generator noise functions
1770         */
1771
1772         s16 level = m_emerge->getGroundLevelAtPoint(p2d);
1773         return level;
1774
1775         //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
1776         //return (s16)level;
1777 }
1778
1779 void ServerMap::createDirs(const std::string &path)
1780 {
1781         if (!fs::CreateAllDirs(path)) {
1782                 m_dout<<"ServerMap: Failed to create directory "
1783                                 <<"\""<<path<<"\""<<std::endl;
1784                 throw BaseException("ServerMap failed to create directory");
1785         }
1786 }
1787
1788 void ServerMap::save(ModifiedState save_level)
1789 {
1790         if (!m_map_saving_enabled) {
1791                 warningstream<<"Not saving map, saving disabled."<<std::endl;
1792                 return;
1793         }
1794
1795         u64 start_time = porting::getTimeNs();
1796
1797         if(save_level == MOD_STATE_CLEAN)
1798                 infostream<<"ServerMap: Saving whole map, this can take time."
1799                                 <<std::endl;
1800
1801         if (m_map_metadata_changed || save_level == MOD_STATE_CLEAN) {
1802                 if (settings_mgr.saveMapMeta())
1803                         m_map_metadata_changed = false;
1804         }
1805
1806         // Profile modified reasons
1807         Profiler modprofiler;
1808
1809         u32 block_count = 0;
1810         u32 block_count_all = 0; // Number of blocks in memory
1811
1812         // Don't do anything with sqlite unless something is really saved
1813         bool save_started = false;
1814
1815         for (auto &sector_it : m_sectors) {
1816                 MapSector *sector = sector_it.second;
1817
1818                 MapBlockVect blocks;
1819                 sector->getBlocks(blocks);
1820
1821                 for (MapBlock *block : blocks) {
1822                         block_count_all++;
1823
1824                         if(block->getModified() >= (u32)save_level) {
1825                                 // Lazy beginSave()
1826                                 if(!save_started) {
1827                                         beginSave();
1828                                         save_started = true;
1829                                 }
1830
1831                                 modprofiler.add(block->getModifiedReasonString(), 1);
1832
1833                                 saveBlock(block);
1834                                 block_count++;
1835                         }
1836                 }
1837         }
1838
1839         if(save_started)
1840                 endSave();
1841
1842         /*
1843                 Only print if something happened or saved whole map
1844         */
1845         if(save_level == MOD_STATE_CLEAN
1846                         || block_count != 0) {
1847                 infostream << "ServerMap: Written: "
1848                                 << block_count << " blocks"
1849                                 << ", " << block_count_all << " blocks in memory."
1850                                 << std::endl;
1851                 PrintInfo(infostream); // ServerMap/ClientMap:
1852                 infostream<<"Blocks modified by: "<<std::endl;
1853                 modprofiler.print(infostream);
1854         }
1855
1856         auto end_time = porting::getTimeNs();
1857         m_save_time_counter->increment(end_time - start_time);
1858 }
1859
1860 void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
1861 {
1862         dbase->listAllLoadableBlocks(dst);
1863         if (dbase_ro)
1864                 dbase_ro->listAllLoadableBlocks(dst);
1865 }
1866
1867 void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
1868 {
1869         for (auto &sector_it : m_sectors) {
1870                 MapSector *sector = sector_it.second;
1871
1872                 MapBlockVect blocks;
1873                 sector->getBlocks(blocks);
1874
1875                 for (MapBlock *block : blocks) {
1876                         v3s16 p = block->getPos();
1877                         dst.push_back(p);
1878                 }
1879         }
1880 }
1881
1882 MapDatabase *ServerMap::createDatabase(
1883         const std::string &name,
1884         const std::string &savedir,
1885         Settings &conf)
1886 {
1887         if (name == "sqlite3")
1888                 return new MapDatabaseSQLite3(savedir);
1889         if (name == "dummy")
1890                 return new Database_Dummy();
1891         #if USE_LEVELDB
1892         if (name == "leveldb")
1893                 return new Database_LevelDB(savedir);
1894         #endif
1895         #if USE_REDIS
1896         if (name == "redis")
1897                 return new Database_Redis(conf);
1898         #endif
1899         #if USE_POSTGRESQL
1900         if (name == "postgresql") {
1901                 std::string connect_string;
1902                 conf.getNoEx("pgsql_connection", connect_string);
1903                 return new MapDatabasePostgreSQL(connect_string);
1904         }
1905         #endif
1906
1907         throw BaseException(std::string("Database backend ") + name + " not supported.");
1908 }
1909
1910 void ServerMap::pingDatabase()
1911 {
1912         dbase->pingDatabase();
1913 }
1914
1915 void ServerMap::beginSave()
1916 {
1917         dbase->beginSave();
1918 }
1919
1920 void ServerMap::endSave()
1921 {
1922         dbase->endSave();
1923 }
1924
1925 bool ServerMap::saveBlock(MapBlock *block)
1926 {
1927         return saveBlock(block, dbase);
1928 }
1929
1930 bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db)
1931 {
1932         v3s16 p3d = block->getPos();
1933
1934         // Dummy blocks are not written
1935         if (block->isDummy()) {
1936                 warningstream << "saveBlock: Not writing dummy block "
1937                         << PP(p3d) << std::endl;
1938                 return true;
1939         }
1940
1941         // Format used for writing
1942         u8 version = SER_FMT_VER_HIGHEST_WRITE;
1943
1944         /*
1945                 [0] u8 serialization version
1946                 [1] data
1947         */
1948         std::ostringstream o(std::ios_base::binary);
1949         o.write((char*) &version, 1);
1950         block->serialize(o, version, true);
1951
1952         bool ret = db->saveBlock(p3d, o.str());
1953         if (ret) {
1954                 // We just wrote it to the disk so clear modified flag
1955                 block->resetModified();
1956         }
1957         return ret;
1958 }
1959
1960 void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load)
1961 {
1962         try {
1963                 std::istringstream is(*blob, std::ios_base::binary);
1964
1965                 u8 version = SER_FMT_VER_INVALID;
1966                 is.read((char*)&version, 1);
1967
1968                 if(is.fail())
1969                         throw SerializationError("ServerMap::loadBlock(): Failed"
1970                                         " to read MapBlock version");
1971
1972                 MapBlock *block = NULL;
1973                 bool created_new = false;
1974                 block = sector->getBlockNoCreateNoEx(p3d.Y);
1975                 if(block == NULL)
1976                 {
1977                         block = sector->createBlankBlockNoInsert(p3d.Y);
1978                         created_new = true;
1979                 }
1980
1981                 // Read basic data
1982                 block->deSerialize(is, version, true);
1983
1984                 // If it's a new block, insert it to the map
1985                 if (created_new) {
1986                         sector->insertBlock(block);
1987                         ReflowScan scanner(this, m_emerge->ndef);
1988                         scanner.scan(block, &m_transforming_liquid);
1989                 }
1990
1991                 /*
1992                         Save blocks loaded in old format in new format
1993                 */
1994
1995                 //if(version < SER_FMT_VER_HIGHEST_READ || save_after_load)
1996                 // Only save if asked to; no need to update version
1997                 if(save_after_load)
1998                         saveBlock(block);
1999
2000                 // We just loaded it from, so it's up-to-date.
2001                 block->resetModified();
2002         }
2003         catch(SerializationError &e)
2004         {
2005                 errorstream<<"Invalid block data in database"
2006                                 <<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
2007                                 <<" (SerializationError): "<<e.what()<<std::endl;
2008
2009                 // TODO: Block should be marked as invalid in memory so that it is
2010                 // not touched but the game can run
2011
2012                 if(g_settings->getBool("ignore_world_load_errors")){
2013                         errorstream<<"Ignoring block load error. Duck and cover! "
2014                                         <<"(ignore_world_load_errors)"<<std::endl;
2015                 } else {
2016                         throw SerializationError("Invalid block data in database");
2017                 }
2018         }
2019 }
2020
2021 MapBlock* ServerMap::loadBlock(v3s16 blockpos)
2022 {
2023         bool created_new = (getBlockNoCreateNoEx(blockpos) == NULL);
2024
2025         v2s16 p2d(blockpos.X, blockpos.Z);
2026
2027         std::string ret;
2028         dbase->loadBlock(blockpos, &ret);
2029         if (!ret.empty()) {
2030                 loadBlock(&ret, blockpos, createSector(p2d), false);
2031         } else if (dbase_ro) {
2032                 dbase_ro->loadBlock(blockpos, &ret);
2033                 if (!ret.empty()) {
2034                         loadBlock(&ret, blockpos, createSector(p2d), false);
2035                 }
2036         } else {
2037                 return NULL;
2038         }
2039
2040         MapBlock *block = getBlockNoCreateNoEx(blockpos);
2041         if (created_new && (block != NULL)) {
2042                 std::map<v3s16, MapBlock*> modified_blocks;
2043                 // Fix lighting if necessary
2044                 voxalgo::update_block_border_lighting(this, block, modified_blocks);
2045                 if (!modified_blocks.empty()) {
2046                         //Modified lighting, send event
2047                         MapEditEvent event;
2048                         event.type = MEET_OTHER;
2049                         std::map<v3s16, MapBlock *>::iterator it;
2050                         for (it = modified_blocks.begin();
2051                                         it != modified_blocks.end(); ++it)
2052                                 event.modified_blocks.insert(it->first);
2053                         dispatchEvent(event);
2054                 }
2055         }
2056         return block;
2057 }
2058
2059 bool ServerMap::deleteBlock(v3s16 blockpos)
2060 {
2061         if (!dbase->deleteBlock(blockpos))
2062                 return false;
2063
2064         MapBlock *block = getBlockNoCreateNoEx(blockpos);
2065         if (block) {
2066                 v2s16 p2d(blockpos.X, blockpos.Z);
2067                 MapSector *sector = getSectorNoGenerate(p2d);
2068                 if (!sector)
2069                         return false;
2070                 sector->deleteBlock(block);
2071         }
2072
2073         return true;
2074 }
2075
2076 void ServerMap::PrintInfo(std::ostream &out)
2077 {
2078         out<<"ServerMap: ";
2079 }
2080
2081 bool ServerMap::repairBlockLight(v3s16 blockpos,
2082         std::map<v3s16, MapBlock *> *modified_blocks)
2083 {
2084         MapBlock *block = emergeBlock(blockpos, false);
2085         if (!block || !block->isGenerated())
2086                 return false;
2087         voxalgo::repair_block_light(this, block, modified_blocks);
2088         return true;
2089 }
2090
2091 MMVManip::MMVManip(Map *map):
2092                 VoxelManipulator(),
2093                 m_map(map)
2094 {
2095 }
2096
2097 void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
2098         bool load_if_inexistent)
2099 {
2100         TimeTaker timer1("initialEmerge", &emerge_time);
2101
2102         // Units of these are MapBlocks
2103         v3s16 p_min = blockpos_min;
2104         v3s16 p_max = blockpos_max;
2105
2106         VoxelArea block_area_nodes
2107                         (p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
2108
2109         u32 size_MB = block_area_nodes.getVolume()*4/1000000;
2110         if(size_MB >= 1)
2111         {
2112                 infostream<<"initialEmerge: area: ";
2113                 block_area_nodes.print(infostream);
2114                 infostream<<" ("<<size_MB<<"MB)";
2115                 infostream<<std::endl;
2116         }
2117
2118         addArea(block_area_nodes);
2119
2120         for(s32 z=p_min.Z; z<=p_max.Z; z++)
2121         for(s32 y=p_min.Y; y<=p_max.Y; y++)
2122         for(s32 x=p_min.X; x<=p_max.X; x++)
2123         {
2124                 u8 flags = 0;
2125                 MapBlock *block;
2126                 v3s16 p(x,y,z);
2127                 std::map<v3s16, u8>::iterator n;
2128                 n = m_loaded_blocks.find(p);
2129                 if(n != m_loaded_blocks.end())
2130                         continue;
2131
2132                 bool block_data_inexistent = false;
2133                 {
2134                         TimeTaker timer2("emerge load", &emerge_load_time);
2135
2136                         block = m_map->getBlockNoCreateNoEx(p);
2137                         if (!block || block->isDummy())
2138                                 block_data_inexistent = true;
2139                         else
2140                                 block->copyTo(*this);
2141                 }
2142
2143                 if(block_data_inexistent)
2144                 {
2145
2146                         if (load_if_inexistent && !blockpos_over_max_limit(p)) {
2147                                 ServerMap *svrmap = (ServerMap *)m_map;
2148                                 block = svrmap->emergeBlock(p, false);
2149                                 if (block == NULL)
2150                                         block = svrmap->createBlock(p);
2151                                 block->copyTo(*this);
2152                         } else {
2153                                 flags |= VMANIP_BLOCK_DATA_INEXIST;
2154
2155                                 /*
2156                                         Mark area inexistent
2157                                 */
2158                                 VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
2159                                 // Fill with VOXELFLAG_NO_DATA
2160                                 for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
2161                                 for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
2162                                 {
2163                                         s32 i = m_area.index(a.MinEdge.X,y,z);
2164                                         memset(&m_flags[i], VOXELFLAG_NO_DATA, MAP_BLOCKSIZE);
2165                                 }
2166                         }
2167                 }
2168                 /*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE)
2169                 {
2170                         // Mark that block was loaded as blank
2171                         flags |= VMANIP_BLOCK_CONTAINS_CIGNORE;
2172                 }*/
2173
2174                 m_loaded_blocks[p] = flags;
2175         }
2176
2177         m_is_dirty = false;
2178 }
2179
2180 void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
2181         bool overwrite_generated)
2182 {
2183         if(m_area.getExtent() == v3s16(0,0,0))
2184                 return;
2185
2186         /*
2187                 Copy data of all blocks
2188         */
2189         for (auto &loaded_block : m_loaded_blocks) {
2190                 v3s16 p = loaded_block.first;
2191                 MapBlock *block = m_map->getBlockNoCreateNoEx(p);
2192                 bool existed = !(loaded_block.second & VMANIP_BLOCK_DATA_INEXIST);
2193                 if (!existed || (block == NULL) ||
2194                         (!overwrite_generated && block->isGenerated()))
2195                         continue;
2196
2197                 block->copyFrom(*this);
2198                 block->raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_VMANIP);
2199
2200                 if(modified_blocks)
2201                         (*modified_blocks)[p] = block;
2202         }
2203 }
2204
2205 //END