This commit is contained in:
Pascal Engélibert 2020-06-02 16:24:45 +02:00
parent 06f44f717d
commit e22e63967d
2 changed files with 76 additions and 0 deletions

View File

@ -45,6 +45,14 @@ Example:
Prefer cbor+gzip for big imports. lzma is much slower than gzip but produces slightly smaller files. cbor is much smaller than json.
## Library
`mtdb.py` is a Python3 library for interacting with MineTest db.
import mtdb
db = mtdb.init_pgsql("host=127.0.0.1 port=5432 user=minetest password=PASSWORD dbname=minetest-world")
mtdb.get_chunk(db, (0,0,0)) # Chunk position, not node position (1 chunk = cube of 16*16*16 nodes)
## License
GNU AGPL 3.0

68
mtdb.py Normal file
View File

@ -0,0 +1,68 @@
#!/usr/bin/env python3
DB_PGSQL = 1
DB_SQLITE = 2
class Db:
def __init__(self, obj, dbtype):
self.obj = obj
self.dbtype = dbtype
# Init PostgreSQL database
def init_pgsql(connect: str):
global psycopg2
import psycopg2
return Db(psycopg2.connect(connect), DB_PGSQL)
# Init SQLite database
def init_sqlite(dbname: str):
global sqlite3
import sqlite3
return Db(sqlite3.connect(dbname), DB_SQLITE)
def to_signed(x, bits=11):
return x if x >= 0 else (1<<bits)-x
def from_signed(x, bits=11):
b = 1<<bits
return x if x < b else (b^x)-b
def chunk_to_int(pos: (int, int, int)):
return to_signed(pos[2])<<24 | to_signed(pos[1])<<12 | to_signed(pos[0])
def int_to_chunk(pos: int):
return (from_signed(pos>>24), from_signed(pos>>12&0xfff), from_signed(pos&0xfff))
# Read chunk from db
def get_chunk(db: Db, pos: (int, int, int)):
if db.dbtype == DB_PGSQL:
c = db.obj.cursor()
c.execute("SELECT data FROM blocks WHERE posx={} AND posy={} AND posz={} LIMIT 1".format(*pos))
res = c.fetchone()
if res:
res = res[0].tobytes()
return res
else:
c = db.obj.cursor()
c.execute("SELECT data FROM blocks WHERE pos={} LIMIT 1".format(chunk_to_int(pos)))
res = c.fetchone()
if res:
res = res[0]
return res
# Write chunk to db
def set_chunk(db: Db, pos: (int, int, int), data: bytes):
if db.dbtype == DB_PGSQL:
c = db.obj.cursor()
c.execute("SELECT 1 FROM blocks WHERE posx={} AND posy={} AND posz={} LIMIT 1".format(*pos))
if c.fetchone():
c.execute("UPDATE blocks SET data={} WHERE posx={} AND posy={} AND posz={} LIMIT 1".format(data, *pos))
else:
c.execute("INSERT INTO blocks (posx, posy, posz, data) VALUES ({}, {}, {}, {})".format(*pos, data))
else:
chunk_id = chunk_to_int(pos)
c.execute("SELECT 1 FROM blocks WHERE pos={} LIMIT 1".format(chunk_id))
if c.fetchone():
c.execute("UPDATE blocks SET data={} WHERE pos={} LIMIT 1".format(data, chunk_id))
else:
c.execute("INSERT INTO blocks (pos, data) VALUES ({}, {})".format(chunk_id, data))