Bump to version 00.00.02

- Map: Rewrite MapVessels and MapInterface. MapVessels do not manage any cache any more, the MapInterface manages StackCaches (new class)
   for cache_history and mod_cache. Those caches replace the old db.interface.cache. The field 'interface' for MapInterfaces is now called 'container'.
   MapInterface.mod_flag is now called MapInterface.flag_mod, and it comes with MapInterface.unflag_mod (in case you need it). MapInterface cannot discard
   changes on mapblocks when unloading them, it will always save them.
 - Utils: Remove intFromPos since you can use Pos.getAsInt(max_val=16). Pos objects are initialized using three integers, not a dict any more
 - Demos: All demos are updated to use new code
This commit is contained in:
LeMagnesium 2016-04-02 20:18:58 +02:00
parent 69db3587b2
commit 59d3891603
9 changed files with 377 additions and 394 deletions

View File

@ -68,10 +68,7 @@ def removeUnknowns():
print("\n[{0:3.2f}%] {1} nodes removed".format(pct, len(unknowns)))
print("[{0:3.2f}%] Saving mapblock {1}".format(pct, absi))
u.store(i, k.implode())
u.write(i)
u.uncache(i)
u.write(i, k.implode())
u.commit()

View File

@ -15,9 +15,9 @@ import libminetest.logger
import libminetest.map
import libminetest.schematics
pos_import = libminetest.utils.Pos({"x": 300, "y": 100, "z": 300})
pos1_export = libminetest.utils.Pos({"x": -10, "y": -10, "z": -10})
pos2_export = libminetest.utils.Pos({"x": 10, "y": 10, "z": 10})
pos_import = libminetest.utils.Pos(300, 100, 300)
pos1_export = libminetest.utils.Pos(-10, -10, -10)
pos2_export = libminetest.utils.Pos(10, 10, 10)
libminetest.logger.init_logging(debug=True)

View File

@ -8,4 +8,4 @@
#
__version__ = "00.00.01"
__version__ = "00.00.02"

View File

