diff --git a/SLProxy/SLProxy.cs b/SLProxy/SLProxy.cs index b2a6ab82..1087d965 100644 --- a/SLProxy/SLProxy.cs +++ b/SLProxy/SLProxy.cs @@ -458,10 +458,12 @@ namespace SLProxy NetworkStream netStream = new NetworkStream(client); HandyNetReader reader = new HandyNetReader(netStream); - string line; int reqNo; + string line = null; + int reqNo; int contentLength = 0; Match match; - string uri; string meth; + string uri; + string meth; Dictionary headers = new Dictionary(); lock (this) @@ -469,7 +471,8 @@ namespace SLProxy capsReqCount++; reqNo = capsReqCount; } - line = Encoding.UTF8.GetString(reader.ReadLine()).Replace("\r", ""); + byte[] byteLine = reader.ReadLine(); + if (byteLine != null) line = Encoding.UTF8.GetString(byteLine).Replace("\r", ""); if (line == null) throw new Exception("EOF in client HTTP header"); diff --git a/libsecondlife/AssetManager.cs b/libsecondlife/AssetManager.cs index 2b362039..598b78eb 100644 --- a/libsecondlife/AssetManager.cs +++ b/libsecondlife/AssetManager.cs @@ -29,7 +29,7 @@ namespace libsecondlife Clothing = 5, /// Primitive that can contain textures, sounds, /// scripts and more - Object = 6, + Primitive = 6, /// Notecard asset Notecard = 7, /// Holds a collection of inventory items @@ -667,8 +667,8 @@ namespace libsecondlife asset = new AssetTexture(); break; */ - case AssetType.Object: - asset = new AssetObject(); + case AssetType.Primitive: + asset = new AssetPrim(); break; default: Client.Log("Unimplemented asset type: " + download.AssetType, Helpers.LogLevel.Error); diff --git a/libsecondlife/AssetTypes.cs b/libsecondlife/AssetTypes.cs index eb305dbf..68b77a98 100644 --- a/libsecondlife/AssetTypes.cs +++ b/libsecondlife/AssetTypes.cs @@ -146,13 +146,39 @@ namespace libsecondlife } */ - public class AssetObject : Asset + public class AssetPrim : Asset { - public override AssetType AssetType { get { return AssetType.Object; } } + public override AssetType AssetType { get { return AssetType.Primitive; } } - public AssetObject() { } + public AssetPrim() { } public override void Encode() { } public override void Decode() { } } + + public class AssetSound : Asset + { + public override AssetType AssetType { get { return AssetType.Sound; } } + + public AssetSound() { } + + // TODO: Sometime we could add OGG encoding/decoding? + public override void Encode() { } + public override void Decode() { } + } + + public class AssetClothing : Asset + { + public override AssetType AssetType { get { return AssetType.Clothing; } } + + public AssetClothing() { } + + public override void Encode() + { + } + + public override void Decode() + { + } + } } diff --git a/libsecondlife/GroupManager.cs b/libsecondlife/GroupManager.cs index c82012a0..e10a92aa 100644 --- a/libsecondlife/GroupManager.cs +++ b/libsecondlife/GroupManager.cs @@ -452,6 +452,30 @@ namespace libsecondlife /// /// public delegate void GroupAccountTransactionsCallback(GroupAccountTransactions transactions); + /// + /// + /// + /// + /// + /// + public delegate void GroupCreatedCallback(LLUUID groupID, bool success, string message); + /// + /// + /// + /// + /// + public delegate void GroupJoinedCallback(LLUUID groupID, bool success); + /// + /// + /// + /// + /// + public delegate void GroupLeftCallback(LLUUID groupID, bool success); + /// + /// + /// + /// + public delegate void GroupDroppedCallback(LLUUID groupID); #endregion Delegates @@ -474,7 +498,13 @@ namespace libsecondlife /// public event GroupAccountDetailsCallback OnGroupAccountDetails; /// - //public event GroupAccountTransactionsCallback OnGroupAccountTransactions; + public event GroupCreatedCallback OnGroupCreated; + /// + public event GroupJoinedCallback OnGroupJoined; + /// + public event GroupLeftCallback OnGroupLeft; + /// + public event GroupDroppedCallback OnGroupDropped; #endregion Events @@ -501,6 +531,7 @@ namespace libsecondlife GroupRolesMembersCaches = new Dictionary>>(); Client.Network.RegisterCallback(PacketType.AgentGroupDataUpdate, new NetworkManager.PacketCallback(GroupDataHandler)); + Client.Network.RegisterCallback(PacketType.AgentDropGroup, new NetworkManager.PacketCallback(AgentDropGroupHandler)); Client.Network.RegisterCallback(PacketType.GroupTitlesReply, new NetworkManager.PacketCallback(GroupTitlesHandler)); Client.Network.RegisterCallback(PacketType.GroupProfileReply, new NetworkManager.PacketCallback(GroupProfileHandler)); Client.Network.RegisterCallback(PacketType.GroupMembersReply, new NetworkManager.PacketCallback(GroupMembersHandler)); @@ -511,12 +542,15 @@ namespace libsecondlife Client.Network.RegisterCallback(PacketType.GroupAccountSummaryReply, new NetworkManager.PacketCallback(GroupAccountSummaryHandler)); Client.Network.RegisterCallback(PacketType.GroupAccountDetailsReply, new NetworkManager.PacketCallback(GroupAccountDetailsHandler)); Client.Network.RegisterCallback(PacketType.GroupAccountTransactionsReply, new NetworkManager.PacketCallback(GroupAccountTransactionsHandler)); + Client.Network.RegisterCallback(PacketType.CreateGroupReply, new NetworkManager.PacketCallback(CreateGroupReplyHandler)); + Client.Network.RegisterCallback(PacketType.JoinGroupReply, new NetworkManager.PacketCallback(JoinGroupReplyHandler)); + Client.Network.RegisterCallback(PacketType.LeaveGroupReply, new NetworkManager.PacketCallback(LeaveGroupReplyHandler)); } /// /// /// - public void BeginGetCurrentGroups() + public void RequestCurrentGroups() { AgentDataUpdateRequestPacket request = new AgentDataUpdateRequestPacket(); @@ -530,7 +564,7 @@ namespace libsecondlife /// /// /// - public void BeginGetGroupProfile(LLUUID group) + public void RequestGroupProfile(LLUUID group) { GroupProfileRequestPacket request = new GroupProfileRequestPacket(); @@ -545,7 +579,7 @@ namespace libsecondlife /// /// /// - public void BeginGetGroupMembers(LLUUID group) + public void RequestGroupMembers(LLUUID group) { LLUUID requestID = LLUUID.Random(); lock (GroupMembersCaches) GroupMembersCaches[requestID] = new Dictionary(); @@ -564,7 +598,7 @@ namespace libsecondlife /// /// /// - public void BeginGetGroupRoles(LLUUID group) + public void RequestGroupRoles(LLUUID group) { LLUUID requestID = LLUUID.Random(); lock (GroupRolesCaches) GroupRolesCaches[requestID] = new Dictionary(); @@ -583,7 +617,7 @@ namespace libsecondlife /// /// /// - public void BeginGetGroupRoleMembers(LLUUID group) + public void RequestGroupRoleMembers(LLUUID group) { LLUUID requestID = LLUUID.Random(); lock (GroupRolesMembersCaches) @@ -603,7 +637,7 @@ namespace libsecondlife /// /// /// - public void BeginGetGroupTitles(LLUUID group) + public void RequestGroupTitles(LLUUID group) { LLUUID requestID = LLUUID.Random(); @@ -623,7 +657,7 @@ namespace libsecondlife /// The group's ID /// How long of an interval /// Which interval (0 for current, 1 for last) - public void BeginGetGroupAccountSummary(LLUUID group, int intervalDays, int currentInterval) + public void RequestGroupAccountSummary(LLUUID group, int intervalDays, int currentInterval) { GroupAccountSummaryRequestPacket p = new GroupAccountSummaryRequestPacket(); p.AgentData.AgentID = Client.Network.AgentID; @@ -638,34 +672,99 @@ namespace libsecondlife /// /// Invites a user to a group /// - /// The group to invite to. + /// The group to invite to /// A list of roles to invite a person to /// Key of person to invite public void Invite(LLUUID group, List roles, LLUUID personkey) { - libsecondlife.Packets.InviteGroupRequestPacket igp = new libsecondlife.Packets.InviteGroupRequestPacket(); - igp.AgentData = new libsecondlife.Packets.InviteGroupRequestPacket.AgentDataBlock(); + InviteGroupRequestPacket igp = new InviteGroupRequestPacket(); + + igp.AgentData = new InviteGroupRequestPacket.AgentDataBlock(); igp.AgentData.AgentID = Client.Network.AgentID; igp.AgentData.SessionID = Client.Network.SessionID; - igp.GroupData = new libsecondlife.Packets.InviteGroupRequestPacket.GroupDataBlock(); + + igp.GroupData = new InviteGroupRequestPacket.GroupDataBlock(); igp.GroupData.GroupID = group; - List idbs = new List(); - foreach (LLUUID role in roles) + + igp.InviteData = new InviteGroupRequestPacket.InviteDataBlock[roles.Count]; + + for (int i = 0; i < roles.Count; i++) { - libsecondlife.Packets.InviteGroupRequestPacket.InviteDataBlock idb = new libsecondlife.Packets.InviteGroupRequestPacket.InviteDataBlock(); - idb.InviteeID = personkey; - idb.RoleID = role; - idbs.Add(idb); + igp.InviteData[i] = new InviteGroupRequestPacket.InviteDataBlock(); + igp.InviteData[i].InviteeID = personkey; + igp.InviteData[i].RoleID = roles[i]; } - igp.InviteData = idbs.ToArray(); + Client.Network.SendPacket(igp); } /// - /// Create a new group. This method automaticaly deducts the group creation feild + /// Set a group as the current active group + /// + /// + public void ActivateGroup(LLUUID id) + { + ActivateGroupPacket activate = new ActivateGroupPacket(); + activate.AgentData.AgentID = Client.Network.AgentID; + activate.AgentData.SessionID = Client.Network.SessionID; + activate.AgentData.GroupID = id; + + Client.Network.SendPacket(activate); + } + + /// + /// Change the role that determines your active title + /// + /// Group to use + /// Role to change to + public void ActivateTitle(LLUUID group, LLUUID role) + { + GroupTitleUpdatePacket gtu = new GroupTitleUpdatePacket(); + gtu.AgentData.AgentID = Client.Network.AgentID; + gtu.AgentData.SessionID = Client.Network.SessionID; + gtu.AgentData.TitleRoleID = role; + gtu.AgentData.GroupID = group; + + Client.Network.SendPacket(gtu); + } + + /// + /// Set this avatar's tier contribution + /// + /// Group to change tier in + /// amount of tier to donate + public void SetGroupContribution(LLUUID group, int contribution) + { + SetGroupContributionPacket sgp = new SetGroupContributionPacket(); + sgp.AgentData.AgentID = Client.Network.AgentID; + sgp.AgentData.SessionID = Client.Network.SessionID; + sgp.Data.GroupID = group; + sgp.Data.Contribution = contribution; + + Client.Network.SendPacket(sgp); + } + + /// + /// Request to join a group + /// + /// Group ID to join + public void RequestJoinGroup(LLUUID id) + { + JoinGroupRequestPacket join = new JoinGroupRequestPacket(); + join.AgentData.AgentID = Client.Network.AgentID; + join.AgentData.SessionID = Client.Network.SessionID; + + join.GroupData.GroupID = id; + + Client.Network.SendPacket(join); + } + + /// + /// Request to create a new group. If the group is successfully + /// created, L$100 will automatically be deducted /// /// Group struct containing the new group info - public void CreateGroup(Group group) + public void RequestCreateGroup(Group group) { libsecondlife.Packets.CreateGroupRequestPacket cgrp = new CreateGroupRequestPacket(); //Fill in agent data @@ -876,6 +975,15 @@ namespace libsecondlife } } + private void AgentDropGroupHandler(Packet packet, Simulator simulator) + { + if (OnGroupDropped != null) + { + try { OnGroupDropped(((AgentDropGroupPacket)packet).AgentData.GroupID); } + catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } + } + } + private void GroupProfileHandler(Packet packet, Simulator simulator) { if (OnGroupProfile != null) @@ -1111,19 +1219,44 @@ namespace libsecondlife private void GroupAccountTransactionsHandler(Packet packet, Simulator simulator) { - //GroupAccountTransactionsReplyPacket transactions = (GroupAccountTransactionsReplyPacket)packet; + GroupAccountTransactionsReplyPacket reply = (GroupAccountTransactionsReplyPacket)packet; - // TODO: This one is slightly different than the previous two + Client.Log("Got a GroupAccountTransactionsReply packet, implement this callback!" + Environment.NewLine + + reply.ToString(), Helpers.LogLevel.Error); + } - //if (GroupAccountTransactionsCallbacks.ContainsKey(transactions.AgentData.GroupID)) - //{ - // GroupAccountTransactions account = new GroupAccountTransactions(); + private void CreateGroupReplyHandler(Packet packet, Simulator simulator) + { + if (OnGroupCreated != null) + { + CreateGroupReplyPacket reply = (CreateGroupReplyPacket)packet; - // ; + string message = Helpers.FieldToUTF8String(reply.ReplyData.Message); - // try { OnGroupAccountTransactions(account); } - // catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } - //} + try { OnGroupCreated(reply.ReplyData.GroupID, reply.ReplyData.Success, message); } + catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } + } + } + + private void JoinGroupReplyHandler(Packet packet, Simulator simulator) + { + if (OnGroupJoined != null) + { + JoinGroupReplyPacket reply = (JoinGroupReplyPacket)packet; + + try { OnGroupJoined(reply.GroupData.GroupID, reply.GroupData.Success); } + catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } + } + } + + private void LeaveGroupReplyHandler(Packet packet, Simulator simulator) + { + if (OnGroupLeft != null) + { + LeaveGroupReplyPacket reply = (LeaveGroupReplyPacket)packet; + + OnGroupLeft(reply.GroupData.GroupID, reply.GroupData.Success); + } } #endregion Packet Handlers diff --git a/libsecondlife/Login.cs b/libsecondlife/Login.cs index db6e112b..cf84fa2d 100644 --- a/libsecondlife/Login.cs +++ b/libsecondlife/Login.cs @@ -609,8 +609,8 @@ namespace libsecondlife { // Self Client.Self.ID = reply.agent_id; - Client.Self.FirstName = reply.first_name; - Client.Self.LastName = reply.last_name; + Client.Self.firstName = reply.first_name; + Client.Self.lastName = reply.last_name; Client.Self.StartLocation = reply.start_location; Client.Self.AgentAccess = reply.agent_access; ArrayList look_at = (ArrayList)LLSD.ParseTerseLLSD(reply.look_at); diff --git a/libsecondlife/MainAvatar.cs b/libsecondlife/MainAvatar.cs index 9308cce3..16c239ae 100644 --- a/libsecondlife/MainAvatar.cs +++ b/libsecondlife/MainAvatar.cs @@ -42,81 +42,6 @@ namespace libsecondlife { #region Enums - /// - /// Used to specify movement actions for your agent - /// - [Flags] - public enum ControlFlags - { - /// Empty flag - NONE = 0, - /// Move Forward (SL Keybinding: W/Up Arrow) - AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX, - /// Move Backward (SL Keybinding: S/Down Arrow) - AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX, - /// Move Left (SL Keybinding: Shift-(A/Left Arrow)) - AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX, - /// Move Right (SL Keybinding: Shift-(D/Right Arrow)) - AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX, - /// Not Flying: Jump/Flying: Move Up (SL Keybinding: E) - AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX, - /// Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) - AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX, - /// Unused - AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX, - /// Unused - AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX, - /// Unused - AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX, - /// Unused - AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX, - /// ORed with AGENT_CONTROL_AT_* if the keyboard is being used - AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX, - /// ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used - AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX, - /// ORed with AGENT_CONTROL_UP_* if the keyboard is being used - AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX, - /// Fly - AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX, - /// - AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX, - /// Finish our current animation - AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX, - /// Stand up from the ground or a prim seat - AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX, - /// Sit on the ground at our current location - AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX, - /// Whether mouselook is currently enabled - AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX, - /// Legacy, used if a key was pressed for less than a certain amount of time - AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX, - /// - AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX, - /// - AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX, - /// Set when the avatar is idled or set to away. Note that the away animation is - /// activated separately from setting this flag - AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX, - /// - AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX, - /// - AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX, - /// - AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX, - /// - AGENT_CONTROL_ML_LBUTTON_UP = 0x1 << CONTROL_ML_LBUTTON_UP_INDEX - } - /// /// Currently only used to hide your group title /// @@ -606,10 +531,15 @@ namespace libsecondlife public delegate void GroupDroppedCallback(LLUUID groupID); /// - /// Informs the avatar that the active group has changed + /// /// - /// The group that is now the active group - public delegate void ActiveGroupChangedCallback(LLUUID groupID); + /// + /// + /// + /// + /// + /// + public delegate void AgentDataCallback(string firstName, string lastName, LLUUID activeGroupID, string groupTitle, ulong groupPowers, string groupName); /// Callback for incoming chat packets @@ -626,27 +556,23 @@ namespace libsecondlife public event BalanceCallback OnBalanceUpdated; /// Callback for incoming Money Balance Replies public event MoneyBalanceReplyCallback OnMoneyBalanceReplyReceived; - /// Callback reply for an attempt to join a group - public event JoinGroupCallback OnJoinGroup; - /// Callback reply for an attempt to leave a group - public event LeaveGroupCallback OnLeaveGroup; - /// Callback for informing the avatar that it is no longer a member of a group - public event GroupDroppedCallback OnGroupDropped; - /// Callback reply for the current group changing - public event ActiveGroupChangedCallback OnActiveGroupChanged; + /// Callback reply for agent data updates, such as the active + /// group changing + public event AgentDataCallback OnAgentDataUpdated; #endregion #region Public Members + /// Reference to the SecondLife client object + public SecondLife Client; + + // FIXME: Most all of these should change from public variables to read-only public properties + /// Your (client) avatar UUID public LLUUID ID = LLUUID.Zero; /// Your (client) avatar ID, local to the current region/sim public uint LocalID = 0; - /// Avatar First Name (i.e. Philip) - public string FirstName = String.Empty; - /// Avatar Last Name (i.e. Linden) - public string LastName = String.Empty; /// Where the avatar started at login. Can be "last", "home" /// or a login URI public string StartLocation = String.Empty; @@ -691,6 +617,10 @@ namespace libsecondlife /// The UUID of your root inventory folder public LLUUID InventoryRootFolderUUID = LLUUID.Zero; + /// Avatar First Name (i.e. Philip) + public string FirstName { get { return firstName; } } + /// Avatar Last Name (i.e. Linden) + public string LastName { get { return lastName; } } /// Gets the health of the agent public float Health { get { return health; } } /// Gets the current balance of the agent @@ -705,11 +635,12 @@ namespace libsecondlife #endregion Public Members + internal string firstName = String.Empty; + internal string lastName = String.Empty; internal string teleportMessage = String.Empty; internal uint sittingOn = 0; internal DateTime lastInterpolation; - private SecondLife Client; private TeleportStatus TeleportStat = TeleportStatus.None; private ManualResetEvent TeleportEvent = new ManualResetEvent(false); private uint HeightWidthGenCounter = 0; @@ -797,11 +728,6 @@ namespace libsecondlife callback = new NetworkManager.PacketCallback(BalanceHandler); Client.Network.RegisterCallback(PacketType.MoneyBalanceReply, callback); - // Group callbacks - Client.Network.RegisterCallback(PacketType.JoinGroupReply, new NetworkManager.PacketCallback(JoinGroupHandler)); - Client.Network.RegisterCallback(PacketType.LeaveGroupReply, new NetworkManager.PacketCallback(LeaveGroupHandler)); - Client.Network.RegisterCallback(PacketType.AgentDropGroup, new NetworkManager.PacketCallback(DropGroupHandler)); - //Agent Update Callback Client.Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler)); @@ -1414,6 +1340,26 @@ namespace libsecondlife Client.Network.SendPacket(animate); } + public void AutoPilot(double globalX, double globalY, double z) + { + GenericMessagePacket autopilot = new GenericMessagePacket(); + + autopilot.AgentData.AgentID = Client.Network.AgentID; + autopilot.AgentData.SessionID = Client.Network.SessionID; + autopilot.AgentData.TransactionID = LLUUID.Zero; + autopilot.MethodData.Invoice = LLUUID.Zero; + autopilot.MethodData.Method = Helpers.StringToField("autopilot"); + autopilot.ParamList = new GenericMessagePacket.ParamListBlock[3]; + autopilot.ParamList[0] = new GenericMessagePacket.ParamListBlock(); + autopilot.ParamList[0].Parameter = Helpers.StringToField(globalX.ToString()); + autopilot.ParamList[1] = new GenericMessagePacket.ParamListBlock(); + autopilot.ParamList[1].Parameter = Helpers.StringToField(globalY.ToString()); + autopilot.ParamList[2] = new GenericMessagePacket.ParamListBlock(); + autopilot.ParamList[2].Parameter = Helpers.StringToField(z.ToString()); + + Client.Network.SendPacket(autopilot); + } + /// /// Use the autopilot sim function to move the avatar to a new position /// @@ -1421,7 +1367,6 @@ namespace libsecondlife /// Integer value for the global X coordinate to move to /// Integer value for the global Y coordinate to move to /// Floating-point value for the Z coordinate to move to - /// AutoPilot(252620, 247078, 20.2674); public void AutoPilot(ulong globalX, ulong globalY, float z) { GenericMessagePacket autopilot = new GenericMessagePacket(); @@ -1437,8 +1382,7 @@ namespace libsecondlife autopilot.ParamList[1] = new GenericMessagePacket.ParamListBlock(); autopilot.ParamList[1].Parameter = Helpers.StringToField(globalY.ToString()); autopilot.ParamList[2] = new GenericMessagePacket.ParamListBlock(); - // TODO: Do we need to prevent z coordinates from being sent in 1.4827e-18 notation? - autopilot.ParamList[2].Parameter = Helpers.StringToField(z.ToString()); + autopilot.ParamList[2].Parameter = Helpers.StringToField(z.ToString("{0:00.0000}")); Client.Network.SendPacket(autopilot); } @@ -1822,36 +1766,6 @@ namespace libsecondlife Client.Network.SendPacket(move, simulator); } - /// - /// Set this avatar's tier contribution - /// - /// Group to change tier in - /// amount of tier to donate - public void SetGroupContribution(LLUUID group, int contribution) - { - libsecondlife.Packets.SetGroupContributionPacket sgp = new SetGroupContributionPacket(); - sgp.AgentData.AgentID = Client.Network.AgentID; - sgp.AgentData.SessionID = Client.Network.SessionID; - sgp.Data.GroupID = group; - sgp.Data.Contribution = contribution; - Client.Network.SendPacket(sgp); - } - - /// - /// Change the role that determines your active title - /// - /// Group to use - /// Role to change to - public void ChangeTitle(LLUUID group, LLUUID role) - { - libsecondlife.Packets.GroupTitleUpdatePacket gtu = new GroupTitleUpdatePacket(); - gtu.AgentData.AgentID = Client.Network.AgentID; - gtu.AgentData.SessionID = Client.Network.SessionID; - gtu.AgentData.TitleRoleID = role; - gtu.AgentData.GroupID = group; - Client.Network.SendPacket(gtu); - } - /// /// Sends camera and action updates to the server including the /// position and orientation of our camera, and a ControlFlags field @@ -2043,44 +1957,31 @@ namespace libsecondlife health = ((HealthMessagePacket)packet).HealthData.Health; } - private void JoinGroupHandler(Packet packet, Simulator simulator) - { - if (OnJoinGroup != null) - { - JoinGroupReplyPacket reply = (JoinGroupReplyPacket)packet; - - OnJoinGroup(reply.GroupData.GroupID, reply.GroupData.Success); - } - } - - private void LeaveGroupHandler(Packet packet, Simulator simulator) - { - if (OnLeaveGroup != null) - { - LeaveGroupReplyPacket reply = (LeaveGroupReplyPacket)packet; - - OnLeaveGroup(reply.GroupData.GroupID, reply.GroupData.Success); - } - } + public void AgentDataUpdateHandler(Packet packet, Simulator simulator) { AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet; - if (p.AgentData.AgentID == simulator.Client.Network.AgentID) { - if (activeGroup != p.AgentData.ActiveGroupID) + + if (p.AgentData.AgentID == simulator.Client.Network.AgentID) + { + firstName = Helpers.FieldToUTF8String(p.AgentData.FirstName); + lastName = Helpers.FieldToUTF8String(p.AgentData.LastName); + activeGroup = p.AgentData.ActiveGroupID; + + if (OnAgentDataUpdated != null) { - activeGroup = p.AgentData.ActiveGroupID; - if (OnActiveGroupChanged != null) - OnActiveGroupChanged(activeGroup); + string groupTitle = Helpers.FieldToUTF8String(p.AgentData.GroupTitle); + string groupName = Helpers.FieldToUTF8String(p.AgentData.GroupName); + + try { OnAgentDataUpdated(firstName, lastName, activeGroup, groupTitle, p.AgentData.GroupPowers, groupName); } + catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } } - } - - private void DropGroupHandler(Packet packet, Simulator simulator) - { - if (OnGroupDropped != null) + else { - OnGroupDropped(((AgentDropGroupPacket)packet).AgentData.GroupID); + Client.Log("Got an AgentDataUpdate packet for avatar " + p.AgentData.AgentID.ToStringHyphenated() + + " instead of " + Client.Network.AgentID.ToStringHyphenated() + ", this shouldn't happen", Helpers.LogLevel.Error); } } diff --git a/libsecondlife/MainAvatarStatus.cs b/libsecondlife/MainAvatarStatus.cs index 57ed42c7..c5a01c5b 100644 --- a/libsecondlife/MainAvatarStatus.cs +++ b/libsecondlife/MainAvatarStatus.cs @@ -33,6 +33,85 @@ namespace libsecondlife { public partial class MainAvatar { + #region Enums + + /// + /// Used to specify movement actions for your agent + /// + [Flags] + public enum ControlFlags + { + /// Empty flag + NONE = 0, + /// Move Forward (SL Keybinding: W/Up Arrow) + AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX, + /// Move Backward (SL Keybinding: S/Down Arrow) + AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX, + /// Move Left (SL Keybinding: Shift-(A/Left Arrow)) + AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX, + /// Move Right (SL Keybinding: Shift-(D/Right Arrow)) + AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX, + /// Not Flying: Jump/Flying: Move Up (SL Keybinding: E) + AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX, + /// Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) + AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX, + /// Unused + AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX, + /// Unused + AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX, + /// Unused + AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX, + /// Unused + AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX, + /// ORed with AGENT_CONTROL_AT_* if the keyboard is being used + AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX, + /// ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used + AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX, + /// ORed with AGENT_CONTROL_UP_* if the keyboard is being used + AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX, + /// Fly + AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX, + /// + AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX, + /// Finish our current animation + AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX, + /// Stand up from the ground or a prim seat + AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX, + /// Sit on the ground at our current location + AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX, + /// Whether mouselook is currently enabled + AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX, + /// Legacy, used if a key was pressed for less than a certain amount of time + AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX, + /// + AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX, + /// + AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX, + /// Set when the avatar is idled or set to away. Note that the away animation is + /// activated separately from setting this flag + AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX, + /// + AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX, + /// + AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX, + /// + AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX, + /// + AGENT_CONTROL_ML_LBUTTON_UP = 0x1 << CONTROL_ML_LBUTTON_UP_INDEX + } + + #endregion Enums + /// /// Holds current camera and control key status /// @@ -302,8 +381,7 @@ namespace libsecondlife #endregion Properties - /// Timer for sending AgentUpdate packets, disabled by - /// default + /// Timer for sending AgentUpdate packets public Timer UpdateTimer; /// Holds camera flags public CameraStatus Camera; @@ -336,7 +414,7 @@ namespace libsecondlife UpdateTimer = new Timer(Settings.AGENT_UPDATE_INTERVAL); UpdateTimer.Elapsed += new ElapsedEventHandler(UpdateTimer_Elapsed); - UpdateTimer.Enabled = Client.Settings.SEND_AGENT_UPDATES; + UpdateTimer.Start(); } /// @@ -407,7 +485,7 @@ namespace libsecondlife duplicateCount = 0; } - if (duplicateCount < 2) + if (Client.Settings.CONTINUOUS_AGENT_UPDATES || duplicateCount < 10) { // Store the current state to do duplicate checking in the future Camera.LastHeadRotation = Camera.HeadRotation; @@ -453,7 +531,7 @@ namespace libsecondlife private void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e) { - if (Client.Network.Connected) + if (Client.Network.Connected && Client.Settings.SEND_AGENT_UPDATES) { //Send an AgentUpdate packet SendUpdate(); diff --git a/libsecondlife/Settings.cs b/libsecondlife/Settings.cs index a925213a..473eae83 100644 --- a/libsecondlife/Settings.cs +++ b/libsecondlife/Settings.cs @@ -157,6 +157,10 @@ namespace libsecondlife /// If true, any reference received for a folder or item /// libsecondlife is not aware of will automatically be fetched. public bool FETCH_MISSING_INVENTORY = true; + /// If true, and SEND_AGENT_UPDATES is true, + /// AgentUpdate packets will continuously be sent out to give the bot + /// smoother movement and autopiloting + public bool CONTINUOUS_AGENT_UPDATES = true; /// Cost of uploading an asset /// Read-only since this value is dynamically fetched at login diff --git a/libsecondlife/SoundManager.cs b/libsecondlife/SoundManager.cs index 753c2335..feb9faf4 100644 --- a/libsecondlife/SoundManager.cs +++ b/libsecondlife/SoundManager.cs @@ -38,14 +38,20 @@ namespace libsecondlife { Client = client; - Client.Network.RegisterCallback(PacketType.AttachedSound, new NetworkManager.PacketCallback(AttachedSoundHandler)); + Client.Network.RegisterCallback(PacketType.AttachedSound, new NetworkManager.PacketCallback(AttachedSoundHandler)); + Client.Network.RegisterCallback(PacketType.AttachedSoundGainChange, new NetworkManager.PacketCallback(AttachedSoundGainChangeHandler)); Client.Network.RegisterCallback(PacketType.PreloadSound, new NetworkManager.PacketCallback(PreloadSoundHandler)); - Client.Network.RegisterCallback(PacketType.SoundTrigger, new NetworkManager.PacketCallback(SoundTriggerHandler)); + Client.Network.RegisterCallback(PacketType.SoundTrigger, new NetworkManager.PacketCallback(SoundTriggerHandler)); } protected void AttachedSoundHandler(Packet packet, Simulator simulator) { //FIXME + } + + protected void AttachedSoundGainChangeHandler(Packet packet, Simulator simulator) + { + //FIXME } protected void PreloadSoundHandler(Packet packet, Simulator simulator) diff --git a/libsecondlife/examples/TestClient/Commands/Inventory/AppearanceCommand.cs b/libsecondlife/examples/TestClient/Commands/Inventory/AppearanceCommand.cs index 0b96a3ff..b1e10bd0 100644 --- a/libsecondlife/examples/TestClient/Commands/Inventory/AppearanceCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Inventory/AppearanceCommand.cs @@ -16,7 +16,7 @@ namespace libsecondlife.TestClient public override string Execute(string[] args, LLUUID fromAgentID) { - Client.NewAppearanceManager.SetPreviousAppearance(); + Client.Appearance.SetPreviousAppearance(); return "Done."; } } diff --git a/libsecondlife/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs b/libsecondlife/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs index d3a5059e..18c71f68 100644 --- a/libsecondlife/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Inventory/DumpOutfitCommand.cs @@ -37,7 +37,7 @@ namespace libsecondlife.TestClient StringBuilder output = new StringBuilder("Downloading "); lock (OutfitAssets) OutfitAssets.Clear(); - Client.NewAssetManager.OnImageReceived += ImageReceivedHandler; + Client.Assets.OnImageReceived += ImageReceivedHandler; foreach (KeyValuePair face in avatar.Textures.FaceTextures) { @@ -55,7 +55,7 @@ namespace libsecondlife.TestClient } OutfitAssets.Add(face.Value.TextureID); - Client.NewAssetManager.RequestImage(face.Value.TextureID, type, 100000.0f, 0); + Client.Assets.RequestImage(face.Value.TextureID, type, 100000.0f, 0); output.Append(((AppearanceManager.TextureIndex)face.Key).ToString()); output.Append(" "); @@ -99,7 +99,7 @@ namespace libsecondlife.TestClient OutfitAssets.Remove(image.ID); if (OutfitAssets.Count == 0) - Client.NewAssetManager.OnImageReceived -= ImageReceivedHandler; + Client.Assets.OnImageReceived -= ImageReceivedHandler; } } } diff --git a/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs b/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs index f5074a34..fa0dd8ef 100644 --- a/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs @@ -12,6 +12,8 @@ namespace libsecondlife.TestClient { Name = "follow"; Description = "Follow another avatar. (usage: follow [FirstName LastName]) If no target is set then will follow master."; + + testClient.Network.RegisterCallback(PacketType.AlertMessage, new NetworkManager.PacketCallback(AlertMessageHandler)); } public override string Execute(string[] args, LLUUID fromAgentID) @@ -38,7 +40,7 @@ namespace libsecondlife.TestClient } const float DISTANCE_BUFFER = 3.0f; - Avatar followAvatar; + uint targetLocalID = 0; bool Follow(string name) { @@ -46,11 +48,13 @@ namespace libsecondlife.TestClient { if (av.Name == name) { - followAvatar = av; + targetLocalID = av.LocalID; Active = true; return true; } } + + Active = false; return false; } @@ -60,31 +64,57 @@ namespace libsecondlife.TestClient { if (av.ID == id) { - followAvatar = av; + targetLocalID = av.LocalID; Active = true; return true; } } + + Active = false; return false; } public override void Think() { - if (Helpers.VecDist(followAvatar.Position, Client.Self.Position) > DISTANCE_BUFFER) + // Find the target position + if (Client.Network.CurrentSim != null && Client.AvatarList.ContainsKey(targetLocalID)) { - //move toward target - LLVector3 avPos = followAvatar.Position; - Client.Self.AutoPilot((ulong)avPos.X + (ulong)Client.regionX, (ulong)avPos.Y + (ulong)Client.regionY, avPos.Z); - } - //else - //{ - // //stop at current position - // LLVector3 myPos = client.Self.Position; - // client.Self.AutoPilot((ulong)myPos.x, (ulong)myPos.y, myPos.Z); - //} + Avatar targetAv = Client.AvatarList[targetLocalID]; + float distance = Helpers.VecDist(targetAv.Position, Client.Self.Position); + + if (distance > DISTANCE_BUFFER) + { + uint regionX, regionY; + Helpers.LongToUInts(Client.Network.CurrentSim.Handle, out regionX, out regionY); + + double xTarget = (double)targetAv.Position.X + (double)regionX; + double yTarget = (double)targetAv.Position.Y + (double)regionY; + double zTarget = targetAv.Position.Z - 2f; + + Client.DebugLog(String.Format("[Autopilot] {0} meters away from the target, starting autopilot to <{1},{2},{3}>", + distance, xTarget, yTarget, zTarget)); + + Client.Self.AutoPilot(xTarget, yTarget, zTarget); + } + else + { + // We are in range of the target and moving, stop moving + Client.Self.AutoPilotCancel(); + } + } base.Think(); } + private void AlertMessageHandler(Packet packet, Simulator simulator) + { + AlertMessagePacket alert = (AlertMessagePacket)packet; + string message = Helpers.FieldToUTF8String(alert.AlertData.Message); + + if (message.Contains("Autopilot cancel")) + { + Client.Log("Server cancelled the autopilot", Helpers.LogLevel.Info); + } + } } } diff --git a/libsecondlife/examples/TestClient/Commands/Movement/MoveToCommand.cs b/libsecondlife/examples/TestClient/Commands/Movement/MoveToCommand.cs index 6d0a2254..e8278ff3 100644 --- a/libsecondlife/examples/TestClient/Commands/Movement/MoveToCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Movement/MoveToCommand.cs @@ -2,23 +2,33 @@ using System; using System.Collections.Generic; using System.Text; -namespace libsecondlife.TestClient.Commands.Movement { - class MovetoCommand : Command { - public MovetoCommand(TestClient client) { +namespace libsecondlife.TestClient.Commands.Movement +{ + class MovetoCommand : Command + { + public MovetoCommand(TestClient client) + { Name = "moveto"; Description = "Moves the avatar to the specified global position using simulator autopilot."; } - public override string Execute(string[] args, LLUUID fromAgentID) { + + public override string Execute(string[] args, LLUUID fromAgentID) + { if (args.Length != 3) return "usage: moveto x y z"; - float x = Client.Self.Position.X + Client.regionX; - float y = Client.Self.Position.Y + Client.regionY; + + uint regionX, regionY; + Helpers.LongToUInts(Client.Network.CurrentSim.Handle, out regionX, out regionY); + + float x = Client.Self.Position.X + (ulong)regionX; + float y = Client.Self.Position.Y + (ulong)regionY; float z = Client.Self.Position.Z; float.TryParse(args[0], out x); float.TryParse(args[1], out y); float.TryParse(args[2], out z); Client.Self.AutoPilot((ulong)x, (ulong)y, z); - return "Attempting to move to <" + x + ", " + y + ", " + z + ">"; + + return String.Format("Attempting to move to <{0},{1},{2}>", x, y, z); } } } diff --git a/libsecondlife/examples/TestClient/Commands/Movement/StandCommand.cs b/libsecondlife/examples/TestClient/Commands/Movement/StandCommand.cs index 8a005529..e79bdfb7 100644 --- a/libsecondlife/examples/TestClient/Commands/Movement/StandCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Movement/StandCommand.cs @@ -15,33 +15,9 @@ namespace libsecondlife.TestClient } public override string Execute(string[] args, LLUUID fromAgentID) - { - Client.Self.Status.StandUp = true; - stand(Client); - return "Standing up."; - } - - void stand(SecondLife client) - { - SendAgentUpdate(client, (uint)MainAvatar.ControlFlags.AGENT_CONTROL_STAND_UP); - } - - const float DRAW_DISTANCE = 96.0f; - void SendAgentUpdate(SecondLife client, uint ControlID) - { - AgentUpdatePacket p = new AgentUpdatePacket(); - p.AgentData.Far = DRAW_DISTANCE; - //LLVector3 myPos = client.Self.Position; - p.AgentData.CameraCenter = new LLVector3(0, 0, 0); - p.AgentData.CameraAtAxis = new LLVector3(0, 0, 0); - p.AgentData.CameraLeftAxis = new LLVector3(0, 0, 0); - p.AgentData.CameraUpAxis = new LLVector3(0, 0, 0); - p.AgentData.HeadRotation = new LLQuaternion(0, 0, 0, 1); ; - p.AgentData.BodyRotation = new LLQuaternion(0, 0, 0, 1); ; - p.AgentData.AgentID = client.Network.AgentID; - p.AgentData.SessionID = client.Network.SessionID; - p.AgentData.ControlFlags = ControlID; - client.Network.SendPacket(p); - } + { + Client.Self.Stand(); + return "Standing up."; + } } } diff --git a/libsecondlife/examples/TestClient/TestClient.cs b/libsecondlife/examples/TestClient/TestClient.cs index 2ba3b16b..f3e35710 100644 --- a/libsecondlife/examples/TestClient/TestClient.cs +++ b/libsecondlife/examples/TestClient/TestClient.cs @@ -23,8 +23,6 @@ namespace libsecondlife.TestClient public string MasterName = String.Empty; public LLUUID MasterKey = LLUUID.Zero; public ClientManager ClientManager; - public int regionX; - public int regionY; //internal libsecondlife.InventorySystem.InventoryFolder currentDirectory; @@ -34,10 +32,6 @@ namespace libsecondlife.TestClient private LLVector3 up = new LLVector3(0, 0, 0.9999f); private System.Timers.Timer updateTimer; - // FIXME: get rid of these when they are moved to the main lib - public AssetManager NewAssetManager; - public AppearanceManager NewAppearanceManager; - /// /// /// @@ -45,10 +39,7 @@ namespace libsecondlife.TestClient { ClientManager = manager; - NewAssetManager = new AssetManager(this); - NewAppearanceManager = new AppearanceManager(this, NewAssetManager); - - updateTimer = new System.Timers.Timer(1000); + updateTimer = new System.Timers.Timer(500); updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed); RegisterAllCommands(Assembly.GetExecutingAssembly()); @@ -56,6 +47,7 @@ namespace libsecondlife.TestClient Settings.DEBUG = true; Settings.STORE_LAND_PATCHES = true; Settings.ALWAYS_REQUEST_OBJECTS = true; + Settings.SEND_AGENT_UPDATES = true; Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler)); @@ -68,6 +60,7 @@ namespace libsecondlife.TestClient Inventory.OnInventoryObjectReceived += new InventoryManager.InventoryObjectReceived(Inventory_OnInventoryObjectReceived); Network.RegisterCallback(PacketType.AvatarAppearance, new NetworkManager.PacketCallback(AvatarAppearanceHandler)); + Network.RegisterCallback(PacketType.AlertMessage, new NetworkManager.PacketCallback(AlertMessageHandler)); updateTimer.Start(); } @@ -179,7 +172,7 @@ namespace libsecondlife.TestClient Console.WriteLine("Got the group ID for " + sim.Client.ToString() + ", requesting group members..."); GroupID = p.AgentData.ActiveGroupID; - sim.Client.Groups.BeginGetGroupMembers(GroupID); + sim.Client.Groups.RequestGroupMembers(GroupID); } } @@ -273,6 +266,13 @@ namespace libsecondlife.TestClient lock (Appearances) Appearances[appearance.Sender.ID] = appearance; } + private void AlertMessageHandler(Packet packet, Simulator simulator) + { + AlertMessagePacket message = (AlertMessagePacket)packet; + + Log("[AlertMessage] " + Helpers.FieldToUTF8String(message.AlertData.Message), Helpers.LogLevel.Info); + } + private void Self_OnInstantMessage(LLUUID fromAgentID, string fromAgentName, LLUUID toAgentID, uint parentEstateID, LLUUID regionID, LLVector3 position, MainAvatar.InstantMessageDialog dialog, bool groupIM, LLUUID imSessionID, DateTime timestamp, string message, diff --git a/libsecondlife/examples/groupmanager/frmGroupInfo.cs b/libsecondlife/examples/groupmanager/frmGroupInfo.cs index acaa2641..2a03bc8e 100644 --- a/libsecondlife/examples/groupmanager/frmGroupInfo.cs +++ b/libsecondlife/examples/groupmanager/frmGroupInfo.cs @@ -52,9 +52,9 @@ namespace groupmanager Client.Avatars.OnAvatarNames += AvatarNamesCallback; // Request the group information - Client.Groups.BeginGetGroupProfile(Group.ID); - Client.Groups.BeginGetGroupMembers(Group.ID); - Client.Groups.BeginGetGroupTitles(Group.ID); + Client.Groups.RequestGroupProfile(Group.ID); + Client.Groups.RequestGroupMembers(Group.ID); + Client.Groups.RequestGroupTitles(Group.ID); } ~frmGroupInfo() @@ -249,7 +249,17 @@ namespace groupmanager } else { - // TODO: Finish this + lock (Titles) + { + foreach (KeyValuePair kvp in Titles) + { + Console.Write("Title: " + kvp.Value.Title + " = " + kvp.Key.ToStringHyphenated()); + if (kvp.Value.Selected) + Console.WriteLine(" (Selected)"); + else + Console.WriteLine(); + } + } } } } diff --git a/libsecondlife/examples/groupmanager/frmGroupManager.cs b/libsecondlife/examples/groupmanager/frmGroupManager.cs index 66f8ad0a..a4034969 100644 --- a/libsecondlife/examples/groupmanager/frmGroupManager.cs +++ b/libsecondlife/examples/groupmanager/frmGroupManager.cs @@ -44,6 +44,7 @@ namespace groupmanager foreach (Group group in Groups.Values) { + Console.WriteLine(String.Format("Adding group {0} ({1})", group.Name, group.ID.ToStringHyphenated())); lstGroups.Items.Add(group); } } @@ -71,7 +72,7 @@ namespace groupmanager { groupBox.Enabled = true; - Client.Groups.BeginGetCurrentGroups(); + Client.Groups.RequestCurrentGroups(); } else { diff --git a/libsecondlife/libsecondlife.csproj b/libsecondlife/libsecondlife.csproj index b21e1a64..43c857e2 100644 --- a/libsecondlife/libsecondlife.csproj +++ b/libsecondlife/libsecondlife.csproj @@ -173,6 +173,6 @@ - xcopy $(ProjectDir)\Resources\*.* $(OutDir)avatar_data /i /d /y + xcopy "$(ProjectDir)\Resources\*.*" "$(OutDir)avatar_data" /i /d /y \ No newline at end of file