From e22e63967d893878313e3fdecc03d0ef7184be9f Mon Sep 17 00:00:00 2001 From: tuxmain Date: Tue, 2 Jun 2020 16:24:45 +0200 Subject: [PATCH] mtdb --- README.md | 8 +++++++ mtdb.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 mtdb.py diff --git a/README.md b/README.md index 40994e1..f777dbf 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/mtdb.py b/mtdb.py new file mode 100644 index 0000000..f269c5d --- /dev/null +++ b/mtdb.py @@ -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<>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))