//
// Radegast Metaverse Client
-// Copyright (c) 2009-2012, Radegast Development Team
+// Copyright (c) 2009-2014, Radegast Development Team
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
using OpenMetaverse;
-using Radegast.Bot;
+using Radegast.Automation;
using Radegast.Netcom;
namespace Radegast
public string ID { get; set; }
public string Name { get; set; }
public Quaternion Heading { get; set; }
+
public KnownHeading(string id, string name, Quaternion heading)
{
this.ID = id;
internal static Random rnd = new Random();
private System.Threading.Timer lookAtTimer;
+ public float FOVVerticalAngle = Utils.TWO_PI - 0.05f;
+
/// <summary>
/// Passes walk state
/// </summary>
}
public Dictionary<UUID, string> KnownAnimations;
+ public bool CameraTracksOwnAvatar = true;
+ public Vector3 DefaultCameraOffset = new Vector3(-5, 0, 0);
public StateManager(RadegastInstance instance)
{
this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
KnownAnimations = Animations.ToDictionary();
autosit = new AutoSit(this.instance);
+ pseudohome = new PseudoHome(this.instance);
+ lslHelper = new LSLHelper(this.instance);
beamTimer = new System.Timers.Timer();
beamTimer.Enabled = false;
private void RegisterClientEvents(GridClient client)
{
+ client.Objects.AvatarUpdate += new EventHandler<AvatarUpdateEventArgs>(Objects_AvatarUpdate);
client.Objects.TerseObjectUpdate += new EventHandler<TerseObjectUpdateEventArgs>(Objects_TerseObjectUpdate);
client.Objects.AvatarSitChanged += new EventHandler<AvatarSitChangedEventArgs>(Objects_AvatarSitChanged);
client.Self.AlertMessage += new EventHandler<AlertMessageEventArgs>(Self_AlertMessage);
private void UnregisterClientEvents(GridClient client)
{
+ client.Objects.AvatarUpdate -= new EventHandler<AvatarUpdateEventArgs>(Objects_AvatarUpdate);
client.Objects.TerseObjectUpdate -= new EventHandler<TerseObjectUpdateEventArgs>(Objects_TerseObjectUpdate);
client.Objects.AvatarSitChanged -= new EventHandler<AvatarSitChangedEventArgs>(Objects_AvatarSitChanged);
client.Self.AlertMessage -= new EventHandler<AlertMessageEventArgs>(Self_AlertMessage);
walkTimer.Dispose();
walkTimer = null;
}
+
+ if (autosit != null)
+ {
+ autosit.Dispose();
+ autosit = null;
+ }
+
+ if (lslHelper == null)
+ {
+ lslHelper.Dispose();
+ lslHelper = null;
+ }
}
void instance_ClientChanged(object sender, ClientChangedEventArgs e)
{
if (e.Avatar.LocalID != client.Self.LocalID) return;
- this.sitting = e.SittingOn != 0;
+ sitting = e.SittingOn != 0;
+
+ if (client.Self.SittingOn != 0 && !client.Network.CurrentSim.ObjectsPrimitives.ContainsKey(client.Self.SittingOn))
+ {
+ client.Objects.RequestObject(client.Network.CurrentSim, client.Self.SittingOn);
+ }
+
if (SitStateChanged != null)
{
SitStateChanged(this, new SitEventArgs(this.sitting));
public bool TryFindAvatar(UUID person, out Vector3 position)
{
Simulator sim;
- return TryFindAvatar(person, out sim, out position);
+ if (!TryFindAvatar(person, out sim, out position)) return false;
+ // same sim?
+ if (sim == client.Network.CurrentSim) return true;
+ position = ToLocalPosition(sim.Handle, position);
+ return true;
+ }
+
+ public Vector3 ToLocalPosition(ulong handle, Vector3 position)
+ {
+ Vector3d diff = ToVector3D(handle, position) - client.Self.GlobalPosition;
+ position = new Vector3((float) diff.X, (float) diff.Y, (float) diff.Z) - position;
+ return position;
+ }
+
+ public static Vector3d ToVector3D(ulong handle, Vector3 pos)
+ {
+ uint globalX, globalY;
+ Utils.LongToUInts(handle, out globalX, out globalY);
+
+ return new Vector3d(
+ (double)globalX + (double)pos.X,
+ (double)globalY + (double)pos.Y,
+ (double)pos.Z);
}
/// <summary>
if (s.AvatarPositions.ContainsKey(person))
{
position = s.AvatarPositions[person];
+ sim = s;
break;
}
}
return false;
}
+ public bool TryLocatePrim(Primitive avi, out Simulator sim, out Vector3 position)
+ {
+ Simulator[] Simulators = null;
+ lock (client.Network.Simulators)
+ {
+ Simulators = client.Network.Simulators.ToArray();
+ }
+
+ sim = client.Network.CurrentSim;
+ position = Vector3.Zero;
+ {
+ foreach (var s in Simulators)
+ {
+ if (s.Handle == avi.RegionHandle)
+ {
+ sim = s;
+ break;
+ }
+ }
+ }
+ if (avi != null)
+ {
+ if (avi.ParentID == 0)
+ {
+ position = avi.Position;
+ }
+ else
+ {
+ Primitive seat;
+ if (sim.ObjectsPrimitives.TryGetValue(avi.ParentID, out seat))
+ {
+ position = seat.Position + avi.Position*seat.Rotation;
+ }
+ }
+ }
+ if (position.Z > 0.1f)
+ return true;
+ else
+ return false;
+ }
+
/// <summary>
/// Move to target position either by walking or by teleporting
/// </summary>
void Network_SimChanged(object sender, SimChangedEventArgs e)
{
- autosit.TrySit();
+ WorkPool.QueueUserWorkItem(sync =>
+ {
+ Thread.Sleep(15 * 1000);
+ autosit.TrySit();
+ pseudohome.ETGoHome();
+ });
+ client.Self.Movement.SetFOVVerticalAngle(FOVVerticalAngle);
}
private UUID teleportEffect = UUID.Random();
}
}
+ void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e)
+ {
+ if (e.Avatar.LocalID == client.Self.LocalID)
+ {
+ SetDefaultCamera();
+ }
+ }
+
void Objects_TerseObjectUpdate(object sender, TerseObjectUpdateEventArgs e)
{
if (!e.Update.Avatar) return;
+
+ if (e.Prim.LocalID == client.Self.LocalID)
+ {
+ SetDefaultCamera();
+ }
+
if (!following) return;
Avatar av;
}
}
+ public void SetDefaultCamera()
+ {
+ if (CameraTracksOwnAvatar)
+ {
+ if (client.Self.SittingOn != 0 && !client.Network.CurrentSim.ObjectsPrimitives.ContainsKey(client.Self.SittingOn))
+ {
+ // We are sitting but don't have the information about the object we are sitting on
+ // Sim seems to ignore RequestMutlipleObjects message
+ // client.Objects.RequestObject(client.Network.CurrentSim, client.Self.SittingOn);
+ }
+ else
+ {
+ Vector3 pos = client.Self.SimPosition + DefaultCameraOffset * client.Self.Movement.BodyRotation;
+ //Logger.Log("Setting camera position to " + pos.ToString(), Helpers.LogLevel.Debug);
+ client.Self.Movement.Camera.LookAt(
+ pos,
+ client.Self.SimPosition
+ );
+ }
+ }
+ }
+
public Quaternion AvatarRotation(Simulator sim, UUID avID)
{
Quaternion rot = Quaternion.Identity;
void netcom_ChatReceived(object sender, ChatEventArgs e)
{
+ //somehow it can be too early (when Radegast is loaded from running bot)
+ if (instance.GlobalSettings==null) return;
if (!instance.GlobalSettings["disable_look_at"]
&& e.SourceID != client.Self.AgentID
&& (e.SourceType == ChatSourceType.Agent || e.Type == ChatType.StartTyping))
{
WalkTo(GlobalPosition(prim));
}
+ public double WaitUntilPosition(Vector3d pos, TimeSpan maxWait, double howClose)
+ {
+
+ DateTime until = DateTime.Now + maxWait;
+ while (until > DateTime.Now)
+ {
+ double dist = Vector3d.Distance(client.Self.GlobalPosition, pos);
+ if (howClose >= dist) return dist;
+ Thread.Sleep(250);
+ }
+ return Vector3d.Distance(client.Self.GlobalPosition, pos);
+
+ }
public void WalkTo(Vector3d globalPos)
{
EndWalking();
return;
}
- walkTimer.Change(walkChekInterval, Timeout.Infinite);
+ if (walkTimer != null) walkTimer.Change(walkChekInterval, Timeout.Infinite);
}
}
awayAnim.Add(awayAnimationID, away);
client.Self.Animate(awayAnim, true);
+ if (UseMoveControl) client.Self.Movement.Away = away;
this.away = away;
}
}
}
- public Vector3d GlobalPosition(Simulator sim, Vector3 pos)
+ static public Vector3d GlobalPosition(Simulator sim, Vector3 pos)
{
uint globalX, globalY;
Utils.LongToUInts(sim.Handle, out globalX, out globalY);
public bool IsAway
{
- get { return away; }
+ get
+ {
+ if (UseMoveControl) return client.Self.Movement.Away;
+ return away;
+ }
}
public bool IsBusy
public bool IsFlying
{
- get { return flying; }
+ get { return client.Self.Movement.Fly; }
}
public bool IsSitting
{
- get { return sitting; }
+ get
+ {
+ if (client.Self.Movement.SitOnGround || client.Self.SittingOn != 0) return true;
+ if (sitting) {
+ Logger.Log("out of sync sitting", Helpers.LogLevel.Debug);
+ sitting = false;
+ }
+ return false;
+ }
}
public bool IsPointing
{
get { return autosit; }
}
+
+ private LSLHelper lslHelper;
+ public LSLHelper LSLHelper
+ {
+ get { return lslHelper; }
+ }
+
+ private PseudoHome pseudohome;
+
+ /// <summary>
+ /// Experimental Option that sometimes the Client has more authority than state mananger
+ /// </summary>
+ public static bool UseMoveControl;
+
+ public PseudoHome PseudoHome
+ {
+ get { return pseudohome; }
+ }
}
public class SitEventArgs : EventArgs
this.Sitting = sitting;
}
}
-}
\ No newline at end of file
+}