X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futil%2Fareastore.cpp;h=cea526336b66b8d5ec1e16e9baf2833c8bbbc2bd;hb=3f702fa1a9ace33111256ed7b7d5579099830015;hp=568492383d9efb636507ae3f7aef13673ab77ccf;hpb=5641da43d635ae46770eb20c5482a8971086202f;p=minetest.git diff --git a/src/util/areastore.cpp b/src/util/areastore.cpp index 568492383..cea526336 100644 --- a/src/util/areastore.cpp +++ b/src/util/areastore.cpp @@ -54,72 +54,69 @@ AreaStore *AreaStore::getOptimalImplementation() #endif } -u16 AreaStore::size() const +const Area *AreaStore::getArea(u32 id) const { - return areas_map.size(); + AreaMap::const_iterator it = areas_map.find(id); + if (it == areas_map.end()) + return nullptr; + return &it->second; } -const Area *AreaStore::getArea(u32 id) const +void AreaStore::serialize(std::ostream &os) const { - const Area *res = NULL; - std::map::const_iterator itr = areas_map.find(id); - if (itr != areas_map.end()) { - res = &itr->second; + // WARNING: + // Before 5.1.0-dev: version != 0 throws SerializationError + // After 5.1.0-dev: version >= 5 throws SerializationError + // Forwards-compatibility is assumed before version 5. + + writeU8(os, 0); // Serialisation version + + // TODO: Compression? + writeU16(os, areas_map.size()); + for (const auto &it : areas_map) { + const Area &a = it.second; + writeV3S16(os, a.minedge); + writeV3S16(os, a.maxedge); + writeU16(os, a.data.size()); + os.write(a.data.data(), a.data.size()); } - return res; + + // Serialize IDs + for (const auto &it : areas_map) + writeU32(os, it.second.id); } -#if 0 -Currently, serialisation is commented out. This is because of multiple reasons: -1. Why do we store the areastore into a file, why not into the database? -2. We don't use libspatial's serialisation, but we should, or perhaps not, because - it would remove the ability to switch. Perhaps write migration routines? -3. Various things need fixing, e.g. the size is serialized as - c++ implementation defined size_t -bool AreaStore::deserialize(std::istream &is) +void AreaStore::deserialize(std::istream &is) { u8 ver = readU8(is); - if (ver != 1) - return false; - u16 count_areas = readU16(is); - for (u16 i = 0; i < count_areas; i++) { - // deserialize an area - Area a; - a.id = readU32(is); + // Assume forwards-compatibility before version 5 + if (ver >= 5) + throw SerializationError("Unknown AreaStore " + "serialization version!"); + + u16 num_areas = readU16(is); + std::vector areas; + for (u32 i = 0; i < num_areas; ++i) { + Area a(U32_MAX); a.minedge = readV3S16(is); a.maxedge = readV3S16(is); - a.datalen = readU16(is); - a.data = new char[a.datalen]; - is.read((char *) a.data, a.datalen); - insertArea(a); + u16 data_len = readU16(is); + char *data = new char[data_len]; + is.read(data, data_len); + a.data = std::string(data, data_len); + areas.emplace_back(a); + delete [] data; } - return true; -} + bool read_ids = is.good(); // EOF for old formats -static bool serialize_area(void *ostr, Area *a) -{ - std::ostream &os = *((std::ostream *) ostr); - writeU32(os, a->id); - writeV3S16(os, a->minedge); - writeV3S16(os, a->maxedge); - writeU16(os, a->datalen); - os.write(a->data, a->datalen); - - return false; -} - - -void AreaStore::serialize(std::ostream &os) const -{ - // write initial data - writeU8(os, 1); // serialisation version - writeU16(os, areas_map.size()); //DANGER: not platform independent - forEach(&serialize_area, &os); + for (auto &area : areas) { + if (read_ids) + area.id = readU32(is); + insertArea(&area); + } } -#endif - void AreaStore::invalidateCache() { if (m_cache_enabled) { @@ -127,6 +124,19 @@ void AreaStore::invalidateCache() } } +u32 AreaStore::getNextId() const +{ + u32 free_id = 0; + for (const auto &area : areas_map) { + if (area.first > free_id) + return free_id; // Found gap + + free_id = area.first + 1; + } + // End of map + return free_id; +} + void AreaStore::setCacheParams(bool enabled, u8 block_radius, size_t limit) { m_cache_enabled = enabled; @@ -182,7 +192,8 @@ void AreaStore::getAreasForPos(std::vector *result, v3s16 pos) bool VectorAreaStore::insertArea(Area *a) { - a->id = getNextId(); + if (a->id == U32_MAX) + a->id = getNextId(); std::pair res = areas_map.insert(std::make_pair(a->id, *a)); if (!res.second) @@ -213,10 +224,9 @@ bool VectorAreaStore::removeArea(u32 id) void VectorAreaStore::getAreasForPosImpl(std::vector *result, v3s16 pos) { - for (size_t i = 0; i < m_areas.size(); ++i) { - Area *b = m_areas[i]; - if (AST_CONTAINS_PT(b, pos)) { - result->push_back(b); + for (Area *area : m_areas) { + if (AST_CONTAINS_PT(area, pos)) { + result->push_back(area); } } } @@ -224,26 +234,13 @@ void VectorAreaStore::getAreasForPosImpl(std::vector *result, v3s16 pos) void VectorAreaStore::getAreasInArea(std::vector *result, v3s16 minedge, v3s16 maxedge, bool accept_overlap) { - for (size_t i = 0; i < m_areas.size(); ++i) { - Area *b = m_areas[i]; - if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, b) : - AST_CONTAINS_AREA(minedge, maxedge, b)) { - result->push_back(b); - } - } -} - -#if 0 -bool SimpleAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const -{ - for (size_t i = 0; i < m_areas.size(); ++i) { - if (callback(m_areas[i], arg)) { - return true; + for (Area *area : m_areas) { + if (accept_overlap ? AST_AREAS_OVERLAP(minedge, maxedge, area) : + AST_CONTAINS_AREA(minedge, maxedge, area)) { + result->push_back(area); } } - return false; } -#endif #if USE_SPATIAL @@ -266,11 +263,12 @@ static inline SpatialIndex::Point get_spatial_point(const v3s16 pos) bool SpatialAreaStore::insertArea(Area *a) { - a->id = getNextId(); + if (a->id == U32_MAX) + a->id = getNextId(); if (!areas_map.insert(std::make_pair(a->id, *a)).second) // ID is not unique return false; - m_tree->insertData(0, NULL, get_spatial_region(a->minedge, a->maxedge), a->id); + m_tree->insertData(0, nullptr, get_spatial_region(a->minedge, a->maxedge), a->id); invalidateCache(); return true; } @@ -282,6 +280,7 @@ bool SpatialAreaStore::removeArea(u32 id) Area *a = &itr->second; bool result = m_tree->deleteData(get_spatial_region(a->minedge, a->maxedge), id); + areas_map.erase(itr); invalidateCache(); return result; } else { @@ -307,14 +306,6 @@ void SpatialAreaStore::getAreasInArea(std::vector *result, } } -#if 0 -bool SpatialAreaStore::forEach(bool (*callback)(void *args, Area *a), void *args) const -{ - // TODO ?? (this is only needed for serialisation, but libspatial has its own serialisation) - return false; -} -#endif - SpatialAreaStore::~SpatialAreaStore() { delete m_tree;