python-minetest/inventory.py
LeMagnesium b8cbe3b75b Set_node and mapblock implosion fixed, invref in development
* 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
2016-02-14 21:31:23 +01:00

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])