diff --git a/libsecondlife-cs/examples/TestTool/Command.cs b/libsecondlife-cs/examples/TestTool/Command.cs
new file mode 100644
index 00000000..6359c8a5
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Command.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public abstract class Command
+ {
+ public string Name;
+ public string Description;
+
+ public TestTool TestTool;
+
+ public SecondLife Client
+ {
+ get { return TestTool.Client; }
+ }
+
+ public abstract string Execute(string[] args, LLUUID fromAgentID);
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/BalanceCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/BalanceCommand.cs
new file mode 100644
index 00000000..9351d5b3
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/BalanceCommand.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class BalanceCommand: Command
+ {
+ public BalanceCommand()
+ {
+ Name = "balance";
+ Description = "Shows the amount of L$.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ return "L$: " + Client.Self.Balance;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/GiveAllCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/GiveAllCommand.cs
new file mode 100644
index 00000000..e5a8e0e7
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/GiveAllCommand.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class GiveAllCommand: Command
+ {
+ public GiveAllCommand()
+ {
+ Name = "giveAll";
+ Description = "Gives you all it's money.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ if (fromAgentID == null)
+ return "Unable to send money to console. This command only works when IMed.";
+
+ int amount = Client.Self.Balance;
+ Client.Self.GiveMoney(fromAgentID, Client.Self.Balance, String.Empty);
+ return "Gave $" + amount + " to " + fromAgentID;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/GotoCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/GotoCommand.cs
new file mode 100644
index 00000000..bc1afac3
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/GotoCommand.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class GotoCommand: Command
+ {
+ public GotoCommand()
+ {
+ Name = "goto";
+ Description = "Goto location. (e.g. \"goto simname/100/100/30\")";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ if (args.Length < 1)
+ return "Destination should be specified as: sim/x/y/z";
+
+ char[] seps = { '/' };
+ string[] destination = args[0].Split(seps);
+ if( destination.Length != 4 )
+ return "Destination should be specified as: sim/x/y/z";
+
+ string sim = destination[0];
+ float x = Client.Self.Position.X;
+ float y = Client.Self.Position.Y;
+ float z = Client.Self.Position.Z;
+ float.TryParse(destination[1], out x);
+ float.TryParse(destination[2], out y);
+ float.TryParse(destination[3], out z);
+
+ Client.Self.Teleport(sim, new LLVector3(x, y, z));
+
+ return "Teleported to " + sim + " {" + x + "," + y + "," + z + "}";
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/HelpCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/HelpCommand.cs
new file mode 100644
index 00000000..8cbddb99
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/HelpCommand.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class HelpCommand: Command
+ {
+ public HelpCommand()
+ {
+ Name = "help";
+ Description = "Lists available commands.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("\n\nHELP\nClient accept teleport lures from master and group members.\n");
+ foreach (Command c in TestTool.Commands.Values)
+ {
+ result.AppendFormat("{0} - {1}\n", c.Name, c.Description);
+ }
+
+ return result.ToString();
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/JumpCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/JumpCommand.cs
new file mode 100644
index 00000000..3a0d2803
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/JumpCommand.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class JumpCommand: Command
+ {
+ public JumpCommand()
+ {
+ Name = "jump";
+ Description = "Teleports to the specified height. (e.g. \"jump 1000\")";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ if (args.Length < 1)
+ return "usage: jump 1000";
+
+ float height = 0;
+ float.TryParse(args[0], out height);
+
+ Client.Self.Teleport
+ (
+ Client.Network.CurrentSim.Region.Name,
+ new LLVector3(Client.Self.Position.X, Client.Self.Position.Y, Client.Self.Position.Z + height)
+ );
+
+ return "Jumped " + height;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/LocationCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/LocationCommand.cs
new file mode 100644
index 00000000..91f29c92
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/LocationCommand.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class LocationCommand: Command
+ {
+ public LocationCommand()
+ {
+ Name = "location";
+ Description = "Show the location.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ return "CurrentSim: '" + Client.Network.CurrentSim.Region.Name + "' Position: " + Client.Self.Position.ToString();
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/PrimCountCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/PrimCountCommand.cs
new file mode 100644
index 00000000..fc370daf
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/PrimCountCommand.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class PrimCountCommand: Command
+ {
+ public PrimCountCommand()
+ {
+ Name = "primCount";
+ Description = "Shows the number of prims that have been received.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ return TestTool.Prims.Count.ToString();
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/QuitCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/QuitCommand.cs
new file mode 100644
index 00000000..a9ba0cc8
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/QuitCommand.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class QuitCommand: Command
+ {
+ public QuitCommand()
+ {
+ Name = "quit";
+ Description = "Log off";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ TestTool.Running = false;
+ Client.Network.Logout();
+ return "Logging off.";
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/SayCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/SayCommand.cs
new file mode 100644
index 00000000..98615c31
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/SayCommand.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class SayCommand: Command
+ {
+ public SayCommand()
+ {
+ Name = "say";
+ Description = "Say something.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ if (args.Length < 1)
+ return "usage: say whatever";
+
+ string message = String.Empty;
+ foreach (string s in args)
+ message += s + " ";
+
+ Client.Self.Chat(message, 0, MainAvatar.ChatType.Normal);
+
+ return "Said " + message;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/SetMasterCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/SetMasterCommand.cs
new file mode 100644
index 00000000..89200b1e
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/SetMasterCommand.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class SetMasterCommand: Command
+ {
+ public DateTime Created = DateTime.Now;
+
+ public SetMasterCommand()
+ {
+ Name = "setMaster";
+ Description = "Sets the user name of the master user. The master user can IM to run commands.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ string masterName = String.Empty;
+ for (int ct = 0; ct < args.Length;ct++)
+ masterName = masterName + args[ct] + " ";
+ TestTool.Master = masterName.TrimEnd();
+
+ return "Master set to " + masterName;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/SitCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/SitCommand.cs
new file mode 100644
index 00000000..d700c9de
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/SitCommand.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class SitCommand: Command
+ {
+ public SitCommand()
+ {
+ Name = "sit";
+ Description = "Sit on closest touchable prim.";
+ }
+
+ public string Sit(LLUUID target)
+ {
+ AgentRequestSitPacket sitPacket = new AgentRequestSitPacket();
+
+ sitPacket.AgentData.AgentID = Client.Network.AgentID;
+ sitPacket.AgentData.SessionID = Client.Network.SessionID;
+
+ sitPacket.TargetObject.TargetID = target;
+ sitPacket.TargetObject.Offset = new LLVector3();
+
+ Client.Network.SendPacket(sitPacket);
+
+// SitTime = DateTime.Now;
+
+ return String.Empty;
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ PrimObject closest = null;
+ double closestDistance = Double.MaxValue;
+
+ lock (TestTool.Prims)
+ {
+ foreach (PrimObject p in TestTool.Prims.Values)
+ {
+ if ((p.Flags & ObjectFlags.Touch) > 0)
+ {
+ double distance = QuadranceBetween(Client.Self.Position, p.Position);
+ if (closest == null || distance < closestDistance)
+ {
+ closest = p;
+ closestDistance = distance;
+ }
+ }
+ }
+ }
+
+ if (closest != null)
+ {
+ Sit(closest.ID);
+ return TestTool.Prims.Count + " prims. Sat on " + closest.ID + ". Distance: " + closestDistance;
+ }
+
+ return String.Empty;
+ }
+
+ //string standUpCommand(string[] args, LLUUID fromAgentID)
+ //{
+ // client.Self.AutoPilotLocal(1, 1, 1);
+ // return "Stood up.";
+ //}
+
+ //string sitTimeCommand(string[] args, LLUUID fromAgentID)
+ //{
+ // return "Sitting Since: " + SitTime + " (" + (DateTime.Now - SitTime) + ")";
+ //}
+
+ public static double QuadranceBetween(LLVector3 a, LLVector3 b)
+ {
+ return
+ (
+ ((a.X - b.X) * (a.X - b.X))
+ + ((a.Y - b.Y) * (a.Y - b.Y))
+ + ((a.Z - b.Z) * (a.Z - b.Z))
+ );
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/TreeCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/TreeCommand.cs
new file mode 100644
index 00000000..9e00ca05
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/TreeCommand.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class TreeCommand: Command
+ {
+ public TreeCommand()
+ {
+ Name = "tree";
+ Description = "Rez a tree.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ if (args.Length == 1)
+ {
+ try
+ {
+ string treeName = args[0].Trim(new char[] { ' ' });
+ ObjectManager.Tree tree = (ObjectManager.Tree)Enum.Parse(typeof(ObjectManager.Tree), treeName);
+
+ LLVector3 treePosition = new LLVector3(Client.Self.Position.X, Client.Self.Position.Y,
+ Client.Self.Position.Z);
+ treePosition.Z += 3.0f;
+
+ Client.Objects.AddTree(Client.Network.CurrentSim, new LLVector3(0.5f, 0.5f, 0.5f),
+ LLQuaternion.Identity, treePosition, tree, TestTool.GroupID, false);
+
+ return "Attempted to rez a " + treeName + " tree";
+ }
+ catch (Exception)
+ {
+ return "Type !tree for usage";
+ }
+ }
+
+ string usage = "Usage: !tree [";
+ foreach (string value in Enum.GetNames(typeof(ObjectManager.Tree)))
+ {
+ usage += value + ",";
+ }
+ usage = usage.TrimEnd(new char[] { ',' });
+ usage += "]";
+ return usage;
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Commands/UptimeCommand.cs b/libsecondlife-cs/examples/TestTool/Commands/UptimeCommand.cs
new file mode 100644
index 00000000..4b8a1cc1
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Commands/UptimeCommand.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class UptimeCommand: Command
+ {
+ public DateTime Created = DateTime.Now;
+
+ public UptimeCommand()
+ {
+ Name = "uptime";
+ Description = "Shows the login time and length of time logged on.";
+ }
+
+ public override string Execute(string[] args, LLUUID fromAgentID)
+ {
+ return "Up Since: " + Created + " (" + (DateTime.Now - Created) + ")";
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Program.cs b/libsecondlife-cs/examples/TestTool/Program.cs
new file mode 100644
index 00000000..2da6f821
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace libsecondlife.TestTool
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ if (args.Length < 3)
+ {
+ Console.WriteLine("Usage: TestTool.exe firstname lastname password [Master Name]");
+ return;
+ }
+
+ string masterName = String.Empty;
+ for (int ct = 3; ct < args.Length;ct++)
+ masterName = masterName + args[ct] + " ";
+
+ TestTool testTool = new TestTool(args[0], args[1], args[2], masterName.TrimEnd());
+ testTool.Run();
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/Properties/AssemblyInfo.cs b/libsecondlife-cs/examples/TestTool/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..f5072f2d
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestTool")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TestTool")]
+[assembly: AssemblyCopyright("Copyright © 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0563f706-7fa9-42f6-bf23-c6acd1175964")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/libsecondlife-cs/examples/TestTool/TestTool.build b/libsecondlife-cs/examples/TestTool/TestTool.build
new file mode 100644
index 00000000..246b134e
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/TestTool.build
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libsecondlife-cs/examples/TestTool/TestTool.cs b/libsecondlife-cs/examples/TestTool/TestTool.cs
new file mode 100644
index 00000000..1a6cadcb
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/TestTool.cs
@@ -0,0 +1,222 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using libsecondlife;
+using libsecondlife.Packets;
+
+namespace libsecondlife.TestTool
+{
+ public class TestTool
+ {
+ public SecondLife Client;
+ public LLUUID GroupID;
+ public Dictionary GroupMembers;
+ public Dictionary Prims = new Dictionary();
+ public Dictionary Avatars = new Dictionary();
+ public Dictionary Commands = new Dictionary();
+ public bool Running = true;
+ public string Master;
+
+ LLQuaternion bodyRotation;
+ System.Timers.Timer updateTimer;
+
+ public TestTool(string first, string last, string password, string master)
+ {
+ Client = new SecondLife();
+
+ Master = master;
+
+ GroupID = LLUUID.Zero;
+ Client.Objects.RequestAllObjects = true;
+ bodyRotation = LLQuaternion.Identity;
+ updateTimer = new System.Timers.Timer(500);
+ updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed);
+
+ Client.Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler));
+
+ Client.Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim);
+ Client.Objects.OnPrimMoved += new ObjectManager.PrimMovedCallback(Objects_OnPrimMoved);
+ Client.Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(Objects_OnObjectKilled);
+ Client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar);
+ Client.Objects.OnAvatarMoved += new ObjectManager.AvatarMovedCallback(Objects_OnAvatarMoved);
+ Client.Self.OnInstantMessage += new InstantMessageCallback(Self_OnInstantMessage);
+
+ RegisterAllCommands(Assembly.GetExecutingAssembly());
+
+ if (Client.Network.Login(first, last, password, "TestTool", "contact@libsecondlife.org"))
+ {
+ updateTimer.Start();
+ }
+ }
+
+ public void RegisterAllCommands(Assembly assembly)
+ {
+ foreach (Type t in assembly.GetTypes())
+ {
+ if (t.IsSubclassOf(typeof(Command)))
+ {
+ Command command = (Command)t.GetConstructor(new Type[0]).Invoke(new object[0]);
+ RegisterCommand(command);
+ }
+ }
+ }
+
+ public void RegisterCommand(Command command)
+ {
+ command.TestTool = this;
+ Commands.Add(command.Name.ToLower(), command);
+ }
+
+ public void DoCommand(string cmd, LLUUID fromAgentID, LLUUID imSessionID)
+ {
+ string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' });
+ if (tokens.Length == 0)
+ return;
+
+ string response = "";
+ if (Commands.ContainsKey(tokens[0].ToLower()))
+ {
+ string[] args = new string[tokens.Length - 1];
+ Array.Copy(tokens, 1, args, 0, args.Length);
+ response = Commands[tokens[0].ToLower()].Execute(args, fromAgentID);
+ }
+ else
+ {
+ response = "Unknown command.";
+ }
+
+ if (response.Length > 0)
+ {
+ if (fromAgentID != null)
+ Client.Self.InstantMessage(fromAgentID, response, imSessionID);
+ Console.WriteLine(response);
+ }
+ }
+
+ public void Run()
+ {
+ Console.WriteLine("Type quit to exit. Type help for a command list.");
+
+ while (Running && Client.Network.Connected)
+ {
+ PrintPrompt();
+ string input = Console.ReadLine();
+ DoCommand(input, null, null);
+ }
+
+ if (Client.Network.Connected)
+ Client.Network.Logout();
+ }
+
+ public void PrintPrompt()
+ {
+ Console.Write(String.Format("{0} {1} - {2}> ", Client.Self.FirstName, Client.Self.LastName, Client.Network.CurrentSim.Region.Name));
+ }
+
+ void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ LLVector3 forward = new LLVector3(0, 0.9999f, 0);
+ LLVector3 left = new LLVector3(0.9999f, 0, 0);
+ LLVector3 up = new LLVector3(0, 0, 0.9999f);
+
+ Client.Self.UpdateCamera(0, Client.Self.Position, forward, left, up, bodyRotation,
+ LLQuaternion.Identity, 64, false);
+ }
+
+ void AgentDataUpdateHandler(Packet packet, Simulator sim)
+ {
+ AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet;
+ if (p.AgentData.AgentID == Client.Network.AgentID)
+ {
+ Console.WriteLine("Got my group ID, requesting group members...");
+ GroupID = p.AgentData.ActiveGroupID;
+
+ Client.Groups.BeginGetGroupMembers(GroupID, new GroupManager.GroupMembersCallback(OnGroupMembers));
+ }
+ }
+
+ void OnGroupMembers(Dictionary members)
+ {
+ Console.WriteLine("Got " + members.Count + " group members.");
+ GroupMembers = members;
+ PrintPrompt();
+ }
+
+ void Objects_OnObjectKilled(Simulator simulator, uint objectID)
+ {
+ lock (Prims)
+ {
+ if (Prims.ContainsKey(objectID))
+ Prims.Remove(objectID);
+ }
+
+ lock (Avatars)
+ {
+ if (Avatars.ContainsKey(objectID))
+ Avatars.Remove(objectID);
+ }
+ }
+
+ void Objects_OnPrimMoved(Simulator simulator, PrimUpdate prim, ulong regionHandle, ushort timeDilation)
+ {
+ lock (Prims)
+ {
+ if (Prims.ContainsKey(prim.LocalID))
+ {
+ Prims[prim.LocalID].Position = prim.Position;
+ Prims[prim.LocalID].Rotation = prim.Rotation;
+ }
+ }
+ }
+
+ void Objects_OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
+ {
+ lock (Prims)
+ {
+ Prims[prim.LocalID] = prim;
+ }
+ }
+
+ void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
+ {
+ lock (Avatars)
+ {
+ Avatars[avatar.LocalID] = avatar;
+ }
+ }
+
+ void Objects_OnAvatarMoved(Simulator simulator, AvatarUpdate avatar, ulong regionHandle, ushort timeDilation)
+ {
+ lock (Avatars)
+ {
+ if (Avatars.ContainsKey(avatar.LocalID))
+ {
+ Avatars[avatar.LocalID].Position = avatar.Position;
+ Avatars[avatar.LocalID].Rotation = avatar.Rotation;
+ }
+ }
+ }
+
+ void Self_OnInstantMessage(LLUUID fromAgentID, string fromAgentName, LLUUID toAgentID, uint parentEstateID, LLUUID regionID, LLVector3 position, byte dialog, bool groupIM, LLUUID imSessionID, DateTime timestamp, string message, byte offline, byte[] binaryBucket)
+ {
+ Console.WriteLine("" + fromAgentName + ": " + message + "\n");
+
+ if (GroupMembers != null && !GroupMembers.ContainsKey(fromAgentID) && fromAgentName.ToLower().TrimEnd() != Master.ToLower().TrimEnd())
+ {
+ //Not a member of my group, ignore the IM.
+ return;
+ }
+
+ if (dialog == 22)
+ {
+ Console.WriteLine("Accepting teleport lure.");
+ Client.Self.TeleportLureRespond(fromAgentID, true);
+
+ return;
+ }
+
+ DoCommand(message, fromAgentID, imSessionID);
+ }
+ }
+}
diff --git a/libsecondlife-cs/examples/TestTool/TestTool.csproj b/libsecondlife-cs/examples/TestTool/TestTool.csproj
new file mode 100644
index 00000000..8d27fdf8
--- /dev/null
+++ b/libsecondlife-cs/examples/TestTool/TestTool.csproj
@@ -0,0 +1,68 @@
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880}
+ Exe
+ Properties
+ libsecondlife.TestTool
+ TestBot
+
+
+ true
+ full
+ false
+ ..\..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ ..\..\bin\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}
+ libsecondlife
+
+
+
+
+
\ No newline at end of file
diff --git a/libsecondlife-cs/libsecondlife.sln b/libsecondlife-cs/libsecondlife.sln
index d515f169..bf261cda 100644
--- a/libsecondlife-cs/libsecondlife.sln
+++ b/libsecondlife-cs/libsecondlife.sln
@@ -50,6 +50,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatConsole", "..\SLProxy\C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BodyPartMorphGenerator", "examples\BodyPartMorphGenerator\BodyPartMorphGenerator.csproj", "{98C44481-3F15-4305-840D-037EA0D9C221}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTool", "examples\TestTool\TestTool.csproj", "{B87682F6-B2D7-4C4D-A529-400C24FD4880}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools and Examples", "Tools and Examples", "{F35EF72F-4302-4924-A162-10447B94F635}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -152,6 +156,10 @@ Global
{98C44481-3F15-4305-840D-037EA0D9C221}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98C44481-3F15-4305-840D-037EA0D9C221}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98C44481-3F15-4305-840D-037EA0D9C221}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -164,5 +172,19 @@ Global
{E464B963-46E3-4E1A-A36F-9C640C880E68} = {AE3B6C21-9B43-490E-ABCE-2018DC1AEA44}
{8598E42A-DCBC-4224-9503-5694F17B2F45} = {AE3B6C21-9B43-490E-ABCE-2018DC1AEA44}
{98C44481-3F15-4305-840D-037EA0D9C221} = {AE3B6C21-9B43-490E-ABCE-2018DC1AEA44}
+ {6222B134-AE5F-489A-8A77-423A721B7C62} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {4EF98AD4-B3B3-42B0-9273-13A614A823F7} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {D8ECCBE1-AC71-4054-AAA6-2D50E5629504} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {7AE16AC1-E64C-4FDC-9B85-4BB6145D511C} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {F460FAB3-0D12-4873-89EB-2696818764B8} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {B5AC6795-E426-4BC3-950F-D7B2970E2394} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {B87682F6-B2D7-4C4D-A529-400C24FD4880} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {E4115DC9-FC88-47D6-B3B6-2400AD19B80D} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {8855EB2F-BC4C-485A-A577-0989EB16BFDC} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {F6258A68-C624-46A0-BA73-B55D21BB0A3B} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {FC19D5F6-076E-4923-8456-9B0E00E22896} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {77E5330D-8A8C-41B4-A2D1-6F06FE45ED6D} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {623B86F7-7753-44B7-A8C8-CBC89FB8AF8E} = {F35EF72F-4302-4924-A162-10447B94F635}
+ {66FFD34E-652C-4EF5-81FE-06AD011169D2} = {F35EF72F-4302-4924-A162-10447B94F635}
EndGlobalSection
EndGlobal