- Map :
- Unified indentation in the source code - MapInterfaces (`minetest.map.MapInterface`) can now import schematics as well - Some prints in MapVessel's (`minetest.map.MapVessel`) code were labeled "WARNING", the others commented - Utils : - A class called Vector (`minetest.utils.Vector`) is added to deal with vectors and Pos (`minetest.utils.Pos`) manipulation - Tests : - Tests are made more fancy with check lists (rather than big data dumps) and time tests. All tests were remade and organized to include assertations and prettier printing - Demo : - A new demo is available, it is called demo_schematics_manipulation and serves the purpose of exporting/importing schematics from/into a map database - Schematics : - The export method now writes position integers on the correct amount of bytes - Minetest : - All python source code files are imported into the single file minetest.py, later imported by any other source code file
This commit is contained in:
parent
9c1f363087
commit
724018376f
51
src/demo_schematic_manipulation.py
Executable file
51
src/demo_schematic_manipulation.py
Executable file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3.4
|
||||
# -*- encoding: utf-8 -*-
|
||||
############################
|
||||
## Demo of Python-Minetest :
|
||||
## Exports/Imports a schematic to a map
|
||||
##
|
||||
## args :
|
||||
## ./demo_schematic_manipulation.py <import|export> <path to sqlite file> <path to schematic file>
|
||||
##
|
||||
#
|
||||
|
||||
import minetest
|
||||
|
||||
pos_import = minetest.utils.Pos({"x": -33, "y": 100, "z": 48})
|
||||
pos1_export = minetest.utils.Pos({"x": -10, "y": -10, "z": -10})
|
||||
pos2_export = minetest.utils.Pos({"x": 10, "y": 10, "z": 10})
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "help":
|
||||
print("./demo_schematic_manipulation.py <import|export> <path to sqlite file> <path to schematic file>")
|
||||
else:
|
||||
print("See demo_schematic_manipulation.py help for help")
|
||||
sys.exit(0)
|
||||
|
||||
mode, dbfile, schfile = sys.argv[1:4]
|
||||
|
||||
try:
|
||||
open(dbfile)
|
||||
except Exception as err:
|
||||
print("Couldn't open db file {0} : {1}".format(dbfile, err))
|
||||
sys.exit(0)
|
||||
|
||||
db = minetest.map.MapInterface(dbfile)
|
||||
|
||||
if mode.lower() == "import":
|
||||
print("Importing schematic..")
|
||||
db.import_schematic(pos_import, minetest.schematics.Schematic(schfile))
|
||||
db.save()
|
||||
print("Done")
|
||||
|
||||
elif mode.lower() == "export":
|
||||
print("Exporting schematic..")
|
||||
db.export_schematic(pos1_export, pos2_export).export_to_file(schfile)
|
||||
print("Done")
|
||||
|
||||
else:
|
||||
print("Unknown mode {0}".format(mode))
|
||||
sys.exit(9)
|
1062
src/map.py
1062
src/map.py
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,9 @@
|
||||
#
|
||||
|
||||
import utils
|
||||
from utils import Pos
|
||||
from map import MapInterface
|
||||
import map
|
||||
|
||||
from nodes import *
|
||||
import schematics
|
||||
import inventory
|
||||
import errors
|
||||
import metadata
|
||||
import nodes
|
||||
|
@ -20,7 +20,7 @@ from io import BytesIO
|
||||
# Quick spec for ver4
|
||||
"""
|
||||
u32 signature (= b"MTSM")
|
||||
u16 version?
|
||||
u16 version
|
||||
u16 size_x
|
||||
u16 size_y
|
||||
u16 size_z
|
||||
@ -109,9 +109,9 @@ class Schematic:
|
||||
data.write(b"MTSM")
|
||||
writeU16(data, self.version)
|
||||
|
||||
writeU8(data, self.size["x"])
|
||||
writeU8(data, self.size["y"])
|
||||
writeU8(data, self.size["z"])
|
||||
writeU16(data, self.size["x"])
|
||||
writeU16(data, self.size["y"])
|
||||
writeU16(data, self.size["z"])
|
||||
|
||||
for u in range(self.size["y"]):
|
||||
p = self.y_slice_probs.get(u) or 127
|
||||
|
165
src/test.py
165
src/test.py
@ -6,93 +6,170 @@
|
||||
|
||||
import minetest
|
||||
import random
|
||||
from utils import readS8, readS16, Pos
|
||||
import time
|
||||
|
||||
from io import BytesIO
|
||||
from schematics import Schematic
|
||||
|
||||
def testSignedEndians():
|
||||
print(readS16(BytesIO(b"\x9f\xff")))
|
||||
|
||||
def testMapBlockLoad():
|
||||
file = minetest.map.MapVessel("./map.sqlite")
|
||||
#i = 2+12*4096+(-9)*4096*4096
|
||||
#i = 0
|
||||
for i in range(-4096, 4096):
|
||||
res, code = file.read(i)
|
||||
if not res:
|
||||
continue
|
||||
else:
|
||||
print("Read {0}: {1}".format(i, (res, code)))
|
||||
file = minetest.map.MapVessel("./map.sqlite")
|
||||
for i in range(-4096, 4096):
|
||||
res, code = file.read(i)
|
||||
if not res:
|
||||
continue
|
||||
else:
|
||||
mapb = file.load(i)
|
||||
print("Read and loaded {0}: {1}".format(i, mapb), end = " \r")
|
||||
|
||||
mapb = file.load(i)
|
||||
print("Loaded {0}: {1}".format(i, mapb))
|
||||
print(" -> There are in total {0} mapblocks in the map".format(len(file.get_all_mapblock_ids())), end = (' ' * 20) + '\n')
|
||||
print(" --> Test successful")
|
||||
|
||||
def testEndians():
|
||||
assert(minetest.utils.readS8(BytesIO(b"\xf8")) == -8)
|
||||
print(" -> readS8: OK")
|
||||
assert(minetest.utils.readS16(BytesIO(b"\x9f\xff")) == -24577)
|
||||
print(" -> readS16: OK")
|
||||
assert(minetest.utils.readS32(BytesIO(b"\xf0\x00\x00\x00")) == -268435456)
|
||||
print(" -> readS32: OK")
|
||||
|
||||
assert(minetest.utils.readU8(BytesIO(b"\xf8")) == 248)
|
||||
print(" -> readU8: OK")
|
||||
assert(minetest.utils.readU16(BytesIO(b"\x9f\xff")) == 40959)
|
||||
print(" -> readU16: OK")
|
||||
assert(minetest.utils.readU32(BytesIO(b"\xf0\x00\x00\x00")) == 4026531840)
|
||||
print(" -> readU32: OK")
|
||||
|
||||
print(" --> Test successful")
|
||||
|
||||
print(len(file.cache))
|
||||
|
||||
def testGetNode():
|
||||
db = minetest.MapInterface("./map.sqlite")
|
||||
for _ in range(1000):
|
||||
pos = Pos({'x': random.randint(-300, 300), 'y': random.randint(-300, 300), 'z': random.randint(-300, 300)})
|
||||
db = minetest.map.MapInterface("./map.sqlite")
|
||||
|
||||
u = random.randint(500, 2000)
|
||||
k = random.randint(40,400)
|
||||
|
||||
db.set_maxcachesize(k)
|
||||
print(" -> Maximum cache size set to {0} mapblocks".format(k))
|
||||
|
||||
s = time.time()
|
||||
for i in range(u):
|
||||
pos = minetest.utils.Pos({'x': random.randint(-300, 300), 'y': random.randint(-300, 300), 'z': random.randint(-300, 300)})
|
||||
assert(db.get_node(pos).get_name() != "")
|
||||
|
||||
if len(db.interface.cache) == db.get_maxcachesize():
|
||||
endstr = " (MAX)\r"
|
||||
else:
|
||||
endstr = " \r"
|
||||
|
||||
print("[{0}/{1}] Cache size: {2}".format(i, u, len(db.interface.cache)), end = endstr)
|
||||
|
||||
print("{0}: {1}".format(pos, db.get_node(pos).get_name()))
|
||||
print("Cache size: {0}".format(len(db.interface.cache)), end = " \r")
|
||||
assert(len(db.interface.cache) <= db.get_maxcachesize())
|
||||
|
||||
print(" -> ~{0:.4f}ms per call to get_node".format((time.time()-s)*1000/u), end = " \n")
|
||||
print(" --> Test successful")
|
||||
|
||||
def testSetNode():
|
||||
db = minetest.MapInterface("./map.sqlite")
|
||||
db = minetest.map.MapInterface("./map.sqlite")
|
||||
f = open("./dump.bin", "w")
|
||||
dummy = minetest.Node("default:nyancat")
|
||||
dummy = minetest.nodes.Node("default:nyancat")
|
||||
s = time.time()
|
||||
u = 100
|
||||
|
||||
for y in range(1, 10):
|
||||
db.set_node(Pos({'x': 0, 'y': y, 'z': 0}), dummy)
|
||||
for y in range(1, u+1):
|
||||
db.set_node(minetest.utils.Pos({'x': 0, 'y': y, 'z': 0}), dummy)
|
||||
|
||||
print(" -> {0} nyan cats placed".format(u))
|
||||
print(" -> {0}ms per call to set_node".format((time.time()-s)/u*1000))
|
||||
s = time.time()
|
||||
db.save()
|
||||
print(" -> database saving took {0}s".format(time.time()-s))
|
||||
print(" --> Test successful")
|
||||
|
||||
def invManip():
|
||||
db = minetest.MapInterface("./map.sqlite")
|
||||
chest = db.get_meta(Pos({'x': 0, 'y': 0, 'z': 0}))
|
||||
#print(chest)
|
||||
db = minetest.map.MapInterface("./map.sqlite")
|
||||
pos = minetest.utils.Pos({'x': 0, 'y': 0, 'z': 0})
|
||||
chest = db.get_meta(pos)
|
||||
inv = chest.get_inventory()
|
||||
#print(inv)
|
||||
#print(chest.get_string("formspec"))
|
||||
#chest.set_string("formspec", chest.get_string("formspec") + "button[0,0;1,0.5;moo;Moo]")
|
||||
#print(chest.get_string("formspec"))
|
||||
print(inv.is_empty("main"))
|
||||
print(inv.get_size("main"))
|
||||
|
||||
db.save()
|
||||
print(" -> Testing inventory in node at {0}".format(pos))
|
||||
print(" ~~> Node's name is {0}".format(db.get_node(pos).get_name()))
|
||||
if inv.is_empty("main"):
|
||||
print(" ~~> Inventory is empty")
|
||||
else:
|
||||
print(" ~~> Inventory is not empty")
|
||||
|
||||
print(" ~~> Size of 'main' list is {0} slots".format(inv.get_size("main")))
|
||||
print(" --> Test successful")
|
||||
|
||||
def testSchematics():
|
||||
# Import from file
|
||||
schem = Schematic("/home/lymkwi/.minetest/games/minetest_game/mods/default/schematics/apple_tree_from_sapling.mts")
|
||||
schem = minetest.schematics.Schematic("/home/lymkwi/.minetest/games/minetest_game/mods/default/schematics/apple_tree_from_sapling.mts")
|
||||
print(" -> Schematic : {0}".format(schem))
|
||||
|
||||
# Export to BytesStream & file
|
||||
print(schem.export().read())
|
||||
assert(schem.export().read())
|
||||
print(" -> Export : OK")
|
||||
s = time.time()
|
||||
schem.export_to_file("test.mts")
|
||||
print(" ~~> File export : {0}s".format(time.time()-s))
|
||||
assert(open("test.mts"))
|
||||
|
||||
# Map export
|
||||
db = minetest.MapInterface("./map.sqlite")
|
||||
schem = db.export_schematic(Pos(), Pos({"x": -100, "y": 10, "z": 100}))
|
||||
db = minetest.map.MapInterface("./map.sqlite")
|
||||
s = time.time()
|
||||
schem = db.export_schematic(minetest.utils.Pos(), minetest.utils.Pos({"x": -100, "y": 10, "z": 100}))
|
||||
s = time.time() - s
|
||||
assert(schem.export().read())
|
||||
print(" -> Schematic exportation : OK")
|
||||
print(" ~~> Exportation took {0}s".format(s))
|
||||
schem.export_to_file("test.mts")
|
||||
|
||||
# Get node
|
||||
print(schem.get_node(Pos({"x": 1, "y": 1, "z": 0})))
|
||||
node = schem.get_node(minetest.utils.Pos({"x": 0, "y": 0, "z": 0})).get_name()
|
||||
assert(node != "")
|
||||
print(" -> Node in (0,0,0) is {0}".format(node))
|
||||
|
||||
# Import
|
||||
s = time.time()
|
||||
db.import_schematic(minetest.utils.Pos({"x": 100, "y": 100, "z": 100}), schem)
|
||||
print(" -> Importation in map took {0}s".format(time.time() - s))
|
||||
|
||||
print(" -> {0} mapblock(s) to be saved".format(len(db.mod_cache)))
|
||||
s = time.time()
|
||||
db.save()
|
||||
print(" -> Saving took {0}s".format(time.time() - s))
|
||||
print(" --> Test successful")
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=> MapBlockLoad")
|
||||
|
||||
print("=> MapBlockLoad Test")
|
||||
s = time.time()
|
||||
testMapBlockLoad()
|
||||
print("=> signed endians")
|
||||
testSignedEndians()
|
||||
print("=> get_node")
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
||||
print("=> Signed Endians")
|
||||
s = time.time()
|
||||
testEndians()
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
||||
print("=> get_node Test")
|
||||
s = time.time()
|
||||
testGetNode()
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
||||
print("=> set_node")
|
||||
s = time.time()
|
||||
testSetNode()
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
||||
print("=> inventory manipulation (WIP)")
|
||||
s = time.time()
|
||||
invManip()
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
||||
print("=> schematic manipulation (WIP)")
|
||||
s = time.time()
|
||||
testSchematics()
|
||||
print(" => Test took {0:.10f}s".format(time.time()-s))
|
||||
|
30
src/utils.py
30
src/utils.py
@ -131,11 +131,27 @@ def writeU16(strm, val):
|
||||
strm.write(bytes(vals))
|
||||
|
||||
def writeU32(strm, val):
|
||||
vals = []
|
||||
for _ in range(4):
|
||||
k = val % 256
|
||||
vals.insert(0, int(k))
|
||||
val -= k
|
||||
val /= 256
|
||||
vals = []
|
||||
for _ in range(4):
|
||||
k = val % 256
|
||||
vals.insert(0, int(k))
|
||||
val -= k
|
||||
val /= 256
|
||||
|
||||
strm.write(bytes(vals))
|
||||
strm.write(bytes(vals))
|
||||
|
||||
class Vector:
|
||||
def add(self, pos1, pos2):
|
||||
return Pos({"x": pos1.x + pos2.x, "y": pos1.y + pos2.y, "z": pos1.z + pos2.z})
|
||||
|
||||
def sub(self, pos1, pos2):
|
||||
return Pos({"x": pos1.x - pos2.x, "y": pos1.y - pos2.y, "z": pos1.z - pos2.z})
|
||||
|
||||
def mult(self, pos, lmbd):
|
||||
return Pos({"x": pos.x * lmbd, "y": pos.y * lmbd, "z": pos.z * lmbd})
|
||||
|
||||
def div(self, pos, lmbd):
|
||||
return self.mult(self, pos, 1/lmbd)
|
||||
|
||||
def round(self, pos):
|
||||
return Pos({"x": round(pos.x), "y": round(pos.y), "z": round(pos.z)})
|
||||
|
Loading…
x
Reference in New Issue
Block a user