diff --git a/pyogp/lib/base/agent.py b/pyogp/lib/base/agent.py index b39d7c1..b57b963 100644 --- a/pyogp/lib/base/agent.py +++ b/pyogp/lib/base/agent.py @@ -311,36 +311,33 @@ class Agent(object): def _enable_callbacks(self): """ enable the glue layer once the region is established """ + if self.settings.ENABLE_INVENTORY_MANAGEMENT and self.inventory != None: + self.inventory.enable_callbacks() + if self.settings.ENABLE_GROUP_CHAT: self.group_manager = GroupManager(self, self.settings) if self.settings.MULTIPLE_SIM_CONNECTIONS: onEnableSimulator_received = self.event_queue_handler._register('EnableSimulator') - onEnableSimulator_received.subscribe(onEnableSimulator, self) + onEnableSimulator_received.subscribe(self.onEnableSimulator) onEstablishAgentCommunication_received = self.event_queue_handler._register('EstablishAgentCommunication') - onEstablishAgentCommunication_received.subscribe(onEstablishAgentCommunication, self) - # set up callbacks (is this a decent place to do this? it's perhaps premature) + onEstablishAgentCommunication_received.subscribe(self.onEstablishAgentCommunication) + if self.settings.HANDLE_PACKETS: onAlertMessage_received = self.region.packet_handler._register('AlertMessage') - onAlertMessage_received.subscribe(onAlertMessage, self) + onAlertMessage_received.subscribe(self.onAlertMessage) onAgentDataUpdate_received = self.region.packet_handler._register('AgentDataUpdate') - onAgentDataUpdate_received.subscribe(onAgentDataUpdate, self) + onAgentDataUpdate_received.subscribe(self.onAgentDataUpdate) onAgentMovementComplete_received = self.region.packet_handler._register('AgentMovementComplete') - onAgentMovementComplete_received.subscribe(onAgentMovementComplete, self) + onAgentMovementComplete_received.subscribe(self.onAgentMovementComplete) onHealthMessage_received = self.region.packet_handler._register('HealthMessage') - onHealthMessage_received.subscribe(onHealthMessage, self) - - onInventoryDescendents_received = self.region.packet_handler._register('InventoryDescendents') - onInventoryDescendents_received.subscribe(onInventoryDescendents, self.inventory) - - onFetchInventoryReply_received = self.region.packet_handler._register('FetchInventoryReply') - onFetchInventoryReply_received.subscribe(onFetchInventoryReply, self.inventory) + onHealthMessage_received.subscribe(self.onHealthMessage) if self.settings.ENABLE_COMMUNICATIONS_TRACKING: @@ -485,150 +482,200 @@ class Agent(object): else: return '%s %s' % (self.firstname, self.lastname) -def onAgentDataUpdate(packet, agent): + def onAgentDataUpdate(self, packet): - if agent.agent_id == None: - agent.agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data + if self.agent_id == None: + self.agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data - if agent.firstname == None: - agent.firstname = packet.message_data.blocks['AgentData'][0].get_variable('FirstName').data + if self.firstname == None: + self.firstname = packet.message_data.blocks['AgentData'][0].get_variable('FirstName').data - if agent.lastname == None: - agent.firstname = packet.message_data.blocks['AgentData'][0].get_variable('LastName').data + if self.lastname == None: + self.firstname = packet.message_data.blocks['AgentData'][0].get_variable('LastName').data - agent.GroupTitle = packet.message_data.blocks['AgentData'][0].get_variable('GroupTitle').data + self.GroupTitle = packet.message_data.blocks['AgentData'][0].get_variable('GroupTitle').data - agent.ActiveGroupID = packet.message_data.blocks['AgentData'][0].get_variable('ActiveGroupID').data + self.ActiveGroupID = packet.message_data.blocks['AgentData'][0].get_variable('ActiveGroupID').data - agent.GroupPowers = packet.message_data.blocks['AgentData'][0].get_variable('GroupPowers').data + self.GroupPowers = packet.message_data.blocks['AgentData'][0].get_variable('GroupPowers').data - agent.GroupName = packet.message_data.blocks['AgentData'][0].get_variable('GroupName').data + self.GroupName = packet.message_data.blocks['AgentData'][0].get_variable('GroupName').data -def onAgentMovementComplete(packet, agent): + def onAgentMovementComplete(self, packet): - agent.Position = packet.message_data.blocks['Data'][0].get_variable('Position').data + self.Position = packet.message_data.blocks['Data'][0].get_variable('Position').data - agent.LookAt = packet.message_data.blocks['Data'][0].get_variable('LookAt').data + self.LookAt = packet.message_data.blocks['Data'][0].get_variable('LookAt').data - agent.region.RegionHandle = packet.message_data.blocks['Data'][0].get_variable('RegionHandle').data + self.region.RegionHandle = packet.message_data.blocks['Data'][0].get_variable('RegionHandle').data - #agent.Timestamp = packet.message_data.blocks['Data'][0].get_variable('Timestamp') + #agent.Timestamp = packet.message_data.blocks['Data'][0].get_variable('Timestamp') - agent.region.ChannelVersion = packet.message_data.blocks['SimData'][0].get_variable('ChannelVersion').data + self.region.ChannelVersion = packet.message_data.blocks['SimData'][0].get_variable('ChannelVersion').data -def onHealthMessage(packet, agent): + def onHealthMessage(self, packet): - agent.health = packet.message_data.blocks['HealthData'][0].get_variable('Health').data + self.health = packet.message_data.blocks['HealthData'][0].get_variable('Health').data -def onAgentGroupDataUpdate(packet, agent): + def onAgentGroupDataUpdate(self, packet): - # AgentData block - AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data + # AgentData block + AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data - # GroupData block - for GroupData_block in packet.message_data.blocks['GroupData']: + # GroupData block + for GroupData_block in packet.message_data.blocks['GroupData']: - AcceptNotices = GroupData_block.get_variable('AcceptNotices').data - GroupPowers = GroupData_block.get_variable('GroupPowers').data - GroupID = uuid.UUID(str(GroupData_block.get_variable('GroupID').data)) - GroupName = GroupData_block.get_variable('GroupName').data - ListInProfile = GroupData_block.get_variable('ListInProfile').data - Contribution = GroupData_block.get_variable('Contribution').data - GroupInsigniaID = uuid.UUID(str(GroupData_block.get_variable('GroupInsigniaID').data)) + AcceptNotices = GroupData_block.get_variable('AcceptNotices').data + GroupPowers = GroupData_block.get_variable('GroupPowers').data + GroupID = uuid.UUID(str(GroupData_block.get_variable('GroupID').data)) + GroupName = GroupData_block.get_variable('GroupName').data + ListInProfile = GroupData_block.get_variable('ListInProfile').data + Contribution = GroupData_block.get_variable('Contribution').data + GroupInsigniaID = uuid.UUID(str(GroupData_block.get_variable('GroupInsigniaID').data)) - # make sense of group powers - GroupPowers = [ord(x) for x in GroupPowers] - GroupPowers = ''.join([str(x) for x in GroupPowers]) + # make sense of group powers + GroupPowers = [ord(x) for x in GroupPowers] + GroupPowers = ''.join([str(x) for x in GroupPowers]) - group = Group(AcceptNotices, GroupPowers, GroupID, GroupName, ListInProfile, Contribution,GroupInsigniaID ) + group = Group(AcceptNotices, GroupPowers, GroupID, GroupName, ListInProfile, Contribution,GroupInsigniaID ) - agent.group_manager.store_group(group) + self.group_manager.store_group(group) - ''' - Name: AgentGroupDataUpdate - Block Name: GroupData - AcceptNotices: True - GroupPowers: ? - GroupID: 69fd708c-3f20-a01b-f9b5-b5c4b310e5ca - GroupName: EnusBot Army - ListInProfile: False - Contribution: 0 - GroupInsigniaID: 00000000-0000-0000-0000-000000000000 - AcceptNotices: True - GroupPowers: ? - GroupID: 69fd708c-3f20-a01b-f9b5-b5c4b310e5ca - GroupName: EnusBot Army - ListInProfile: False - Contribution: 0 - GroupInsigniaID: 00000000-0000-0000-0000-000000000000 - Block Name: AgentData - AgentID: a517168d-1af5-4854-ba6d-672c8a59e439 + ''' + Name: AgentGroupDataUpdate + Block Name: GroupData + AcceptNotices: True + GroupPowers: ? + GroupID: 69fd708c-3f20-a01b-f9b5-b5c4b310e5ca + GroupName: EnusBot Army + ListInProfile: False + Contribution: 0 + GroupInsigniaID: 00000000-0000-0000-0000-000000000000 + AcceptNotices: True + GroupPowers: ? + GroupID: 69fd708c-3f20-a01b-f9b5-b5c4b310e5ca + GroupName: EnusBot Army + ListInProfile: False + Contribution: 0 + GroupInsigniaID: 00000000-0000-0000-0000-000000000000 + Block Name: AgentData + AgentID: a517168d-1af5-4854-ba6d-672c8a59e439 - ''' + ''' -def onChatFromSimulator(packet, agent): + def onChatFromSimulator(self, packet): - pass - ''' - { - ChatFromSimulator Low 139 Trusted Unencoded + pass + ''' { - ChatData Single - { FromName Variable 1 } - { SourceID LLUUID } // agent id or object id - { OwnerID LLUUID } // object's owner - { SourceType U8 } - { ChatType U8 } - { Audible U8 } - { Position LLVector3 } - { Message Variable 2 } // UTF-8 text + ChatFromSimulator Low 139 Trusted Unencoded + { + ChatData Single + { FromName Variable 1 } + { SourceID LLUUID } // agent id or object id + { OwnerID LLUUID } // object's owner + { SourceType U8 } + { ChatType U8 } + { Audible U8 } + { Position LLVector3 } + { Message Variable 2 } // UTF-8 text + } } - } - ''' + ''' -def onImprovedInstantMessage(packet, agent): + def onImprovedInstantMessage(self, packet): - pass - ''' - // ImprovedInstantMessage - // This message can potentially route all over the place - // ParentEstateID: parent estate id of the source estate - // RegionID: region id of the source of the IM. - // Position: position of the sender in region local coordinates - // Dialog see llinstantmessage.h for values - // ID May be used by dialog. Interpretation depends on context. - // BinaryBucket May be used by some dialog types - // reliable - { - ImprovedInstantMessage Low 254 NotTrusted Zerocoded + pass + ''' + // ImprovedInstantMessage + // This message can potentially route all over the place + // ParentEstateID: parent estate id of the source estate + // RegionID: region id of the source of the IM. + // Position: position of the sender in region local coordinates + // Dialog see llinstantmessage.h for values + // ID May be used by dialog. Interpretation depends on context. + // BinaryBucket May be used by some dialog types + // reliable { - AgentData Single - { AgentID LLUUID } - { SessionID LLUUID } + ImprovedInstantMessage Low 254 NotTrusted Zerocoded + { + AgentData Single + { AgentID LLUUID } + { SessionID LLUUID } + } + { + MessageBlock Single + { FromGroup BOOL } + { ToAgentID LLUUID } + { ParentEstateID U32 } + { RegionID LLUUID } + { Position LLVector3 } + { Offline U8 } + { Dialog U8 } // U8 - IM type + { ID LLUUID } + { Timestamp U32 } + { FromAgentName Variable 1 } + { Message Variable 2 } + { BinaryBucket Variable 2 } + } } - { - MessageBlock Single - { FromGroup BOOL } - { ToAgentID LLUUID } - { ParentEstateID U32 } - { RegionID LLUUID } - { Position LLVector3 } - { Offline U8 } - { Dialog U8 } // U8 - IM type - { ID LLUUID } - { Timestamp U32 } - { FromAgentName Variable 1 } - { Message Variable 2 } - { BinaryBucket Variable 2 } - } - } - ''' + ''' -def onAlertMessage(packet, agent): + def onAlertMessage(self, packet): - AlertMessage = packet.message_data.blocks['AlertData'][0].get_variable('Message').data + AlertMessage = packet.message_data.blocks['AlertData'][0].get_variable('Message').data - log(WARNING, "AlertMessage from simulator: %s" % (AlertMessage)) + log(WARNING, "AlertMessage from simulator: %s" % (AlertMessage)) + + def onEnableSimulator(self, packet): + """ handler for the EnableSimulator packet sent over the event queue """ + + IP = [ord(x) for x in packet.message_data.blocks['SimulatorInfo'][0].get_variable('IP').data] + IP = '.'.join([str(x) for x in IP]) + + Port = packet.message_data.blocks['SimulatorInfo'][0].get_variable('Port').data + + # not sure what this is, but pass it up + Handle = [ord(x) for x in packet.message_data.blocks['SimulatorInfo'][0].get_variable('Handle').data] + + region_params = {'IP': IP, 'Port': Port, 'Handle': Handle} + + log(INFO, 'Received EnableSimulator for %s' % (str(IP) + ":" + str(Port))) + + # are we already prepping to connect to the sim? + if region_params not in self._pending_child_regions: + + # are we already connected to the sim? + known_region = False + + # don't append to the list if we already know about this region + for region in self.child_regions: + if region.sim_ip == region_params['IP'] and region.sim_port == region_params['Port']: + known_region = True + + #agent._enable_child_region(IP, Port, Handle) + if not known_region: + self._pending_child_regions.append(region_params) + + def onEstablishAgentCommunication(self, message): + """ handler for the EstablishAgentCommunication sent over the event queue + + contains the seed cap for a neighboring region + """ + + log(INFO, 'Received EstablishAgentCommunication for %s' % (message.sim_ip_and_port)) + + is_running = False + + # don't enable the event queue when we already have it running + for region in self.child_regions: + if (str(region.sim_ip) + ":" + str(region.sim_port) == message.sim_ip_and_port) and region.event_queue != None: + if region.event_queue._running: + is_running = True + + # start the event queue + if is_running == False: + self._start_EQ_on_neighboring_region(message) class Home(object): """ contains the parameters descibing an agent's home location """ @@ -653,142 +700,3 @@ class Home(object): self.local_x = self.position[0] self.local_y = self.position[1] self.local_z = self.position[2] - -def onEnableSimulator(packet, agent): - """ handler for the EnableSimulator packet sent over the event queue """ - - IP = [ord(x) for x in packet.message_data.blocks['SimulatorInfo'][0].get_variable('IP').data] - IP = '.'.join([str(x) for x in IP]) - - Port = packet.message_data.blocks['SimulatorInfo'][0].get_variable('Port').data - - # not sure what this is, but pass it up - Handle = [ord(x) for x in packet.message_data.blocks['SimulatorInfo'][0].get_variable('Handle').data] - - region_params = {'IP': IP, 'Port': Port, 'Handle': Handle} - - log(INFO, 'Received EnableSimulator for %s' % (str(IP) + ":" + str(Port))) - - # are we already prepping to connect to the sim? - if region_params not in agent._pending_child_regions: - - # are we already connected to the sim? - known_region = False - - # don't append to the list if we already know about this region - for region in agent.child_regions: - if region.sim_ip == region_params['IP'] and region.sim_port == region_params['Port']: - known_region = True - - #agent._enable_child_region(IP, Port, Handle) - if not known_region: - agent._pending_child_regions.append(region_params) - -def onEstablishAgentCommunication(message, agent): - """ handler for the EstablishAgentCommunication sent over the event queue - - contains the seed cap for a neighboring region - """ - - log(INFO, 'Received EstablishAgentCommunication for %s' % (message.sim_ip_and_port)) - - is_running = False - - # don't enable the event queue when we already have it running - for region in agent.child_regions: - if (str(region.sim_ip) + ":" + str(region.sim_port) == message.sim_ip_and_port) and region.event_queue != None: - if region.event_queue._running: - is_running = True - - # start the event queue - if is_running == False: - agent._start_EQ_on_neighboring_region(message) - #~~~~~~~~~~ - # Callbacks - #~~~~~~~~~~ - -def onInventoryDescendents(packet, inventory): - - if packet.message_data.blocks['AgentData'][0].get_variable('Descendents') > 0: - - _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') - _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') - _folder_id = packet.message_data.blocks['AgentData'][0].get_variable('FolderID') - _owner_id = packet.message_data.blocks['AgentData'][0].get_variable('OwnerID') - _version = packet.message_data.blocks['AgentData'][0].get_variable('Version') - _descendents = packet.message_data.blocks['AgentData'][0].get_variable('Descendents') - - if packet.message_data.blocks['ItemData'][0].get_variable('ItemID').data != uuid.UUID('00000000-0000-0000-0000-000000000000'): - - for ItemData_block in packet.message_data.blocks['ItemData']: - - _ItemID = ItemData_block.get_variable('ItemID').data - _FolderID = ItemData_block.get_variable('FolderID').data - _CreatorID = ItemData_block.get_variable('CreatorID').data - _OwnerID = ItemData_block.get_variable('OwnerID').data - _GroupID = ItemData_block.get_variable('GroupID').data - _BaseMask = ItemData_block.get_variable('BaseMask').data - _OwnerMask = ItemData_block.get_variable('OwnerMask').data - _GroupMask = ItemData_block.get_variable('GroupMask').data - _EveryoneMask = ItemData_block.get_variable('EveryoneMask').data - _NextOwnerMask = ItemData_block.get_variable('NextOwnerMask').data - _GroupOwned = ItemData_block.get_variable('GroupOwned').data - _AssetID = ItemData_block.get_variable('AssetID').data - _Type = ItemData_block.get_variable('Type').data - _InvType = ItemData_block.get_variable('InvType').data - _Flags = ItemData_block.get_variable('Flags').data - _SaleType = ItemData_block.get_variable('SaleType').data - _SalePrice = ItemData_block.get_variable('SalePrice').data - _Name = ItemData_block.get_variable('Name').data - _Description = ItemData_block.get_variable('Description').data - _CreationDate = ItemData_block.get_variable('CreationDate').data - _CRC = ItemData_block.get_variable('CRC').data - - inventory_item = InventoryItem(_ItemID, _FolderID, _CreatorID, _OwnerID, _GroupID, _BaseMask, _OwnerMask, _GroupMask, _EveryoneMask, _NextOwnerMask, _GroupOwned, _AssetID, _Type, _InvType, _Flags, _SaleType, _SalePrice, _Name, _Description, _CreationDate, _CRC) - - inventory._add_inventory_item(inventory_item) - - if packet.message_data.blocks['FolderData'][0].get_variable('FolderID').data != uuid.UUID('00000000-0000-0000-0000-000000000000'): - - for FolderData_block in packet.message_data.blocks['FolderData']: - - _FolderID = FolderData_block.get_variable('FolderID').data - _ParentID = FolderData_block.get_variable('ParentID').data - _Type = FolderData_block.get_variable('Type').data - _Name = FolderData_block.get_variable('Name').data - - folder = InventoryFolder( _Name, _FolderID, _ParentID, None, _Type) - - inventory._add_inventory_folder(folder) - -def onFetchInventoryReply(packet, inventory): - - _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') - - for InventoryData_block in packet.message_data.blocks['InventoryData']: - - _ItemID = InventoryData_block.get_variable('ItemID').data - _FolderID = InventoryData_block.get_variable('FolderID').data - _CreatorID = InventoryData_block.get_variable('CreatorID').data - _OwnerID = InventoryData_block.get_variable('OwnerID').data - _GroupID = InventoryData_block.get_variable('GroupID').data - _BaseMask = InventoryData_block.get_variable('BaseMask').data - _OwnerMask = InventoryData_block.get_variable('OwnerMask').data - _GroupMask = InventoryData_block.get_variable('GroupMask').data - _EveryoneMask = InventoryData_block.get_variable('EveryoneMask').data - _NextOwnerMask = InventoryData_block.get_variable('NextOwnerMask').data - _GroupOwned = InventoryData_block.get_variable('GroupOwned').data - _AssetID = InventoryData_block.get_variable('AssetID').data - _Type = InventoryData_block.get_variable('Type').data - _InvType = InventoryData_block.get_variable('InvType').data - _Flags = InventoryData_block.get_variable('Flags').data - _SaleType = InventoryData_block.get_variable('SaleType').data - _SalePrice = InventoryData_block.get_variable('SalePrice').data - _Name = InventoryData_block.get_variable('Name').data - _Description = InventoryData_block.get_variable('Description').data - _CreationDate = InventoryData_block.get_variable('CreationDate').data - _CRC = InventoryData_block.get_variable('CRC').data - - inventory_item = InventoryItem(_ItemID, _FolderID, _CreatorID, _OwnerID, _GroupID, _BaseMask, _OwnerMask, _GroupMask, _EveryoneMask, _NextOwnerMask, _GroupOwned, _AssetID, _Type, _InvType, _Flags, _SaleType, _SalePrice, _Name, _Description, _CreationDate, _CRC) - - inventory._add_inventory_item(inventory_item) diff --git a/pyogp/lib/base/examples/sample_multi_region_connect.py b/pyogp/lib/base/examples/sample_multi_region_connect.py index 51b6a92..5489709 100644 --- a/pyogp/lib/base/examples/sample_multi_region_connect.py +++ b/pyogp/lib/base/examples/sample_multi_region_connect.py @@ -109,8 +109,8 @@ def login(): print '\tsim_ip : %s' % region.sim_ip print '\tsim_port : %s' % region.sim_port print '\tseed_cap : %s' % region.seed_capability_url - print '\tpackets_in : %s' % region.packets_in - print '\tpackets_out: %s' % region.packets_out + print '\tpackets_in : %s' % region.messenger.packets_in + print '\tpackets_out: %s' % region.messenger.packets_out def main(): return login() diff --git a/pyogp/lib/base/examples/sample_object_tracking.py b/pyogp/lib/base/examples/sample_object_tracking.py index eb9d375..d871db3 100644 --- a/pyogp/lib/base/examples/sample_object_tracking.py +++ b/pyogp/lib/base/examples/sample_object_tracking.py @@ -133,7 +133,7 @@ def login(): print '' print '' for _avatar in client.region.objects.avatar_store: - print 'ID:', _avatar.ID, '\tUUID: ', _avatar.FullID , '\tNameValue: ', _avatar.NameValue, '\tPosition: ', _avatar.Position + print 'ID:', _avatar.LocalID, '\tUUID: ', _avatar.FullID , '\tNameValue: ', _avatar.NameValue, '\tPosition: ', _avatar.Position print '' print '' print 'Region attributes:' diff --git a/pyogp/lib/base/groups.py b/pyogp/lib/base/groups.py index 593f992..43c0337 100644 --- a/pyogp/lib/base/groups.py +++ b/pyogp/lib/base/groups.py @@ -72,19 +72,19 @@ class GroupManager(object): # ~~~~~~~~~ if self.settings.HANDLE_PACKETS: onAgentGroupDataUpdate_received = self.agent.region.event_queue_handler._register("AgentGroupDataUpdate") - onAgentGroupDataUpdate_received.subscribe(onAgentGroupDataUpdate, self) + onAgentGroupDataUpdate_received.subscribe(self.onAgentGroupDataUpdate) onChatterBoxInvitation_received = self.agent.region.event_queue_handler._register('ChatterBoxInvitation') - onChatterBoxInvitation_received.subscribe(onChatterBoxInvitation_Message, self) + onChatterBoxInvitation_received.subscribe(self.onChatterBoxInvitation_Message) onChatterBoxSessionEventReply_received = self.agent.region.event_queue_handler._register('ChatterBoxSessionEventReply') - onChatterBoxSessionEventReply_received.subscribe(onChatterBoxSessionEventReply, self) + onChatterBoxSessionEventReply_received.subscribe(self.onChatterBoxSessionEventReply) onChatterBoxSessionAgentListUpdates_received = self.agent.region.event_queue_handler._register('ChatterBoxSessionAgentListUpdates') - onChatterBoxSessionAgentListUpdates_received.subscribe(onChatterBoxSessionAgentListUpdates, self) + onChatterBoxSessionAgentListUpdates_received.subscribe(self.onChatterBoxSessionAgentListUpdates) onChatterBoxSessionStartReply_received = self.agent.region.event_queue_handler._register('ChatterBoxSessionStartReply') - onChatterBoxSessionStartReply_received.subscribe(onChatterBoxSessionStartReply, self) + onChatterBoxSessionStartReply_received.subscribe(self.onChatterBoxSessionStartReply) if self.settings.LOG_VERBOSE: log(DEBUG, "Initialized the Group Manager") @@ -234,6 +234,94 @@ class GroupManager(object): self.agent.region.enqueue_message(packet()) + # ~~~~~~~~~~~~~~~~~~ + # Callback functions + # ~~~~~~~~~~~~~~~~~~ + + def onCreateGroupReply(self, packet): + """ when we get a CreateGroupReply packet, log Success, and if True, request the group details. remove the callback in any case """ + + # remove the monitor + self.onCreateGroupReply_received.unsubscribe(onCreateGroupReply, group_manager) + + AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data + GroupID = packet.message_data.blocks['ReplyData'][0].get_variable('GroupID').data + Success = packet.message_data.blocks['ReplyData'][0].get_variable('Success').data + Message = packet.message_data.blocks['ReplyData'][0].get_variable('Message').data + + if Success: + log(INFO, "Created group %s. Message data is: %s" % (GroupID, Message)) + log(WARNING, "We now need to request the group data...") + else: + log(WARNING, "Failed to create group due to: %s" % (Message)) + + def onJoinGroupReply(self, packet): + """ the simulator tells us if joining a group was a success. """ + + self.onJoinGroupReply_received.unsubscribe(onJoinGroupReply, group_manager) + + AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data + GroupID = packet.message_data.blocks['GroupData'][0].get_variable('GroupID').data + Success = packet.message_data.blocks['GroupData'][0].get_variable('Success').data + + if Success: + log(INFO, "Joined group %s" % (GroupID)) + else: + log(WARNING, "Failed to join group %s" % (GroupID)) + + def onAgentGroupDataUpdate(self, packet): + """ deal with the data that comes in over the event queue """ + + group_data = {} + + AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data + + # GroupData block + for GroupData_block in packet.message_data.blocks['GroupData']: + + group_data['GroupID'] = GroupData_block.get_variable('GroupID').data + group_data['GroupPowers'] = GroupData_block.get_variable('GroupPowers').data + group_data['AcceptNotices'] = GroupData_block.get_variable('AcceptNotices').data + group_data['GroupInsigniaID'] = GroupData_block.get_variable('GroupInsigniaID').data + group_data['Contribution'] = GroupData_block.get_variable('Contribution').data + group_data['GroupName'] = GroupData_block.get_variable('GroupName').data + + # make sense of group powers + group_data['GroupPowers'] = [ord(x) for x in group_data['GroupPowers']] + group_data['GroupPowers'] = ''.join([str(x) for x in group_data['GroupPowers']]) + + self.update_group(group_data) + + def onChatterBoxInvitation_Message(self, message): + """ handle a group chat message from the event queue """ + + self.handle_group_chat(message) + + def onChatterBoxSessionEventReply(self, message): + """ handle a response from the simulator re: a message we sent to a group chat """ + + self.agent.helpers.log_event_queue_data(message, self) + + def onChatterBoxSessionAgentListUpdates(self, message): + """ parse teh response to a request to join a group chat and propagate data out """ + + data = {} + data['session_id'] = message.session_id + data['agent_updates'] = message.agent_updates + + self.update_group_by_session_id(data) + + def onChatterBoxSessionStartReply(self, message): + + data = {} + data['temp_session_id'] = message.temp_session_id + data['success'] = message.success + data['session_id'] = message.session_id + data['session_info'] = message.session_info + + self.update_group_by_name(data, data['session_info']['session_name']) + + class Group(object): """ representation of a group """ @@ -486,92 +574,6 @@ class ChatterBoxSessionStartReply_Message(object): self.name = "ChatterBoxSessionStartReply" #{'body': {'temp_session_id': 4dd70b7f-8b3a-eef9-fc2f-909151d521f6, 'success': True, 'session_id': 4dd70b7f-8b3a-eef9-fc2f-909151d521f6, 'session_info': {'voice_enabled': True, 'session_name': "Enus' Construction Crew", 'type': 0, 'moderated_mode': {'voice': False}}}, 'message': 'ChatterBoxSessionStartReply'}], -# ~~~~~~~~~~~~~~~~~~ -# Callback functions -# ~~~~~~~~~~~~~~~~~~ - -def onCreateGroupReply(packet, group_manager): - """ when we get a CreateGroupReply packet, log Success, and if True, request the group details. remove the callback in any case """ - - # remove the monitor - group_manager.onCreateGroupReply_received.unsubscribe(onCreateGroupReply, group_manager) - - AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data - GroupID = packet.message_data.blocks['ReplyData'][0].get_variable('GroupID').data - Success = packet.message_data.blocks['ReplyData'][0].get_variable('Success').data - Message = packet.message_data.blocks['ReplyData'][0].get_variable('Message').data - - if Success: - log(INFO, "Created group %s. Message data is: %s" % (GroupID, Message)) - log(WARNING, "We now need to request the group data...") - else: - log(WARNING, "Failed to create group due to: %s" % (Message)) - -def onJoinGroupReply(packet, group_manager): - """ the simulator tells us if joining a group was a success. """ - - group_manager.onJoinGroupReply_received.unsubscribe(onJoinGroupReply, group_manager) - - AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data - GroupID = packet.message_data.blocks['GroupData'][0].get_variable('GroupID').data - Success = packet.message_data.blocks['GroupData'][0].get_variable('Success').data - - if Success: - log(INFO, "Joined group %s" % (GroupID)) - else: - log(WARNING, "Failed to join group %s" % (GroupID)) - -def onAgentGroupDataUpdate(packet, group_manager): - """ deal with the data that comes in over the event queue """ - - group_data = {} - - AgentID = packet.message_data.blocks['AgentData'][0].get_variable('AgentID').data - - # GroupData block - for GroupData_block in packet.message_data.blocks['GroupData']: - - group_data['GroupID'] = GroupData_block.get_variable('GroupID').data - group_data['GroupPowers'] = GroupData_block.get_variable('GroupPowers').data - group_data['AcceptNotices'] = GroupData_block.get_variable('AcceptNotices').data - group_data['GroupInsigniaID'] = GroupData_block.get_variable('GroupInsigniaID').data - group_data['Contribution'] = GroupData_block.get_variable('Contribution').data - group_data['GroupName'] = GroupData_block.get_variable('GroupName').data - - # make sense of group powers - group_data['GroupPowers'] = [ord(x) for x in group_data['GroupPowers']] - group_data['GroupPowers'] = ''.join([str(x) for x in group_data['GroupPowers']]) - - group_manager.update_group(group_data) - -def onChatterBoxInvitation_Message(message, group_manager): - """ handle a group chat message from the event queue """ - - group_manager.handle_group_chat(message) - -def onChatterBoxSessionEventReply(message, group_manager): - """ handle a response from the simulator re: a message we sent to a group chat """ - - group_manager.agent.helpers.log_event_queue_data(message, group_manager) - -def onChatterBoxSessionAgentListUpdates(message, group_manager): - """ parse teh response to a request to join a group chat and propagate data out """ - - data = {} - data['session_id'] = message.session_id - data['agent_updates'] = message.agent_updates - - group_manager.update_group_by_session_id(data) - -def onChatterBoxSessionStartReply(message, group_manager): - - data = {} - data['temp_session_id'] = message.temp_session_id - data['success'] = message.success - data['session_id'] = message.session_id - data['session_info'] = message.session_info - - group_manager.update_group_by_name(data, data['session_info']['session_name']) ''' Groups related messages: diff --git a/pyogp/lib/base/inventory.py b/pyogp/lib/base/inventory.py index ff80a9a..405b474 100644 --- a/pyogp/lib/base/inventory.py +++ b/pyogp/lib/base/inventory.py @@ -69,6 +69,101 @@ class Inventory(object): if self.settings.LOG_VERBOSE: log(INFO, "Initializing inventory storage") + def enable_callbacks(self): + """ enable monitors for certain inventory related packet events """ + + onInventoryDescendents_received = self.agent.region.packet_handler._register('InventoryDescendents') + onInventoryDescendents_received.subscribe(self.onInventoryDescendents) + + onFetchInventoryReply_received = self.agent.region.packet_handler._register('FetchInventoryReply') + onFetchInventoryReply_received.subscribe(self.onFetchInventoryReply) + + def onInventoryDescendents(self, packet): + + if packet.message_data.blocks['AgentData'][0].get_variable('Descendents') > 0: + + _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') + _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') + _folder_id = packet.message_data.blocks['AgentData'][0].get_variable('FolderID') + _owner_id = packet.message_data.blocks['AgentData'][0].get_variable('OwnerID') + _version = packet.message_data.blocks['AgentData'][0].get_variable('Version') + _descendents = packet.message_data.blocks['AgentData'][0].get_variable('Descendents') + + if packet.message_data.blocks['ItemData'][0].get_variable('ItemID').data != uuid.UUID('00000000-0000-0000-0000-000000000000'): + + for ItemData_block in packet.message_data.blocks['ItemData']: + + _ItemID = ItemData_block.get_variable('ItemID').data + _FolderID = ItemData_block.get_variable('FolderID').data + _CreatorID = ItemData_block.get_variable('CreatorID').data + _OwnerID = ItemData_block.get_variable('OwnerID').data + _GroupID = ItemData_block.get_variable('GroupID').data + _BaseMask = ItemData_block.get_variable('BaseMask').data + _OwnerMask = ItemData_block.get_variable('OwnerMask').data + _GroupMask = ItemData_block.get_variable('GroupMask').data + _EveryoneMask = ItemData_block.get_variable('EveryoneMask').data + _NextOwnerMask = ItemData_block.get_variable('NextOwnerMask').data + _GroupOwned = ItemData_block.get_variable('GroupOwned').data + _AssetID = ItemData_block.get_variable('AssetID').data + _Type = ItemData_block.get_variable('Type').data + _InvType = ItemData_block.get_variable('InvType').data + _Flags = ItemData_block.get_variable('Flags').data + _SaleType = ItemData_block.get_variable('SaleType').data + _SalePrice = ItemData_block.get_variable('SalePrice').data + _Name = ItemData_block.get_variable('Name').data + _Description = ItemData_block.get_variable('Description').data + _CreationDate = ItemData_block.get_variable('CreationDate').data + _CRC = ItemData_block.get_variable('CRC').data + + inventory_item = InventoryItem(_ItemID, _FolderID, _CreatorID, _OwnerID, _GroupID, _BaseMask, _OwnerMask, _GroupMask, _EveryoneMask, _NextOwnerMask, _GroupOwned, _AssetID, _Type, _InvType, _Flags, _SaleType, _SalePrice, _Name, _Description, _CreationDate, _CRC) + + self._add_inventory_item(inventory_item) + + if packet.message_data.blocks['FolderData'][0].get_variable('FolderID').data != uuid.UUID('00000000-0000-0000-0000-000000000000'): + + for FolderData_block in packet.message_data.blocks['FolderData']: + + _FolderID = FolderData_block.get_variable('FolderID').data + _ParentID = FolderData_block.get_variable('ParentID').data + _Type = FolderData_block.get_variable('Type').data + _Name = FolderData_block.get_variable('Name').data + + folder = InventoryFolder( _Name, _FolderID, _ParentID, None, _Type) + + self._add_inventory_folder(folder) + + def onFetchInventoryReply(self, packet): + + _agent_id = packet.message_data.blocks['AgentData'][0].get_variable('AgentID') + + for InventoryData_block in packet.message_data.blocks['InventoryData']: + + _ItemID = InventoryData_block.get_variable('ItemID').data + _FolderID = InventoryData_block.get_variable('FolderID').data + _CreatorID = InventoryData_block.get_variable('CreatorID').data + _OwnerID = InventoryData_block.get_variable('OwnerID').data + _GroupID = InventoryData_block.get_variable('GroupID').data + _BaseMask = InventoryData_block.get_variable('BaseMask').data + _OwnerMask = InventoryData_block.get_variable('OwnerMask').data + _GroupMask = InventoryData_block.get_variable('GroupMask').data + _EveryoneMask = InventoryData_block.get_variable('EveryoneMask').data + _NextOwnerMask = InventoryData_block.get_variable('NextOwnerMask').data + _GroupOwned = InventoryData_block.get_variable('GroupOwned').data + _AssetID = InventoryData_block.get_variable('AssetID').data + _Type = InventoryData_block.get_variable('Type').data + _InvType = InventoryData_block.get_variable('InvType').data + _Flags = InventoryData_block.get_variable('Flags').data + _SaleType = InventoryData_block.get_variable('SaleType').data + _SalePrice = InventoryData_block.get_variable('SalePrice').data + _Name = InventoryData_block.get_variable('Name').data + _Description = InventoryData_block.get_variable('Description').data + _CreationDate = InventoryData_block.get_variable('CreationDate').data + _CRC = InventoryData_block.get_variable('CRC').data + + inventory_item = InventoryItem(_ItemID, _FolderID, _CreatorID, _OwnerID, _GroupID, _BaseMask, _OwnerMask, _GroupMask, _EveryoneMask, _NextOwnerMask, _GroupOwned, _AssetID, _Type, _InvType, _Flags, _SaleType, _SalePrice, _Name, _Description, _CreationDate, _CRC) + + self._add_inventory_item(inventory_item) + def _parse_folders_from_login_response(self): """ the login response may contain inventory information, append data to our folders list """ @@ -357,7 +452,11 @@ class InventoryItem(object): sendRezObject(agent, self, location_to_rez, location_to_rez) def update(agent, name = None, value = None): - """ allow arbitraty update to any data in the inventory item """ + """ allow arbitraty update to any data in the inventory item + + accepts a dictionary of key:value pairs which will update the stored inventory items + and then send an UpdateInventoryItem packet + """ if self.__dict__.has_key(name): self.setattr(self, name, value) diff --git a/pyogp/lib/base/message/udpdispatcher.py b/pyogp/lib/base/message/udpdispatcher.py index 9725173..9f94733 100644 --- a/pyogp/lib/base/message/udpdispatcher.py +++ b/pyogp/lib/base/message/udpdispatcher.py @@ -50,6 +50,9 @@ class UDPDispatcher(object): self.region = region + self.packets_in = 0 + self.packets_out = 0 + self.circuit_manager = CircuitManager() self.data_unpacker = DataUnpacker() @@ -110,7 +113,7 @@ class UDPDispatcher(object): if circuit == None: raise exc.CircuitNotFound(host, 'preparing to check for packets') - self.region.packets_in += 1 + self.packets_in += 1 recv_packet = self.udp_deserializer.deserialize(msg_buf) @@ -210,7 +213,7 @@ class UDPDispatcher(object): #TODO: remove this when testing a network self.udp_client.send_packet(self.socket, send_buffer, host) - self.region.packets_out += 1 + self.packets_out += 1 return send_buffer diff --git a/pyogp/lib/base/objects.py b/pyogp/lib/base/objects.py index ca897a4..a4186ad 100644 --- a/pyogp/lib/base/objects.py +++ b/pyogp/lib/base/objects.py @@ -87,19 +87,19 @@ class Objects(object): self.packet_handler = PacketHandler() onObjectUpdate_received = self.packet_handler._register('ObjectUpdate') - onObjectUpdate_received.subscribe(onObjectUpdate, self) + onObjectUpdate_received.subscribe(self.onObjectUpdate) onObjectUpdateCached_received = self.packet_handler._register('ObjectUpdateCached') - onObjectUpdateCached_received.subscribe(onObjectUpdateCached, self) + onObjectUpdateCached_received.subscribe(self.onObjectUpdateCached) onObjectUpdateCompressed_received= self.packet_handler._register('ObjectUpdateCompressed') - onObjectUpdateCompressed_received.subscribe(onObjectUpdateCompressed, self) + onObjectUpdateCompressed_received.subscribe(self.onObjectUpdateCompressed) onObjectProperties_received = self.packet_handler._register('ObjectProperties') - onObjectProperties_received.subscribe(onObjectProperties, self) + onObjectProperties_received.subscribe(self.onObjectProperties) onKillObject_received= self.packet_handler._register('KillObject') - onKillObject_received.subscribe(onKillObject, self) + onKillObject_received.subscribe(self.onKillObject) # uncomment these to view packets sent back to simulator # onObjectName_sent = self.packet_handler._register('ObjectName') @@ -245,6 +245,10 @@ class Objects(object): if victim == None: victim = self.get_avatar_from_store(LocalID = ID) + # if we do not know about this object, pass + if victim == None or victim == []: + return + # this is an avatar if victim.PCode == 47: @@ -425,6 +429,458 @@ class Objects(object): self.region.enqueue_message(packet(), True) + def onObjectUpdate(self, packet): + """ populates an Object instance and adds it to the Objects() store """ + + object_list = [] + + # ToDo: handle these 2 variables properly + _RegionHandle = packet.message_data.blocks['RegionData'][0].get_variable('RegionHandle').data + _TimeDilation = packet.message_data.blocks['RegionData'][0].get_variable('TimeDilation').data + + for ObjectData_block in packet.message_data.blocks['ObjectData']: + + object_properties = {} + + object_properties['LocalID'] = ObjectData_block.get_variable('ID').data + object_properties['State'] = ObjectData_block.get_variable('State').data + object_properties['FullID'] = ObjectData_block.get_variable('FullID').data + object_properties['CRC'] = ObjectData_block.get_variable('CRC').data + object_properties['PCode'] = ObjectData_block.get_variable('PCode').data + object_properties['Material'] = ObjectData_block.get_variable('Material').data + object_properties['ClickAction'] = ObjectData_block.get_variable('ClickAction').data + object_properties['Scale'] = ObjectData_block.get_variable('Scale').data + object_properties['ObjectData'] = ObjectData_block.get_variable('ObjectData').data + object_properties['ParentID'] = ObjectData_block.get_variable('ParentID').data + object_properties['UpdateFlags'] = ObjectData_block.get_variable('UpdateFlags').data + object_properties['PathCurve'] = ObjectData_block.get_variable('PathCurve').data + object_properties['ProfileCurve'] = ObjectData_block.get_variable('ProfileCurve').data + object_properties['PathBegin'] = ObjectData_block.get_variable('PathBegin').data + object_properties['PathEnd'] = ObjectData_block.get_variable('PathEnd').data + object_properties['PathScaleX'] = ObjectData_block.get_variable('PathScaleX').data + object_properties['PathScaleY'] = ObjectData_block.get_variable('PathScaleY').data + object_properties['PathShearX'] = ObjectData_block.get_variable('PathShearX').data + object_properties['PathShearY'] = ObjectData_block.get_variable('PathShearY').data + object_properties['PathTwist'] = ObjectData_block.get_variable('PathTwist').data + object_properties['PathTwistBegin'] = ObjectData_block.get_variable('PathTwistBegin').data + object_properties['PathRadiusOffset'] = ObjectData_block.get_variable('PathRadiusOffset').data + object_properties['PathTaperX'] = ObjectData_block.get_variable('PathTaperX').data + object_properties['PathTaperY'] = ObjectData_block.get_variable('PathTaperY').data + object_properties['PathRevolutions'] = ObjectData_block.get_variable('PathRevolutions').data + object_properties['PathSkew'] = ObjectData_block.get_variable('PathSkew').data + object_properties['ProfileBegin'] = ObjectData_block.get_variable('ProfileBegin').data + object_properties['ProfileEnd'] = ObjectData_block.get_variable('ProfileEnd').data + object_properties['ProfileHollow'] = ObjectData_block.get_variable('ProfileHollow').data + object_properties['TextureEntry'] = ObjectData_block.get_variable('TextureEntry').data + object_properties['TextureAnim'] = ObjectData_block.get_variable('TextureAnim').data + object_properties['NameValue'] = ObjectData_block.get_variable('NameValue').data + object_properties['Data'] = ObjectData_block.get_variable('Data').data + object_properties['Text'] = ObjectData_block.get_variable('Text').data + object_properties['TextColor'] = ObjectData_block.get_variable('TextColor').data + object_properties['MediaURL'] = ObjectData_block.get_variable('MediaURL').data + object_properties['PSBlock'] = ObjectData_block.get_variable('PSBlock').data + object_properties['ExtraParams'] = ObjectData_block.get_variable('ExtraParams').data + object_properties['Sound'] = ObjectData_block.get_variable('Sound').data + object_properties['OwnerID'] = ObjectData_block.get_variable('OwnerID').data + object_properties['Gain'] = ObjectData_block.get_variable('Gain').data + object_properties['Flags'] = ObjectData_block.get_variable('Flags').data + object_properties['Radius'] = ObjectData_block.get_variable('Radius').data + object_properties['JointType'] = ObjectData_block.get_variable('JointType').data + object_properties['JointPivot'] = ObjectData_block.get_variable('JointPivot').data + object_properties['JointAxisOrAnchor'] = ObjectData_block.get_variable('JointAxisOrAnchor').data + + # deal with the data stored in _ObjectData + # see http://wiki.secondlife.com/wiki/ObjectUpdate#ObjectData_Format for details + + object_properties['FootCollisionPlane'] = None + object_properties['Position'] = None + object_properties['Velocity'] = None + object_properties['Acceleration'] = None + object_properties['Rotation'] = None + object_properties['AngularVelocity'] = None + + if len(object_properties['ObjectData']) == 76: + + # Foot collision plane. LLVector4. + # Angular velocity is ignored and set to 0. Falls through to 60 bytes parser. + + object_properties['FootCollisionPlane'] = Quaternion(object_properties['ObjectData'], 0) + object_properties['Position'] = Vector3(object_properties['ObjectData'], 16) + object_properties['Velocity'] = Vector3(object_properties['ObjectData'], 28) + object_properties['Acceleration'] = Vector3(object_properties['ObjectData'], 40) + object_properties['Rotation'] = Vector3(object_properties['ObjectData'], 52) + object_properties['AngularVelocity'] = Vector3(object_properties['ObjectData'], 60) + + elif len(object_properties['ObjectData']) == 60: + + # 32 bit precision update. + + object_properties['Position'] = Vector3(object_properties['ObjectData'], 0) + object_properties['Velocity'] = Vector3(object_properties['ObjectData'], 12) + object_properties['Acceleration'] = Vector3(object_properties['ObjectData'], 24) + object_properties['Rotation'] = Vector3(object_properties['ObjectData'], 36) + object_properties['AngularVelocity'] = Vector3(object_properties['ObjectData'], 48) + + elif len(object_properties['ObjectData']) == 48: + + # Foot collision plane. LLVector4 + # Falls through to 32 bytes parser. + + log(WARNING, "48 bit ObjectData precision not implemented") + + elif len(object_properties['ObjectData']) == 32: + + # 32 bit precision update. + + # Position. U16Vec3. + # Velocity. U16Vec3. + # Acceleration. U16Vec3. + # Rotation. U16Rot(4xU16). + # Angular velocity. LLVector3. + log(WARNING, "32 bit ObjectData precision not implemented") + + elif len(object_properties['ObjectData']) == 16: + + # 8 bit precision update. + + # Position. U8Vec3. + # Velocity. U8Vec3. + # Acceleration. U8Vec3. + # Rotation. U8Rot(4xU8). + # Angular velocity. U8Vec3 + log(WARNING, "16 bit ObjectData precision not implemented") + + object_list.append(object_properties) + + self.update_multiple_objects_properties(object_list) + + def onObjectUpdateCached(self, packet): + """ borrowing from libomv, we'll request object data for all data coming in via ObjectUpdateCached""" + + # ToDo: handle these 2 variables properly + _RegionHandle = packet.message_data.blocks['RegionData'][0].get_variable('RegionHandle').data + _TimeDilation = packet.message_data.blocks['RegionData'][0].get_variable('TimeDilation').data + + _request_list = [] + + for ObjectData_block in packet.message_data.blocks['ObjectData']: + + LocalID = ObjectData_block.get_variable('ID').data + _CRC = ObjectData_block.get_variable('CRC').data + _UpdateFlags = ObjectData_block.get_variable('UpdateFlags').data + + # Objects.request_object_update() expects a tuple of (_ID, CacheMissType) + + # see if we have the object stored already + _object = objects.get_object_from_store(LocalID = LocalID) + + if _object == None or _object == []: + CacheMissType = 1 + else: + CacheMissType = 0 + + _request_list.append((LocalID, CacheMissType)) + + # ask the simulator for updates + self.request_object_update(ID_list = _request_list) + + def onObjectUpdateCompressed(self, packet): + + object_list = [] + + # ToDo: handle these 2 variables properly + _RegionHandle = packet.message_data.blocks['RegionData'][0].get_variable('RegionHandle').data + _TimeDilation = packet.message_data.blocks['RegionData'][0].get_variable('TimeDilation').data + + for ObjectData_block in packet.message_data.blocks['ObjectData']: + + object_properties = {} + + object_properties['UpdateFlags'] = ObjectData_block.get_variable('UpdateFlags').data + object_properties['Data'] = ObjectData_block.get_variable('Data').data + _Data = object_properties['Data'] + + pos = 0 # position in the binary string + object_properties['FullID'] = UUID(bytes = _Data, offset = 0) # LLUUID + pos += 16 + object_properties['LocalID'] = struct.unpack("B", _Data[pos:pos+1])[0] + pos += 1 + + if object_properties['PCode'] != 9: # if it is not a prim, stop. + log(WARNING, 'Fix Me!! Skipping parsing of ObjectUpdateCompressed packet when it is not a prim.') + # we ought to parse it and make sense of the data... + continue + + object_properties['State'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['CRC'] = struct.unpack("B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['ClickAction'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['Scale'] = Vector3(_Data, pos) + pos += 12 + object_properties['Position'] = Vector3(_Data, pos) + pos += 12 + object_properties['Rotation'] = Vector3(_Data, pos) + pos += 12 + object_properties['Flags'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['OwnerID'] = UUID(_Data, pos) + pos += 16 + + # Placeholder vars, to be populated via flags if present + object_properties['AngularVelocity'] = Vector3() + object_properties['ParentID'] = UUID() + object_properties['Text'] = '' + object_properties['TextColor'] = None + object_properties['MediaURL'] = '' + object_properties['Sound'] = UUID() + object_properties['Gain'] = 0 + object_properties['Flags'] = 0 + object_properties['Radius'] = 0 + object_properties['NameValue'] = '' + object_properties['ExtraParams'] = None + + if object_properties['Flags'] != 0: + + log(WARNING, "FixMe! Quiting parsing an ObjectUpdateCompressed packet with flags due to incomplete implemention. Storing a partial representation of an object with uuid of %s" % (_FullID)) + + # the commented code is not working right, we need to figure out why! + # ExtraParams in particular seemed troublesome + + ''' + print 'Flags: ', Flags + + if (Flags & CompressedUpdateFlags.contains_AngularVelocity) != 0: + _AngularVelocity = Vector3(_Data, pos) + pos += 12 + print 'AngularVelocity: ', _AngularVelocity + else: + _AngularVelocity = None + + if (Flags & CompressedUpdateFlags.contains_Parent) != 0: + _ParentID = UUID(_Data, pos) + pos += 16 + print 'ParentID: ', _ParentID + else: + _ParentID = None + + if (Flags & CompressedUpdateFlags.Tree) != 0: + # skip it, only iterate the position + pos += 1 + print 'Tree' + + if (Flags & CompressedUpdateFlags.ScratchPad) != 0: + # skip it, only iterate the position + size = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + pos += size + print 'Scratchpad size' + + if (Flags & CompressedUpdateFlags.contains_Text) != 0: + # skip it, only iterate the position + _Text = '' + while struct.unpack(">B", _Data[pos:pos+1])[0] != 0: + pos += 1 + pos += 1 + _TextColor = struct.unpack("B", _Data[pos:pos+1])[0] != 0: + pos += 1 + pos += 1 + print '_MediaURL: ', _MediaURL + + if (Flags & CompressedUpdateFlags.contains_Particles) != 0: + # skip it, only iterate the position + ParticleData = _Data[pos:pos+86] + pos += 86 + print 'Particles' + + # parse ExtraParams + # ToDo: finish this up, for now we are just incrementing the position and not dealing with the data + + _Flexible = None + _Light = None + _Sculpt = None + + num_extra_params = struct.unpack(">b", _Data[pos:pos+1])[0] + print 'Number of extra params: ', num_extra_params + pos += 1 + + for i in range(num_extra_params): + + # ExtraParam type + extraparam_type = struct.unpack("f", _Data[pos:pos+4])[0] + pos += 4 + + #_Flags = stuct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + + #_Radius = struct.unpack(">f", _Data[pos:pos+4])[0] + pos += 4 + + if (Flags & CompressedUpdateFlags.contains_NameValues) != 0: + # skip it, only iterate the position + _NameValue = '' + + while _Data[pos:pos+1] != 0: + #_NameValue += struct.unpack(">c", _Data[pos:pos+1])[0] + pos += 1 + pos += 1 + ''' + + object_properties['PathCurve'] = None + object_properties['PathBegin'] = None + object_properties['PathEnd'] = None + object_properties['PathScaleX'] = None + object_properties['PathScaleY'] = None + object_properties['PathShearX'] = None + object_properties['PathShearY'] = None + object_properties['PathTwist'] = None + object_properties['PathTwistBegin'] = None + object_properties['PathRadiusOffset'] = None + object_properties['PathTaperX'] = None + object_properties['PathTaperY'] = None + object_properties['PathRevolutions'] = None + object_properties['PathSkew'] = None + object_properties['ProfileCurve'] = None + object_properties['ProfileBegin'] = None + object_properties['ProfileEnd'] = None + object_properties['ProfileHollow'] = None + object_properties['TextureEntry'] = None + object_properties['TextureAnim'] = None + object_properties['TextureAnim'] = None + + else: + + object_properties['PathCurve'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathBegin'] = struct.unpack("B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathScaleY'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathShearX'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathShearY'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathTwist'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathTwistBegin'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathRadiusOffset'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathTaperX'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathTaperY'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathRevolutions'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['PathSkew'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['ProfileCurve'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['ProfileBegin'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['ProfileEnd'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + object_properties['ProfileHollow'] = struct.unpack(">B", _Data[pos:pos+1])[0] + pos += 1 + + # Texture handling + size = struct.unpack("B", _Data[pos:pos+1])[0] - pos += 1 - - if object_properties['PCode'] != 9: # if it is not a prim, stop. - log(WARNING, 'Fix Me!! Skipping parsing of ObjectUpdateCompressed packet when it is not a prim.') - # we ought to parse it and make sense of the data... - continue - - object_properties['State'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['CRC'] = struct.unpack("B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['ClickAction'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['Scale'] = Vector3(_Data, pos) - pos += 12 - object_properties['Position'] = Vector3(_Data, pos) - pos += 12 - object_properties['Rotation'] = Vector3(_Data, pos) - pos += 12 - object_properties['Flags'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['OwnerID'] = UUID(_Data, pos) - pos += 16 - - # Placeholder vars, to be populated via flags if present - object_properties['AngularVelocity'] = Vector3() - object_properties['ParentID'] = UUID() - object_properties['Text'] = '' - object_properties['TextColor'] = None - object_properties['MediaURL'] = '' - object_properties['Sound'] = UUID() - object_properties['Gain'] = 0 - object_properties['Flags'] = 0 - object_properties['Radius'] = 0 - object_properties['NameValue'] = '' - object_properties['ExtraParams'] = None - - if object_properties['Flags'] != 0: - - log(WARNING, "FixMe! Quiting parsing an ObjectUpdateCompressed packet with flags due to incomplete implemention. Storing a partial representation of an object with uuid of %s" % (_FullID)) - - # the commented code is not working right, we need to figure out why! - # ExtraParams in particular seemed troublesome - - ''' - print 'Flags: ', Flags - - if (Flags & CompressedUpdateFlags.contains_AngularVelocity) != 0: - _AngularVelocity = Vector3(_Data, pos) - pos += 12 - print 'AngularVelocity: ', _AngularVelocity - else: - _AngularVelocity = None - - if (Flags & CompressedUpdateFlags.contains_Parent) != 0: - _ParentID = UUID(_Data, pos) - pos += 16 - print 'ParentID: ', _ParentID - else: - _ParentID = None - - if (Flags & CompressedUpdateFlags.Tree) != 0: - # skip it, only iterate the position - pos += 1 - print 'Tree' - - if (Flags & CompressedUpdateFlags.ScratchPad) != 0: - # skip it, only iterate the position - size = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - pos += size - print 'Scratchpad size' - - if (Flags & CompressedUpdateFlags.contains_Text) != 0: - # skip it, only iterate the position - _Text = '' - while struct.unpack(">B", _Data[pos:pos+1])[0] != 0: - pos += 1 - pos += 1 - _TextColor = struct.unpack("B", _Data[pos:pos+1])[0] != 0: - pos += 1 - pos += 1 - print '_MediaURL: ', _MediaURL - - if (Flags & CompressedUpdateFlags.contains_Particles) != 0: - # skip it, only iterate the position - ParticleData = _Data[pos:pos+86] - pos += 86 - print 'Particles' - - # parse ExtraParams - # ToDo: finish this up, for now we are just incrementing the position and not dealing with the data - - _Flexible = None - _Light = None - _Sculpt = None - - num_extra_params = struct.unpack(">b", _Data[pos:pos+1])[0] - print 'Number of extra params: ', num_extra_params - pos += 1 - - for i in range(num_extra_params): - - # ExtraParam type - extraparam_type = struct.unpack("f", _Data[pos:pos+4])[0] - pos += 4 - - #_Flags = stuct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - - #_Radius = struct.unpack(">f", _Data[pos:pos+4])[0] - pos += 4 - - if (Flags & CompressedUpdateFlags.contains_NameValues) != 0: - # skip it, only iterate the position - _NameValue = '' - - while _Data[pos:pos+1] != 0: - #_NameValue += struct.unpack(">c", _Data[pos:pos+1])[0] - pos += 1 - pos += 1 - ''' - - object_properties['PathCurve'] = None - object_properties['PathBegin'] = None - object_properties['PathEnd'] = None - object_properties['PathScaleX'] = None - object_properties['PathScaleY'] = None - object_properties['PathShearX'] = None - object_properties['PathShearY'] = None - object_properties['PathTwist'] = None - object_properties['PathTwistBegin'] = None - object_properties['PathRadiusOffset'] = None - object_properties['PathTaperX'] = None - object_properties['PathTaperY'] = None - object_properties['PathRevolutions'] = None - object_properties['PathSkew'] = None - object_properties['ProfileCurve'] = None - object_properties['ProfileBegin'] = None - object_properties['ProfileEnd'] = None - object_properties['ProfileHollow'] = None - object_properties['TextureEntry'] = None - object_properties['TextureAnim'] = None - object_properties['TextureAnim'] = None - - else: - - object_properties['PathCurve'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathBegin'] = struct.unpack("B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathScaleY'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathShearX'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathShearY'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathTwist'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathTwistBegin'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathRadiusOffset'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathTaperX'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathTaperY'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathRevolutions'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['PathSkew'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['ProfileCurve'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['ProfileBegin'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['ProfileEnd'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - object_properties['ProfileHollow'] = struct.unpack(">B", _Data[pos:pos+1])[0] - pos += 1 - - # Texture handling - size = struct.unpack("