Files
libremetaverse/libsecondlife-cs/examples/TestClient/TestClient.cs
lonecoder c9054f3b70 Added full InstantMessageDialog enum info.
Added new InstantMessage override for sending dialog responses.
Added InventoryCommand to TestClient
Added response to InventoryOffer messages for TestClient, but it appears to be cosmetic and has nothing to do with the actual inventory transfer.

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@819 52acb1d6-8a22-11de-b505-999d5b087335
2007-01-09 04:56:12 +00:00

307 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;
using libsecondlife;
using libsecondlife.Packets;
using libsecondlife.AssetSystem;
namespace libsecondlife.TestClient
{
public class TestClient : SecondLife
{
public delegate void PrimCreatedCallback(Simulator simulator, PrimObject prim);
public event PrimCreatedCallback OnPrimCreated;
public Dictionary<Simulator, Dictionary<uint, PrimObject>> SimPrims;
public LLUUID GroupID = LLUUID.Zero;
public Dictionary<LLUUID, GroupMember> GroupMembers;
public Dictionary<uint, Avatar> AvatarList = new Dictionary<uint,Avatar>();
public Dictionary<LLUUID, AvatarAppearancePacket> Appearances = new Dictionary<LLUUID, AvatarAppearancePacket>();
public Dictionary<string, Command> Commands = new Dictionary<string,Command>();
public Dictionary<string, object> SharedValues = new Dictionary<string, object>();
public bool Running = true;
public string Master = String.Empty;
public ClientManager ClientManager;
private LLQuaternion bodyRotation = LLQuaternion.Identity;
private LLVector3 forward = new LLVector3(0, 0.9999f, 0);
private LLVector3 left = new LLVector3(0.9999f, 0, 0);
private LLVector3 up = new LLVector3(0, 0, 0.9999f);
private int DrawDistance = 64;
private System.Timers.Timer updateTimer;
public int regionX;
public int regionY;
/// <summary>
///
/// </summary>
public TestClient(ClientManager manager)
{
ClientManager = manager;
updateTimer = new System.Timers.Timer(1000);
updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed);
RegisterAllCommands(Assembly.GetExecutingAssembly());
Debug = false;
Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler));
Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim);
Objects.OnPrimMoved += new ObjectManager.PrimMovedCallback(Objects_OnPrimMoved);
Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(Objects_OnObjectKilled);
Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar);
Objects.OnAvatarMoved += new ObjectManager.AvatarMovedCallback(Objects_OnAvatarMoved);
Self.OnInstantMessage += new MainAvatar.InstantMessageCallback(Self_OnInstantMessage);
Network.RegisterCallback(PacketType.AvatarAppearance, new NetworkManager.PacketCallback(AvatarAppearanceHandler));
Objects.RequestAllObjects = true;
updateTimer.Start();
}
public void RegisterAllCommands(Assembly assembly)
{
foreach (Type t in assembly.GetTypes())
{
try
{
if (t.IsSubclassOf(typeof(Command)))
{
ConstructorInfo info = t.GetConstructor(new Type[] { typeof(TestClient) });
Command command = (Command)info.Invoke(new object[] { this });
RegisterCommand(command);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
private void RegisterCommand(Command command)
{
command.Client = this;
if (!Commands.ContainsKey(command.Name.ToLower()))
{
Commands.Add(command.Name.ToLower(), command);
}
}
//breaks up large responses to deal with the max IM size
private void SendResponseIM(SecondLife client, LLUUID fromAgentID, string data, LLUUID imSessionID)
{
for ( int i = 0 ; i < data.Length ; i += 1024 ) {
int y;
if ((i + 1023) > data.Length)
{
y = data.Length - i;
}
else
{
y = 1023;
}
string message = data.Substring(i, y);
client.Self.InstantMessage(fromAgentID, message, imSessionID);
}
}
public void DoCommand(string cmd, LLUUID fromAgentID, LLUUID imSessionID)
{
string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' });
string firstToken = tokens[0].ToLower();
if (tokens.Length == 0)
return;
// "all balance" will send the balance command to all currently logged in bots
if (firstToken == "all" && tokens.Length > 1)
{
cmd = "";
// Reserialize all of the arguments except for "all"
for (int i = 1; i < tokens.Length; i++)
{
cmd += tokens[i] + " ";
}
ClientManager.DoCommandAll(cmd, fromAgentID, imSessionID);
return;
}
if (Commands.ContainsKey(firstToken))
{
string[] args = new string[tokens.Length - 1];
Array.Copy(tokens, 1, args, 0, args.Length);
string response = response = Commands[firstToken].Execute(args, fromAgentID);
if (response.Length > 0)
{
if (fromAgentID != null && Network.Connected)
SendResponseIM(this, fromAgentID, response, imSessionID);
Console.WriteLine(response);
}
}
}
private void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Self.UpdateCamera(0, Self.Position, forward, left, up, bodyRotation,
LLQuaternion.Identity, DrawDistance, false);
foreach (Command c in Commands.Values)
if (c.Active)
c.Think();
}
private void AgentDataUpdateHandler(Packet packet, Simulator sim)
{
AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet;
if (p.AgentData.AgentID == sim.Client.Network.AgentID)
{
Console.WriteLine("Got the group ID for " + sim.Client.ToString() + ", requesting group members...");
GroupID = p.AgentData.ActiveGroupID;
sim.Client.Groups.BeginGetGroupMembers(GroupID, new GroupManager.GroupMembersCallback(OnGroupMembers));
}
}
private void OnGroupMembers(Dictionary<LLUUID, GroupMember> members)
{
Console.WriteLine("Got " + members.Count + " group members.");
GroupMembers = members;
}
private void Objects_OnObjectKilled(Simulator simulator, uint objectID)
{
lock (SimPrims)
{
if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(objectID))
SimPrims[simulator].Remove(objectID);
}
lock (AvatarList)
{
if (AvatarList.ContainsKey(objectID))
AvatarList.Remove(objectID);
}
}
private void Objects_OnPrimMoved(Simulator simulator, PrimUpdate prim, ulong regionHandle, ushort timeDilation)
{
lock (SimPrims)
{
if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(prim.LocalID))
{
SimPrims[simulator][prim.LocalID].Position = prim.Position;
SimPrims[simulator][prim.LocalID].Rotation = prim.Rotation;
}
}
}
private void Objects_OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
{
lock (SimPrims)
{
if (!SimPrims.ContainsKey(simulator))
{
SimPrims[simulator] = new Dictionary<uint, PrimObject>(10000);
}
SimPrims[simulator][prim.LocalID] = prim;
}
if ((prim.Flags & ObjectFlags.CreateSelected) != 0 && OnPrimCreated != null)
{
OnPrimCreated(simulator, prim);
}
}
private void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
{
lock (AvatarList)
{
AvatarList[avatar.LocalID] = avatar;
}
}
private void Objects_OnAvatarMoved(Simulator simulator, AvatarUpdate avatar, ulong regionHandle, ushort timeDilation)
{
regionX = (int)(regionHandle >> 32);
regionY = (int)(regionHandle & 0xFFFFFFFF);
lock (AvatarList)
{
if (AvatarList.ContainsKey(avatar.LocalID))
{
AvatarList[avatar.LocalID].Position = avatar.Position;
AvatarList[avatar.LocalID].Rotation = avatar.Rotation;
}
}
}
private void AvatarAppearanceHandler(Packet packet, Simulator simulator)
{
AvatarAppearancePacket appearance = (AvatarAppearancePacket)packet;
lock (Appearances) Appearances[appearance.Sender.ID] = appearance;
}
private 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)
{
if (Master != null && Master.Length > 0)
{
if (fromAgentName.ToLower().Trim() != Master.ToLower().Trim())
{
// Received an IM from someone that is not the bot's master, ignore
Console.WriteLine("<IM>" + fromAgentName + " (not master): " + message + "@" + regionID.ToString() + ":" + position.ToString() );
return;
}
}
else
{
if (GroupMembers != null && !GroupMembers.ContainsKey(fromAgentID))
{
// Received an IM from someone outside the bot's group, ignore
Console.WriteLine("<IM>" + fromAgentName + " (not in group): " + message + "@" + regionID.ToString() + ":" + position.ToString());
return;
}
}
Console.WriteLine("<IM>" + fromAgentName + ": " + message);
if (Self.ID == toAgentID)
{
if (dialog == (byte)MainAvatar.InstantMessageDialog.LureUser)
{
Console.WriteLine("Accepting teleport lure.");
Self.TeleportLureRespond(fromAgentID, true);
}
else
{
if (dialog == (byte)MainAvatar.InstantMessageDialog.InventoryOffered)
{
Console.WriteLine("Accepting inventory offer.");
Self.InstantMessage(fromAgentID, MainAvatar.InstantMessageDialog.InventoryAccepted);
}
DoCommand(message, fromAgentID, imSessionID);
}
}
else
{
// This shouldn't happen
Console.WriteLine("A bot that we aren't tracking received an IM?");
}
}
}
}