servermap.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2024 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "map.h"
  17. #include "mapsector.h"
  18. #include "filesys.h"
  19. #include "voxel.h"
  20. #include "voxelalgorithms.h"
  21. #include "porting.h"
  22. #include "serialization.h"
  23. #include "settings.h"
  24. #include "log.h"
  25. #include "profiler.h"
  26. #include "gamedef.h"
  27. #include "util/directiontables.h"
  28. #include "rollback_interface.h"
  29. #include "reflowscan.h"
  30. #include "emerge.h"
  31. #include "mapgen/mapgen_v6.h"
  32. #include "mapgen/mg_biome.h"
  33. #include "config.h"
  34. #include "server.h"
  35. #include "database/database.h"
  36. #include "database/database-dummy.h"
  37. #include "database/database-sqlite3.h"
  38. #include "script/scripting_server.h"
  39. #include "irrlicht_changes/printing.h"
  40. #if USE_LEVELDB
  41. #include "database/database-leveldb.h"
  42. #endif
  43. #if USE_REDIS
  44. #include "database/database-redis.h"
  45. #endif
  46. #if USE_POSTGRESQL
  47. #include "database/database-postgresql.h"
  48. #endif
  49. /*
  50. ServerMap
  51. */
  52. ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef,
  53. EmergeManager *emerge, MetricsBackend *mb):
  54. Map(gamedef),
  55. settings_mgr(savedir + DIR_DELIM + "map_meta.txt"),
  56. m_emerge(emerge)
  57. {
  58. verbosestream<<FUNCTION_NAME<<std::endl;
  59. // Tell the EmergeManager about our MapSettingsManager
  60. emerge->map_settings_mgr = &settings_mgr;
  61. /*
  62. Try to load map; if not found, create a new one.
  63. */
  64. // Determine which database backend to use
  65. std::string conf_path = savedir + DIR_DELIM + "world.mt";
  66. Settings conf;
  67. bool succeeded = conf.readConfigFile(conf_path.c_str());
  68. if (!succeeded || !conf.exists("backend")) {
  69. // fall back to sqlite3
  70. conf.set("backend", "sqlite3");
  71. }
  72. std::string backend = conf.get("backend");
  73. dbase = createDatabase(backend, savedir, conf);
  74. if (conf.exists("readonly_backend")) {
  75. std::string readonly_dir = savedir + DIR_DELIM + "readonly";
  76. dbase_ro = createDatabase(conf.get("readonly_backend"), readonly_dir, conf);
  77. }
  78. if (!conf.updateConfigFile(conf_path.c_str()))
  79. errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl;
  80. m_savedir = savedir;
  81. m_map_saving_enabled = false;
  82. m_save_time_counter = mb->addCounter(
  83. "minetest_map_save_time", "Time spent saving blocks (in microseconds)");
  84. m_save_count_counter = mb->addCounter(
  85. "minetest_map_saved_blocks", "Number of blocks saved");
  86. m_loaded_blocks_gauge = mb->addGauge(
  87. "minetest_map_loaded_blocks", "Number of loaded blocks");
  88. m_map_compression_level = rangelim(g_settings->getS16("map_compression_level_disk"), -1, 9);
  89. try {
  90. // If directory exists, check contents and load if possible
  91. if (fs::PathExists(m_savedir)) {
  92. // If directory is empty, it is safe to save into it.
  93. if (fs::GetDirListing(m_savedir).empty()) {
  94. infostream<<"ServerMap: Empty save directory is valid."
  95. <<std::endl;
  96. m_map_saving_enabled = true;
  97. }
  98. else
  99. {
  100. if (settings_mgr.loadMapMeta()) {
  101. infostream << "ServerMap: Metadata loaded from "
  102. << savedir << std::endl;
  103. } else {
  104. infostream << "ServerMap: Metadata could not be loaded "
  105. "from " << savedir << ", assuming valid save "
  106. "directory." << std::endl;
  107. }
  108. m_map_saving_enabled = true;
  109. // Map loaded, not creating new one
  110. return;
  111. }
  112. }
  113. // If directory doesn't exist, it is safe to save to it
  114. else{
  115. m_map_saving_enabled = true;
  116. }
  117. }
  118. catch(std::exception &e)
  119. {
  120. warningstream<<"ServerMap: Failed to load map from "<<savedir
  121. <<", exception: "<<e.what()<<std::endl;
  122. infostream<<"Please remove the map or fix it."<<std::endl;
  123. warningstream<<"Map saving will be disabled."<<std::endl;
  124. }
  125. }
  126. ServerMap::~ServerMap()
  127. {
  128. verbosestream<<FUNCTION_NAME<<std::endl;
  129. try
  130. {
  131. if (m_map_saving_enabled) {
  132. // Save only changed parts
  133. save(MOD_STATE_WRITE_AT_UNLOAD);
  134. infostream << "ServerMap: Saved map to " << m_savedir << std::endl;
  135. } else {
  136. infostream << "ServerMap: Map not saved" << std::endl;
  137. }
  138. }
  139. catch(std::exception &e)
  140. {
  141. errorstream << "ServerMap: Failed to save map to " << m_savedir
  142. << ", exception: " << e.what() << std::endl;
  143. }
  144. /*
  145. Close database if it was opened
  146. */
  147. delete dbase;
  148. delete dbase_ro;
  149. deleteDetachedBlocks();
  150. }
  151. MapgenParams *ServerMap::getMapgenParams()
  152. {
  153. // getMapgenParams() should only ever be called after Server is initialized
  154. assert(settings_mgr.mapgen_params != NULL);
  155. return settings_mgr.mapgen_params;
  156. }
  157. u64 ServerMap::getSeed()
  158. {
  159. return getMapgenParams()->seed;
  160. }
  161. bool ServerMap::blockpos_over_mapgen_limit(v3s16 p)
  162. {
  163. const s16 mapgen_limit_bp = rangelim(
  164. getMapgenParams()->mapgen_limit, 0, MAX_MAP_GENERATION_LIMIT) /
  165. MAP_BLOCKSIZE;
  166. return p.X < -mapgen_limit_bp ||
  167. p.X > mapgen_limit_bp ||
  168. p.Y < -mapgen_limit_bp ||
  169. p.Y > mapgen_limit_bp ||
  170. p.Z < -mapgen_limit_bp ||
  171. p.Z > mapgen_limit_bp;
  172. }
  173. bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
  174. {
  175. s16 csize = getMapgenParams()->chunksize;
  176. v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize);
  177. v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1);
  178. if (!m_chunks_in_progress.insert(bpmin).second)
  179. return false;
  180. bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
  181. EMERGE_DBG_OUT("initBlockMake(): " << bpmin << " - " << bpmax);
  182. v3s16 extra_borders(1, 1, 1);
  183. v3s16 full_bpmin = bpmin - extra_borders;
  184. v3s16 full_bpmax = bpmax + extra_borders;
  185. // Do nothing if not inside mapgen limits (+-1 because of neighbors)
  186. if (blockpos_over_mapgen_limit(full_bpmin) ||
  187. blockpos_over_mapgen_limit(full_bpmax))
  188. return false;
  189. data->seed = getSeed();
  190. data->blockpos_min = bpmin;
  191. data->blockpos_max = bpmax;
  192. data->nodedef = m_nodedef;
  193. /*
  194. Create the whole area of this and the neighboring blocks
  195. */
  196. for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
  197. for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++) {
  198. v2s16 sectorpos(x, z);
  199. // Sector metadata is loaded from disk if not already loaded.
  200. MapSector *sector = createSector(sectorpos);
  201. FATAL_ERROR_IF(sector == NULL, "createSector() failed");
  202. for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
  203. v3s16 p(x, y, z);
  204. MapBlock *block = emergeBlock(p, false);
  205. if (block == NULL) {
  206. block = createBlock(p);
  207. // Block gets sunlight if this is true.
  208. // Refer to the map generator heuristics.
  209. bool ug = m_emerge->isBlockUnderground(p);
  210. block->setIsUnderground(ug);
  211. }
  212. }
  213. }
  214. /*
  215. Now we have a big empty area.
  216. Make a ManualMapVoxelManipulator that contains this and the
  217. neighboring blocks
  218. */
  219. data->vmanip = new MMVManip(this);
  220. data->vmanip->initialEmerge(full_bpmin, full_bpmax);
  221. // Data is ready now.
  222. return true;
  223. }
  224. void ServerMap::finishBlockMake(BlockMakeData *data,
  225. std::map<v3s16, MapBlock*> *changed_blocks)
  226. {
  227. v3s16 bpmin = data->blockpos_min;
  228. v3s16 bpmax = data->blockpos_max;
  229. bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info;
  230. EMERGE_DBG_OUT("finishBlockMake(): " << bpmin << " - " << bpmax);
  231. /*
  232. Blit generated stuff to map
  233. NOTE: blitBackAll adds nearly everything to changed_blocks
  234. */
  235. data->vmanip->blitBackAll(changed_blocks);
  236. EMERGE_DBG_OUT("finishBlockMake: changed_blocks.size()="
  237. << changed_blocks->size());
  238. /*
  239. Copy transforming liquid information
  240. */
  241. while (data->transforming_liquid.size()) {
  242. m_transforming_liquid.push_back(data->transforming_liquid.front());
  243. data->transforming_liquid.pop_front();
  244. }
  245. for (auto &changed_block : *changed_blocks) {
  246. MapBlock *block = changed_block.second;
  247. if (!block)
  248. continue;
  249. /*
  250. Update is air cache of the MapBlocks
  251. */
  252. block->expireIsAirCache();
  253. /*
  254. Set block as modified
  255. */
  256. block->raiseModified(MOD_STATE_WRITE_NEEDED,
  257. MOD_REASON_EXPIRE_IS_AIR);
  258. }
  259. /*
  260. Set central blocks as generated
  261. */
  262. for (s16 x = bpmin.X; x <= bpmax.X; x++)
  263. for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
  264. for (s16 y = bpmin.Y; y <= bpmax.Y; y++) {
  265. MapBlock *block = getBlockNoCreateNoEx(v3s16(x, y, z));
  266. if (!block)
  267. continue;
  268. block->setGenerated(true);
  269. }
  270. /*
  271. Save changed parts of map
  272. NOTE: Will be saved later.
  273. */
  274. //save(MOD_STATE_WRITE_AT_UNLOAD);
  275. m_chunks_in_progress.erase(bpmin);
  276. }
  277. MapSector *ServerMap::createSector(v2s16 p2d)
  278. {
  279. /*
  280. Check if it exists already in memory
  281. */
  282. MapSector *sector = getSectorNoGenerate(p2d);
  283. if (sector)
  284. return sector;
  285. /*
  286. Do not create over max mapgen limit
  287. */
  288. if (blockpos_over_max_limit(v3s16(p2d.X, 0, p2d.Y)))
  289. throw InvalidPositionException("createSector(): pos over max mapgen limit");
  290. /*
  291. Generate blank sector
  292. */
  293. sector = new MapSector(this, p2d, m_gamedef);
  294. /*
  295. Insert to container
  296. */
  297. m_sectors[p2d] = sector;
  298. return sector;
  299. }
  300. MapBlock * ServerMap::createBlock(v3s16 p)
  301. {
  302. v2s16 p2d(p.X, p.Z);
  303. s16 block_y = p.Y;
  304. /*
  305. This will create or load a sector if not found in memory.
  306. */
  307. MapSector *sector;
  308. try {
  309. sector = createSector(p2d);
  310. } catch (InvalidPositionException &e) {
  311. infostream<<"createBlock: createSector() failed"<<std::endl;
  312. throw e;
  313. }
  314. /*
  315. Try to get a block from the sector
  316. */
  317. MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
  318. if (block)
  319. return block;
  320. // Create blank
  321. try {
  322. block = sector->createBlankBlock(block_y);
  323. } catch (InvalidPositionException &e) {
  324. infostream << "createBlock: createBlankBlock() failed" << std::endl;
  325. throw e;
  326. }
  327. return block;
  328. }
  329. MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
  330. {
  331. {
  332. MapBlock *block = getBlockNoCreateNoEx(p);
  333. if (block)
  334. return block;
  335. }
  336. {
  337. MapBlock *block = loadBlock(p);
  338. if(block)
  339. return block;
  340. }
  341. if (create_blank) {
  342. try {
  343. MapSector *sector = createSector(v2s16(p.X, p.Z));
  344. return sector->createBlankBlock(p.Y);
  345. } catch (InvalidPositionException &e) {}
  346. }
  347. return NULL;
  348. }
  349. MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d, bool generate)
  350. {
  351. MapBlock *block = getBlockNoCreateNoEx(p3d);
  352. if (block == NULL)
  353. m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, p3d, generate);
  354. return block;
  355. }
  356. bool ServerMap::isBlockInQueue(v3s16 pos)
  357. {
  358. return m_emerge && m_emerge->isBlockInQueue(pos);
  359. }
  360. void ServerMap::addNodeAndUpdate(v3s16 p, MapNode n,
  361. std::map<v3s16, MapBlock*> &modified_blocks,
  362. bool remove_metadata)
  363. {
  364. Map::addNodeAndUpdate(p, n, modified_blocks, remove_metadata);
  365. /*
  366. Add neighboring liquid nodes and this node to transform queue.
  367. (it's vital for the node itself to get updated last, if it was removed.)
  368. */
  369. for (const v3s16 &dir : g_7dirs) {
  370. v3s16 p2 = p + dir;
  371. bool is_valid_position;
  372. MapNode n2 = getNode(p2, &is_valid_position);
  373. if(is_valid_position &&
  374. (m_nodedef->get(n2).isLiquid() ||
  375. n2.getContent() == CONTENT_AIR))
  376. m_transforming_liquid.push_back(p2);
  377. }
  378. }
  379. // N.B. This requires no synchronization, since data will not be modified unless
  380. // the VoxelManipulator being updated belongs to the same thread.
  381. void ServerMap::updateVManip(v3s16 pos)
  382. {
  383. Mapgen *mg = m_emerge->getCurrentMapgen();
  384. if (!mg)
  385. return;
  386. MMVManip *vm = mg->vm;
  387. if (!vm)
  388. return;
  389. if (!vm->m_area.contains(pos))
  390. return;
  391. s32 idx = vm->m_area.index(pos);
  392. vm->m_data[idx] = getNode(pos);
  393. vm->m_flags[idx] &= ~VOXELFLAG_NO_DATA;
  394. vm->m_is_dirty = true;
  395. }
  396. void ServerMap::reportMetrics(u64 save_time_us, u32 saved_blocks, u32 all_blocks)
  397. {
  398. m_loaded_blocks_gauge->set(all_blocks);
  399. m_save_time_counter->increment(save_time_us);
  400. m_save_count_counter->increment(saved_blocks);
  401. }
  402. void ServerMap::save(ModifiedState save_level)
  403. {
  404. if (!m_map_saving_enabled) {
  405. warningstream<<"Not saving map, saving disabled."<<std::endl;
  406. return;
  407. }
  408. const auto start_time = porting::getTimeUs();
  409. if(save_level == MOD_STATE_CLEAN)
  410. infostream<<"ServerMap: Saving whole map, this can take time."
  411. <<std::endl;
  412. if (m_map_metadata_changed || save_level == MOD_STATE_CLEAN) {
  413. if (settings_mgr.saveMapMeta())
  414. m_map_metadata_changed = false;
  415. }
  416. // Profile modified reasons
  417. Profiler modprofiler;
  418. u32 block_count = 0;
  419. u32 block_count_all = 0; // Number of blocks in memory
  420. // Don't do anything with sqlite unless something is really saved
  421. bool save_started = false;
  422. for (auto &sector_it : m_sectors) {
  423. MapSector *sector = sector_it.second;
  424. MapBlockVect blocks;
  425. sector->getBlocks(blocks);
  426. for (MapBlock *block : blocks) {
  427. block_count_all++;
  428. if(block->getModified() >= (u32)save_level) {
  429. // Lazy beginSave()
  430. if(!save_started) {
  431. beginSave();
  432. save_started = true;
  433. }
  434. modprofiler.add(block->getModifiedReasonString(), 1);
  435. saveBlock(block);
  436. block_count++;
  437. }
  438. }
  439. }
  440. if(save_started)
  441. endSave();
  442. /*
  443. Only print if something happened or saved whole map
  444. */
  445. if(save_level == MOD_STATE_CLEAN
  446. || block_count != 0) {
  447. infostream << "ServerMap: Written: "
  448. << block_count << " blocks"
  449. << ", " << block_count_all << " blocks in memory."
  450. << std::endl;
  451. PrintInfo(infostream); // ServerMap/ClientMap:
  452. infostream<<"Blocks modified by: "<<std::endl;
  453. modprofiler.print(infostream);
  454. }
  455. const auto end_time = porting::getTimeUs();
  456. reportMetrics(end_time - start_time, block_count, block_count_all);
  457. }
  458. void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
  459. {
  460. dbase->listAllLoadableBlocks(dst);
  461. if (dbase_ro)
  462. dbase_ro->listAllLoadableBlocks(dst);
  463. }
  464. void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
  465. {
  466. for (auto &sector_it : m_sectors) {
  467. MapSector *sector = sector_it.second;
  468. MapBlockVect blocks;
  469. sector->getBlocks(blocks);
  470. for (MapBlock *block : blocks) {
  471. v3s16 p = block->getPos();
  472. dst.push_back(p);
  473. }
  474. }
  475. }
  476. MapDatabase *ServerMap::createDatabase(
  477. const std::string &name,
  478. const std::string &savedir,
  479. Settings &conf)
  480. {
  481. if (name == "sqlite3")
  482. return new MapDatabaseSQLite3(savedir);
  483. if (name == "dummy")
  484. return new Database_Dummy();
  485. #if USE_LEVELDB
  486. if (name == "leveldb")
  487. return new Database_LevelDB(savedir);
  488. #endif
  489. #if USE_REDIS
  490. if (name == "redis")
  491. return new Database_Redis(conf);
  492. #endif
  493. #if USE_POSTGRESQL
  494. if (name == "postgresql") {
  495. std::string connect_string;
  496. conf.getNoEx("pgsql_connection", connect_string);
  497. return new MapDatabasePostgreSQL(connect_string);
  498. }
  499. #endif
  500. throw BaseException(std::string("Database backend ") + name + " not supported.");
  501. }
  502. void ServerMap::beginSave()
  503. {
  504. dbase->beginSave();
  505. }
  506. void ServerMap::endSave()
  507. {
  508. dbase->endSave();
  509. }
  510. bool ServerMap::saveBlock(MapBlock *block)
  511. {
  512. return saveBlock(block, dbase, m_map_compression_level);
  513. }
  514. bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db, int compression_level)
  515. {
  516. v3s16 p3d = block->getPos();
  517. // Format used for writing
  518. u8 version = SER_FMT_VER_HIGHEST_WRITE;
  519. /*
  520. [0] u8 serialization version
  521. [1] data
  522. */
  523. std::ostringstream o(std::ios_base::binary);
  524. o.write((char*) &version, 1);
  525. block->serialize(o, version, true, compression_level);
  526. // FIXME: zero copy possible in c++20 or with custom rdbuf
  527. bool ret = db->saveBlock(p3d, o.str());
  528. if (ret) {
  529. // We just wrote it to the disk so clear modified flag
  530. block->resetModified();
  531. }
  532. return ret;
  533. }
  534. void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load)
  535. {
  536. try {
  537. std::istringstream is(*blob, std::ios_base::binary);
  538. u8 version = readU8(is);
  539. if(is.fail())
  540. throw SerializationError("ServerMap::loadBlock(): Failed"
  541. " to read MapBlock version");
  542. MapBlock *block = nullptr;
  543. std::unique_ptr<MapBlock> block_created_new;
  544. block = sector->getBlockNoCreateNoEx(p3d.Y);
  545. if (!block) {
  546. block_created_new = sector->createBlankBlockNoInsert(p3d.Y);
  547. block = block_created_new.get();
  548. }
  549. {
  550. ScopeProfiler sp(g_profiler, "ServerMap: deSer block", SPT_AVG, PRECISION_MICRO);
  551. block->deSerialize(is, version, true);
  552. }
  553. // If it's a new block, insert it to the map
  554. if (block_created_new) {
  555. sector->insertBlock(std::move(block_created_new));
  556. ReflowScan scanner(this, m_emerge->ndef);
  557. scanner.scan(block, &m_transforming_liquid);
  558. }
  559. /*
  560. Save blocks loaded in old format in new format
  561. */
  562. //if(version < SER_FMT_VER_HIGHEST_READ || save_after_load)
  563. // Only save if asked to; no need to update version
  564. if(save_after_load)
  565. saveBlock(block);
  566. // We just loaded it from, so it's up-to-date.
  567. block->resetModified();
  568. }
  569. catch(SerializationError &e)
  570. {
  571. errorstream<<"Invalid block data in database"
  572. <<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
  573. <<" (SerializationError): "<<e.what()<<std::endl;
  574. // TODO: Block should be marked as invalid in memory so that it is
  575. // not touched but the game can run
  576. if(g_settings->getBool("ignore_world_load_errors")){
  577. errorstream<<"Ignoring block load error. Duck and cover! "
  578. <<"(ignore_world_load_errors)"<<std::endl;
  579. } else {
  580. throw SerializationError("Invalid block data in database");
  581. }
  582. }
  583. }
  584. MapBlock* ServerMap::loadBlock(v3s16 blockpos)
  585. {
  586. ScopeProfiler sp(g_profiler, "ServerMap: load block", SPT_AVG, PRECISION_MICRO);
  587. bool created_new = (getBlockNoCreateNoEx(blockpos) == NULL);
  588. v2s16 p2d(blockpos.X, blockpos.Z);
  589. std::string ret;
  590. dbase->loadBlock(blockpos, &ret);
  591. if (!ret.empty()) {
  592. loadBlock(&ret, blockpos, createSector(p2d), false);
  593. } else if (dbase_ro) {
  594. dbase_ro->loadBlock(blockpos, &ret);
  595. if (!ret.empty()) {
  596. loadBlock(&ret, blockpos, createSector(p2d), false);
  597. }
  598. } else {
  599. return NULL;
  600. }
  601. MapBlock *block = getBlockNoCreateNoEx(blockpos);
  602. if (created_new && (block != NULL)) {
  603. std::map<v3s16, MapBlock*> modified_blocks;
  604. // Fix lighting if necessary
  605. voxalgo::update_block_border_lighting(this, block, modified_blocks);
  606. if (!modified_blocks.empty()) {
  607. //Modified lighting, send event
  608. MapEditEvent event;
  609. event.type = MEET_OTHER;
  610. event.setModifiedBlocks(modified_blocks);
  611. dispatchEvent(event);
  612. }
  613. }
  614. return block;
  615. }
  616. bool ServerMap::deleteBlock(v3s16 blockpos)
  617. {
  618. if (!dbase->deleteBlock(blockpos))
  619. return false;
  620. MapBlock *block = getBlockNoCreateNoEx(blockpos);
  621. if (block) {
  622. v2s16 p2d(blockpos.X, blockpos.Z);
  623. MapSector *sector = getSectorNoGenerate(p2d);
  624. if (!sector)
  625. return false;
  626. // It may not be safe to delete the block from memory at the moment
  627. // (pointers to it could still be in use)
  628. m_detached_blocks.push_back(sector->detachBlock(block));
  629. }
  630. return true;
  631. }
  632. void ServerMap::deleteDetachedBlocks()
  633. {
  634. for (const auto &block : m_detached_blocks) {
  635. assert(block->isOrphan());
  636. (void)block; // silence unused-variable warning in release builds
  637. }
  638. m_detached_blocks.clear();
  639. }
  640. void ServerMap::step()
  641. {
  642. // Delete from memory blocks removed by deleteBlocks() only when pointers
  643. // to them are (probably) no longer in use
  644. deleteDetachedBlocks();
  645. }
  646. void ServerMap::PrintInfo(std::ostream &out)
  647. {
  648. out<<"ServerMap: ";
  649. }
  650. bool ServerMap::repairBlockLight(v3s16 blockpos,
  651. std::map<v3s16, MapBlock *> *modified_blocks)
  652. {
  653. MapBlock *block = emergeBlock(blockpos, false);
  654. if (!block || !block->isGenerated())
  655. return false;
  656. voxalgo::repair_block_light(this, block, modified_blocks);
  657. return true;
  658. }
  659. /*
  660. Liquids
  661. */
  662. #define WATER_DROP_BOOST 4
  663. const static v3s16 liquid_6dirs[6] = {
  664. // order: upper before same level before lower
  665. v3s16( 0, 1, 0),
  666. v3s16( 0, 0, 1),
  667. v3s16( 1, 0, 0),
  668. v3s16( 0, 0,-1),
  669. v3s16(-1, 0, 0),
  670. v3s16( 0,-1, 0)
  671. };
  672. enum NeighborType : u8 {
  673. NEIGHBOR_UPPER,
  674. NEIGHBOR_SAME_LEVEL,
  675. NEIGHBOR_LOWER
  676. };
  677. struct NodeNeighbor {
  678. MapNode n;
  679. NeighborType t;
  680. v3s16 p;
  681. NodeNeighbor()
  682. : n(CONTENT_AIR), t(NEIGHBOR_SAME_LEVEL)
  683. { }
  684. NodeNeighbor(const MapNode &node, NeighborType n_type, const v3s16 &pos)
  685. : n(node),
  686. t(n_type),
  687. p(pos)
  688. { }
  689. };
  690. static s8 get_max_liquid_level(NodeNeighbor nb, s8 current_max_node_level)
  691. {
  692. s8 max_node_level = current_max_node_level;
  693. u8 nb_liquid_level = (nb.n.param2 & LIQUID_LEVEL_MASK);
  694. switch (nb.t) {
  695. case NEIGHBOR_UPPER:
  696. if (nb_liquid_level + WATER_DROP_BOOST > current_max_node_level) {
  697. max_node_level = LIQUID_LEVEL_MAX;
  698. if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
  699. max_node_level = nb_liquid_level + WATER_DROP_BOOST;
  700. } else if (nb_liquid_level > current_max_node_level) {
  701. max_node_level = nb_liquid_level;
  702. }
  703. break;
  704. case NEIGHBOR_LOWER:
  705. break;
  706. case NEIGHBOR_SAME_LEVEL:
  707. if ((nb.n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
  708. nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level)
  709. max_node_level = nb_liquid_level - 1;
  710. break;
  711. }
  712. return max_node_level;
  713. }
  714. void ServerMap::transforming_liquid_add(v3s16 p)
  715. {
  716. m_transforming_liquid.push_back(p);
  717. }
  718. void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
  719. ServerEnvironment *env)
  720. {
  721. u32 loopcount = 0;
  722. u32 initial_size = m_transforming_liquid.size();
  723. /*if(initial_size != 0)
  724. infostream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;*/
  725. // list of nodes that due to viscosity have not reached their max level height
  726. std::vector<v3s16> must_reflow;
  727. std::vector<std::pair<v3s16, MapNode> > changed_nodes;
  728. std::vector<v3s16> check_for_falling;
  729. u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
  730. u32 loop_max = liquid_loop_max;
  731. while (m_transforming_liquid.size() != 0)
  732. {
  733. // This should be done here so that it is done when continue is used
  734. if (loopcount >= initial_size || loopcount >= loop_max)
  735. break;
  736. loopcount++;
  737. /*
  738. Get a queued transforming liquid node
  739. */
  740. v3s16 p0 = m_transforming_liquid.front();
  741. m_transforming_liquid.pop_front();
  742. MapNode n0 = getNode(p0);
  743. /*
  744. Collect information about current node
  745. */
  746. s8 liquid_level = -1;
  747. // The liquid node which will be placed there if
  748. // the liquid flows into this node.
  749. content_t liquid_kind = CONTENT_IGNORE;
  750. // The node which will be placed there if liquid
  751. // can't flow into this node.
  752. content_t floodable_node = CONTENT_AIR;
  753. const ContentFeatures &cf = m_nodedef->get(n0);
  754. LiquidType liquid_type = cf.liquid_type;
  755. switch (liquid_type) {
  756. case LIQUID_SOURCE:
  757. liquid_level = LIQUID_LEVEL_SOURCE;
  758. liquid_kind = cf.liquid_alternative_flowing_id;
  759. break;
  760. case LIQUID_FLOWING:
  761. liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
  762. liquid_kind = n0.getContent();
  763. break;
  764. case LIQUID_NONE:
  765. // if this node is 'floodable', it *could* be transformed
  766. // into a liquid, otherwise, continue with the next node.
  767. if (!cf.floodable)
  768. continue;
  769. floodable_node = n0.getContent();
  770. liquid_kind = CONTENT_AIR;
  771. break;
  772. case LiquidType_END:
  773. break;
  774. }
  775. /*
  776. Collect information about the environment
  777. */
  778. NodeNeighbor sources[6]; // surrounding sources
  779. int num_sources = 0;
  780. NodeNeighbor flows[6]; // surrounding flowing liquid nodes
  781. int num_flows = 0;
  782. NodeNeighbor airs[6]; // surrounding air
  783. int num_airs = 0;
  784. NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
  785. int num_neutrals = 0;
  786. bool flowing_down = false;
  787. bool ignored_sources = false;
  788. bool floating_node_above = false;
  789. for (u16 i = 0; i < 6; i++) {
  790. NeighborType nt = NEIGHBOR_SAME_LEVEL;
  791. switch (i) {
  792. case 0:
  793. nt = NEIGHBOR_UPPER;
  794. break;
  795. case 5:
  796. nt = NEIGHBOR_LOWER;
  797. break;
  798. default:
  799. break;
  800. }
  801. v3s16 npos = p0 + liquid_6dirs[i];
  802. NodeNeighbor nb(getNode(npos), nt, npos);
  803. const ContentFeatures &cfnb = m_nodedef->get(nb.n);
  804. if (nt == NEIGHBOR_UPPER && cfnb.floats)
  805. floating_node_above = true;
  806. switch (cfnb.liquid_type) {
  807. case LIQUID_NONE:
  808. if (cfnb.floodable) {
  809. airs[num_airs++] = nb;
  810. // if the current node is a water source the neighbor
  811. // should be enqueded for transformation regardless of whether the
  812. // current node changes or not.
  813. if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
  814. m_transforming_liquid.push_back(npos);
  815. // if the current node happens to be a flowing node, it will start to flow down here.
  816. if (nb.t == NEIGHBOR_LOWER)
  817. flowing_down = true;
  818. } else {
  819. neutrals[num_neutrals++] = nb;
  820. if (nb.n.getContent() == CONTENT_IGNORE) {
  821. // If node below is ignore prevent water from
  822. // spreading outwards and otherwise prevent from
  823. // flowing away as ignore node might be the source
  824. if (nb.t == NEIGHBOR_LOWER)
  825. flowing_down = true;
  826. else
  827. ignored_sources = true;
  828. }
  829. }
  830. break;
  831. case LIQUID_SOURCE:
  832. // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
  833. if (liquid_kind == CONTENT_AIR)
  834. liquid_kind = cfnb.liquid_alternative_flowing_id;
  835. if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
  836. neutrals[num_neutrals++] = nb;
  837. } else {
  838. // Do not count bottom source, it will screw things up
  839. if(nt != NEIGHBOR_LOWER)
  840. sources[num_sources++] = nb;
  841. }
  842. break;
  843. case LIQUID_FLOWING:
  844. if (nb.t != NEIGHBOR_SAME_LEVEL ||
  845. (nb.n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK) {
  846. // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
  847. // but exclude falling liquids on the same level, they cannot flow here anyway
  848. // used to determine if the neighbor can even flow into this node
  849. s8 max_level_from_neighbor = get_max_liquid_level(nb, -1);
  850. u8 range = m_nodedef->get(cfnb.liquid_alternative_flowing_id).liquid_range;
  851. if (liquid_kind == CONTENT_AIR &&
  852. max_level_from_neighbor >= (LIQUID_LEVEL_MAX + 1 - range))
  853. liquid_kind = cfnb.liquid_alternative_flowing_id;
  854. }
  855. if (cfnb.liquid_alternative_flowing_id != liquid_kind) {
  856. neutrals[num_neutrals++] = nb;
  857. } else {
  858. flows[num_flows++] = nb;
  859. if (nb.t == NEIGHBOR_LOWER)
  860. flowing_down = true;
  861. }
  862. break;
  863. case LiquidType_END:
  864. break;
  865. }
  866. }
  867. /*
  868. decide on the type (and possibly level) of the current node
  869. */
  870. content_t new_node_content;
  871. s8 new_node_level = -1;
  872. s8 max_node_level = -1;
  873. u8 range = m_nodedef->get(liquid_kind).liquid_range;
  874. if (range > LIQUID_LEVEL_MAX + 1)
  875. range = LIQUID_LEVEL_MAX + 1;
  876. if ((num_sources >= 2 && m_nodedef->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
  877. // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
  878. // or the flowing alternative of the first of the surrounding sources (if it's air), so
  879. // it's perfectly safe to use liquid_kind here to determine the new node content.
  880. new_node_content = m_nodedef->get(liquid_kind).liquid_alternative_source_id;
  881. } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
  882. // liquid_kind is set properly, see above
  883. max_node_level = new_node_level = LIQUID_LEVEL_MAX;
  884. if (new_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
  885. new_node_content = liquid_kind;
  886. else
  887. new_node_content = floodable_node;
  888. } else if (ignored_sources && liquid_level >= 0) {
  889. // Maybe there are neighboring sources that aren't loaded yet
  890. // so prevent flowing away.
  891. new_node_level = liquid_level;
  892. new_node_content = liquid_kind;
  893. } else {
  894. // no surrounding sources, so get the maximum level that can flow into this node
  895. for (u16 i = 0; i < num_flows; i++) {
  896. max_node_level = get_max_liquid_level(flows[i], max_node_level);
  897. }
  898. u8 viscosity = m_nodedef->get(liquid_kind).liquid_viscosity;
  899. if (viscosity > 1 && max_node_level != liquid_level) {
  900. // amount to gain, limited by viscosity
  901. // must be at least 1 in absolute value
  902. s8 level_inc = max_node_level - liquid_level;
  903. if (level_inc < -viscosity || level_inc > viscosity)
  904. new_node_level = liquid_level + level_inc/viscosity;
  905. else if (level_inc < 0)
  906. new_node_level = liquid_level - 1;
  907. else if (level_inc > 0)
  908. new_node_level = liquid_level + 1;
  909. if (new_node_level != max_node_level)
  910. must_reflow.push_back(p0);
  911. } else {
  912. new_node_level = max_node_level;
  913. }
  914. if (max_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
  915. new_node_content = liquid_kind;
  916. else
  917. new_node_content = floodable_node;
  918. }
  919. /*
  920. check if anything has changed. if not, just continue with the next node.
  921. */
  922. if (new_node_content == n0.getContent() &&
  923. (m_nodedef->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
  924. ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
  925. ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
  926. == flowing_down)))
  927. continue;
  928. /*
  929. check if there is a floating node above that needs to be updated.
  930. */
  931. if (floating_node_above && new_node_content == CONTENT_AIR)
  932. check_for_falling.push_back(p0);
  933. /*
  934. update the current node
  935. */
  936. MapNode n00 = n0;
  937. //bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
  938. if (m_nodedef->get(new_node_content).liquid_type == LIQUID_FLOWING) {
  939. // set level to last 3 bits, flowing down bit to 4th bit
  940. n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
  941. } else {
  942. // set the liquid level and flow bits to 0
  943. n0.param2 &= ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
  944. }
  945. // change the node.
  946. n0.setContent(new_node_content);
  947. // on_flood() the node
  948. if (floodable_node != CONTENT_AIR) {
  949. if (env->getScriptIface()->node_on_flood(p0, n00, n0))
  950. continue;
  951. }
  952. // Ignore light (because calling voxalgo::update_lighting_nodes)
  953. ContentLightingFlags f0 = m_nodedef->getLightingFlags(n0);
  954. n0.setLight(LIGHTBANK_DAY, 0, f0);
  955. n0.setLight(LIGHTBANK_NIGHT, 0, f0);
  956. // Find out whether there is a suspect for this action
  957. std::string suspect;
  958. if (m_gamedef->rollback())
  959. suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
  960. if (m_gamedef->rollback() && !suspect.empty()) {
  961. // Blame suspect
  962. RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
  963. // Get old node for rollback
  964. RollbackNode rollback_oldnode(this, p0, m_gamedef);
  965. // Set node
  966. setNode(p0, n0);
  967. // Report
  968. RollbackNode rollback_newnode(this, p0, m_gamedef);
  969. RollbackAction action;
  970. action.setSetNode(p0, rollback_oldnode, rollback_newnode);
  971. m_gamedef->rollback()->reportAction(action);
  972. } else {
  973. // Set node
  974. setNode(p0, n0);
  975. }
  976. v3s16 blockpos = getNodeBlockPos(p0);
  977. MapBlock *block = getBlockNoCreateNoEx(blockpos);
  978. if (block != NULL) {
  979. modified_blocks[blockpos] = block;
  980. changed_nodes.emplace_back(p0, n00);
  981. }
  982. /*
  983. enqueue neighbors for update if necessary
  984. */
  985. switch (m_nodedef->get(n0.getContent()).liquid_type) {
  986. case LIQUID_SOURCE:
  987. case LIQUID_FLOWING:
  988. // make sure source flows into all neighboring nodes
  989. for (u16 i = 0; i < num_flows; i++)
  990. if (flows[i].t != NEIGHBOR_UPPER)
  991. m_transforming_liquid.push_back(flows[i].p);
  992. for (u16 i = 0; i < num_airs; i++)
  993. if (airs[i].t != NEIGHBOR_UPPER)
  994. m_transforming_liquid.push_back(airs[i].p);
  995. break;
  996. case LIQUID_NONE:
  997. // this flow has turned to air; neighboring flows might need to do the same
  998. for (u16 i = 0; i < num_flows; i++)
  999. m_transforming_liquid.push_back(flows[i].p);
  1000. break;
  1001. case LiquidType_END:
  1002. break;
  1003. }
  1004. }
  1005. //infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
  1006. for (const auto &iter : must_reflow)
  1007. m_transforming_liquid.push_back(iter);
  1008. voxalgo::update_lighting_nodes(this, changed_nodes, modified_blocks);
  1009. for (const v3s16 &p : check_for_falling) {
  1010. env->getScriptIface()->check_for_falling(p);
  1011. }
  1012. env->getScriptIface()->on_liquid_transformed(changed_nodes);
  1013. /* ----------------------------------------------------------------------
  1014. * Manage the queue so that it does not grow indefinitely
  1015. */
  1016. u16 time_until_purge = g_settings->getU16("liquid_queue_purge_time");
  1017. if (time_until_purge == 0)
  1018. return; // Feature disabled
  1019. time_until_purge *= 1000; // seconds -> milliseconds
  1020. u64 curr_time = porting::getTimeMs();
  1021. u32 prev_unprocessed = m_unprocessed_count;
  1022. m_unprocessed_count = m_transforming_liquid.size();
  1023. // if unprocessed block count is decreasing or stable
  1024. if (m_unprocessed_count <= prev_unprocessed) {
  1025. m_queue_size_timer_started = false;
  1026. } else {
  1027. if (!m_queue_size_timer_started)
  1028. m_inc_trending_up_start_time = curr_time;
  1029. m_queue_size_timer_started = true;
  1030. }
  1031. // Account for curr_time overflowing
  1032. if (m_queue_size_timer_started && m_inc_trending_up_start_time > curr_time)
  1033. m_queue_size_timer_started = false;
  1034. /* If the queue has been growing for more than liquid_queue_purge_time seconds
  1035. * and the number of unprocessed blocks is still > liquid_loop_max then we
  1036. * cannot keep up; dump the oldest blocks from the queue so that the queue
  1037. * has liquid_loop_max items in it
  1038. */
  1039. if (m_queue_size_timer_started
  1040. && curr_time - m_inc_trending_up_start_time > time_until_purge
  1041. && m_unprocessed_count > liquid_loop_max) {
  1042. size_t dump_qty = m_unprocessed_count - liquid_loop_max;
  1043. infostream << "transformLiquids(): DUMPING " << dump_qty
  1044. << " blocks from the queue" << std::endl;
  1045. while (dump_qty--)
  1046. m_transforming_liquid.pop_front();
  1047. m_queue_size_timer_started = false; // optimistically assume we can keep up now
  1048. m_unprocessed_count = m_transforming_liquid.size();
  1049. }
  1050. }