diff --git a/OpenMetaverse/AgentManager.cs b/OpenMetaverse/AgentManager.cs index fac590d6..afacbccc 100644 --- a/OpenMetaverse/AgentManager.cs +++ b/OpenMetaverse/AgentManager.cs @@ -36,295 +36,295 @@ using OpenMetaverse.Packets; namespace OpenMetaverse { - #region Enums - - /// + #region Enums + + /// /// Permission request flags, asked when a script wants to control an Avatar /// [Flags] public enum ScriptPermission : int { - /// Placeholder for empty values, shouldn't ever see this - None = 0, - /// Script wants ability to take money from you - Debit = 1 << 1, - /// Script wants to take camera controls for you - TakeControls = 1 << 2, - /// Script wants to remap avatars controls - RemapControls = 1 << 3, - /// Script wants to trigger avatar animations + /// Placeholder for empty values, shouldn't ever see this + None = 0, + /// Script wants ability to take money from you + Debit = 1 << 1, + /// Script wants to take camera controls for you + TakeControls = 1 << 2, + /// Script wants to remap avatars controls + RemapControls = 1 << 3, + /// Script wants to trigger avatar animations /// This function is not implemented on the grid - TriggerAnimation = 1 << 4, - /// Script wants to attach or detach the prim or primset to your avatar - Attach = 1 << 5, - /// Script wants permission to release ownership + TriggerAnimation = 1 << 4, + /// Script wants to attach or detach the prim or primset to your avatar + Attach = 1 << 5, + /// Script wants permission to release ownership /// This function is not implemented on the grid /// The concept of "public" objects does not exist anymore. - ReleaseOwnership = 1 << 6, - /// Script wants ability to link/delink with other prims - ChangeLinks = 1 << 7, - /// Script wants permission to change joints + ReleaseOwnership = 1 << 6, + /// Script wants ability to link/delink with other prims + ChangeLinks = 1 << 7, + /// Script wants permission to change joints /// This function is not implemented on the grid - ChangeJoints = 1 << 8, - /// Script wants permissions to change permissions + ChangeJoints = 1 << 8, + /// Script wants permissions to change permissions /// This function is not implemented on the grid - ChangePermissions = 1 << 9, - /// Script wants to track avatars camera position and rotation - TrackCamera = 1 << 10, - /// Script wants to control your camera - ControlCamera = 1 << 11 + ChangePermissions = 1 << 9, + /// Script wants to track avatars camera position and rotation + TrackCamera = 1 << 10, + /// Script wants to control your camera + ControlCamera = 1 << 11 } - + /// - /// Special commands used in Instant Messages - /// - public enum InstantMessageDialog : byte - { - /// Indicates a regular IM from another agent - MessageFromAgent = 0, - /// Simple notification box with an OK button - MessageBox = 1, - // Used to show a countdown notification with an OK - // button, deprecated now + /// Special commands used in Instant Messages + /// + public enum InstantMessageDialog : byte + { + /// Indicates a regular IM from another agent + MessageFromAgent = 0, + /// Simple notification box with an OK button + MessageBox = 1, + // Used to show a countdown notification with an OK + // button, deprecated now //[Obsolete] //MessageBoxCountdown = 2, - /// You've been invited to join a group. - GroupInvitation = 3, - /// Inventory offer - InventoryOffered = 4, - /// Accepted inventory offer - InventoryAccepted = 5, - /// Declined inventory offer - InventoryDeclined = 6, - /// Group vote - GroupVote = 7, - // A message to everyone in the agent's group, no longer - // used + /// You've been invited to join a group. + GroupInvitation = 3, + /// Inventory offer + InventoryOffered = 4, + /// Accepted inventory offer + InventoryAccepted = 5, + /// Declined inventory offer + InventoryDeclined = 6, + /// Group vote + GroupVote = 7, + // A message to everyone in the agent's group, no longer + // used //[Obsolete] //DeprecatedGroupMessage = 8, - /// An object is offering its inventory - TaskInventoryOffered = 9, - /// Accept an inventory offer from an object - TaskInventoryAccepted = 10, - /// Decline an inventory offer from an object - TaskInventoryDeclined = 11, - /// Unknown - NewUserDefault = 12, - /// Start a session, or add users to a session - SessionAdd = 13, - /// Start a session, but don't prune offline users - SessionOfflineAdd = 14, - /// Start a session with your group - SessionGroupStart = 15, - /// Start a session without a calling card (finder or objects) - SessionCardlessStart = 16, - /// Send a message to a session - SessionSend = 17, - /// Leave a session - SessionDrop = 18, - /// Indicates that the IM is from an object - MessageFromObject = 19, - /// Sent an IM to a busy user, this is the auto response - BusyAutoResponse = 20, - /// Shows the message in the console and chat history - ConsoleAndChatHistory = 21, - /// Send a teleport lure - RequestTeleport = 22, - /// Response sent to the agent which inititiated a teleport invitation - AcceptTeleport = 23, - /// Response sent to the agent which inititiated a teleport invitation - DenyTeleport = 24, - /// Only useful if you have Linden permissions - GodLikeRequestTeleport = 25, - /// A placeholder type for future expansion, currently not - /// used - CurrentlyUnused = 26, - // Notification of a new group election, this is - // deprecated + /// An object is offering its inventory + TaskInventoryOffered = 9, + /// Accept an inventory offer from an object + TaskInventoryAccepted = 10, + /// Decline an inventory offer from an object + TaskInventoryDeclined = 11, + /// Unknown + NewUserDefault = 12, + /// Start a session, or add users to a session + SessionAdd = 13, + /// Start a session, but don't prune offline users + SessionOfflineAdd = 14, + /// Start a session with your group + SessionGroupStart = 15, + /// Start a session without a calling card (finder or objects) + SessionCardlessStart = 16, + /// Send a message to a session + SessionSend = 17, + /// Leave a session + SessionDrop = 18, + /// Indicates that the IM is from an object + MessageFromObject = 19, + /// Sent an IM to a busy user, this is the auto response + BusyAutoResponse = 20, + /// Shows the message in the console and chat history + ConsoleAndChatHistory = 21, + /// Send a teleport lure + RequestTeleport = 22, + /// Response sent to the agent which inititiated a teleport invitation + AcceptTeleport = 23, + /// Response sent to the agent which inititiated a teleport invitation + DenyTeleport = 24, + /// Only useful if you have Linden permissions + GodLikeRequestTeleport = 25, + /// A placeholder type for future expansion, currently not + /// used + CurrentlyUnused = 26, + // Notification of a new group election, this is + // deprecated //[Obsolete] //DeprecatedGroupElection = 27, - /// IM to tell the user to go to an URL - GotoUrl = 28, - /// IM for help - Session911Start = 29, - /// IM sent automatically on call for help, sends a lure - /// to each Helper reached - Lure911 = 30, - /// Like an IM but won't go to email - FromTaskAsAlert = 31, - /// IM from a group officer to all group members - GroupNotice = 32, - /// Unknown - GroupNoticeInventoryAccepted = 33, - /// Unknown - GroupNoticeInventoryDeclined = 34, - /// Accept a group invitation - GroupInvitationAccept = 35, - /// Decline a group invitation - GroupInvitationDecline = 36, - /// Unknown - GroupNoticeRequested = 37, - /// An avatar is offering you friendship - FriendshipOffered = 38, - /// An avatar has accepted your friendship offer - FriendshipAccepted = 39, - /// An avatar has declined your friendship offer - FriendshipDeclined = 40, - /// Indicates that a user has started typing - StartTyping = 41, - /// Indicates that a user has stopped typing - StopTyping = 42 + /// IM to tell the user to go to an URL + GotoUrl = 28, + /// IM for help + Session911Start = 29, + /// IM sent automatically on call for help, sends a lure + /// to each Helper reached + Lure911 = 30, + /// Like an IM but won't go to email + FromTaskAsAlert = 31, + /// IM from a group officer to all group members + GroupNotice = 32, + /// Unknown + GroupNoticeInventoryAccepted = 33, + /// Unknown + GroupNoticeInventoryDeclined = 34, + /// Accept a group invitation + GroupInvitationAccept = 35, + /// Decline a group invitation + GroupInvitationDecline = 36, + /// Unknown + GroupNoticeRequested = 37, + /// An avatar is offering you friendship + FriendshipOffered = 38, + /// An avatar has accepted your friendship offer + FriendshipAccepted = 39, + /// An avatar has declined your friendship offer + FriendshipDeclined = 40, + /// Indicates that a user has started typing + StartTyping = 41, + /// Indicates that a user has stopped typing + StopTyping = 42 } - /// - /// Flag in Instant Messages, whether the IM should be delivered to - /// offline avatars as well - /// - public enum InstantMessageOnline - { - /// Only deliver to online avatars - Online = 0, - /// If the avatar is offline the message will be held until - /// they login next, and possibly forwarded to their e-mail account - Offline = 1 - } + /// + /// Flag in Instant Messages, whether the IM should be delivered to + /// offline avatars as well + /// + public enum InstantMessageOnline + { + /// Only deliver to online avatars + Online = 0, + /// If the avatar is offline the message will be held until + /// they login next, and possibly forwarded to their e-mail account + Offline = 1 + } - /// - /// Conversion type to denote Chat Packet types in an easier-to-understand format - /// - public enum ChatType : byte - { - /// Whisper (5m radius) - Whisper = 0, - /// Normal chat (10/20m radius), what the official viewer typically sends - Normal = 1, - /// Shouting! (100m radius) - Shout = 2, - // Say chat (10/20m radius) - The official viewer will - // print "[4:15] You say, hey" instead of "[4:15] You: hey" + /// + /// Conversion type to denote Chat Packet types in an easier-to-understand format + /// + public enum ChatType : byte + { + /// Whisper (5m radius) + Whisper = 0, + /// Normal chat (10/20m radius), what the official viewer typically sends + Normal = 1, + /// Shouting! (100m radius) + Shout = 2, + // Say chat (10/20m radius) - The official viewer will + // print "[4:15] You say, hey" instead of "[4:15] You: hey" //[Obsolete] //Say = 3, - /// Event message when an Avatar has begun to type - StartTyping = 4, - /// Event message when an Avatar has stopped typing - StopTyping = 5, - /// Unknown - Debug = 6, + /// Event message when an Avatar has begun to type + StartTyping = 4, + /// Event message when an Avatar has stopped typing + StopTyping = 5, + /// Unknown + Debug = 6, /// Event message when an object uses llOwnerSay - OwnerSay = 8 - } + OwnerSay = 8 + } - /// - /// Identifies the source of a chat message - /// - public enum ChatSourceType : byte - { - /// Chat from the grid or simulator - System = 0, - /// Chat from another avatar - Agent = 1, - /// Chat from an object - Object = 2 - } + /// + /// Identifies the source of a chat message + /// + public enum ChatSourceType : byte + { + /// Chat from the grid or simulator + System = 0, + /// Chat from another avatar + Agent = 1, + /// Chat from an object + Object = 2 + } - /// - /// - /// - public enum ChatAudibleLevel : sbyte - { - /// - Not = -1, - /// - Barely = 0, - /// - Fully = 1 - } + /// + /// + /// + public enum ChatAudibleLevel : sbyte + { + /// + Not = -1, + /// + Barely = 0, + /// + Fully = 1 + } - /// - /// Effect type used in ViewerEffect packets - /// - public enum EffectType : byte - { - /// - Text = 0, - /// - Icon, - /// - Connector, - /// - FlexibleObject, - /// - AnimalControls, - /// - AnimationObject, - /// - Cloth, - /// Project a beam from a source to a destination, such as - /// the one used when editing an object - Beam, - /// - Glow, - /// - Point, - /// - Trail, - /// Create a swirl of particles around an object - Sphere, - /// - Spiral, - /// - Edit, - /// Cause an avatar to look at an object - LookAt, - /// Cause an avatar to point at an object - PointAt - } + /// + /// Effect type used in ViewerEffect packets + /// + public enum EffectType : byte + { + /// + Text = 0, + /// + Icon, + /// + Connector, + /// + FlexibleObject, + /// + AnimalControls, + /// + AnimationObject, + /// + Cloth, + /// Project a beam from a source to a destination, such as + /// the one used when editing an object + Beam, + /// + Glow, + /// + Point, + /// + Trail, + /// Create a swirl of particles around an object + Sphere, + /// + Spiral, + /// + Edit, + /// Cause an avatar to look at an object + LookAt, + /// Cause an avatar to point at an object + PointAt + } - /// - /// The action an avatar is doing when looking at something, used in - /// ViewerEffect packets for the LookAt effect - /// - public enum LookAtType : byte - { - /// - None, - /// - Idle, - /// - AutoListen, - /// - FreeLook, - /// - Respond, - /// - Hover, - /// Deprecated + /// + /// The action an avatar is doing when looking at something, used in + /// ViewerEffect packets for the LookAt effect + /// + public enum LookAtType : byte + { + /// + None, + /// + Idle, + /// + AutoListen, + /// + FreeLook, + /// + Respond, + /// + Hover, + /// Deprecated [Obsolete] - Conversation, - /// - Select, - /// - Focus, - /// - Mouselook, - /// - Clear - } + Conversation, + /// + Select, + /// + Focus, + /// + Mouselook, + /// + Clear + } - /// - /// The action an avatar is doing when pointing at something, used in - /// ViewerEffect packets for the PointAt effect - /// - public enum PointAtType : byte - { - /// - None, - /// - Select, - /// - Grab, - /// - Clear + /// + /// The action an avatar is doing when pointing at something, used in + /// ViewerEffect packets for the PointAt effect + /// + public enum PointAtType : byte + { + /// + None, + /// + Select, + /// + Grab, + /// + Clear } /// @@ -502,17 +502,17 @@ namespace OpenMetaverse MouseLookLeftButton = 1073741824 } #endregion Enums - + #region Structs - - /// - /// Instant Message - /// - public struct InstantMessage - { - /// Key of sender - public UUID FromAgentID; - /// Name of sender + + /// + /// Instant Message + /// + public struct InstantMessage + { + /// Key of sender + public UUID FromAgentID; + /// Name of sender public string FromAgentName; /// Key of destination avatar public UUID ToAgentID; @@ -536,21 +536,23 @@ namespace OpenMetaverse public InstantMessageOnline Offline; /// Context specific packed data public byte[] BinaryBucket; - //Print the contents of a message - public override string ToString(){ - string result=""; - Type imType = this.GetType(); - FieldInfo[] fields = imType.GetFields(); - foreach (FieldInfo field in fields){ - result += (field.Name + " = " + field.GetValue(this) + " "); - } - return result; + //Print the contents of a message + public override string ToString() + { + string result = ""; + Type imType = this.GetType(); + FieldInfo[] fields = imType.GetFields(); + foreach (FieldInfo field in fields) + { + result += (field.Name + " = " + field.GetValue(this) + " "); + } + return result; + + } + } + + #endregion Structs - } - } - - #endregion Structs - /// /// Manager class for our own avatar /// @@ -611,39 +613,39 @@ namespace OpenMetaverse public enum TeleportFlags : uint { /// No flags set, or teleport failed - Default = 0, + Default = 0, /// Set when newbie leaves help island for first time SetHomeToTarget = 1 << 0, /// SetLastToTarget = 1 << 1, /// Via Lure - ViaLure = 1 << 2, + ViaLure = 1 << 2, /// Via Landmark - ViaLandmark = 1 << 3, + ViaLandmark = 1 << 3, /// Via Location - ViaLocation = 1 << 4, + ViaLocation = 1 << 4, /// Via Home - ViaHome = 1 << 5, + ViaHome = 1 << 5, /// Via Telehub - ViaTelehub = 1 << 6, + ViaTelehub = 1 << 6, /// Via Login - ViaLogin = 1 << 7, + ViaLogin = 1 << 7, /// Linden Summoned - ViaGodlikeLure = 1 << 8, + ViaGodlikeLure = 1 << 8, /// Linden Forced me - Godlike = 1 << 9, + Godlike = 1 << 9, /// - NineOneOne = 1 << 10, + NineOneOne = 1 << 10, /// Agent Teleported Home via Script - DisableCancel = 1 << 11, + DisableCancel = 1 << 11, /// - ViaRegionID = 1 << 12, + ViaRegionID = 1 << 12, /// - IsFlying = 1 << 13, + IsFlying = 1 << 13, /// - ResetHome = 1 << 14, + ResetHome = 1 << 14, /// forced to new location for example when avatar is banned or ejected - ForceRedirect = 1 << 15, + ForceRedirect = 1 << 15, /// Teleport Finished via a Lure FinishedViaLure = 1 << 26, /// Finished, Sim Changed @@ -697,7 +699,7 @@ namespace OpenMetaverse /// Key of source /// Key of the sender /// Senders position - public delegate void ChatCallback(string message, ChatAudibleLevel audible, ChatType type, + public delegate void ChatCallback(string message, ChatAudibleLevel audible, ChatType type, ChatSourceType sourceType, string fromName, UUID id, UUID ownerid, Vector3 position); /// @@ -734,7 +736,7 @@ namespace OpenMetaverse /// Whether or not ownerID is a group /// Message displayed along with URL /// Offered URL - public delegate void LoadURLCallback( string objectName, UUID objectID, UUID ownerID, bool ownerIsGroup, string message, string URL); + public delegate void LoadURLCallback(string objectName, UUID objectID, UUID ownerID, bool ownerIsGroup, string message, string URL); /// /// Triggered when the L$ account balance for this avatar changes @@ -797,7 +799,7 @@ namespace OpenMetaverse /// Avatars Active Title /// Powers Avatar has in group /// Name of the Group - public delegate void AgentDataCallback(string firstName, string lastName, UUID activeGroupID, + public delegate void AgentDataCallback(string firstName, string lastName, UUID activeGroupID, string groupTitle, GroupPowers groupPowers, string groupName); /// @@ -832,17 +834,17 @@ namespace OpenMetaverse /// Temporary session Key /// if session start successful, /// otherwise - public delegate void GroupChatJoined(UUID groupChatSessionID, UUID tmpSessionID, bool success); + public delegate void GroupChatJoinedCallback(UUID groupChatSessionID, string sessionName, UUID tmpSessionID, bool success); /// Fired when agent group chat session terminated /// Key of Session (groups UUID) - public delegate void GroupChatLeft(UUID groupchatSessionID); + public delegate void GroupChatLeftCallback(UUID groupchatSessionID); /// /// Fired when alert message received from simulator /// /// the message sent from the grid to our avatar. - public delegate void AlertMessage(string message); + public delegate void AlertMessageCallback(string message); /// /// Fired when a script wants to give or release controls. @@ -889,6 +891,19 @@ namespace OpenMetaverse public delegate void AvatarSitResponseCallback(UUID objectID, bool autoPilot, Vector3 cameraAtOffset, Vector3 cameraEyeOffset, bool forceMouselook, Vector3 sitPosition, Quaternion sitRotation); + /// + /// Fired when a new member joins a Group chat session + /// + /// the ID of the session + /// the ID of the avatar that joined + public delegate void ChatSessionMemberAddedCallback(UUID sessionID, UUID agent_key); + /// + /// Fired when a member of a Group chat leaves the session + /// + /// the ID of the session + /// the ID of the avatar that joined + public delegate void ChatSessionMemberLeftCallback(UUID sessionID, UUID agent_key); + #endregion Callbacks #region Events @@ -927,11 +942,11 @@ namespace OpenMetaverse /// Callback for the agent moving in to a neighboring sim public event RegionCrossedCallback OnRegionCrossed; /// Callback for when agent is confirmed joined group chat session. - public event GroupChatJoined OnGroupChatJoin; + public event GroupChatJoinedCallback OnGroupChatJoin; /// Callback for when agent is confirmed to have left group chat session. - public event GroupChatLeft OnGroupChatLeft; + public event GroupChatLeftCallback OnGroupChatLeft; /// Alert messages sent to client from simulator - public event AlertMessage OnAlertMessage; + public event AlertMessageCallback OnAlertMessage; /// Fired when a script wants to take or release control of your avatar. public event ScriptControlCallback OnScriptControlChange; /// Fired when our avatar camera reaches the maximum possible point @@ -940,6 +955,10 @@ namespace OpenMetaverse public event ScriptSensorReplyCallback OnScriptSensorReply; /// Fired in response to a sit request public event AvatarSitResponseCallback OnAvatarSitResponse; + /// Fired when a new member joins an active ChatterBoxSession session + public event ChatSessionMemberAddedCallback OnChatSessionMemberAdded; + /// Fired when a member of an active ChatterBoxSession leaves the session + public event ChatSessionMemberLeftCallback OnChatSessionMemberLeft; #endregion Events @@ -954,7 +973,7 @@ namespace OpenMetaverse /// /// Dictionary containing current Group Chat sessions and members /// - public InternalDictionary> GroupChatSessions = new InternalDictionary>(); + public InternalDictionary> GroupChatSessions = new InternalDictionary>(); #region Properties @@ -1027,7 +1046,7 @@ namespace OpenMetaverse if (sittingOn != 0) { Primitive parent; - if(Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent)) + if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent)) { return parent.Position + relativePosition; } @@ -1122,7 +1141,7 @@ namespace OpenMetaverse private uint heightWidthGenCounter; private float health; private int balance; - private UUID activeGroup; + private UUID activeGroup; #endregion Private Members /// @@ -1162,15 +1181,15 @@ namespace OpenMetaverse Client.Network.RegisterCallback(PacketType.HealthMessage, new NetworkManager.PacketCallback(HealthHandler)); // Money callback Client.Network.RegisterCallback(PacketType.MoneyBalanceReply, new NetworkManager.PacketCallback(BalanceHandler)); - //Agent update callback - Client.Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler)); + //Agent update callback + Client.Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler)); // Animation callback Client.Network.RegisterCallback(PacketType.AvatarAnimation, new NetworkManager.PacketCallback(AvatarAnimationHandler)); // Object colliding into our agent callback Client.Network.RegisterCallback(PacketType.MeanCollisionAlert, new NetworkManager.PacketCallback(MeanCollisionAlertHandler)); // Region Crossing Client.Network.RegisterCallback(PacketType.CrossedRegion, new NetworkManager.PacketCallback(CrossedRegionHandler)); - // CAPS callbacks + // CAPS callbacks Client.Network.RegisterEventCallback("EstablishAgentCommunication", new Caps.EventQueueCallback(EstablishAgentCommunicationEventHandler)); // Incoming Group Chat Client.Network.RegisterEventCallback("ChatterBoxInvitation", new Caps.EventQueueCallback(ChatterBoxInvitationHandler)); @@ -1254,9 +1273,9 @@ namespace OpenMetaverse /// Text message being sent /// IM session ID (to differentiate between IM windows) /// IDs of sessions for a conference - public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID, + public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID, UUID[] conferenceIDs) - { + { byte[] binaryBucket; if (conferenceIDs != null && conferenceIDs.Length > 0) @@ -1270,9 +1289,9 @@ namespace OpenMetaverse binaryBucket = new byte[0]; } - InstantMessage(fromName, target, message, imSessionID, InstantMessageDialog.MessageFromAgent, + InstantMessage(fromName, target, message, imSessionID, InstantMessageDialog.MessageFromAgent, InstantMessageOnline.Offline, Vector3.Zero, UUID.Zero, binaryBucket); - } + } /// /// Send an Instant Message @@ -1287,8 +1306,8 @@ namespace OpenMetaverse /// RegionID Sender is In /// Packed binary data that is specific to /// the dialog type - public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID, - InstantMessageDialog dialog, InstantMessageOnline offline, Vector3 position, UUID regionID, + public void InstantMessage(string fromName, UUID target, string message, UUID imSessionID, + InstantMessageDialog dialog, InstantMessageOnline offline, Vector3 position, UUID regionID, byte[] binaryBucket) { if (target != UUID.Zero) @@ -1365,12 +1384,12 @@ namespace OpenMetaverse im.MessageBlock.Position = Vector3.Zero; im.MessageBlock.RegionID = UUID.Zero; im.MessageBlock.BinaryBucket = Utils.StringToBytes("\0"); - + Client.Network.SendPacket(im); } else { - Logger.Log("No Active group chat session appears to exist, use RequestJoinGroupChat() to join one", + Logger.Log("No Active group chat session appears to exist, use RequestJoinGroupChat() to join one", Helpers.LogLevel.Error, Client); } } @@ -1389,11 +1408,12 @@ namespace OpenMetaverse im.MessageBlock.FromAgentName = Utils.StringToBytes(Client.Self.Name); im.MessageBlock.FromGroup = false; im.MessageBlock.Message = new byte[0]; + im.MessageBlock.ParentEstateID = 0; im.MessageBlock.Offline = 0; im.MessageBlock.ID = groupID; im.MessageBlock.ToAgentID = groupID; im.MessageBlock.BinaryBucket = new byte[0]; - im.MessageBlock.Position = Vector3.Zero; + im.MessageBlock.Position = Client.Self.SimPosition; im.MessageBlock.RegionID = UUID.Zero; Client.Network.SendPacket(im); @@ -1462,7 +1482,7 @@ namespace OpenMetaverse UUID effectID) { ViewerEffectPacket effect = new ViewerEffectPacket(); - + effect.AgentData.AgentID = Client.Self.AgentID; effect.AgentData.SessionID = Client.Self.SessionID; @@ -1563,7 +1583,7 @@ namespace OpenMetaverse /// Color values of beam /// a float representing the duration the beam will last /// of the Effect - public void BeamEffect(UUID sourceAvatar, UUID targetObject, Vector3d globalOffset, Color4 color, + public void BeamEffect(UUID sourceAvatar, UUID targetObject, Vector3d globalOffset, Color4 color, float duration, UUID effectID) { ViewerEffectPacket effect = new ViewerEffectPacket(); @@ -1913,7 +1933,7 @@ namespace OpenMetaverse /// public void PayUploadFee() { - GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, String.Empty, MoneyTransactionType.UploadCharge, + GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, String.Empty, MoneyTransactionType.UploadCharge, TransactionFlags.None); } @@ -1923,7 +1943,7 @@ namespace OpenMetaverse /// description of the transaction public void PayUploadFee(string description) { - GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, description, MoneyTransactionType.UploadCharge, + GiveMoney(UUID.Zero, Client.Settings.UPLOAD_COST, description, MoneyTransactionType.UploadCharge, TransactionFlags.None); } @@ -2025,21 +2045,21 @@ namespace OpenMetaverse return Teleport(UUID.Zero); } - /// - /// Teleport agent to a landmark - /// - /// of the landmark to teleport agent to - /// true on success, false on failure - public bool Teleport(UUID landmark) - { - teleportStat = TeleportStatus.None; + /// + /// Teleport agent to a landmark + /// + /// of the landmark to teleport agent to + /// true on success, false on failure + public bool Teleport(UUID landmark) + { + teleportStat = TeleportStatus.None; teleportEvent.Reset(); - TeleportLandmarkRequestPacket p = new TeleportLandmarkRequestPacket(); - p.Info = new TeleportLandmarkRequestPacket.InfoBlock(); - p.Info.AgentID = Client.Self.AgentID; - p.Info.SessionID = Client.Self.SessionID; - p.Info.LandmarkID = landmark; - Client.Network.SendPacket(p); + TeleportLandmarkRequestPacket p = new TeleportLandmarkRequestPacket(); + p.Info = new TeleportLandmarkRequestPacket.InfoBlock(); + p.Info.AgentID = Client.Self.AgentID; + p.Info.SessionID = Client.Self.SessionID; + p.Info.LandmarkID = landmark; + Client.Network.SendPacket(p); teleportEvent.WaitOne(Client.Settings.TELEPORT_TIMEOUT, false); @@ -2052,7 +2072,7 @@ namespace OpenMetaverse } return (teleportStat == TeleportStatus.Finished); - } + } /// /// Attempt to look up a simulator name and teleport to the discovered @@ -2233,7 +2253,7 @@ namespace OpenMetaverse /// true to accept the lure, false to decline it public void TeleportLureRespond(UUID requesterID, bool accept) { - InstantMessage(Name, requesterID, String.Empty, UUID.Random(), + InstantMessage(Name, requesterID, String.Empty, UUID.Random(), accept ? InstantMessageDialog.AcceptTeleport : InstantMessageDialog.DenyTeleport, InstantMessageOnline.Offline, this.SimPosition, UUID.Zero, new byte[0]); @@ -2437,23 +2457,23 @@ namespace OpenMetaverse if (OnInstantMessage != null) { - InstantMessage message; - message.FromAgentID = im.AgentData.AgentID; - message.FromAgentName = Utils.BytesToString(im.MessageBlock.FromAgentName); - message.ToAgentID = im.MessageBlock.ToAgentID; - message.ParentEstateID = im.MessageBlock.ParentEstateID; - message.RegionID = im.MessageBlock.RegionID; - message.Position = im.MessageBlock.Position; - message.Dialog = (InstantMessageDialog)im.MessageBlock.Dialog; - message.GroupIM = im.MessageBlock.FromGroup; - message.IMSessionID = im.MessageBlock.ID; - message.Timestamp = new DateTime(im.MessageBlock.Timestamp); - message.Message = Utils.BytesToString(im.MessageBlock.Message); - message.Offline = (InstantMessageOnline)im.MessageBlock.Offline; - message.BinaryBucket = im.MessageBlock.BinaryBucket; + InstantMessage message; + message.FromAgentID = im.AgentData.AgentID; + message.FromAgentName = Utils.BytesToString(im.MessageBlock.FromAgentName); + message.ToAgentID = im.MessageBlock.ToAgentID; + message.ParentEstateID = im.MessageBlock.ParentEstateID; + message.RegionID = im.MessageBlock.RegionID; + message.Position = im.MessageBlock.Position; + message.Dialog = (InstantMessageDialog)im.MessageBlock.Dialog; + message.GroupIM = im.MessageBlock.FromGroup; + message.IMSessionID = im.MessageBlock.ID; + message.Timestamp = new DateTime(im.MessageBlock.Timestamp); + message.Message = Utils.BytesToString(im.MessageBlock.Message); + message.Offline = (InstantMessageOnline)im.MessageBlock.Offline; + message.BinaryBucket = im.MessageBlock.BinaryBucket; - try { OnInstantMessage(message, simulator); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + try { OnInstantMessage(message, simulator); } + catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } } @@ -2567,7 +2587,8 @@ namespace OpenMetaverse LoadURLPacket loadURL = (LoadURLPacket)packet; if (OnLoadURL != null) { - try { + try + { OnLoadURL( Utils.BytesToString(loadURL.Data.ObjectName), loadURL.Data.ObjectID, @@ -2647,10 +2668,13 @@ namespace OpenMetaverse if (OnMoneyBalanceReplyReceived != null) { - try { OnMoneyBalanceReplyReceived(mbrp.MoneyData.TransactionID, - mbrp.MoneyData.TransactionSuccess, mbrp.MoneyData.MoneyBalance, - mbrp.MoneyData.SquareMetersCredit, mbrp.MoneyData.SquareMetersCommitted, - Utils.BytesToString(mbrp.MoneyData.Description)); } + try + { + OnMoneyBalanceReplyReceived(mbrp.MoneyData.TransactionID, + mbrp.MoneyData.TransactionSuccess, mbrp.MoneyData.MoneyBalance, + mbrp.MoneyData.SquareMetersCredit, mbrp.MoneyData.SquareMetersCommitted, + Utils.BytesToString(mbrp.MoneyData.Description)); + } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } @@ -2700,7 +2724,7 @@ namespace OpenMetaverse { bool finished = false; TeleportFlags flags = TeleportFlags.Default; - + if (packet.Type == PacketType.TeleportStart) { TeleportStartPacket start = (TeleportStartPacket)packet; @@ -2962,27 +2986,25 @@ namespace OpenMetaverse LLSDMap map = (LLSDMap)llsd; UUID sessionID = map["session_id"].AsUUID(); UUID tmpSessionID = map["temp_session_id"].AsUUID(); + + string sessionName = String.Empty; + bool success = map["success"].AsBoolean(); if (success) { - LLSDArray agentlist = (LLSDArray)map["agents"]; - List agents = new List(); - foreach (LLSD id in agentlist) - agents.Add(id.AsUUID()); - - lock (GroupChatSessions.Dictionary) - { - if (GroupChatSessions.ContainsKey(sessionID)) - GroupChatSessions.Dictionary[sessionID] = agents; - else - GroupChatSessions.Add(sessionID, agents); - } + LLSDMap sessionInfo = (LLSDMap)map["session_info"]; + sessionName = sessionInfo["session_name"].AsString(); + + /* Parameters we do not currently use for anything */ + // sessionInfo["type"].AsInteger(); + // sessionInfo["voice_enabled"}.AsBoolean(); + // sessionInfo["moderated_mode"] -> ["voice"].AsBoolean() } if (OnGroupChatJoin != null) { - try { OnGroupChatJoin(sessionID, tmpSessionID, success); } + try { OnGroupChatJoin(sessionID, sessionName, tmpSessionID, success); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } @@ -2995,40 +3017,171 @@ namespace OpenMetaverse /// private void ChatterBoxSessionAgentListReplyHandler(string capsKey, LLSD llsd, Simulator simulator) { + // parse the LLSD LLSDMap map = (LLSDMap)llsd; - UUID sessionID = map["session_id"].AsUUID(); - LLSDMap update = (LLSDMap)map["updates"]; - string errormsg = map["error"].AsString(); - - //if (errormsg.Equals("already in session")) - // return; - foreach (KeyValuePair kvp in update) + // verify sessions exists, if not add it + UUID sessionID; + if (map.ContainsKey("session_id")) { - if (kvp.Value.Equals("ENTER")) + sessionID = map["session_id"].AsUUID(); + lock (GroupChatSessions) + if (!GroupChatSessions.ContainsKey(sessionID)) + GroupChatSessions.Add(sessionID, new List()); + } + else + { + return; + } + + + //string errormsg = map["error"].AsString(); + LLSDMap updates = (LLSDMap)map["updates"]; + + // Handle any agent data updates + LLSDMap agent_updates = (LLSDMap)map["agent_updates"]; + + foreach (KeyValuePair kvp in agent_updates) + { + UUID agent_key = kvp.Key; + LLSDMap record = (LLSDMap)kvp.Value; + + // handle joins/parts first + if (record.ContainsKey("transition")) { + // find existing record if any + ChatSessionMember fndMbr; lock (GroupChatSessions.Dictionary) { - if (!GroupChatSessions.Dictionary[sessionID].Contains((UUID)kvp.Key)) - GroupChatSessions.Dictionary[sessionID].Add((UUID)kvp.Key); + fndMbr = GroupChatSessions[sessionID].Find(delegate(ChatSessionMember member) + { + return member.AvatarKey == agent_key; + }); + } + + // handle joins + if (record["transition"].AsString().Equals("ENTER")) + { + if (fndMbr.AvatarKey == null) + { + fndMbr = new ChatSessionMember(); + fndMbr.AvatarKey = agent_key; + + lock (GroupChatSessions.Dictionary) + GroupChatSessions[sessionID].Add(fndMbr); + + if (OnChatSessionMemberAdded != null) + { + try { OnChatSessionMemberAdded(sessionID, agent_key); } + catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + } + } + + } + // handle parts + else if (record["transition"].AsString().Equals("LEAVE")) + { + if (fndMbr.AvatarKey != null) + lock (GroupChatSessions.Dictionary) + GroupChatSessions[sessionID].Remove(fndMbr); + + if (OnChatSessionMemberLeft != null) + { + try { OnChatSessionMemberLeft(sessionID, agent_key); } + catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + } + // no need to process anything else in this record + continue; + } + // this should only fire if LL adds a new transition but doesn't tell anyone + else + { + Logger.Log("Unknown transition action " + record["transition"], Helpers.LogLevel.Warning, Client); } } - else if (kvp.Value.Equals("LEAVE")) - { - lock (GroupChatSessions.Dictionary) - { - if (GroupChatSessions.Dictionary[sessionID].Contains((UUID)kvp.Key)) - GroupChatSessions.Dictionary[sessionID].Remove((UUID)kvp.Key); - // we left session, remove from dictionary - if (kvp.Key.Equals(Client.Self.id) && OnGroupChatLeft != null) + + // Handle any updates + + // search for member to update + ChatSessionMember update_member = GroupChatSessions.Dictionary[sessionID].Find(delegate(ChatSessionMember m) + { + return m.AvatarKey == agent_key; + }); + + LLSDMap record_info = (LLSDMap)record["info"]; + + lock (GroupChatSessions.Dictionary) + { + + if (record_info.ContainsKey("mutes")) + { + LLSDMap mutes = (LLSDMap)record_info["mutes"]; + foreach (KeyValuePair muteEntry in mutes) { - GroupChatSessions.Dictionary.Remove(sessionID); - OnGroupChatLeft(sessionID); + if (muteEntry.Key == "text") + { + update_member.MuteText = muteEntry.Value.AsBoolean(); + } + else if (muteEntry.Key == "voice") + { + update_member.MuteVoice = muteEntry.Value.AsBoolean(); + } } } + + if (record_info.ContainsKey("can_voice_chat")) + { + update_member.CanVoiceChat = record_info["can_voice_chat"].AsBoolean(); + } + + if (record_info.ContainsKey("is_moderator")) + { + update_member.IsModerator = record_info["is_moderator"].AsBoolean(); + } } + + // replace existing member record + lock (GroupChatSessions.Dictionary) + { + int found = GroupChatSessions.Dictionary[sessionID].FindIndex(delegate(ChatSessionMember m) + { + return m.AvatarKey == agent_key; + }); + + if (found >= 0) + GroupChatSessions.Dictionary[sessionID][found] = update_member; + } + } + + + //foreach (KeyValuePair kvp in updates) + //{ + // if (kvp.Value.Equals("ENTER")) + // { + // lock (GroupChatSessions.Dictionary) + // { + // if (!GroupChatSessions.Dictionary[sessionID].Contains((UUID)kvp.Key)) + // GroupChatSessions.Dictionary[sessionID].Add((UUID)kvp.Key); + // } + // } + // else if (kvp.Value.Equals("LEAVE")) + // { + // lock (GroupChatSessions.Dictionary) + // { + // if (GroupChatSessions.Dictionary[sessionID].Contains((UUID)kvp.Key)) + // GroupChatSessions.Dictionary[sessionID].Remove((UUID)kvp.Key); + + // // we left session, remove from dictionary + // if (kvp.Key.Equals(Client.Self.id) && OnGroupChatLeft != null) + // { + // GroupChatSessions.Dictionary.Remove(sessionID); + // OnGroupChatLeft(sessionID); + // } + // } + // } + //} } /// @@ -3038,34 +3191,75 @@ namespace OpenMetaverse /// LLSD Map containing invitation /// Originating Simulator private void ChatterBoxInvitationHandler(string capsKey, LLSD llsd, Simulator simulator) - { - if (OnInstantMessage != null) - { - LLSDMap map = (LLSDMap)llsd; - LLSDMap im = (LLSDMap)map["instantmessage"]; - LLSDMap agent = (LLSDMap)im["agent_params"]; - LLSDMap msg = (LLSDMap)im["message_params"]; - LLSDMap msgdata = (LLSDMap)msg["data"]; + { + if (OnInstantMessage != null) + { + LLSDMap map = (LLSDMap)llsd; + LLSDMap im = (LLSDMap)map["instantmessage"]; + LLSDMap agent = (LLSDMap)im["agent_params"]; + LLSDMap msg = (LLSDMap)im["message_params"]; + LLSDMap msgdata = (LLSDMap)msg["data"]; - InstantMessage message = new InstantMessage(); - - message.FromAgentID = map["from_id"].AsUUID(); - message.FromAgentName = map["from_name"].AsString(); - message.ToAgentID = msg["to_id"].AsString(); - message.ParentEstateID = (uint)msg["parent_estate_id"].AsInteger(); - message.RegionID = msg["region_id"].AsUUID(); - message.Position = ((LLSDArray)msg["position"]).AsVector3(); - message.Dialog = (InstantMessageDialog)msgdata["type"].AsInteger(); - message.GroupIM = true; - message.IMSessionID = map["session_id"].AsUUID(); - message.Timestamp = new DateTime(msgdata["timestamp"].AsInteger()); - message.Message = msg["message"].AsString(); - message.Offline = (InstantMessageOnline)msg["offline"].AsInteger(); - message.BinaryBucket = msg["binary_bucket"].AsBinary(); + InstantMessage message = new InstantMessage(); - try { OnInstantMessage(message, simulator); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } - } + message.FromAgentID = map["from_id"].AsUUID(); + message.FromAgentName = map["from_name"].AsString(); + message.ToAgentID = msg["to_id"].AsString(); + message.ParentEstateID = (uint)msg["parent_estate_id"].AsInteger(); + message.RegionID = msg["region_id"].AsUUID(); + message.Position = ((LLSDArray)msg["position"]).AsVector3(); + message.Dialog = (InstantMessageDialog)msgdata["type"].AsInteger(); + message.GroupIM = true; + message.IMSessionID = map["session_id"].AsUUID(); + message.Timestamp = new DateTime(msgdata["timestamp"].AsInteger()); + message.Message = msg["message"].AsString(); + message.Offline = (InstantMessageOnline)msg["offline"].AsInteger(); + message.BinaryBucket = msg["binary_bucket"].AsBinary(); + + try { OnInstantMessage(message, simulator); } + catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + } + } + + + /// + /// Moderate a chat session + /// + /// the of the session to moderate, for group chats this will be the groups UUID + /// the of the avatar to moderate + /// true to moderate (silence user), false to allow avatar to speak + public void ModerateChatSessions(UUID sessionID, UUID memberID, bool moderateText) + { + if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) + throw new Exception("ChatSessionRequest capability is not currently available"); + + Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest"); + + if (url != null) + { + LLSDMap req = new LLSDMap(); + req.Add("method", LLSD.FromString("mute update")); + + LLSDMap mute_info = new LLSDMap(); + mute_info.Add("text", LLSD.FromBoolean(moderateText)); + + LLSDMap parameters = new LLSDMap(); + parameters["agent_id"] = LLSD.FromUUID(memberID); + parameters["mute_info"] = mute_info; + + req["params"] = parameters; + + req.Add("session-id", LLSD.FromUUID(sessionID)); + + byte[] postData = StructuredData.LLSDParser.SerializeXmlBytes(req); + + CapsClient request = new CapsClient(url); + request.StartRequest(postData); + } + else + { + throw new Exception("ChatSessionRequest capability is not currently available"); + } } /// @@ -3116,13 +3310,16 @@ namespace OpenMetaverse { ScriptSensorReplyPacket.SensedDataBlock block = reply.SensedData[i]; ScriptSensorReplyPacket.RequesterBlock requestor = reply.Requester; - - try { OnScriptSensorReply(requestor.SourceID, block.GroupID, Utils.BytesToString(block.Name), - block.ObjectID, block.OwnerID, block.Position, block.Range, block.Rotation, (ScriptSensorTypeFlags)block.Type, block.Velocity); } + + try + { + OnScriptSensorReply(requestor.SourceID, block.GroupID, Utils.BytesToString(block.Name), + block.ObjectID, block.OwnerID, block.Position, block.Range, block.Rotation, (ScriptSensorTypeFlags)block.Type, block.Velocity); + } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } - + } /// diff --git a/OpenMetaverse/AvatarManager.cs b/OpenMetaverse/AvatarManager.cs index 37bca1c1..3c598563 100644 --- a/OpenMetaverse/AvatarManager.cs +++ b/OpenMetaverse/AvatarManager.cs @@ -239,6 +239,7 @@ namespace OpenMetaverse /// The avatar key to retrieve a name for public void RequestAvatarName(UUID id) { + Console.WriteLine("AvatarManager requesting UUID for {0}", id); UUIDNameRequestPacket request = new UUIDNameRequestPacket(); request.UUIDNameBlock = new UUIDNameRequestPacket.UUIDNameBlockBlock[1]; request.UUIDNameBlock[0] = new UUIDNameRequestPacket.UUIDNameBlockBlock(); @@ -253,16 +254,25 @@ namespace OpenMetaverse /// The avatar keys to retrieve names for public void RequestAvatarNames(List ids) { - UUIDNameRequestPacket request = new UUIDNameRequestPacket(); - request.UUIDNameBlock = new UUIDNameRequestPacket.UUIDNameBlockBlock[ids.Count]; - - for (int i = 0; i < ids.Count; i++) + Console.WriteLine("AvatarManager requesting UUIDs count {0}", ids.Count); + if (ids.Count > 0) { - request.UUIDNameBlock[i] = new UUIDNameRequestPacket.UUIDNameBlockBlock(); - request.UUIDNameBlock[i].ID = ids[i]; + UUIDNameRequestPacket request = new UUIDNameRequestPacket(); + request.UUIDNameBlock = new UUIDNameRequestPacket.UUIDNameBlockBlock[ids.Count]; + + for (int i = 0; i < ids.Count; i++) + { + request.UUIDNameBlock[i] = new UUIDNameRequestPacket.UUIDNameBlockBlock(); + request.UUIDNameBlock[i].ID = ids[i]; + } + + Client.Network.SendPacket(request); + } + else + { + // not sending request, no ids! } - Client.Network.SendPacket(request); } /// diff --git a/OpenMetaverse/GroupManager.cs b/OpenMetaverse/GroupManager.cs index e2f9e72b..1381138f 100644 --- a/OpenMetaverse/GroupManager.cs +++ b/OpenMetaverse/GroupManager.cs @@ -239,6 +239,24 @@ namespace OpenMetaverse } } + /// + /// Struct representing a member of a group chat session and their settings + /// + public struct ChatSessionMember + { + public UUID AvatarKey; + public bool CanVoiceChat; + public bool IsModerator; + public bool MuteText; + public bool MuteVoice; + + public override string ToString() + { + return String.Format("Avatar={0} CanVoiceChat={1} IsModerator={2} MuteText={3} MuteVoice={4}", + AvatarKey, CanVoiceChat, IsModerator, MuteText, MuteVoice); + } + } + #endregion Structs #region Enums @@ -260,100 +278,102 @@ namespace OpenMetaverse /// Group role powers flags /// [Flags] - public enum GroupRolePowers : long + public enum GroupPowers : long { + /// None = 0, + /// Can send invitations to groups default role Invite = 1 << 1, + /// Can eject members from group Eject = 1 << 2, + /// Can toggle 'Open Enrollment' and change 'Signup fee' ChangeOptions = 1 << 3, + /// Can create new roles CreateRole = 1 << 4, + /// Can delete existing roles DeleteRole = 1 << 5, + /// Can change Role names, titles and descriptions RoleProperties = 1 << 6, + /// Can assign other members to assigners role AssignMemberLimited = 1 << 7, + /// Can assign other members to any role AssignMember = 1 << 8, + /// Can remove members from roles RemoveMember = 1 << 9, + /// Can assign and remove abilities in roles ChangeActions = 1 << 10, + /// Can change group Charter, Insignia, 'Publish on the web' and which + /// members are publicly visible in group member listings ChangeIdentity = 1 << 11, + /// Can buy land or deed land to group LandDeed = 1 << 12, + /// Can abandon group owned land to Governor Linden on mainland, or Estate owner for + /// private estates LandRelease = 1 << 13, + /// Can set land for-sale information on group owned parcels LandSetSale = 1 << 14, - LandDevideJoin = 1 << 15, + /// Can subdivide and join parcels + LandDivideJoin = 1 << 15, + /// Can join group chat sessions + JoinChat = 1 << 16, + /// Can toggle "Show in Find Places" and set search category FindPlaces = 1 << 17, + /// Can change parcel name, description, and 'Publish on web' settings LandChangeIdentity = 1 << 18, + /// Can set the landing point and teleport routing on group land SetLandingPoint = 1 << 19, + /// Can change music and media settings ChangeMedia = 1 << 20, + /// Can toggle 'Edit Terrain' option in Land settings LandEdit = 1 << 21, + /// Can toggle various About Land > Options settings LandOptions = 1 << 22, + /// Can always terraform land, even if parcel settings have it turned off AllowEditLand = 1 << 23, + /// Can always fly while over group owned land AllowFly = 1 << 24, + /// Can always rez objects on group owned land AllowRez = 1 << 25, + /// Can always create landmarks for group owned parcels AllowLandmark = 1 << 26, + /// Can use voice chat in Group Chat sessions + AllowVoiceChat = 1 << 27, + /// Can set home location on any group owned parcel AllowSetHome = 1 << 28, + /// Can modify public access settings for group owned parcels LandManageAllowed = 1 << 29, + /// Can manager parcel ban lists on group owned land LandManageBanned = 1 << 30, + /// Can manage pass list sales information LandManagePasses = 1 << 31, + /// Can eject and freeze other avatars on group owned land LandEjectAndFreeze = 1 << 32, - ReturnGroupOwned = 1 << 48, + /// Can return objects set to group ReturnGroupSet = 1 << 33, + /// Can return non-group owned/set objects ReturnNonGroup = 1 << 34, + /// Can landscape using Linden plants LandGardening = 1 << 35, + /// Can deed objects to group DeedObject = 1 << 36, + /// Can moderate group chat sessions + ModerateChat = 1 << 37, + /// Can move group owned objects ObjectManipulate = 1 << 38, + /// Can set group owned objects for-sale ObjectSetForSale = 1 << 39, + /// Pay group liabilities and receive group dividends Accountable = 1 << 40, + /// Can send group notices SendNotices = 1 << 42, + /// Can receive group notices ReceiveNotices = 1 << 43, + /// Can create group proposals StartProposal = 1 << 44, - VoteOnProposal = 1 << 45 - } - - [Flags] - public enum GroupPowers : ulong - { - MemberInvite = 2, - MemberEject = 4, - MemberOptions = 8, - MemberVisibleInDir = 140737488355328, - RoleCreate = 16, - RoleDelete = 32, - RoleProperties = 64, - RoleAssignMemberLimited = 128, - RoleAssignMember = 256, - RoleRemoveMember = 512, - RoleChangeActions = 1024, - GroupChangeIdentity = 2048, - LandDeed = 4096, - LandRelease = 8192, - LandSetSaleInfo = 16384, - LandDivideJoin = 32768, - LandFindPlaces = 131072, - LandChangeIdentity = 262144, - LandSetLandingPoint = 524288, - LandChangeMedia = 1048576, - LandEdit = 2097152, - LandOptions = 4194304, - LandAllowEditLand = 8388608, - LandAllowFly = 16777216, - LandAllowCreate = 33554432, - LandAllowLandmark = 67108864, - LandAllowSetHome = 268435456, - LandManageAllowed = 536870912, - LandManageBanned = 1073741824, - LandManagePasses = 2147483648, - LandAdmin = 4294967296, - LandReturnGroupOwned = 281474976710656, - LandReturnGroupSet = 8589934592, - LandReturnNonGroup = 17179869184, - LandReturn = LandReturnGroupOwned | LandReturnGroupSet | LandReturnNonGroup, - LandGardening = 34359738368, - ObjectDeed = 68719476736, - ObjectManipulate = 274877906944, - ObjectSetSale = 549755813888, - AccountingAccountable = 1099511627776, - NoticesSend = 4398046511104, - NoticesReceive = 8796093022208, - ProposalStart = 17592186044416, - ProposalVote = 35184372088832 + /// Can vote on group proposals + VoteOnProposal = 1 << 45, + /// Can return group owned objects + ReturnGroupOwned = 1 << 48 } #endregion Enums diff --git a/Programs/examples/TestClient/Commands/Communication/IMGroupCommand.cs b/Programs/examples/TestClient/Commands/Communication/IMGroupCommand.cs index 58ae71a7..624a6da2 100644 --- a/Programs/examples/TestClient/Commands/Communication/IMGroupCommand.cs +++ b/Programs/examples/TestClient/Commands/Communication/IMGroupCommand.cs @@ -33,7 +33,7 @@ namespace OpenMetaverse.TestClient message = message.TrimEnd(); if (message.Length > 1023) message = message.Remove(1023); - Client.Self.OnGroupChatJoin += new AgentManager.GroupChatJoined(Self_OnGroupChatJoin); + Client.Self.OnGroupChatJoin += new AgentManager.GroupChatJoinedCallback(Self_OnGroupChatJoin); if (!Client.Self.GroupChatSessions.ContainsKey(ToGroupID)) { WaitForSessionStart.Reset(); @@ -44,7 +44,7 @@ namespace OpenMetaverse.TestClient WaitForSessionStart.Set(); } - if (WaitForSessionStart.WaitOne(10000, false)) + if (WaitForSessionStart.WaitOne(20000, false)) { Client.Self.InstantMessageGroup(ToGroupID, message); } @@ -53,7 +53,7 @@ namespace OpenMetaverse.TestClient return "Timeout waiting for group session start"; } - Client.Self.OnGroupChatJoin -= new AgentManager.GroupChatJoined(Self_OnGroupChatJoin); + Client.Self.OnGroupChatJoin -= new AgentManager.GroupChatJoinedCallback(Self_OnGroupChatJoin); return "Instant Messaged group " + ToGroupID.ToString() + " with message: " + message; } else @@ -62,11 +62,11 @@ namespace OpenMetaverse.TestClient } } - void Self_OnGroupChatJoin(UUID groupChatSessionID, UUID tmpSessionID, bool success) + void Self_OnGroupChatJoin(UUID groupChatSessionID, string sessionName, UUID tmpSessionID, bool success) { if (success) { - Console.WriteLine("Join Group Chat Success!"); + Console.WriteLine("Joined {0} Group Chat Success!", sessionName); WaitForSessionStart.Set(); } else