11#include < stdexcept>
22#include < sstream>
3+ #include < algorithm>
34#include " db-leveldb.h"
45#include " types.h"
56
@@ -25,7 +26,7 @@ DBLevelDB::DBLevelDB(const std::string &mapdir)
2526 options.create_if_missing = false ;
2627 leveldb::Status status = leveldb::DB::Open (options, mapdir + " map.db" , &db);
2728 if (!status.ok ()) {
28- throw std::runtime_error (std::string (" Failed to open Database : " ) + status.ToString ());
29+ throw std::runtime_error (std::string (" Failed to open database : " ) + status.ToString ());
2930 }
3031
3132 /* LevelDB is a dumb key-value store, so the only optimization we can do
@@ -41,18 +42,22 @@ DBLevelDB::~DBLevelDB()
4142}
4243
4344
44- std::vector<BlockPos> DBLevelDB::getBlockPos (BlockPos min, BlockPos max)
45+ std::vector<BlockPos> DBLevelDB::getBlockPosXZ (BlockPos min, BlockPos max)
4546{
4647 std::vector<BlockPos> res;
4748 for (const auto &it : posCache) {
48- if (it.first < min.z || it.first >= max.z )
49+ const int16_t zpos = it.first ;
50+ if (zpos < min.z || zpos >= max.z )
4951 continue ;
5052 for (auto pos2 : it.second ) {
51- if (pos2.first < min.x || pos2.first >= max.x )
53+ if (pos2.x < min.x || pos2.x >= max.x )
5254 continue ;
53- if (pos2.second < min.y || pos2.second >= max.y )
55+ if (pos2.y < min.y || pos2.y >= max.y )
5456 continue ;
55- res.emplace_back (pos2.first , pos2.second , it.first );
57+ // skip duplicates
58+ if (!res.empty () && res.back ().x == pos2.x && res.back ().z == zpos)
59+ continue ;
60+ res.emplace_back (pos2.x , pos2.y , zpos);
5661 }
5762 }
5863 return res;
@@ -61,14 +66,17 @@ std::vector<BlockPos> DBLevelDB::getBlockPos(BlockPos min, BlockPos max)
6166
6267void DBLevelDB::loadPosCache ()
6368{
64- leveldb::Iterator * it = db->NewIterator (leveldb::ReadOptions ());
69+ leveldb::Iterator *it = db->NewIterator (leveldb::ReadOptions ());
6570 for (it->SeekToFirst (); it->Valid (); it->Next ()) {
6671 int64_t posHash = stoi64 (it->key ().ToString ());
6772 BlockPos pos = decodeBlockPos (posHash);
6873
6974 posCache[pos.z ].emplace_back (pos.x , pos.y );
7075 }
7176 delete it;
77+
78+ for (auto &it : posCache)
79+ std::sort (it.second .begin (), it.second .end ());
7280}
7381
7482
@@ -82,12 +90,13 @@ void DBLevelDB::getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
8290 if (it == posCache.cend ())
8391 return ;
8492 for (auto pos2 : it->second ) {
85- if (pos2.first != x)
93+ // TODO this could be optimized more since the cached list is sorted
94+ if (pos2.x != x)
8695 continue ;
87- if (pos2.second < min_y || pos2.second >= max_y)
96+ if (pos2.y < min_y || pos2.y >= max_y)
8897 continue ;
8998
90- BlockPos pos (x, pos2.second , z);
99+ BlockPos pos (x, pos2.y , z);
91100 status = db->Get (leveldb::ReadOptions (), i64tos (encodeBlockPos (pos)), &datastr);
92101 if (status.ok ()) {
93102 blocks.emplace_back (
0 commit comments