2009-03-03 01:40:52 +00:00
# standard python libs
2008-11-26 06:00:42 +00:00
from logging import getLogger , CRITICAL , ERROR , WARNING , INFO , DEBUG
2009-03-03 01:40:52 +00:00
import re
import sys
import signal
2009-03-11 22:52:07 +00:00
import uuid
2009-04-27 22:48:01 +00:00
import sets
2009-03-03 01:40:52 +00:00
#related
from eventlet import api
# pyogp
from pyogp . lib . base . login import Login , LegacyLoginParams , OGPLoginParams
2009-03-21 06:28:10 +00:00
from pyogp . lib . base . datatypes import *
2009-03-03 01:40:52 +00:00
from pyogp . lib . base . exc import LoginError
from pyogp . lib . base . region import Region
2009-04-02 22:24:16 +00:00
from pyogp . lib . base . inventory import *
2009-03-26 20:10:13 +00:00
from pyogp . lib . base . groups import *
2009-04-27 22:48:01 +00:00
from pyogp . lib . base . event_system import *
2009-03-11 03:56:56 +00:00
# from pyogp.lib.base.appearance import Appearance
2008-09-16 06:26:17 +00:00
2009-03-03 01:40:52 +00:00
# pyogp messaging
2009-03-12 20:48:26 +00:00
from pyogp . lib . base . event_queue import EventQueueHandler
2009-03-11 22:52:07 +00:00
from pyogp . lib . base . message . packets import *
# pyogp utilities
from pyogp . lib . base . utilities . helpers import Helpers
2009-04-27 22:48:01 +00:00
from pyogp . lib . base . utilities . enums import ImprovedIMDialogue
2008-06-27 15:10:24 +00:00
2009-03-03 01:40:52 +00:00
# initialize logging
2008-11-26 06:00:42 +00:00
logger = getLogger ( ' pyogp.lib.base.agent ' )
log = logger . log
2008-06-27 15:10:24 +00:00
class Agent ( object ) :
2009-04-27 22:48:01 +00:00
""" The Agent class is a container for agent specific data.
2009-03-11 22:52:07 +00:00
Example , of login via the agent class :
Initialize the login class
2009-04-27 22:48:01 +00:00
>> > client = Agent ( )
2009-03-11 22:52:07 +00:00
>> > client . login ( ' https://login.agni.lindenlab.com/cgi-bin/login.cgi ' , ' firstname ' , ' lastname ' , ' secret ' , start_location = ' last ' )
Sample implementations : examples / sample_agent_login . py
Tests : tests / login . txt , tests / test_agent . py
"""
2009-04-27 22:48:01 +00:00
def __init__ ( self , settings = None , firstname = ' ' , lastname = ' ' , password = ' ' , agent_id = None , events_handler = None ) :
2009-03-11 22:52:07 +00:00
""" initialize this agent """
# allow the settings to be passed in
# otherwise, grab the defaults
if settings != None :
self . settings = settings
else :
from pyogp . lib . base . settings import Settings
self . settings = Settings ( )
2009-04-27 22:48:01 +00:00
# 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 = EventsHandler ( )
2009-03-11 22:52:07 +00:00
# signal handler to capture erm signals
self . signal_handler = signal . signal ( signal . SIGINT , self . sigint_handler )
# storage containers for agent attributes
2009-03-30 16:16:26 +00:00
# we overwrite with what the grid tells us, rather than what
2009-03-11 22:52:07 +00:00
# is passed in and stored in Login()
2009-03-27 21:48:13 +00:00
self . firstname = firstname
self . lastname = lastname
self . password = password
2009-03-11 22:52:07 +00:00
self . agent_id = None
self . session_id = None
self . secure_session_id = None
2009-03-30 16:16:26 +00:00
self . name = self . Name ( )
2009-03-11 22:52:07 +00:00
# other storage containers
self . inventory_host = None
self . agent_access = None
self . udp_blacklist = None
self . home = None
self . inventory = None
# additional attributes
self . login_response = None
self . connected = False
self . grid_type = None
self . running = True
2009-04-01 23:49:16 +00:00
#self.packet_handler = PacketHandler(self.settings)
2009-03-17 04:24:08 +00:00
self . event_queue_handler = EventQueueHandler ( self . settings )
2009-03-11 22:52:07 +00:00
self . helpers = Helpers ( )
# data we store as it comes in from the grid
2009-03-21 06:28:10 +00:00
self . Position = Vector3 ( ) # this will get updated later, but seed it with 000
2009-04-27 22:48:01 +00:00
self . ActiveGroupID = UUID ( )
2009-03-11 22:52:07 +00:00
# should we include these here?
self . agentdomain = None # the agent domain the agent is connected to if an OGP context
2009-04-01 23:49:16 +00:00
self . child_regions = [ ] # all neighboring regions
self . _pending_child_regions = [ ] # neighbor regions an agent may connect to
2009-03-11 22:52:07 +00:00
self . region = None # the host simulation for the agent
# init Appearance()
# self.appearance = Appearance(self.settings, self)
if self . settings . LOG_VERBOSE : log ( DEBUG , ' Initializing agent: %s ' % ( self ) )
2009-03-26 20:10:13 +00:00
def Name ( self ) :
2009-04-27 22:48:01 +00:00
""" returns a concatenated firstname + ' ' + lastname """
2009-03-26 20:10:13 +00:00
return self . firstname + ' ' + self . lastname
2009-03-27 21:48:13 +00:00
def login ( self , loginuri , firstname = None , lastname = None , password = None , login_params = None , start_location = None , handler = None , connect_region = True ) :
2009-04-27 22:48:01 +00:00
""" login to a login endpoint using the Login() class """
2009-03-11 22:52:07 +00:00
if ( re . search ( ' auth.cgi$ ' , loginuri ) ) :
self . grid_type = ' OGP '
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
elif ( re . search ( ' login.cgi$ ' , loginuri ) ) :
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
self . grid_type = ' Legacy '
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
else :
log ( WARNING , ' Unable to identify the loginuri schema. Stopping ' )
sys . exit ( - 1 )
2009-03-03 01:40:52 +00:00
2009-03-27 21:48:13 +00:00
if firstname != None :
self . firstname = firstname
if lastname != None :
2009-03-30 16:16:26 +00:00
self . lastname = lastname
2009-03-27 21:48:13 +00:00
if password != None :
2009-03-30 16:16:26 +00:00
self . password = password
2009-03-27 21:48:13 +00:00
2009-03-11 22:52:07 +00:00
# handle either login params passed in, or, account info
if login_params == None :
2008-11-26 06:00:42 +00:00
2009-03-27 21:48:13 +00:00
if ( self . firstname == ' ' ) or ( self . lastname == ' ' ) or ( self . password == ' ' ) :
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
raise LoginError ( ' Unable to login an unknown agent. ' )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
else :
2008-11-26 06:00:42 +00:00
2009-03-27 21:48:13 +00:00
self . _login_params = self . _get_login_params ( loginuri , self . firstname , self . lastname , self . password )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
else :
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
self . _login_params = login_params
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# login and parse the response
login = Login ( settings = self . settings )
2008-11-26 06:00:42 +00:00
2009-04-27 22:48:01 +00:00
self . login_response = login . login ( loginuri , self . _login_params , start_location , handler = handler )
self . _parse_login_response ( )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
# ToDo: what to do with self.login_response['look_at']?
2008-11-26 06:00:42 +00:00
2009-04-01 23:49:16 +00:00
if self . settings . MULTIPLE_SIM_CONNECTIONS :
api . spawn ( self . _monitor_for_new_regions )
2009-03-11 22:52:07 +00:00
if connect_region :
self . _enable_current_region ( )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
def logout ( self ) :
2009-04-27 22:48:01 +00:00
""" logs an agent out of the current region. calls Region()._kill_coroutines() for all child regions, and Region().logout() for the host region """
if not self . connected :
log ( INFO , ' Agent is not logged into the grid. Stopping. ' )
sys . exit ( )
2009-03-03 01:40:52 +00:00
2009-03-27 21:48:13 +00:00
self . running = False
if self . region == None :
return
2009-04-01 23:49:16 +00:00
else :
# kill udp and or event queue for child regions
[ region . _kill_coroutines ( ) for region in self . child_regions ]
if self . region . logout ( ) :
self . connected = False
2009-03-09 21:43:15 +00:00
2009-03-27 21:48:13 +00:00
# zero out the password in case we dump it somewhere
self . password = ' '
2009-03-11 22:52:07 +00:00
def _get_login_params ( self , loginuri , firstname , lastname , password ) :
2009-04-27 22:48:01 +00:00
""" get the proper login parameters of the legacy or ogp enabled grid """
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
if self . grid_type == ' OGP ' :
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
login_params = OGPLoginParams ( firstname , lastname , password )
2008-06-27 15:10:24 +00:00
2009-03-11 22:52:07 +00:00
elif self . grid_type == ' Legacy ' :
2008-06-27 15:10:24 +00:00
2009-03-11 22:52:07 +00:00
login_params = LegacyLoginParams ( firstname , lastname , password )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
return login_params
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
def _parse_login_response ( self ) :
2009-04-27 22:48:01 +00:00
""" evaluates the login response and propagates data to the Agent() attributes. enables Inventory() if settings dictate """
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
if self . grid_type == ' Legacy ' :
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
self . firstname = re . sub ( r ' \ " ' , ' ' , self . login_response [ ' first_name ' ] )
self . lastname = self . login_response [ ' last_name ' ]
2009-04-27 22:48:01 +00:00
self . agent_id = UUID ( self . login_response [ ' agent_id ' ] )
self . session_id = UUID ( self . login_response [ ' session_id ' ] )
self . secure_session_id = UUID ( self . login_response [ ' secure_session_id ' ] )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
self . connected = bool ( self . login_response [ ' login ' ] )
self . inventory_host = self . login_response [ ' inventory_host ' ]
self . agent_access = self . login_response [ ' agent_access ' ]
self . udp_blacklist = self . login_response [ ' udp_blacklist ' ]
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
if self . login_response . has_key ( ' home ' ) : self . home = Home ( self . login_response [ ' home ' ] )
2009-01-29 06:58:03 +00:00
2009-03-11 22:52:07 +00:00
elif self . grid_type == ' OGP ' :
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
pass
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
def _enable_current_region ( self , region_x = None , region_y = None , seed_capability = None , udp_blacklist = None , sim_ip = None , sim_port = None , circuit_code = None ) :
2009-04-27 22:48:01 +00:00
""" enables and connects udp and event queue for an agent ' s current region """
2009-03-03 01:40:52 +00:00
2009-03-30 18:26:21 +00:00
if self . login_response . has_key ( ' circuit_code ' ) :
self . circuit_code = self . login_response [ ' circuit_code ' ]
2009-03-26 20:10:13 +00:00
2009-03-11 22:52:07 +00:00
# enable the current region, setting connect = True
2009-04-01 23:49:16 +00:00
self . region = Region ( self . login_response [ ' region_x ' ] , self . login_response [ ' region_y ' ] , self . login_response [ ' seed_capability ' ] , self . login_response [ ' udp_blacklist ' ] , self . login_response [ ' sim_ip ' ] , self . login_response [ ' sim_port ' ] , self . login_response [ ' circuit_code ' ] , self , settings = self . settings , event_queue_handler = self . event_queue_handler )
self . region . is_host_region = True
self . _enable_callbacks ( )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# start the simulator udp and event queue connections
2009-04-01 23:49:16 +00:00
if self . settings . LOG_COROUTINE_SPAWNS : log ( INFO , " Spawning a coroutine for connecting to the agent ' s host region. " )
2009-03-11 22:52:07 +00:00
api . spawn ( self . region . connect )
2009-03-03 01:40:52 +00:00
2009-04-27 22:48:01 +00:00
while self . region . capabilities == { } :
api . sleep ( 0 )
if self . settings . ENABLE_INVENTORY_MANAGEMENT :
inventory_caps = [ ' FetchInventory ' , ' WebFetchInventoryDescendents ' , ' FetchLib ' , ' FetchLibDescendents ' ]
if sets . Set ( self . region . capabilities . keys ( ) ) . intersection ( inventory_caps ) :
caps = dict ( [ ( capname , self . region . capabilities [ capname ] ) for capname in inventory_caps ] )
log ( INFO , " Using the capability based inventory management mechanism " )
self . inventory = AIS ( self , caps )
else :
log ( INFO , " Using the UDP based inventory management mechanism " )
self . inventory = UDP_Inventory ( self )
self . inventory . _parse_folders_from_login_response ( )
self . inventory . enable_callbacks ( )
2009-04-01 23:49:16 +00:00
def _enable_child_region ( self , region_params ) :
2009-03-26 20:10:13 +00:00
""" enables a child region. eligible simulators are sent in EnableSimulator over the event queue, and routed through the packet handler """
2009-03-30 16:16:26 +00:00
# if this is the sim we are already connected to, skip it
2009-04-01 23:49:16 +00:00
if self . region . sim_ip == region_params [ ' IP ' ] and self . region . sim_port == region_params [ ' Port ' ] :
2009-03-30 16:16:26 +00:00
#self.region.sendCompleteAgentMovement()
2009-04-01 23:49:16 +00:00
log ( DEBUG , " Not enabling a region we are already connected to: %s " % ( str ( region_params [ ' IP ' ] ) + " : " + str ( region_params [ ' Port ' ] ) ) )
2009-03-30 16:16:26 +00:00
return
2009-04-01 23:49:16 +00:00
child_region = Region ( circuit_code = self . circuit_code , sim_ip = region_params [ ' IP ' ] , sim_port = region_params [ ' Port ' ] , handle = region_params [ ' Handle ' ] , agent = self , settings = self . settings , event_queue_handler = self . event_queue_handler )
2009-03-26 20:10:13 +00:00
2009-04-01 23:49:16 +00:00
self . child_regions . append ( child_region )
2009-03-26 20:10:13 +00:00
2009-04-01 23:49:16 +00:00
log ( INFO , " Enabling a child region with ip:port of %s " % ( str ( region_params [ ' IP ' ] ) + " : " + str ( region_params [ ' Port ' ] ) ) )
if self . settings . LOG_COROUTINE_SPAWNS : log ( INFO , " Spawning a coroutine for connecting to a neighboring region. " )
2009-03-26 20:10:13 +00:00
api . spawn ( child_region . connect_child )
2009-04-01 23:49:16 +00:00
def _monitor_for_new_regions ( self ) :
2009-04-27 22:48:01 +00:00
""" enable connections to neighboring regions found in the pending queue """
2009-04-01 23:49:16 +00:00
2009-03-26 20:10:13 +00:00
while self . running :
2009-04-01 23:49:16 +00:00
if len ( self . _pending_child_regions ) > 0 :
for region_params in self . _pending_child_regions :
self . _enable_child_region ( region_params )
self . _pending_child_regions . remove ( region_params )
2009-03-26 20:10:13 +00:00
api . sleep ( 0 )
2009-04-01 23:49:16 +00:00
def _start_EQ_on_neighboring_region ( self , message ) :
2009-04-27 22:48:01 +00:00
""" enables the event queue on an agent ' s neighboring region """
2009-04-01 23:49:16 +00:00
region = [ region for region in self . child_regions if message . sim_ip_and_port == str ( region . sim_ip ) + " : " + str ( region . sim_port ) ]
if region != [ ] :
region [ 0 ] . _set_seed_capability ( message . seed_capability_url )
region [ 0 ] . _get_region_capabilities ( )
log ( DEBUG , ' Spawning neighboring region event queue connection ' )
region [ 0 ] . _startEventQueue ( )
def _enable_callbacks ( self ) :
2009-04-27 22:48:01 +00:00
""" enable the Agents() callback handlers for packet received events """
2009-04-01 23:49:16 +00:00
2009-04-06 21:29:17 +00:00
if self . settings . ENABLE_INVENTORY_MANAGEMENT and self . inventory != None :
self . inventory . enable_callbacks ( )
2009-04-01 23:49:16 +00:00
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 ' )
2009-04-06 21:29:17 +00:00
onEnableSimulator_received . subscribe ( self . onEnableSimulator )
2009-04-01 23:49:16 +00:00
onEstablishAgentCommunication_received = self . event_queue_handler . _register ( ' EstablishAgentCommunication ' )
2009-04-06 21:29:17 +00:00
onEstablishAgentCommunication_received . subscribe ( self . onEstablishAgentCommunication )
2009-04-01 23:49:16 +00:00
if self . settings . HANDLE_PACKETS :
onAlertMessage_received = self . region . packet_handler . _register ( ' AlertMessage ' )
2009-04-06 21:29:17 +00:00
onAlertMessage_received . subscribe ( self . onAlertMessage )
2009-04-01 23:49:16 +00:00
onAgentDataUpdate_received = self . region . packet_handler . _register ( ' AgentDataUpdate ' )
2009-04-06 21:29:17 +00:00
onAgentDataUpdate_received . subscribe ( self . onAgentDataUpdate )
2009-04-01 23:49:16 +00:00
onAgentMovementComplete_received = self . region . packet_handler . _register ( ' AgentMovementComplete ' )
2009-04-06 21:29:17 +00:00
onAgentMovementComplete_received . subscribe ( self . onAgentMovementComplete )
2009-04-01 23:49:16 +00:00
onHealthMessage_received = self . region . packet_handler . _register ( ' HealthMessage ' )
2009-04-06 21:29:17 +00:00
onHealthMessage_received . subscribe ( self . onHealthMessage )
2009-04-02 22:24:16 +00:00
2009-04-27 22:48:01 +00:00
onImprovedInstantMessage_received = self . region . packet_handler . _register ( ' ImprovedInstantMessage ' )
onImprovedInstantMessage_received . subscribe ( self . onImprovedInstantMessage )
2009-04-01 23:49:16 +00:00
if self . settings . ENABLE_COMMUNICATIONS_TRACKING :
onChatFromSimulator_received = self . region . packet_handler . _register ( ' ChatFromSimulator ' )
onChatFromSimulator_received . subscribe ( self . helpers . log_packet , self )
2009-03-11 22:52:07 +00:00
def send_AgentDataUpdateRequest ( self ) :
2009-04-27 22:48:01 +00:00
""" queues a packet requesting an agent data update """
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
packet = AgentDataUpdateRequestPacket ( )
2009-03-03 01:40:52 +00:00
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = self . agent_id
packet . AgentData [ ' SessionID ' ] = self . session_id
2009-03-04 07:27:56 +00:00
2009-03-11 22:52:07 +00:00
self . region . enqueue_message ( packet ( ) )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# ~~~~~~~~~~~~~~
# Communications
# ~~~~~~~~~~~~~~
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# Chat
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
def say ( self , Message , Type = 1 , Channel = 0 ) :
2009-04-27 22:48:01 +00:00
""" queues a packet to send open chat via ChatFromViewer
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
Channel : 0 is open chat
Type : 0 = Whisper
1 = Say
2 = Shout
"""
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
packet = ChatFromViewerPacket ( )
2009-03-03 01:40:52 +00:00
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = self . agent_id
packet . AgentData [ ' SessionID ' ] = self . session_id
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
packet . ChatData [ ' Message ' ] = Message + ' \x00 ' # Message needs a terminator. Arnold was busy as gov...
packet . ChatData [ ' Type ' ] = Type
packet . ChatData [ ' Channel ' ] = Channel
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
self . region . enqueue_message ( packet ( ) )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# Instant Message (im, group chat)
2009-03-03 01:40:52 +00:00
2009-03-12 20:48:26 +00:00
def instant_message ( self , ToAgentID = None , Message = None , _ID = None ) :
2009-04-27 22:48:01 +00:00
""" sends an instant message to another avatar, wrapping Agent().send_ImprovedInstantMessage() with some handy defaults """
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
if ToAgentID != None and Message != None :
2009-03-03 01:40:52 +00:00
2009-04-27 22:48:01 +00:00
if _ID == None : _ID = self . agent_id
2009-03-12 20:48:26 +00:00
2009-04-27 22:48:01 +00:00
_AgentID = self . agent_id
_SessionID = self . session_id
2009-03-11 22:52:07 +00:00
_FromGroup = False
2009-04-27 22:48:01 +00:00
_ToAgentID = UUID ( str ( ToAgentID ) )
2009-03-11 22:52:07 +00:00
_ParentEstateID = 0
2009-04-27 22:48:01 +00:00
_RegionID = UUID ( )
2009-03-11 22:52:07 +00:00
_Position = self . Position
_Offline = 0
2009-04-27 22:48:01 +00:00
_Dialog = ImprovedIMDialogue . FromAgent
2009-03-12 20:48:26 +00:00
_ID = _ID
2009-03-11 22:52:07 +00:00
_Timestamp = 0
_FromAgentName = self . firstname + ' ' + self . lastname
_Message = Message
_BinaryBucket = ' '
2009-03-04 07:27:56 +00:00
2009-03-11 22:52:07 +00:00
self . send_ImprovedInstantMessage ( _AgentID , _SessionID , _FromGroup , _ToAgentID , _ParentEstateID , _RegionID , _Position , _Offline , _Dialog , _ID , _Timestamp , _FromAgentName , _Message , _BinaryBucket )
2009-03-04 07:27:56 +00:00
2009-03-11 22:52:07 +00:00
else :
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
log ( INFO , " Please specify an agentid and message to send in agent.instant_message " )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
def send_ImprovedInstantMessage ( self , AgentID = None , SessionID = None , FromGroup = None , ToAgentID = None , ParentEstateID = None , RegionID = None , Position = None , Offline = None , Dialog = None , _ID = None , Timestamp = None , FromAgentName = None , Message = None , BinaryBucket = None , AgentDataBlock = { } , MessageBlockBlock = { } ) :
2009-04-27 22:48:01 +00:00
""" sends an instant message packet to ToAgentID. this is a multi-purpose message for inventory offer handling, im, group chat, and more """
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
packet = ImprovedInstantMessagePacket ( )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
if AgentDataBlock == { } :
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = AgentID
packet . AgentData [ ' SessionID ' ] = SessionID
2009-03-11 22:52:07 +00:00
else :
packet . AgentData = AgentDataBlock
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
if FromAgentName == None :
2009-04-27 22:48:01 +00:00
FromAgentName = self . Name ( )
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
# ha! when scripting out packets.py, never considered a block named *block
if MessageBlockBlock == { } :
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
packet . MessageBlock [ ' FromGroup ' ] = FromGroup # Bool
2009-04-27 22:48:01 +00:00
packet . MessageBlock [ ' ToAgentID ' ] = UUID ( str ( ToAgentID ) ) # LLUUID
2009-03-11 22:52:07 +00:00
packet . MessageBlock [ ' ParentEstateID ' ] = ParentEstateID # U32
2009-04-27 22:48:01 +00:00
packet . MessageBlock [ ' RegionID ' ] = UUID ( str ( RegionID ) ) # LLUUID
2009-03-26 20:10:13 +00:00
packet . MessageBlock [ ' Position ' ] = Position ( ) # LLVector3
2009-03-11 22:52:07 +00:00
packet . MessageBlock [ ' Offline ' ] = Offline # U8
packet . MessageBlock [ ' Dialog ' ] = Dialog # U8 IM Type
2009-04-27 22:48:01 +00:00
packet . MessageBlock [ ' ID ' ] = UUID ( str ( _ID ) ) # LLUUID
2009-03-11 22:52:07 +00:00
packet . MessageBlock [ ' Timestamp ' ] = Timestamp # U32
packet . MessageBlock [ ' FromAgentName ' ] = FromAgentName # Variable 1
packet . MessageBlock [ ' Message ' ] = Message # Variable 2
packet . MessageBlock [ ' BinaryBucket ' ] = BinaryBucket # Variable 2
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
self . region . enqueue_message ( packet ( ) , True )
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
def send_RetrieveInstantMessages ( self ) :
""" asks simulator for instant messages stored while agent was offline """
2009-03-09 21:43:15 +00:00
2009-03-11 22:52:07 +00:00
packet = RetrieveInstantMessagesPackets ( )
2009-03-09 21:43:15 +00:00
2009-04-27 22:48:01 +00:00
packet . AgentDataBlock [ ' AgentID ' ] = self . agent_id
packet . AgentDataBlock [ ' SessionID ' ] = self . session_id
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
self . region . enqueue_message ( packet ( ) )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
def sigint_handler ( self , signal , frame ) :
2009-04-27 22:48:01 +00:00
""" catches terminal signals (Ctrl-C) to kill running client instances """
2009-03-11 22:52:07 +00:00
log ( INFO , " Caught signal... %d . Stopping " % signal )
2009-03-27 21:48:13 +00:00
#self.running = False
2009-03-11 22:52:07 +00:00
self . logout ( )
#sys.exit(0)
2009-03-11 03:56:56 +00:00
2009-03-11 22:52:07 +00:00
def __repr__ ( self ) :
""" returns a representation of the agent """
2009-03-11 03:56:56 +00:00
2009-03-11 22:52:07 +00:00
if self . firstname == None :
return ' A new agent instance '
else :
2009-04-27 22:48:01 +00:00
return self . Name ( )
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
def onAgentDataUpdate ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received AgentDataUpdate messages which populates various Agent() attributes """
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
if self . agent_id == None :
self . agent_id = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' AgentID ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
if self . firstname == None :
self . firstname = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' FirstName ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
if self . lastname == None :
self . firstname = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' LastName ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . GroupTitle = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' GroupTitle ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . ActiveGroupID = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' ActiveGroupID ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . GroupPowers = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' GroupPowers ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . GroupName = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' GroupName ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
def onAgentMovementComplete ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received AgentMovementComplete messages which populates various Agent() and Region() attributes """
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . Position = packet . message_data . blocks [ ' Data ' ] [ 0 ] . get_variable ( ' Position ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . LookAt = packet . message_data . blocks [ ' Data ' ] [ 0 ] . get_variable ( ' LookAt ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . region . RegionHandle = packet . message_data . blocks [ ' Data ' ] [ 0 ] . get_variable ( ' RegionHandle ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
#agent.Timestamp = packet.message_data.blocks['Data'][0].get_variable('Timestamp')
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . region . ChannelVersion = packet . message_data . blocks [ ' SimData ' ] [ 0 ] . get_variable ( ' ChannelVersion ' ) . data
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
def onHealthMessage ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received HealthMessage messages which populates Agent().health """
2009-03-03 01:40:52 +00:00
2009-04-06 21:29:17 +00:00
self . health = packet . message_data . blocks [ ' HealthData ' ] [ 0 ] . get_variable ( ' Health ' ) . data
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
def onAgentGroupDataUpdate ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received AgentGroupDataUpdate messages which updates stored group instances in the group_manager """
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
# AgentData block
AgentID = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' AgentID ' ) . data
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
# GroupData block
for GroupData_block in packet . message_data . blocks [ ' GroupData ' ] :
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
AcceptNotices = GroupData_block . get_variable ( ' AcceptNotices ' ) . data
GroupPowers = GroupData_block . get_variable ( ' GroupPowers ' ) . data
2009-04-27 22:48:01 +00:00
GroupID = GroupData_block . get_variable ( ' GroupID ' ) . data
2009-04-06 21:29:17 +00:00
GroupName = GroupData_block . get_variable ( ' GroupName ' ) . data
ListInProfile = GroupData_block . get_variable ( ' ListInProfile ' ) . data
Contribution = GroupData_block . get_variable ( ' Contribution ' ) . data
2009-04-27 22:48:01 +00:00
GroupInsigniaID = GroupData_block . get_variable ( ' GroupInsigniaID ' ) . data
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
# make sense of group powers
GroupPowers = [ ord ( x ) for x in GroupPowers ]
GroupPowers = ' ' . join ( [ str ( x ) for x in GroupPowers ] )
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
group = Group ( AcceptNotices , GroupPowers , GroupID , GroupName , ListInProfile , Contribution , GroupInsigniaID )
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
self . group_manager . store_group ( group )
2009-03-13 22:09:43 +00:00
2009-04-06 21:29:17 +00:00
def onChatFromSimulator ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received ChatFromSimulator messages which parses and fires a ChatReceived event. (not implemented """
# ToDo: implement firing an event when this is called
2009-03-09 21:43:15 +00:00
2009-04-06 21:29:17 +00:00
pass
'''
2009-03-11 22:52:07 +00:00
{
2009-04-06 21:29:17 +00:00
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
}
2009-03-11 22:52:07 +00:00
}
2009-04-06 21:29:17 +00:00
'''
def onImprovedInstantMessage ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received ImprovedInstantMessage messages. much is passed in this message, and handling the data is only partially implemented """
2009-04-06 21:29:17 +00:00
2009-04-27 22:48:01 +00:00
log ( INFO , " Working on parsing ImprovedInstantMessage messages.... " )
Dialog = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' Dialog ' ) . data
FromAgentID = packet . message_data . blocks [ ' AgentData ' ] [ 0 ] . get_variable ( ' AgentID ' ) . data
if Dialog == ImprovedIMDialogue . InventoryOffered :
self . inventory . handle_inventory_offer ( packet )
elif Dialog == ImprovedIMDialogue . InventoryAccepted :
if str ( FromAgentID ) != str ( self . agent_id ) :
FromAgentName = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' FromAgentName ' ) . data
InventoryName = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' Message ' ) . data
log ( INFO , " Agent %s accepted the inventory offer. " % ( FromAgentName ) )
elif Dialog == ImprovedIMDialogue . InventoryDeclined :
if str ( FromAgentID ) != str ( self . agent_id ) :
FromAgentName = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' FromAgentName ' ) . data
InventoryName = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' Message ' ) . data
log ( INFO , " Agent %s declined the inventory offer. " % ( FromAgentName ) )
elif Dialog == ImprovedIMDialogue . FromAgent :
RegionID = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' RegionID ' ) . data
Position = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' Position ' ) . data
ID = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' ID ' ) . data
FromAgentName = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' FromAgentName ' ) . data
Message = packet . message_data . blocks [ ' MessageBlock ' ] [ 0 ] . get_variable ( ' Message ' ) . data
message = InstantMessageReceived ( FromAgentID , RegionID , Position , ID , FromAgentName , Message )
log ( INFO , " Received instant message from %s : %s " % ( FromAgentName , Message ) )
self . events_handler . _handle ( message )
else :
self . helpers . log_packet ( packet , self )
2009-04-06 21:29:17 +00:00
def onAlertMessage ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received AlertMessage messages. logs and raises an event """
# ToDo: raise an event when this is received
2009-04-06 21:29:17 +00:00
AlertMessage = packet . message_data . blocks [ ' AlertData ' ] [ 0 ] . get_variable ( ' Message ' ) . data
log ( WARNING , " AlertMessage from simulator: %s " % ( AlertMessage ) )
def onEnableSimulator ( self , packet ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received EnableSimulator messages. stores the region data for later connections """
2009-04-06 21:29:17 +00:00
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 }
2009-03-09 21:43:15 +00:00
2009-04-06 21:29:17 +00:00
log ( INFO , ' Received EnableSimulator for %s ' % ( str ( IP ) + " : " + str ( Port ) ) )
2009-03-14 00:09:15 +00:00
2009-04-06 21:29:17 +00:00
# are we already prepping to connect to the sim?
if region_params not in self . _pending_child_regions :
2009-03-14 00:09:15 +00:00
2009-04-06 21:29:17 +00:00
# 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 ) :
2009-04-27 22:48:01 +00:00
""" callback handler for received EstablishAgentCommunication messages. try to enable the event queue for a neighboring region based on the data received """
2009-04-06 21:29:17 +00:00
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 )
2009-03-14 00:09:15 +00:00
2009-03-03 01:40:52 +00:00
class Home ( object ) :
2009-04-27 22:48:01 +00:00
""" contains the parameters describing an agent ' s home location as returned in login_response[ ' home ' ] """
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
def __init__ ( self , params ) :
2009-04-27 22:48:01 +00:00
""" initialize the Home object by parsing the data passed in """
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# eval(params) would be nice, but fails to parse the string the way one thinks it might
items = params . split ( ' , \' ' )
2009-03-03 01:40:52 +00:00
2009-03-11 22:52:07 +00:00
# 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 ] ) ) )
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
self . global_x = self . region_handle [ 0 ]
self . global_y = self . region_handle [ 1 ]
2008-11-26 06:00:42 +00:00
2009-03-11 22:52:07 +00:00
self . local_x = self . position [ 0 ]
self . local_y = self . position [ 1 ]
2009-03-26 20:10:13 +00:00
self . local_z = self . position [ 2 ]
2009-04-27 22:48:01 +00:00
"""
Contributors can be viewed at :
http : / / svn . secondlife . com / svn / linden / projects / 2008 / pyogp / CONTRIBUTORS . txt
$ LicenseInfo : firstyear = 2008 & license = apachev2 $
Copyright 2009 , Linden Research , Inc .
Licensed under the Apache License , Version 2.0 ( the " License " ) .
You may obtain a copy of the License at :
http : / / www . apache . org / licenses / LICENSE - 2.0
or in
http : / / svn . secondlife . com / svn / linden / projects / 2008 / pyogp / LICENSE . txt
$ / LicenseInfo $
"""