make inventory maps proxy items and containers propxy inventories
This commit is contained in:
parent
b09b07d172
commit
d9b3c4500e
|
@ -1,7 +1,10 @@
|
|||
from typing import Union
|
||||
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.orm import base as sa_base
|
||||
|
||||
from ttfrog.db.schema.inventory import Inventory, InventoryType
|
||||
from ttfrog.db.schema.inventory import Inventory, InventoryMap, InventoryType
|
||||
from ttfrog.db.schema.item import Item, ItemType
|
||||
|
||||
__all__ = [
|
||||
|
@ -19,3 +22,14 @@ class Container(Item):
|
|||
lazy="immediate",
|
||||
default_factory=lambda: Inventory(inventory_type=InventoryType.EQUIPMENT),
|
||||
)
|
||||
|
||||
def __contains__(self, obj: Union[InventoryMap, Item]):
|
||||
return obj in self.inventory
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.inventory
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name == sa_base.DEFAULT_STATE_ATTR:
|
||||
raise AttributeError()
|
||||
return getattr(self.inventory, name)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from typing import List
|
||||
from typing import List, Union
|
||||
|
||||
from sqlalchemy import ForeignKey, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.orm import base as sa_base
|
||||
|
||||
from ttfrog.db.base import BaseObject, EnumField
|
||||
from ttfrog.db.schema.item import Item, ItemProperty, ItemType
|
||||
|
@ -32,77 +33,6 @@ def inventory_map_creator(fields):
|
|||
return InventoryMap(**fields)
|
||||
|
||||
|
||||
class Inventory(BaseObject):
|
||||
__tablename__ = "inventory"
|
||||
__table_args__ = (UniqueConstraint("character_id", "container_id", "inventory_type"),)
|
||||
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
|
||||
inventory_type: Mapped[InventoryType] = mapped_column(nullable=False)
|
||||
|
||||
item_map: Mapped[List["InventoryMap"]] = relationship(
|
||||
uselist=True, cascade="all,delete,delete-orphan", lazy="immediate", default_factory=lambda: []
|
||||
)
|
||||
|
||||
character_id: Mapped[int] = mapped_column(ForeignKey("character.id"), nullable=True, default=None)
|
||||
container_id: Mapped[int] = mapped_column(ForeignKey("item.id"), nullable=True, default=None)
|
||||
|
||||
character = relationship("Character", init=False, viewonly=True, lazy="immediate")
|
||||
container = relationship("Item", init=False, viewonly=True, lazy="immediate")
|
||||
|
||||
@property
|
||||
def items(self):
|
||||
return [mapping.item for mapping in self.item_map]
|
||||
|
||||
@property
|
||||
def all_items(self):
|
||||
def inventory_contents(inventory):
|
||||
for mapping in inventory.item_map:
|
||||
yield mapping
|
||||
if mapping.item.item_type == ItemType.CONTAINER:
|
||||
yield from inventory_contents(mapping.item.inventory)
|
||||
yield from inventory_contents(self)
|
||||
|
||||
@property
|
||||
def all_item_maps(self):
|
||||
def inventory_map(inventory):
|
||||
for mapping in inventory.item_map:
|
||||
yield mapping
|
||||
if mapping.item.item_type == ItemType.CONTAINER:
|
||||
yield from inventory_map(mapping.item.inventory)
|
||||
yield from inventory_map(self)
|
||||
|
||||
def get(self, item):
|
||||
return self.get_all(item)[0]
|
||||
|
||||
def get_all(self, item):
|
||||
return [mapping for mapping in self.all_item_maps if mapping.item == item]
|
||||
|
||||
def add(self, item):
|
||||
if item.item_type not in inventory_type_map[self.inventory_type]:
|
||||
return False
|
||||
mapping = InventoryMap(inventory_id=self.id, item_id=item.id)
|
||||
if item.consumable:
|
||||
mapping.count = item.count
|
||||
if item.charges:
|
||||
mapping.charges = [Charge(inventory_map_id=mapping.id) for i in range(item.charges)]
|
||||
self.item_map.append(mapping)
|
||||
return mapping
|
||||
|
||||
def remove(self, mapping):
|
||||
if mapping in self.item_map:
|
||||
self.item_map.remove(mapping)
|
||||
return True
|
||||
return False
|
||||
|
||||
def __contains__(self, obj):
|
||||
for item in self.all_items:
|
||||
if item == obj:
|
||||
return True
|
||||
return False
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.all_items
|
||||
|
||||
|
||||
class InventoryMap(BaseObject):
|
||||
__tablename__ = "inventory_map"
|
||||
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
|
||||
|
@ -215,6 +145,84 @@ class InventoryMap(BaseObject):
|
|||
self.attuned = False
|
||||
return True
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name == sa_base.DEFAULT_STATE_ATTR:
|
||||
raise AttributeError()
|
||||
return getattr(self.item, name)
|
||||
|
||||
class Inventory(BaseObject):
|
||||
__tablename__ = "inventory"
|
||||
__table_args__ = (UniqueConstraint("character_id", "container_id", "inventory_type"),)
|
||||
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
|
||||
inventory_type: Mapped[InventoryType] = mapped_column(nullable=False)
|
||||
|
||||
item_map: Mapped[List["InventoryMap"]] = relationship(
|
||||
uselist=True, cascade="all,delete,delete-orphan", lazy="immediate", default_factory=lambda: []
|
||||
)
|
||||
|
||||
character_id: Mapped[int] = mapped_column(ForeignKey("character.id"), nullable=True, default=None)
|
||||
container_id: Mapped[int] = mapped_column(ForeignKey("item.id"), nullable=True, default=None)
|
||||
|
||||
character = relationship("Character", init=False, viewonly=True, lazy="immediate")
|
||||
container = relationship("Item", init=False, viewonly=True, lazy="immediate")
|
||||
|
||||
@property
|
||||
def items(self):
|
||||
return [mapping.item for mapping in self.item_map]
|
||||
|
||||
@property
|
||||
def all_items(self):
|
||||
def inventory_contents(inventory):
|
||||
for mapping in inventory.item_map:
|
||||
yield mapping
|
||||
if mapping.item.item_type == ItemType.CONTAINER:
|
||||
yield from inventory_contents(mapping.item.inventory)
|
||||
yield from inventory_contents(self)
|
||||
|
||||
@property
|
||||
def all_item_maps(self):
|
||||
def inventory_map(inventory):
|
||||
for mapping in inventory.item_map:
|
||||
yield mapping
|
||||
if mapping.item.item_type == ItemType.CONTAINER:
|
||||
yield from inventory_map(mapping.item.inventory)
|
||||
yield from inventory_map(self)
|
||||
|
||||
def get(self, item):
|
||||
return self.get_all(item)[0]
|
||||
|
||||
def get_all(self, item):
|
||||
return [mapping for mapping in self.all_item_maps if mapping.item == item]
|
||||
|
||||
def add(self, item):
|
||||
if item.item_type not in inventory_type_map[self.inventory_type]:
|
||||
return False
|
||||
mapping = InventoryMap(inventory_id=self.id, item_id=item.id)
|
||||
if item.consumable:
|
||||
mapping.count = item.count
|
||||
if item.charges:
|
||||
mapping.charges = [Charge(inventory_map_id=mapping.id) for i in range(item.charges)]
|
||||
self.item_map.append(mapping)
|
||||
return mapping
|
||||
|
||||
def remove(self, mapping):
|
||||
if mapping in self.item_map:
|
||||
self.item_map.remove(mapping)
|
||||
return True
|
||||
return False
|
||||
|
||||
def __contains__(self, obj: Union[InventoryMap, Item]):
|
||||
if isinstance(obj, InventoryMap):
|
||||
item = obj.item
|
||||
else:
|
||||
item = obj
|
||||
return item in [mapping.item for mapping in self.all_items]
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.all_items
|
||||
|
||||
|
||||
|
||||
|
||||
class Charge(BaseObject):
|
||||
__tablename__ = "charge"
|
||||
|
|
|
@ -165,11 +165,11 @@ def test_containers(db, carl):
|
|||
db.add_or_update([carl, ten_foot_pole, bag_of_holding])
|
||||
|
||||
# add the ten_foot_pole to the bag of holding
|
||||
assert bag_of_holding.inventory.add(ten_foot_pole)
|
||||
assert bag_of_holding.add(ten_foot_pole)
|
||||
db.add_or_update(bag_of_holding)
|
||||
pole_from_bag = bag_of_holding.inventory.get(ten_foot_pole)
|
||||
assert pole_from_bag
|
||||
assert pole_from_bag in bag_of_holding.inventory
|
||||
pole_from_bag = bag_of_holding.get(ten_foot_pole)
|
||||
assert pole_from_bag.item == ten_foot_pole
|
||||
assert pole_from_bag in bag_of_holding
|
||||
assert pole_from_bag not in carl.equipment
|
||||
|
||||
# add the bag of holding to carl's equipment
|
||||
|
@ -183,4 +183,4 @@ def test_containers(db, carl):
|
|||
assert carls_pole == pole_from_bag
|
||||
|
||||
# remove the pole from the bag
|
||||
assert carls_bag.item.inventory.remove(pole_from_bag)
|
||||
assert carls_bag.remove(pole_from_bag)
|
||||
|
|
Loading…
Reference in New Issue
Block a user