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 import ForeignKey
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
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
|
from ttfrog.db.schema.item import Item, ItemType
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -19,3 +22,14 @@ class Container(Item):
|
||||||
lazy="immediate",
|
lazy="immediate",
|
||||||
default_factory=lambda: Inventory(inventory_type=InventoryType.EQUIPMENT),
|
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 import ForeignKey, UniqueConstraint
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
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.base import BaseObject, EnumField
|
||||||
from ttfrog.db.schema.item import Item, ItemProperty, ItemType
|
from ttfrog.db.schema.item import Item, ItemProperty, ItemType
|
||||||
|
@ -32,77 +33,6 @@ def inventory_map_creator(fields):
|
||||||
return InventoryMap(**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):
|
class InventoryMap(BaseObject):
|
||||||
__tablename__ = "inventory_map"
|
__tablename__ = "inventory_map"
|
||||||
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
|
id: Mapped[int] = mapped_column(init=False, primary_key=True, autoincrement=True)
|
||||||
|
@ -215,6 +145,84 @@ class InventoryMap(BaseObject):
|
||||||
self.attuned = False
|
self.attuned = False
|
||||||
return True
|
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):
|
class Charge(BaseObject):
|
||||||
__tablename__ = "charge"
|
__tablename__ = "charge"
|
||||||
|
|
|
@ -165,11 +165,11 @@ def test_containers(db, carl):
|
||||||
db.add_or_update([carl, ten_foot_pole, bag_of_holding])
|
db.add_or_update([carl, ten_foot_pole, bag_of_holding])
|
||||||
|
|
||||||
# add the ten_foot_pole to the 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)
|
db.add_or_update(bag_of_holding)
|
||||||
pole_from_bag = bag_of_holding.inventory.get(ten_foot_pole)
|
pole_from_bag = bag_of_holding.get(ten_foot_pole)
|
||||||
assert pole_from_bag
|
assert pole_from_bag.item == ten_foot_pole
|
||||||
assert pole_from_bag in bag_of_holding.inventory
|
assert pole_from_bag in bag_of_holding
|
||||||
assert pole_from_bag not in carl.equipment
|
assert pole_from_bag not in carl.equipment
|
||||||
|
|
||||||
# add the bag of holding to carl's 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
|
assert carls_pole == pole_from_bag
|
||||||
|
|
||||||
# remove the pole from the 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