mtdb
This commit is contained in:
parent
06f44f717d
commit
e22e63967d
@ -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
68
mtdb.py
Normal 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))
|
Loading…
x
Reference in New Issue
Block a user