Source code for bravo.inventory

from itertools import chain

from bravo import blocks
from bravo.beta.structures import Slot

class NextLoop(Exception):
    pass

[docs]class SerializableSlots(object): ''' Base class for all slots configurations ''' def __len__(self): return self.metalength @property def metalength(self): return sum(map(len, self.metalist)) def load_from_list(self, l): if len(l) < self.metalength: # XXX why will it break everything? :T raise AttributeError # otherwise it will break everything for target in self.metalist: if len(target): target[:], l = l[:len(target)], l[len(target):] def save_to_list(self): return [i for i in chain(*self.metalist)]
[docs]class Inventory(SerializableSlots): ''' The class represents Player's inventory ''' def __init__(self): self.armor = [None] * 4 self.crafting = [None] * 27 self.storage = [None] * 27 self.holdables = [None] * 9 self.dummy = [None] * 64 # represents gap in serialized structure
[docs] def add(self, item, quantity): """ Attempt to add an item to the inventory. :param tuple item: a key representing the item :returns: quantity of items that did not fit inventory """ while quantity: try: qty_before = quantity # Try to stack first for stash in (self.holdables, self.storage): for i, slot in enumerate(stash): if slot is not None and slot.holds(item) and slot.quantity < 64 \ and slot.primary not in blocks.unstackable: count = slot.quantity + quantity if count > 64: count, quantity = 64, count - 64 else: quantity = 0 stash[i] = slot.replace(quantity=count) if quantity == 0: return 0 # one more loop for rest of items raise NextLoop # break to outer while loop # try to find empty space for stash in (self.holdables, self.storage): for i, slot in enumerate(stash): if slot is None: stash[i] = Slot(item[0], item[1], quantity) return 0 if qty_before == quantity: # did one loop but was not able to put any of the items break except NextLoop: # used to break out of all 'for' loops pass return quantity
[docs] def consume(self, item, index): """ Attempt to remove a used holdable from the inventory. A return value of ``False`` indicates that there were no holdables of the given type and slot to consume. :param tuple item: a key representing the type of the item :param int slot: which slot was selected :returns: whether the item was successfully removed """ slot = self.holdables[index] # Can't really remove things from an empty slot... if slot is None: return False if slot.holds(item): self.holdables[index] = slot.decrement() return True return False
[docs] def select_armor(self, index, alternate, shift, selected = None): """ Handle a slot selection on an armor slot. :returns tuple: ( True/False, new selection ) """ # Special case for armor slots. allowed_items_per_slot = { 0: blocks.armor_helmets, 1: blocks.armor_chestplates, 2: blocks.armor_leggings, 3: blocks.armor_boots } allowed_items = allowed_items_per_slot[index] if selected is not None: sslot = selected if sslot.primary not in allowed_items: return (False, selected) if self.armor[index] is None: # Put one armor piece into the slot, decrement the amount # in the selection. self.armor[index] = sslot.replace(quantity=1) selected = sslot.decrement() else: # If both slot and selection are the same item, do nothing. # If not, the quantity needs to be 1, because only one item # fits into the slot, and exchanging slot and selection is not # possible otherwise. if not self.armor[index].holds(sslot) and sslot.quantity == 1: selected, self.armor[index] = self.armor[index], selected else: return (False, selected) else: if self.armor[index] is None: # Slot and selection are empty, do nothing. return (False, selected) else: # Move item in the slot into the selection. selected = self.armor[index] self.armor[index] = None # Yeah, okay, success. return (True, selected) # # The methods below are for serialization purposes only. #
@property def metalist(self): # this one is used for serialization return [self.holdables, self.storage, self.dummy, self.armor] def load_from_list(self, l): SerializableSlots.load_from_list(self, l) # reverse armor slots (notchian) self.armor = [i for i in reversed(self.armor)] def save_to_list(self): # save armor tmp_armor = self.armor # reverse armor (notchian) self.armor = [i for i in reversed(self.armor)] # generate the list l = SerializableSlots.save_to_list(self) # restore armor self.armor = tmp_armor return l

Project Versions

This Page