File: db.h

package info (click to toggle)
minetestmapper 20241111-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 300 kB
  • sloc: cpp: 2,635; python: 143; sh: 68; ansic: 30; makefile: 9
file content (123 lines) | stat: -rw-r--r-- 2,739 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#pragma once

#include <cstdint>
#include <list>
#include <vector>
#include <utility>
#include "types.h"


struct BlockPos {
	int16_t x;
	int16_t y;
	int16_t z;

	BlockPos() : x(0), y(0), z(0) {}
	explicit BlockPos(int16_t v) : x(v), y(v), z(v) {}
	BlockPos(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {}

	// Implements the inverse ordering so that (2,2,2) < (1,1,1)
	bool operator < (const BlockPos &p) const
	{
		if (z > p.z)
			return true;
		if (z < p.z)
			return false;
		if (y > p.y)
			return true;
		if (y < p.y)
			return false;
		if (x > p.x)
			return true;
		if (x < p.x)
			return false;
		return false;
	}
};


typedef std::pair<BlockPos, ustring> Block;
typedef std::list<Block> BlockList;


class DB {
protected:
	// Helpers that implement the hashed positions used by most backends
	inline int64_t  encodeBlockPos(const BlockPos pos) const;
	inline BlockPos decodeBlockPos(int64_t hash) const;

public:
	/* Return all block positions inside the range given by min and max,
	 * so that min.x <= x < max.x, ...
	 */
	virtual std::vector<BlockPos> getBlockPos(BlockPos min, BlockPos max) = 0;
	/* Read all blocks in column given by x and z
	 * and inside the given Y range (min_y <= y < max_y) into list
	 */
	virtual void getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
			int16_t min_y, int16_t max_y) = 0;
	/* Read blocks at given positions into list
	 */
	virtual void getBlocksByPos(BlockList &blocks,
			const std::vector<BlockPos> &positions) = 0;
	/* Can this database efficiently do range queries?
	 * (for large data sets, more efficient that brute force)
	 */
	virtual bool preferRangeQueries() const = 0;


	virtual ~DB() {}
};



/****************
 * Black magic! *
 ****************
 * The position hashing is seriously messed up,
 * and is a lot more complicated than it looks.
 */

static inline int16_t unsigned_to_signed(uint16_t i, uint16_t max_positive)
{
	if (i < max_positive) {
		return i;
	} else {
		return i - (max_positive * 2);
	}
}


// Modulo of a negative number does not work consistently in C
static inline int64_t pythonmodulo(int64_t i, int64_t mod)
{
	if (i >= 0) {
		return i % mod;
	}
	return mod - ((-i) % mod);
}


inline int64_t DB::encodeBlockPos(const BlockPos pos) const
{
	return (uint64_t) pos.z * 0x1000000 +
		(uint64_t) pos.y * 0x1000 +
		(uint64_t) pos.x;
}


inline BlockPos DB::decodeBlockPos(int64_t hash) const
{
	BlockPos pos;
	pos.x = unsigned_to_signed(pythonmodulo(hash, 4096), 2048);
	hash = (hash - pos.x) / 4096;
	pos.y = unsigned_to_signed(pythonmodulo(hash, 4096), 2048);
	hash = (hash - pos.y) / 4096;
	pos.z = unsigned_to_signed(pythonmodulo(hash, 4096), 2048);
	return pos;
}

/*******************
 * End black magic *
 *******************/