mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Remove MapSector, take 2
This commit is contained in:
parent
0ea89d4112
commit
1771b8c9a1
14 changed files with 236 additions and 649 deletions
|
@ -463,7 +463,6 @@ set(common_SRCS
|
|||
map.cpp
|
||||
mapblock.cpp
|
||||
mapnode.cpp
|
||||
mapsector.cpp
|
||||
nodedef.cpp
|
||||
pathfinder.cpp
|
||||
player.cpp
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "filesys.h"
|
||||
#include "mapblock_mesh.h"
|
||||
#include "mapblock.h"
|
||||
#include "mapsector.h"
|
||||
#include "minimap.h"
|
||||
#include "modchannels.h"
|
||||
#include "content/mods.h"
|
||||
|
@ -589,15 +588,14 @@ void Client::step(float dtime)
|
|||
bool do_mapper_update = true;
|
||||
|
||||
ClientMap &map = m_env.getClientMap();
|
||||
MapSector *sector = map.emergeSector(v2s16(r.p.X, r.p.Z));
|
||||
|
||||
MapBlock *block = sector->getBlockNoCreateNoEx(r.p.Y);
|
||||
MapBlock *block = map.getBlockNoCreateNoEx(r.p);
|
||||
|
||||
// The block in question is not visible (perhaps it is culled at the server),
|
||||
// create a blank block just to hold the chunk's mesh.
|
||||
// If the block becomes visible later it will replace the blank block.
|
||||
if (!block && r.mesh)
|
||||
block = sector->createBlankBlock(r.p.Y);
|
||||
block = map.createBlankBlock(r.p);
|
||||
|
||||
if (block) {
|
||||
// Delete the old mesh
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <IMaterialRenderer.h>
|
||||
#include <IVideoDriver.h>
|
||||
#include <matrix4.h>
|
||||
#include "mapsector.h"
|
||||
#include "mapblock.h"
|
||||
#include "nodedef.h"
|
||||
#include "profiler.h"
|
||||
|
@ -239,20 +238,6 @@ void ClientMap::updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SCo
|
|||
}
|
||||
}
|
||||
|
||||
MapSector * ClientMap::emergeSector(v2s16 p2d)
|
||||
{
|
||||
// Check that it doesn't exist already
|
||||
MapSector *sector = getSectorNoGenerate(p2d);
|
||||
|
||||
// Create it if it does not exist yet
|
||||
if (!sector) {
|
||||
sector = new MapSector(this, p2d, m_gamedef);
|
||||
m_sectors[p2d] = sector;
|
||||
}
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
void ClientMap::OnRegisterSceneNode()
|
||||
{
|
||||
if(IsVisible)
|
||||
|
@ -409,91 +394,75 @@ void ClientMap::updateDrawList()
|
|||
frustum and display them.
|
||||
*/
|
||||
if (m_control.range_all || m_loops_occlusion_culler) {
|
||||
// Number of blocks currently loaded by the client
|
||||
u32 blocks_loaded = 0;
|
||||
// Number of blocks with mesh in rendering range
|
||||
u32 blocks_in_range_with_mesh = 0;
|
||||
|
||||
MapBlockVect sectorblocks;
|
||||
// Loop through all blocks
|
||||
for (const auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
|
||||
for (auto §or_it : m_sectors) {
|
||||
const MapSector *sector = sector_it.second;
|
||||
v2s16 sp = sector->getPos();
|
||||
// Calculate the coordinates for range and frustum culling
|
||||
v3f mesh_sphere_center;
|
||||
f32 mesh_sphere_radius;
|
||||
|
||||
blocks_loaded += sector->size();
|
||||
if (!m_control.range_all) {
|
||||
if (sp.X < p_blocks_min.X || sp.X > p_blocks_max.X ||
|
||||
sp.Y < p_blocks_min.Z || sp.Y > p_blocks_max.Z)
|
||||
continue;
|
||||
v3s16 block_pos_nodes = block->getPosRelative();
|
||||
|
||||
if (mesh) {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ mesh->getBoundingSphereCenter();
|
||||
mesh_sphere_radius = mesh->getBoundingRadius();
|
||||
} else {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
|
||||
mesh_sphere_radius = 0.0f;
|
||||
}
|
||||
|
||||
// Loop through blocks in sector
|
||||
for (const auto &entry : sector->getBlocks()) {
|
||||
MapBlock *block = entry.second.get();
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
// First, perform a simple distance check.
|
||||
if (!m_control.range_all &&
|
||||
mesh_sphere_center.getDistanceFrom(m_camera_position) >
|
||||
m_control.wanted_range * BS + mesh_sphere_radius)
|
||||
continue; // Out of range, skip.
|
||||
|
||||
// Calculate the coordinates for range and frustum culling
|
||||
v3f mesh_sphere_center;
|
||||
f32 mesh_sphere_radius;
|
||||
// Keep the block alive as long as it is in range.
|
||||
block->resetUsageTimer();
|
||||
blocks_in_range_with_mesh++;
|
||||
|
||||
v3s16 block_pos_nodes = block->getPosRelative();
|
||||
// Frustum culling
|
||||
// Only do coarse culling here, to account for fast camera movement.
|
||||
// This is needed because this function is not called every frame.
|
||||
float frustum_cull_extra_radius = 300.0f;
|
||||
if (is_frustum_culled(mesh_sphere_center,
|
||||
mesh_sphere_radius + frustum_cull_extra_radius)) {
|
||||
blocks_frustum_culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesh) {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ mesh->getBoundingSphereCenter();
|
||||
mesh_sphere_radius = mesh->getBoundingRadius();
|
||||
} else {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
|
||||
mesh_sphere_radius = 0.0f;
|
||||
}
|
||||
// Raytraced occlusion culling - send rays from the camera to the block's corners
|
||||
if (!m_control.range_all && occlusion_culling_enabled && m_enable_raytraced_culling &&
|
||||
mesh &&
|
||||
isMeshOccluded(block, mesh_grid.cell_size, cam_pos_nodes)) {
|
||||
blocks_occlusion_culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// First, perform a simple distance check.
|
||||
if (!m_control.range_all &&
|
||||
mesh_sphere_center.getDistanceFrom(m_camera_position) >
|
||||
m_control.wanted_range * BS + mesh_sphere_radius)
|
||||
continue; // Out of range, skip.
|
||||
|
||||
// Keep the block alive as long as it is in range.
|
||||
block->resetUsageTimer();
|
||||
blocks_in_range_with_mesh++;
|
||||
|
||||
// Frustum culling
|
||||
// Only do coarse culling here, to account for fast camera movement.
|
||||
// This is needed because this function is not called every frame.
|
||||
float frustum_cull_extra_radius = 300.0f;
|
||||
if (is_frustum_culled(mesh_sphere_center,
|
||||
mesh_sphere_radius + frustum_cull_extra_radius)) {
|
||||
blocks_frustum_culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Raytraced occlusion culling - send rays from the camera to the block's corners
|
||||
if (!m_control.range_all && occlusion_culling_enabled && m_enable_raytraced_culling &&
|
||||
mesh &&
|
||||
isMeshOccluded(block, mesh_grid.cell_size, cam_pos_nodes)) {
|
||||
blocks_occlusion_culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mesh_grid.cell_size > 1) {
|
||||
// Block meshes are stored in the corner block of a chunk
|
||||
// (where all coordinate are divisible by the chunk size)
|
||||
// Add them to the de-dup set.
|
||||
shortlist.emplace(mesh_grid.getMeshPos(block->getPos()));
|
||||
// All other blocks we can grab and add to the keeplist right away.
|
||||
m_keeplist.push_back(block);
|
||||
block->refGrab();
|
||||
} else if (mesh) {
|
||||
// without mesh chunking we can add the block to the drawlist
|
||||
block->refGrab();
|
||||
m_drawlist.emplace(block->getPos(), block);
|
||||
}
|
||||
if (mesh_grid.cell_size > 1) {
|
||||
// Block meshes are stored in the corner block of a chunk
|
||||
// (where all coordinate are divisible by the chunk size)
|
||||
// Add them to the de-dup set.
|
||||
shortlist.emplace(mesh_grid.getMeshPos(block->getPos()));
|
||||
// All other blocks we can grab and add to the keeplist right away.
|
||||
m_keeplist.push_back(block);
|
||||
block->refGrab();
|
||||
} else if (mesh) {
|
||||
// without mesh chunking we can add the block to the drawlist
|
||||
block->refGrab();
|
||||
m_drawlist.emplace(block->getPos(), block);
|
||||
}
|
||||
}
|
||||
|
||||
g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh);
|
||||
g_profiler->avg("MapBlocks loaded [#]", blocks_loaded);
|
||||
g_profiler->avg("MapBlocks loaded [#]", m_blocks.size());
|
||||
} else {
|
||||
// Blocks visited by the algorithm
|
||||
u32 blocks_visited = 0;
|
||||
|
@ -529,10 +498,7 @@ void ClientMap::updateDrawList()
|
|||
|
||||
blocks_visited++;
|
||||
|
||||
// Get the sector, block and mesh
|
||||
MapSector *sector = this->getSectorNoGenerate(v2s16(block_coord.X, block_coord.Z));
|
||||
|
||||
MapBlock *block = sector ? sector->getBlockNoCreateNoEx(block_coord.Y) : nullptr;
|
||||
MapBlock *block = getBlockNoCreateNoEx(block_coord);
|
||||
|
||||
MapBlockMesh *mesh = block ? block->mesh : nullptr;
|
||||
|
||||
|
@ -729,60 +695,42 @@ void ClientMap::touchMapBlocks()
|
|||
v3s16 p_blocks_max;
|
||||
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
|
||||
|
||||
// Number of blocks currently loaded by the client
|
||||
u32 blocks_loaded = 0;
|
||||
// Number of blocks with mesh in rendering range
|
||||
u32 blocks_in_range_with_mesh = 0;
|
||||
|
||||
for (const auto §or_it : m_sectors) {
|
||||
const MapSector *sector = sector_it.second;
|
||||
v2s16 sp = sector->getPos();
|
||||
for (const auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
|
||||
blocks_loaded += sector->size();
|
||||
if (!m_control.range_all) {
|
||||
if (sp.X < p_blocks_min.X || sp.X > p_blocks_max.X ||
|
||||
sp.Y < p_blocks_min.Z || sp.Y > p_blocks_max.Z)
|
||||
continue;
|
||||
// Calculate the coordinates for range and frustum culling
|
||||
v3f mesh_sphere_center;
|
||||
f32 mesh_sphere_radius;
|
||||
|
||||
v3s16 block_pos_nodes = block->getPosRelative();
|
||||
|
||||
if (mesh) {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ mesh->getBoundingSphereCenter();
|
||||
mesh_sphere_radius = mesh->getBoundingRadius();
|
||||
} else {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
|
||||
mesh_sphere_radius = 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
Loop through blocks in sector
|
||||
*/
|
||||
// First, perform a simple distance check.
|
||||
if (!m_control.range_all &&
|
||||
mesh_sphere_center.getDistanceFrom(m_camera_position) >
|
||||
m_control.wanted_range * BS + mesh_sphere_radius)
|
||||
continue; // Out of range, skip.
|
||||
|
||||
for (const auto &entry : sector->getBlocks()) {
|
||||
MapBlock *block = entry.second.get();
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
|
||||
// Calculate the coordinates for range and frustum culling
|
||||
v3f mesh_sphere_center;
|
||||
f32 mesh_sphere_radius;
|
||||
|
||||
v3s16 block_pos_nodes = block->getPosRelative();
|
||||
|
||||
if (mesh) {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ mesh->getBoundingSphereCenter();
|
||||
mesh_sphere_radius = mesh->getBoundingRadius();
|
||||
} else {
|
||||
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
|
||||
+ v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
|
||||
mesh_sphere_radius = 0.0f;
|
||||
}
|
||||
|
||||
// First, perform a simple distance check.
|
||||
if (!m_control.range_all &&
|
||||
mesh_sphere_center.getDistanceFrom(m_camera_position) >
|
||||
m_control.wanted_range * BS + mesh_sphere_radius)
|
||||
continue; // Out of range, skip.
|
||||
|
||||
// Keep the block alive as long as it is in range.
|
||||
block->resetUsageTimer();
|
||||
blocks_in_range_with_mesh++;
|
||||
}
|
||||
// Keep the block alive as long as it is in range.
|
||||
block->resetUsageTimer();
|
||||
blocks_in_range_with_mesh++;
|
||||
}
|
||||
|
||||
g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh);
|
||||
g_profiler->avg("MapBlocks loaded [#]", blocks_loaded);
|
||||
g_profiler->avg("MapBlocks loaded [#]", m_blocks.size());
|
||||
}
|
||||
|
||||
void MeshBufListMaps::addFromBlock(v3s16 block_pos, MapBlockMesh *block_mesh,
|
||||
|
@ -1532,48 +1480,36 @@ void ClientMap::updateDrawListShadow(v3f shadow_light_pos, v3f shadow_light_dir,
|
|||
}
|
||||
m_drawlist_shadow.clear();
|
||||
|
||||
// Number of blocks currently loaded by the client
|
||||
u32 blocks_loaded = 0;
|
||||
// Number of blocks with mesh in rendering range
|
||||
u32 blocks_in_range_with_mesh = 0;
|
||||
|
||||
for (auto §or_it : m_sectors) {
|
||||
const MapSector *sector = sector_it.second;
|
||||
if (!sector)
|
||||
for (const auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
if (!mesh) {
|
||||
// Ignore if mesh doesn't exist
|
||||
continue;
|
||||
blocks_loaded += sector->size();
|
||||
}
|
||||
|
||||
/*
|
||||
Loop through blocks in sector
|
||||
*/
|
||||
for (const auto &entry : sector->getBlocks()) {
|
||||
MapBlock *block = entry.second.get();
|
||||
MapBlockMesh *mesh = block->mesh;
|
||||
if (!mesh) {
|
||||
// Ignore if mesh doesn't exist
|
||||
continue;
|
||||
}
|
||||
v3f block_pos = intToFloat(block->getPosRelative(), BS) + mesh->getBoundingSphereCenter();
|
||||
v3f projection = shadow_light_pos + shadow_light_dir * shadow_light_dir.dotProduct(block_pos - shadow_light_pos);
|
||||
if (projection.getDistanceFrom(block_pos) > (radius + mesh->getBoundingRadius()))
|
||||
continue;
|
||||
|
||||
v3f block_pos = intToFloat(block->getPosRelative(), BS) + mesh->getBoundingSphereCenter();
|
||||
v3f projection = shadow_light_pos + shadow_light_dir * shadow_light_dir.dotProduct(block_pos - shadow_light_pos);
|
||||
if (projection.getDistanceFrom(block_pos) > (radius + mesh->getBoundingRadius()))
|
||||
continue;
|
||||
blocks_in_range_with_mesh++;
|
||||
|
||||
blocks_in_range_with_mesh++;
|
||||
// This block is in range. Reset usage timer.
|
||||
block->resetUsageTimer();
|
||||
|
||||
// This block is in range. Reset usage timer.
|
||||
block->resetUsageTimer();
|
||||
|
||||
// Add to set
|
||||
if (m_drawlist_shadow.emplace(block->getPos(), block).second) {
|
||||
block->refGrab();
|
||||
}
|
||||
// Add to set
|
||||
if (m_drawlist_shadow.emplace(block->getPos(), block).second) {
|
||||
block->refGrab();
|
||||
}
|
||||
}
|
||||
|
||||
g_profiler->avg("SHADOW MapBlock meshes in range [#]", blocks_in_range_with_mesh);
|
||||
g_profiler->avg("SHADOW MapBlocks drawn [#]", m_drawlist_shadow.size());
|
||||
g_profiler->avg("SHADOW MapBlocks loaded [#]", blocks_loaded);
|
||||
g_profiler->avg("SHADOW MapBlocks loaded [#]", m_blocks.size());
|
||||
}
|
||||
|
||||
void ClientMap::reportMetrics(u64 save_time_us, u32 saved_blocks, u32 all_blocks)
|
||||
|
|
|
@ -69,11 +69,6 @@ public:
|
|||
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SColor light_color);
|
||||
|
||||
/*
|
||||
Forcefully get a sector from somewhere
|
||||
*/
|
||||
MapSector * emergeSector(v2s16 p) override;
|
||||
|
||||
/*
|
||||
ISceneNode methods
|
||||
*/
|
||||
|
|
|
@ -239,7 +239,6 @@ void MapDatabaseSQLite3::createDatabase()
|
|||
// Declaring a primary key automatically creates an index and the
|
||||
// order largely dictates which range operations can be sped up.
|
||||
// see also: <https://www.sqlite.org/optoverview.html#skipscan>
|
||||
// Putting XZ before Y matches our MapSector abstraction.
|
||||
"PRIMARY KEY (`x`, `z`, `y`)"
|
||||
");\n"
|
||||
;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "map.h"
|
||||
#include "mapsector.h"
|
||||
|
||||
class DummyMap : public Map
|
||||
{
|
||||
|
@ -13,12 +12,9 @@ public:
|
|||
DummyMap(IGameDef *gamedef, v3s16 bpmin, v3s16 bpmax): Map(gamedef)
|
||||
{
|
||||
for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
|
||||
for (s16 x = bpmin.X; x <= bpmax.X; x++) {
|
||||
v2s16 p2d(x, z);
|
||||
MapSector *sector = new MapSector(this, p2d, gamedef);
|
||||
m_sectors[p2d] = sector;
|
||||
for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
|
||||
sector->createBlankBlock(y);
|
||||
for (s16 x = bpmin.X; x <= bpmax.X; x++)
|
||||
for (s16 y = bpmin.Y; y <= bpmax.Y; y++) {
|
||||
createBlankBlock(v3s16(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
184
src/map.cpp
184
src/map.cpp
|
@ -3,7 +3,6 @@
|
|||
// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
#include "map.h"
|
||||
#include "mapsector.h"
|
||||
#include "mapblock.h"
|
||||
#include "voxel.h"
|
||||
#include "voxelalgorithms.h"
|
||||
|
@ -31,10 +30,10 @@ Map::Map(IGameDef *gamedef):
|
|||
Map::~Map()
|
||||
{
|
||||
/*
|
||||
Free all MapSectors
|
||||
Free all MapBlocks
|
||||
*/
|
||||
for (auto §or : m_sectors) {
|
||||
delete sector.second;
|
||||
for (auto &entry : m_blocks) {
|
||||
delete entry.second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,40 +54,61 @@ void Map::dispatchEvent(const MapEditEvent &event)
|
|||
}
|
||||
}
|
||||
|
||||
MapSector * Map::getSectorNoGenerateNoLock(v2s16 p)
|
||||
MapBlock* Map::createBlankBlockNoInsert(v3s16 p)
|
||||
{
|
||||
if(m_sector_cache != NULL && p == m_sector_cache_p){
|
||||
MapSector * sector = m_sector_cache;
|
||||
return sector;
|
||||
}
|
||||
if (blockpos_over_max_limit(v3s16(p)))
|
||||
throw InvalidPositionException("createBlankBlockNoInsert(): pos over max mapgen limit");
|
||||
|
||||
auto n = m_sectors.find(p);
|
||||
|
||||
if (n == m_sectors.end())
|
||||
return NULL;
|
||||
|
||||
MapSector *sector = n->second;
|
||||
|
||||
// Cache the last result
|
||||
m_sector_cache_p = p;
|
||||
m_sector_cache = sector;
|
||||
|
||||
return sector;
|
||||
return new MapBlock(p, m_gamedef);
|
||||
}
|
||||
|
||||
MapSector *Map::getSectorNoGenerate(v2s16 p)
|
||||
MapBlock *Map::createBlankBlock(v3s16 p)
|
||||
{
|
||||
return getSectorNoGenerateNoLock(p);
|
||||
MapBlock *block = createBlankBlockNoInsert(p);
|
||||
|
||||
m_blocks[p] = block;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void Map::deleteBlockImmediate(MapBlock *block)
|
||||
{
|
||||
detachBlock(block);
|
||||
// returned smart-ptr is dropped
|
||||
}
|
||||
|
||||
std::unique_ptr<MapBlock> Map::detachBlock(MapBlock *block)
|
||||
{
|
||||
// Remove from container
|
||||
auto it = m_blocks.find(block->getPos());
|
||||
assert(it != m_blocks.end());
|
||||
std::unique_ptr<MapBlock> ret(it->second);
|
||||
assert(ret.get() == block);
|
||||
m_blocks.erase(it);
|
||||
|
||||
// Mark as removed
|
||||
block->makeOrphan();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Map::insertBlock(MapBlock *block)
|
||||
{
|
||||
v3s16 pos = block->getPos();
|
||||
|
||||
MapBlock *block2 = getBlockNoCreateNoEx(pos);
|
||||
if (block2) {
|
||||
throw AlreadyExistsException("Block already exists");
|
||||
}
|
||||
|
||||
// Insert into container
|
||||
m_blocks[pos] = block;
|
||||
}
|
||||
|
||||
MapBlock *Map::getBlockNoCreateNoEx(v3s16 p3d)
|
||||
{
|
||||
v2s16 p2d(p3d.X, p3d.Z);
|
||||
MapSector *sector = getSectorNoGenerate(p2d);
|
||||
if (!sector)
|
||||
return nullptr;
|
||||
MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y);
|
||||
return block;
|
||||
auto it = m_blocks.find(p3d);
|
||||
return it != m_blocks.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
MapBlock *Map::getBlockNoCreate(v3s16 p3d)
|
||||
|
@ -256,11 +276,9 @@ bool Map::removeNodeWithEvent(v3s16 p)
|
|||
}
|
||||
|
||||
struct TimeOrderedMapBlock {
|
||||
MapSector *sect;
|
||||
MapBlock *block;
|
||||
|
||||
TimeOrderedMapBlock(MapSector *sect, MapBlock *block) :
|
||||
sect(sect),
|
||||
TimeOrderedMapBlock(MapBlock *block) :
|
||||
block(block)
|
||||
{}
|
||||
|
||||
|
@ -281,7 +299,6 @@ void Map::timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
|||
// Profile modified reasons
|
||||
Profiler modprofiler;
|
||||
|
||||
std::vector<v2s16> sector_deletion_queue;
|
||||
u32 deleted_blocks_count = 0;
|
||||
u32 saved_blocks_count = 0;
|
||||
u32 block_count_all = 0;
|
||||
|
@ -292,62 +309,44 @@ void Map::timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
|||
|
||||
// If there is no practical limit, we spare creation of mapblock_queue
|
||||
if (max_loaded_blocks < 0) {
|
||||
MapBlockVect blocks;
|
||||
for (auto §or_it : m_sectors) {
|
||||
MapSector *sector = sector_it.second;
|
||||
for (auto it = m_blocks.begin(); it != m_blocks.end();) {
|
||||
MapBlock *block = it->second;
|
||||
block->incrementUsageTimer(dtime);
|
||||
|
||||
bool all_blocks_deleted = true;
|
||||
if (block->refGet() == 0
|
||||
&& block->getUsageTimer() > unload_timeout) {
|
||||
v3s16 p = block->getPos();
|
||||
|
||||
blocks.clear();
|
||||
sector->getBlocks(blocks);
|
||||
|
||||
for (MapBlock *block : blocks) {
|
||||
block->incrementUsageTimer(dtime);
|
||||
|
||||
if (block->refGet() == 0
|
||||
&& block->getUsageTimer() > unload_timeout) {
|
||||
v3s16 p = block->getPos();
|
||||
|
||||
// Save if modified
|
||||
if (block->getModified() != MOD_STATE_CLEAN
|
||||
&& save_before_unloading) {
|
||||
modprofiler.add(block->getModifiedReasonString(), 1);
|
||||
if (!saveBlock(block))
|
||||
continue;
|
||||
saved_blocks_count++;
|
||||
// Save if modified
|
||||
if (block->getModified() != MOD_STATE_CLEAN
|
||||
&& save_before_unloading) {
|
||||
modprofiler.add(block->getModifiedReasonString(), 1);
|
||||
if (!saveBlock(block)) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete from memory
|
||||
sector->deleteBlock(block);
|
||||
|
||||
if (unloaded_blocks)
|
||||
unloaded_blocks->push_back(p);
|
||||
|
||||
deleted_blocks_count++;
|
||||
} else {
|
||||
all_blocks_deleted = false;
|
||||
block_count_all++;
|
||||
saved_blocks_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete sector if we emptied it
|
||||
if (all_blocks_deleted) {
|
||||
sector_deletion_queue.push_back(sector_it.first);
|
||||
// Delete directly from container
|
||||
it = m_blocks.erase(it);
|
||||
delete block;
|
||||
|
||||
if (unloaded_blocks)
|
||||
unloaded_blocks->push_back(p);
|
||||
|
||||
deleted_blocks_count++;
|
||||
} else {
|
||||
block_count_all++;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::priority_queue<TimeOrderedMapBlock> mapblock_queue;
|
||||
MapBlockVect blocks;
|
||||
for (auto §or_it : m_sectors) {
|
||||
MapSector *sector = sector_it.second;
|
||||
|
||||
blocks.clear();
|
||||
sector->getBlocks(blocks);
|
||||
|
||||
for (MapBlock *block : blocks) {
|
||||
block->incrementUsageTimer(dtime);
|
||||
mapblock_queue.push(TimeOrderedMapBlock(sector, block));
|
||||
}
|
||||
for (auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
block->incrementUsageTimer(dtime);
|
||||
mapblock_queue.push(TimeOrderedMapBlock(block));
|
||||
}
|
||||
block_count_all = mapblock_queue.size();
|
||||
|
||||
|
@ -375,7 +374,7 @@ void Map::timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
|||
}
|
||||
|
||||
// Delete from memory
|
||||
b.sect->deleteBlock(block);
|
||||
deleteBlockImmediate(block);
|
||||
|
||||
if (unloaded_blocks)
|
||||
unloaded_blocks->push_back(p);
|
||||
|
@ -383,13 +382,6 @@ void Map::timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
|||
deleted_blocks_count++;
|
||||
block_count_all--;
|
||||
}
|
||||
|
||||
// Delete empty sectors
|
||||
for (auto §or_it : m_sectors) {
|
||||
if (sector_it.second->empty()) {
|
||||
sector_deletion_queue.push_back(sector_it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endSave();
|
||||
|
@ -397,9 +389,6 @@ void Map::timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
|||
|
||||
reportMetrics(end_time - start_time, saved_blocks_count, block_count_all);
|
||||
|
||||
// Finally delete the empty sectors
|
||||
deleteSectors(sector_deletion_queue);
|
||||
|
||||
if(deleted_blocks_count != 0)
|
||||
{
|
||||
PrintInfo(infostream); // ServerMap/ClientMap:
|
||||
|
@ -422,19 +411,6 @@ void Map::unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks)
|
|||
timerUpdate(0, -1, 0, unloaded_blocks);
|
||||
}
|
||||
|
||||
void Map::deleteSectors(const std::vector<v2s16> §orList)
|
||||
{
|
||||
for (v2s16 j : sectorList) {
|
||||
MapSector *sector = m_sectors[j];
|
||||
// If sector is in sector cache, remove it from there
|
||||
if (m_sector_cache == sector)
|
||||
m_sector_cache = nullptr;
|
||||
// Remove from map and delete
|
||||
m_sectors.erase(j);
|
||||
delete sector;
|
||||
}
|
||||
}
|
||||
|
||||
void Map::PrintInfo(std::ostream &out)
|
||||
{
|
||||
out<<"Map: ";
|
||||
|
|
36
src/map.h
36
src/map.h
|
@ -7,6 +7,7 @@
|
|||
#include <iostream>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "mapblock.h"
|
||||
|
@ -18,7 +19,6 @@
|
|||
#include "nodetimer.h"
|
||||
#include "debug.h"
|
||||
|
||||
class MapSector;
|
||||
class NodeMetadata;
|
||||
class IGameDef;
|
||||
class IRollbackManager;
|
||||
|
@ -113,22 +113,20 @@ public:
|
|||
// event shall be deleted by caller after the call.
|
||||
void dispatchEvent(const MapEditEvent &event);
|
||||
|
||||
// On failure returns NULL
|
||||
MapSector * getSectorNoGenerateNoLock(v2s16 p2d);
|
||||
// Same as the above (there exists no lock anymore)
|
||||
MapSector * getSectorNoGenerate(v2s16 p2d);
|
||||
|
||||
/*
|
||||
This is overloaded by ClientMap and ServerMap to allow
|
||||
their differing fetch methods.
|
||||
*/
|
||||
virtual MapSector * emergeSector(v2s16 p){ return NULL; }
|
||||
|
||||
// Returns InvalidPositionException if not found
|
||||
MapBlock * getBlockNoCreate(v3s16 p);
|
||||
// Returns NULL if not found
|
||||
MapBlock * getBlockNoCreateNoEx(v3s16 p);
|
||||
|
||||
MapBlock* createBlankBlockNoInsert(v3s16 p);
|
||||
MapBlock *createBlankBlock(v3s16 p);
|
||||
void insertBlock(MapBlock *block);
|
||||
|
||||
void deleteBlockImmediate(MapBlock *block);
|
||||
// Remove a block from the map without deleting it
|
||||
// Returns an owning ptr to block.
|
||||
std::unique_ptr<MapBlock> detachBlock(MapBlock *block);
|
||||
|
||||
/* Server overrides */
|
||||
virtual MapBlock * emergeBlock(v3s16 p, bool create_blank=true)
|
||||
{ return getBlockNoCreateNoEx(p); }
|
||||
|
@ -179,7 +177,7 @@ public:
|
|||
virtual bool deleteBlock(v3s16 blockpos) { return false; }
|
||||
|
||||
/*
|
||||
Updates usage timers and unloads unused blocks and sectors.
|
||||
Updates usage timers and unloads unused blocks.
|
||||
Saves modified blocks before unloading if possible.
|
||||
*/
|
||||
void timerUpdate(float dtime, float unload_timeout, s32 max_loaded_blocks,
|
||||
|
@ -191,11 +189,6 @@ public:
|
|||
*/
|
||||
void unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks=NULL);
|
||||
|
||||
// Deletes sectors and their blocks from memory
|
||||
// Takes cache into account
|
||||
// If deleted sector is in sector cache, clears cache
|
||||
void deleteSectors(const std::vector<v2s16> &list);
|
||||
|
||||
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||
virtual void PrintInfo(std::ostream &out);
|
||||
|
||||
|
@ -248,7 +241,6 @@ public:
|
|||
for (s16 bz = bpmin.Z; bz <= bpmax.Z; bz++)
|
||||
for (s16 bx = bpmin.X; bx <= bpmax.X; bx++)
|
||||
for (s16 by = bpmin.Y; by <= bpmax.Y; by++) {
|
||||
// y is iterated innermost to make use of the sector cache.
|
||||
v3s16 bp(bx, by, bz);
|
||||
MapBlock *block = getBlockNoCreateNoEx(bp);
|
||||
v3s16 basep = bp * MAP_BLOCKSIZE;
|
||||
|
@ -282,11 +274,7 @@ protected:
|
|||
|
||||
std::set<MapEventReceiver*> m_event_receivers;
|
||||
|
||||
std::unordered_map<v2s16, MapSector*> m_sectors;
|
||||
|
||||
// Be sure to set this to NULL when the cached sector is deleted
|
||||
MapSector *m_sector_cache = nullptr;
|
||||
v2s16 m_sector_cache_p;
|
||||
std::unordered_map<v3s16, MapBlock*> m_blocks;
|
||||
|
||||
// This stores the properties of the nodes on the map.
|
||||
const NodeDefManager *m_nodedef;
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
// Luanti
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
#include "mapsector.h"
|
||||
#include "exceptions.h"
|
||||
#include "mapblock.h"
|
||||
#include "serialization.h"
|
||||
|
||||
MapSector::MapSector(Map *parent, v2s16 pos, IGameDef *gamedef):
|
||||
m_parent(parent),
|
||||
m_pos(pos),
|
||||
m_gamedef(gamedef)
|
||||
{
|
||||
}
|
||||
|
||||
MapSector::~MapSector()
|
||||
{
|
||||
deleteBlocks();
|
||||
}
|
||||
|
||||
void MapSector::deleteBlocks()
|
||||
{
|
||||
// Clear cache
|
||||
m_block_cache = nullptr;
|
||||
|
||||
// Delete all blocks
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
MapBlock *MapSector::getBlockBuffered(s16 y)
|
||||
{
|
||||
MapBlock *block;
|
||||
|
||||
if (m_block_cache && y == m_block_cache_y) {
|
||||
return m_block_cache;
|
||||
}
|
||||
|
||||
// If block doesn't exist, return NULL
|
||||
auto it = m_blocks.find(y);
|
||||
block = it != m_blocks.end() ? it->second.get() : nullptr;
|
||||
|
||||
// Cache the last result
|
||||
m_block_cache_y = y;
|
||||
m_block_cache = block;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
MapBlock *MapSector::getBlockNoCreateNoEx(s16 y)
|
||||
{
|
||||
return getBlockBuffered(y);
|
||||
}
|
||||
|
||||
std::unique_ptr<MapBlock> MapSector::createBlankBlockNoInsert(s16 y)
|
||||
{
|
||||
assert(getBlockBuffered(y) == nullptr); // Pre-condition
|
||||
|
||||
if (blockpos_over_max_limit(v3s16(0, y, 0)))
|
||||
throw InvalidPositionException("createBlankBlockNoInsert(): pos over max mapgen limit");
|
||||
|
||||
v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
|
||||
|
||||
return std::make_unique<MapBlock>(blockpos_map, m_gamedef);
|
||||
}
|
||||
|
||||
MapBlock *MapSector::createBlankBlock(s16 y)
|
||||
{
|
||||
std::unique_ptr<MapBlock> block_u = createBlankBlockNoInsert(y);
|
||||
MapBlock *block = block_u.get();
|
||||
|
||||
m_blocks[y] = std::move(block_u);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void MapSector::insertBlock(std::unique_ptr<MapBlock> block)
|
||||
{
|
||||
s16 block_y = block->getPos().Y;
|
||||
|
||||
MapBlock *block2 = getBlockBuffered(block_y);
|
||||
if (block2) {
|
||||
throw AlreadyExistsException("Block already exists");
|
||||
}
|
||||
|
||||
v2s16 p2d(block->getPos().X, block->getPos().Z);
|
||||
assert(p2d == m_pos);
|
||||
|
||||
// Insert into container
|
||||
m_blocks[block_y] = std::move(block);
|
||||
}
|
||||
|
||||
void MapSector::deleteBlock(MapBlock *block)
|
||||
{
|
||||
detachBlock(block);
|
||||
// returned smart-ptr is dropped
|
||||
}
|
||||
|
||||
std::unique_ptr<MapBlock> MapSector::detachBlock(MapBlock *block)
|
||||
{
|
||||
s16 block_y = block->getPos().Y;
|
||||
|
||||
// Clear from cache
|
||||
m_block_cache = nullptr;
|
||||
|
||||
// Remove from container
|
||||
auto it = m_blocks.find(block_y);
|
||||
assert(it != m_blocks.end());
|
||||
std::unique_ptr<MapBlock> ret = std::move(it->second);
|
||||
assert(ret.get() == block);
|
||||
m_blocks.erase(it);
|
||||
|
||||
// Mark as removed
|
||||
block->makeOrphan();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MapSector::getBlocks(MapBlockVect &dest)
|
||||
{
|
||||
dest.reserve(dest.size() + m_blocks.size());
|
||||
for (auto &block : m_blocks) {
|
||||
dest.push_back(block.second.get());
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
// Luanti
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "irr_v2d.h"
|
||||
#include "mapblock.h"
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class Map;
|
||||
class IGameDef;
|
||||
|
||||
/*
|
||||
This is an Y-wise stack of MapBlocks.
|
||||
*/
|
||||
|
||||
#define MAPSECTOR_SERVER 0
|
||||
#define MAPSECTOR_CLIENT 1
|
||||
|
||||
class MapSector
|
||||
{
|
||||
public:
|
||||
|
||||
MapSector(Map *parent, v2s16 pos, IGameDef *gamedef);
|
||||
virtual ~MapSector();
|
||||
|
||||
void deleteBlocks();
|
||||
|
||||
v2s16 getPos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
MapBlock *getBlockNoCreateNoEx(s16 y);
|
||||
std::unique_ptr<MapBlock> createBlankBlockNoInsert(s16 y);
|
||||
MapBlock *createBlankBlock(s16 y);
|
||||
|
||||
void insertBlock(std::unique_ptr<MapBlock> block);
|
||||
|
||||
void deleteBlock(MapBlock *block);
|
||||
|
||||
// Remove a block from the map and the sector without deleting it
|
||||
// Returns an owning ptr to block.
|
||||
std::unique_ptr<MapBlock> detachBlock(MapBlock *block);
|
||||
|
||||
// This makes a copy of the internal collection.
|
||||
// Prefer getBlocks() if possible.
|
||||
void getBlocks(MapBlockVect &dest);
|
||||
|
||||
// Get access to the internal collection
|
||||
// This is explicitly only allowed on a const object since modifying anything while iterating is unsafe.
|
||||
// The caller needs to make sure that this does not happen.
|
||||
const auto &getBlocks() const { return m_blocks; }
|
||||
const auto &getBlocks() = delete;
|
||||
|
||||
bool empty() const { return m_blocks.empty(); }
|
||||
|
||||
int size() const { return m_blocks.size(); }
|
||||
protected:
|
||||
|
||||
// The pile of MapBlocks
|
||||
std::unordered_map<s16, std::unique_ptr<MapBlock>> m_blocks;
|
||||
|
||||
Map *m_parent;
|
||||
// Position on parent (in MapBlock widths)
|
||||
v2s16 m_pos;
|
||||
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
// Last-used block is cached here for quicker access.
|
||||
// Be sure to set this to nullptr when the cached block is deleted
|
||||
MapBlock *m_block_cache = nullptr;
|
||||
s16 m_block_cache_y;
|
||||
|
||||
/*
|
||||
Private methods
|
||||
*/
|
||||
MapBlock *getBlockBuffered(s16 y);
|
||||
|
||||
};
|
|
@ -13,7 +13,6 @@
|
|||
#include "client/clientmedia.h"
|
||||
#include "log.h"
|
||||
#include "servermap.h"
|
||||
#include "mapsector.h"
|
||||
#include "client/minimap.h"
|
||||
#include "modchannels.h"
|
||||
#include "nodedef.h"
|
||||
|
@ -285,15 +284,7 @@ void Client::handleCommand_BlockData(NetworkPacket* pkt)
|
|||
std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
|
||||
std::istringstream istr(datastring, std::ios_base::binary);
|
||||
|
||||
MapSector *sector;
|
||||
MapBlock *block;
|
||||
|
||||
v2s16 p2d(p.X, p.Z);
|
||||
sector = m_env.getMap().emergeSector(p2d);
|
||||
|
||||
assert(sector->getPos() == p2d);
|
||||
|
||||
block = sector->getBlockNoCreateNoEx(p.Y);
|
||||
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
||||
if (block) {
|
||||
/*
|
||||
Update an existing block
|
||||
|
@ -305,7 +296,7 @@ void Client::handleCommand_BlockData(NetworkPacket* pkt)
|
|||
/*
|
||||
Create a new block
|
||||
*/
|
||||
block = sector->createBlankBlock(p.Y);
|
||||
block = m_env.getMap().createBlankBlock(p);
|
||||
block->deSerialize(istr, m_server_ser_ver, false);
|
||||
block->deSerializeNetworkSpecific(istr);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// Copyright (C) 2010-2024 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
#include "map.h"
|
||||
#include "mapsector.h"
|
||||
#include "filesys.h"
|
||||
#include "voxel.h"
|
||||
#include "voxelalgorithms.h"
|
||||
|
@ -228,24 +227,18 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data)
|
|||
Create the whole area of this and the neighboring blocks
|
||||
*/
|
||||
for (s16 x = full_bpmin.X; x <= full_bpmax.X; x++)
|
||||
for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++) {
|
||||
v2s16 sectorpos(x, z);
|
||||
// Sector metadata is loaded from disk if not already loaded.
|
||||
MapSector *sector = createSector(sectorpos);
|
||||
FATAL_ERROR_IF(sector == NULL, "createSector() failed");
|
||||
for (s16 z = full_bpmin.Z; z <= full_bpmax.Z; z++)
|
||||
for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
|
||||
v3s16 p(x, y, z);
|
||||
|
||||
for (s16 y = full_bpmin.Y; y <= full_bpmax.Y; y++) {
|
||||
v3s16 p(x, y, z);
|
||||
MapBlock *block = emergeBlock(p, false);
|
||||
if (block == NULL) {
|
||||
block = createBlock(p);
|
||||
|
||||
MapBlock *block = emergeBlock(p, false);
|
||||
if (block == NULL) {
|
||||
block = createBlock(p);
|
||||
|
||||
// Block gets sunlight if this is true.
|
||||
// Refer to the map generator heuristics.
|
||||
bool ug = m_emerge->isBlockUnderground(p);
|
||||
block->setIsUnderground(ug);
|
||||
}
|
||||
// Block gets sunlight if this is true.
|
||||
// Refer to the map generator heuristics.
|
||||
bool ug = m_emerge->isBlockUnderground(p);
|
||||
block->setIsUnderground(ug);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,61 +315,15 @@ void ServerMap::finishBlockMake(BlockMakeData *data,
|
|||
m_chunks_in_progress.erase(bpmin);
|
||||
}
|
||||
|
||||
MapSector *ServerMap::createSector(v2s16 p2d)
|
||||
{
|
||||
/*
|
||||
Check if it exists already in memory
|
||||
*/
|
||||
MapSector *sector = getSectorNoGenerate(p2d);
|
||||
if (sector)
|
||||
return sector;
|
||||
|
||||
/*
|
||||
Do not create over max mapgen limit
|
||||
*/
|
||||
if (blockpos_over_max_limit(v3s16(p2d.X, 0, p2d.Y)))
|
||||
throw InvalidPositionException("createSector(): pos over max mapgen limit");
|
||||
|
||||
/*
|
||||
Generate blank sector
|
||||
*/
|
||||
sector = new MapSector(this, p2d, m_gamedef);
|
||||
|
||||
/*
|
||||
Insert to container
|
||||
*/
|
||||
m_sectors[p2d] = sector;
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
MapBlock * ServerMap::createBlock(v3s16 p)
|
||||
{
|
||||
v2s16 p2d(p.X, p.Z);
|
||||
s16 block_y = p.Y;
|
||||
|
||||
/*
|
||||
This will create or load a sector if not found in memory.
|
||||
*/
|
||||
MapSector *sector;
|
||||
try {
|
||||
sector = createSector(p2d);
|
||||
} catch (InvalidPositionException &e) {
|
||||
infostream<<"createBlock: createSector() failed"<<std::endl;
|
||||
throw e;
|
||||
}
|
||||
|
||||
/*
|
||||
Try to get a block from the sector
|
||||
*/
|
||||
|
||||
MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
|
||||
MapBlock *block = getBlockNoCreateNoEx(p);
|
||||
if (block)
|
||||
return block;
|
||||
|
||||
// Create blank
|
||||
try {
|
||||
block = sector->createBlankBlock(block_y);
|
||||
block = createBlankBlock(p);
|
||||
} catch (InvalidPositionException &e) {
|
||||
infostream << "createBlock: createBlankBlock() failed" << std::endl;
|
||||
throw e;
|
||||
|
@ -401,8 +348,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
|
|||
|
||||
if (create_blank) {
|
||||
try {
|
||||
MapSector *sector = createSector(v2s16(p.X, p.Z));
|
||||
return sector->createBlankBlock(p.Y);
|
||||
return createBlankBlock(p);
|
||||
} catch (InvalidPositionException &e) {}
|
||||
}
|
||||
|
||||
|
@ -502,27 +448,21 @@ void ServerMap::save(ModifiedState save_level)
|
|||
// Don't do anything with sqlite unless something is really saved
|
||||
bool save_started = false;
|
||||
|
||||
for (auto §or_it : m_sectors) {
|
||||
MapSector *sector = sector_it.second;
|
||||
for (auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
block_count_all++;
|
||||
|
||||
MapBlockVect blocks;
|
||||
sector->getBlocks(blocks);
|
||||
|
||||
for (MapBlock *block : blocks) {
|
||||
block_count_all++;
|
||||
|
||||
if(block->getModified() >= (u32)save_level) {
|
||||
// Lazy beginSave()
|
||||
if(!save_started) {
|
||||
beginSave();
|
||||
save_started = true;
|
||||
}
|
||||
|
||||
modprofiler.add(block->getModifiedReasonString(), 1);
|
||||
|
||||
saveBlock(block);
|
||||
block_count++;
|
||||
if(block->getModified() >= (u32)save_level) {
|
||||
// Lazy beginSave()
|
||||
if(!save_started) {
|
||||
beginSave();
|
||||
save_started = true;
|
||||
}
|
||||
|
||||
modprofiler.add(block->getModifiedReasonString(), 1);
|
||||
|
||||
saveBlock(block);
|
||||
block_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,16 +497,10 @@ void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
|||
|
||||
void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
|
||||
{
|
||||
for (auto §or_it : m_sectors) {
|
||||
MapSector *sector = sector_it.second;
|
||||
|
||||
MapBlockVect blocks;
|
||||
sector->getBlocks(blocks);
|
||||
|
||||
for (MapBlock *block : blocks) {
|
||||
v3s16 p = block->getPos();
|
||||
dst.push_back(p);
|
||||
}
|
||||
for (auto &entry : m_blocks) {
|
||||
MapBlock *block = entry.second;
|
||||
v3s16 p = block->getPos();
|
||||
dst.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,14 +600,11 @@ MapBlock *ServerMap::loadBlock(const std::string &blob, v3s16 p3d, bool save_aft
|
|||
bool created_new = false;
|
||||
|
||||
try {
|
||||
v2s16 p2d(p3d.X, p3d.Z);
|
||||
MapSector *sector = createSector(p2d);
|
||||
|
||||
std::unique_ptr<MapBlock> block_created_new;
|
||||
block = sector->getBlockNoCreateNoEx(p3d.Y);
|
||||
MapBlock* block_created_new = nullptr;
|
||||
block = getBlockNoCreateNoEx(p3d);
|
||||
if (!block) {
|
||||
block_created_new = sector->createBlankBlockNoInsert(p3d.Y);
|
||||
block = block_created_new.get();
|
||||
block_created_new = createBlankBlockNoInsert(p3d);
|
||||
block = block_created_new;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -683,7 +614,7 @@ MapBlock *ServerMap::loadBlock(const std::string &blob, v3s16 p3d, bool save_aft
|
|||
|
||||
// If it's a new block, insert it to the map
|
||||
if (block_created_new) {
|
||||
sector->insertBlock(std::move(block_created_new));
|
||||
insertBlock(block_created_new);
|
||||
created_new = true;
|
||||
}
|
||||
} catch (SerializationError &e) {
|
||||
|
@ -751,13 +682,9 @@ bool ServerMap::deleteBlock(v3s16 blockpos)
|
|||
|
||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if (block) {
|
||||
v2s16 p2d(blockpos.X, blockpos.Z);
|
||||
MapSector *sector = getSectorNoGenerate(p2d);
|
||||
if (!sector)
|
||||
return false;
|
||||
// It may not be safe to delete the block from memory at the moment
|
||||
// (pointers to it could still be in use)
|
||||
m_detached_blocks.push_back(sector->detachBlock(block));
|
||||
m_detached_blocks.push_back(detachBlock(block));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -49,14 +49,6 @@ public:
|
|||
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().
|
||||
*/
|
||||
|
|
|
@ -753,13 +753,13 @@ void update_block_border_lighting(Map *map, MapBlock *block,
|
|||
/*!
|
||||
* Resets the lighting of the given VoxelManipulator to
|
||||
* complete darkness and full sunlight.
|
||||
* Operates in one map sector.
|
||||
* Operates in one map column.
|
||||
*
|
||||
* \param offset contains the least x and z node coordinates
|
||||
* of the map sector.
|
||||
* of the map column.
|
||||
* \param light incoming sunlight, light[x][z] is true if there
|
||||
* is sunlight above the voxel manipulator at the given x-z coordinates.
|
||||
* The array's indices are relative node coordinates in the sector.
|
||||
* The array's indices are relative node coordinates in the column.
|
||||
* After the procedure returns, this contains outgoing light at
|
||||
* the bottom of the voxel manipulator.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue