Start improving InventoryManager

This commit is contained in:
Salad Dais
2024-01-16 01:56:34 +00:00
parent a6bbd97b98
commit a7825a881c
4 changed files with 67 additions and 7 deletions

View File

@@ -304,6 +304,9 @@ class JankStringyBytes(bytes):
def __str__(self):
return self.rstrip(b"\x00").decode("utf8", errors="replace")
def __bool__(self):
return not (super().__eq__(b"") or super().__eq__(b"\x00"))
def __eq__(self, other):
if isinstance(other, str):
return str(self) == other

View File

@@ -294,7 +294,7 @@ class InventoryModel(InventoryBase):
if not update_fields:
# Update everything but the model parameter
update_fields = set(node._get_fields_dict().keys()) - {"model"}
update_fields = node.get_field_names()
for field_name in update_fields:
setattr(orig_node, field_name, getattr(node, field_name))
return orig_node
@@ -402,6 +402,10 @@ class InventoryNodeBase(InventoryBase, _HasName):
default=None, init=False, hash=False, compare=False, repr=False
)
@classmethod
def get_field_names(cls) -> Set[str]:
return set(cls._get_fields_dict().keys()) - {"model"}
@property
def node_id(self) -> UUID:
return getattr(self, self.ID_ATTR)
@@ -602,6 +606,8 @@ class InventoryItem(InventoryNodeBase):
permissions=InventoryPermissions(
creator_id=block["CreatorID"],
owner_id=block["OwnerID"],
# Unknown, not sent in this schema
last_owner_id=block.get("LastOwnerID", UUID.ZERO),
group_id=block["GroupID"],
base_mask=block["BaseMask"],
owner_mask=block["OwnerMask"],
@@ -628,7 +634,43 @@ class InventoryItem(InventoryNodeBase):
if flavor == "ais":
# There's little chance this differs from owner ID, just place it.
val["agent_id"] = val["permissions"]["owner_id"]
if val["type"] == AssetType.LINK:
# For link items, there is no asset, only a linked ID.
val["linked_id"] = val.pop("asset_id")
# These don't exist either
val.pop("permissions", None)
val.pop("sale_info", None)
return val
@classmethod
def from_llsd(cls, inv_dict: Dict, flavor: str = "legacy"):
if flavor == "ais" and inv_dict["type"] == AssetType.LINK:
# Links get represented differently than other items for whatever reason.
# This is incredibly annoying, under *NIX there's nothing really special about symlinks.
inv_dict = inv_dict.copy()
# Fill this in since it needs to be there
if "permissions" not in inv_dict:
inv_dict["permissions"] = InventoryPermissions(
base_mask=0xFFffFFff,
owner_mask=0xFFffFFff,
group_mask=0xFFffFFff,
everyone_mask=0,
next_owner_mask=0xFFffFFff,
creator_id=UUID.ZERO,
owner_id=UUID.ZERO,
last_owner_id=UUID.ZERO,
group_id=UUID.ZERO,
).to_llsd("ais")
if "sale_info" not in inv_dict:
inv_dict["sale_info"] = InventorySaleInfo(
sale_type=SaleType.NOT,
sale_price=0,
).to_llsd("ais")
# In the context of symlinks, asset id means linked item ID.
# This is also how indra stores symlinks. Why the asymmetry in AIS if none of the
# consumers actually want it? Who knows.
inv_dict["asset_id"] = inv_dict.pop("linked_id")
return super().from_llsd(inv_dict, flavor)
INVENTORY_TYPES: Tuple[Type[InventoryNodeBase], ...] = (InventoryCategory, InventoryObject, InventoryItem)

View File

@@ -23,8 +23,8 @@ class InventoryManager:
self._load_skeleton()
self._session.message_handler.subscribe("BulkUpdateInventory", self._handle_bulk_update_inventory)
self._session.message_handler.subscribe("UpdateCreateInventoryItem", self._handle_update_create_inventory_item)
self._session.message_handler.subscribe("UpdateInventoryItem", self._handle_update_inventory_item)
self._session.message_handler.subscribe("RemoveInventoryItem", self._handle_remove_inventory_item)
self._session.message_handler.subscribe("MoveInventoryItem", self._handle_move_inventory_item)
def _load_skeleton(self):
assert not self.model.nodes
@@ -148,14 +148,26 @@ class InventoryManager:
for inventory_block in msg["InventoryData"]:
self.model.upsert(InventoryItem.from_inventory_data(inventory_block))
def _handle_update_inventory_item(self, msg: Message):
self._validate_recipient(msg["AgentData"]["AgentID"])
for inventory_block in msg["InventoryData"]:
self.model.update(InventoryItem.from_inventory_data(inventory_block))
def _handle_remove_inventory_item(self, msg: Message):
self._validate_recipient(msg["AgentData"]["AgentID"])
for inventory_block in msg["InventoryData"]:
node = self.model.get(inventory_block["ItemID"])
if node:
self.model.unlink(node)
def _handle_remove_inventory_folder(self, msg: Message):
self._validate_recipient(msg["AgentData"]["AgentID"])
for folder_block in msg["FolderData"]:
node = self.model.get(folder_block["FolderID"])
if node:
self.model.unlink(node)
def _handle_move_inventory_item(self, msg: Message):
for inventory_block in msg["InventoryData"]:
node = self.model.get(inventory_block["ItemID"])
if not node:
LOG.warning(f"Missing inventory item {inventory_block['ItemID']}")
continue
if inventory_block["NewName"]:
node.name = str(inventory_block["NewName"])
node.parent_id = inventory_block['FolderID']