diff --git a/hippolyzer/lib/base/message/data_packer.py b/hippolyzer/lib/base/message/data_packer.py index 601c771..02507d0 100644 --- a/hippolyzer/lib/base/message/data_packer.py +++ b/hippolyzer/lib/base/message/data_packer.py @@ -29,7 +29,10 @@ PACKER = Callable[[Any], bytes] UNPACKER = Callable[[bytes], Any] +LLSD_PACKER = Callable[[Any], Any] +LLSD_UNPACKER = Callable[[Any], Any] SPEC = Tuple[UNPACKER, PACKER] +LLSD_SPEC = Tuple[LLSD_UNPACKER, LLSD_PACKER] def _pack_string(pack_string): @@ -64,6 +67,21 @@ def _packer(x): return lambda x: typ(*struct_obj.unpack(x)), _packer +def _make_llsd_tuplecoord_spec(typ: Type[TupleCoord], needed_elems: Optional[int] = None): + if needed_elems is None: + # Number of elems needed matches the number in the coord type + def _packer(x): + return list(x) + else: + # Special case, we only want to pack some of the components. + # Mostly for Quaternion since we don't actually need to send W. + def _packer(x): + if isinstance(x, TupleCoord): + x = x.data() + return list(x.data(needed_elems)) + return lambda x: typ(*x), _packer + + def _unpack_specs(cls): cls.UNPACKERS = {k: v[0] for (k, v) in cls.SPECS.items()} cls.PACKERS = {k: v[1] for (k, v) in cls.SPECS.items()} @@ -110,10 +128,15 @@ def pack(cls, data, data_type): class LLSDDataPacker(TemplateDataPacker): # Some template var types aren't directly representable in LLSD, so they # get encoded to binary fields. - SPECS = { + SPECS: Dict[MsgType, LLSD_SPEC] = { MsgType.MVT_IP_ADDR: (socket.inet_ntoa, socket.inet_aton), # LLSD ints are technically bound to S32 range. MsgType.MVT_U32: _make_struct_spec('!I'), MsgType.MVT_U64: _make_struct_spec('!Q'), MsgType.MVT_S64: _make_struct_spec('!q'), + # These are arrays in LLSD, we need to turn them into coords. + MsgType.MVT_LLVector3: _make_llsd_tuplecoord_spec(Vector3), + MsgType.MVT_LLVector3d: _make_llsd_tuplecoord_spec(Vector3), + MsgType.MVT_LLVector4: _make_llsd_tuplecoord_spec(Vector4), + MsgType.MVT_LLQuaternion: _make_llsd_tuplecoord_spec(Quaternion, needed_elems=3) } diff --git a/hippolyzer/lib/base/message/msgtypes.py b/hippolyzer/lib/base/message/msgtypes.py index 2eb074d..e646d98 100644 --- a/hippolyzer/lib/base/message/msgtypes.py +++ b/hippolyzer/lib/base/message/msgtypes.py @@ -55,6 +55,8 @@ class PacketFlags(enum.IntFlag): RELIABLE = 0x40 RESENT = 0x20 ACK = 0x10 + # Not a real flag, just used for display. + EQ = 1 << 10 # frequency for messages diff --git a/hippolyzer/lib/base/templates.py b/hippolyzer/lib/base/templates.py index b1c3dbf..dba7cbc 100644 --- a/hippolyzer/lib/base/templates.py +++ b/hippolyzer/lib/base/templates.py @@ -1952,7 +1952,7 @@ class AvatarPropertiesFlags(IntFlag): @se.flag_field_serializer("AvatarGroupsReply", "GroupData", "GroupPowers") -@se.flag_field_serializer("AvatarGroupDataUpdate", "GroupData", "GroupPowers") +@se.flag_field_serializer("AgentGroupDataUpdate", "GroupData", "GroupPowers") @se.flag_field_serializer("AgentDataUpdate", "AgentData", "GroupPowers") @se.flag_field_serializer("GroupProfileReply", "GroupData", "PowersMask") @se.flag_field_serializer("GroupRoleDataReply", "RoleData", "Powers") @@ -2134,6 +2134,43 @@ class ScriptPermissions(IntFlag): CHANGE_ENVIRONMENT = 1 << 18 +@se.flag_field_serializer("ParcelProperties", "ParcelData", "ParcelFlags") +class ParcelFlags(IntFlag): + ALLOW_FLY = 1 << 0 # Can start flying + ALLOW_OTHER_SCRIPTS = 1 << 1 # Scripts by others can run. + FOR_SALE = 1 << 2 # Can buy this land + FOR_SALE_OBJECTS = 1 << 7 # Can buy all objects on this land + ALLOW_LANDMARK = 1 << 3 # Always true/deprecated + ALLOW_TERRAFORM = 1 << 4 + ALLOW_DAMAGE = 1 << 5 + CREATE_OBJECTS = 1 << 6 + # 7 is moved above + USE_ACCESS_GROUP = 1 << 8 + USE_ACCESS_LIST = 1 << 9 + USE_BAN_LIST = 1 << 10 + USE_PASS_LIST = 1 << 11 + SHOW_DIRECTORY = 1 << 12 + ALLOW_DEED_TO_GROUP = 1 << 13 + CONTRIBUTE_WITH_DEED = 1 << 14 + SOUND_LOCAL = 1 << 15 # Hear sounds in this parcel only + SELL_PARCEL_OBJECTS = 1 << 16 # Objects on land are included as part of the land when the land is sold + ALLOW_PUBLISH = 1 << 17 # Allow publishing of parcel information on the web + MATURE_PUBLISH = 1 << 18 # The information on this parcel is mature + URL_WEB_PAGE = 1 << 19 # The "media URL" is an HTML page + URL_RAW_HTML = 1 << 20 # The "media URL" is a raw HTML string like