* Inventory: Two functions added : is_empty(listname) and get_size(listname), both working in a similar fashion as their minetest API counterpart * Map: - Implosion fixed. The num_name_id_mappings variable is correctly set, all data are written to the correct byte streams. A function is added to check whether a position given to a function (list get/set_node) is correct and the mapblock is loaded. - Data storage type for static object data fixed - MapBlocks now have a get_meta(abspos) method. Abspos is the integer representing the position of the querried metadata inside the mapblock - MapVessels default to forcefully save a flagged mapblock before unloading it - A new method in MapInterface can flag a mapblock as modified. It is used in member methods to deal with the modification cache flags more easily - MapInterface has got another new function to check whether a mapblock is loaded or not and try to load it, all depending on a given position - MapInterface's save method is fixed - MapInterfaces can return a node's metadata using the get_meta(pos) method. It determines what mapblock contains the quierried node, and use the said mapblock's get_meta method to return a NodeMetaRef object * Metadata : Strings are stored as and decoded from arrays of integers, easier to convert from bytes without knowing what is float, what is int, and what is string * Nodes : The position argument in a Node object is now a key argument. The only mandatory parameter is the itemstring * Test : testSetNode now completly working. It doesn't change the node in (0,0,0) anymore. This node is a chest in the test map and is used to test metadata and inventory manipulation in the new invManip function called upon execution of test.py
149 lines
3.8 KiB
Python
149 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
# -*- encoding: utf8 -*-
|
|
###########################
|
|
## Inventory for Python-MT
|
|
##
|
|
##
|
|
#
|
|
|
|
from io import StringIO
|
|
|
|
from errors import InventoryDeserializationError
|
|
from utils import readU8
|
|
|
|
def getSerializedInventory(strm):
|
|
# serialized inventory
|
|
inv = "".join([chr(readU8(strm)) for _ in range(len(b"EndInventory\n"))])
|
|
while not "EndInventory\n" in inv:
|
|
inv += chr(readU8(strm))
|
|
|
|
return inv
|
|
|
|
|
|
def deserializeInventory(serializat):
|
|
newlists = {}
|
|
lines = serializat.split('\n')
|
|
expectation = 0
|
|
current_listname = ""
|
|
expected_type = None
|
|
|
|
for line in lines:
|
|
params = line.split(' ')
|
|
|
|
if params[0] == "":
|
|
# EOF
|
|
break
|
|
|
|
elif params[0] == "List":
|
|
newlists[params[1]] = {}
|
|
expectation = int(params[2])
|
|
expected_type = "ItemStack"
|
|
current_listname = params[1]
|
|
|
|
elif params[0] == "Width":
|
|
if expected_type == "ItemStack":
|
|
continue
|
|
|
|
elif params[0] == "Empty" or params[0] == "Item":
|
|
if expectation > 0:
|
|
expectation -= 1
|
|
else:
|
|
raise InventoryDeserializationError("Unexpected Item (line {0})".format(lines.index(line)+1))
|
|
|
|
newlists[current_listname][expectation] = ItemStack(" ".join(params[1:]))
|
|
|
|
elif params[0] == "EndInventoryList":
|
|
if expectation > 0:
|
|
raise InventoryDeserializationError("Too few items for list {0}".format(current_listname))
|
|
|
|
expected_type = "ItemStack"
|
|
|
|
# Reverse everything
|
|
new_current_list = dict()
|
|
new_current_list_size = len(newlists[current_listname])
|
|
for i in newlists[current_listname]:
|
|
new_current_list[new_current_list_size - i - 1] = newlists[current_listname][i]
|
|
|
|
newlists[current_listname] = new_current_list
|
|
current_listname = ""
|
|
|
|
return newlists
|
|
|
|
|
|
|
|
class ItemStack:
|
|
def __init__(self, deft):
|
|
if not deft or deft == "":
|
|
self.name = ""
|
|
self.count = 0
|
|
|
|
elif type(deft) == type("str"):
|
|
self.deserialize(deft)
|
|
|
|
elif type(deft) == type({}):
|
|
self.name = deft["name"]
|
|
self.count = deft["count"]
|
|
|
|
def deserialize(self, serializat):
|
|
params = serializat.split(' ')
|
|
self.name = params[0]
|
|
if len(params) > 1:
|
|
self.count = int(params[1])
|
|
else:
|
|
self.count = 0
|
|
|
|
def get_name(self):
|
|
return self.name
|
|
|
|
def get_count(self):
|
|
return self.count
|
|
|
|
|
|
class InvRef:
|
|
def __init__(self, fields = {}):
|
|
self.lists = fields
|
|
|
|
def from_string(self, serializat):
|
|
self.lists = deserializeInventory(serializat)
|
|
|
|
def from_list(self, lists):
|
|
self.lists = lists
|
|
|
|
def to_string(self):
|
|
data = StringIO("")
|
|
|
|
for list_name in self.lists:
|
|
data.write("List {0} {1}\n".format(list_name, len(self.lists[list_name])))
|
|
data.write("Width 0\n")
|
|
|
|
for id in range(len(self.lists[list_name])):
|
|
stack = self.lists[list_name].get(id)
|
|
if stack.get_name() == "":
|
|
data.write("Empty\n")
|
|
else:
|
|
data.write("Item {0} {1}\n".format(stack.get_name(), stack.get_count()))
|
|
|
|
data.write("EndInventoryList\n")
|
|
|
|
|
|
data.write("EndInventory\n")
|
|
|
|
return data.getvalue()
|
|
|
|
# Some stuff from MT
|
|
def is_empty(self, listname):
|
|
if not self.lists.get(listname):
|
|
return True
|
|
|
|
for stack in self.lists[listname].values():
|
|
if stack.get_name() != "":
|
|
return False
|
|
|
|
return True
|
|
|
|
def get_size(self, listname):
|
|
if not self.lists.get(listname):
|
|
return 0
|
|
else:
|
|
return len(self.lists[listname])
|