Improve inventory handling

This commit is contained in:
Salad Dais
2025-07-15 01:53:24 +00:00
parent 0c2dfd3213
commit 0cc3397402
7 changed files with 29 additions and 6 deletions

View File

@@ -626,6 +626,9 @@ class InventoryItem(InventoryNodeBase):
name: Optional[str] = schema_field(SchemaMultilineStr, default=None)
desc: Optional[str] = schema_field(SchemaMultilineStr, default=None)
metadata: Optional[Dict[str, Any]] = schema_field(SchemaLLSD, default=None, include_none=True)
"""Specifically for script metadata, generally just experience info"""
thumbnail: Optional[Dict[str, Any]] = schema_field(SchemaLLSD, default=None, include_none=False)
"""Generally just a dict with the thumbnail UUID in it"""
creation_date: Optional[dt.datetime] = schema_field(SchemaDate, llsd_name="created_at", default=None)
__hash__ = InventoryNodeBase.__hash__

View File

@@ -330,7 +330,7 @@ class HippoClientSession(BaseClientSession):
super().__init__(id, secure_session_id, agent_id, circuit_code, session_manager, login_data=login_data)
self.http_session = session_manager.http_session
self.objects = ClientWorldObjectManager(proxify(self), session_manager.settings, None)
self.inventory_manager = InventoryManager(proxify(self))
self.inventory = InventoryManager(proxify(self))
self.transport: Optional[SocketUDPTransport] = None
self.protocol: Optional[HippoClientProtocol] = None
self.message_handler.take_by_default = False

View File

@@ -6,16 +6,18 @@ import gzip
import itertools
import logging
from pathlib import Path
from typing import Union, List, Tuple, Set, Sequence, Dict
from typing import Union, List, Tuple, Set, Sequence, Dict, TYPE_CHECKING
from hippolyzer.lib.base import llsd
from hippolyzer.lib.base.datatypes import UUID
from hippolyzer.lib.base.inventory import InventoryModel, InventoryCategory, InventoryItem, InventoryNodeBase
from hippolyzer.lib.base.message.message import Message, Block
from hippolyzer.lib.base.templates import AssetType, FolderType, InventoryType, Permissions
from hippolyzer.lib.client.state import BaseClientSession
from hippolyzer.lib.base.templates import WearableType
if TYPE_CHECKING:
from hippolyzer.lib.client.state import BaseClientSession
LOG = logging.getLogger(__name__)

View File

@@ -15,7 +15,7 @@ from typing import *
from hippolyzer.lib.base.datatypes import UUID, Vector3
from hippolyzer.lib.base.helpers import proxify
from hippolyzer.lib.base.inventory import InventoryItem, InventoryModel
from hippolyzer.lib.base.inventory import InventoryItem, InventoryModel, InventoryObject
from hippolyzer.lib.base.message.message import Block, Message
from hippolyzer.lib.base.message.message_handler import MessageHandler
from hippolyzer.lib.base.message.msgtypes import PacketFlags
@@ -229,7 +229,18 @@ class ClientObjectManager:
async def request_object_inv_via_cap(self, obj: Object) -> List[InventoryItem]:
async with self._region.caps_client.get("RequestTaskInventory", params={"task_id": obj.FullID}) as resp:
resp.raise_for_status()
return [InventoryItem.from_llsd(x) for x in (await resp.read_llsd())["contents"]]
all_items = [InventoryItem.from_llsd(x) for x in (await resp.read_llsd())["contents"]]
# Synthesize the Contents directory so the items can have a parent
parent = InventoryObject(
obj_id=obj.FullID,
name="Contents",
)
model = InventoryModel()
model.add(parent)
for item in all_items:
model.add(item)
return all_items
async def request_object_inv_via_xfer(self, obj: Object) -> List[InventoryItem]:
session = self._region.session()
@@ -370,6 +381,10 @@ class ClientWorldObjectManager:
futs.extend(region_mgr.request_object_properties(region_objs))
return futs
async def request_object_inv(self, obj: Object) -> List[InventoryItem]:
region_mgr = self._get_region_manager(obj.RegionHandle)
return await region_mgr.request_object_inv(obj)
async def load_ancestors(self, obj: Object, wait_time: float = 1.0):
"""
Ensure that the entire chain of parents above this object is loaded

View File

@@ -18,6 +18,7 @@ from hippolyzer.lib.base.network.caps_client import CapsClient
from hippolyzer.lib.base.network.transport import ADDR_TUPLE
from hippolyzer.lib.base.objects import handle_to_global_pos
from hippolyzer.lib.base.xfer_manager import XferManager
from hippolyzer.lib.client.inventory_manager import InventoryManager
from hippolyzer.lib.client.object_manager import ClientObjectManager, ClientWorldObjectManager
@@ -91,6 +92,7 @@ class BaseClientSession(abc.ABC):
region_by_handle: Callable[[int], Optional[BaseClientRegion]]
region_by_circuit_addr: Callable[[ADDR_TUPLE], Optional[BaseClientRegion]]
objects: ClientWorldObjectManager
inventory: InventoryManager
login_data: Dict[str, Any]
REGION_CLS = Type[BaseClientRegion]

View File

@@ -34,6 +34,7 @@ if TYPE_CHECKING:
class Session(BaseClientSession):
regions: MutableSequence[ProxiedRegion]
inventory: ProxyInventoryManager
region_by_handle: Callable[[int], Optional[ProxiedRegion]]
region_by_circuit_addr: Callable[[ADDR_TUPLE], Optional[ProxiedRegion]]
main_region: Optional[ProxiedRegion]

View File

@@ -159,7 +159,7 @@ class TestHippoClient(unittest.IsolatedAsyncioTestCase):
async def test_inventory_manager(self):
await self._log_client_in(self.client)
self.assertEqual(self.client.session.inventory_manager.model.root.node_id, UUID(int=4))
self.assertEqual(self.client.session.inventory.model.root.node_id, UUID(int=4))
async def test_resend_suppression(self):
"""Make sure the client only handles the first seen copy of a reliable message"""