mirror of
https://github.com/luanti-org/luanti.git
synced 2026-01-14 05:15:21 +01:00
When generating a new chunk, the chunk's liquid queue is processed immediately, instead of adding entries to the global liquid queue. Since the generated have not been sent to the client, this avoids sending duplicate blocks (that interfere with map sending) later when the global liquid queue is processed.
210 lines
5.6 KiB
C++
210 lines
5.6 KiB
C++
// Luanti
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
// Copyright (C) 2010-2024 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
#include "map.h"
|
|
#include "util/container.h" // UniqueQueue
|
|
#include "util/metricsbackend.h" // ptr typedefs
|
|
#include "map_settings_manager.h"
|
|
|
|
class Settings;
|
|
class MapDatabase;
|
|
class EmergeManager;
|
|
class ServerEnvironment;
|
|
struct BlockMakeData;
|
|
class MetricsBackend;
|
|
|
|
// TODO: this could wrap all calls to MapDatabase, including locking
|
|
struct MapDatabaseAccessor {
|
|
/// Lock, to be taken for any operation
|
|
std::mutex mutex;
|
|
/// Main database
|
|
MapDatabase *dbase = nullptr;
|
|
/// Fallback database for read operations
|
|
MapDatabase *dbase_ro = nullptr;
|
|
|
|
/// Load a block, taking dbase_ro into account.
|
|
/// @note call locked
|
|
void loadBlock(v3s16 blockpos, std::string &ret);
|
|
};
|
|
|
|
/*
|
|
ServerMap
|
|
|
|
This is the only map class that is able to generate map.
|
|
*/
|
|
|
|
class ServerMap : public Map
|
|
{
|
|
public:
|
|
/*
|
|
savedir: directory to which map data should be saved
|
|
*/
|
|
ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge, MetricsBackend *mb);
|
|
~ServerMap();
|
|
|
|
/*
|
|
Get a sector from somewhere.
|
|
- Check memory
|
|
- Check disk (doesn't load blocks)
|
|
- Create blank one
|
|
*/
|
|
MapSector *createSector(v2s16 p);
|
|
|
|
/*
|
|
Blocks are generated by using these and makeBlock().
|
|
*/
|
|
bool blockpos_over_mapgen_limit(v3s16 p);
|
|
/// @brief copy data from map to prepare for mapgen
|
|
/// @return true if mapgen should actually happen
|
|
bool initBlockMake(v3s16 blockpos, BlockMakeData *data);
|
|
/// @brief write data back to map after mapgen
|
|
/// @param now current game time
|
|
void finishBlockMake(BlockMakeData *data,
|
|
std::map<v3s16, MapBlock*> *changed_blocks, ServerEnvironment *env);
|
|
void cancelBlockMake(BlockMakeData *data);
|
|
|
|
/*
|
|
Get a block from somewhere.
|
|
- Memory
|
|
- Create blank
|
|
*/
|
|
MapBlock *createBlock(v3s16 p);
|
|
|
|
/*
|
|
Forcefully get a block from somewhere (blocking!).
|
|
- Memory
|
|
- Load from disk
|
|
- Create blank filled with CONTENT_IGNORE
|
|
|
|
*/
|
|
MapBlock *emergeBlock(v3s16 p, bool create_blank=true) override;
|
|
|
|
/*
|
|
Try to get a block.
|
|
If it does not exist in memory, add it to the emerge queue.
|
|
- Memory
|
|
- Emerge Queue (deferred disk or generate)
|
|
*/
|
|
MapBlock *getBlockOrEmerge(v3s16 p3d, bool generate);
|
|
|
|
bool isBlockInQueue(v3s16 pos);
|
|
|
|
void addNodeAndUpdate(v3s16 p, MapNode n,
|
|
std::map<v3s16, MapBlock*> &modified_blocks,
|
|
bool remove_metadata) override;
|
|
|
|
/*
|
|
Database functions
|
|
*/
|
|
static std::vector<std::string> getDatabaseBackends();
|
|
static MapDatabase *createDatabase(const std::string &name, const std::string &savedir, Settings &conf);
|
|
|
|
// Call these before and after saving of blocks
|
|
void beginSave() override;
|
|
void endSave() override;
|
|
|
|
void save(ModifiedState save_level) override;
|
|
void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
|
void listAllLoadedBlocks(std::vector<v3s16> &dst);
|
|
|
|
MapgenParams *getMapgenParams();
|
|
|
|
bool saveBlock(MapBlock *block) override;
|
|
static bool saveBlock(MapBlock *block, MapDatabase *db, int compression_level = -1);
|
|
|
|
// Load block in a synchronous fashion
|
|
MapBlock *loadBlock(v3s16 p);
|
|
/// Load a block that was already read from disk. Used by EmergeManager.
|
|
/// @return non-null block (but can be blank)
|
|
MapBlock *loadBlock(const std::string &blob, v3s16 p, bool save_after_load=false);
|
|
|
|
// Helper for deserializing blocks from disk
|
|
// @throws SerializationError
|
|
static void deSerializeBlock(MapBlock *block, std::istream &is);
|
|
|
|
// Blocks are removed from the map but not deleted from memory until
|
|
// deleteDetachedBlocks() is called, since pointers to them may still exist
|
|
// when deleteBlock() is called.
|
|
bool deleteBlock(v3s16 blockpos) override;
|
|
|
|
void deleteDetachedBlocks();
|
|
|
|
void step();
|
|
|
|
void updateVManip(v3s16 pos);
|
|
|
|
// For debug printing
|
|
void PrintInfo(std::ostream &out) override;
|
|
|
|
bool isSavingEnabled(){ return m_map_saving_enabled; }
|
|
|
|
u64 getSeed();
|
|
|
|
/*!
|
|
* Fixes lighting in one map block.
|
|
* May modify other blocks as well, as light can spread
|
|
* out of the specified block.
|
|
* Returns false if the block is not generated (so nothing
|
|
* changed), true otherwise.
|
|
*/
|
|
bool repairBlockLight(v3s16 blockpos,
|
|
std::map<v3s16, MapBlock *> *modified_blocks);
|
|
|
|
void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks,
|
|
ServerEnvironment *env);
|
|
void transformLiquidsLocal(std::map<v3s16, MapBlock*> &modified_blocks, UniqueQueue<v3s16> &liquid_queue,
|
|
ServerEnvironment *env, u32 liquid_loop_max);
|
|
void transforming_liquid_add(v3s16 p);
|
|
|
|
MapSettingsManager settings_mgr;
|
|
|
|
protected:
|
|
|
|
void reportMetrics(u64 save_time_us, u32 saved_blocks, u32 all_blocks) override;
|
|
|
|
private:
|
|
friend class ModApiMapgen; // for m_transforming_liquid
|
|
|
|
// extra border area during mapgen (in blocks)
|
|
constexpr static v3s16 EMERGE_EXTRA_BORDER{1, 1, 1};
|
|
|
|
// Emerge manager
|
|
EmergeManager *m_emerge;
|
|
|
|
std::string m_savedir;
|
|
bool m_map_saving_enabled;
|
|
|
|
int m_map_compression_level;
|
|
|
|
std::set<v3s16> m_chunks_in_progress;
|
|
|
|
// used by deleteBlock() and deleteDetachedBlocks()
|
|
std::vector<std::unique_ptr<MapBlock>> m_detached_blocks;
|
|
|
|
// Queued transforming water nodes
|
|
UniqueQueue<v3s16> m_transforming_liquid;
|
|
f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
|
|
u32 m_unprocessed_count = 0;
|
|
u64 m_inc_trending_up_start_time = 0; // milliseconds
|
|
bool m_queue_size_timer_started = false;
|
|
|
|
/*
|
|
Metadata is re-written on disk only if this is true.
|
|
This is reset to false when written on disk.
|
|
*/
|
|
bool m_map_metadata_changed = true;
|
|
|
|
MapDatabaseAccessor m_db;
|
|
|
|
// Map metrics
|
|
MetricGaugePtr m_loaded_blocks_gauge;
|
|
MetricCounterPtr m_save_time_counter;
|
|
MetricCounterPtr m_save_count_counter;
|
|
};
|