1
1
#include < stdexcept>
2
2
#include < sstream>
3
+ #include < algorithm>
3
4
#include " db-leveldb.h"
4
5
#include " types.h"
5
6
@@ -25,7 +26,7 @@ DBLevelDB::DBLevelDB(const std::string &mapdir)
25
26
options.create_if_missing = false ;
26
27
leveldb::Status status = leveldb::DB::Open (options, mapdir + " map.db" , &db);
27
28
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 ());
29
30
}
30
31
31
32
/* LevelDB is a dumb key-value store, so the only optimization we can do
@@ -41,18 +42,22 @@ DBLevelDB::~DBLevelDB()
41
42
}
42
43
43
44
44
- std::vector<BlockPos> DBLevelDB::getBlockPos (BlockPos min, BlockPos max)
45
+ std::vector<BlockPos> DBLevelDB::getBlockPosXZ (BlockPos min, BlockPos max)
45
46
{
46
47
std::vector<BlockPos> res;
47
48
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 )
49
51
continue ;
50
52
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 )
52
54
continue ;
53
- if (pos2.second < min.y || pos2.second >= max.y )
55
+ if (pos2.y < min.y || pos2.y >= max.y )
54
56
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);
56
61
}
57
62
}
58
63
return res;
@@ -61,14 +66,17 @@ std::vector<BlockPos> DBLevelDB::getBlockPos(BlockPos min, BlockPos max)
61
66
62
67
void DBLevelDB::loadPosCache ()
63
68
{
64
- leveldb::Iterator * it = db->NewIterator (leveldb::ReadOptions ());
69
+ leveldb::Iterator *it = db->NewIterator (leveldb::ReadOptions ());
65
70
for (it->SeekToFirst (); it->Valid (); it->Next ()) {
66
71
int64_t posHash = stoi64 (it->key ().ToString ());
67
72
BlockPos pos = decodeBlockPos (posHash);
68
73
69
74
posCache[pos.z ].emplace_back (pos.x , pos.y );
70
75
}
71
76
delete it;
77
+
78
+ for (auto &it : posCache)
79
+ std::sort (it.second .begin (), it.second .end ());
72
80
}
73
81
74
82
@@ -82,12 +90,13 @@ void DBLevelDB::getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
82
90
if (it == posCache.cend ())
83
91
return ;
84
92
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)
86
95
continue ;
87
- if (pos2.second < min_y || pos2.second >= max_y)
96
+ if (pos2.y < min_y || pos2.y >= max_y)
88
97
continue ;
89
98
90
- BlockPos pos (x, pos2.second , z);
99
+ BlockPos pos (x, pos2.y , z);
91
100
status = db->Get (leveldb::ReadOptions (), i64tos (encodeBlockPos (pos)), &datastr);
92
101
if (status.ok ()) {
93
102
blocks.emplace_back (
0 commit comments