@ -28,13 +28,6 @@ DAY_NIGHT_DIFFERS = 2
LIGHTING_EXPIRED = 4
GENERATED = 8
def determineMapBlock(pos):
posx = math.floor(pos.x / 16)
posy = math.floor(pos.y / 16)
posz = math.floor(pos.z / 16)
return Pos({'x': posx, 'y': posy, 'z': posz})
class MapBlock:
def __init__(self, data = None, abspos = 0):
self.abspos = abspos
@ -46,7 +39,7 @@ class MapBlock:
self.nodes = dict()
self.version = 25
self.mapblocksize = 16 # Normally
self.bitmask = 12
self.bitmask = GENERATED & LIGHTING_EXPIRED
self.content_width = 2
self.param_width = 2
self.node_meta = dict()
@ -62,7 +55,8 @@ class MapBlock:
self.node_timers = dict() #u16, s32, s32
for x in range(4096):
self.set_node(x, Node("air"))
# Bypass position verification
self.nodes[x] = Node("air")
self.name_id_mappings = self.create_name_id_mappings()
self.num_name_id_mappings = len(self.name_id_mappings)
@ -191,9 +185,6 @@ class MapBlock:
def add_node(self, mapblockpos, node):
self.set_node(self, mapblockpos, node)
def remove_node(self, mapblockpos):
self.set_node(mapblockpos, Node("air"))
def explode(self, bytelist):
data = BytesIO(bytelist)
@ -387,7 +378,7 @@ class MapBlock:
self.static_objects.append({
"type": otype,
"pos": Pos({'x': pos_x_nodes + self.mapblockpos.x, 'y': pos_y_nodes + self.mapblockpos.y, 'z': pos_z_nodes + self.mapblockpos.z}),
"pos": Pos(pos_x_nodes + self.mapblockpos.x,pos_y_nodes + self.mapblockpos.y, pos_z_nodes + self.mapblockpos.z),
"data": str(odata),
})
@ -419,7 +410,7 @@ class MapBlock:
pos = posFromInt(readU16(data), 16).getAsTuple()
timeout = readS32(data) / 1000
elapsed = readS32(data) / 1000
self.node_timers[pos] = NodeTimerRef(Pos().fromTuple(pos), timeout, elapsed)
self.node_timers[pos] = NodeTimerRef(Pos(0, 0, 0).fromTuple(pos), timeout, elapsed)
for id in range(4096):
itemstring = self.name_id_mappings[node_data["param0"][id]]
@ -439,22 +430,19 @@ class MapBlock:
return self.node_meta.get(abspos) or NodeMetaRef()
"""
MapVessel
"""
class MapVessel:
def __init__(self, mapfile, backend = "sqlite3"):
self.mapfile = mapfile
self.cache = dict()
self.open(mapfile, backend)
def __str__(self):
if self.is_empty():
return "empty mapfile vessel"
else:
return "mapfile vessel for {0}".format(self.mapfile)
return "mapfile vessel for {0}".format(self.mapfile)
def get_all_mapblock_ids(self):
if self.is_empty():
raise EmptyMapVesselError()
try:
self.cur.execute("SELECT \"pos\" from \"blocks\"")
except _sql.OperationalError as err:
@ -462,9 +450,6 @@ class MapVessel:
return [id[0] for id in self.cur.fetchall()]
def is_empty(self):
return self.mapfile == None
def open(self, mapfile, backend = "sqlite3"):
try:
self.conn = _sql.connect(mapfile)
@ -474,17 +459,11 @@ class MapVessel:
def close(self):
self.conn.close()
self.cache = None
self.mapblocks = None
self.mapfile = None
self.cache = dict()
def read(self, blockID):
if self.is_empty():
raise EmptyMapVesselError()
if self.cache.get(blockID):
return False, "dejavu"
try:
self.cur.execute("SELECT * from blocks where pos = {0}".format(blockID))
except _sql.OperationalError as err:
@ -492,68 +471,40 @@ class MapVessel:
data = self.cur.fetchall()
if len(data) == 1:
self.cache[blockID] = data[0][1]
return True, "ok"
else:
return False, "notfound"
logger.debug("Binary blob for mapblock {0} read".format(blockID))
return data[0][1]
def uncache(self, blockID):
if self.is_empty():
raise EmptyMapVesselError()
def load(self, blockID):
data = self.read(blockID)
if not data:
logger.debug("Mapblock {0} not found".format(blockID))
return
self.cache[blockID] = None
del self.cache[blockID]
return True, "ok"
def write(self, blockID):
if self.is_empty():
raise EmptyMapVesselError()
logger.debug("Building mapblock {0} from binary blob".format(blockID))
return MapBlock(data, abspos = blockID)
def write(self, blockID, data):
try:
self.cur.execute("REPLACE INTO `blocks` (`pos`, `data`) VALUES ({0}, ?)".format(blockID),
[self.cache[blockID]])
self.cur.execute("REPLACE INTO `blocks` (`pos`, `data`) VALUES ({0}, ?)".format(blockID), [data])
except _sql.OperationalError as err:
raise MapError(err)
logger.debug("Binary blob for mapblock {0} written".format(blockID))
def commit(self):
logger.debug("Committing on database")
self.conn.commit()
def load(self, blockID):
if self.is_empty():
raise EmptyMapVesselError()
if not self.cache.get(blockID):
res, code = self.read(blockID)
if not res and code == "notfound":
return
elif not res:
return res, code
return MapBlock(self.cache[blockID], abspos = blockID)
def remove(self, blockID):
if self.is_empty():
raise EmptyMapVesselError()
try:
self.cur.execute("DELETE FROM `blocks` WHERE `pos` = ?", [blockID])
except _sql.OperationalError as err:
raise MapError(err)
def store(self, blockID, mapblockData):
if self.is_empty():
raise EmptyMapVesselError()
self.cache[blockID] = mapblockData
logger.debug("Mapblock {0} stored".format(blockID))
return True
def empty_map(self):
"""
Delete the entire map's mapblocks. Also empties the object's cache
Note : Removal of mapblocks in the database after the last commit is reversible until the next call to commit(). Cache vacuuming is irreversible
Delete the entire map's mapblocks
Note : Removal of mapblocks in the database after the last commit is reversible until the next call to commit()
"""
logger.warning("WARNING: Emptying the entire map of its mapblocks")
@ -562,36 +513,56 @@ class MapVessel:
except _sql.OperationalError as err:
raise MapError("Error while removing all mapblock : {0}".format(err))
self.cache = dict()
class StackCache:
def __init__(self):
self.data = []
def __contains__(self, val):
return val in self.data
def __delitem__(self, key):
self.remove(key)
def __getitem__(self, key):
return self.data[key]
def __iter__(self):
return self.data.__iter__()
def __len__(self):
return len(self.data)
def __str__(self):
return str(self.data)
def add(self, elem):
while elem in self.data:
self.data.remove(elem)
self.data.append(elem)
def remove(self, elem):
while elem in self.data:
self.data.remove(elem)
def flush(self, elem):
self.data = []
class MapInterface:
def __init__(self, datafile, backend = "sqlite3"):
self.datafile = datafile
self.interface = MapVessel(datafile, backend)
self.mapblocks = dict()
self.cache_history = []
self.container = MapVessel(datafile, backend)
self.max_cache_size = 100
self.mod_cache = []
self.force_save_on_unload = True
self.mapblocks = dict()
self.cache_history = StackCache()
self.mod_cache = StackCache()
def mod_flag(self, mapblockpos):
if not mapblockpos in self.mod_cache:
self.mod_cache.append(mapblockpos)
def unload_mapblock(self, blockID):
if blockID in self.cache_history:
del self.cache_history[self.cache_history.index(blockID)]
# Cache stuff
def flag_mod(self, mapblockid):
self.mod_cache.add(mapblockid)
if blockID in self.mod_cache:
if not self.force_save_on_unload:
logger.warning("Unloading unsaved mapblock at pos {0}!".format(blockID))
del self.mod_cache[self.mod_cache.index(blockID)]
else:
logger.debug("Unloading and saving mapblock at pos {0}".format(blockID))
self.save_mapblock(blockID)
self.interface.uncache(blockID)
self.mapblocks[blockID] = None
def unflag_mod(self, mapblockid):
self.mod_cache.remove(mapblockid)
def set_maxcachesize(self, size):
if type(size) != type(0):
@ -601,38 +572,62 @@ class MapInterface:
logger.debug("MapVessel's maximum cache size set to {0}".format(size))
self.check_cache()
def check_cache(self):
while len(self.interface.cache) > self.max_cache_size:
self.interface.uncache(self.cache_history[0])
self.unload_mapblock(self.cache_history[0])
def get_maxcachesize(self):
return self.max_cache_size
def check_cache(self):
while len(self.mapblocks) > self.max_cache_size:
logger.debug("Removing mapblock {0} from cache to create space".format(self.cache_history[0]))
self.unload_mapblock(self.cache_history[0])
def flush_cache(self):
self.save()
while len(self.cache_history) > 0:
logger.debug("Removing mapblock {id} for cache flush".format(id=self.cache_history[0]))
self.unload_mapblock(self.cache_history[0])
# Mapblock loading/unloading
def load_mapblock(self, blockID):
self.mapblocks[blockID] = self.interface.load(blockID)
logger.debug("Loaded mapblock at {id}".format(id=blockID))
if not blockID in self.cache_history:
self.cache_history.append(blockID)
self.check_cache()
data = self.container.load(blockID)
if not data:
logger.debug("Mapblock is None")
return False
self.mapblocks[blockID] = data
self.cache_history.add(blockID)
self.check_cache()
return True
def unload_mapblock(self, blockID):
if blockID in self.mod_cache:
logger.debug("Unloading and saving mapblock at pos {0}".format(blockID))
self.save_mapblock(blockID)
self.cache_history.remove(blockID)
del self.mapblocks[blockID]
def save_mapblock(self, blockID):
if not self.mapblocks.get(blockID):
return False
logger.debug("Saving block at pos {0} {1}".format(blockID, posFromInt(blockID, 4096)))
self.interface.store(blockID, self.mapblocks[blockID].implode())
self.interface.write(blockID)
del self.mod_cache[self.mod_cache.index(blockID)]
self.container.write(blockID, self.mapblocks[blockID].implode())
self.mod_cache.remove(blockID)
return True
def init_mapblock(self, mapblockpos):
logger.debug("Init mapblock at {0}".format(str(mapblockpos)))
self.mapblocks[mapblockpos] = MapBlock(abspos = mapblockpos)
self.mod_cache.add(mapblockpos)
self.cache_history.add(mapblockpos)
# Node interface stuff
def check_for_pos(self, mapblockpos):
if not self.mapblocks.get(mapblockpos):
self.load_mapblock(mapblockpos)
if not self.mapblocks.get(mapblockpos):
self.unload_mapblock(mapblockpos)
return False
return self.load_mapblock(mapblockpos)
return True
@ -642,59 +637,46 @@ class MapInterface:
if not self.check_for_pos(mapblockpos):
return Node("ignore", pos = pos)
return self.mapblocks[mapblockpos].get_node((pos.x % 16) + (pos.y % 16) * 16 + (pos.z % 16) * 16 * 16)
return self.mapblocks[mapblockpos].get_node(pos.getAsInt())
def set_node(self, pos, node):
mapblock = determineMapBlock(pos)
mapblockpos = getMapBlockPos(mapblock)
if not self.check_for_pos(mapblockpos):
raise IgnoreContentReplacementError("Pos: " + str(pos))
raise IgnoreContentReplacementError("Pos: {0}".format(pos))
node.pos = pos
self.mod_flag(mapblockpos)
self.flag_mod(mapblockpos)
return self.mapblocks[mapblockpos].set_node((pos.x % 16) + (pos.y % 16) * 16 + (pos.z % 16) * 16 * 16, node)
return self.mapblocks[mapblockpos].set_node(pos.getAsInt(), node)
def remove_node(self, pos):
mapblock = determineMapBlock(pos)
mapblockpos = getMapBlockPos(mapblock)
if not self.check_for_pos(mapblockpos):
return
return self.mapblocks[mapblockpos].remove_node((pos.x % 16) + (pos.y % 16) * 16 + (pos.z % 16) * 16 * 16, node)
def save(self):
logger.debug("Saving..")
while len(self.mod_cache) > 0:
logger.debug("{0} mapblocks left to save".format(len(self.mod_cache)))
self.save_mapblock(self.mod_cache[0])
self.interface.commit()
return self.set_node(self, pos, Node("air"))
def get_meta(self, pos):
mapblock = determineMapBlock(pos)
mapblockpos = getMapBlockPos(mapblock)
self.mod_flag(mapblockpos)
self.flag_mod(mapblockpos) # Just in case, we don't know if metadata will be modified
if not self.check_for_pos(mapblockpos):
return NodeMetaRef()
return self.mapblocks[mapblockpos].get_meta(intFromPos(pos, 16))
return self.mapblocks[mapblockpos].get_meta(pos.getAsInt())
# The schematics stuff
def export_schematic(self, startpos, endpos, forceplace = True):
# Get the corners first
spos = Pos({"x": min(startpos.x, endpos.x), "y": min(startpos.y, endpos.y), "z": min(startpos.z, endpos.z)})
epos = Pos({"x": max(startpos.x, endpos.x), "y": max(startpos.y, endpos.y), "z": max(startpos.z, endpos.z)})
minpos = Pos(min(startpos.x, endpos.x), min(startpos.y, endpos.y), min(startpos.z, endpos.z))
maxpos = Pos(max(startpos.x, endpos.x), max(startpos.y, endpos.y), max(startpos.z, endpos.z))
schem = {}
schem["size"] = {"x": epos.x - spos.x, "y": epos.y - spos.y, "z": epos.z - spos.y}
schem["size"] = {"x": maxpos.x - minpos.x, "y": maxpos.y - minpos.y, "z": maxpos.z - minpos.y}
schem["data"] = {}
for x in range(schem["size"]["x"]):
for y in range(schem["size"]["y"]):
for z in range(schem["size"]["z"]):
schem["data"][x + (y * schem["size"]["x"]) + (z * schem["size"]["y"] * schem["size"]["x"])] = {
"name": self.get_node(Pos({"x": spos.x + x, "y": spos.y + y, "z": spos.z + z})).get_name(),
"name": self.get_node(Pos(minpos.x + x, minpos.y + y, minpos.z + z)).get_name(),
"prob": 255,
"force_place": forceplace
}
@ -711,7 +693,7 @@ class MapInterface:
for x in range(schematic.size["x"]):
for z in range(schematic.size["z"]):
v = Vector()
rpos = Pos({"x": x, "y": y, "z": z})
rpos = Pos(x, y, z)
pct = (1 + z + (x * schematic.size["z"]) + (y * schematic.size["z"] * schematic.size["x"])) / k * 100
node = schematic.get_node(rpos)
vpos = v.add(pos, rpos)
@ -724,22 +706,20 @@ class MapInterface:
except IgnoreContentReplacementError:
self.init_mapblock(getMapBlockPos(determineMapBlock(v.add(pos, rpos))))
continue
logger.debug(pctstr)
if stage_save and int(pct/stage_save) != tenth:
tenth = int(pct/stage_save)
logger.debug("Saving partial import at {0:3.5f}%..".format(pct))
logger.debug("{0} mapblocks to save".format(len(self.mod_cache)))
self.save()
logger.debug("Committing on database..")
self.interface.commit()
logger.debug(pctstr)
if stage_save and int(pct/stage_save) != tenth:
tenth = int(pct/stage_save)
logger.debug("Saving partial import at {0:3.5f}%..".format(pct))
logger.debug("{0} mapblocks to save".format(len(self.mod_cache)))
self.save()
def init_mapblock(self, mapblockpos, override = False):
res = self.interface.load(mapblockpos)
if (not res) or override:
m = MapBlock(abspos = mapblockpos)
abspos = mapblockpos
self.interface.store(mapblockpos, m.implode())
self.interface.write(mapblockpos)
self.interface.load(mapblockpos)
# Method to save
def save(self):
logger.debug("Saving..")
while len(self.mod_cache) > 0:
logger.debug("{0} mapblocks left to save".format(len(self.mod_cache)))
u = self.mod_cache[0]
self.save_mapblock(u)
self.unload_mapblock(u)
logger.debug("Init mapblock at {0}".format(str(mapblockpos)))
self.container.commit()

