def _set_value(self, value): if self.value_type in (NameValueType.Asset, NameValueType.String): self.value = value elif self.value_type == NameValueType.F32: try: self.value = float(value) except ValueError: logger.warn("Unparsable float in NameValue: %s", value) self.value = 0 elif self.value_type in (NameValueType.S32, NameValueType.U32, NameValueType.U64): try: self.value = int(value) except ValueError: logger.warn("Unparsable int in NameValue: %s", value) self.value = 0 elif self.value_type == NameValueType.Vector3: try: self.value = Vector3.parse(value) except ValueError: self.value = Vector3(X=0, Y=0, Z=0) else: self.value = None logger.warn("Unknown value type in NameValue: %s", self.value_type)
def request_join_group_chat(self): """ sends an ImprovedInstantMessage packet with the atributes necessary to join a group chat """ logger.info("Requesting to join group chat session for \'%s\'" % (self.GroupName)) _AgentID = self.agent.agent_id _SessionID = self.agent.session_id _FromGroup = False _ToAgentID = self.GroupID _ParentEstateID = 0 _RegionID = UUID() _Position = Vector3() _Offline = 0 _Dialog = ImprovedIMDialogue.SessionGroupStart _ID = self.GroupID _Timestamp = 0 _FromAgentName = self.agent.Name() _Message = 'Message' '' _BinaryBucket = '' self.agent.send_ImprovedInstantMessage(_AgentID, _SessionID, _FromGroup, _ToAgentID, _ParentEstateID, _RegionID, _Position, _Offline, _Dialog, _ID, _Timestamp, _FromAgentName, _Message, _BinaryBucket)
def unpack_v3(data, offset, min, max): vector3 = Vector3(X=Helpers.packed_u16_to_float(data, offset, min, max), Y=Helpers.packed_u16_to_float(data, offset + 2, min, max), Z=Helpers.packed_u16_to_float(data, offset + 4, min, max)) return vector3
def sendLocalTeleport(self, agent, pos): client = self.manager.client if not agent.FullID == client.agent_id: print("Trying to move an agent for other user") t_id = uuid.uuid4() invoice_id = UUID() client.teleport(region_handle=client.region.RegionHandle, position=Vector3(X=pos[0], Y=pos[1], Z=pos[2]))
def onImprovedTerseObjectUpdate(self, packet): client = self.manager.client for packet_ObjectData in packet['ObjectData']: data = packet_ObjectData['Data'] localID = struct.unpack("<I", data[0:4])[0] naaliProto = False if len(data) == 30: is_avatar = True naaliProto = True idx = 4 else: attachPoint = struct.unpack("<b", data[4])[0] is_avatar = struct.unpack("<?", data[5])[0] idx = 6 if is_avatar: collisionPlane = Quaternion(data[idx:idx + 16]) idx += 16 minlen = idx + 12 + 6 + 6 + 6 + 8 if is_avatar: minlen += 16 if len(data) < minlen: data = data + ('\0' * (minlen - len(data))) pos = Vector3(data[idx:idx + 12]) idx += 12 vel = unpack_v3(data, idx, -128.0, 128.0) idx += 6 if not naaliProto: accel = unpack_v3(data, idx, -64.0, 64.0) idx += 6 rot = unpack_q(data, idx) idx += 8 if not naaliProto: angular_vel = unpack_v3(data, idx, -64.0, 64.0) if is_avatar: obj = client.region.objects.get_avatar_from_store( LocalID=localID) if not obj: print("cant find avatar!!") else: obj = client.region.objects.get_object_from_store( LocalID=localID) # print("onImprovedTerseObjectUpdate", localID, pos, vel, accel, obj) if obj: if self._eatupdates[obj.LocalID]: self._eatupdates[obj.LocalID] -= 1 return obj_uuid = str(obj.FullID) obj.pos = v3_to_list(pos) obj.rot = q_to_list(rot) if obj_uuid and obj.pos and obj.rot: self.out_queue.put( ['pos', obj_uuid, v3_to_list(pos), q_to_list(rot)]) else: print("not avatar update") else: print("cant find object")
def get_size(self): """ Computes the size of the avatar, bases off of libomv's implementation for now. """ height = 1.706 + (self.visualParams[692].value*0.1918) + (self.visualParams[842].value*0.0375) + \ (self.visualParams[33].value*0.12022) + (self.visualParams[682].value*0.01117) + \ (self.visualParams[756].value*0.038) + (self.visualParams[198].value*0.08) + \ (self.visualParams[503].value*0.07) return Vector3(X=0.45, Y=0.60, Z=height)
def degrab(self, objectID, uvCoord = Vector3(), stCoord = Vector3(), faceIndex=0, position=Vector3(), normal=Vector3(), binormal=Vector3()): packet = Message('ObjectDeGrab', Block('AgentData', AgentID = self.agent_id, SessionID = self.session_id), Block('ObjectData', LocalID = objectID), [Block('SurfaceInfo', UVCoord = uvCoord, STCoord = stCoord, FaceIndex = faceIndex, Position = position, Normal = normal, Binormal = binormal)]) self.region.enqueue_message(packet)
def test_can_teleport(self): """ Tests teleport by teleporting to a new location and verifying position has changed """ old_pos = Vector3(X=client.Position.X, Y=client.Position.Y, Z=client.Position.Z) new_pos = Vector3(X=client.Position.X + 5, Y=client.Position.Y + 5, Z=client.Position.Z) client.teleport(region_handle=client.region.RegionHandle, position=new_pos) api.sleep(5) # wait for object update self.assertFalse(client.Position.X == old_pos.X and \ client.Position.Y == old_pos.Y and \ client.Position.Z == old_pos.Z) client.teleport(region_handle=client.region.RegionHandle, position=old_pos)
def test_physics(self): """ Physics by flying up, stopping, and verify avatar's position changes every second over 5 seconds. """ client.fly() client.up() api.sleep(3) old_pos = Vector3(X=client.Position.X, Y=client.Position.Y, Z=client.Position.Z) client.up(False) client.fly(False) api.sleep(5) new_pos = Vector3(X=client.Position.X, Y=client.Position.Y, Z=client.Position.Z) self.assertFalse(new_pos.X == old_pos.X and \ new_pos.Y == old_pos.Y and \ new_pos.Z == old_pos.Z)
def __init__(self, params): """ initialize the Home object by parsing the data passed in """ # eval(params) would be nice, but fails to parse the string the way one thinks it might items = params.split(', \'') # this creates: # self.region_handle # self.look_at # self.position for i in items: i = re.sub(r'[\"\{}\'"]', '', i) i = i.split(':') setattr(self, i[0], eval(re.sub('r', '', i[1]))) self.global_x = self.region_handle[0] self.global_y = self.region_handle[1] # convert the position and lookat to a Vector3 instance self.look_at = Vector3(X=self.look_at[0], Y=self.look_at[1], Z=self.look_at[2]) self.position = Vector3(X=self.position[0], Y=self.position[1], Z=self.position[2])
def test_onObjectUpdate_selected(self): self.object_store.agent = Agent() fake_uuid = UUID() fake_uuid.random() packet = Message( 'ObjectUpdate', Block('RegionData', RegionHandle=0, TimeDilation=0), Block('ObjectData', ID=1, State=1, FullID=fake_uuid, CRC=0, PCode=0, Material=0, ClickAction=0, Scale=Vector3(X=0.0, Y=0.0, Z=0.0), ObjectData='', ParentID=fake_uuid, UpdateFlags=0, ProfileCurve=0, PathBegin=0.0, PathEnd=0.0, PathScaleX=0.0, PathScaleY=0.0, PathShearX=0.0, PathShearY=0.0, PathTwist=-1, PathTwistBegin=-1, PathRadiusOffset=-1, PathTaperX=-1, PathTaperY=-1, PathRevolutions=0, PathSkew=-1, ProfileBegin=0, ProfileEnd=0, ProfileHollow=0, TextureEntry='', TextureAnim='', NameValue='Test', Data='', Text='', TextColor=0x0, MedialURL='')) def callback(payload): self.data.append("foo") object_handler = self.object_store.agent.events_handler.register( "ObjectSelected") object_handler.subscribe(callback) self.object_store.region.message_handler.handle(packet) self.assertTrue(self.data.pop, "foo")
def finishObjectUpdate(self, obj_uuid, pars, objdata, parent_id): if not 'ParentID' in pars: parent = self.client.region.objects.get_object_from_store( LocalID=parent_id) pars["ParentID"] = str(parent.FullID) obj = self.client.region.objects.get_object_from_store(FullID=obj_uuid) out_queue = self.out_queue out_queue.put(['props', obj_uuid, pars]) if len(objdata) == 48: pos_vector = Vector3(objdata) vel = Vector3(objdata[12:]) acc = Vector3(objdata[24:]) rot = Quaternion(objdata[36:]) if obj: obj.pos = v3_to_list(pos_vector) obj.rot = q_to_list(rot) out_queue.put( ['pos', obj_uuid, v3_to_list(pos_vector), q_to_list(rot)]) elif len(objdata) == 12: if True: # position only packed as 3 floats pos = Vector3(objdata) if obj: obj.pos = v3_to_list(pos) out_queue.put(['pos', obj_uuid, v3_to_list(pos)]) elif ObjectData_block.Type in [4, 20, 12, 28]: # position only packed as 3 floats scale = Vector3(objdata) out_queue.put(['scale', obj_uuid, v3_to_list(scale)]) elif ObjectData_block.Type in [2, 10]: # rotation only packed as 3 floats rot = Quaternion(objdata) out_queue.put(['rot', obj_uuid, q_to_list(rot)]) else: # missing sizes: 28, 40, 44, 64 self.logger.debug("Unparsed update of size " + str(len(objdata)))
def test_fly(self): """ Tests flying by flying for 5 seconds and verifying position change """ old_pos = Vector3(X=client.Position.X, Y=client.Position.Y, Z=client.Position.Z) client.fly() api.sleep(5) self.assertFalse(client.Position.X == old_pos.X and \ client.Position.Y == old_pos.Y and \ client.Position.Z == old_pos.Z) client.fly(False)
def chat(self, Message=None): """ sends an instant message to another avatar wraps send_ImprovedInstantMessage with some handy defaults """ if self.session_id == None: self.request_join_group_chat() Wait(5) if self.session_id == None: logger.warning( "Failed to start chat session with group %s. Please try again later." % (self.GroupName)) return if Message != None: _ID = self.GroupID _AgentID = self.agent.agent_id _SessionID = self.agent.session_id _FromGroup = False _ToAgentID = self.GroupID _ParentEstateID = 0 _RegionID = UUID() _Position = Vector3() # don't send position, send uuid zero _Offline = 0 _Dialog = ImprovedIMDialogue.SessionSend _ID = self.GroupID _Timestamp = 0 _FromAgentName = self.agent.Name( ) + "\x00" #struct.pack(">" + str(len(self.agent.Name)) + "c", *(self.agent.Name())) _Message = Message + "\x00" #struct.pack(">" + str(len(Message)) + "c", *(Message)) _BinaryBucket = "\x00" # self.GroupName #struct.pack(">" + str(len(self.GroupName)) + "c", *(self.GroupName)) self.agent.send_ImprovedInstantMessage( _AgentID, _SessionID, _FromGroup, _ToAgentID, _ParentEstateID, _RegionID, _Position, _Offline, _Dialog, _ID, _Timestamp, _FromAgentName, _Message, _BinaryBucket)
def grabUpdate(self, objectID, grabPosition = Vector3(), grabOffset = Vector3(), uvCoord = Vector3(), stCoord = Vector3(), faceIndex=0, position=Vector3(), normal=Vector3(), binormal=Vector3()): packet = Message('ObjectGrabUpdate', Block('AgentData', AgentID = self.agent_id, SessionID = self.session_id), Block('ObjectData', LocalID = objectID, GrabOffsetInitial = grabOffset, GrabPostion = grabPosition), [Block('SurfaceInfo', UVCoord = uvCoord, STCoord = stCoord, FaceIndex = faceIndex, Position = position, Normal = normal, Binormal = binormal)]) self.region.enqueue_message(packet)
def teleport(self, region_name=None, region_handle=None, region_id=None, landmark_id=None, position=Vector3(X=128, Y=128, Z=128), look_at=Vector3(X=128, Y=128, Z=128)): """Initiate a teleport to the specified location. When passing a region name it may be necessary to request the destination region handle from the current sim before the teleport can start.""" logger.info('teleport name=%s handle=%s id=%s', str(region_name), str(region_handle), str(region_id)) # Landmarks are easy, get those out of the way if landmark_id: logger.info('sending landmark TP request packet') packet = Message('TeleportLandmarkRequest', Block('Info', AgentID = self.agent_id, SessionID = self.session_id, LandmarkID = UUID(landmark_id))) self.region.enqueue_message(packet) return # Handle intra-region teleports even by name if not region_id and region_name and region_name.lower() == self.region.SimName.lower(): region_id = self.region.RegionID if region_id: logger.info('sending TP request packet') packet = Message('TeleportRequest', Block('AgentData', AgentID = self.agent_id, SessionID = self.session_id), Block('Info', RegionID = region_id, Position = position, LookAt = look_at)) self.region.enqueue_message(packet) elif region_handle: logger.info('sending TP location request packet') packet = Message('TeleportLocationRequest', Block('AgentData', AgentID = self.agent_id, SessionID = self.session_id), Block('Info', RegionHandle = region_handle, Position = position, LookAt = look_at)) self.region.enqueue_message(packet) else: logger.info("Target region's handle not known, sending map name request") # do a region_name to region_id lookup and then request the teleport self.map_service.request_handle( region_name, lambda handle: self.teleport(region_handle=handle, position=position, look_at=look_at))
def __init__(self, settings = None, firstname = '', lastname = '', password = '', agent_id = None, events_handler = None, handle_signals=True): """ initialize this agent """ # allow the settings to be passed in # otherwise, grab the defaults if settings != None: self.settings = settings else: from pyogp.lib.client.settings import Settings self.settings = Settings() # allow the eventhandler to be passed in # so that applications running multiple avatars # may use the same eventhandler # otherwise, let's just use our own if events_handler != None: self.events_handler = events_handler else: self.events_handler = AppEventsHandler() # signal handler to capture erm signals if handle_signals: self.signal_handler = signal.signal(signal.SIGINT, self.sigint_handler) # storage containers for agent attributes # we overwrite with what the grid tells us, rather than what # is passed in and stored in Login() self.firstname = firstname self.lastname = lastname self.password = password self.agent_id = None self.session_id = None self.local_id = None self.secure_session_id = None self.name = self.Name() self.active_group_powers = None self.active_group_name = None self.active_group_title = None self.active_group_id = None self.health = None self._login_params = None self.circuit_code = None # other storage containers self.inventory_host = None self.agent_access = None self.udp_blacklist = None self.home = None self.inventory = None self.start_location = None self.group_manager = GroupManager(self, self.settings) self.asset_manager = AssetManager(self, self.settings) self.map_service = MapService(self, self.settings) # additional attributes self.login_response = None self.connected = False self.grid_type = None self.running = True self.helpers = Helpers() # data we store as it comes in from the grid self.Position = Vector3() # this will get updated later, but seed it with 000 self.LookAt = Vector3() self.ActiveGroupID = UUID() # populated via ObjectUpdates self.FootCollisionPlane = Quaternion() self.Velocity = Vector3() self.Acceleration = Vector3() self.Rotation = Vector3() self.AngularVelocity = Vector3() # movement self.state = AgentState.Null # typing, editing self.control_flags = 0 self.agent_update_flags = AgentUpdateFlags.Null # should we include these here? self.agentdomain = None # the agent domain the agent is connected to if an OGP context self.child_regions = [] # all neighboring regions self._pending_child_regions = [] # neighbor regions an agent may connect to self.region = None # the host simulation for the agent # init AppearanceManager() self.appearance = AppearanceManager(self, self.settings) # Cache of agent_id->(first_name, last_name); per agent to prevent info leaks self.agent_id_map = {} if self.settings.LOG_VERBOSE: logger.debug('Initializing agent: %s' % (self))