169 lines
6.0 KiB
C#
169 lines
6.0 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Collections.Generic;
|
|
using libsecondlife;
|
|
using libsecondlife.Packets;
|
|
|
|
namespace FollowBot
|
|
{
|
|
class FollowBot
|
|
{
|
|
SecondLife client;
|
|
Dictionary<uint, Avatar> avatars;
|
|
static bool logout;
|
|
const float DISTANCE_BUFFER = 3.0f;
|
|
string followName;
|
|
int regionX;
|
|
int regionY;
|
|
|
|
static void Main(string[] args)
|
|
{
|
|
if (args.Length != 3)
|
|
{
|
|
Console.WriteLine("Usage: FollowBot <firstName> <lastName> <password>");
|
|
}
|
|
else
|
|
{
|
|
FollowBot bot = new FollowBot(args[0], args[1], args[2]);
|
|
}
|
|
}
|
|
|
|
public FollowBot(string firstName, string lastName, string password)
|
|
{
|
|
client = new SecondLife();
|
|
avatars = new Dictionary<uint, Avatar>();
|
|
client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(OnNewAvatarEvent);
|
|
client.Objects.OnAvatarMoved += new ObjectManager.AvatarMovedCallback(OnAvatarMovedEvent);
|
|
client.Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(OnObjectKilledEvent);
|
|
client.Network.Login(firstName, lastName, password, "FollowBot", "root66@gmail.com");
|
|
SendAgentUpdate(0);
|
|
while (!logout) ParseCommand(Console.ReadLine());
|
|
client.Network.Logout();
|
|
}
|
|
|
|
//EVENTS #####################################################
|
|
void OnNewAvatarEvent(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
|
|
{
|
|
lock (avatars)
|
|
{
|
|
avatars[avatar.LocalID] = avatar;
|
|
}
|
|
}
|
|
|
|
void OnAvatarMovedEvent(Simulator simulator, AvatarUpdate avatar, ulong regionHandle, ushort timeDilation)
|
|
{
|
|
Avatar test;
|
|
if (!avatars.TryGetValue(avatar.LocalID, out test)) return;
|
|
regionX = (int)(regionHandle >> 32);
|
|
regionY = (int)(regionHandle & 0xFFFFFFFF);
|
|
lock (avatars)
|
|
{
|
|
string name = avatars[avatar.LocalID].Name;
|
|
if (avatars[avatar.LocalID].Name == followName)
|
|
{
|
|
avatars[avatar.LocalID].Position = avatar.Position;
|
|
avatars[avatar.LocalID].Rotation = avatar.Rotation;
|
|
if (!Follow(name)) SendAgentUpdate(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnObjectKilledEvent(Simulator simulator, uint objectID)
|
|
{
|
|
lock (avatars)
|
|
{
|
|
if (avatars.ContainsKey(objectID)) avatars.Remove(objectID);
|
|
}
|
|
}
|
|
|
|
//FUNCTIONS ##########################################################
|
|
void ParseCommand(string message)
|
|
{
|
|
if (message.Length == 0) return;
|
|
char[] splitChar = { ' ' };
|
|
string[] msg = message.Split(splitChar);
|
|
string command = msg[0].ToLower();
|
|
string response = "";
|
|
|
|
//Store command arguments in "details" variable
|
|
string details = null;
|
|
for (int i = 1; i < msg.Length; i++)
|
|
{
|
|
details += msg[i];
|
|
if (i + 1 < msg.Length) details += " ";
|
|
}
|
|
|
|
switch (command)
|
|
{
|
|
case "follow":
|
|
{
|
|
followName = details;
|
|
SendAgentUpdate(0);
|
|
response = "Following " + details;
|
|
break;
|
|
}
|
|
case "quit":
|
|
{
|
|
logout = true;
|
|
response = "Logging out";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (response != "") Console.WriteLine("* " + response);
|
|
}
|
|
|
|
float vecDist(LLVector3 pointA, LLVector3 pointB)
|
|
{
|
|
float xd = pointB.X - pointA.X;
|
|
float yd = pointB.Y - pointA.Y;
|
|
float zd = pointB.Z - pointA.Z;
|
|
return (float)Math.Sqrt(xd * xd + yd * yd + zd * zd);
|
|
}
|
|
|
|
|
|
bool Follow(string name)
|
|
{
|
|
followName = name;
|
|
foreach (Avatar av in avatars.Values)
|
|
{
|
|
if (av.Name != name) continue;
|
|
else if (vecDist(av.Position, client.Self.Position) > DISTANCE_BUFFER)
|
|
{
|
|
//move toward target
|
|
ulong x = (ulong)(av.Position.X + regionX);
|
|
ulong y = (ulong)(av.Position.Y + regionY);
|
|
client.Self.AutoPilot(x, y, av.Position.Z);
|
|
}
|
|
else
|
|
{
|
|
//stop at current position
|
|
//LLVector3 myPos = client.Self.Position;
|
|
//client.Self.AutoPilot((ulong)myPos.X, (ulong)myPos.Y, myPos.Z);
|
|
}
|
|
Thread.Sleep(200); //Sleep 200ms between updates
|
|
SendAgentUpdate(0);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SendAgentUpdate(uint ControlID)
|
|
{
|
|
AgentUpdatePacket p = new AgentUpdatePacket();
|
|
p.AgentData.Far = 30.0f;
|
|
p.AgentData.CameraAtAxis = new LLVector3(0, 0, 0);
|
|
p.AgentData.CameraCenter = 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);
|
|
}
|
|
|
|
}
|
|
}
|