View File

@ -23,7 +23,7 @@ class NodeMetaRef:
"""
self.data = meta or dict()
self.pos = spos or Pos()
self.pos = spos or Pos(0, 0, 0)
self.inv = inv or InvRef()
def get_raw(self, key):

View File

@ -9,7 +9,7 @@
from .utils import Pos
class NodeTimerRef:
def __init__(self, pos = Pos(), timeout = 0.0, elapsed = 0.0):
def __init__(self, pos = Pos(0, 0, 0), timeout = 0.0, elapsed = 0.0):
self.pos = pos
self.timeout = timeout
self.elapsed = elapsed
@ -35,7 +35,7 @@ class NodeTimerRef:
return self.active
class Node:
def __init__(self, itemstring, param1 = 0, param2 = 0, pos = Pos()):
def __init__(self, itemstring, param1 = 0, param2 = 0, pos = Pos(0, 0, 0)):
self.pos = pos
self.itemstring = itemstring
self.param1, self.param2 = param1, param2

View File

@ -7,6 +7,7 @@
#
from io import BytesIO
from math import floor
def posFromInt(pos, blocksize):
posx, posy = 0, 0
@ -19,14 +20,7 @@ def posFromInt(pos, blocksize):
pos -= posy
pos = int(pos/blocksize)
return Pos({'x': posx, 'y': posy, 'z': pos})
def intFromPos(pos, blocksize):
posint = 0
posint += pos.x
posint += pos.y * blocksize
posint += pos.z * blocksize * blocksize
return posint
return Pos(posx, posy, pos)
def int64(u):
while u >= 2**63:
@ -38,6 +32,14 @@ def int64(u):
def getMapBlockPos(pos):
return pos.z * 4096 * 4096 + pos.y * 4096 + pos.x
def determineMapBlock(pos):
posx = floor(pos.x / 16)
posy = floor(pos.y / 16)
posz = floor(pos.z / 16)
return Pos(posx, posy, posz)
def getIntegerAsBlock(i):
x = unsignedToSigned(i % 4096, 2048)
i = int((i - x) / 4096)
@ -45,7 +47,7 @@ def getIntegerAsBlock(i):
i = int((i - y) / 4096)
z = unsignedToSigned(i % 4096, 2048)
i = int((i - z) / 4096)
return Pos({"x": x, "y": y, "z": z})
return Pos(x, y, z)
def unsignedToSigned(i, max_positive):
if i < max_positive:
@ -54,11 +56,10 @@ def unsignedToSigned(i, max_positive):
return i - 2*max_positive
class Pos:
def __init__(self, posdict = {"x": 0, "y": 0, "z": 0}):
self.dict = posdict
self.x = posdict.get("x") or 0
self.y = posdict.get("y") or 0
self.z = posdict.get("z") or 0
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return "({0}, {1}, {2})".format(self.x, self.y, self.z)
@ -70,7 +71,7 @@ class Pos:
return self.x == other.x and self.y == other.y and self.z == other.z
def getAsInt(self, max_val = 16):
return int64(self.z * max_val * max_val + self.y * max_val + self.x)
return int64((self.z % max_val) * max_val * max_val + (self.y % max_val) * max_val + (self.x % max_val))
def getAsTuple(self):
return (self.x, self.y, self.z)
@ -80,10 +81,9 @@ class Pos:
return False
self.x, self.y, self.z = tup[0], tup[1], tup[2]
self.dict = {'x': self.x, 'y': self.y, 'z': self.z}
return self
# Thanks to @gravgun/elementW for those
# Thanks to @gravgun/ElementW for those.
# Big-endian!!!
def readU8(strm):
return (ord(strm.read(1)))
@ -142,16 +142,16 @@ def writeU32(strm, val):
class Vector:
def add(self, pos1, pos2):
return Pos({"x": pos1.x + pos2.x, "y": pos1.y + pos2.y, "z": pos1.z + pos2.z})
return Pos(pos1.x + pos2.x, pos1.y + pos2.y, 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})
return Pos(pos1.x - pos2.x, pos1.y - pos2.y, pos1.z - pos2.z)
def mult(self, pos, lmbd):
return Pos({"x": pos.x * lmbd, "y": pos.y * lmbd, "z": pos.z * lmbd})
return Pos(pos.x * lmbd, pos.y * lmbd, 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)})
return Pos(round(pos.x), round(pos.y), round(pos.z))

View File

@ -2,7 +2,7 @@ from setuptools import setup
setup(
name="libminetest",
version="0.0.1",
version="0.0.2",
author="LeMagnesium",
author_email="mg<dot>minetest<at>gmail<dot>com",
packages=['libminetest'],

View File

@ -17,269 +17,275 @@ import sys
from io import BytesIO
def testMapBlockLoad(map):
file = libminetest.map.MapVessel(map)
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")
file = libminetest.map.MapVessel(map)
for i in range(-4096, 4096):
res = file.read(i)
if not res:
continue
else:
mapb = libminetest.map.MapBlock(res, abspos = i)
print("Read and loaded {0}: {1}".format(i, mapb), end = " \r")
print(" -> There are in total {0} mapblocks in the map".format(len(file.get_all_mapblock_ids())), end = (' ' * 20) + '\n')
print(" --> Test successful")
print(" -> There are in total {0} mapblocks in the map".format(len(file.get_all_mapblock_ids())), end = (' ' * 25) + '\n')
print(" --> Test successful")
def testEndians():
assert(libminetest.utils.readS8(BytesIO(b"\xf8")) == -8)
print(" -> readS8: OK")
assert(libminetest.utils.readS16(BytesIO(b"\x9f\xff")) == -24577)
print(" -> readS16: OK")
assert(libminetest.utils.readS32(BytesIO(b"\xf0\x00\x00\x00")) == -268435456)
print(" -> readS32: OK")
assert(libminetest.utils.readS8(BytesIO(b"\xf8")) == -8)
print(" -> readS8: OK")
assert(libminetest.utils.readS16(BytesIO(b"\x9f\xff")) == -24577)
print(" -> readS16: OK")
assert(libminetest.utils.readS32(BytesIO(b"\xf0\x00\x00\x00")) == -268435456)
print(" -> readS32: OK")
assert(libminetest.utils.readU8(BytesIO(b"\xf8")) == 248)
print(" -> readU8: OK")
assert(libminetest.utils.readU16(BytesIO(b"\x9f\xff")) == 40959)
print(" -> readU16: OK")
assert(libminetest.utils.readU32(BytesIO(b"\xf0\x00\x00\x00")) == 4026531840)
print(" -> readU32: OK")
assert(libminetest.utils.readU8(BytesIO(b"\xf8")) == 248)
print(" -> readU8: OK")
assert(libminetest.utils.readU16(BytesIO(b"\x9f\xff")) == 40959)
print(" -> readU16: OK")
assert(libminetest.utils.readU32(BytesIO(b"\xf0\x00\x00\x00")) == 4026531840)
print(" -> readU32: OK")
print(" --> Test successful")
print(" --> Test successful")
def testGetNode(map):
db = libminetest.map.MapInterface(map)
db = libminetest.map.MapInterface(map)
u = random.randint(500, 2000)
k = random.randint(40,400)
u = random.randint(500, 2000)
k = random.randint(40,150)
db.set_maxcachesize(k)
print(" -> Maximum cache size set to {0} mapblocks".format(k))
db.set_maxcachesize(k)
print(" -> Maximum cache size set to {0} mapblocks".format(k))
s = time.time()
for i in range(u):
pos = libminetest.utils.Pos({'x': random.randint(-300, 300), 'y': random.randint(-300, 300), 'z': random.randint(-300, 300)})
assert(db.get_node(pos).get_name() != "")
s = time.time()
for i in range(u):
pos = libminetest.utils.Pos(random.randint(-300, 300), random.randint(-300, 300), 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"
if len(db.mapblocks) == 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}] Cache size: {2}".format(i, u, len(db.mapblocks)), end = endstr)
assert(len(db.interface.cache) <= db.get_maxcachesize())
assert(len(db.mapblocks) <= db.get_maxcachesize())
print(" -> ~{0:.4f}ms per call to get_node".format((time.time()-s)*1000/u), end = " \n")
print(" --> Test successful")
print(" -> ~{0:.4f}ms per call to get_node".format((time.time()-s)*1000/u), end = " \n")
print(" --> Test successful")
def testSetNode(map):
db = libminetest.map.MapInterface(map)
f = open("./dump.bin", "w")
dummy = libminetest.nodes.Node("default:nyancat")
s = time.time()
u = 100
db = libminetest.map.MapInterface(map)
f = open("./dump.bin", "w")
dummy = libminetest.nodes.Node("default:nyancat")
s = time.time()
u = 100
for y in range(1, u+1):
db.set_node(libminetest.utils.Pos({'x': 0, 'y': y, 'z': 0}), dummy)
for y in range(1, u+1):
try:
db.set_node(libminetest.utils.Pos(0, y, 0), dummy)
except libminetest.errors.IgnoreContentReplacementError:
pass
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")
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(map):
db = libminetest.map.MapInterface(map)
pos = libminetest.utils.Pos({'x': 0, 'y': 0, 'z': 0})
chest = db.get_meta(pos)
inv = chest.get_inventory()
db = libminetest.map.MapInterface(map)
pos = libminetest.utils.Pos(0, 0, 0)
chest = db.get_meta(pos)
inv = chest.get_inventory()
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(" -> 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")
print(" ~~> Size of 'main' list is {0} slots".format(inv.get_size("main")))
print(" --> Test successful")
def testSchematics(map):
# Import from file
schem = libminetest.schematics.Schematic(os.environ["HOME"] + "/.minetest/games/minetest_game/mods/default/schematics/apple_tree_from_sapling.mts")
print(" -> Schematic : {0}".format(schem))
# Import from file
schem = libminetest.schematics.Schematic(os.environ["HOME"] + "/.minetest/games/minetest_game/mods/default/schematics/apple_tree_from_sapling.mts")
print(" -> Schematic : {0}".format(schem))
# Export to BytesStream & file
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"))
# Export to BytesStream & file
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 = libminetest.map.MapInterface(map)
s = time.time()
schem = db.export_schematic(libminetest.utils.Pos(), libminetest.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")
# Map export
db = libminetest.map.MapInterface(map)
s = time.time()
schem = db.export_schematic(libminetest.utils.Pos(0, 0, 0), libminetest.utils.Pos(-100, 10, 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
node = schem.get_node(libminetest.utils.Pos({"x": 0, "y": 0, "z": 0})).get_name()
assert(node != "")
print(" -> Node in (0,0,0) is {0}".format(node))
# Get node
node = schem.get_node(libminetest.utils.Pos(0, 0, 0)).get_name()
assert(node != "")
print(" -> Node in (0,0,0) is {0}".format(node))
# Import
s = time.time()
db.import_schematic(libminetest.utils.Pos({"x": 100, "y": 100, "z": 100}), schem)
print(" -> Importation in map took {0}s".format(time.time() - s))
# Import
s = time.time()
db.import_schematic(libminetest.utils.Pos(100, 100, 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")
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")
def testMapBlockInit(map):
# Open the db
db = libminetest.map.MapInterface(map)
# Open the db
db = libminetest.map.MapInterface(map)
# Override
print(" -> Init mapblock at (0,0,0)")
db.init_mapblock(0, override = True)
# Override
print(" -> Init mapblock at (0,0,0)")
db.init_mapblock(0)
print(" -> Saving..")
db.save()
db.unload_mapblock(0)
print(" -> Saving..")
db.save()
# Seek node at (0,0,0)
print(" -> Assertion about node at (0,0,0)")
assert(db.get_node(libminetest.utils.Pos()).get_name() == "air")
print(" -> Assertion succeeded")
print(" --> Test successful")
# Seek node at (0,0,0)
print(" -> Assertion about node at (0,0,0)")
assert(db.get_node(libminetest.utils.Pos(0, 0, 0)).get_name() == "air")
print(" -> Assertion succeeded")
print(" --> Test successful")
def testConfiguration():
# Open the file
dir = os.environ["HOME"] + "/.minetest/worlds/world"
print(" -> Testing world configuration first")
print(" ~~> Trying to open {0}(/world.mt)".format(dir))
conf = libminetest.config.Configuration.open_world(dir)
if not conf:
print("=> No conf found")
return
# Open the file
dir = os.environ["HOME"] + "/.minetest/worlds/world"
print(" -> Testing world configuration first")
print(" ~~> Trying to open {0}(/world.mt)".format(dir))
conf = libminetest.config.Configuration.open_world(dir)
if not conf:
print("=> No conf found")
return
print(" ~~> The world's backend is {0}".format(conf["backend"]))
print(" ~~> There are {0} configuration keys in the file".format(len(conf)))
if "load_mod_mesecon" in conf and conf["load_mod_mesecon"]:
print(" ~~> You have mesecon installed and set to be loaded")
else:
print(" ~~> You do not have mesecon installed, or it is disabled")
print(" ~~> The world's backend is {0}".format(conf["backend"]))
print(" ~~> There are {0} configuration keys in the file".format(len(conf)))
if "load_mod_mesecon" in conf and conf["load_mod_mesecon"]:
print(" ~~> You have mesecon installed and set to be loaded")
else:
print(" ~~> You do not have mesecon installed, or it is disabled")
print(" -> Testing libminetest.conf second")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
if not conf:
print(" ~~> File not opened")
return
print(" -> Testing libminetest.conf second")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
if not conf:
print(" ~~> File not opened")
return
print(" ~~> The admin's name is {0}".format(conf["name"] or "unknown"))
print(" ~~> The last server you joined was at {0}:{1}".format(conf["address"], conf["port"] or '?????'))
print(" ~~> The last selected world is located at {0}".format(conf["selected_world_path"]))
print(" ~~> The admin's name is {0}".format(conf["name"] or "unknown"))
print(" ~~> The last server you joined was at {0}:{1}".format(conf["address"], conf["port"] or '?????'))
print(" ~~> The last selected world is located at {0}".format(conf["selected_world_path"]))
print(" -> Checking write abilities.. ")
fixed_map_seed = random.randint(0, 100000000)
conf["fixed_map_seed"] = fixed_map_seed
print(" ~~> Fixed map seed to {0}".format(fixed_map_seed))
print(" -> Checking write abilities.. ")
fixed_map_seed = random.randint(0, 100000000)
conf["fixed_map_seed"] = fixed_map_seed
print(" ~~> Fixed map seed to {0}".format(fixed_map_seed))
assert(conf.write())
print(" ~~> Configuration written")
assert(conf.write())
print(" ~~> Configuration written")
conf = None
print(" ~~> Object thrown away")
newconf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
print(" ~~> Checking fixed_map_seed...")
print(" ~~> fixed_map_seed = {0}".format(newconf["fixed_map_seed"]))
assert(newconf["fixed_map_seed"] == fixed_map_seed)
print(" ~~> Assertion passed")
newconf = None
conf = None
print(" ~~> Object thrown away")
newconf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
print(" ~~> Checking fixed_map_seed...")
print(" ~~> fixed_map_seed = {0}".format(newconf["fixed_map_seed"]))
assert(newconf["fixed_map_seed"] == fixed_map_seed)
print(" ~~> Assertion passed")
newconf = None
print(" ~~> Checking item removal")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
name = conf["name"]
del conf["name"]
conf.write()
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
assert(not conf["name"])
print(" ~~> Item 'name' removed correctly")
conf = None
print(" ~~> Checking item removal")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
name = conf["name"]
if name:
del conf["name"]
conf.write()
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
assert(not conf["name"])
print(" ~~> Item 'name' removed correctly")
conf = None
else:
print(" ~~> No 'name' key found")
name = "celeron55"
print(" ~~> Checking item insertion")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
conf["name"] = name
conf.write()
conf = None
print(" ~~> Name inserted back")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
print(" ~~> Name is '{}'".format(conf["name"]))
assert(conf["name"] == name)
print(" ~~> Assertion passed")
conf = None
print(" ~~> Checking item insertion")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
conf["name"] = name
conf.write()
conf = None
print(" ~~> Name inserted back")
conf = libminetest.config.Configuration(os.environ["HOME"] + "/.minetest/minetest.conf")
print(" ~~> Name is '{}'".format(conf["name"]))
assert(conf["name"] == name)
print(" ~~> Assertion passed")
conf = None
print(" --> Test successful")
print(" --> Test successful")
def main(map):
print("=> Tests will begin now")
time.sleep(3)
print("=> Tests will begin now")
time.sleep(3)
print("=> MapBlockLoad Test")
s = time.time()
testMapBlockLoad(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> MapBlockLoad Test")
s = time.time()
testMapBlockLoad(map)
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("=> Signed Endians")
s = time.time()
testEndians()
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> get_node Test")
s = time.time()
testGetNode(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> get_node Test")
s = time.time()
testGetNode(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> set_node")
s = time.time()
testSetNode(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> set_node")
s = time.time()
testSetNode(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> inventory manipulation (WIP)")
s = time.time()
invManip(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> inventory manipulation (WIP)")
s = time.time()
invManip(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> schematic manipulation")
s = time.time()
testSchematics(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> schematic manipulation")
s = time.time()
testSchematics(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> MapBlock init")
s = time.time()
testMapBlockInit(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> MapBlock init")
s = time.time()
testMapBlockInit(map)
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> Configuration Test (WIP)")
s = time.time()
testConfiguration()
print(" => Test took {0:.10f}s".format(time.time()-s))
print("=> Configuration Test (WIP)")
s = time.time()
testConfiguration()
print(" => Test took {0:.10f}s".format(time.time()-s))
if __name__ == "__main__":
if not len(sys.argv) >= 2:
print("Please give the path to a map file")
else:
main(sys.argv[1])
if not len(sys.argv) >= 2:
print("Please give the path to a map file")
else:
main(sys.argv[1])