2009-04-21 15:30:03 +00:00
/ *
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2009-04-21 15:30:03 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using System.Reflection ;
2009-04-29 22:31:00 +00:00
using System.Timers ;
2009-04-21 15:30:03 +00:00
using log4net ;
2009-08-05 20:20:46 +00:00
using Mono.Addins ;
2009-04-21 15:30:03 +00:00
using Nini.Config ;
using OpenMetaverse ;
using OpenMetaverse.StructuredData ;
using OpenSim.Framework ;
2009-04-25 18:58:18 +00:00
using OpenSim.Framework.Communications ;
2009-04-21 15:30:03 +00:00
using OpenSim.Region.Framework.Interfaces ;
using OpenSim.Region.Framework.Scenes ;
2010-01-08 18:43:34 +00:00
using OpenSim.Services.Interfaces ;
2013-08-02 19:26:28 +00:00
using System.Text ;
2009-04-21 15:30:03 +00:00
using DirFindFlags = OpenMetaverse . DirectoryManager . DirFindFlags ;
namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
{
2012-11-13 02:08:02 +00:00
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
2009-08-05 18:15:53 +00:00
public class GroupsModule : ISharedRegionModule , IGroupsModule
2009-04-21 15:30:03 +00:00
{
/// <summary>
2009-04-21 20:44:17 +00:00
/// ; To use this module, you must specify the following in your OpenSim.ini
2009-04-21 15:30:03 +00:00
/// [GROUPS]
/// Enabled = true
2009-08-05 21:56:48 +00:00
///
2009-08-06 16:34:30 +00:00
/// Module = GroupsModule
2009-08-05 21:56:48 +00:00
/// NoticesEnabled = true
/// DebugEnabled = true
///
/// GroupsServicesConnectorModule = XmlRpcGroupsServicesConnector
/// XmlRpcServiceURL = http://osflotsam.org/xmlrpc.php
/// XmlRpcServiceReadKey = 1234
2009-04-29 22:31:00 +00:00
/// XmlRpcServiceWriteKey = 1234
2009-04-21 15:30:03 +00:00
///
2009-08-06 16:34:30 +00:00
/// MessagingModule = GroupsMessagingModule
/// MessagingEnabled = true
2009-08-05 21:56:48 +00:00
///
2009-04-21 20:44:17 +00:00
/// ; Disables HTTP Keep-Alive for Groups Module HTTP Requests, work around for
/// ; a problem discovered on some Windows based region servers. Only disable
/// ; if you see a large number (dozens) of the following Exceptions:
/// ; System.Net.WebException: The request was aborted: The request was canceled.
///
/// XmlRpcDisableKeepAlive = false
2009-04-21 15:30:03 +00:00
/// </summary>
private static readonly ILog m_log =
LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2009-04-22 10:03:38 +00:00
private List < Scene > m_sceneList = new List < Scene > ( ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
private IMessageTransferModule m_msgTransferModule = null ;
2009-04-25 18:58:18 +00:00
2009-08-05 18:15:53 +00:00
private IGroupsServicesConnector m_groupData = null ;
2009-04-21 15:30:03 +00:00
// Configuration settings
2009-04-22 10:03:38 +00:00
private bool m_groupsEnabled = false ;
private bool m_groupNoticesEnabled = true ;
2011-12-16 20:53:50 +00:00
private bool m_debugEnabled = false ;
2012-03-27 20:09:58 +00:00
private int m_levelGroupCreate = 0 ;
2009-04-21 15:30:03 +00:00
2012-11-12 19:18:20 +00:00
#region Region Module interfaceBase Members
2009-04-21 15:30:03 +00:00
public void Initialise ( IConfigSource config )
{
IConfig groupsConfig = config . Configs [ "Groups" ] ;
if ( groupsConfig = = null )
{
// Do not run this module by default.
return ;
}
else
{
2009-04-22 10:03:38 +00:00
m_groupsEnabled = groupsConfig . GetBoolean ( "Enabled" , false ) ;
if ( ! m_groupsEnabled )
2009-04-21 15:30:03 +00:00
{
return ;
}
2009-08-05 21:56:48 +00:00
if ( groupsConfig . GetString ( "Module" , "Default" ) ! = Name )
2009-04-21 15:30:03 +00:00
{
2009-04-22 10:03:38 +00:00
m_groupsEnabled = false ;
2009-04-21 15:30:03 +00:00
return ;
}
2009-07-24 20:08:26 +00:00
m_log . InfoFormat ( "[GROUPS]: Initializing {0}" , this . Name ) ;
2009-05-14 21:38:17 +00:00
2009-08-05 21:56:48 +00:00
m_groupNoticesEnabled = groupsConfig . GetBoolean ( "NoticesEnabled" , true ) ;
2011-01-04 23:23:42 +00:00
m_debugEnabled = groupsConfig . GetBoolean ( "DebugEnabled" , false ) ;
2012-03-27 20:09:58 +00:00
m_levelGroupCreate = groupsConfig . GetInt ( "LevelGroupCreate" , 0 ) ;
2009-04-21 15:30:03 +00:00
}
}
public void AddRegion ( Scene scene )
{
2009-04-22 10:03:38 +00:00
if ( m_groupsEnabled )
2012-10-19 22:45:55 +00:00
{
2009-04-21 15:30:03 +00:00
scene . RegisterModuleInterface < IGroupsModule > ( this ) ;
2012-10-19 22:45:55 +00:00
scene . AddCommand (
2013-01-10 22:46:25 +00:00
"Debug" ,
2012-10-19 22:45:55 +00:00
this ,
"debug groups verbose" ,
"debug groups verbose <true|false>" ,
"This setting turns on very verbose groups debugging" ,
HandleDebugGroupsVerbose ) ;
}
}
private void HandleDebugGroupsVerbose ( object modules , string [ ] args )
{
if ( args . Length < 4 )
{
MainConsole . Instance . Output ( "Usage: debug groups verbose <true|false>" ) ;
return ;
}
bool verbose = false ;
if ( ! bool . TryParse ( args [ 3 ] , out verbose ) )
{
MainConsole . Instance . Output ( "Usage: debug groups verbose <true|false>" ) ;
return ;
}
m_debugEnabled = verbose ;
2012-10-20 00:08:52 +00:00
MainConsole . Instance . OutputFormat ( "{0} verbose logging set to {1}" , Name , m_debugEnabled ) ;
2009-04-21 15:30:03 +00:00
}
public void RegionLoaded ( Scene scene )
{
2009-04-22 10:03:38 +00:00
if ( ! m_groupsEnabled )
2009-04-21 15:30:03 +00:00
return ;
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-08-05 18:15:53 +00:00
if ( m_groupData = = null )
{
m_groupData = scene . RequestModuleInterface < IGroupsServicesConnector > ( ) ;
// No Groups Service Connector, then nothing works...
if ( m_groupData = = null )
{
m_groupsEnabled = false ;
m_log . Error ( "[GROUPS]: Could not get IGroupsServicesConnector" ) ;
Close ( ) ;
return ;
}
}
2009-04-22 10:03:38 +00:00
if ( m_msgTransferModule = = null )
2009-04-21 15:30:03 +00:00
{
2009-04-27 05:22:44 +00:00
m_msgTransferModule = scene . RequestModuleInterface < IMessageTransferModule > ( ) ;
2009-04-25 18:58:18 +00:00
// No message transfer module, no notices, group invites, rejects, ejects, etc
2009-04-27 05:22:44 +00:00
if ( m_msgTransferModule = = null )
2009-04-25 18:58:18 +00:00
{
2009-04-27 05:22:44 +00:00
m_groupsEnabled = false ;
2010-12-14 23:36:34 +00:00
m_log . Warn ( "[GROUPS]: Could not get MessageTransferModule" ) ;
2009-04-25 18:58:18 +00:00
}
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
lock ( m_sceneList )
{
2009-04-27 05:22:44 +00:00
m_sceneList . Add ( scene ) ;
2009-04-25 18:58:18 +00:00
}
2009-04-21 15:30:03 +00:00
scene . EventManager . OnNewClient + = OnNewClient ;
2010-04-06 02:56:03 +00:00
scene . EventManager . OnIncomingInstantMessage + = OnGridInstantMessage ;
2009-04-25 18:58:18 +00:00
// The InstantMessageModule itself doesn't do this,
// so lets see if things explode if we don't do it
// scene.EventManager.OnClientClosed += OnClientClosed;
2010-04-06 02:56:03 +00:00
}
2009-04-21 15:30:03 +00:00
public void RemoveRegion ( Scene scene )
{
2009-04-22 10:03:38 +00:00
if ( ! m_groupsEnabled )
2009-04-21 15:30:03 +00:00
return ;
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
lock ( m_sceneList )
{
2009-04-27 05:22:44 +00:00
m_sceneList . Remove ( scene ) ;
2009-04-25 18:58:18 +00:00
}
2009-04-21 15:30:03 +00:00
}
public void Close ( )
{
2009-04-22 10:03:38 +00:00
if ( ! m_groupsEnabled )
2009-04-21 15:30:03 +00:00
return ;
2009-04-25 18:58:18 +00:00
2009-08-05 21:56:48 +00:00
if ( m_debugEnabled ) m_log . Debug ( "[GROUPS]: Shutting down Groups module." ) ;
2009-04-21 15:30:03 +00:00
}
2009-08-10 22:08:22 +00:00
public Type ReplaceableInterface
2009-07-10 20:17:13 +00:00
{
get { return null ; }
}
2009-04-21 15:30:03 +00:00
public string Name
{
2009-08-05 21:56:48 +00:00
get { return "GroupsModule" ; }
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
2009-04-21 15:30:03 +00:00
# endregion
2009-04-25 18:58:18 +00:00
#region ISharedRegionModule Members
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
public void PostInitialise ( )
2009-04-21 15:30:03 +00:00
{
2009-04-25 18:58:18 +00:00
// NoOp
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
# endregion
2009-04-21 15:30:03 +00:00
#region EventHandlers
private void OnNewClient ( IClientAPI client )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
client . OnUUIDGroupNameRequest + = HandleUUIDGroupNameRequest ;
client . OnAgentDataUpdateRequest + = OnAgentDataUpdateRequest ;
client . OnRequestAvatarProperties + = OnRequestAvatarProperties ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Used for Notices and Group Invites/Accept/Reject
client . OnInstantMessage + = OnInstantMessage ;
2009-04-29 22:31:00 +00:00
2011-12-17 02:23:24 +00:00
// Send client their groups information.
2009-04-25 18:58:18 +00:00
SendAgentGroupDataUpdate ( client , client . AgentId ) ;
}
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
private void OnRequestAvatarProperties ( IClientAPI remoteClient , UUID avatarID )
{
2009-09-16 23:51:22 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2010-04-02 13:53:10 +00:00
//GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray();
2009-09-16 23:51:22 +00:00
GroupMembershipData [ ] avatarGroups = GetProfileListedGroupMemberships ( remoteClient , avatarID ) ;
2009-04-25 18:58:18 +00:00
remoteClient . SendAvatarGroupsReply ( avatarID , avatarGroups ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-22 10:03:38 +00:00
2009-04-25 18:58:18 +00:00
/ *
* This becomes very problematic in a shared module . In a shared module you may have more then one
* reference to IClientAPI ' s , one for 0 or 1 root connections , and 0 or more child connections .
* The OnClientClosed event does not provide anything to indicate which one of those should be closed
* nor does it provide what scene it was from so that the specific reference can be looked up .
* The InstantMessageModule . cs does not currently worry about unregistering the handles ,
* and it should be an issue , since it ' s the client that references us not the other way around
* , so as long as we don ' t keep a reference to the client laying around , the client can still be GC ' ed
private void OnClientClosed ( UUID AgentId )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
lock ( m_ActiveClients )
2009-04-21 15:30:03 +00:00
{
2009-04-25 18:58:18 +00:00
if ( m_ActiveClients . ContainsKey ( AgentId ) )
2009-04-21 15:30:03 +00:00
{
2009-04-25 18:58:18 +00:00
IClientAPI client = m_ActiveClients [ AgentId ] ;
2009-04-21 15:30:03 +00:00
client . OnUUIDGroupNameRequest - = HandleUUIDGroupNameRequest ;
client . OnAgentDataUpdateRequest - = OnAgentDataUpdateRequest ;
client . OnDirFindQuery - = OnDirFindQuery ;
client . OnInstantMessage - = OnInstantMessage ;
2009-04-25 18:58:18 +00:00
m_ActiveClients . Remove ( AgentId ) ;
2009-04-21 15:30:03 +00:00
}
else
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . WarnFormat ( "[GROUPS]: Client closed that wasn't registered here." ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
2009-04-21 15:30:03 +00:00
}
}
2009-04-25 18:58:18 +00:00
* /
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
private void OnAgentDataUpdateRequest ( IClientAPI remoteClient , UUID dataForAgentID , UUID sessionID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
UUID activeGroupID = UUID . Zero ;
string activeGroupTitle = string . Empty ;
string activeGroupName = string . Empty ;
ulong activeGroupPowers = ( ulong ) GroupPowers . None ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
GroupMembershipData membership = m_groupData . GetAgentActiveMembership ( GetRequestingAgentID ( remoteClient ) , dataForAgentID ) ;
2009-04-21 15:30:03 +00:00
if ( membership ! = null )
{
2009-04-22 10:03:38 +00:00
activeGroupID = membership . GroupID ;
activeGroupTitle = membership . GroupTitle ;
activeGroupPowers = membership . GroupPowers ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
SendAgentDataUpdate ( remoteClient , dataForAgentID , activeGroupID , activeGroupName , activeGroupPowers , activeGroupTitle ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
SendScenePresenceUpdate ( dataForAgentID , activeGroupTitle ) ;
2009-04-21 15:30:03 +00:00
}
2010-03-26 00:10:29 +00:00
private void HandleUUIDGroupNameRequest ( UUID GroupID , IClientAPI remoteClient )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
string GroupName ;
2009-04-29 22:31:00 +00:00
2010-04-02 13:53:10 +00:00
GroupRecord group = m_groupData . GetGroupRecord ( GetRequestingAgentID ( remoteClient ) , GroupID , null ) ;
2009-04-21 15:30:03 +00:00
if ( group ! = null )
{
2009-04-25 18:58:18 +00:00
GroupName = group . GroupName ;
2009-04-21 15:30:03 +00:00
}
else
{
2009-04-25 18:58:18 +00:00
GroupName = "Unknown" ;
2009-04-21 15:30:03 +00:00
}
2009-04-29 22:31:00 +00:00
remoteClient . SendGroupNameReply ( GroupID , GroupName ) ;
2009-04-21 15:30:03 +00:00
}
private void OnInstantMessage ( IClientAPI remoteClient , GridInstantMessage im )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
// Group invitations
2009-04-25 18:58:18 +00:00
if ( ( im . dialog = = ( byte ) InstantMessageDialog . GroupInvitationAccept ) | | ( im . dialog = = ( byte ) InstantMessageDialog . GroupInvitationDecline ) )
2009-04-21 15:30:03 +00:00
{
UUID inviteID = new UUID ( im . imSessionID ) ;
2010-04-02 13:53:10 +00:00
GroupInviteInfo inviteInfo = m_groupData . GetAgentToGroupInvite ( GetRequestingAgentID ( remoteClient ) , inviteID ) ;
2009-04-21 15:30:03 +00:00
2009-07-24 20:08:26 +00:00
if ( inviteInfo = = null )
{
if ( m_debugEnabled ) m_log . WarnFormat ( "[GROUPS]: Received an Invite IM for an invite that does not exist {0}." , inviteID ) ;
return ;
}
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: Invite is for Agent {0} to Group {1}." , inviteInfo . AgentID , inviteInfo . GroupID ) ;
2009-04-21 15:30:03 +00:00
UUID fromAgentID = new UUID ( im . fromAgentID ) ;
if ( ( inviteInfo ! = null ) & & ( fromAgentID = = inviteInfo . AgentID ) )
{
// Accept
if ( im . dialog = = ( byte ) InstantMessageDialog . GroupInvitationAccept )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: Received an accept invite notice." ) ;
2009-04-21 15:30:03 +00:00
// and the sessionid is the role
2010-04-02 13:53:10 +00:00
m_groupData . AddAgentToGroup ( GetRequestingAgentID ( remoteClient ) , inviteInfo . AgentID , inviteInfo . GroupID , inviteInfo . RoleID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
GridInstantMessage msg = new GridInstantMessage ( ) ;
msg . imSessionID = UUID . Zero . Guid ;
msg . fromAgentID = UUID . Zero . Guid ;
msg . toAgentID = inviteInfo . AgentID . Guid ;
msg . timestamp = ( uint ) Util . UnixTimeSinceEpoch ( ) ;
msg . fromAgentName = "Groups" ;
msg . message = string . Format ( "You have been added to the group." ) ;
msg . dialog = ( byte ) OpenMetaverse . InstantMessageDialog . MessageBox ;
msg . fromGroup = false ;
msg . offline = ( byte ) 0 ;
msg . ParentEstateID = 0 ;
msg . Position = Vector3 . Zero ;
msg . RegionID = UUID . Zero . Guid ;
msg . binaryBucket = new byte [ 0 ] ;
OutgoingInstantMessage ( msg , inviteInfo . AgentID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
UpdateAllClientsWithGroupInfo ( inviteInfo . AgentID ) ;
// TODO: If the inviter is still online, they need an agent dataupdate
// and maybe group membership updates for the invitee
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
m_groupData . RemoveAgentToGroupInvite ( GetRequestingAgentID ( remoteClient ) , inviteID ) ;
2009-04-21 15:30:03 +00:00
}
// Reject
if ( im . dialog = = ( byte ) InstantMessageDialog . GroupInvitationDecline )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: Received a reject invite notice." ) ;
2010-04-02 13:53:10 +00:00
m_groupData . RemoveAgentToGroupInvite ( GetRequestingAgentID ( remoteClient ) , inviteID ) ;
2009-04-21 15:30:03 +00:00
}
}
}
// Group notices
if ( ( im . dialog = = ( byte ) InstantMessageDialog . GroupNotice ) )
{
2009-04-22 10:03:38 +00:00
if ( ! m_groupNoticesEnabled )
2009-04-21 15:30:03 +00:00
{
return ;
}
2009-04-25 18:58:18 +00:00
UUID GroupID = new UUID ( im . toAgentID ) ;
2010-04-02 13:53:10 +00:00
if ( m_groupData . GetGroupRecord ( GetRequestingAgentID ( remoteClient ) , GroupID , null ) ! = null )
2009-04-21 15:30:03 +00:00
{
2009-04-25 18:58:18 +00:00
UUID NoticeID = UUID . Random ( ) ;
string Subject = im . message . Substring ( 0 , im . message . IndexOf ( '|' ) ) ;
string Message = im . message . Substring ( Subject . Length + 1 ) ;
2009-04-21 15:30:03 +00:00
2013-08-02 19:26:28 +00:00
InventoryItemBase item = null ;
bool hasAttachment = false ;
UUID itemID = UUID . Zero ; //Assignment to quiet compiler
UUID ownerID = UUID . Zero ; //Assignment to quiet compiler
2009-04-21 15:30:03 +00:00
byte [ ] bucket ;
2013-08-02 19:26:28 +00:00
if ( im . binaryBucket . Length > = 1 & & im . binaryBucket [ 0 ] > 0 )
2009-04-21 15:30:03 +00:00
{
string binBucket = OpenMetaverse . Utils . BytesToString ( im . binaryBucket ) ;
binBucket = binBucket . Remove ( 0 , 14 ) . Trim ( ) ;
2013-08-02 19:26:28 +00:00
OSDMap binBucketOSD = ( OSDMap ) OSDParser . DeserializeLLSDXml ( binBucket ) ;
if ( binBucketOSD is OSD )
2009-04-21 15:30:03 +00:00
{
2013-08-02 19:26:28 +00:00
OSDMap binBucketMap = ( OSDMap ) binBucketOSD ;
itemID = binBucketMap [ "item_id" ] . AsUUID ( ) ;
ownerID = binBucketMap [ "owner_id" ] . AsUUID ( ) ;
2009-04-27 05:22:44 +00:00
2013-08-02 19:26:28 +00:00
//Attempt to get the details of the attached item.
//If sender doesn't own the attachment, the item
//variable will be set to null and attachment will
//not be included with the group notice.
Scene scene = ( Scene ) remoteClient . Scene ;
item = new InventoryItemBase ( itemID , ownerID ) ;
item = scene . InventoryService . GetItem ( item ) ;
if ( item ! = null )
2009-04-27 05:22:44 +00:00
{
2013-08-02 19:26:28 +00:00
//Got item details so include the attachment.
hasAttachment = true ;
2009-09-30 16:00:09 +00:00
}
2009-04-25 18:58:18 +00:00
}
2013-08-02 19:26:28 +00:00
else
{
m_log . DebugFormat ( "[Groups]: Received OSD with unexpected type: {0}" , binBucketOSD . GetType ( ) ) ;
}
}
if ( hasAttachment )
{
//Bucket contains information about attachment.
/ /
//Byte offset and description of bucket data:
//0: 1 byte indicating if attachment is present
//1: 1 byte indicating the type of attachment
//2: 16 bytes - Group UUID
//18: 16 bytes - UUID of the attachment owner
//34: 16 bytes - UUID of the attachment
//50: variable - Name of the attachment
//??: NUL byte to terminate the attachment name
byte [ ] name = Encoding . UTF8 . GetBytes ( item . Name ) ;
bucket = new byte [ 51 + name . Length ] ; //3 bytes, 3 UUIDs, and name
bucket [ 0 ] = 1 ; //Has attachment flag
bucket [ 1 ] = ( byte ) item . InvType ; //Type of Attachment
GroupID . ToBytes ( bucket , 2 ) ;
ownerID . ToBytes ( bucket , 18 ) ;
itemID . ToBytes ( bucket , 34 ) ;
name . CopyTo ( bucket , 50 ) ;
}
else
{
2009-04-21 15:30:03 +00:00
bucket = new byte [ 19 ] ;
2013-08-02 19:26:28 +00:00
bucket [ 0 ] = 0 ; //Has attachment flag
bucket [ 1 ] = 0 ; //Type of attachment
2009-04-25 18:58:18 +00:00
GroupID . ToBytes ( bucket , 2 ) ;
2013-08-02 19:26:28 +00:00
bucket [ 18 ] = 0 ; //NUL terminate name of attachment
2009-04-21 15:30:03 +00:00
}
2010-04-02 13:53:10 +00:00
m_groupData . AddGroupNotice ( GetRequestingAgentID ( remoteClient ) , GroupID , NoticeID , im . fromAgentName , Subject , Message , bucket ) ;
2009-04-21 15:30:03 +00:00
if ( OnNewGroupNotice ! = null )
{
2009-04-25 18:58:18 +00:00
OnNewGroupNotice ( GroupID , NoticeID ) ;
2009-04-21 15:30:03 +00:00
}
// Send notice out to everyone that wants notices
2010-04-02 13:53:10 +00:00
foreach ( GroupMembersData member in m_groupData . GetGroupMembers ( GetRequestingAgentID ( remoteClient ) , GroupID ) )
2009-04-21 15:30:03 +00:00
{
2009-08-19 14:37:39 +00:00
if ( m_debugEnabled )
{
2010-01-08 18:43:34 +00:00
UserAccount targetUser = m_sceneList [ 0 ] . UserAccountService . GetUserAccount ( remoteClient . Scene . RegionInfo . ScopeID , member . AgentID ) ;
if ( targetUser ! = null )
2009-08-19 14:37:39 +00:00
{
2010-01-08 18:43:34 +00:00
m_log . DebugFormat ( "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})" , NoticeID , targetUser . FirstName + " " + targetUser . LastName , member . AcceptNotices ) ;
2009-08-19 14:37:39 +00:00
}
else
{
m_log . DebugFormat ( "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})" , NoticeID , member . AgentID , member . AcceptNotices ) ;
}
}
if ( member . AcceptNotices )
2009-04-21 15:30:03 +00:00
{
2013-08-02 19:26:28 +00:00
// Build notice IM
2009-04-26 18:19:14 +00:00
GridInstantMessage msg = CreateGroupNoticeIM ( UUID . Zero , NoticeID , ( byte ) OpenMetaverse . InstantMessageDialog . GroupNotice ) ;
2009-04-21 15:30:03 +00:00
msg . toAgentID = member . AgentID . Guid ;
2009-04-25 18:58:18 +00:00
OutgoingInstantMessage ( msg , member . AgentID ) ;
2009-04-21 15:30:03 +00:00
}
}
}
}
2013-08-02 19:26:28 +00:00
if ( im . dialog = = ( byte ) InstantMessageDialog . GroupNoticeInventoryAccepted )
{
//Is bucket large enough to hold UUID of the attachment?
if ( im . binaryBucket . Length < 16 )
return ;
UUID noticeID = new UUID ( im . imSessionID ) ;
GroupNoticeInfo notice = m_groupData . GetGroupNotice ( GetRequestingAgentID ( remoteClient ) , noticeID ) ;
if ( notice ! = null )
{
UUID giver = new UUID ( notice . BinaryBucket , 18 ) ;
UUID attachmentUUID = new UUID ( notice . BinaryBucket , 34 ) ;
if ( m_debugEnabled )
m_log . DebugFormat ( "[Groups]: Giving inventory from {0} to {1}" , giver , remoteClient . AgentId ) ;
InventoryItemBase itemCopy = ( ( Scene ) ( remoteClient . Scene ) ) . GiveInventoryItem ( remoteClient . AgentId ,
giver , attachmentUUID ) ;
if ( itemCopy = = null )
{
remoteClient . SendAgentAlertMessage ( "Can't find item to give. Nothing given." , false ) ;
return ;
}
remoteClient . SendInventoryItemCreateUpdate ( itemCopy , 0 ) ;
}
}
2009-04-21 15:30:03 +00:00
// Interop, received special 210 code for ejecting a group member
// this only works within the comms servers domain, and won't work hypergrid
2013-08-02 19:26:28 +00:00
// TODO:FIXME: Use a presence server of some kind to find out where the
2009-04-21 15:30:03 +00:00
// client actually is, and try contacting that region directly to notify them,
// or provide the notification via xmlrpc update queue
2009-04-25 18:58:18 +00:00
if ( ( im . dialog = = 210 ) )
2009-04-21 15:30:03 +00:00
{
// This is sent from the region that the ejectee was ejected from
// if it's being delivered here, then the ejectee is here
// so we need to send local updates to the agent.
UUID ejecteeID = new UUID ( im . toAgentID ) ;
2009-04-25 18:58:18 +00:00
im . dialog = ( byte ) InstantMessageDialog . MessageFromAgent ;
OutgoingInstantMessage ( im , ejecteeID ) ;
IClientAPI ejectee = GetActiveClient ( ejecteeID ) ;
if ( ejectee ! = null )
2009-04-21 15:30:03 +00:00
{
2010-05-06 15:38:23 +00:00
UUID groupID = new UUID ( im . imSessionID ) ;
2009-04-25 18:58:18 +00:00
ejectee . SendAgentDropGroup ( groupID ) ;
2009-04-21 15:30:03 +00:00
}
}
}
private void OnGridInstantMessage ( GridInstantMessage msg )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
// Trigger the above event handler
OnInstantMessage ( null , msg ) ;
2009-04-21 20:44:17 +00:00
// If a message from a group arrives here, it may need to be forwarded to a local client
if ( msg . fromGroup = = true )
{
2009-04-24 00:58:48 +00:00
switch ( msg . dialog )
2009-04-21 20:44:17 +00:00
{
case ( byte ) InstantMessageDialog . GroupInvitation :
case ( byte ) InstantMessageDialog . GroupNotice :
UUID toAgentID = new UUID ( msg . toAgentID ) ;
2009-04-25 18:58:18 +00:00
IClientAPI localClient = GetActiveClient ( toAgentID ) ;
2009-04-27 05:22:44 +00:00
if ( localClient ! = null )
2009-04-21 20:44:17 +00:00
{
2009-04-25 18:58:18 +00:00
localClient . SendInstantMessage ( msg ) ;
2009-04-21 20:44:17 +00:00
}
break ;
}
}
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
# endregion
2009-04-21 15:30:03 +00:00
#region IGroupsModule Members
public event NewGroupNotice OnNewGroupNotice ;
2009-04-25 18:58:18 +00:00
public GroupRecord GetGroupRecord ( UUID GroupID )
2009-04-21 15:30:03 +00:00
{
2010-04-02 13:53:10 +00:00
return m_groupData . GetGroupRecord ( UUID . Zero , GroupID , null ) ;
2009-04-21 15:30:03 +00:00
}
2010-03-26 00:10:29 +00:00
public GroupRecord GetGroupRecord ( string name )
{
2010-04-02 13:53:10 +00:00
return m_groupData . GetGroupRecord ( UUID . Zero , UUID . Zero , name ) ;
2010-03-26 00:10:29 +00:00
}
2009-04-21 15:30:03 +00:00
public void ActivateGroup ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
m_groupData . SetAgentActiveGroup ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Changing active group changes title, active powers, all kinds of things
// anyone who is in any region that can see this client, should probably be
// updated with new group info. At a minimum, they should get ScenePresence
// updated with new title.
2010-04-02 13:53:10 +00:00
UpdateAllClientsWithGroupInfo ( GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
/// <summary>
/// Get the Role Titles for an Agent, for a specific group
/// </summary>
public List < GroupTitlesData > GroupTitlesRequest ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-29 22:31:00 +00:00
2010-04-02 13:53:10 +00:00
List < GroupRolesData > agentRoles = m_groupData . GetAgentGroupRoles ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID ) ;
GroupMembershipData agentMembership = m_groupData . GetAgentGroupMembership ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID ) ;
2009-04-21 15:30:03 +00:00
List < GroupTitlesData > titles = new List < GroupTitlesData > ( ) ;
foreach ( GroupRolesData role in agentRoles )
{
GroupTitlesData title = new GroupTitlesData ( ) ;
title . Name = role . Name ;
if ( agentMembership ! = null )
{
title . Selected = agentMembership . ActiveRole = = role . RoleID ;
}
title . UUID = role . RoleID ;
titles . Add ( title ) ;
}
return titles ;
}
public List < GroupMembersData > GroupMembersRequest ( IClientAPI remoteClient , UUID groupID )
{
2010-10-19 00:54:51 +00:00
if ( m_debugEnabled )
m_log . DebugFormat (
"[GROUPS]: GroupMembersRequest called for {0} from client {1}" , groupID , remoteClient . Name ) ;
2010-05-05 23:54:48 +00:00
List < GroupMembersData > data = m_groupData . GetGroupMembers ( GetRequestingAgentID ( remoteClient ) , groupID ) ;
if ( m_debugEnabled )
{
foreach ( GroupMembersData member in data )
{
m_log . DebugFormat ( "[GROUPS]: Member({0}) - IsOwner({1})" , member . AgentID , member . IsOwner ) ;
}
2010-04-02 13:53:10 +00:00
}
2009-04-21 15:30:03 +00:00
return data ;
2009-04-25 18:58:18 +00:00
2009-04-21 15:30:03 +00:00
}
public List < GroupRolesData > GroupRoleDataRequest ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
List < GroupRolesData > data = m_groupData . GetGroupRoles ( GetRequestingAgentID ( remoteClient ) , groupID ) ;
2009-04-21 15:30:03 +00:00
return data ;
}
public List < GroupRoleMembersData > GroupRoleMembersRequest ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-05-05 23:54:48 +00:00
List < GroupRoleMembersData > data = m_groupData . GetGroupRoleMembers ( GetRequestingAgentID ( remoteClient ) , groupID ) ;
if ( m_debugEnabled )
{
foreach ( GroupRoleMembersData member in data )
{
m_log . DebugFormat ( "[GROUPS]: Member({0}) - Role({1})" , member . MemberID , member . RoleID ) ;
}
2010-04-02 13:53:10 +00:00
}
2009-04-21 15:30:03 +00:00
return data ;
}
public GroupProfileData GroupProfileRequest ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
GroupProfileData profile = new GroupProfileData ( ) ;
2009-04-29 22:31:00 +00:00
2010-04-02 13:53:10 +00:00
GroupRecord groupInfo = m_groupData . GetGroupRecord ( GetRequestingAgentID ( remoteClient ) , groupID , null ) ;
2009-04-21 15:30:03 +00:00
if ( groupInfo ! = null )
{
profile . AllowPublish = groupInfo . AllowPublish ;
profile . Charter = groupInfo . Charter ;
profile . FounderID = groupInfo . FounderID ;
profile . GroupID = groupID ;
2010-04-02 13:53:10 +00:00
profile . GroupMembershipCount = m_groupData . GetGroupMembers ( GetRequestingAgentID ( remoteClient ) , groupID ) . Count ;
profile . GroupRolesCount = m_groupData . GetGroupRoles ( GetRequestingAgentID ( remoteClient ) , groupID ) . Count ;
2009-04-21 15:30:03 +00:00
profile . InsigniaID = groupInfo . GroupPicture ;
profile . MaturePublish = groupInfo . MaturePublish ;
profile . MembershipFee = groupInfo . MembershipFee ;
profile . Money = 0 ; // TODO: Get this from the currency server?
profile . Name = groupInfo . GroupName ;
profile . OpenEnrollment = groupInfo . OpenEnrollment ;
profile . OwnerRole = groupInfo . OwnerRoleID ;
profile . ShowInList = groupInfo . ShowInList ;
}
2010-04-02 13:53:10 +00:00
GroupMembershipData memberInfo = m_groupData . GetAgentGroupMembership ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID ) ;
2009-04-21 15:30:03 +00:00
if ( memberInfo ! = null )
{
profile . MemberTitle = memberInfo . GroupTitle ;
profile . PowersMask = memberInfo . GroupPowers ;
}
return profile ;
}
2009-04-25 18:58:18 +00:00
public GroupMembershipData [ ] GetMembershipData ( UUID agentID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
return m_groupData . GetAgentGroupMemberships ( UUID . Zero , agentID ) . ToArray ( ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
public GroupMembershipData GetMembershipData ( UUID groupID , UUID agentID )
2009-04-21 15:30:03 +00:00
{
2010-03-25 23:53:05 +00:00
if ( m_debugEnabled )
m_log . DebugFormat (
"[GROUPS]: {0} called with groupID={1}, agentID={2}" ,
System . Reflection . MethodBase . GetCurrentMethod ( ) . Name , groupID , agentID ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
return m_groupData . GetAgentGroupMembership ( UUID . Zero , agentID , groupID ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
public void UpdateGroupInfo ( IClientAPI remoteClient , UUID groupID , string charter , bool showInList , UUID insigniaID , int membershipFee , bool openEnrollment , bool allowPublish , bool maturePublish )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
// Note: Permissions checking for modification rights is handled by the Groups Server/Service
m_groupData . UpdateGroup ( GetRequestingAgentID ( remoteClient ) , groupID , charter , showInList , insigniaID , membershipFee , openEnrollment , allowPublish , maturePublish ) ;
2009-04-21 15:30:03 +00:00
}
public void SetGroupAcceptNotices ( IClientAPI remoteClient , UUID groupID , bool acceptNotices , bool listInProfile )
{
2010-04-02 13:53:10 +00:00
// Note: Permissions checking for modification rights is handled by the Groups Server/Service
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
m_groupData . SetAgentGroupInfo ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID , acceptNotices , listInProfile ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
public UUID CreateGroup ( IClientAPI remoteClient , string name , string charter , bool showInList , UUID insigniaID , int membershipFee , bool openEnrollment , bool allowPublish , bool maturePublish )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
if ( m_groupData . GetGroupRecord ( GetRequestingAgentID ( remoteClient ) , UUID . Zero , name ) ! = null )
2009-04-21 15:30:03 +00:00
{
remoteClient . SendCreateGroupReply ( UUID . Zero , false , "A group with the same name already exists." ) ;
return UUID . Zero ;
}
2012-03-27 20:09:58 +00:00
// check user level
ScenePresence avatar = null ;
Scene scene = ( Scene ) remoteClient . Scene ;
scene . TryGetScenePresence ( remoteClient . AgentId , out avatar ) ;
if ( avatar ! = null )
{
if ( avatar . UserLevel < m_levelGroupCreate )
{
remoteClient . SendCreateGroupReply ( UUID . Zero , false , "You have got insufficient permissions to create a group." ) ;
return UUID . Zero ;
}
}
// check funds
2009-07-23 15:32:11 +00:00
// is there is a money module present ?
2012-03-27 20:09:58 +00:00
IMoneyModule money = scene . RequestModuleInterface < IMoneyModule > ( ) ;
2009-07-21 23:57:56 +00:00
if ( money ! = null )
{
2009-07-23 15:32:11 +00:00
// do the transaction, that is if the agent has got sufficient funds
2012-01-28 00:18:12 +00:00
if ( ! money . AmountCovered ( remoteClient . AgentId , money . GroupCreationCharge ) ) {
2012-03-27 20:09:58 +00:00
remoteClient . SendCreateGroupReply ( UUID . Zero , false , "You have got insufficient funds to create a group." ) ;
2009-07-23 15:32:11 +00:00
return UUID . Zero ;
}
2013-05-25 01:08:54 +00:00
money . ApplyCharge ( GetRequestingAgentID ( remoteClient ) , money . GroupCreationCharge , MoneyTransactionType . GroupCreate ) ;
2009-07-23 15:32:11 +00:00
}
2010-04-02 13:53:10 +00:00
UUID groupID = m_groupData . CreateGroup ( GetRequestingAgentID ( remoteClient ) , name , charter , showInList , insigniaID , membershipFee , openEnrollment , allowPublish , maturePublish , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
remoteClient . SendCreateGroupReply ( groupID , true , "Group created successfullly" ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Update the founder with new group information.
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
return groupID ;
2009-04-21 15:30:03 +00:00
}
2009-04-22 10:03:38 +00:00
public GroupNoticeData [ ] GroupNoticesListRequest ( IClientAPI remoteClient , UUID groupID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
// ToDo: check if agent is a member of group and is allowed to see notices?
2009-04-29 22:31:00 +00:00
2010-04-02 13:53:10 +00:00
return m_groupData . GetGroupNotices ( GetRequestingAgentID ( remoteClient ) , groupID ) . ToArray ( ) ;
2009-04-21 15:30:03 +00:00
}
/// <summary>
/// Get the title of the agent's current role.
/// </summary>
public string GetGroupTitle ( UUID avatarID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
GroupMembershipData membership = m_groupData . GetAgentActiveMembership ( UUID . Zero , avatarID ) ;
2009-04-21 15:30:03 +00:00
if ( membership ! = null )
{
return membership . GroupTitle ;
}
return string . Empty ;
}
/// <summary>
/// Change the current Active Group Role for Agent
/// </summary>
2009-04-22 10:03:38 +00:00
public void GroupTitleUpdate ( IClientAPI remoteClient , UUID groupID , UUID titleRoleID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
m_groupData . SetAgentActiveGroupRole ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID , titleRoleID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// TODO: Not sure what all is needed here, but if the active group role change is for the group
// the client currently has set active, then we need to do a scene presence update too
2010-04-02 13:53:10 +00:00
// if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
2009-04-25 18:58:18 +00:00
2010-04-02 13:53:10 +00:00
UpdateAllClientsWithGroupInfo ( GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
public void GroupRoleUpdate ( IClientAPI remoteClient , UUID groupID , UUID roleID , string name , string description , string title , ulong powers , byte updateType )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-08-19 15:17:29 +00:00
// Security Checks are handled in the Groups Service.
2009-04-21 15:30:03 +00:00
switch ( ( OpenMetaverse . GroupRoleUpdate ) updateType )
{
case OpenMetaverse . GroupRoleUpdate . Create :
2010-04-02 13:53:10 +00:00
m_groupData . AddGroupRole ( GetRequestingAgentID ( remoteClient ) , groupID , UUID . Random ( ) , name , description , title , powers ) ;
2009-04-21 15:30:03 +00:00
break ;
case OpenMetaverse . GroupRoleUpdate . Delete :
2010-04-02 13:53:10 +00:00
m_groupData . RemoveGroupRole ( GetRequestingAgentID ( remoteClient ) , groupID , roleID ) ;
2009-04-21 15:30:03 +00:00
break ;
case OpenMetaverse . GroupRoleUpdate . UpdateAll :
case OpenMetaverse . GroupRoleUpdate . UpdateData :
case OpenMetaverse . GroupRoleUpdate . UpdatePowers :
2009-08-19 15:17:29 +00:00
if ( m_debugEnabled )
{
GroupPowers gp = ( GroupPowers ) powers ;
m_log . DebugFormat ( "[GROUPS]: Role ({0}) updated with Powers ({1}) ({2})" , name , powers . ToString ( ) , gp . ToString ( ) ) ;
}
2010-04-02 13:53:10 +00:00
m_groupData . UpdateGroupRole ( GetRequestingAgentID ( remoteClient ) , groupID , roleID , name , description , title , powers ) ;
2009-04-21 15:30:03 +00:00
break ;
case OpenMetaverse . GroupRoleUpdate . NoUpdate :
default :
// No Op
break ;
}
2009-04-25 18:58:18 +00:00
// TODO: This update really should send out updates for everyone in the role that just got changed.
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
public void GroupRoleChanges ( IClientAPI remoteClient , UUID groupID , UUID roleID , UUID memberID , uint changes )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
// Todo: Security check
switch ( changes )
{
case 0 :
// Add
2010-04-02 13:53:10 +00:00
m_groupData . AddAgentToGroupRole ( GetRequestingAgentID ( remoteClient ) , memberID , groupID , roleID ) ;
2009-04-21 15:30:03 +00:00
break ;
case 1 :
// Remove
2010-04-02 13:53:10 +00:00
m_groupData . RemoveAgentFromGroupRole ( GetRequestingAgentID ( remoteClient ) , memberID , groupID , roleID ) ;
2009-04-21 15:30:03 +00:00
break ;
default :
2009-04-29 19:38:20 +00:00
m_log . ErrorFormat ( "[GROUPS]: {0} does not understand changes == {1}" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name , changes ) ;
2009-04-21 15:30:03 +00:00
break ;
}
2009-04-25 18:58:18 +00:00
// TODO: This update really should send out updates for everyone in the role that just got changed.
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
public void GroupNoticeRequest ( IClientAPI remoteClient , UUID groupNoticeID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
GroupNoticeInfo data = m_groupData . GetGroupNotice ( GetRequestingAgentID ( remoteClient ) , groupNoticeID ) ;
2009-04-21 15:30:03 +00:00
if ( data ! = null )
{
2013-08-02 19:26:28 +00:00
GridInstantMessage msg = CreateGroupNoticeIM ( remoteClient . AgentId , groupNoticeID , ( byte ) InstantMessageDialog . GroupNoticeRequested ) ;
2009-04-25 18:58:18 +00:00
2010-04-02 13:53:10 +00:00
OutgoingInstantMessage ( msg , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
}
public GridInstantMessage CreateGroupNoticeIM ( UUID agentID , UUID groupNoticeID , byte dialog )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
GridInstantMessage msg = new GridInstantMessage ( ) ;
2013-08-02 19:26:28 +00:00
byte [ ] bucket ;
msg . imSessionID = groupNoticeID . Guid ;
2009-04-21 15:30:03 +00:00
msg . toAgentID = agentID . Guid ;
msg . dialog = dialog ;
msg . fromGroup = true ;
2011-11-02 23:50:47 +00:00
msg . offline = ( byte ) 0 ;
2009-04-21 15:30:03 +00:00
msg . ParentEstateID = 0 ;
msg . Position = Vector3 . Zero ;
msg . RegionID = UUID . Zero . Guid ;
2010-04-02 13:53:10 +00:00
GroupNoticeInfo info = m_groupData . GetGroupNotice ( agentID , groupNoticeID ) ;
2009-04-21 15:30:03 +00:00
if ( info ! = null )
{
msg . fromAgentID = info . GroupID . Guid ;
msg . timestamp = info . noticeData . Timestamp ;
msg . fromAgentName = info . noticeData . FromName ;
msg . message = info . noticeData . Subject + "|" + info . Message ;
2013-08-02 19:26:28 +00:00
if ( info . BinaryBucket [ 0 ] > 0 )
{
//32 is due to not needing space for two of the UUIDs.
//(Don't need UUID of attachment or its owner in IM)
//50 offset gets us to start of attachment name.
//We are skipping the attachment flag, type, and
//the three UUID fields at the start of the bucket.
bucket = new byte [ info . BinaryBucket . Length - 32 ] ;
bucket [ 0 ] = 1 ; //Has attachment
bucket [ 1 ] = info . BinaryBucket [ 1 ] ;
Array . Copy ( info . BinaryBucket , 50 ,
bucket , 18 , info . BinaryBucket . Length - 50 ) ;
}
else
{
bucket = new byte [ 19 ] ;
bucket [ 0 ] = 0 ; //No attachment
bucket [ 1 ] = 0 ; //Attachment type
bucket [ 18 ] = 0 ; //NUL terminate name
}
info . GroupID . ToBytes ( bucket , 2 ) ;
msg . binaryBucket = bucket ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
else
{
2013-08-02 19:26:28 +00:00
if ( m_debugEnabled )
m_log . DebugFormat ( "[GROUPS]: Group Notice {0} not found, composing empty message." , groupNoticeID ) ;
2009-04-25 18:58:18 +00:00
msg . fromAgentID = UUID . Zero . Guid ;
2013-08-02 19:26:28 +00:00
msg . timestamp = ( uint ) Util . UnixTimeSinceEpoch ( ) ;
2009-04-25 18:58:18 +00:00
msg . fromAgentName = string . Empty ;
msg . message = string . Empty ;
msg . binaryBucket = new byte [ 0 ] ;
}
2009-04-21 15:30:03 +00:00
return msg ;
}
public void SendAgentGroupDataUpdate ( IClientAPI remoteClient )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Send agent information about his groups
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
public void JoinGroupRequest ( IClientAPI remoteClient , UUID groupID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
// Should check to see if OpenEnrollment, or if there's an outstanding invitation
2010-04-02 13:53:10 +00:00
m_groupData . AddAgentToGroup ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID , UUID . Zero ) ;
2009-04-21 15:30:03 +00:00
remoteClient . SendJoinGroupReply ( groupID , true ) ;
2009-04-25 18:58:18 +00:00
// Should this send updates to everyone in the group?
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-22 10:03:38 +00:00
public void LeaveGroupRequest ( IClientAPI remoteClient , UUID groupID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2010-04-02 13:53:10 +00:00
m_groupData . RemoveAgentFromGroup ( GetRequestingAgentID ( remoteClient ) , GetRequestingAgentID ( remoteClient ) , groupID ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
remoteClient . SendLeaveGroupReply ( groupID , true ) ;
2009-04-21 15:30:03 +00:00
2009-04-22 10:03:38 +00:00
remoteClient . SendAgentDropGroup ( groupID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// SL sends out notifcations to the group messaging session that the person has left
// Should this also update everyone who is in the group?
2010-04-02 13:53:10 +00:00
SendAgentGroupDataUpdate ( remoteClient , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-22 10:03:38 +00:00
public void EjectGroupMemberRequest ( IClientAPI remoteClient , UUID groupID , UUID ejecteeID )
2009-04-21 15:30:03 +00:00
{
2012-03-27 20:30:02 +00:00
EjectGroupMember ( remoteClient , GetRequestingAgentID ( remoteClient ) , groupID , ejecteeID ) ;
}
2009-04-21 15:30:03 +00:00
2012-03-27 20:30:02 +00:00
public void EjectGroupMember ( IClientAPI remoteClient , UUID agentID , UUID groupID , UUID ejecteeID )
{
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-29 22:31:00 +00:00
2009-04-21 15:30:03 +00:00
// Todo: Security check?
2012-03-27 20:30:02 +00:00
m_groupData . RemoveAgentFromGroup ( agentID , ejecteeID , groupID ) ;
2009-04-21 15:30:03 +00:00
2012-03-27 20:30:02 +00:00
string agentName ;
RegionInfo regionInfo ;
2010-04-02 13:53:10 +00:00
2012-03-27 20:30:02 +00:00
// remoteClient provided or just agentID?
if ( remoteClient ! = null )
{
agentName = remoteClient . Name ;
regionInfo = remoteClient . Scene . RegionInfo ;
remoteClient . SendEjectGroupMemberReply ( agentID , groupID , true ) ;
}
else
{
IClientAPI client = GetActiveClient ( agentID ) ;
if ( client ! = null )
{
agentName = client . Name ;
regionInfo = client . Scene . RegionInfo ;
client . SendEjectGroupMemberReply ( agentID , groupID , true ) ;
}
else
{
regionInfo = m_sceneList [ 0 ] . RegionInfo ;
UserAccount acc = m_sceneList [ 0 ] . UserAccountService . GetUserAccount ( regionInfo . ScopeID , agentID ) ;
if ( acc ! = null )
{
agentName = acc . FirstName + " " + acc . LastName ;
}
else
{
agentName = "Unknown member" ;
}
}
}
GroupRecord groupInfo = m_groupData . GetGroupRecord ( agentID , groupID , null ) ;
2009-04-21 15:30:03 +00:00
2012-03-27 20:30:02 +00:00
UserAccount account = m_sceneList [ 0 ] . UserAccountService . GetUserAccount ( regionInfo . ScopeID , ejecteeID ) ;
2010-01-08 18:43:34 +00:00
if ( ( groupInfo = = null ) | | ( account = = null ) )
2009-04-25 18:58:18 +00:00
{
return ;
2010-09-12 17:43:49 +00:00
}
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Send Message to Ejectee
GridInstantMessage msg = new GridInstantMessage ( ) ;
msg . imSessionID = UUID . Zero . Guid ;
2012-03-27 20:30:02 +00:00
msg . fromAgentID = agentID . Guid ;
2009-04-25 18:58:18 +00:00
// msg.fromAgentID = info.GroupID;
msg . toAgentID = ejecteeID . Guid ;
//msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
msg . timestamp = 0 ;
2012-03-27 20:30:02 +00:00
msg . fromAgentName = agentName ;
msg . message = string . Format ( "You have been ejected from '{1}' by {0}." , agentName , groupInfo . GroupName ) ;
2009-04-25 18:58:18 +00:00
msg . dialog = ( byte ) OpenMetaverse . InstantMessageDialog . MessageFromAgent ;
msg . fromGroup = false ;
msg . offline = ( byte ) 0 ;
msg . ParentEstateID = 0 ;
msg . Position = Vector3 . Zero ;
2012-03-27 20:30:02 +00:00
msg . RegionID = regionInfo . RegionID . Guid ;
2009-04-25 18:58:18 +00:00
msg . binaryBucket = new byte [ 0 ] ;
OutgoingInstantMessage ( msg , ejecteeID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// Message to ejector
// Interop, received special 210 code for ejecting a group member
// this only works within the comms servers domain, and won't work hypergrid
2013-08-02 19:26:28 +00:00
// TODO:FIXME: Use a presence server of some kind to find out where the
2009-04-25 18:58:18 +00:00
// client actually is, and try contacting that region directly to notify them,
// or provide the notification via xmlrpc update queue
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
msg = new GridInstantMessage ( ) ;
msg . imSessionID = UUID . Zero . Guid ;
2012-03-27 20:30:02 +00:00
msg . fromAgentID = agentID . Guid ;
msg . toAgentID = agentID . Guid ;
2009-04-25 18:58:18 +00:00
msg . timestamp = 0 ;
2012-03-27 20:30:02 +00:00
msg . fromAgentName = agentName ;
2010-01-08 18:43:34 +00:00
if ( account ! = null )
2009-04-25 18:58:18 +00:00
{
2012-03-27 20:30:02 +00:00
msg . message = string . Format ( "{2} has been ejected from '{1}' by {0}." , agentName , groupInfo . GroupName , account . FirstName + " " + account . LastName ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-25 18:58:18 +00:00
else
{
2012-03-27 20:30:02 +00:00
msg . message = string . Format ( "{2} has been ejected from '{1}' by {0}." , agentName , groupInfo . GroupName , "Unknown member" ) ;
2009-04-25 18:58:18 +00:00
}
msg . dialog = ( byte ) 210 ; //interop
msg . fromGroup = false ;
msg . offline = ( byte ) 0 ;
msg . ParentEstateID = 0 ;
msg . Position = Vector3 . Zero ;
2012-03-27 20:30:02 +00:00
msg . RegionID = regionInfo . RegionID . Guid ;
2009-04-25 18:58:18 +00:00
msg . binaryBucket = new byte [ 0 ] ;
2012-03-27 20:30:02 +00:00
OutgoingInstantMessage ( msg , agentID ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
// SL sends out messages to everyone in the group
// Who all should receive updates and what should they be updated with?
UpdateAllClientsWithGroupInfo ( ejecteeID ) ;
2009-04-21 15:30:03 +00:00
}
2009-04-22 10:03:38 +00:00
public void InviteGroupRequest ( IClientAPI remoteClient , UUID groupID , UUID invitedAgentID , UUID roleID )
2012-03-27 20:30:02 +00:00
{
InviteGroup ( remoteClient , GetRequestingAgentID ( remoteClient ) , groupID , invitedAgentID , roleID ) ;
}
public void InviteGroup ( IClientAPI remoteClient , UUID agentID , UUID groupID , UUID invitedAgentID , UUID roleID )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2012-03-27 20:30:02 +00:00
string agentName ;
RegionInfo regionInfo ;
// remoteClient provided or just agentID?
if ( remoteClient ! = null )
{
agentName = remoteClient . Name ;
regionInfo = remoteClient . Scene . RegionInfo ;
}
else
{
IClientAPI client = GetActiveClient ( agentID ) ;
if ( client ! = null )
{
agentName = client . Name ;
regionInfo = client . Scene . RegionInfo ;
}
else
{
regionInfo = m_sceneList [ 0 ] . RegionInfo ;
UserAccount account = m_sceneList [ 0 ] . UserAccountService . GetUserAccount ( regionInfo . ScopeID , agentID ) ;
if ( account ! = null )
{
agentName = account . FirstName + " " + account . LastName ;
}
else
{
agentName = "Unknown member" ;
}
}
}
2009-04-21 15:30:03 +00:00
// Todo: Security check, probably also want to send some kind of notification
2009-04-25 18:58:18 +00:00
UUID InviteID = UUID . Random ( ) ;
2009-04-21 15:30:03 +00:00
2012-03-27 20:30:02 +00:00
m_groupData . AddAgentToGroupInvite ( agentID , InviteID , groupID , roleID , invitedAgentID ) ;
2009-04-21 15:30:03 +00:00
2009-07-24 20:08:26 +00:00
// Check to see if the invite went through, if it did not then it's possible
// the remoteClient did not validate or did not have permission to invite.
2012-03-27 20:30:02 +00:00
GroupInviteInfo inviteInfo = m_groupData . GetAgentToGroupInvite ( agentID , InviteID ) ;
2009-04-25 18:58:18 +00:00
2009-07-24 20:08:26 +00:00
if ( inviteInfo ! = null )
{
if ( m_msgTransferModule ! = null )
{
Guid inviteUUID = InviteID . Guid ;
GridInstantMessage msg = new GridInstantMessage ( ) ;
msg . imSessionID = inviteUUID ;
2012-03-27 20:30:02 +00:00
// msg.fromAgentID = agentID.Guid;
2009-07-24 20:08:26 +00:00
msg . fromAgentID = groupID . Guid ;
msg . toAgentID = invitedAgentID . Guid ;
//msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
msg . timestamp = 0 ;
2012-03-27 20:30:02 +00:00
msg . fromAgentName = agentName ;
msg . message = string . Format ( "{0} has invited you to join a group. There is no cost to join this group." , agentName ) ;
2009-07-24 20:08:26 +00:00
msg . dialog = ( byte ) OpenMetaverse . InstantMessageDialog . GroupInvitation ;
msg . fromGroup = true ;
msg . offline = ( byte ) 0 ;
msg . ParentEstateID = 0 ;
msg . Position = Vector3 . Zero ;
2012-03-27 20:30:02 +00:00
msg . RegionID = regionInfo . RegionID . Guid ;
2009-07-24 20:08:26 +00:00
msg . binaryBucket = new byte [ 20 ] ;
OutgoingInstantMessage ( msg , invitedAgentID ) ;
}
2009-04-21 15:30:03 +00:00
}
}
2013-07-28 20:49:58 +00:00
public List < DirGroupsReplyData > FindGroups ( IClientAPI remoteClient , string query )
{
return m_groupData . FindGroups ( GetRequestingAgentID ( remoteClient ) , query ) ;
}
2009-04-21 15:30:03 +00:00
# endregion
2009-04-25 18:58:18 +00:00
#region Client/Update Tools
/// <summary>
/// Try to find an active IClientAPI reference for agentID giving preference to root connections
/// </summary>
private IClientAPI GetActiveClient ( UUID agentID )
{
IClientAPI child = null ;
// Try root avatar first
foreach ( Scene scene in m_sceneList )
{
2011-10-27 09:26:37 +00:00
ScenePresence sp = scene . GetScenePresence ( agentID ) ;
if ( sp ! = null )
2009-04-25 18:58:18 +00:00
{
2011-10-27 09:26:37 +00:00
if ( ! sp . IsChildAgent )
2009-04-25 18:58:18 +00:00
{
2011-10-27 09:26:37 +00:00
return sp . ControllingClient ;
2009-04-25 18:58:18 +00:00
}
else
{
2011-10-27 09:26:37 +00:00
child = sp . ControllingClient ;
2009-04-25 18:58:18 +00:00
}
}
}
// If we didn't find a root, then just return whichever child we found, or null if none
return child ;
}
/// <summary>
/// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'.
/// </summary>
private void SendGroupMembershipInfoViaCaps ( IClientAPI remoteClient , UUID dataForAgentID , GroupMembershipData [ ] data )
2009-04-21 15:30:03 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
OSDArray AgentData = new OSDArray ( 1 ) ;
OSDMap AgentDataMap = new OSDMap ( 1 ) ;
AgentDataMap . Add ( "AgentID" , OSD . FromUUID ( dataForAgentID ) ) ;
AgentData . Add ( AgentDataMap ) ;
2009-04-21 15:30:03 +00:00
2009-04-25 18:58:18 +00:00
OSDArray GroupData = new OSDArray ( data . Length ) ;
OSDArray NewGroupData = new OSDArray ( data . Length ) ;
2009-04-21 15:30:03 +00:00
foreach ( GroupMembershipData membership in data )
{
2010-04-02 13:53:10 +00:00
if ( GetRequestingAgentID ( remoteClient ) ! = dataForAgentID )
2009-09-16 23:12:23 +00:00
{
if ( ! membership . ListInProfile )
{
// If we're sending group info to remoteclient about another agent,
// filter out groups the other agent doesn't want to share.
continue ;
}
}
2009-04-25 18:58:18 +00:00
OSDMap GroupDataMap = new OSDMap ( 6 ) ;
OSDMap NewGroupDataMap = new OSDMap ( 1 ) ;
GroupDataMap . Add ( "GroupID" , OSD . FromUUID ( membership . GroupID ) ) ;
2010-08-17 20:50:04 +00:00
GroupDataMap . Add ( "GroupPowers" , OSD . FromULong ( membership . GroupPowers ) ) ;
2009-04-25 18:58:18 +00:00
GroupDataMap . Add ( "AcceptNotices" , OSD . FromBoolean ( membership . AcceptNotices ) ) ;
GroupDataMap . Add ( "GroupInsigniaID" , OSD . FromUUID ( membership . GroupPicture ) ) ;
GroupDataMap . Add ( "Contribution" , OSD . FromInteger ( membership . Contribution ) ) ;
GroupDataMap . Add ( "GroupName" , OSD . FromString ( membership . GroupName ) ) ;
NewGroupDataMap . Add ( "ListInProfile" , OSD . FromBoolean ( membership . ListInProfile ) ) ;
GroupData . Add ( GroupDataMap ) ;
NewGroupData . Add ( NewGroupDataMap ) ;
2009-04-21 15:30:03 +00:00
}
OSDMap llDataStruct = new OSDMap ( 3 ) ;
2009-04-25 18:58:18 +00:00
llDataStruct . Add ( "AgentData" , AgentData ) ;
llDataStruct . Add ( "GroupData" , GroupData ) ;
2010-05-05 23:54:48 +00:00
llDataStruct . Add ( "NewGroupData" , NewGroupData ) ;
if ( m_debugEnabled )
{
m_log . InfoFormat ( "[GROUPS]: {0}" , OSDParser . SerializeJsonString ( llDataStruct ) ) ;
2010-04-02 13:53:10 +00:00
}
2009-04-21 15:30:03 +00:00
IEventQueue queue = remoteClient . Scene . RequestModuleInterface < IEventQueue > ( ) ;
if ( queue ! = null )
{
2011-04-30 16:24:15 +00:00
queue . Enqueue ( queue . BuildEvent ( "AgentGroupDataUpdate" , llDataStruct ) , GetRequestingAgentID ( remoteClient ) ) ;
2009-04-21 15:30:03 +00:00
}
}
2009-04-25 18:58:18 +00:00
private void SendScenePresenceUpdate ( UUID AgentID , string Title )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: Updating scene title for {0} with title: {1}" , AgentID , Title ) ;
2009-04-25 18:58:18 +00:00
ScenePresence presence = null ;
2009-10-21 17:45:37 +00:00
foreach ( Scene scene in m_sceneList )
2009-04-25 18:58:18 +00:00
{
2009-10-21 17:45:37 +00:00
presence = scene . GetScenePresence ( AgentID ) ;
if ( presence ! = null )
2009-04-25 18:58:18 +00:00
{
2010-11-24 00:08:10 +00:00
if ( presence . Grouptitle ! = Title )
{
presence . Grouptitle = Title ;
2009-04-25 18:58:18 +00:00
2010-11-24 00:08:10 +00:00
if ( ! presence . IsChildAgent )
presence . SendAvatarDataToAllAgents ( ) ;
}
2009-04-25 18:58:18 +00:00
}
}
}
/// <summary>
/// Send updates to all clients who might be interested in groups data for dataForClientID
/// </summary>
private void UpdateAllClientsWithGroupInfo ( UUID dataForClientID )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-25 18:58:18 +00:00
2009-10-01 00:38:36 +00:00
// TODO: Probably isn't nessesary to update every client in every scene.
2009-04-25 18:58:18 +00:00
// Need to examine client updates and do only what's nessesary.
lock ( m_sceneList )
{
foreach ( Scene scene in m_sceneList )
{
scene . ForEachClient ( delegate ( IClientAPI client ) { SendAgentGroupDataUpdate ( client , dataForClientID ) ; } ) ;
}
}
}
/// <summary>
/// Update remoteClient with group information about dataForAgentID
/// </summary>
2009-04-29 22:31:00 +00:00
private void SendAgentGroupDataUpdate ( IClientAPI remoteClient , UUID dataForAgentID )
2009-04-25 18:58:18 +00:00
{
2009-04-29 22:31:00 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: {0} called for {1}" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name , remoteClient . Name ) ;
2009-04-25 18:58:18 +00:00
// TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
2009-04-29 22:31:00 +00:00
OnAgentDataUpdateRequest ( remoteClient , dataForAgentID , UUID . Zero ) ;
2009-04-25 18:58:18 +00:00
// Need to send a group membership update to the client
2009-04-29 22:31:00 +00:00
// UDP version doesn't seem to behave nicely. But we're going to send it out here
// with an empty group membership to hopefully remove groups being displayed due
// to the core Groups Stub
2009-06-10 04:28:56 +00:00
remoteClient . SendGroupMembership ( new GroupMembershipData [ 0 ] ) ;
2009-04-25 18:58:18 +00:00
2009-09-16 23:51:22 +00:00
GroupMembershipData [ ] membershipArray = GetProfileListedGroupMemberships ( remoteClient , dataForAgentID ) ;
SendGroupMembershipInfoViaCaps ( remoteClient , dataForAgentID , membershipArray ) ;
remoteClient . SendAvatarGroupsReply ( dataForAgentID , membershipArray ) ;
2012-04-05 11:03:57 +00:00
if ( remoteClient . AgentId = = dataForAgentID )
remoteClient . RefreshGroupMembership ( ) ;
2009-09-16 23:51:22 +00:00
}
/// <summary>
/// Get a list of groups memberships for the agent that are marked "ListInProfile"
2011-06-01 00:33:40 +00:00
/// (unless that agent has a godLike aspect, in which case get all groups)
2009-09-16 23:51:22 +00:00
/// </summary>
/// <param name="dataForAgentID"></param>
/// <returns></returns>
private GroupMembershipData [ ] GetProfileListedGroupMemberships ( IClientAPI requestingClient , UUID dataForAgentID )
{
2010-04-02 13:53:10 +00:00
List < GroupMembershipData > membershipData = m_groupData . GetAgentGroupMemberships ( requestingClient . AgentId , dataForAgentID ) ;
2009-09-16 22:39:52 +00:00
GroupMembershipData [ ] membershipArray ;
2009-04-25 18:58:18 +00:00
2011-06-01 00:33:40 +00:00
// cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for
// those with a GodLike aspect.
2011-06-01 19:55:03 +00:00
Scene cScene = ( Scene ) requestingClient . Scene ;
2011-06-01 00:33:40 +00:00
bool isGod = cScene . Permissions . IsGod ( requestingClient . AgentId ) ;
2009-09-16 22:39:52 +00:00
2011-06-01 19:55:03 +00:00
if ( isGod )
{
2011-06-01 00:33:40 +00:00
membershipArray = membershipData . ToArray ( ) ;
2009-09-16 23:51:22 +00:00
}
else
{
2011-06-01 00:33:40 +00:00
if ( requestingClient . AgentId ! = dataForAgentID )
{
Predicate < GroupMembershipData > showInProfile = delegate ( GroupMembershipData membership )
{
return membership . ListInProfile ;
} ;
membershipArray = membershipData . FindAll ( showInProfile ) . ToArray ( ) ;
}
else
{
membershipArray = membershipData . ToArray ( ) ;
}
}
2011-06-01 19:55:03 +00:00
2009-09-16 23:12:23 +00:00
if ( m_debugEnabled )
{
2009-09-16 23:51:22 +00:00
m_log . InfoFormat ( "[GROUPS]: Get group membership information for {0} requested by {1}" , dataForAgentID , requestingClient . AgentId ) ;
2009-09-16 23:12:23 +00:00
foreach ( GroupMembershipData membership in membershipArray )
{
2010-04-02 13:53:10 +00:00
m_log . InfoFormat ( "[GROUPS]: {0} :: {1} - {2} - {3}" , dataForAgentID , membership . GroupName , membership . GroupTitle , membership . GroupPowers ) ;
2009-09-16 23:12:23 +00:00
}
}
2009-09-16 23:51:22 +00:00
return membershipArray ;
2009-04-25 18:58:18 +00:00
}
2011-06-01 00:33:40 +00:00
2009-04-25 18:58:18 +00:00
private void SendAgentDataUpdate ( IClientAPI remoteClient , UUID dataForAgentID , UUID activeGroupID , string activeGroupName , ulong activeGroupPowers , string activeGroupTitle )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-25 18:58:18 +00:00
// TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
2010-01-08 18:43:34 +00:00
UserAccount account = m_sceneList [ 0 ] . UserAccountService . GetUserAccount ( remoteClient . Scene . RegionInfo . ScopeID , dataForAgentID ) ;
2009-04-25 18:58:18 +00:00
string firstname , lastname ;
2010-01-08 18:43:34 +00:00
if ( account ! = null )
2009-04-25 18:58:18 +00:00
{
2010-01-08 18:43:34 +00:00
firstname = account . FirstName ;
lastname = account . LastName ;
2009-04-25 18:58:18 +00:00
}
else
{
firstname = "Unknown" ;
lastname = "Unknown" ;
}
remoteClient . SendAgentDataUpdate ( dataForAgentID , activeGroupID , firstname ,
lastname , activeGroupPowers , activeGroupName ,
activeGroupTitle ) ;
}
# endregion
#region IM Backed Processes
private void OutgoingInstantMessage ( GridInstantMessage msg , UUID msgTo )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: {0} called" , System . Reflection . MethodBase . GetCurrentMethod ( ) . Name ) ;
2009-04-25 18:58:18 +00:00
IClientAPI localClient = GetActiveClient ( msgTo ) ;
if ( localClient ! = null )
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: MsgTo ({0}) is local, delivering directly" , localClient . Name ) ;
2009-04-25 18:58:18 +00:00
localClient . SendInstantMessage ( msg ) ;
}
2010-12-14 23:36:34 +00:00
else if ( m_msgTransferModule ! = null )
2009-04-25 18:58:18 +00:00
{
2009-04-29 19:38:20 +00:00
if ( m_debugEnabled ) m_log . InfoFormat ( "[GROUPS]: MsgTo ({0}) is not local, delivering via TransferModule" , msgTo ) ;
m_msgTransferModule . SendInstantMessage ( msg , delegate ( bool success ) { if ( m_debugEnabled ) m_log . DebugFormat ( "[GROUPS]: Message Sent: {0}" , success ? "Succeeded" : "Failed" ) ; } ) ;
2009-04-25 18:58:18 +00:00
}
}
2009-05-12 15:52:28 +00:00
public void NotifyChange ( UUID groupID )
{
// Notify all group members of a chnge in group roles and/or
// permissions
/ /
}
2010-05-05 23:54:48 +00:00
# endregion
private UUID GetRequestingAgentID ( IClientAPI client )
{
UUID requestingAgentID = UUID . Zero ;
if ( client ! = null )
{
requestingAgentID = client . AgentId ;
}
return requestingAgentID ;
2010-04-02 13:53:10 +00:00
}
2009-04-21 15:30:03 +00:00
}
2010-04-02 13:53:10 +00:00
public class GroupNoticeInfo
{
public GroupNoticeData noticeData = new GroupNoticeData ( ) ;
public UUID GroupID = UUID . Zero ;
public string Message = string . Empty ;
public byte [ ] BinaryBucket = new byte [ 0 ] ;
}
2009-04-21 15:30:03 +00:00
}